From 13e4ee73716a8c918df23c8af05a496b33f41414 Mon Sep 17 00:00:00 2001 From: Ihor Radchenko Date: Wed, 6 Sep 2023 12:19:14 +0300 Subject: [PATCH] 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 Link: https://orgmode.org/list/CAMJKaZwuTV-06pPz5nv87CNcoVcqCwFjEodubXTzXs15Q=OFug@mail.gmail.com --- lisp/ob-comint.el | 34 ++++++++++++++++++---------------- testing/lisp/test-ob-octave.el | 10 ++++++++++ 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/lisp/ob-comint.el b/lisp/ob-comint.el index d6c048c58..407e9d239 100644 --- a/lisp/ob-comint.el +++ b/lisp/ob-comint.el @@ -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 "promptprompt ...>. - ;; 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 "promptprompt ...>. + ;; 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 diff --git a/testing/lisp/test-ob-octave.el b/testing/lisp/test-ob-octave.el index bbe9676de..dfcfc0190 100644 --- a/testing/lisp/test-ob-octave.el +++ b/testing/lisp/test-ob-octave.el @@ -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)