aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/eshell
diff options
context:
space:
mode:
authorJohn Wiegley2000-10-29 05:18:48 +0000
committerJohn Wiegley2000-10-29 05:18:48 +0000
commitdace60cfea488a9cc8a775109c56b66907aa6abb (patch)
tree364b9c0114540a5f51a42e1e28a37b98714edaee /lisp/eshell
parent657f9cb8b7f7c3a9687f3998319ce63346ef13a4 (diff)
downloademacs-dace60cfea488a9cc8a775109c56b66907aa6abb.tar.gz
emacs-dace60cfea488a9cc8a775109c56b66907aa6abb.zip
See ChangeLog
Diffstat (limited to 'lisp/eshell')
-rw-r--r--lisp/eshell/em-alias.el7
-rw-r--r--lisp/eshell/em-dirs.el6
-rw-r--r--lisp/eshell/em-glob.el5
-rw-r--r--lisp/eshell/em-ls.el74
-rw-r--r--lisp/eshell/em-script.el3
-rw-r--r--lisp/eshell/em-smart.el35
-rw-r--r--lisp/eshell/em-unix.el129
-rw-r--r--lisp/eshell/esh-cmd.el120
-rw-r--r--lisp/eshell/esh-groups.el1
-rw-r--r--lisp/eshell/esh-maint.el68
-rw-r--r--lisp/eshell/esh-mode.el11
-rw-r--r--lisp/eshell/esh-module.el6
-rw-r--r--lisp/eshell/esh-test.el8
-rw-r--r--lisp/eshell/esh-util.el14
14 files changed, 279 insertions, 208 deletions
diff --git a/lisp/eshell/em-alias.el b/lisp/eshell/em-alias.el
index 85e4e97e692..a407bf5deb8 100644
--- a/lisp/eshell/em-alias.el
+++ b/lisp/eshell/em-alias.el
@@ -151,7 +151,12 @@ command, which will automatically write them to the file named by
151 (add-hook 'eshell-alternate-command-hook 'eshell-fix-bad-commands t t) 151 (add-hook 'eshell-alternate-command-hook 'eshell-fix-bad-commands t t)
152 (eshell-read-aliases-list) 152 (eshell-read-aliases-list)
153 (make-local-hook 'eshell-named-command-hook) 153 (make-local-hook 'eshell-named-command-hook)
154 (add-hook 'eshell-named-command-hook 'eshell-maybe-replace-by-alias t t)) 154 (add-hook 'eshell-named-command-hook 'eshell-maybe-replace-by-alias t t)
155 (make-local-variable 'eshell-complex-commands)
156 (add-to-list 'eshell-complex-commands 'eshell-command-aliased-p))
157
158(defun eshell-command-aliased-p (name)
159 (member name eshell-command-aliases-list))
155 160
156(defun eshell/alias (&optional alias &rest definition) 161(defun eshell/alias (&optional alias &rest definition)
157 "Define an ALIAS in the user's alias list using DEFINITION." 162 "Define an ALIAS in the user's alias list using DEFINITION."
diff --git a/lisp/eshell/em-dirs.el b/lisp/eshell/em-dirs.el
index 02d1eb3076b..0c147f14be6 100644
--- a/lisp/eshell/em-dirs.el
+++ b/lisp/eshell/em-dirs.el
@@ -297,7 +297,7 @@ Thus, this does not include the current directory.")
297 (file-name-as-directory (cdr user)))) 297 (file-name-as-directory (cdr user))))
298 eshell-user-names))))))) 298 eshell-user-names)))))))
299 299
300(defun eshell/pwd (&rest args) ; ignored 300(defun eshell/pwd (&rest args)
301 "Change output from `pwd` to be cleaner." 301 "Change output from `pwd` to be cleaner."
302 (let* ((path default-directory) 302 (let* ((path default-directory)
303 (len (length path))) 303 (len (length path)))
@@ -307,8 +307,8 @@ Thus, this does not include the current directory.")
307 (string-match "\\`[A-Za-z]:[\\\\/]\\'" path)))) 307 (string-match "\\`[A-Za-z]:[\\\\/]\\'" path))))
308 (setq path (substring path 0 (1- (length path))))) 308 (setq path (substring path 0 (1- (length path)))))
309 (if eshell-pwd-convert-function 309 (if eshell-pwd-convert-function
310 (setq path (funcall eshell-pwd-convert-function path))) 310 (funcall eshell-pwd-convert-function path)
311 path)) 311 path)))
312 312
313(defun eshell-expand-multiple-dots (path) 313(defun eshell-expand-multiple-dots (path)
314 "Convert '...' to '../..', '....' to '../../..', etc.. 314 "Convert '...' to '../..', '....' to '../../..', etc..
diff --git a/lisp/eshell/em-glob.el b/lisp/eshell/em-glob.el
index b281cee4fd7..f4f9ebbe5b6 100644
--- a/lisp/eshell/em-glob.el
+++ b/lisp/eshell/em-glob.el
@@ -81,8 +81,9 @@ by zsh for filename generation."
81 :type 'boolean 81 :type 'boolean
82 :group 'eshell-glob) 82 :group 'eshell-glob)
83 83
84(defcustom eshell-glob-show-progress t 84(defcustom eshell-glob-show-progress nil
85 "*If non-nil, display progress messages during a recursive glob." 85 "*If non-nil, display progress messages during a recursive glob.
86This option slows down recursive glob processing by quite a bit."
86 :type 'boolean 87 :type 'boolean
87 :group 'eshell-glob) 88 :group 'eshell-glob)
88 89
diff --git a/lisp/eshell/em-ls.el b/lisp/eshell/em-ls.el
index 2afef625f55..534ea932c3c 100644
--- a/lisp/eshell/em-ls.el
+++ b/lisp/eshell/em-ls.el
@@ -57,6 +57,12 @@ properties to colorize its output based on the setting of
57 :type 'hook 57 :type 'hook
58 :group 'eshell-ls) 58 :group 'eshell-ls)
59 59
60(defcustom eshell-ls-initial-args nil
61 "*If non-nil, this list of args is included before any call to `ls'.
62This is useful for enabling human-readable format (-h), for example."
63 :type '(repeat :tag "Arguments" string)
64 :group 'eshell-ls)
65
60(defcustom eshell-ls-use-in-dired nil 66(defcustom eshell-ls-use-in-dired nil
61 "*If non-nil, use `eshell-ls' to read directories in dired." 67 "*If non-nil, use `eshell-ls' to read directories in dired."
62 :set (lambda (symbol value) 68 :set (lambda (symbol value)
@@ -77,11 +83,18 @@ properties to colorize its output based on the setting of
77 :type 'integer 83 :type 'integer
78 :group 'eshell-ls) 84 :group 'eshell-ls)
79 85
80(defcustom eshell-ls-exclude-regexp "\\`\\." 86(defcustom eshell-ls-exclude-regexp nil
81 "*Unless -a is specified, files matching this regexp will not be shown." 87 "*Unless -a is specified, files matching this regexp will not be shown."
82 :type 'regexp 88 :type 'regexp
83 :group 'eshell-ls) 89 :group 'eshell-ls)
84 90
91(defcustom eshell-ls-exclude-hidden t
92 "*Unless -a is specified, files beginning with . will not be shown.
93Using this boolean, instead of `eshell-ls-exclude-regexp', is both
94faster and conserves more memory."
95 :type 'boolean
96 :group 'eshell-ls)
97
85(defcustom eshell-ls-use-colors t 98(defcustom eshell-ls-use-colors t
86 "*If non-nil, use colors in file listings." 99 "*If non-nil, use colors in file listings."
87 :type 'boolean 100 :type 'boolean
@@ -196,13 +209,13 @@ This is really just for efficiency, to avoid having to stat the file
196yet again." 209yet again."
197 `(if (numberp (nth 2 ,attrs)) 210 `(if (numberp (nth 2 ,attrs))
198 (if (= (user-uid) (nth 2 ,attrs)) 211 (if (= (user-uid) (nth 2 ,attrs))
199 (not (eq (aref (nth 8 ,attrs) ,index) ?-)) 212 (not (eq (aref (nth 8 ,attrs) ,index) ?-))
200 (,(eval func) ,file)) 213 (,(eval func) ,file))
201 (not (eq (aref (nth 8 ,attrs) 214 (not (eq (aref (nth 8 ,attrs)
202 (+ ,index (if (member (nth 2 ,attrs) 215 (+ ,index (if (member (nth 2 ,attrs)
203 (eshell-current-ange-uids)) 216 (eshell-current-ange-uids))
204 0 6))) 217 0 6)))
205 ?-)))) 218 ?-))))
206 219
207(defcustom eshell-ls-highlight-alist nil 220(defcustom eshell-ls-highlight-alist nil
208 "*This alist correlates test functions to color. 221 "*This alist correlates test functions to color.
@@ -248,7 +261,8 @@ instead."
248 (symbol-value 'font-lock-buffers))))) 261 (symbol-value 'font-lock-buffers)))))
249 (let ((insert-func 'insert) 262 (let ((insert-func 'insert)
250 (error-func 'insert) 263 (error-func 'insert)
251 (flush-func 'ignore)) 264 (flush-func 'ignore)
265 eshell-ls-initial-args)
252 (eshell-do-ls (append switches (list file)))))))) 266 (eshell-do-ls (append switches (list file))))))))
253 267
254(defsubst eshell/ls (&rest args) 268(defsubst eshell/ls (&rest args)
@@ -281,7 +295,9 @@ instead."
281 (funcall flush-func -1) 295 (funcall flush-func -1)
282 ;; process the command arguments, and begin listing files 296 ;; process the command arguments, and begin listing files
283 (eshell-eval-using-options 297 (eshell-eval-using-options
284 "ls" args 298 "ls" (if eshell-ls-initial-args
299 (list eshell-ls-initial-args args)
300 args)
285 `((?a "all" nil show-all 301 `((?a "all" nil show-all
286 "show all files in directory") 302 "show all files in directory")
287 (?c nil by-ctime sort-method 303 (?c nil by-ctime sort-method
@@ -343,11 +359,11 @@ Sort entries alphabetically across.")
343 (error (concat "-I option requires that `eshell-glob'" 359 (error (concat "-I option requires that `eshell-glob'"
344 " be a member of `eshell-modules-list'"))) 360 " be a member of `eshell-modules-list'")))
345 (set-text-properties 0 (length ignore-pattern) nil ignore-pattern) 361 (set-text-properties 0 (length ignore-pattern) nil ignore-pattern)
346 (if eshell-ls-exclude-regexp 362 (setq eshell-ls-exclude-regexp
347 (setq eshell-ls-exclude-regexp 363 (if eshell-ls-exclude-regexp
348 (concat "\\(" eshell-ls-exclude-regexp "\\|" 364 (concat "\\(" eshell-ls-exclude-regexp "\\|"
349 (eshell-glob-regexp ignore-pattern) "\\)")) 365 (eshell-glob-regexp ignore-pattern) "\\)")
350 (setq eshell-ls-exclude-regexp (eshell-glob-regexp ignore-pattern)))) 366 (eshell-glob-regexp ignore-pattern))))
351 ;; list the files! 367 ;; list the files!
352 (eshell-ls-entries 368 (eshell-ls-entries
353 (mapcar (function 369 (mapcar (function
@@ -356,7 +372,8 @@ Sort entries alphabetically across.")
356 (file-name-absolute-p arg)) 372 (file-name-absolute-p arg))
357 (expand-file-name arg) 373 (expand-file-name arg)
358 arg) 374 arg)
359 (eshell-file-attributes arg)))) args) 375 (eshell-file-attributes arg))))
376 args)
360 t (expand-file-name default-directory))) 377 t (expand-file-name default-directory)))
361 (funcall flush-func))) 378 (funcall flush-func)))
362 379
@@ -491,12 +508,13 @@ relative to that directory."
491 (file-relative-name dir root-dir) 508 (file-relative-name dir root-dir)
492 (expand-file-name dir))) 509 (expand-file-name dir)))
493 (cdr dirinfo))) ":\n")) 510 (cdr dirinfo))) ":\n"))
494 (let ((entries 511 (let ((entries (eshell-directory-files-and-attributes
495 (eshell-directory-files-and-attributes dir nil nil t))) 512 dir nil (and (not show-all)
496 (unless show-all 513 eshell-ls-exclude-hidden
497 (while (and entries 514 "\\`[^.]") t)))
498 (string-match eshell-ls-exclude-regexp 515 (when (and (not show-all) eshell-ls-exclude-regexp)
499 (caar entries))) 516 (while (and entries (string-match eshell-ls-exclude-regexp
517 (caar entries)))
500 (setq entries (cdr entries))) 518 (setq entries (cdr entries)))
501 (let ((e entries)) 519 (let ((e entries))
502 (while (cdr e) 520 (while (cdr e)
@@ -552,17 +570,13 @@ In Eshell's implementation of ls, ENTRIES is always reversed."
552 (let ((result 570 (let ((result
553 (cond 571 (cond
554 ((eq sort-method 'by-atime) 572 ((eq sort-method 'by-atime)
555 (eshell-ls-compare-entries 573 (eshell-ls-compare-entries l r 4 'eshell-time-less-p))
556 l r 4 'eshell-time-less-p))
557 ((eq sort-method 'by-mtime) 574 ((eq sort-method 'by-mtime)
558 (eshell-ls-compare-entries 575 (eshell-ls-compare-entries l r 5 'eshell-time-less-p))
559 l r 5 'eshell-time-less-p))
560 ((eq sort-method 'by-ctime) 576 ((eq sort-method 'by-ctime)
561 (eshell-ls-compare-entries 577 (eshell-ls-compare-entries l r 6 'eshell-time-less-p))
562 l r 6 'eshell-time-less-p))
563 ((eq sort-method 'by-size) 578 ((eq sort-method 'by-size)
564 (eshell-ls-compare-entries 579 (eshell-ls-compare-entries l r 7 '<))
565 l r 7 '<))
566 ((eq sort-method 'by-extension) 580 ((eq sort-method 'by-extension)
567 (let ((lx (file-name-extension 581 (let ((lx (file-name-extension
568 (directory-file-name (car l)))) 582 (directory-file-name (car l))))
@@ -699,8 +713,8 @@ need to be printed."
699 (if (and need-return (not dir-literal)) 713 (if (and need-return (not dir-literal))
700 (funcall insert-func "\n")) 714 (funcall insert-func "\n"))
701 (eshell-ls-dir dir show-names 715 (eshell-ls-dir dir show-names
702 (unless (file-name-absolute-p (car dir)) 716 (unless (file-name-absolute-p (car dir)) root-dir)
703 root-dir) size-width) 717 size-width)
704 (setq need-return t)))) 718 (setq need-return t))))
705 719
706(defun eshell-ls-find-column-widths (files) 720(defun eshell-ls-find-column-widths (files)
diff --git a/lisp/eshell/em-script.el b/lisp/eshell/em-script.el
index d6a8ea54e2f..8967426cadf 100644
--- a/lisp/eshell/em-script.el
+++ b/lisp/eshell/em-script.el
@@ -63,6 +63,9 @@ This includes when running `eshell-command'."
63 (string= (file-name-nondirectory file) 63 (string= (file-name-nondirectory file)
64 "eshell")) . eshell/source) 64 "eshell")) . eshell/source)
65 eshell-interpreter-alist)) 65 eshell-interpreter-alist))
66 (make-local-variable 'eshell-complex-commands)
67 (setq eshell-complex-commands
68 (append '("source" ".") eshell-complex-commands))
66 ;; these two variables are changed through usage, but we don't want 69 ;; these two variables are changed through usage, but we don't want
67 ;; to ruin it for other modules 70 ;; to ruin it for other modules
68 (let (eshell-inside-quote-regexp 71 (let (eshell-inside-quote-regexp
diff --git a/lisp/eshell/em-smart.el b/lisp/eshell/em-smart.el
index cc02f2fedc3..9bef8b10d20 100644
--- a/lisp/eshell/em-smart.el
+++ b/lisp/eshell/em-smart.el
@@ -77,6 +77,11 @@ it to get a real sense of how it works."
77;; scroll, etc. 77;; scroll, etc.
78;; 78;;
79;; @ Like I said, it's not really comprehensible until you try it! ;) 79;; @ Like I said, it's not really comprehensible until you try it! ;)
80;;
81;; One disadvantage of this module is that it increases Eshell's
82;; memory consumption by a factor of two or more. With small commands
83;; (such as pwd), where the screen is mostly full, consumption can
84;; increase by orders of magnitude.
80 85
81;;; User Variables: 86;;; User Variables:
82 87
@@ -154,6 +159,7 @@ The options are `begin', `after' or `end'."
154 159
155(defvar eshell-smart-displayed nil) 160(defvar eshell-smart-displayed nil)
156(defvar eshell-smart-command-done nil) 161(defvar eshell-smart-command-done nil)
162(defvar eshell-currently-handling-window nil)
157 163
158;;; Functions: 164;;; Functions:
159 165
@@ -175,19 +181,17 @@ The options are `begin', `after' or `end'."
175 181
176 (make-local-hook 'pre-command-hook) 182 (make-local-hook 'pre-command-hook)
177 (make-local-hook 'after-change-functions) 183 (make-local-hook 'after-change-functions)
178 (add-hook 'after-change-functions 184 (add-hook 'after-change-functions 'eshell-disable-after-change nil t)
179 'eshell-disable-after-change nil t)
180 185
181 (make-local-hook 'eshell-input-filter-functions) 186 (make-local-hook 'eshell-input-filter-functions)
182 (add-hook 'eshell-input-filter-functions 187 (add-hook 'eshell-input-filter-functions 'eshell-smart-display-setup nil t)
183 'eshell-smart-display-setup nil t)
184 188
185 (make-local-variable 'eshell-smart-command-done) 189 (make-local-variable 'eshell-smart-command-done)
186 (make-local-hook 'eshell-post-command-hook) 190 (make-local-hook 'eshell-post-command-hook)
187 (add-hook 'eshell-post-command-hook 191 (add-hook 'eshell-post-command-hook
188 (function 192 (function
189 (lambda () 193 (lambda ()
190 (setq eshell-smart-command-done t))) t t) 194 (setq eshell-smart-command-done t))) t t)
191 195
192 (unless (eq eshell-review-quick-commands t) 196 (unless (eq eshell-review-quick-commands t)
193 (add-hook 'eshell-post-command-hook 197 (add-hook 'eshell-post-command-hook
@@ -198,10 +202,9 @@ The options are `begin', `after' or `end'."
198 (unless eshell-currently-handling-window 202 (unless eshell-currently-handling-window
199 (let ((inhibit-point-motion-hooks t) 203 (let ((inhibit-point-motion-hooks t)
200 (eshell-currently-handling-window t)) 204 (eshell-currently-handling-window t))
201 (save-current-buffer 205 (save-selected-window
202 (save-selected-window 206 (select-window wind)
203 (select-window wind) 207 (eshell-smart-redisplay)))))
204 (eshell-smart-redisplay))))))
205 208
206(defun eshell-refresh-windows (&optional frame) 209(defun eshell-refresh-windows (&optional frame)
207 "Refresh all visible Eshell buffers." 210 "Refresh all visible Eshell buffers."
@@ -210,10 +213,10 @@ The options are `begin', `after' or `end'."
210 (function 213 (function
211 (lambda (wind) 214 (lambda (wind)
212 (with-current-buffer (window-buffer wind) 215 (with-current-buffer (window-buffer wind)
213 (when eshell-mode 216 (if eshell-mode
214 (let (window-scroll-functions) 217 (let (window-scroll-functions)
215 (eshell-smart-scroll-window wind (window-start)) 218 (eshell-smart-scroll-window wind (window-start))
216 (setq affected t)))))) 219 (setq affected t))))))
217 0 frame) 220 0 frame)
218 (if affected 221 (if affected
219 (let (window-scroll-functions) 222 (let (window-scroll-functions)
diff --git a/lisp/eshell/em-unix.el b/lisp/eshell/em-unix.el
index 7f0414ef056..c9b3d418b83 100644
--- a/lisp/eshell/em-unix.el
+++ b/lisp/eshell/em-unix.el
@@ -124,6 +124,11 @@ Otherwise, `rmdir' is required."
124 :type 'boolean 124 :type 'boolean
125 :group 'eshell-unix) 125 :group 'eshell-unix)
126 126
127(defcustom eshell-default-target-is-dot nil
128 "*If non-nil, the default destination for cp, mv or ln is `.'."
129 :type 'boolean
130 :group 'eshell-unix)
131
127(defcustom eshell-du-prefer-over-ange nil 132(defcustom eshell-du-prefer-over-ange nil
128 "*Use Eshell's du in ange-ftp remote directories. 133 "*Use Eshell's du in ange-ftp remote directories.
129Otherwise, Emacs will attempt to use rsh to invoke du on the remote machine." 134Otherwise, Emacs will attempt to use rsh to invoke du on the remote machine."
@@ -140,7 +145,12 @@ Otherwise, Emacs will attempt to use rsh to invoke du on the remote machine."
140 (when (eshell-using-module 'eshell-cmpl) 145 (when (eshell-using-module 'eshell-cmpl)
141 (make-local-hook 'pcomplete-try-first-hook) 146 (make-local-hook 'pcomplete-try-first-hook)
142 (add-hook 'pcomplete-try-first-hook 147 (add-hook 'pcomplete-try-first-hook
143 'eshell-complete-host-reference nil t))) 148 'eshell-complete-host-reference nil t))
149 (make-local-variable 'eshell-complex-commands)
150 (setq eshell-complex-commands
151 (append '("grep" "egrep" "fgrep" "agrep" "glimpse" "locate"
152 "cat" "time" "cp" "mv" "make" "du" "diff")
153 eshell-complex-commands)))
144 154
145(defalias 'eshell/date 'current-time-string) 155(defalias 'eshell/date 'current-time-string)
146(defalias 'eshell/basename 'file-name-nondirectory) 156(defalias 'eshell/basename 'file-name-nondirectory)
@@ -157,6 +167,7 @@ Otherwise, Emacs will attempt to use rsh to invoke du on the remote machine."
157 (funcall 'man (apply 'eshell-flatten-and-stringify args))) 167 (funcall 'man (apply 'eshell-flatten-and-stringify args)))
158 168
159(defun eshell-remove-entries (path files &optional top-level) 169(defun eshell-remove-entries (path files &optional top-level)
170 "From PATH, remove all of the given FILES, perhaps interactively."
160 (while files 171 (while files
161 (if (string-match "\\`\\.\\.?\\'" 172 (if (string-match "\\`\\.\\.?\\'"
162 (file-name-nondirectory (car files))) 173 (file-name-nondirectory (car files)))
@@ -302,8 +313,6 @@ Remove the DIRECTORY(ies), if they are empty.")
302 313
303(defun eshell-shuffle-files (command action files target func deep &rest args) 314(defun eshell-shuffle-files (command action files target func deep &rest args)
304 "Shuffle around some filesystem entries, using FUNC to do the work." 315 "Shuffle around some filesystem entries, using FUNC to do the work."
305 (if (null target)
306 (error "%s: missing destination file" command))
307 (let ((attr-target (eshell-file-attributes target)) 316 (let ((attr-target (eshell-file-attributes target))
308 (is-dir (or (file-directory-p target) 317 (is-dir (or (file-directory-p target)
309 (and preview (not eshell-warn-dot-directories)))) 318 (and preview (not eshell-warn-dot-directories))))
@@ -417,30 +426,35 @@ Remove the DIRECTORY(ies), if they are empty.")
417 (format "tar %s %s" tar-args archive) args)))) 426 (format "tar %s %s" tar-args archive) args))))
418 427
419;; this is to avoid duplicating code... 428;; this is to avoid duplicating code...
420(defmacro eshell-mvcp-template 429(defmacro eshell-mvcpln-template (command action func query-var
421 (command action func query-var force-var &optional preserve) 430 force-var &optional preserve)
422 `(if (and (string-match eshell-tar-regexp (car (last args))) 431 `(let ((len (length args)))
423 (or (> (length args) 2) 432 (if (or (= len 0)
424 (and (file-directory-p (car args)) 433 (and (= len 1) (null eshell-default-target-is-dot)))
425 (or (not no-dereference) 434 (error "%s: missing destination file or directory" ,command))
426 (not (file-symlink-p (car args))))))) 435 (if (= len 1)
427 (eshell-shorthand-tar-command ,command args) 436 (nconc args '(".")))
428 (let (target ange-cache) 437 (setq args (eshell-stringify-list (eshell-flatten-list args)))
429 (if (> (length args) 1) 438 (if (and ,(not (equal command "ln"))
430 (progn 439 (string-match eshell-tar-regexp (car (last args)))
431 (setq target (car (last args))) 440 (or (> (length args) 2)
432 (setcdr (last args 2) nil)) 441 (and (file-directory-p (car args))
433 (setq args nil)) 442 (or (not no-dereference)
434 (eshell-shuffle-files 443 (not (file-symlink-p (car args)))))))
435 ,command ,action args target ,func nil 444 (eshell-shorthand-tar-command ,command args)
436 ,@(append 445 (let ((target (car (last args)))
437 `((if (and (or interactive 446 ange-cache)
438 ,query-var) 447 (setcdr (last args 2) nil)
439 (not force)) 448 (eshell-shuffle-files
440 1 (or force ,force-var))) 449 ,command ,action args target ,func nil
441 (if preserve 450 ,@(append
442 (list preserve))))) 451 `((if (and (or interactive
443 nil)) 452 ,query-var)
453 (not force))
454 1 (or force ,force-var)))
455 (if preserve
456 (list preserve)))))
457 nil)))
444 458
445(defun eshell/mv (&rest args) 459(defun eshell/mv (&rest args)
446 "Implementation of mv in Lisp." 460 "Implementation of mv in Lisp."
@@ -455,6 +469,7 @@ Remove the DIRECTORY(ies), if they are empty.")
455 (?v "verbose" nil verbose 469 (?v "verbose" nil verbose
456 "explain what is being done") 470 "explain what is being done")
457 (nil "help" nil nil "show this usage screen") 471 (nil "help" nil nil "show this usage screen")
472 :preserve-args
458 :external "mv" 473 :external "mv"
459 :show-usage 474 :show-usage
460 :usage "[OPTION]... SOURCE DEST 475 :usage "[OPTION]... SOURCE DEST
@@ -462,9 +477,9 @@ Remove the DIRECTORY(ies), if they are empty.")
462Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY. 477Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.
463\[OPTION] DIRECTORY...") 478\[OPTION] DIRECTORY...")
464 (let ((no-dereference t)) 479 (let ((no-dereference t))
465 (eshell-mvcp-template "mv" "moving" 'rename-file 480 (eshell-mvcpln-template "mv" "moving" 'rename-file
466 eshell-mv-interactive-query 481 eshell-mv-interactive-query
467 eshell-mv-overwrite-files)))) 482 eshell-mv-overwrite-files))))
468 483
469(defun eshell/cp (&rest args) 484(defun eshell/cp (&rest args)
470 "Implementation of cp in Lisp." 485 "Implementation of cp in Lisp."
@@ -487,6 +502,7 @@ Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.
487 (?v "verbose" nil verbose 502 (?v "verbose" nil verbose
488 "explain what is being done") 503 "explain what is being done")
489 (nil "help" nil nil "show this usage screen") 504 (nil "help" nil nil "show this usage screen")
505 :preserve-args
490 :external "cp" 506 :external "cp"
491 :show-usage 507 :show-usage
492 :usage "[OPTION]... SOURCE DEST 508 :usage "[OPTION]... SOURCE DEST
@@ -494,9 +510,9 @@ Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.
494Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.") 510Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.")
495 (if archive 511 (if archive
496 (setq preserve t no-dereference t recursive t)) 512 (setq preserve t no-dereference t recursive t))
497 (eshell-mvcp-template "cp" "copying" 'copy-file 513 (eshell-mvcpln-template "cp" "copying" 'copy-file
498 eshell-cp-interactive-query 514 eshell-cp-interactive-query
499 eshell-cp-overwrite-files preserve))) 515 eshell-cp-overwrite-files preserve)))
500 516
501(defun eshell/ln (&rest args) 517(defun eshell/ln (&rest args)
502 "Implementation of ln in Lisp." 518 "Implementation of ln in Lisp."
@@ -505,11 +521,13 @@ Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.")
505 '((?h "help" nil nil "show this usage screen") 521 '((?h "help" nil nil "show this usage screen")
506 (?s "symbolic" nil symbolic 522 (?s "symbolic" nil symbolic
507 "make symbolic links instead of hard links") 523 "make symbolic links instead of hard links")
508 (?i "interactive" nil interactive "request confirmation if target already exists") 524 (?i "interactive" nil interactive
525 "request confirmation if target already exists")
509 (?f "force" nil force "remove existing destinations, never prompt") 526 (?f "force" nil force "remove existing destinations, never prompt")
510 (?n "preview" nil preview 527 (?n "preview" nil preview
511 "don't change anything on disk") 528 "don't change anything on disk")
512 (?v "verbose" nil verbose "explain what is being done") 529 (?v "verbose" nil verbose "explain what is being done")
530 :preserve-args
513 :external "ln" 531 :external "ln"
514 :show-usage 532 :show-usage
515 :usage "[OPTION]... TARGET [LINK_NAME] 533 :usage "[OPTION]... TARGET [LINK_NAME]
@@ -518,27 +536,19 @@ Create a link to the specified TARGET with optional LINK_NAME. If there is
518more than one TARGET, the last argument must be a directory; create links 536more than one TARGET, the last argument must be a directory; create links
519in DIRECTORY to each TARGET. Create hard links by default, symbolic links 537in DIRECTORY to each TARGET. Create hard links by default, symbolic links
520with '--symbolic'. When creating hard links, each TARGET must exist.") 538with '--symbolic'. When creating hard links, each TARGET must exist.")
521 (let (target no-dereference ange-cache) 539 (let ((no-dereference t))
522 (if (> (length args) 1) 540 (eshell-mvcpln-template "ln" "linking"
523 (progn 541 (if symbolic
524 (setq target (car (last args))) 542 'make-symbolic-link
525 (setcdr (last args 2) nil)) 543 'add-name-to-file)
526 (setq args nil)) 544 eshell-ln-interactive-query
527 (eshell-shuffle-files "ln" "linking" args target 545 eshell-ln-overwrite-files))))
528 (if symbolic
529 'make-symbolic-link
530 'add-name-to-file) nil
531 (if (and (or interactive
532 eshell-ln-interactive-query)
533 (not force))
534 1 (or force eshell-ln-overwrite-files))))
535 nil))
536 546
537(defun eshell/cat (&rest args) 547(defun eshell/cat (&rest args)
538 "Implementation of cat in Lisp. 548 "Implementation of cat in Lisp.
539If in a pipeline, or the file is not a regular file, directory or 549If in a pipeline, or the file is not a regular file, directory or
540symlink, then revert to the system's definition of cat." 550symlink, then revert to the system's definition of cat."
541 (setq args (eshell-flatten-list args)) 551 (setq args (eshell-stringify-list (eshell-flatten-list args)))
542 (if (or eshell-in-pipeline-p 552 (if (or eshell-in-pipeline-p
543 (catch 'special 553 (catch 'special
544 (eshell-for arg args 554 (eshell-for arg args
@@ -593,7 +603,8 @@ Concatenate FILE(s), or standard input, to standard output.")
593 (list 'quote (eshell-copy-environment)))))) 603 (list 'quote (eshell-copy-environment))))))
594 (compile (concat "make " (eshell-flatten-and-stringify args)))) 604 (compile (concat "make " (eshell-flatten-and-stringify args))))
595 (throw 'eshell-replace-command 605 (throw 'eshell-replace-command
596 (eshell-parse-command "*make" (eshell-flatten-list args))))) 606 (eshell-parse-command "*make" (eshell-stringify-list
607 (eshell-flatten-list args))))))
597 608
598(defun eshell-occur-mode-goto-occurrence () 609(defun eshell-occur-mode-goto-occurrence ()
599 "Go to the occurrence the current line describes." 610 "Go to the occurrence the current line describes."
@@ -627,7 +638,8 @@ available..."
627 (default-directory default-dir)) 638 (default-directory default-dir))
628 (erase-buffer) 639 (erase-buffer)
629 (occur-mode) 640 (occur-mode)
630 (let ((files (eshell-flatten-list (cdr args))) 641 (let ((files (eshell-stringify-list
642 (eshell-flatten-list (cdr args))))
631 (inhibit-redisplay t) 643 (inhibit-redisplay t)
632 string) 644 string)
633 (when (car args) 645 (when (car args)
@@ -670,14 +682,16 @@ external command."
670 (not eshell-in-subcommand-p)))) 682 (not eshell-in-subcommand-p))))
671 (throw 'eshell-replace-command 683 (throw 'eshell-replace-command
672 (eshell-parse-command (concat "*" command) 684 (eshell-parse-command (concat "*" command)
673 (eshell-flatten-list args))) 685 (eshell-stringify-list
686 (eshell-flatten-list args))))
674 (let* ((compilation-process-setup-function 687 (let* ((compilation-process-setup-function
675 (list 'lambda nil 688 (list 'lambda nil
676 (list 'setq 'process-environment 689 (list 'setq 'process-environment
677 (list 'quote (eshell-copy-environment))))) 690 (list 'quote (eshell-copy-environment)))))
678 (args (mapconcat 'identity 691 (args (mapconcat 'identity
679 (mapcar 'shell-quote-argument 692 (mapcar 'shell-quote-argument
680 (eshell-flatten-list args)) 693 (eshell-stringify-list
694 (eshell-flatten-list args)))
681 " ")) 695 " "))
682 (cmd (progn 696 (cmd (progn
683 (set-text-properties 0 (length args) 697 (set-text-properties 0 (length args)
@@ -797,7 +811,7 @@ external command."
797(defun eshell/du (&rest args) 811(defun eshell/du (&rest args)
798 "Implementation of \"du\" in Lisp, passing ARGS." 812 "Implementation of \"du\" in Lisp, passing ARGS."
799 (setq args (if args 813 (setq args (if args
800 (eshell-flatten-list args) 814 (eshell-stringify-list (eshell-flatten-list args))
801 '("."))) 815 '(".")))
802 (let ((ext-du (eshell-search-path "du"))) 816 (let ((ext-du (eshell-search-path "du")))
803 (if (and ext-du 817 (if (and ext-du
@@ -909,7 +923,7 @@ Show wall-clock time elapsed during execution of COMMAND.")
909 923
910(defun eshell/diff (&rest args) 924(defun eshell/diff (&rest args)
911 "Alias \"diff\" to call Emacs `diff' function." 925 "Alias \"diff\" to call Emacs `diff' function."
912 (let ((orig-args (eshell-flatten-list args))) 926 (let ((orig-args (eshell-stringify-list (eshell-flatten-list args))))
913 (if (or eshell-plain-diff-behavior 927 (if (or eshell-plain-diff-behavior
914 (not (and (eshell-interactive-output-p) 928 (not (and (eshell-interactive-output-p)
915 (not eshell-in-pipeline-p) 929 (not eshell-in-pipeline-p)
@@ -951,7 +965,8 @@ Show wall-clock time elapsed during execution of COMMAND.")
951 (and (stringp (car args)) 965 (and (stringp (car args))
952 (string-match "^-" (car args)))) 966 (string-match "^-" (car args))))
953 (throw 'eshell-replace-command 967 (throw 'eshell-replace-command
954 (eshell-parse-command "*locate" (eshell-flatten-list args))) 968 (eshell-parse-command "*locate" (eshell-stringify-list
969 (eshell-flatten-list args))))
955 (save-selected-window 970 (save-selected-window
956 (let ((locate-history-list (list (car args)))) 971 (let ((locate-history-list (list (car args))))
957 (locate-with-filter (car args) (cadr args)))))) 972 (locate-with-filter (car args) (cadr args))))))
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index 6d2ede0a72c..7d5a53625f5 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -203,6 +203,21 @@ which may be modified directly. Any return value is ignored."
203 :type 'hook 203 :type 'hook
204 :group 'eshell-cmd) 204 :group 'eshell-cmd)
205 205
206(defcustom eshell-complex-commands nil
207 "*A list of commands names or functions, that determine complexity.
208That is, if a command is defined by a function named eshell/NAME,
209and NAME is part of this list, it is invoked as a complex command.
210Complex commands are always correct, but run much slower. If a
211command works fine without being part of this list, then it doesn't
212need to be.
213
214If an entry is a function, it will be called with the name, and should
215return non-nil if the command is complex."
216 :type '(repeat :tag "Commands"
217 (choice (string :tag "Name")
218 (function :tag "Predicate")))
219 :group 'eshell-cmd)
220
206;;; Code: 221;;; Code:
207 222
208(require 'esh-util) 223(require 'esh-util)
@@ -518,8 +533,8 @@ implemented via rewriting, rather than as a function."
518 (list 'car 533 (list 'car
519 (list 'symbol-value 534 (list 'symbol-value
520 (list 'quote 'for-items))))) 535 (list 'quote 'for-items)))))
521 (list 'eshell-copy-handles 536 (list 'eshell-protect
522 (eshell-invokify-arg body t))) 537 (eshell-invokify-arg body t)))
523 (list 'setcar 'for-items 538 (list 'setcar 'for-items
524 (list 'cadr 539 (list 'cadr
525 (list 'symbol-value 540 (list 'symbol-value
@@ -583,7 +598,7 @@ must be implemented via rewriting, rather than as a function."
583 (eshell-structure-basic-command 598 (eshell-structure-basic-command
584 'while '("while" "until") (car terms) 599 'while '("while" "until") (car terms)
585 (eshell-invokify-arg (cadr terms) nil t) 600 (eshell-invokify-arg (cadr terms) nil t)
586 (list 'eshell-copy-handles 601 (list 'eshell-protect
587 (eshell-invokify-arg (car (last terms)) t))))) 602 (eshell-invokify-arg (car (last terms)) t)))))
588 603
589(defun eshell-rewrite-if-command (terms) 604(defun eshell-rewrite-if-command (terms)
@@ -596,13 +611,15 @@ must be implemented via rewriting, rather than as a function."
596 (eshell-structure-basic-command 611 (eshell-structure-basic-command
597 'if '("if" "unless") (car terms) 612 'if '("if" "unless") (car terms)
598 (eshell-invokify-arg (cadr terms) nil t) 613 (eshell-invokify-arg (cadr terms) nil t)
599 (eshell-invokify-arg 614 (list 'eshell-protect
600 (if (= (length terms) 5) 615 (eshell-invokify-arg
601 (car (last terms 3)) 616 (if (= (length terms) 5)
602 (car (last terms))) t) 617 (car (last terms 3))
603 (eshell-invokify-arg 618 (car (last terms))) t))
604 (if (= (length terms) 5) 619 (if (= (length terms) 5)
605 (car (last terms))) t)))) 620 (list 'eshell-protect
621 (eshell-invokify-arg
622 (car (last terms)))) t))))
606 623
607(defun eshell-exit-success-p () 624(defun eshell-exit-success-p ()
608 "Return non-nil if the last command was \"successful\". 625 "Return non-nil if the last command was \"successful\".
@@ -651,8 +668,8 @@ For an external command, it means an exit code of 0."
651 (assert (car sep-terms)) 668 (assert (car sep-terms))
652 (setq final (eshell-structure-basic-command 669 (setq final (eshell-structure-basic-command
653 'if (string= (car sep-terms) "&&") "if" 670 'if (string= (car sep-terms) "&&") "if"
654 (list 'eshell-commands (car results)) 671 (list 'eshell-protect (car results))
655 final 672 (list 'eshell-protect final)
656 nil t) 673 nil t)
657 results (cdr results) 674 results (cdr results)
658 sep-terms (cdr sep-terms))) 675 sep-terms (cdr sep-terms)))
@@ -690,8 +707,8 @@ For an external command, it means an exit code of 0."
690 (list 'eshell-lisp-command (list 'quote obj))) 707 (list 'eshell-lisp-command (list 'quote obj)))
691 (ignore (goto-char here)))))) 708 (ignore (goto-char here))))))
692 709
693(defun eshell-separate-commands 710(defun eshell-separate-commands (terms separator &optional
694 (terms separator &optional reversed last-terms-sym) 711 reversed last-terms-sym)
695 "Separate TERMS using SEPARATOR. 712 "Separate TERMS using SEPARATOR.
696If REVERSED is non-nil, the list of separated term groups will be 713If REVERSED is non-nil, the list of separated term groups will be
697returned in reverse order. If LAST-TERMS-SYM is a symbol, it's value 714returned in reverse order. If LAST-TERMS-SYM is a symbol, it's value
@@ -772,21 +789,6 @@ this grossness will be made to disappear by using `call/cc'..."
772 (eshell-errorn (error-message-string err)) 789 (eshell-errorn (error-message-string err))
773 (eshell-close-handles 1))))) 790 (eshell-close-handles 1)))))
774 791
775;; (defun eshell-copy-or-protect-handles ()
776;; (if (eshell-processp (car (aref eshell-current-handles
777;; eshell-output-handle)))
778;; (eshell-protect-handles eshell-current-handles)
779;; (eshell-create-handles
780;; (car (aref eshell-current-handles
781;; eshell-output-handle)) nil
782;; (car (aref eshell-current-handles
783;; eshell-error-handle)) nil)))
784
785;; (defmacro eshell-copy-handles (object)
786;; "Duplicate current I/O handles, so OBJECT works with its own copy."
787;; `(let ((eshell-current-handles (eshell-copy-or-protect-handles)))
788;; ,object))
789
790(defmacro eshell-copy-handles (object) 792(defmacro eshell-copy-handles (object)
791 "Duplicate current I/O handles, so OBJECT works with its own copy." 793 "Duplicate current I/O handles, so OBJECT works with its own copy."
792 `(let ((eshell-current-handles 794 `(let ((eshell-current-handles
@@ -965,6 +967,22 @@ at the moment are:
965 (if subform 967 (if subform
966 (concat "\n\n" (eshell-stringify subform)) "")))))) 968 (concat "\n\n" (eshell-stringify subform)) ""))))))
967 969
970(defun eshell-invoke-directly (command input)
971 (let ((base (cadr (nth 2 (nth 2 (cadr command))))) name)
972 (if (and (eq (car base) 'eshell-trap-errors)
973 (eq (car (cadr base)) 'eshell-named-command))
974 (setq name (cadr (cadr base))))
975 (and name (stringp name)
976 (not (member name eshell-complex-commands))
977 (catch 'simple
978 (progn
979 (eshell-for pred eshell-complex-commands
980 (if (and (functionp pred)
981 (funcall pred name))
982 (throw 'simple nil)))
983 t))
984 (fboundp (intern-soft (concat "eshell/" name))))))
985
968(defun eshell-eval-command (command &optional input) 986(defun eshell-eval-command (command &optional input)
969 "Evaluate the given COMMAND iteratively." 987 "Evaluate the given COMMAND iteratively."
970 (if eshell-current-command 988 (if eshell-current-command
@@ -1163,29 +1181,29 @@ be finished later after the completion of an asynchronous subprocess."
1163 ((eq (car form) 'prog1) 1181 ((eq (car form) 'prog1)
1164 (cadr form)) 1182 (cadr form))
1165 (t 1183 (t
1184 ;; If a command desire to replace its execution form with
1185 ;; another command form, all it needs to do is throw the new
1186 ;; form using the exception tag `eshell-replace-command'.
1187 ;; For example, let's say that the form currently being
1188 ;; eval'd is:
1189 ;;
1190 ;; (eshell-named-command "hello")
1191 ;;
1192 ;; Now, let's assume the 'hello' command is an Eshell alias,
1193 ;; the definition of which yields the command:
1194 ;;
1195 ;; (eshell-named-command "echo" (list "Hello" "world"))
1196 ;;
1197 ;; What the alias code would like to do is simply substitute
1198 ;; the alias form for the original form. To accomplish
1199 ;; this, all it needs to do is to throw the substitution
1200 ;; form with the `eshell-replace-command' tag, and the form
1201 ;; will be replaced within the current command, and
1202 ;; execution will then resume (iteratively) as before.
1203 ;; Thus, aliases can even contain references to asynchronous
1204 ;; sub-commands, and things will still work out as they
1205 ;; should.
1166 (let (result new-form) 1206 (let (result new-form)
1167 ;; If a command desire to replace its execution form with
1168 ;; another command form, all it needs to do is throw the
1169 ;; new form using the exception tag
1170 ;; `eshell-replace-command'. For example, let's say that
1171 ;; the form currently being eval'd is:
1172 ;;
1173 ;; (eshell-named-command \"hello\")
1174 ;;
1175 ;; Now, let's assume the 'hello' command is an Eshell
1176 ;; alias, the definition of which yields the command:
1177 ;;
1178 ;; (eshell-named-command \"echo\" (list \"Hello\" \"world\"))
1179 ;;
1180 ;; What the alias code would like to do is simply
1181 ;; substitute the alias form for the original form. To
1182 ;; accomplish this, all it needs to do is to throw the
1183 ;; substitution form with the `eshell-replace-command'
1184 ;; tag, and the form will be replaced within the current
1185 ;; command, and execution will then resume (iteratively)
1186 ;; as before. Thus, aliases can even contain references
1187 ;; to asynchronous sub-commands, and things will still
1188 ;; work out as they should.
1189 (if (setq new-form 1207 (if (setq new-form
1190 (catch 'eshell-replace-command 1208 (catch 'eshell-replace-command
1191 (ignore 1209 (ignore
diff --git a/lisp/eshell/esh-groups.el b/lisp/eshell/esh-groups.el
index 218bd2a2e52..d82cdff4ffd 100644
--- a/lisp/eshell/esh-groups.el
+++ b/lisp/eshell/esh-groups.el
@@ -132,4 +132,3 @@ functions, or as aliases which make some of Emacs' behavior more
132naturally accessible within Emacs." 132naturally accessible within Emacs."
133 :tag "Extra alias functions" 133 :tag "Extra alias functions"
134 :group 'eshell-module) 134 :group 'eshell-module)
135
diff --git a/lisp/eshell/esh-maint.el b/lisp/eshell/esh-maint.el
index 13b3597b4ce..89e50401c67 100644
--- a/lisp/eshell/esh-maint.el
+++ b/lisp/eshell/esh-maint.el
@@ -48,7 +48,7 @@
48;; (interactive) 48;; (interactive)
49;; (require 'autoload) 49;; (require 'autoload)
50;; (setq generated-autoload-file 50;; (setq generated-autoload-file
51;; (expand-file-name (car command-line-args-left))) 51;; (expand-file-name (car command-line-args-left)))
52;; (setq command-line-args-left (cdr command-line-args-left)) 52;; (setq command-line-args-left (cdr command-line-args-left))
53;; (batch-update-autoloads)) 53;; (batch-update-autoloads))
54 54
@@ -65,23 +65,23 @@
65;; Core Functionality\n") 65;; Core Functionality\n")
66;; (eshell-for module 66;; (eshell-for module
67;; (sort (eshell-subgroups 'eshell) 67;; (sort (eshell-subgroups 'eshell)
68;; (function 68;; (function
69;; (lambda (a b) 69;; (lambda (a b)
70;; (string-lessp (symbol-name a) 70;; (string-lessp (symbol-name a)
71;; (symbol-name b))))) 71;; (symbol-name b)))))
72;; (insert (format "* %-34s" 72;; (insert (format "* %-34s"
73;; (concat (get module 'custom-tag) "::")) 73;; (concat (get module 'custom-tag) "::"))
74;; (symbol-name module) ".\n")) 74;; (symbol-name module) ".\n"))
75;; (insert "\nOptional Functionality\n") 75;; (insert "\nOptional Functionality\n")
76;; (eshell-for module 76;; (eshell-for module
77;; (sort (eshell-subgroups 'eshell-module) 77;; (sort (eshell-subgroups 'eshell-module)
78;; (function 78;; (function
79;; (lambda (a b) 79;; (lambda (a b)
80;; (string-lessp (symbol-name a) 80;; (string-lessp (symbol-name a)
81;; (symbol-name b))))) 81;; (symbol-name b)))))
82;; (insert (format "* %-34s" 82;; (insert (format "* %-34s"
83;; (concat (get module 'custom-tag) "::")) 83;; (concat (get module 'custom-tag) "::"))
84;; (symbol-name module) ".\n")) 84;; (symbol-name module) ".\n"))
85;; (insert "@end menu\n")) 85;; (insert "@end menu\n"))
86 86
87;; (defun eshell-make-texi () 87;; (defun eshell-make-texi ()
@@ -91,27 +91,27 @@
91;; (require 'texidoc) 91;; (require 'texidoc)
92;; (require 'pcomplete) 92;; (require 'pcomplete)
93;; (apply 'texidoc-files 'eshell-generate-main-menu "eshell.doci" 93;; (apply 'texidoc-files 'eshell-generate-main-menu "eshell.doci"
94;; (append 94;; (append
95;; (list "eshell.el") 95;; (list "eshell.el")
96;; (sort (mapcar 96;; (sort (mapcar
97;; (function 97;; (function
98;; (lambda (sym) 98;; (lambda (sym)
99;; (let ((name (symbol-name sym))) 99;; (let ((name (symbol-name sym)))
100;; (if (string-match "\\`eshell-\\(.*\\)" name) 100;; (if (string-match "\\`eshell-\\(.*\\)" name)
101;; (setq name (concat "esh-" (match-string 1 name)))) 101;; (setq name (concat "esh-" (match-string 1 name))))
102;; (concat name ".el")))) 102;; (concat name ".el"))))
103;; (eshell-subgroups 'eshell)) 103;; (eshell-subgroups 'eshell))
104;; 'string-lessp) 104;; 'string-lessp)
105;; (sort (mapcar 105;; (sort (mapcar
106;; (function 106;; (function
107;; (lambda (sym) 107;; (lambda (sym)
108;; (let ((name (symbol-name sym))) 108;; (let ((name (symbol-name sym)))
109;; (if (string-match "\\`eshell-\\(.*\\)" name) 109;; (if (string-match "\\`eshell-\\(.*\\)" name)
110;; (setq name (concat "em-" (match-string 1 name)))) 110;; (setq name (concat "em-" (match-string 1 name))))
111;; (concat name ".el")))) 111;; (concat name ".el"))))
112;; (eshell-subgroups 'eshell-module)) 112;; (eshell-subgroups 'eshell-module))
113;; 'string-lessp) 113;; 'string-lessp)
114;; (list "eshell.texi")))) 114;; (list "eshell.texi"))))
115 115
116;; (defun eshell-make-readme () 116;; (defun eshell-make-readme ()
117;; "Make the README file from eshell.el." 117;; "Make the README file from eshell.el."
diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el
index ad513c47a0b..5da511626c5 100644
--- a/lisp/eshell/esh-mode.el
+++ b/lisp/eshell/esh-mode.el
@@ -180,9 +180,7 @@ inserted. They return the string as it should be inserted."
180 :group 'eshell-mode) 180 :group 'eshell-mode)
181 181
182(defcustom eshell-password-prompt-regexp 182(defcustom eshell-password-prompt-regexp
183 "\\(\\([Oo]ld \\|[Nn]ew \\|Kerberos \\|CVS \\|'s \\|login \\|^\\)\ 183 "[Pp]ass\\(word\\|phrase\\).*:\\s *\\'"
184[Pp]assword\\|pass phrase\\|\\(Enter\\|Repeat\\) passphrase\\)\
185\\( for [^@ \t\n]+@[^@ \t\n]+\\)?:\\s *\\'"
186 "*Regexp matching prompts for passwords in the inferior process. 184 "*Regexp matching prompts for passwords in the inferior process.
187This is used by `eshell-watch-for-password-prompt'." 185This is used by `eshell-watch-for-password-prompt'."
188 :type 'regexp 186 :type 'regexp
@@ -462,7 +460,8 @@ sessions, such as when using `eshell-command'.")
462 460
463(eshell-deftest var window-height 461(eshell-deftest var window-height
464 "LINES equals window height" 462 "LINES equals window height"
465 (eshell-command-result-p "= $LINES (window-height)" "t\n")) 463 (let ((eshell-stringify-t t))
464 (eshell-command-result-p "= $LINES (window-height)" "t\n")))
466 465
467(defun eshell-command-started () 466(defun eshell-command-started ()
468 "Indicate in the modeline that a command has started." 467 "Indicate in the modeline that a command has started."
@@ -736,7 +735,9 @@ newline."
736 (run-hooks 'eshell-input-filter-functions) 735 (run-hooks 'eshell-input-filter-functions)
737 (and (catch 'eshell-terminal 736 (and (catch 'eshell-terminal
738 (ignore 737 (ignore
739 (eshell-eval-command cmd input))) 738 (if (eshell-invoke-directly cmd input)
739 (eval cmd)
740 (eshell-eval-command cmd input))))
740 (eshell-life-is-too-much))))) 741 (eshell-life-is-too-much)))))
741 (quit 742 (quit
742 (eshell-reset t) 743 (eshell-reset t)
diff --git a/lisp/eshell/esh-module.el b/lisp/eshell/esh-module.el
index 3eab199201e..f09f1ac7b24 100644
--- a/lisp/eshell/esh-module.el
+++ b/lisp/eshell/esh-module.el
@@ -24,7 +24,9 @@
24 24
25(provide 'esh-module) 25(provide 'esh-module)
26 26
27(eval-when-compile (require 'esh-maint) (require 'cl)) 27(eval-when-compile
28 (require 'esh-maint)
29 (require 'cl))
28 30
29(defgroup eshell-module nil 31(defgroup eshell-module nil
30 "The `eshell-module' group is for Eshell extension modules, which 32 "The `eshell-module' group is for Eshell extension modules, which
@@ -85,7 +87,7 @@ customizing the variable `eshell-modules-list'."
85 (equal (file-name-nondirectory byte-compile-current-file) 87 (equal (file-name-nondirectory byte-compile-current-file)
86 "esh-modu.el")))) 88 "esh-modu.el"))))
87 (let* ((directory (file-name-directory byte-compile-current-file)) 89 (let* ((directory (file-name-directory byte-compile-current-file))
88 (elc-file (expand-file-name "esh-groups.elc" directory))) 90 (elc-file (expand-file-name "esh-groups.elc" directory)))
89 (eshell-load-defgroups directory) 91 (eshell-load-defgroups directory)
90 (if (file-exists-p elc-file) (delete-file elc-file))))) 92 (if (file-exists-p elc-file) (delete-file elc-file)))))
91 93
diff --git a/lisp/eshell/esh-test.el b/lisp/eshell/esh-test.el
index 6a14541ab39..acfb409da57 100644
--- a/lisp/eshell/esh-test.el
+++ b/lisp/eshell/esh-test.el
@@ -173,12 +173,12 @@
173 system-configuration 173 system-configuration
174 (cond ((featurep 'motif) ", Motif") 174 (cond ((featurep 'motif) ", Motif")
175 ((featurep 'x-toolkit) ", X toolkit") 175 ((featurep 'x-toolkit) ", X toolkit")
176 (t ""))) "\n") 176 (t ""))))
177 (switch-to-buffer test-buffer) 177 (switch-to-buffer test-buffer)
178 (delete-other-windows)) 178 (delete-other-windows))
179 (eshell-for funcname 179 (eshell-for funcname (sort (all-completions "eshell-test--"
180 (sort (all-completions "eshell-test--" obarray 'functionp) 180 obarray 'functionp)
181 'string-lessp) 181 'string-lessp)
182 (with-current-buffer test-buffer 182 (with-current-buffer test-buffer
183 (insert "\n")) 183 (insert "\n"))
184 (funcall (intern-soft funcname))) 184 (funcall (intern-soft funcname)))
diff --git a/lisp/eshell/esh-util.el b/lisp/eshell/esh-util.el
index 01c0ff2c76e..3d8dedc6bae 100644
--- a/lisp/eshell/esh-util.el
+++ b/lisp/eshell/esh-util.el
@@ -36,6 +36,14 @@
36 36
37;;; User Variables: 37;;; User Variables:
38 38
39(defcustom eshell-stringify-t t
40 "*If non-nil, the string representation of t is 't'.
41If nil, t will be represented only in the exit code of the function,
42and not printed as a string. This causes Lisp functions to behave
43similarly to external commands, as far as successful result output."
44 :type 'boolean
45 :group 'eshell-util)
46
39(defcustom eshell-group-file "/etc/group" 47(defcustom eshell-group-file "/etc/group"
40 "*If non-nil, the name of the group file on your system." 48 "*If non-nil, the name of the group file on your system."
41 :type '(choice (const :tag "No group file" nil) file) 49 :type '(choice (const :tag "No group file" nil) file)
@@ -305,7 +313,9 @@ If N or M is nil, it means the end of the list."
305 ((numberp object) 313 ((numberp object)
306 (number-to-string object)) 314 (number-to-string object))
307 (t 315 (t
308 (pp-to-string object)))) 316 (unless (and (eq object t)
317 (not eshell-stringify-t))
318 (pp-to-string object)))))
309 319
310(defsubst eshell-stringify-list (args) 320(defsubst eshell-stringify-list (args)
311 "Convert each element of ARGS into a string value." 321 "Convert each element of ARGS into a string value."
@@ -611,7 +621,7 @@ Unless optional argument INPLACE is non-nil, return a new string."
611 (autoload 'parse-time-string "parse-time")) 621 (autoload 'parse-time-string "parse-time"))
612 622
613(eval-when-compile 623(eval-when-compile
614 (require 'ange-ftp)) 624 (load "ange-ftp" t))
615 625
616(defun eshell-parse-ange-ls (dir) 626(defun eshell-parse-ange-ls (dir)
617 (let (entry) 627 (let (entry)