From 866ed1a3c5c37cad243085f9a8fa904970e4d614 Mon Sep 17 00:00:00 2001 From: Ihor Radchenko Date: Fri, 24 Mar 2023 11:15:58 +0100 Subject: [PATCH] org-babel-comint-with-output: Fix edge case for partial prompts * lisp/ob-comint.el (org-babel-comint-with-output): Do not try to filter out prompts in `comint-output-filter-functions'. The prompts may arrive there arbitrarily - multiple prompts together, partial prompts, full prompts, etc. For example "ghci> " prompt may arrive as "gh" + "ci> " with second part still matching `comint-prompt-regexp'. As a result, if we keep using `comint-output-filter-functions', the split prompts may sometimes retain their initial part, littering the results. Now, we postpone filtering to after receiving the output, still making sure that agglomerated prompts gets filtered using a custom regexp derived from `comint-prompt-regexp'. --- lisp/ob-comint.el | 46 ++++++++++++++++------------------------------ 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/lisp/ob-comint.el b/lisp/ob-comint.el index 7b5171642..35d1356a6 100644 --- a/lisp/ob-comint.el +++ b/lisp/ob-comint.el @@ -81,28 +81,7 @@ or user `keyboard-quit' during execution of body." (let* ((string-buffer "") (comint-output-filter-functions (cons (lambda (text) - (setq string-buffer - (concat - string-buffer - ;; Upon concatenation, the prompt may no - ;; longer match `comint-prompt-regexp'. - ;; In particular, when the regexp has ^ - ;; and the output does not contain - ;; trailing newline. Use more reliable - ;; match to split the output later. - (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 - text)))) + (setq string-buffer (concat string-buffer text))) comint-output-filter-functions)) dangling-text) ;; got located, and save dangling text @@ -117,21 +96,28 @@ or user `keyboard-quit' during execution of body." (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))))) + (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)))) ;; replace cut dangling text (goto-char (process-mark (get-buffer-process (current-buffer)))) (insert dangling-text) - ;; Replace partially supplied input lines. - ;; This is needed when output filter spits partial lines that - ;; do not include a full prompt at a time. + ;; Filter out prompts. (setq string-buffer (replace-regexp-in-string - comint-prompt-regexp + ;; 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