branch: externals/org
commit 801c93638ab4b6616567035c6438ad229bc14c1d
Author: Ihor Radchenko <yanta...@posteo.net>
Commit: Ihor Radchenko <yanta...@posteo.net>

    ob-shell: Fix multi-line scripts in sessions
    
    * lisp/ob-comint.el (org-babel-comint-with-output): Clean up empty
    output.  Such output is emitted unnecessarily for multi-line scripts.
    * lisp/ob-shell.el (org-babel-shell-set-prompt-commands): Disable
    PS2 and equivalent prompts.  Make sure that PROMPT_COMMAND does not
    interfere with PS1 setting in POSIX shells.
    (org-babel-sh-evaluate): Do not send input line-by-line.  Instead, let
    `org-babel-coming-with-output' handle waiting for the output as well
    as recording it.  Update to the new `org-babel-coming-with-output'
    behavior of cleaning empty outputs.
    * testing/lisp/test-ob-shell.el (test-ob-shell/session): Add a test.
    
    Reported-by: Rudolf Adamkovič <salu...@me.com>
    Link: https://list.orgmode.org/orgmode/m2r0zboix1....@me.com/
---
 lisp/ob-comint.el             |  2 +-
 lisp/ob-shell.el              | 29 ++++++++++++++---------------
 testing/lisp/test-ob-shell.el |  6 +++++-
 3 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/lisp/ob-comint.el b/lisp/ob-comint.el
index 36a55d36c1..ec7d3f6c96 100644
--- a/lisp/ob-comint.el
+++ b/lisp/ob-comint.el
@@ -109,7 +109,7 @@ or user `keyboard-quit' during execution of body."
                      "\n" "[\r\n]+" (regexp-quote (or ,full-body "")))
                     string-buffer))
           (setq string-buffer (substring string-buffer (match-end 0))))
-        (split-string string-buffer comint-prompt-regexp)))))
+         (delete "" (split-string string-buffer comint-prompt-regexp))))))
 
 (defun org-babel-comint-input-command (buffer cmd)
   "Pass CMD to BUFFER.
diff --git a/lisp/ob-shell.el b/lisp/ob-shell.el
index 4d579ae87b..d38d2d3353 100644
--- a/lisp/ob-shell.el
+++ b/lisp/ob-shell.el
@@ -47,10 +47,15 @@
 (defvar org-babel-shell-names)
 
 (defconst org-babel-shell-set-prompt-commands
-  '(("fish" . "function fish_prompt\n\techo \"%s\"\nend")
-    ("csh" . "set prompt=\"%s\"")
+  '(;; Fish has no PS2 equivalent.
+    ("fish" . "function fish_prompt\n\techo \"%s\"\nend")
+    ;; prompt2 is like PS2 in POSIX shells.
+    ("csh" . "set prompt=\"%s\"\nset prompt2=\"\"")
+    ;; PowerShell, similar to fish, does not have PS2 equivalent.
     ("posh" . "function prompt { \"%s\" }")
-    (t . "PS1=\"%s\""))
+    ;; PROMPT_COMMAND can override PS1 settings.  Disable it.
+    ;; Disable PS2 to avoid garbage in multi-line inputs.
+    (t . "PROMPT_COMMAND=;PS1=\"%s\";PS2="))
   "Alist assigning shells with their prompt setting command.
 
 Each element of the alist associates a shell type from
@@ -299,20 +304,14 @@ return the value of the last statement in BODY."
             #'org-babel-sh-strip-weird-long-prompt
             (mapcar
              #'org-trim
-             (butlast
+             (butlast ; Remove eoe indicator
               (org-babel-comint-with-output
                   (session org-babel-sh-eoe-output t body)
-                (dolist (line (append (split-string (org-trim body) "\n")
-                                      (list org-babel-sh-eoe-indicator)))
-                  (insert line)
-                  (comint-send-input nil t)
-                  (while (save-excursion
-                           (goto-char comint-last-input-end)
-                           (not (re-search-forward
-                                 comint-prompt-regexp nil t)))
-                    (accept-process-output
-                     (get-buffer-process (current-buffer))))))
-              2))
+                 (insert (org-trim body) "\n"
+                         org-babel-sh-eoe-indicator)
+                (comint-send-input nil t))
+               ;; Remove `org-babel-sh-eoe-indicator' output line.
+              1))
             "\n"))
           ;; External shell script, with or without a predefined
           ;; shebang.
diff --git a/testing/lisp/test-ob-shell.el b/testing/lisp/test-ob-shell.el
index a0d5a8d224..05c369174c 100644
--- a/testing/lisp/test-ob-shell.el
+++ b/testing/lisp/test-ob-shell.el
@@ -46,7 +46,11 @@ returned empty results."
 ob-comint.el, which was not previously tested."
   (let ((res (org-babel-execute:sh "echo 1; echo 2" '((:session . "yes")))))
     (should res)
-    (should (listp res))))
+    (should (listp res)))
+  ;; Test multi-line input.
+  (let ((res (org-babel-execute:sh "if true; then\necho \"yes\"\nfi" 
'((:session . "yes")))))
+    (should res)
+    (should (string= "yes" res))))
 
 ; A list of tests using the samples in ob-shell-test.org
 (ert-deftest ob-shell/generic-uses-no-arrays ()

Reply via email to