update packages
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
;;; ob-comint.el --- Babel Functions for Interaction with Comint Buffers -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2009-2025 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Eric Schulte
|
||||
;; Keywords: literate programming, reproducible research, comint
|
||||
@@ -58,6 +58,48 @@ executed inside the protection of `save-excursion' and
|
||||
(let ((comint-input-filter (lambda (_input) nil)))
|
||||
,@body))))))
|
||||
|
||||
(defvar-local org-babel-comint-prompt-regexp-old nil
|
||||
"Fallback regexp used to detect prompt.")
|
||||
|
||||
(defcustom org-babel-comint-fallback-regexp-threshold 5.0
|
||||
"Waiting time until trying to use fallback regexp to detect prompt.
|
||||
This is useful when prompt unexpectedly changes."
|
||||
:type 'float
|
||||
:group 'org-babel
|
||||
:package-version '(Org . "9.7"))
|
||||
|
||||
(defun org-babel-comint--set-fallback-prompt ()
|
||||
"Swap `comint-prompt-regexp' and `org-babel-comint-prompt-regexp-old'."
|
||||
(when org-babel-comint-prompt-regexp-old
|
||||
(let ((tmp comint-prompt-regexp))
|
||||
(setq comint-prompt-regexp org-babel-comint-prompt-regexp-old
|
||||
org-babel-comint-prompt-regexp-old tmp))))
|
||||
|
||||
(defun org-babel-comint--prompt-filter (string &optional prompt-regexp)
|
||||
"Remove PROMPT-REGEXP from STRING.
|
||||
|
||||
PROMPT-REGEXP defaults to `comint-prompt-regexp'."
|
||||
(let* ((prompt-regexp (or prompt-regexp comint-prompt-regexp))
|
||||
;; We need newline in case if we do progressive replacement
|
||||
;; of agglomerated comint prompts with `comint-prompt-regexp'
|
||||
;; containing ^.
|
||||
(separator "org-babel-comint--prompt-filter-separator\n"))
|
||||
(while (string-match-p prompt-regexp string)
|
||||
(setq string
|
||||
(replace-regexp-in-string
|
||||
(format "\\(?:%s\\)?\\(?:%s\\)[ \t]*" separator prompt-regexp)
|
||||
separator string)))
|
||||
(delete "" (split-string string separator))))
|
||||
|
||||
(defun org-babel-comint--echo-filter (string &optional echo)
|
||||
"Remove ECHO from STRING."
|
||||
(and echo string
|
||||
(string-match
|
||||
(replace-regexp-in-string "\n" "[\r\n]+" (regexp-quote echo))
|
||||
string)
|
||||
(setq string (substring string (match-end 0))))
|
||||
string)
|
||||
|
||||
(defmacro org-babel-comint-with-output (meta &rest body)
|
||||
"Evaluate BODY in BUFFER and return process output.
|
||||
Will wait until EOE-INDICATOR appears in the output, then return
|
||||
@@ -74,9 +116,7 @@ or user `keyboard-quit' during execution of body."
|
||||
(let ((buffer (nth 0 meta))
|
||||
(eoe-indicator (nth 1 meta))
|
||||
(remove-echo (nth 2 meta))
|
||||
(full-body (nth 3 meta))
|
||||
(org-babel-comint-prompt-separator
|
||||
"org-babel-comint-prompt-separator"))
|
||||
(full-body (nth 3 meta)))
|
||||
`(org-babel-comint-in-buffer ,buffer
|
||||
(let* ((string-buffer "")
|
||||
(comint-output-filter-functions
|
||||
@@ -93,43 +133,39 @@ or user `keyboard-quit' during execution of body."
|
||||
;; pass FULL-BODY to process
|
||||
,@body
|
||||
;; wait for end-of-evaluation indicator
|
||||
(while (progn
|
||||
(goto-char comint-last-input-end)
|
||||
(not (save-excursion
|
||||
(and (re-search-forward
|
||||
(regexp-quote ,eoe-indicator) nil t)
|
||||
(re-search-forward
|
||||
comint-prompt-regexp nil t)))))
|
||||
(accept-process-output (get-buffer-process (current-buffer))))
|
||||
(let ((start-time (current-time)))
|
||||
(while (progn
|
||||
(goto-char comint-last-input-end)
|
||||
(not (save-excursion
|
||||
(and (re-search-forward
|
||||
(regexp-quote ,eoe-indicator) nil t)
|
||||
(re-search-forward
|
||||
comint-prompt-regexp nil t)))))
|
||||
(accept-process-output
|
||||
(get-buffer-process (current-buffer))
|
||||
org-babel-comint-fallback-regexp-threshold)
|
||||
(when (and org-babel-comint-prompt-regexp-old
|
||||
(> (float-time (time-since start-time))
|
||||
org-babel-comint-fallback-regexp-threshold)
|
||||
(progn
|
||||
(goto-char comint-last-input-end)
|
||||
(save-excursion
|
||||
(and
|
||||
(re-search-forward
|
||||
(regexp-quote ,eoe-indicator) nil t)
|
||||
(re-search-forward
|
||||
org-babel-comint-prompt-regexp-old nil t)))))
|
||||
(org-babel-comint--set-fallback-prompt))))
|
||||
;; replace cut dangling text
|
||||
(goto-char (process-mark (get-buffer-process (current-buffer))))
|
||||
(insert dangling-text)
|
||||
|
||||
;; remove echo'd FULL-BODY from input
|
||||
(and ,remove-echo ,full-body
|
||||
(setq string-buffer (org-babel-comint--echo-filter string-buffer ,full-body)))
|
||||
|
||||
;; Filter out prompts.
|
||||
(setq string-buffer
|
||||
(replace-regexp-in-string
|
||||
;; Sometimes, we get multiple agglomerated
|
||||
;; prompts together in a single output:
|
||||
;; "prompt prompt prompt output"
|
||||
;; Remove them progressively, so that
|
||||
;; possible "^" in the prompt regexp gets to
|
||||
;; work as we remove the heading prompt
|
||||
;; instance.
|
||||
(if (string-prefix-p "^" comint-prompt-regexp)
|
||||
(format "^\\(%s\\)+" (substring comint-prompt-regexp 1))
|
||||
comint-prompt-regexp)
|
||||
,org-babel-comint-prompt-separator
|
||||
string-buffer))
|
||||
;; remove echo'd FULL-BODY from input
|
||||
(when (and ,remove-echo ,full-body
|
||||
(string-match
|
||||
(replace-regexp-in-string
|
||||
"\n" "[\r\n]+" (regexp-quote (or ,full-body "")))
|
||||
string-buffer))
|
||||
(setq string-buffer (substring string-buffer (match-end 0))))
|
||||
(delete "" (split-string
|
||||
string-buffer
|
||||
,org-babel-comint-prompt-separator))))))
|
||||
(org-babel-comint--prompt-filter string-buffer)))))
|
||||
|
||||
(defun org-babel-comint-input-command (buffer cmd)
|
||||
"Pass CMD to BUFFER.
|
||||
@@ -145,11 +181,23 @@ The input will not be echoed."
|
||||
Note: this is only safe when waiting for the result of a single
|
||||
statement (not large blocks of code)."
|
||||
(org-babel-comint-in-buffer buffer
|
||||
(while (progn
|
||||
(goto-char comint-last-input-end)
|
||||
(not (and (re-search-forward comint-prompt-regexp nil t)
|
||||
(goto-char (match-beginning 0)))))
|
||||
(accept-process-output (get-buffer-process buffer)))))
|
||||
(let ((start-time (current-time)))
|
||||
(while (progn
|
||||
(goto-char comint-last-input-end)
|
||||
(not (and (re-search-forward comint-prompt-regexp nil t)
|
||||
(goto-char (match-beginning 0)))))
|
||||
(accept-process-output
|
||||
(get-buffer-process buffer)
|
||||
org-babel-comint-fallback-regexp-threshold)
|
||||
(when (and org-babel-comint-prompt-regexp-old
|
||||
(> (float-time (time-since start-time))
|
||||
org-babel-comint-fallback-regexp-threshold)
|
||||
(progn
|
||||
(goto-char comint-last-input-end)
|
||||
(save-excursion
|
||||
(re-search-forward
|
||||
org-babel-comint-prompt-regexp-old nil t))))
|
||||
(org-babel-comint--set-fallback-prompt))))))
|
||||
|
||||
(defun org-babel-comint-eval-invisibly-and-wait-for-file
|
||||
(buffer file string &optional period)
|
||||
@@ -191,9 +239,12 @@ Its single argument is a string consisting of output from the
|
||||
comint process. It should return a string that will be passed
|
||||
to `org-babel-insert-result'.")
|
||||
|
||||
(defvar-local org-babel-comint-async-remove-prompts-p t
|
||||
"Whether prompts should be detected and removed from async output.")
|
||||
|
||||
(defvar-local org-babel-comint-async-dangling nil
|
||||
"Dangling piece of the last process output, in case
|
||||
`org-babel-comint-async-indicator' is spread across multiple
|
||||
"Dangling piece of the last process output, as a string.
|
||||
Used when `org-babel-comint-async-indicator' is spread across multiple
|
||||
comint outputs due to buffering.")
|
||||
|
||||
(defun org-babel-comint-use-async (params)
|
||||
@@ -221,6 +272,8 @@ STRING contains the output originally inserted into the comint buffer."
|
||||
(file-callback org-babel-comint-async-file-callback)
|
||||
(combined-string (concat org-babel-comint-async-dangling string))
|
||||
(new-dangling combined-string)
|
||||
;; Assumes comint filter called with session buffer current
|
||||
(session-dir default-directory)
|
||||
;; list of UUID's matched by `org-babel-comint-async-indicator'
|
||||
uuid-list)
|
||||
(with-temp-buffer
|
||||
@@ -245,7 +298,8 @@ STRING contains the output originally inserted into the comint buffer."
|
||||
(let* ((info (org-babel-get-src-block-info))
|
||||
(params (nth 2 info))
|
||||
(result-params
|
||||
(cdr (assq :result-params params))))
|
||||
(cdr (assq :result-params params)))
|
||||
(default-directory session-dir))
|
||||
(org-babel-insert-result
|
||||
(funcall file-callback
|
||||
(nth
|
||||
@@ -268,16 +322,23 @@ STRING contains the output originally inserted into the comint buffer."
|
||||
(res-str-raw
|
||||
(buffer-substring
|
||||
;; move point to beginning of indicator
|
||||
(- (match-beginning 0) 1)
|
||||
(match-beginning 0)
|
||||
;; find the matching start indicator
|
||||
(cl-loop
|
||||
do (re-search-backward indicator)
|
||||
until (and (equal (match-string 1) "start")
|
||||
(equal (match-string 2) uuid))
|
||||
finally return (+ 1 (match-end 0)))))
|
||||
;; Apply callback to clean up the result
|
||||
;; Apply user callback
|
||||
(res-str (funcall org-babel-comint-async-chunk-callback
|
||||
res-str-raw)))
|
||||
(if org-babel-comint-async-remove-prompts-p
|
||||
(org-trim (string-join
|
||||
(mapcar #'org-trim
|
||||
(org-babel-comint--prompt-filter
|
||||
res-str-raw))
|
||||
"\n")
|
||||
t)
|
||||
res-str-raw))))
|
||||
;; Search for uuid in associated org-buffers to insert results
|
||||
(cl-loop for buf in org-buffers
|
||||
until (with-current-buffer buf
|
||||
@@ -288,7 +349,8 @@ STRING contains the output originally inserted into the comint buffer."
|
||||
(let* ((info (org-babel-get-src-block-info))
|
||||
(params (nth 2 info))
|
||||
(result-params
|
||||
(cdr (assq :result-params params))))
|
||||
(cdr (assq :result-params params)))
|
||||
(default-directory session-dir))
|
||||
(org-babel-insert-result
|
||||
res-str result-params info))
|
||||
t))))
|
||||
@@ -297,18 +359,31 @@ STRING contains the output originally inserted into the comint buffer."
|
||||
|
||||
(defun org-babel-comint-async-register
|
||||
(session-buffer org-buffer indicator-regexp
|
||||
chunk-callback file-callback)
|
||||
chunk-callback file-callback
|
||||
&optional prompt-handling)
|
||||
"Set local org-babel-comint-async variables in SESSION-BUFFER.
|
||||
ORG-BUFFER is added to `org-babel-comint-async-buffers' if not
|
||||
present. `org-babel-comint-async-indicator',
|
||||
`org-babel-comint-async-chunk-callback', and
|
||||
`org-babel-comint-async-file-callback' are set to
|
||||
INDICATOR-REGEXP, CHUNK-CALLBACK, and FILE-CALLBACK
|
||||
respectively."
|
||||
INDICATOR-REGEXP, CHUNK-CALLBACK, and FILE-CALLBACK respectively.
|
||||
PROMPT-HANDLING may be either of the symbols `filter-prompts', in
|
||||
which case prompts matching `comint-prompt-regexp' are filtered
|
||||
from output before it is passed to CHUNK-CALLBACK, or
|
||||
`disable-prompt-filtering', in which case this behavior is
|
||||
disabled. For backward-compatibility, the default value of `nil'
|
||||
is equivalent to `filter-prompts'."
|
||||
(org-babel-comint-in-buffer session-buffer
|
||||
(setq org-babel-comint-async-indicator indicator-regexp
|
||||
org-babel-comint-async-chunk-callback chunk-callback
|
||||
org-babel-comint-async-file-callback file-callback)
|
||||
(setq org-babel-comint-async-remove-prompts-p
|
||||
(cond
|
||||
((eq prompt-handling 'disable-prompt-filtering) nil)
|
||||
((eq prompt-handling 'filter-prompts) t)
|
||||
((eq prompt-handling nil) t)
|
||||
(t (error (format "Unrecognized prompt handling behavior %s"
|
||||
prompt-handling)))))
|
||||
(unless (memq org-buffer org-babel-comint-async-buffers)
|
||||
(setq org-babel-comint-async-buffers
|
||||
(cons org-buffer org-babel-comint-async-buffers)))
|
||||
|
||||
Reference in New Issue
Block a user