summaryrefslogtreecommitdiff
path: root/lisp/eshell/esh-mode.el
diff options
context:
space:
mode:
authorJim Porter <jporterbugs@gmail.com>2022-01-30 18:53:53 -0800
committerLars Ingebrigtsen <larsi@gnus.org>2022-02-03 20:02:22 +0100
commit3a388ab4a604f868ab2c1f9b3c63a7f7a3221f7f (patch)
treee0c4cb817c5dc16179305307ec0b56e527d7f36d /lisp/eshell/esh-mode.el
parent2e60ef696a3cf16b0eb297948e27ba0cb32a125e (diff)
downloademacs-3a388ab4a604f868ab2c1f9b3c63a7f7a3221f7f.tar.gz
emacs-3a388ab4a604f868ab2c1f9b3c63a7f7a3221f7f.tar.bz2
emacs-3a388ab4a604f868ab2c1f9b3c63a7f7a3221f7f.zip
When executing an Eshell pipeline, send input to the first process
Previously, input was sent to the last process in the pipeline, resulting in unexpected behavior when running commands like 'tr a-z A-Z | rev'. * lisp/eshell/esh-util.el (eshell-process-pair-p) (eshell-make-process-pair): New functions. * lisp/eshell/esh-cmd.el (eshell-last-async-proc): Rename to... (eshell-last-async-procs): ... this, and store a pair of processes. (eshell-interactive-process): Replace with... (eshell-interactive-process-p, eshell-head-process) (eshell-tail-process): ... these. (eshell-cmd-initialize): Set 'eshell-last-async-procs'. (eshell-do-pipelines): Set 'headproc'. (eshell-execute-pipeline): Return 'headproc' and 'tailproc'. (eshell-resume-eval): Use 'eshell-last-async-procs'. (eshell-do-eval): Make sure we work with a pair of processes. * lisp/eshell/esh-proc.el (eshell-send-eof-to-process): Move from here... * lisp/eshell/esh-mode.el (eshell-send-eof-to-process): ... to here, and only send EOF to the head process. * lisp/eshell/em-cmpl.el (eshell-complete-parse-arguments) * lisp/eshell/esh-mode.el (eshell-intercept-commands) (eshell-watch-for-password-prompt): Use 'eshell-interactive-process-p'. * lisp/eshell/em-rebind.el (eshell-delchar-or-maybe-eof) * lisp/eshell/em-term.el (eshell-term-send-raw-string) * lisp/eshell/esh-mode.el (eshell-self-insert-command) (eshell-send-input, eshell-send-invisible): Use 'eshell-head-process'. * lisp/eshell/esh-cmd.el (eshell-as-subcommand): Use 'eshell-tail-process'. * lisp/eshell/eshell.el (eshell-command): * test/lisp/eshell/eshell-tests-helpers.el (eshell-wait-for-subprocess): Use 'eshell-interactive-process-p' and 'eshell-tail-process'. * test/lisp/eshell/eshell-tests.el (eshell-test/pipe-headproc-stdin): New test.
Diffstat (limited to 'lisp/eshell/esh-mode.el')
-rw-r--r--lisp/eshell/esh-mode.el28
1 files changed, 19 insertions, 9 deletions
diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el
index 8302eefe1e6..59c8f8034fe 100644
--- a/lisp/eshell/esh-mode.el
+++ b/lisp/eshell/esh-mode.el
@@ -423,13 +423,13 @@ and the hook `eshell-exit-hook'."
(defun eshell-self-insert-command ()
(interactive)
(process-send-string
- (eshell-interactive-process)
+ (eshell-head-process)
(char-to-string (if (symbolp last-command-event)
(get last-command-event 'ascii-character)
last-command-event))))
(defun eshell-intercept-commands ()
- (when (and (eshell-interactive-process)
+ (when (and (eshell-interactive-process-p)
(not (and (integerp last-input-event)
(memq last-input-event '(?\C-x ?\C-c)))))
(let ((possible-events (where-is-internal this-command))
@@ -595,13 +595,13 @@ If NO-NEWLINE is non-nil, the input is sent without an implied final
newline."
(interactive "P")
;; Note that the input string does not include its terminal newline.
- (let ((proc-running-p (and (eshell-interactive-process)
+ (let ((proc-running-p (and (eshell-head-process)
(not queue-p)))
(inhibit-point-motion-hooks t)
(inhibit-modification-hooks t))
(unless (and proc-running-p
(not (eq (process-status
- (eshell-interactive-process))
+ (eshell-head-process))
'run)))
(if (or proc-running-p
(>= (point) eshell-last-output-end))
@@ -627,8 +627,8 @@ newline."
(if (or eshell-send-direct-to-subprocesses
(= eshell-last-input-start eshell-last-input-end))
(unless no-newline
- (process-send-string (eshell-interactive-process) "\n"))
- (process-send-region (eshell-interactive-process)
+ (process-send-string (eshell-head-process) "\n"))
+ (process-send-region (eshell-head-process)
eshell-last-input-start
eshell-last-input-end)))
(if (= eshell-last-output-end (point))
@@ -665,6 +665,16 @@ newline."
(run-hooks 'eshell-post-command-hook)
(insert-and-inherit input)))))))))
+(defun eshell-send-eof-to-process ()
+ "Send EOF to the currently-running \"head\" process."
+ (interactive)
+ (require 'esh-mode)
+ (declare-function eshell-send-input "esh-mode"
+ (&optional use-region queue-p no-newline))
+ (eshell-send-input nil nil t)
+ (when (eshell-head-process)
+ (process-send-eof (eshell-head-process))))
+
(defsubst eshell-kill-new ()
"Add the last input text to the kill ring."
(kill-ring-save eshell-last-input-start eshell-last-input-end))
@@ -924,9 +934,9 @@ Then send it to the process running in the current buffer."
(interactive) ; Don't pass str as argument, to avoid snooping via C-x ESC ESC
(let ((str (read-passwd
(format "%s Password: "
- (process-name (eshell-interactive-process))))))
+ (process-name (eshell-head-process))))))
(if (stringp str)
- (process-send-string (eshell-interactive-process)
+ (process-send-string (eshell-head-process)
(concat str "\n"))
(message "Warning: text will be echoed"))))
@@ -937,7 +947,7 @@ buffer's process if STRING contains a password prompt defined by
`eshell-password-prompt-regexp'.
This function could be in the list `eshell-output-filter-functions'."
- (when (eshell-interactive-process)
+ (when (eshell-interactive-process-p)
(save-excursion
(let ((case-fold-search t))
(goto-char eshell-last-output-block-begin)