aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/eshell/em-dirs.el99
-rw-r--r--lisp/eshell/esh-cmd.el92
-rw-r--r--lisp/eshell/esh-var.el110
3 files changed, 136 insertions, 165 deletions
diff --git a/lisp/eshell/em-dirs.el b/lisp/eshell/em-dirs.el
index 31588a472ab..7a228676256 100644
--- a/lisp/eshell/em-dirs.el
+++ b/lisp/eshell/em-dirs.el
@@ -62,12 +62,11 @@ they lack somewhat in feel from the typical shell equivalents."
62(defcustom eshell-dirs-load-hook nil 62(defcustom eshell-dirs-load-hook nil
63 "A hook that gets run when `eshell-dirs' is loaded." 63 "A hook that gets run when `eshell-dirs' is loaded."
64 :version "24.1" ; removed eshell-dirs-initialize 64 :version "24.1" ; removed eshell-dirs-initialize
65 :type 'hook 65 :type 'hook)
66 :group 'eshell-dirs)
67 66
68(defcustom eshell-pwd-convert-function (if (eshell-under-windows-p) 67(defcustom eshell-pwd-convert-function (if (eshell-under-windows-p)
69 'expand-file-name 68 #'expand-file-name
70 'identity) 69 #'identity)
71 "The function used to normalize the value of Eshell's `pwd'. 70 "The function used to normalize the value of Eshell's `pwd'.
72The value returned by `pwd' is also used when recording the 71The value returned by `pwd' is also used when recording the
73last-visited directory in the last-dir-ring, so it will affect the 72last-visited directory in the last-dir-ring, so it will affect the
@@ -75,8 +74,7 @@ form of the list used by `cd ='."
75 :type '(radio (function-item file-truename) 74 :type '(radio (function-item file-truename)
76 (function-item expand-file-name) 75 (function-item expand-file-name)
77 (function-item identity) 76 (function-item identity)
78 (function :tag "Other")) 77 (function :tag "Other")))
79 :group 'eshell-dirs)
80 78
81(defcustom eshell-ask-to-save-last-dir 'always 79(defcustom eshell-ask-to-save-last-dir 'always
82 "Determine if the last-dir-ring should be automatically saved. 80 "Determine if the last-dir-ring should be automatically saved.
@@ -88,63 +86,53 @@ If set to t, always ask if any Eshell buffers are open at exit time.
88If set to `always', the list-dir-ring will always be saved, silently." 86If set to `always', the list-dir-ring will always be saved, silently."
89 :type '(choice (const :tag "Never" nil) 87 :type '(choice (const :tag "Never" nil)
90 (const :tag "Ask" t) 88 (const :tag "Ask" t)
91 (const :tag "Always save" always)) 89 (const :tag "Always save" always)))
92 :group 'eshell-dirs)
93 90
94(defcustom eshell-cd-shows-directory nil 91(defcustom eshell-cd-shows-directory nil
95 "If non-nil, using `cd' will report the directory it changes to." 92 "If non-nil, using `cd' will report the directory it changes to."
96 :type 'boolean 93 :type 'boolean)
97 :group 'eshell-dirs)
98 94
99(defcustom eshell-cd-on-directory t 95(defcustom eshell-cd-on-directory t
100 "If non-nil, do a cd if a directory is in command position." 96 "If non-nil, do a cd if a directory is in command position."
101 :type 'boolean 97 :type 'boolean)
102 :group 'eshell-dirs)
103 98
104(defcustom eshell-directory-change-hook nil 99(defcustom eshell-directory-change-hook nil
105 "A hook to run when the current directory changes." 100 "A hook to run when the current directory changes."
106 :type 'hook 101 :type 'hook)
107 :group 'eshell-dirs)
108 102
109(defcustom eshell-list-files-after-cd nil 103(defcustom eshell-list-files-after-cd nil
110 "If non-nil, call \"ls\" with any remaining args after doing a cd. 104 "If non-nil, call \"ls\" with any remaining args after doing a cd.
111This is provided for convenience, since the same effect is easily 105This is provided for convenience, since the same effect is easily
112achieved by adding a function to `eshell-directory-change-hook' that 106achieved by adding a function to `eshell-directory-change-hook' that
113calls \"ls\" and references `eshell-last-arguments'." 107calls \"ls\" and references `eshell-last-arguments'."
114 :type 'boolean 108 :type 'boolean)
115 :group 'eshell-dirs)
116 109
117(defcustom eshell-pushd-tohome nil 110(defcustom eshell-pushd-tohome nil
118 "If non-nil, make pushd with no arg behave as `pushd ~' (like `cd'). 111 "If non-nil, make pushd with no arg behave as `pushd ~' (like `cd').
119This mirrors the optional behavior of tcsh." 112This mirrors the optional behavior of tcsh."
120 :type 'boolean 113 :type 'boolean)
121 :group 'eshell-dirs)
122 114
123(defcustom eshell-pushd-dextract nil 115(defcustom eshell-pushd-dextract nil
124 "If non-nil, make \"pushd +n\" pop the nth dir to the stack top. 116 "If non-nil, make \"pushd +n\" pop the nth dir to the stack top.
125This mirrors the optional behavior of tcsh." 117This mirrors the optional behavior of tcsh."
126 :type 'boolean 118 :type 'boolean)
127 :group 'eshell-dirs)
128 119
129(defcustom eshell-pushd-dunique nil 120(defcustom eshell-pushd-dunique nil
130 "If non-nil, make pushd only add unique directories to the stack. 121 "If non-nil, make pushd only add unique directories to the stack.
131This mirrors the optional behavior of tcsh." 122This mirrors the optional behavior of tcsh."
132 :type 'boolean 123 :type 'boolean)
133 :group 'eshell-dirs)
134 124
135(defcustom eshell-dirtrack-verbose t 125(defcustom eshell-dirtrack-verbose t
136 "If non-nil, show the directory stack following directory change. 126 "If non-nil, show the directory stack following directory change.
137This is effective only if directory tracking is enabled." 127This is effective only if directory tracking is enabled."
138 :type 'boolean 128 :type 'boolean)
139 :group 'eshell-dirs)
140 129
141(defcustom eshell-last-dir-ring-file-name 130(defcustom eshell-last-dir-ring-file-name
142 (expand-file-name "lastdir" eshell-directory-name) 131 (expand-file-name "lastdir" eshell-directory-name)
143 "If non-nil, name of the file to read/write the last-dir-ring. 132 "If non-nil, name of the file to read/write the last-dir-ring.
144See also `eshell-read-last-dir-ring' and `eshell-write-last-dir-ring'. 133See also `eshell-read-last-dir-ring' and `eshell-write-last-dir-ring'.
145If it is nil, the last-dir-ring will not be written to disk." 134If it is nil, the last-dir-ring will not be written to disk."
146 :type 'file 135 :type 'file)
147 :group 'eshell-dirs)
148 136
149(defcustom eshell-last-dir-ring-size 32 137(defcustom eshell-last-dir-ring-size 32
150 "If non-nil, the size of the directory history ring. 138 "If non-nil, the size of the directory history ring.
@@ -164,13 +152,11 @@ directories gets pushed, and its size is unlimited.
164explicitly very much, but every once in a while would like to return to 152explicitly very much, but every once in a while would like to return to
165a previously visited directory without having to type in the whole 153a previously visited directory without having to type in the whole
166thing again." 154thing again."
167 :type 'integer 155 :type 'integer)
168 :group 'eshell-dirs)
169 156
170(defcustom eshell-last-dir-unique t 157(defcustom eshell-last-dir-unique t
171 "If non-nil, `eshell-last-dir-ring' contains only unique entries." 158 "If non-nil, `eshell-last-dir-ring' contains only unique entries."
172 :type 'boolean 159 :type 'boolean)
173 :group 'eshell-dirs)
174 160
175;;; Internal Variables: 161;;; Internal Variables:
176 162
@@ -189,20 +175,22 @@ Thus, this does not include the current directory.")
189 (setq eshell-variable-aliases-list 175 (setq eshell-variable-aliases-list
190 (append 176 (append
191 eshell-variable-aliases-list 177 eshell-variable-aliases-list
192 '(("-" (lambda (indices) 178 `(("-" (lambda (indices)
193 (if (not indices) 179 (if (not indices)
194 (unless (ring-empty-p eshell-last-dir-ring)
195 (expand-file-name
196 (ring-ref eshell-last-dir-ring 0)))
197 (expand-file-name
198 (eshell-apply-indices eshell-last-dir-ring indices)))))
199 ("+" "PWD")
200 ("PWD" (lambda (indices)
201 (expand-file-name (eshell/pwd))) t)
202 ("OLDPWD" (lambda (indices)
203 (unless (ring-empty-p eshell-last-dir-ring) 180 (unless (ring-empty-p eshell-last-dir-ring)
204 (expand-file-name 181 (expand-file-name
205 (ring-ref eshell-last-dir-ring 0)))) t)))) 182 (ring-ref eshell-last-dir-ring 0)))
183 (expand-file-name
184 (eshell-apply-indices eshell-last-dir-ring indices)))))
185 ("+" "PWD")
186 ("PWD" ,(lambda (_indices)
187 (expand-file-name (eshell/pwd)))
188 t)
189 ("OLDPWD" ,(lambda (_indices)
190 (unless (ring-empty-p eshell-last-dir-ring)
191 (expand-file-name
192 (ring-ref eshell-last-dir-ring 0))))
193 t))))
206 194
207 (when eshell-cd-on-directory 195 (when eshell-cd-on-directory
208 (make-local-variable 'eshell-interpreter-alist) 196 (make-local-variable 'eshell-interpreter-alist)
@@ -213,14 +201,14 @@ Thus, this does not include the current directory.")
213 eshell-interpreter-alist))) 201 eshell-interpreter-alist)))
214 202
215 (add-hook 'eshell-parse-argument-hook 203 (add-hook 'eshell-parse-argument-hook
216 'eshell-parse-user-reference nil t) 204 #'eshell-parse-user-reference nil t)
217 (if (eshell-under-windows-p) 205 (if (eshell-under-windows-p)
218 (add-hook 'eshell-parse-argument-hook 206 (add-hook 'eshell-parse-argument-hook
219 'eshell-parse-drive-letter nil t)) 207 #'eshell-parse-drive-letter nil t))
220 208
221 (when (eshell-using-module 'eshell-cmpl) 209 (when (eshell-using-module 'eshell-cmpl)
222 (add-hook 'pcomplete-try-first-hook 210 (add-hook 'pcomplete-try-first-hook
223 'eshell-complete-user-reference nil t)) 211 #'eshell-complete-user-reference nil t))
224 212
225 (make-local-variable 'eshell-dirstack) 213 (make-local-variable 'eshell-dirstack)
226 (make-local-variable 'eshell-last-dir-ring) 214 (make-local-variable 'eshell-last-dir-ring)
@@ -230,9 +218,9 @@ Thus, this does not include the current directory.")
230 (unless eshell-last-dir-ring 218 (unless eshell-last-dir-ring
231 (setq eshell-last-dir-ring (make-ring eshell-last-dir-ring-size))) 219 (setq eshell-last-dir-ring (make-ring eshell-last-dir-ring-size)))
232 220
233 (add-hook 'eshell-exit-hook 'eshell-write-last-dir-ring nil t) 221 (add-hook 'eshell-exit-hook #'eshell-write-last-dir-ring nil t)
234 222
235 (add-hook 'kill-emacs-hook 'eshell-save-some-last-dir)) 223 (add-hook 'kill-emacs-hook #'eshell-save-some-last-dir))
236 224
237(defun eshell-save-some-last-dir () 225(defun eshell-save-some-last-dir ()
238 "Save the list-dir-ring for any open Eshell buffers." 226 "Save the list-dir-ring for any open Eshell buffers."
@@ -309,11 +297,9 @@ Thus, this does not include the current directory.")
309 (not (and (eshell-under-windows-p) 297 (not (and (eshell-under-windows-p)
310 (string-match "\\`[A-Za-z]:[\\/]\\'" path)))) 298 (string-match "\\`[A-Za-z]:[\\/]\\'" path))))
311 (setq path (substring path 0 (1- (length path))))) 299 (setq path (substring path 0 (1- (length path)))))
312 (if eshell-pwd-convert-function 300 (funcall (or eshell-pwd-convert-function #'identity) path)))
313 (funcall eshell-pwd-convert-function path)
314 path)))
315 301
316(defun eshell-expand-multiple-dots (path) 302(defun eshell-expand-multiple-dots (filename)
317 ;; FIXME: This advice recommendation is rather odd: it's somewhat 303 ;; FIXME: This advice recommendation is rather odd: it's somewhat
318 ;; dangerous and it claims not to work with minibuffer-completion, which 304 ;; dangerous and it claims not to work with minibuffer-completion, which
319 ;; makes it much less interesting. 305 ;; makes it much less interesting.
@@ -326,16 +312,17 @@ in the minibuffer:
326 (advice-add 'expand-file-name :around #'my-expand-multiple-dots) 312 (advice-add 'expand-file-name :around #'my-expand-multiple-dots)
327 (defun my-expand-multiple-dots (orig-fun filename &rest args) 313 (defun my-expand-multiple-dots (orig-fun filename &rest args)
328 (apply orig-fun (eshell-expand-multiple-dots filename) args))" 314 (apply orig-fun (eshell-expand-multiple-dots filename) args))"
329 (while (string-match "\\(?:^\\|/\\)\\.\\.\\(\\.+\\)\\(?:$\\|/\\)" path) 315 (while (string-match "\\(?:\\`\\|/\\)\\.\\.\\(\\.+\\)\\(?:\\'\\|/\\)"
330 (let* ((extra-dots (match-string 1 path)) 316 filename)
317 (let* ((extra-dots (match-string 1 filename))
331 (len (length extra-dots)) 318 (len (length extra-dots))
332 replace-text) 319 replace-text)
333 (while (> len 0) 320 (while (> len 0)
334 (setq replace-text (concat replace-text "/..") 321 (setq replace-text (concat replace-text "/..")
335 len (1- len))) 322 len (1- len)))
336 (setq path 323 (setq filename
337 (replace-match replace-text t t path 1)))) 324 (replace-match replace-text t t filename 1))))
338 path) 325 filename)
339 326
340(defun eshell-find-previous-directory (regexp) 327(defun eshell-find-previous-directory (regexp)
341 "Find the most recent last-dir matching REGEXP." 328 "Find the most recent last-dir matching REGEXP."
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index ee4dbd5550f..1ed5d5d7018 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -122,24 +122,20 @@ however."
122 122
123(defcustom eshell-prefer-lisp-functions nil 123(defcustom eshell-prefer-lisp-functions nil
124 "If non-nil, prefer Lisp functions to external commands." 124 "If non-nil, prefer Lisp functions to external commands."
125 :type 'boolean 125 :type 'boolean)
126 :group 'eshell-cmd)
127 126
128(defcustom eshell-lisp-regexp "\\([(`]\\|#'\\)" 127(defcustom eshell-lisp-regexp "\\([(`]\\|#'\\)"
129 "A regexp which, if matched at beginning of an argument, means Lisp. 128 "A regexp which, if matched at beginning of an argument, means Lisp.
130Such arguments will be passed to `read', and then evaluated." 129Such arguments will be passed to `read', and then evaluated."
131 :type 'regexp 130 :type 'regexp)
132 :group 'eshell-cmd)
133 131
134(defcustom eshell-pre-command-hook nil 132(defcustom eshell-pre-command-hook nil
135 "A hook run before each interactive command is invoked." 133 "A hook run before each interactive command is invoked."
136 :type 'hook 134 :type 'hook)
137 :group 'eshell-cmd)
138 135
139(defcustom eshell-post-command-hook nil 136(defcustom eshell-post-command-hook nil
140 "A hook run after each interactive command is invoked." 137 "A hook run after each interactive command is invoked."
141 :type 'hook 138 :type 'hook)
142 :group 'eshell-cmd)
143 139
144(defcustom eshell-prepare-command-hook nil 140(defcustom eshell-prepare-command-hook nil
145 "A set of functions called to prepare a named command. 141 "A set of functions called to prepare a named command.
@@ -149,8 +145,7 @@ the value of these symbols if necessary.
149 145
150To prevent a command from executing at all, set 146To prevent a command from executing at all, set
151`eshell-last-command-name' to nil." 147`eshell-last-command-name' to nil."
152 :type 'hook 148 :type 'hook)
153 :group 'eshell-cmd)
154 149
155(defcustom eshell-named-command-hook nil 150(defcustom eshell-named-command-hook nil
156 "A set of functions called before a named command is invoked. 151 "A set of functions called before a named command is invoked.
@@ -165,7 +160,7 @@ In order to substitute an alternate command form for execution, the
165hook function should throw it using the tag `eshell-replace-command'. 160hook function should throw it using the tag `eshell-replace-command'.
166For example: 161For example:
167 162
168 (add-hook \\='eshell-named-command-hook \\='subst-with-cd) 163 (add-hook \\='eshell-named-command-hook #\\='subst-with-cd)
169 (defun subst-with-cd (command args) 164 (defun subst-with-cd (command args)
170 (throw \\='eshell-replace-command 165 (throw \\='eshell-replace-command
171 (eshell-parse-command \"cd\" args))) 166 (eshell-parse-command \"cd\" args)))
@@ -173,8 +168,7 @@ For example:
173Although useless, the above code will cause any non-glob, non-Lisp 168Although useless, the above code will cause any non-glob, non-Lisp
174command (i.e., `ls' as opposed to `*ls' or `(ls)') to be replaced by a 169command (i.e., `ls' as opposed to `*ls' or `(ls)') to be replaced by a
175call to `cd' using the arguments that were passed to the function." 170call to `cd' using the arguments that were passed to the function."
176 :type 'hook 171 :type 'hook)
177 :group 'eshell-cmd)
178 172
179(defcustom eshell-pre-rewrite-command-hook 173(defcustom eshell-pre-rewrite-command-hook
180 '(eshell-no-command-conversion 174 '(eshell-no-command-conversion
@@ -182,8 +176,7 @@ call to `cd' using the arguments that were passed to the function."
182 "A hook run before command rewriting begins. 176 "A hook run before command rewriting begins.
183The terms of the command to be rewritten is passed as arguments, and 177The terms of the command to be rewritten is passed as arguments, and
184may be modified in place. Any return value is ignored." 178may be modified in place. Any return value is ignored."
185 :type 'hook 179 :type 'hook)
186 :group 'eshell-cmd)
187 180
188(defcustom eshell-rewrite-command-hook 181(defcustom eshell-rewrite-command-hook
189 '(eshell-rewrite-for-command 182 '(eshell-rewrite-for-command
@@ -202,8 +195,7 @@ so by adding a function to this hook. The first function to return a
202substitute command form is the one used. Each function is passed the 195substitute command form is the one used. Each function is passed the
203command's full argument list, which is a list of sexps (typically 196command's full argument list, which is a list of sexps (typically
204forms or strings)." 197forms or strings)."
205 :type 'hook 198 :type 'hook)
206 :group 'eshell-cmd)
207 199
208(defvar eshell-post-rewrite-command-function #'identity 200(defvar eshell-post-rewrite-command-function #'identity
209 "Function run after command rewriting is finished. 201 "Function run after command rewriting is finished.
@@ -228,16 +220,14 @@ If an entry is a function, it will be called with the name, and should
228return non-nil if the command is complex." 220return non-nil if the command is complex."
229 :type '(repeat :tag "Commands" 221 :type '(repeat :tag "Commands"
230 (choice (string :tag "Name") 222 (choice (string :tag "Name")
231 (function :tag "Predicate"))) 223 (function :tag "Predicate"))))
232 :group 'eshell-cmd)
233 224
234;;; User Variables: 225;;; User Variables:
235 226
236(defcustom eshell-cmd-load-hook nil 227(defcustom eshell-cmd-load-hook nil
237 "A hook that gets run when `eshell-cmd' is loaded." 228 "A hook that gets run when `eshell-cmd' is loaded."
238 :version "24.1" ; removed eshell-cmd-initialize 229 :version "24.1" ; removed eshell-cmd-initialize
239 :type 'hook 230 :type 'hook)
240 :group 'eshell-cmd)
241 231
242(defcustom eshell-debug-command nil 232(defcustom eshell-debug-command nil
243 "If non-nil, enable Eshell debugging code. 233 "If non-nil, enable Eshell debugging code.
@@ -247,9 +237,8 @@ you must re-load `esh-cmd.el'."
247 :initialize 'custom-initialize-default 237 :initialize 'custom-initialize-default
248 :set (lambda (symbol value) 238 :set (lambda (symbol value)
249 (set symbol value) 239 (set symbol value)
250 (load-library "esh-cmd")) 240 (load "esh-cmd"))
251 :type 'boolean 241 :type 'boolean)
252 :group 'eshell-cmd)
253 242
254(defcustom eshell-deferrable-commands 243(defcustom eshell-deferrable-commands
255 '(eshell-named-command 244 '(eshell-named-command
@@ -259,16 +248,14 @@ you must re-load `esh-cmd.el'."
259If they return a process object, execution of the calling Eshell 248If they return a process object, execution of the calling Eshell
260command will wait for completion (in the background) before finishing 249command will wait for completion (in the background) before finishing
261the command." 250the command."
262 :type '(repeat function) 251 :type '(repeat function))
263 :group 'eshell-cmd)
264 252
265(defcustom eshell-subcommand-bindings 253(defcustom eshell-subcommand-bindings
266 '((eshell-in-subcommand-p t) 254 '((eshell-in-subcommand-p t)
267 (default-directory default-directory) 255 (default-directory default-directory)
268 (process-environment (eshell-copy-environment))) 256 (process-environment (eshell-copy-environment)))
269 "A list of `let' bindings for subcommand environments." 257 "A list of `let' bindings for subcommand environments."
270 :type 'sexp 258 :type 'sexp)
271 :group 'eshell-cmd)
272 259
273(put 'risky-local-variable 'eshell-subcommand-bindings t) 260(put 'risky-local-variable 'eshell-subcommand-bindings t)
274 261
@@ -307,7 +294,7 @@ otherwise t.")
307 (set (make-local-variable 'eshell-last-command-name) nil) 294 (set (make-local-variable 'eshell-last-command-name) nil)
308 (set (make-local-variable 'eshell-last-async-proc) nil) 295 (set (make-local-variable 'eshell-last-async-proc) nil)
309 296
310 (add-hook 'eshell-kill-hook 'eshell-resume-command nil t) 297 (add-hook 'eshell-kill-hook #'eshell-resume-command nil t)
311 298
312 ;; make sure that if a command is over, and no process is being 299 ;; make sure that if a command is over, and no process is being
313 ;; waited for, that `eshell-current-command' is set to nil. This 300 ;; waited for, that `eshell-current-command' is set to nil. This
@@ -317,16 +304,17 @@ otherwise t.")
317 (function 304 (function
318 (lambda () 305 (lambda ()
319 (setq eshell-current-command nil 306 (setq eshell-current-command nil
320 eshell-last-async-proc nil))) nil t) 307 eshell-last-async-proc nil)))
308 nil t)
321 309
322 (add-hook 'eshell-parse-argument-hook 310 (add-hook 'eshell-parse-argument-hook
323 'eshell-parse-subcommand-argument nil t) 311 #'eshell-parse-subcommand-argument nil t)
324 (add-hook 'eshell-parse-argument-hook 312 (add-hook 'eshell-parse-argument-hook
325 'eshell-parse-lisp-argument nil t) 313 #'eshell-parse-lisp-argument nil t)
326 314
327 (when (eshell-using-module 'eshell-cmpl) 315 (when (eshell-using-module 'eshell-cmpl)
328 (add-hook 'pcomplete-try-first-hook 316 (add-hook 'pcomplete-try-first-hook
329 'eshell-complete-lisp-symbols nil t))) 317 #'eshell-complete-lisp-symbols nil t)))
330 318
331(defun eshell-complete-lisp-symbols () 319(defun eshell-complete-lisp-symbols ()
332 "If there is a user reference, complete it." 320 "If there is a user reference, complete it."
@@ -724,6 +712,8 @@ ensconced in a list."
724 eshell-current-subjob-p) 712 eshell-current-subjob-p)
725 ,object)) 713 ,object))
726 714
715(defvar eshell-this-command-hook nil)
716
727(defmacro eshell-trap-errors (object) 717(defmacro eshell-trap-errors (object)
728 "Trap any errors that occur, so they are not entirely fatal. 718 "Trap any errors that occur, so they are not entirely fatal.
729Also, the variable `eshell-this-command-hook' is available for the 719Also, the variable `eshell-this-command-hook' is available for the
@@ -736,9 +726,9 @@ this grossness will be made to disappear by using `call/cc'..."
736 (eshell-condition-case err 726 (eshell-condition-case err
737 (prog1 727 (prog1
738 ,object 728 ,object
739 (run-hooks 'eshell-this-command-hook)) 729 (mapc #'funcall eshell-this-command-hook))
740 (error 730 (error
741 (run-hooks 'eshell-this-command-hook) 731 (mapc #'funcall eshell-this-command-hook)
742 (eshell-errorn (error-message-string err)) 732 (eshell-errorn (error-message-string err))
743 (eshell-close-handles 1))))) 733 (eshell-close-handles 1)))))
744 734
@@ -1059,16 +1049,8 @@ be finished later after the completion of an asynchronous subprocess."
1059 ((eq (car form) 'setcdr) 1049 ((eq (car form) 'setcdr)
1060 (setcar (cdr args) (eshell-do-eval (cadr args) synchronous-p)) 1050 (setcar (cdr args) (eshell-do-eval (cadr args) synchronous-p))
1061 (eval form)) 1051 (eval form))
1062 ((memq (car form) '(let catch condition-case unwind-protect)) 1052 ((eq (car form) 'let)
1063 ;; `let', `condition-case' and `unwind-protect' have to be 1053 (if (not (eq (car (cadr args)) 'eshell-do-eval))
1064 ;; handled specially, because we only want to call
1065 ;; `eshell-do-eval' on their first form.
1066 ;;
1067 ;; NOTE: This requires obedience by all forms which this
1068 ;; function might encounter, that they do not contain
1069 ;; other special forms.
1070 (if (and (eq (car form) 'let)
1071 (not (eq (car (cadr args)) 'eshell-do-eval)))
1072 (eshell-manipulate "evaluating let args" 1054 (eshell-manipulate "evaluating let args"
1073 (dolist (letarg (car args)) 1055 (dolist (letarg (car args))
1074 (if (and (listp letarg) 1056 (if (and (listp letarg)
@@ -1076,6 +1058,21 @@ be finished later after the completion of an asynchronous subprocess."
1076 (setcdr letarg 1058 (setcdr letarg
1077 (list (eshell-do-eval 1059 (list (eshell-do-eval
1078 (cadr letarg) synchronous-p))))))) 1060 (cadr letarg) synchronous-p)))))))
1061 (cl-progv
1062 (mapcar (lambda (binding) (if (consp binding) (car binding) binding))
1063 (car args))
1064 ;; These expressions should all be constants now.
1065 (mapcar (lambda (binding) (if (consp binding) (eval (cadr binding))))
1066 (car args))
1067 (eshell-do-eval (macroexp-progn (cdr args)) synchronous-p)))
1068 ((memq (car form) '(catch condition-case unwind-protect))
1069 ;; `condition-case' and `unwind-protect' have to be
1070 ;; handled specially, because we only want to call
1071 ;; `eshell-do-eval' on their first form.
1072 ;;
1073 ;; NOTE: This requires obedience by all forms which this
1074 ;; function might encounter, that they do not contain
1075 ;; other special forms.
1079 (unless (eq (car form) 'unwind-protect) 1076 (unless (eq (car form) 'unwind-protect)
1080 (setq args (cdr args))) 1077 (setq args (cdr args)))
1081 (unless (eq (caar args) 'eshell-do-eval) 1078 (unless (eq (caar args) 'eshell-do-eval)
@@ -1158,10 +1155,9 @@ be finished later after the completion of an asynchronous subprocess."
1158 (setq name (substring name 1) 1155 (setq name (substring name 1)
1159 direct t)) 1156 direct t))
1160 (if (and (not direct) 1157 (if (and (not direct)
1161 (eshell-using-module 'eshell-alias) 1158 (fboundp 'eshell-lookup-alias)
1162 (setq alias 1159 (setq alias
1163 (funcall (symbol-function 'eshell-lookup-alias) 1160 (eshell-lookup-alias name)))
1164 name)))
1165 (setq program 1161 (setq program
1166 (concat name " is an alias, defined as \"" 1162 (concat name " is an alias, defined as \""
1167 (cadr alias) "\""))) 1163 (cadr alias) "\"")))
diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el
index 133a4f9c713..d8be72e3596 100644
--- a/lisp/eshell/esh-var.el
+++ b/lisp/eshell/esh-var.el
@@ -128,60 +128,55 @@ variable value, a subcommand, or even the result of a Lisp form."
128(defcustom eshell-var-load-hook nil 128(defcustom eshell-var-load-hook nil
129 "A list of functions to call when loading `eshell-var'." 129 "A list of functions to call when loading `eshell-var'."
130 :version "24.1" ; removed eshell-var-initialize 130 :version "24.1" ; removed eshell-var-initialize
131 :type 'hook 131 :type 'hook)
132 :group 'eshell-var)
133 132
134(defcustom eshell-prefer-lisp-variables nil 133(defcustom eshell-prefer-lisp-variables nil
135 "If non-nil, prefer Lisp variables to environment variables." 134 "If non-nil, prefer Lisp variables to environment variables."
136 :type 'boolean 135 :type 'boolean)
137 :group 'eshell-var)
138 136
139(defcustom eshell-complete-export-definition t 137(defcustom eshell-complete-export-definition t
140 "If non-nil, completing names for `export' shows current definition." 138 "If non-nil, completing names for `export' shows current definition."
141 :type 'boolean 139 :type 'boolean)
142 :group 'eshell-var)
143 140
144(defcustom eshell-modify-global-environment nil 141(defcustom eshell-modify-global-environment nil
145 "If non-nil, using `export' changes Emacs's global environment." 142 "If non-nil, using `export' changes Emacs's global environment."
146 :type 'boolean 143 :type 'boolean)
147 :group 'eshell-var)
148 144
149(defcustom eshell-variable-name-regexp "[A-Za-z0-9_-]+" 145(defcustom eshell-variable-name-regexp "[A-Za-z0-9_-]+"
150 "A regexp identifying what constitutes a variable name reference. 146 "A regexp identifying what constitutes a variable name reference.
151Note that this only applies for `$NAME'. If the syntax `$<NAME>' is 147Note that this only applies for `$NAME'. If the syntax `$<NAME>' is
152used, then NAME can contain any character, including angle brackets, 148used, then NAME can contain any character, including angle brackets,
153if they are quoted with a backslash." 149if they are quoted with a backslash."
154 :type 'regexp 150 :type 'regexp)
155 :group 'eshell-var)
156 151
157(defcustom eshell-variable-aliases-list 152(defcustom eshell-variable-aliases-list
158 '(;; for eshell.el 153 `(;; for eshell.el
159 ("COLUMNS" (lambda (indices) (window-width)) t) 154 ("COLUMNS" ,(lambda (_indices) (window-width)) t)
160 ("LINES" (lambda (indices) (window-height)) t) 155 ("LINES" ,(lambda (_indices) (window-height)) t)
161 156
162 ;; for eshell-cmd.el 157 ;; for eshell-cmd.el
163 ("_" (lambda (indices) 158 ("_" ,(lambda (indices)
164 (if (not indices) 159 (if (not indices)
165 (car (last eshell-last-arguments)) 160 (car (last eshell-last-arguments))
166 (eshell-apply-indices eshell-last-arguments 161 (eshell-apply-indices eshell-last-arguments
167 indices)))) 162 indices))))
168 ("?" eshell-last-command-status) 163 ("?" eshell-last-command-status)
169 ("$" eshell-last-command-result) 164 ("$" eshell-last-command-result)
170 ("0" eshell-command-name) 165 ("0" eshell-command-name)
171 ("1" (lambda (indices) (nth 0 eshell-command-arguments))) 166 ("1" ,(lambda (_indices) (nth 0 eshell-command-arguments)))
172 ("2" (lambda (indices) (nth 1 eshell-command-arguments))) 167 ("2" ,(lambda (_indices) (nth 1 eshell-command-arguments)))
173 ("3" (lambda (indices) (nth 2 eshell-command-arguments))) 168 ("3" ,(lambda (_indices) (nth 2 eshell-command-arguments)))
174 ("4" (lambda (indices) (nth 3 eshell-command-arguments))) 169 ("4" ,(lambda (_indices) (nth 3 eshell-command-arguments)))
175 ("5" (lambda (indices) (nth 4 eshell-command-arguments))) 170 ("5" ,(lambda (_indices) (nth 4 eshell-command-arguments)))
176 ("6" (lambda (indices) (nth 5 eshell-command-arguments))) 171 ("6" ,(lambda (_indices) (nth 5 eshell-command-arguments)))
177 ("7" (lambda (indices) (nth 6 eshell-command-arguments))) 172 ("7" ,(lambda (_indices) (nth 6 eshell-command-arguments)))
178 ("8" (lambda (indices) (nth 7 eshell-command-arguments))) 173 ("8" ,(lambda (_indices) (nth 7 eshell-command-arguments)))
179 ("9" (lambda (indices) (nth 8 eshell-command-arguments))) 174 ("9" ,(lambda (_indices) (nth 8 eshell-command-arguments)))
180 ("*" (lambda (indices) 175 ("*" ,(lambda (indices)
181 (if (not indices) 176 (if (not indices)
182 eshell-command-arguments 177 eshell-command-arguments
183 (eshell-apply-indices eshell-command-arguments 178 (eshell-apply-indices eshell-command-arguments
184 indices))))) 179 indices)))))
185 "This list provides aliasing for variable references. 180 "This list provides aliasing for variable references.
186It is very similar in concept to what `eshell-user-aliases-list' does 181It is very similar in concept to what `eshell-user-aliases-list' does
187for commands. Each member of this defines the name of a command, 182for commands. Each member of this defines the name of a command,
@@ -197,8 +192,7 @@ function), and the arguments passed to this function would be the list
197'(10 20)', and nil." 192'(10 20)', and nil."
198 :type '(repeat (list string sexp 193 :type '(repeat (list string sexp
199 (choice (const :tag "Copy to environment" t) 194 (choice (const :tag "Copy to environment" t)
200 (const :tag "Use only in Eshell" nil)))) 195 (const :tag "Use only in Eshell" nil)))))
201 :group 'eshell-var)
202 196
203(put 'eshell-variable-aliases-list 'risky-local-variable t) 197(put 'eshell-variable-aliases-list 'risky-local-variable t)
204 198
@@ -397,6 +391,8 @@ process any indices that come after the variable reference."
397 indices (and (not (eobp)) 391 indices (and (not (eobp))
398 (eq (char-after) ?\[) 392 (eq (char-after) ?\[)
399 (eshell-parse-indices)) 393 (eshell-parse-indices))
394 ;; This is an expression that will be evaluated by `eshell-do-eval',
395 ;; which only support let-binding of dynamically-scoped vars
400 value `(let ((indices ',indices)) ,value)) 396 value `(let ((indices ',indices)) ,value))
401 (if get-len 397 (if get-len
402 `(length ,value) 398 `(length ,value)
@@ -419,18 +415,17 @@ Possible options are:
419 (if (not end) 415 (if (not end)
420 (throw 'eshell-incomplete ?\{) 416 (throw 'eshell-incomplete ?\{)
421 (prog1 417 (prog1
422 (list 'eshell-convert 418 `(eshell-convert
423 (list 'eshell-command-to-value 419 (eshell-command-to-value
424 (list 'eshell-as-subcommand 420 (eshell-as-subcommand
425 (eshell-parse-command 421 ,(eshell-parse-command (cons (1+ (point)) end)))))
426 (cons (1+ (point)) end)))))
427 (goto-char (1+ end)))))) 422 (goto-char (1+ end))))))
428 ((memq (char-after) '(?\' ?\")) 423 ((memq (char-after) '(?\' ?\"))
429 (let ((name (if (eq (char-after) ?\') 424 (let ((name (if (eq (char-after) ?\')
430 (eshell-parse-literal-quote) 425 (eshell-parse-literal-quote)
431 (eshell-parse-double-quote)))) 426 (eshell-parse-double-quote))))
432 (if name 427 (if name
433 (list 'eshell-get-variable (eval name) 'indices)))) 428 `(eshell-get-variable ,(eval name) indices))))
434 ((eq (char-after) ?\<) 429 ((eq (char-after) ?\<)
435 (let ((end (eshell-find-delimiter ?\< ?\>))) 430 (let ((end (eshell-find-delimiter ?\< ?\>)))
436 (if (not end) 431 (if (not end)
@@ -439,37 +434,30 @@ Possible options are:
439 (cmd (concat (buffer-substring (1+ (point)) end) 434 (cmd (concat (buffer-substring (1+ (point)) end)
440 " > " temp))) 435 " > " temp)))
441 (prog1 436 (prog1
442 (list 437 `(let ((eshell-current-handles
443 'let (list (list 'eshell-current-handles 438 (eshell-create-handles ,temp 'overwrite)))
444 (list 'eshell-create-handles temp 439 (progn
445 (list 'quote 'overwrite)))) 440 (eshell-as-subcommand ,(eshell-parse-command cmd))
446 (list 441 (ignore
447 'progn 442 (nconc eshell-this-command-hook
448 (list 'eshell-as-subcommand 443 (list (function (lambda ()
449 (eshell-parse-command cmd)) 444 (delete-file ,temp))))))
450 (list 'ignore 445 (quote ,temp)))
451 (list 'nconc 'eshell-this-command-hook
452 (list 'list
453 (list 'function
454 (list 'lambda nil
455 (list 'delete-file temp))))))
456 (list 'quote temp)))
457 (goto-char (1+ end))))))) 446 (goto-char (1+ end)))))))
458 ((eq (char-after) ?\() 447 ((eq (char-after) ?\()
459 (condition-case nil 448 (condition-case nil
460 (list 'eshell-command-to-value 449 `(eshell-command-to-value
461 (list 'eshell-lisp-command 450 (eshell-lisp-command
462 (list 'quote (read (current-buffer))))) 451 ',(read (current-buffer))))
463 (end-of-file 452 (end-of-file
464 (throw 'eshell-incomplete ?\()))) 453 (throw 'eshell-incomplete ?\())))
465 ((assoc (char-to-string (char-after)) 454 ((assoc (char-to-string (char-after))
466 eshell-variable-aliases-list) 455 eshell-variable-aliases-list)
467 (forward-char) 456 (forward-char)
468 (list 'eshell-get-variable 457 `(eshell-get-variable ,(char-to-string (char-before)) indices))
469 (char-to-string (char-before)) 'indices))
470 ((looking-at eshell-variable-name-regexp) 458 ((looking-at eshell-variable-name-regexp)
471 (prog1 459 (prog1
472 (list 'eshell-get-variable (match-string 0) 'indices) 460 `(eshell-get-variable ,(match-string 0) indices)
473 (goto-char (match-end 0)))) 461 (goto-char (match-end 0))))
474 (t 462 (t
475 (error "Invalid variable reference")))) 463 (error "Invalid variable reference"))))