When function comint-redirect-results-list-from-process is examining the
output buffer of the command it attempts to skip past the command if it
was echoed.
However, this test uses looking-at and so will fail if the command
contains characters with special meansing to regexps. It can also fail
if the command contains a trailing newline character but the
buffer may have a control-M character.
The latter problem can be fixed by calling comint-carriage-motion before
the test is done; the former by looking-at (regexp-quote command)
instead of just at command.
Note that bug 42662 (27.1; `comint-redirect-results-list-from-process’
treats COMMAND as a regexp) is another symptom of the former problem.
Example code to reproduce the problem:
(defun example ()
(interactive)
;; create shell if not already created
(save-window-excursion
(shell))
(let ((p (get-process "shell"))
command
reply)
(process-send-string p "irb\n")
(setq command "puts File.atime(\"example.el\") if File.exist?(\"example.el\")\n")
(setq reply (comint-redirect-results-list-from-process p command "^.*$" 0))
(process-send-string p "quit\n") ;; cleanup!
(message (car reply)) ;; this should be the a time of the file
reply
))
File example.el creates a shell process then runs “irb”, the ruby
interactive shell, then sends it a command with question-marks in it.
The first line returned should be the atime of the file.
Patch:
--- comint.el.orig 2021-01-17 14:22:17.000000000 -0800
+++ comint.el 2021-01-17 16:49:47.000000000 -0800
@@ -3833,9 +3833,11 @@
(accept-process-output process)))
;; Collect the output
(set-buffer output-buffer)
+ (unless comint-inhibit-carriage-motion
+ (comint-carriage-motion (point-min)(point-max)))
(goto-char (point-min))
;; Skip past the command, if it was echoed
- (and (looking-at command)
+ (and (looking-at (regexp-quote command))
(forward-line))
(while (and (not (eobp))
(re-search-forward regexp nil t))