aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/eshell
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/eshell')
-rw-r--r--lisp/eshell/em-basic.el37
-rw-r--r--lisp/eshell/em-script.el18
-rw-r--r--lisp/eshell/esh-cmd.el63
-rw-r--r--lisp/eshell/esh-opt.el12
4 files changed, 85 insertions, 45 deletions
diff --git a/lisp/eshell/em-basic.el b/lisp/eshell/em-basic.el
index 27b343ad398..ba868cee59e 100644
--- a/lisp/eshell/em-basic.el
+++ b/lisp/eshell/em-basic.el
@@ -82,7 +82,11 @@ equivalent of `echo' can always be achieved by using `identity'."
82It returns a formatted value that should be passed to `eshell-print' 82It returns a formatted value that should be passed to `eshell-print'
83or `eshell-printn' for display." 83or `eshell-printn' for display."
84 (if eshell-plain-echo-behavior 84 (if eshell-plain-echo-behavior
85 (concat (apply 'eshell-flatten-and-stringify args) "\n") 85 (progn
86 ;; If the output does not end in a newline, do not emit one.
87 (setq eshell-ensure-newline-p nil)
88 (concat (apply #'eshell-flatten-and-stringify args)
89 (when output-newline "\n")))
86 (let ((value 90 (let ((value
87 (cond 91 (cond
88 ((= (length args) 0) "") 92 ((= (length args) 0) "")
@@ -109,18 +113,33 @@ or `eshell-printn' for display."
109 "Implementation of `echo'. See `eshell-plain-echo-behavior'." 113 "Implementation of `echo'. See `eshell-plain-echo-behavior'."
110 (eshell-eval-using-options 114 (eshell-eval-using-options
111 "echo" args 115 "echo" args
112 '((?n nil nil output-newline "terminate with a newline") 116 '((?n nil (nil) output-newline
113 (?h "help" nil nil "output this help screen") 117 "do not output the trailing newline")
118 (?N nil (t) output-newline
119 "terminate with a newline")
120 (?E nil nil _disable-escapes
121 "don't interpret backslash escapes (default)")
122 (?h "help" nil nil
123 "output this help screen")
114 :preserve-args 124 :preserve-args
115 :usage "[-n] [object]") 125 :usage "[OPTION]... [OBJECT]...")
116 (eshell-echo args output-newline))) 126 (if eshell-plain-echo-behavior
127 (eshell-echo args (if output-newline (car output-newline) t))
128 ;; In Emacs 28.1 and earlier, "-n" was used to add a newline to
129 ;; non-plain echo in Eshell. This caused confusion due to "-n"
130 ;; generally having the opposite meaning for echo. Retain this
131 ;; compatibility for the time being. For more info, see
132 ;; bug#27361.
133 (when (equal output-newline '(nil))
134 (display-warning
135 :warning "To terminate with a newline, you should use -N instead."))
136 (eshell-echo args output-newline))))
117 137
118(defun eshell/printnl (&rest args) 138(defun eshell/printnl (&rest args)
119 "Print out each of the arguments, separated by newlines." 139 "Print out each of the arguments as strings, separated by newlines."
120 (let ((elems (flatten-tree args))) 140 (let ((elems (flatten-tree args)))
121 (while elems 141 (dolist (elem elems)
122 (eshell-printn (eshell-echo (list (car elems)))) 142 (eshell-printn (eshell-stringify elem)))))
123 (setq elems (cdr elems)))))
124 143
125(defun eshell/listify (&rest args) 144(defun eshell/listify (&rest args)
126 "Return the argument(s) as a single list." 145 "Return the argument(s) as a single list."
diff --git a/lisp/eshell/em-script.el b/lisp/eshell/em-script.el
index e8459513f39..e0bcd8b099f 100644
--- a/lisp/eshell/em-script.el
+++ b/lisp/eshell/em-script.el
@@ -113,27 +113,13 @@ Comments begin with `#'."
113 113
114(defun eshell/source (&rest args) 114(defun eshell/source (&rest args)
115 "Source a file in a subshell environment." 115 "Source a file in a subshell environment."
116 (eshell-eval-using-options 116 (eshell-source-file (car args) (cdr args) t))
117 "source" args
118 '((?h "help" nil nil "show this usage screen")
119 :show-usage
120 :usage "FILE [ARGS]
121Invoke the Eshell commands in FILE in a subshell, binding ARGS to $1,
122$2, etc.")
123 (eshell-source-file (car args) (cdr args) t)))
124 117
125(put 'eshell/source 'eshell-no-numeric-conversions t) 118(put 'eshell/source 'eshell-no-numeric-conversions t)
126 119
127(defun eshell/. (&rest args) 120(defun eshell/. (&rest args)
128 "Source a file in the current environment." 121 "Source a file in the current environment."
129 (eshell-eval-using-options 122 (eshell-source-file (car args) (cdr args)))
130 "." args
131 '((?h "help" nil nil "show this usage screen")
132 :show-usage
133 :usage "FILE [ARGS]
134Invoke the Eshell commands in FILE within the current shell
135environment, binding ARGS to $1, $2, etc.")
136 (eshell-source-file (car args) (cdr args))))
137 123
138(put 'eshell/. 'eshell-no-numeric-conversions t) 124(put 'eshell/. 'eshell-no-numeric-conversions t)
139 125
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index a2d7d9431a9..04d65df4f33 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -107,6 +107,7 @@
107(require 'esh-module) 107(require 'esh-module)
108(require 'esh-io) 108(require 'esh-io)
109(require 'esh-ext) 109(require 'esh-ext)
110(require 'generator)
110 111
111(eval-when-compile 112(eval-when-compile
112 (require 'cl-lib) 113 (require 'cl-lib)
@@ -903,21 +904,55 @@ at the moment are:
903 "Completion for the `debug' command." 904 "Completion for the `debug' command."
904 (while (pcomplete-here '("errors" "commands")))) 905 (while (pcomplete-here '("errors" "commands"))))
905 906
907(iter-defun eshell--find-subcommands (haystack)
908 "Recursively search for subcommand forms in HAYSTACK.
909This yields the SUBCOMMANDs when found in forms like
910\"(eshell-as-subcommand SUBCOMMAND)\"."
911 (dolist (elem haystack)
912 (cond
913 ((eq (car-safe elem) 'eshell-as-subcommand)
914 (iter-yield (cdr elem)))
915 ((listp elem)
916 (iter-yield-from (eshell--find-subcommands elem))))))
917
918(defun eshell--invoke-command-directly (command)
919 "Determine whether the given COMMAND can be invoked directly.
920COMMAND should be a non-top-level Eshell command in parsed form.
921
922A command can be invoked directly if all of the following are true:
923
924* The command is of the form
925 \"(eshell-trap-errors (eshell-named-command NAME ARGS))\",
926 where ARGS is optional.
927
928* NAME is a string referring to an alias function and isn't a
929 complex command (see `eshell-complex-commands').
930
931* Any subcommands in ARGS can also be invoked directly."
932 (when (and (eq (car command) 'eshell-trap-errors)
933 (eq (car (cadr command)) 'eshell-named-command))
934 (let ((name (cadr (cadr command)))
935 (args (cdr-safe (nth 2 (cadr command)))))
936 (and name (stringp name)
937 (not (member name eshell-complex-commands))
938 (catch 'simple
939 (dolist (pred eshell-complex-commands t)
940 (when (and (functionp pred)
941 (funcall pred name))
942 (throw 'simple nil))))
943 (eshell-find-alias-function name)
944 (catch 'indirect-subcommand
945 (iter-do (subcommand (eshell--find-subcommands args))
946 (unless (eshell--invoke-command-directly subcommand)
947 (throw 'indirect-subcommand nil)))
948 t)))))
949
906(defun eshell-invoke-directly (command) 950(defun eshell-invoke-directly (command)
907 (let ((base (cadr (nth 2 (nth 2 (cadr command))))) name) 951 "Determine whether the given COMMAND can be invoked directly.
908 (if (and (eq (car base) 'eshell-trap-errors) 952COMMAND should be a top-level Eshell command in parsed form, as
909 (eq (car (cadr base)) 'eshell-named-command)) 953produced by `eshell-parse-command'."
910 (setq name (cadr (cadr base)))) 954 (let ((base (cadr (nth 2 (nth 2 (cadr command))))))
911 (and name (stringp name) 955 (eshell--invoke-command-directly base)))
912 (not (member name eshell-complex-commands))
913 (catch 'simple
914 (progn
915 (dolist (pred eshell-complex-commands)
916 (if (and (functionp pred)
917 (funcall pred name))
918 (throw 'simple nil)))
919 t))
920 (eshell-find-alias-function name))))
921 956
922(defun eshell-eval-command (command &optional input) 957(defun eshell-eval-command (command &optional input)
923 "Evaluate the given COMMAND iteratively." 958 "Evaluate the given COMMAND iteratively."
diff --git a/lisp/eshell/esh-opt.el b/lisp/eshell/esh-opt.el
index bba1c4ad25d..c802bee3af5 100644
--- a/lisp/eshell/esh-opt.el
+++ b/lisp/eshell/esh-opt.el
@@ -257,12 +257,12 @@ triggered to say that the switch is unrecognized."
257 remaining 257 remaining
258 (let ((extcmd (memq ':external options))) 258 (let ((extcmd (memq ':external options)))
259 (when extcmd 259 (when extcmd
260 (setq extcmd (eshell-search-path (cadr extcmd))) 260 (setq extcmd (eshell-search-path (cadr extcmd))))
261 (if extcmd 261 (if extcmd
262 (throw 'eshell-ext-command extcmd) 262 (throw 'eshell-ext-command extcmd)
263 (error (if (characterp (car switch)) "%s: unrecognized option -%c" 263 (error (if (characterp (car switch)) "%s: unrecognized option -%c"
264 "%s: unrecognized option --%s") 264 "%s: unrecognized option --%s")
265 name (car switch)))))))) 265 name (car switch)))))))
266 266
267(defun eshell--process-args (name args options) 267(defun eshell--process-args (name args options)
268 "Process the given ARGS using OPTIONS." 268 "Process the given ARGS using OPTIONS."