org-babel-comint-with-output: Fix for edge case of `comint-prompt-regexp'

* lisp/ob-comint.el (org-babel-comint-with-output): Implement more
universal algorithm catching agglomerated prompts.  The new approach
works for regexps that match ^, but not as the first char in the
regexp string.
* testing/lisp/test-ob-octave.el (ob-octave/session-multiline): Add
new test.

Reported-by: Paul Stansell <paulstansell@gmail.com>
Link: https://orgmode.org/list/CAMJKaZwuTV-06pPz5nv87CNcoVcqCwFjEodubXTzXs15Q=OFug@mail.gmail.com
This commit is contained in:
Ihor Radchenko 2023-09-06 12:19:14 +03:00
parent f6fc385ed0
commit 13e4ee7371
No known key found for this signature in database
GPG Key ID: 6470762A7DA11D8B
2 changed files with 28 additions and 16 deletions

View File

@ -76,7 +76,10 @@ or user `keyboard-quit' during execution of body."
(remove-echo (nth 2 meta))
(full-body (nth 3 meta))
(org-babel-comint-prompt-separator
"org-babel-comint-prompt-separator"))
;; We need newline in case if we do progressive replacement
;; of agglomerated comint prompts with `comint-prompt-regexp'
;; containing ^.
"org-babel-comint-prompt-separator\n"))
`(org-babel-comint-in-buffer ,buffer
(let* ((string-buffer "")
(comint-output-filter-functions
@ -106,21 +109,20 @@ or user `keyboard-quit' during execution of body."
(insert dangling-text)
;; 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"
;; Or even "<whitespace>prompt<whitespace>prompt ...>.
;; 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 "^\\([ \t]*%s\\)+" (substring comint-prompt-regexp 1))
comint-prompt-regexp)
,org-babel-comint-prompt-separator
string-buffer))
(while (string-match-p comint-prompt-regexp string-buffer)
(setq string-buffer
(replace-regexp-in-string
;; Sometimes, we get multiple agglomerated
;; prompts together in a single output:
;; "prompt prompt prompt output"
;; Or even "<whitespace>prompt<whitespace>prompt ...>.
;; Remove them progressively, so that
;; possible "^" in the prompt regexp gets to
;; work as we remove the heading prompt
;; instance.
(format "\\(?:%s\\)?\\(?:%s\\)[ \t]*" ,org-babel-comint-prompt-separator 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

View File

@ -122,5 +122,15 @@ sombrero;
(when (get-buffer "*Org-Babel Error Output*")
(kill-buffer "*Org-Babel Error Output*")))))
(ert-deftest ob-octave/session-multiline ()
"Test multiline session input."
(dotimes (_ 3)
(org-test-with-temp-text
"#+begin_src octave :session oct2 :results output
x = 1;
x = 1;
x = 1
#+end_src"
(should (equal "x = 1" (org-babel-execute-src-block))))))
(provide 'test-ob-octave)