From 4f7a1369e72b22836cb74931c7c86e845155a729 Mon Sep 17 00:00:00 2001 Message-Id: <4f7a1369e72b22836cb74931c7c86e845155a729.1655522152.git.yantar92@gmail.com> In-Reply-To: <141f810a658d652e1cb3a147c5f71659f62df86f.1655522152.git.yantar92@gmail.com> References: <141f810a658d652e1cb3a147c5f71659f62df86f.1655522152.git.yantar92@gmail.com> From: Ihor Radchenko Date: Sat, 18 Jun 2022 11:11:12 +0800 Subject: [PATCH 2/2] ob-shell: Fix output containing strings matching `comint-prompt-regexp' * lisp/ob-comint.el (org-babel-comint-wait-for-output): Do not rely on `face-at-point' returning non-nil. * lisp/ob-shell.el (org-babel-shell-set-prompt-commands): New constant holding shell-specific commands to change prompt. (org-babel-prompt-command): New variable holding command to be user to set distinguishable prompt. (org-babel-shell-initialize): Set `org-babel-prompt-command' according to shell name. (org-babel-sh-prompt): New variable holding default shell prompt. (org-babel-sh-initiate-session): Change the default prompt to `org-babel-sh-prompt' and alter `comint-prompt-regexp' to match it tightly. * testing/lisp/test-ob-shell.el (ob-shell/percent-session): Do not expect failure in the fixed test. Fixes https://list.orgmode.org/CKK9TULBP2BG.2UITT31YJV03J@laptop/T/#mc8e3ca2f5f1b9a94040a68b4c6201234b209041c --- lisp/ob-comint.el | 4 +--- lisp/ob-shell.el | 42 ++++++++++++++++++++++++++++++----- testing/lisp/test-ob-shell.el | 4 ++-- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/lisp/ob-comint.el b/lisp/ob-comint.el index 427aba341..1d3e24607 100644 --- a/lisp/ob-comint.el +++ b/lisp/ob-comint.el @@ -124,9 +124,7 @@ (defun org-babel-comint-wait-for-output (buffer) (while (progn (goto-char comint-last-input-end) (not (and (re-search-forward comint-prompt-regexp nil t) - (goto-char (match-beginning 0)) - (string= (face-name (face-at-point)) - "comint-highlight-prompt")))) + (goto-char (match-beginning 0))))) (accept-process-output (get-buffer-process buffer))))) (defun org-babel-comint-eval-invisibly-and-wait-for-file diff --git a/lisp/ob-shell.el b/lisp/ob-shell.el index c25941a44..f80783653 100644 --- a/lisp/ob-shell.el +++ b/lisp/ob-shell.el @@ -42,6 +42,23 @@ (declare-function orgtbl-to-generic "org-table" (table params)) (defvar org-babel-default-header-args:shell '()) (defvar org-babel-shell-names) +(defconst org-babel-shell-set-prompt-commands + '(("fish" . "function fish_prompt\n\techo \"%s\"\nend") + ("csh" . "set prompt=\"%s\"") + ("posh" . "function prompt { \"%s\" }") + (t . "PS1=\"%s\"")) + "Alist assigning shells with their prompt setting command. + +Each element of the alist associates a shell type from +`org-babel-shell-names' with a template used to create a command to +change the default prompt. The template is an argument to `format' +that will be called with a single additional argument: prompt string. + +The fallback association template is defined in (t . \"template\") +alist element.") + +(defvar org-babel-prompt-command) + (defun org-babel-shell-initialize () "Define execution functions associated to shell names. This function has to be called whenever `org-babel-shell-names' @@ -51,7 +68,10 @@ (defun org-babel-shell-initialize () (eval `(defun ,(intern (concat "org-babel-execute:" name)) (body params) ,(format "Execute a block of %s commands with Babel." name) - (let ((shell-file-name ,name)) + (let ((shell-file-name ,name) + (org-babel-prompt-command + (or (alist-get ,name org-babel-shell-set-prompt-commands) + (alist-get t org-babel-shell-set-prompt-commands)))) (org-babel-execute:shell body params)))) (eval `(defalias ',(intern (concat "org-babel-variable-assignments:" name)) 'org-babel-variable-assignments:shell @@ -206,6 +226,13 @@ (defun org-babel-sh-var-to-string (var &optional sep hline) (mapconcat echo-var var "\n")) (t (funcall echo-var var))))) +(defvar org-babel-sh-eoe-indicator "echo 'org_babel_sh_eoe'" + "String to indicate that evaluation has completed.") +(defvar org-babel-sh-eoe-output "org_babel_sh_eoe" + "String to indicate that evaluation has completed.") +(defvar org-babel-sh-prompt "org_babel_sh_prompt> " + "String to set prompt in session shell.") + (defun org-babel-sh-initiate-session (&optional session _params) "Initiate a session named SESSION according to PARAMS." (when (and session (not (string= session "none"))) @@ -213,17 +240,20 @@ (defun org-babel-sh-initiate-session (&optional session _params) (or (org-babel-comint-buffer-livep session) (progn (shell session) + ;; Set unique prompt for easier analysis of the output. + (org-babel-comint-wait-for-output (current-buffer)) + (org-babel-comint-input-command + (current-buffer) + (format org-babel-prompt-command org-babel-sh-prompt)) + (setq-local comint-prompt-regexp + (concat "^" (regexp-quote org-babel-sh-prompt) + " *")) ;; Needed for Emacs 23 since the marker is initially ;; undefined and the filter functions try to use it without ;; checking. (set-marker comint-last-output-start (point)) (get-buffer (current-buffer))))))) -(defvar org-babel-sh-eoe-indicator "echo 'org_babel_sh_eoe'" - "String to indicate that evaluation has completed.") -(defvar org-babel-sh-eoe-output "org_babel_sh_eoe" - "String to indicate that evaluation has completed.") - (defun org-babel-sh-evaluate (session body &optional params stdin cmdline) "Pass BODY to the Shell process in BUFFER. If RESULT-TYPE equals `output' then return a list of the outputs diff --git a/testing/lisp/test-ob-shell.el b/testing/lisp/test-ob-shell.el index e81058ac7..2bfc29228 100644 --- a/testing/lisp/test-ob-shell.el +++ b/testing/lisp/test-ob-shell.el @@ -122,8 +122,8 @@ (ert-deftest ob-shell/percent-simple () (ert-deftest ob-shell/percent-session () "Test percent in output for session. -At the second iteration the string before % is dropped." - :expected-result :failed +Percent is matching the default value of `comint-prompt-regexp', which +can cause issues with analysis." (should (equal "one 0% two\ntree 0% four" (org-test-with-temp-text -- 2.35.1