From 45d10c678a3c58486e0571d3c3e8ce64feb39299 Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Sat, 15 Jan 2022 15:16:31 -0800 Subject: [PATCH] In Eshell, allow "-n" to suppress the trailing newline for "plain" echo In addition, add a "-N" option to explicitly request a newline. * lisp/eshell/em-basic.el (eshell-echo): Respect OUTPUT-NEWLINE even when 'eshell-plain-echo-behavior' is non-nil. (eshell/echo): Add "-N" option and recommend its use over "-n" in Lisp-friendly echo. (eshell/printnl): Simplify; 'eshell-stringify' is equivalent to calling 'eshell-echo' here. * doc/misc/eshell.texi (Built-in commands): Expand on the documentation of echo. --- doc/misc/eshell.texi | 13 ++++++++++--- lisp/eshell/em-basic.el | 30 ++++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi index f1d7c63805..df6e3b861e 100644 --- a/doc/misc/eshell.texi +++ b/doc/misc/eshell.texi @@ -407,9 +407,16 @@ Built-ins @item echo @cmindex echo -Echoes its input. If @code{eshell-plain-echo-behavior} is -non-@code{nil}, @command{echo} will try to behave more like a plain -shell's @command{echo}. +Echoes its input. By default, this prints in a Lisp-friendly fashion +(so that the value is useful to a Lisp command using the result of +@command{echo} as an argument). If a single argument is passed, +@command{echo} prints that; if multiple arguments are passed, it +prints a list of all the arguments; otherwise, it prints the empty +string. + +If @code{eshell-plain-echo-behavior} is non-@code{nil}, @command{echo} +will try to behave more like a plain shell's @command{echo}, printing +each argument as a string, separated by a space. @item env @cmindex env diff --git a/lisp/eshell/em-basic.el b/lisp/eshell/em-basic.el index 27b343ad39..d3b15c900b 100644 --- a/lisp/eshell/em-basic.el +++ b/lisp/eshell/em-basic.el @@ -82,7 +82,11 @@ eshell-echo It returns a formatted value that should be passed to `eshell-print' or `eshell-printn' for display." (if eshell-plain-echo-behavior - (concat (apply 'eshell-flatten-and-stringify args) "\n") + (progn + ;; If the output does not end in a newline, do not emit one. + (setq eshell-ensure-newline-p nil) + (concat (apply #'eshell-flatten-and-stringify args) + (when output-newline "\n"))) (let ((value (cond ((= (length args) 0) "") @@ -109,18 +113,28 @@ eshell/echo "Implementation of `echo'. See `eshell-plain-echo-behavior'." (eshell-eval-using-options "echo" args - '((?n nil nil output-newline "terminate with a newline") + '((?n nil (nil) output-newline "do not output the trailing newline") + (?N nil (t) output-newline "terminate with a newline") (?h "help" nil nil "output this help screen") :preserve-args - :usage "[-n] [object]") - (eshell-echo args output-newline))) + :usage "[-n | -N] [object]") + (if eshell-plain-echo-behavior + (eshell-echo args (if output-newline (car output-newline) t)) + ;; In Emacs 28.1 and earlier, "-n" was used to add a newline to + ;; non-plain echo in Eshell. This caused confusion due to "-n" + ;; generally having the opposite meaning for echo. Retain this + ;; compatibility for the time being. For more info, see + ;; bug#27361. + (when (equal output-newline '(nil)) + (display-warning + :warning "To terminate with a newline, you should use -N instead.")) + (eshell-echo args output-newline)))) (defun eshell/printnl (&rest args) - "Print out each of the arguments, separated by newlines." + "Print out each of the arguments as strings, separated by newlines." (let ((elems (flatten-tree args))) - (while elems - (eshell-printn (eshell-echo (list (car elems)))) - (setq elems (cdr elems))))) + (dolist (elem elems) + (eshell-printn (eshell-stringify elem))))) (defun eshell/listify (&rest args) "Return the argument(s) as a single list." -- 2.25.1