aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Wiegley2000-08-29 00:47:45 +0000
committerJohn Wiegley2000-08-29 00:47:45 +0000
commitca7aae916bab6783c5133d8432b61d97b8ffa923 (patch)
tree1b36d8d391a6a0c166fd27a01acbc92a92020530
parentb4bd214e74d885552fe38051253dbc2b362bfe67 (diff)
downloademacs-ca7aae916bab6783c5133d8432b61d97b8ffa923.tar.gz
emacs-ca7aae916bab6783c5133d8432b61d97b8ffa923.zip
See ChangeLog
-rw-r--r--lisp/ChangeLog4
-rw-r--r--lisp/align.el6
-rw-r--r--lisp/eshell/em-cmpl.el9
-rw-r--r--lisp/eshell/em-dirs.el6
-rw-r--r--lisp/eshell/em-hist.el14
-rw-r--r--lisp/eshell/em-ls.el2
-rw-r--r--lisp/eshell/em-rebind.el2
-rw-r--r--lisp/eshell/em-smart.el23
-rw-r--r--lisp/eshell/em-unix.el94
-rw-r--r--lisp/eshell/em-xtra.el2
-rw-r--r--lisp/eshell/esh-cmd.el162
-rw-r--r--lisp/eshell/esh-ext.el6
-rw-r--r--lisp/eshell/esh-io.el27
-rw-r--r--lisp/eshell/esh-mode.el1
-rw-r--r--lisp/eshell/esh-proc.el137
-rw-r--r--lisp/eshell/esh-util.el2
-rw-r--r--lisp/eshell/esh-var.el12
-rw-r--r--lisp/pcmpl-gnu.el7
-rw-r--r--lisp/pcomplete.el10
19 files changed, 348 insertions, 178 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index b0353360325..3399619f343 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,9 @@
12000-08-28 John Wiegley <johnw@gnu.org> 12000-08-28 John Wiegley <johnw@gnu.org>
2 2
3 * eshell/esh-util.el (eshell-flatten-list): It's not too wise to
4 have a defsubst call itself. Made `eshell-flatten-list' back into
5 a function again.
6
3 * eshell/em-smart.el (eshell-smart-redisplay): Added a safety 7 * eshell/em-smart.el (eshell-smart-redisplay): Added a safety
4 catch, in case re-centering point at bottom messes up the display. 8 catch, in case re-centering point at bottom messes up the display.
5 This happens frequently in Emacs 21, due I believe to variable 9 This happens frequently in Emacs 21, due I believe to variable
diff --git a/lisp/align.el b/lisp/align.el
index 0c7184678d7..4a3b098ec2b 100644
--- a/lisp/align.el
+++ b/lisp/align.el
@@ -873,7 +873,8 @@ on the format of these lists."
873 (interactive "r") 873 (interactive "r")
874 (let ((separator 874 (let ((separator
875 (or separate 875 (or separate
876 (if (symbolp align-region-separate) 876 (if (and (symbolp align-region-separate)
877 (boundp align-region-separate))
877 (symbol-value align-region-separate) 878 (symbol-value align-region-separate)
878 align-region-separate) 879 align-region-separate)
879 'entire))) 880 'entire)))
@@ -1038,7 +1039,8 @@ to be colored."
1038(defun align-newline-and-indent () 1039(defun align-newline-and-indent ()
1039 "A replacement function for `newline-and-indent', aligning as it goes." 1040 "A replacement function for `newline-and-indent', aligning as it goes."
1040 (interactive) 1041 (interactive)
1041 (let ((separate (or (if (symbolp align-region-separate) 1042 (let ((separate (or (if (and (symbolp align-region-separate)
1043 (boundp align-region-separate))
1042 (symbol-value align-region-separate) 1044 (symbol-value align-region-separate)
1043 align-region-separate) 1045 align-region-separate)
1044 'entire)) 1046 'entire))
diff --git a/lisp/eshell/em-cmpl.el b/lisp/eshell/em-cmpl.el
index a0668f7d57a..19a0f595e6f 100644
--- a/lisp/eshell/em-cmpl.el
+++ b/lisp/eshell/em-cmpl.el
@@ -225,7 +225,12 @@ to writing a completion function."
225 (documentation-property 'pcomplete-default-completion-function 225 (documentation-property 'pcomplete-default-completion-function
226 'variable-documentation) 226 'variable-documentation)
227 :type (get 'pcomplete-default-completion-function 'custom-type) 227 :type (get 'pcomplete-default-completion-function 'custom-type)
228 :group 'pcomplete) 228 :group 'eshell-cmpl)
229
230(defcustom eshell-cmpl-use-paring t
231 (documentation-property 'pcomplete-use-paring 'variable-documentation)
232 :type (get 'pcomplete-use-paring 'custom-type)
233 :group 'eshell-cmpl)
229 234
230;;; Functions: 235;;; Functions:
231 236
@@ -265,6 +270,8 @@ to writing a completion function."
265 eshell-cmpl-cycle-cutoff-length) 270 eshell-cmpl-cycle-cutoff-length)
266 (set (make-local-variable 'pcomplete-restore-window-delay) 271 (set (make-local-variable 'pcomplete-restore-window-delay)
267 eshell-cmpl-restore-window-delay) 272 eshell-cmpl-restore-window-delay)
273 (set (make-local-variable 'pcomplete-use-paring)
274 eshell-cmpl-use-paring)
268 ;; `pcomplete-arg-quote-list' should only be set after all the 275 ;; `pcomplete-arg-quote-list' should only be set after all the
269 ;; load-hooks for any other extension modules have been run, which 276 ;; load-hooks for any other extension modules have been run, which
270 ;; is true at the time `eshell-mode-hook' is run 277 ;; is true at the time `eshell-mode-hook' is run
diff --git a/lisp/eshell/em-dirs.el b/lisp/eshell/em-dirs.el
index 13565d87521..c59bd042575 100644
--- a/lisp/eshell/em-dirs.el
+++ b/lisp/eshell/em-dirs.el
@@ -382,11 +382,13 @@ in the minibuffer:
382 (index 0)) 382 (index 0))
383 (if (= len 0) 383 (if (= len 0)
384 (error "Directory ring empty")) 384 (error "Directory ring empty"))
385 (eshell-init-print-buffer)
385 (while (< index len) 386 (while (< index len)
386 (eshell-printn 387 (eshell-buffered-print
387 (concat (number-to-string index) ": " 388 (concat (number-to-string index) ": "
388 (ring-ref eshell-last-dir-ring index))) 389 (ring-ref eshell-last-dir-ring index) "\n"))
389 (setq index (1+ index))) 390 (setq index (1+ index)))
391 (eshell-flush)
390 (setq handled t))))) 392 (setq handled t)))))
391 (path 393 (path
392 (setq path (eshell-expand-multiple-dots path)))) 394 (setq path (eshell-expand-multiple-dots path))))
diff --git a/lisp/eshell/em-hist.el b/lisp/eshell/em-hist.el
index 896178a7958..1213dfcc291 100644
--- a/lisp/eshell/em-hist.el
+++ b/lisp/eshell/em-hist.el
@@ -350,17 +350,13 @@ unless a different file is specified on the command line.")
350(defun eshell-put-history (input &optional ring at-beginning) 350(defun eshell-put-history (input &optional ring at-beginning)
351 "Put a new input line into the history ring." 351 "Put a new input line into the history ring."
352 (unless ring (setq ring eshell-history-ring)) 352 (unless ring (setq ring eshell-history-ring))
353 (subst-char-in-string ?\n ?\177 input t)
354 (if at-beginning 353 (if at-beginning
355 (ring-insert-at-beginning ring input) 354 (ring-insert-at-beginning ring input)
356 (ring-insert ring input))) 355 (ring-insert ring input)))
357 356
358(defun eshell-get-history (index &optional ring) 357(defun eshell-get-history (index &optional ring)
359 "Get an input line from the history ring." 358 "Get an input line from the history ring."
360 (unless ring (setq ring eshell-history-ring)) 359 (ring-ref (or ring eshell-history-ring) index))
361 (let ((input (concat (ring-ref ring index))))
362 (subst-char-in-string ?\177 ?\n input t)
363 input))
364 360
365(defun eshell-add-to-history () 361(defun eshell-add-to-history ()
366 "Add INPUT to the history ring. 362 "Add INPUT to the history ring.
@@ -419,7 +415,8 @@ line, with the most recent command last. See also
419 (if (or (null ignore-dups) 415 (if (or (null ignore-dups)
420 (ring-empty-p ring) 416 (ring-empty-p ring)
421 (not (string-equal (ring-ref ring 0) history))) 417 (not (string-equal (ring-ref ring 0) history)))
422 (ring-insert-at-beginning ring history))) 418 (ring-insert-at-beginning
419 ring (subst-char-in-string ?\177 ?\n history))))
423 (setq count (1+ count)))) 420 (setq count (1+ count))))
424 (setq eshell-history-ring ring 421 (setq eshell-history-ring ring
425 eshell-history-index nil)))))) 422 eshell-history-index nil))))))
@@ -451,7 +448,9 @@ See also `eshell-read-history'."
451 (with-temp-buffer 448 (with-temp-buffer
452 (while (> index 0) 449 (while (> index 0)
453 (setq index (1- index)) 450 (setq index (1- index))
454 (insert (ring-ref ring index) ?\n)) 451 (let ((start (point)))
452 (insert (ring-ref ring index) ?\n)
453 (subst-char-in-region start (1- (point)) ?\n ?\177)))
455 (eshell-with-private-file-modes 454 (eshell-with-private-file-modes
456 (write-region (point-min) (point-max) file append 455 (write-region (point-min) (point-max) file append
457 'no-message)))))))) 456 'no-message))))))))
@@ -891,7 +890,6 @@ If N is negative, search backwards for the -Nth previous match."
891 (goto-char eshell-last-output-end) 890 (goto-char eshell-last-output-end)
892 (delete-region (point) (point-max)) 891 (delete-region (point) (point-max))
893 (when (and text (> (length text) 0)) 892 (when (and text (> (length text) 0))
894 (subst-char-in-string ?\177 ?\n text t)
895 (insert text) 893 (insert text)
896 (put-text-property (1- (point)) (point) 894 (put-text-property (1- (point)) (point)
897 'last-search-pos before) 895 'last-search-pos before)
diff --git a/lisp/eshell/em-ls.el b/lisp/eshell/em-ls.el
index e9e46c2f1a6..cd16f049815 100644
--- a/lisp/eshell/em-ls.el
+++ b/lisp/eshell/em-ls.el
@@ -820,7 +820,7 @@ Use TRUENAME for predicate tests, if passed."
820 ((not (eshell-ls-filetype-p (cdr file) ?-)) 820 ((not (eshell-ls-filetype-p (cdr file) ?-))
821 'eshell-ls-special-face) 821 'eshell-ls-special-face)
822 822
823 ((and (not (= (user-uid) 0)) ; root can execute anything 823 ((and (/= (user-uid) 0) ; root can execute anything
824 (eshell-ls-applicable (cdr file) 3 824 (eshell-ls-applicable (cdr file) 3
825 'file-executable-p (car file))) 825 'file-executable-p (car file)))
826 'eshell-ls-executable-face) 826 'eshell-ls-executable-face)
diff --git a/lisp/eshell/em-rebind.el b/lisp/eshell/em-rebind.el
index bd5ee5f5292..0463a78ffb4 100644
--- a/lisp/eshell/em-rebind.el
+++ b/lisp/eshell/em-rebind.el
@@ -235,7 +235,7 @@ input."
235 (let ((proc (get-buffer-process (current-buffer)))) 235 (let ((proc (get-buffer-process (current-buffer))))
236 (if (eobp) 236 (if (eobp)
237 (cond 237 (cond
238 ((not (= (point) eshell-last-output-end)) 238 ((/= (point) eshell-last-output-end)
239 (beep)) 239 (beep))
240 (proc 240 (proc
241 (process-send-eof)) 241 (process-send-eof))
diff --git a/lisp/eshell/em-smart.el b/lisp/eshell/em-smart.el
index 0d5a2732dd5..d7db23a0f9b 100644
--- a/lisp/eshell/em-smart.el
+++ b/lisp/eshell/em-smart.el
@@ -258,15 +258,20 @@ and the end of the buffer are still visible."
258 "Display as much output as possible, smartly." 258 "Display as much output as possible, smartly."
259 (if (eobp) 259 (if (eobp)
260 (recenter -1) 260 (recenter -1)
261 (and (memq 'eshell-smart-display-move pre-command-hook) 261 (let ((top-point (point)))
262 (>= (point) eshell-last-input-start) 262 (and (memq 'eshell-smart-display-move pre-command-hook)
263 (< (point) eshell-last-input-end) 263 (>= (point) eshell-last-input-start)
264 (set-window-start (selected-window) 264 (< (point) eshell-last-input-end)
265 (line-beginning-position) t)) 265 (set-window-start (selected-window)
266 (if (pos-visible-in-window-p (point-max)) 266 (line-beginning-position) t))
267 (save-excursion 267 (if (pos-visible-in-window-p (point-max))
268 (goto-char (point-max)) 268 (save-excursion
269 (recenter -1))))) 269 (goto-char (point-max))
270 (recenter -1)
271 (unless (pos-visible-in-window-p top-point)
272 (goto-char top-point)
273 (set-window-start (selected-window)
274 (line-beginning-position) t)))))))
270 275
271(defun eshell-smart-goto-end () 276(defun eshell-smart-goto-end ()
272 "Like `end-of-buffer', but do not push a mark." 277 "Like `end-of-buffer', but do not push a mark."
diff --git a/lisp/eshell/em-unix.el b/lisp/eshell/em-unix.el
index 33a99cb06a3..17e110f65ed 100644
--- a/lisp/eshell/em-unix.el
+++ b/lisp/eshell/em-unix.el
@@ -117,7 +117,7 @@ Otherwise, `rmdir' is required."
117 :type 'boolean 117 :type 'boolean
118 :group 'eshell-unix) 118 :group 'eshell-unix)
119 119
120(defcustom eshell-ln-overwrite-files t 120(defcustom eshell-ln-overwrite-files nil
121 "*If non-nil, `ln' will overwrite files without warning." 121 "*If non-nil, `ln' will overwrite files without warning."
122 :type 'boolean 122 :type 'boolean
123 :group 'eshell-unix) 123 :group 'eshell-unix)
@@ -224,7 +224,7 @@ Remove (unlink) the FILE(s).")
224 (not (y-or-n-p (format "rm: delete buffer `%s'? " 224 (not (y-or-n-p (format "rm: delete buffer `%s'? "
225 entry))))) 225 entry)))))
226 (eshell-funcalln 'kill-buffer entry))) 226 (eshell-funcalln 'kill-buffer entry)))
227 ((processp entry) 227 ((eshell-processp entry)
228 (if verbose 228 (if verbose
229 (eshell-printn (format "rm: killing process `%s'" entry))) 229 (eshell-printn (format "rm: killing process `%s'" entry)))
230 (unless (or preview 230 (unless (or preview
@@ -353,13 +353,14 @@ Remove the DIRECTORY(ies), if they are empty.")
353 command target))) 353 command target)))
354 (unless preview 354 (unless preview
355 (eshell-funcalln 'make-directory target))) 355 (eshell-funcalln 'make-directory target)))
356 (eshell-shuffle-files command action 356 (apply 'eshell-shuffle-files
357 (mapcar 357 command action
358 (function 358 (mapcar
359 (lambda (file) 359 (function
360 (concat source "/" file))) 360 (lambda (file)
361 (directory-files source)) 361 (concat source "/" file)))
362 target func t args) 362 (directory-files source))
363 target func t args)
363 (when (eq func 'rename-file) 364 (when (eq func 'rename-file)
364 (if verbose 365 (if verbose
365 (eshell-printn 366 (eshell-printn
@@ -527,7 +528,7 @@ with '--symbolic'. When creating hard links, each TARGET must exist.")
527 "Implementation of cat in Lisp." 528 "Implementation of cat in Lisp."
528 (if eshell-in-pipeline-p 529 (if eshell-in-pipeline-p
529 (throw 'eshell-replace-command 530 (throw 'eshell-replace-command
530 (eshell-parse-command "*cat" args)) 531 (eshell-parse-command "*cat" (eshell-flatten-list args)))
531 (eshell-init-print-buffer) 532 (eshell-init-print-buffer)
532 (eshell-eval-using-options 533 (eshell-eval-using-options
533 "cat" args 534 "cat" args
@@ -568,7 +569,7 @@ Concatenate FILE(s), or standard input, to standard output.")
568 (list 'quote (eshell-copy-environment)))))) 569 (list 'quote (eshell-copy-environment))))))
569 (compile (concat "make " (eshell-flatten-and-stringify args)))) 570 (compile (concat "make " (eshell-flatten-and-stringify args))))
570 (throw 'eshell-replace-command 571 (throw 'eshell-replace-command
571 (eshell-parse-command "*make" args)))) 572 (eshell-parse-command "*make" (eshell-flatten-list args)))))
572 573
573(defun eshell-occur-mode-goto-occurrence () 574(defun eshell-occur-mode-goto-occurrence ()
574 "Go to the occurrence the current line describes." 575 "Go to the occurrence the current line describes."
@@ -644,7 +645,8 @@ external command."
644 (not eshell-in-pipeline-p) 645 (not eshell-in-pipeline-p)
645 (not eshell-in-subcommand-p)))) 646 (not eshell-in-subcommand-p))))
646 (throw 'eshell-replace-command 647 (throw 'eshell-replace-command
647 (eshell-parse-command (concat "*" command) args)) 648 (eshell-parse-command (concat "*" command)
649 (eshell-flatten-list args)))
648 (let* ((compilation-process-setup-function 650 (let* ((compilation-process-setup-function
649 (list 'lambda nil 651 (list 'lambda nil
650 (list 'setq 'process-environment 652 (list 'setq 'process-environment
@@ -745,8 +747,8 @@ external command."
745 (cadr (car entries))))) 747 (cadr (car entries)))))
746 (unless (or (and symlink (not dereference-links)) 748 (unless (or (and symlink (not dereference-links))
747 (and only-one-filesystem 749 (and only-one-filesystem
748 (not (= only-one-filesystem 750 (/= only-one-filesystem
749 (nth 12 (car entries)))))) 751 (nth 12 (car entries)))))
750 (if symlink 752 (if symlink
751 (setq entry symlink)) 753 (setq entry symlink))
752 (setq size 754 (setq size
@@ -769,10 +771,10 @@ external command."
769 size)) 771 size))
770 772
771(defun eshell/du (&rest args) 773(defun eshell/du (&rest args)
772 "Implementation of \"du\" in Lisp, passing RAGS." 774 "Implementation of \"du\" in Lisp, passing ARGS."
773 (if (eshell-search-path "du") 775 (if (eshell-search-path "du")
774 (throw 'eshell-replace-command 776 (throw 'eshell-replace-command
775 (eshell-parse-command "*du" args)) 777 (eshell-parse-command "*du" (eshell-flatten-list args)))
776 (eshell-eval-using-options 778 (eshell-eval-using-options
777 "du" args 779 "du" args
778 '((?a "all" nil show-all 780 '((?a "all" nil show-all
@@ -875,32 +877,38 @@ Show wall-clock time elapsed during execution of COMMAND.")
875 877
876(defun eshell/diff (&rest args) 878(defun eshell/diff (&rest args)
877 "Alias \"diff\" to call Emacs `diff' function." 879 "Alias \"diff\" to call Emacs `diff' function."
878 (if (or eshell-plain-diff-behavior 880 (let ((orig-args (eshell-flatten-list args)))
879 (not (and (eshell-interactive-output-p) 881 (if (or eshell-plain-diff-behavior
880 (not eshell-in-pipeline-p) 882 (not (and (eshell-interactive-output-p)
881 (not eshell-in-subcommand-p)))) 883 (not eshell-in-pipeline-p)
882 (throw 'eshell-replace-command 884 (not eshell-in-subcommand-p))))
883 (eshell-parse-command "*diff" args)) 885 (throw 'eshell-replace-command
884 (setq args (eshell-flatten-list args)) 886 (eshell-parse-command "*diff" orig-args))
885 (if (< (length args) 2) 887 (setq args (eshell-copy-list orig-args))
886 (error "diff: missing operand")) 888 (if (< (length args) 2)
887 (let ((old (car (last args 2))) 889 (throw 'eshell-replace-command
888 (new (car (last args))) 890 (eshell-parse-command "*diff" orig-args)))
889 (config (current-window-configuration))) 891 (let ((old (car (last args 2)))
890 (if (= (length args) 2) 892 (new (car (last args)))
891 (setq args nil) 893 (config (current-window-configuration)))
892 (setcdr (last args 3) nil)) 894 (if (= (length args) 2)
893 (with-current-buffer 895 (setq args nil)
894 (diff old new (eshell-flatten-and-stringify args)) 896 (setcdr (last args 3) nil))
895 (when (fboundp 'diff-mode) 897 (with-current-buffer
896 (diff-mode) 898 (condition-case err
897 (set (make-local-variable 'eshell-diff-window-config) config) 899 (diff old new (eshell-flatten-and-stringify args))
898 (local-set-key [?q] 'eshell-diff-quit) 900 (error
899 (if (fboundp 'turn-on-font-lock-if-enabled) 901 (throw 'eshell-replace-command
900 (turn-on-font-lock-if-enabled)))) 902 (eshell-parse-command "*diff" orig-args))))
901 (other-window 1) 903 (when (fboundp 'diff-mode)
902 (goto-char (point-min)) 904 (diff-mode)
903 nil))) 905 (set (make-local-variable 'eshell-diff-window-config) config)
906 (local-set-key [?q] 'eshell-diff-quit)
907 (if (fboundp 'turn-on-font-lock-if-enabled)
908 (turn-on-font-lock-if-enabled))))
909 (other-window 1)
910 (goto-char (point-min))
911 nil))))
904 912
905(defun eshell/locate (&rest args) 913(defun eshell/locate (&rest args)
906 "Alias \"locate\" to call Emacs `locate' function." 914 "Alias \"locate\" to call Emacs `locate' function."
@@ -911,7 +919,7 @@ Show wall-clock time elapsed during execution of COMMAND.")
911 (and (stringp (car args)) 919 (and (stringp (car args))
912 (string-match "^-" (car args)))) 920 (string-match "^-" (car args))))
913 (throw 'eshell-replace-command 921 (throw 'eshell-replace-command
914 (eshell-parse-command "*locate" args)) 922 (eshell-parse-command "*locate" (eshell-flatten-list args)))
915 (save-selected-window 923 (save-selected-window
916 (let ((locate-history-list (list (car args)))) 924 (let ((locate-history-list (list (car args))))
917 (locate-with-filter (car args) (cadr args)))))) 925 (locate-with-filter (car args) (cadr args))))))
diff --git a/lisp/eshell/em-xtra.el b/lisp/eshell/em-xtra.el
index ad5602d97a0..9b4e6ad058e 100644
--- a/lisp/eshell/em-xtra.el
+++ b/lisp/eshell/em-xtra.el
@@ -41,7 +41,7 @@ naturally accessible within Emacs."
41 "Implementation of expr, using the calc package." 41 "Implementation of expr, using the calc package."
42 (if (not (fboundp 'calc-eval)) 42 (if (not (fboundp 'calc-eval))
43 (throw 'eshell-replace-command 43 (throw 'eshell-replace-command
44 (eshell-parse-command "*expr" args)) 44 (eshell-parse-command "*expr" (eshell-flatten-list args)))
45 ;; to fool the byte-compiler... 45 ;; to fool the byte-compiler...
46 (let ((func 'calc-eval)) 46 (let ((func 'calc-eval))
47 (funcall func (eshell-flatten-and-stringify args))))) 47 (funcall func (eshell-flatten-and-stringify args)))))
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index a3c7d58c066..fcdcfbb3fc3 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -516,8 +516,8 @@ implemented via rewriting, rather than as a function."
516 (list 'car 516 (list 'car
517 (list 'symbol-value 517 (list 'symbol-value
518 (list 'quote 'for-items))))) 518 (list 'quote 'for-items)))))
519 (list 'eshell-protect 519 (list 'eshell-copy-handles
520 (eshell-invokify-arg body t))) 520 (eshell-invokify-arg body t)))
521 (list 'setcar 'for-items 521 (list 'setcar 'for-items
522 (list 'cadr 522 (list 'cadr
523 (list 'symbol-value 523 (list 'symbol-value
@@ -581,7 +581,7 @@ must be implemented via rewriting, rather than as a function."
581 (eshell-structure-basic-command 581 (eshell-structure-basic-command
582 'while '("while" "until") (car terms) 582 'while '("while" "until") (car terms)
583 (eshell-invokify-arg (cadr terms) nil t) 583 (eshell-invokify-arg (cadr terms) nil t)
584 (list 'eshell-protect 584 (list 'eshell-copy-handles
585 (eshell-invokify-arg (car (last terms)) t))))) 585 (eshell-invokify-arg (car (last terms)) t)))))
586 586
587(defun eshell-rewrite-if-command (terms) 587(defun eshell-rewrite-if-command (terms)
@@ -770,6 +770,31 @@ this grossness will be made to disappear by using `call/cc'..."
770 (eshell-errorn (error-message-string err)) 770 (eshell-errorn (error-message-string err))
771 (eshell-close-handles 1))))) 771 (eshell-close-handles 1)))))
772 772
773;; (defun eshell-copy-or-protect-handles ()
774;; (if (eshell-processp (car (aref eshell-current-handles
775;; eshell-output-handle)))
776;; (eshell-protect-handles eshell-current-handles)
777;; (eshell-create-handles
778;; (car (aref eshell-current-handles
779;; eshell-output-handle)) nil
780;; (car (aref eshell-current-handles
781;; eshell-error-handle)) nil)))
782
783;; (defmacro eshell-copy-handles (object)
784;; "Duplicate current I/O handles, so OBJECT works with its own copy."
785;; `(let ((eshell-current-handles (eshell-copy-or-protect-handles)))
786;; ,object))
787
788(defmacro eshell-copy-handles (object)
789 "Duplicate current I/O handles, so OBJECT works with its own copy."
790 `(let ((eshell-current-handles
791 (eshell-create-handles
792 (car (aref eshell-current-handles
793 eshell-output-handle)) nil
794 (car (aref eshell-current-handles
795 eshell-error-handle)) nil)))
796 ,object))
797
773(defmacro eshell-protect (object) 798(defmacro eshell-protect (object)
774 "Protect I/O handles, so they aren't get closed after eval'ing OBJECT." 799 "Protect I/O handles, so they aren't get closed after eval'ing OBJECT."
775 `(progn 800 `(progn
@@ -779,32 +804,65 @@ this grossness will be made to disappear by using `call/cc'..."
779(defmacro eshell-do-pipelines (pipeline) 804(defmacro eshell-do-pipelines (pipeline)
780 "Execute the commands in PIPELINE, connecting each to one another." 805 "Execute the commands in PIPELINE, connecting each to one another."
781 (when (setq pipeline (cadr pipeline)) 806 (when (setq pipeline (cadr pipeline))
782 `(let ((eshell-current-handles 807 `(eshell-copy-handles
783 (eshell-create-handles 808 (progn
784 (car (aref eshell-current-handles 809 ,(when (cdr pipeline)
785 eshell-output-handle)) nil 810 `(let (nextproc)
786 (car (aref eshell-current-handles 811 (progn
787 eshell-error-handle)) nil))) 812 (set 'nextproc
813 (eshell-do-pipelines (quote ,(cdr pipeline))))
814 (eshell-set-output-handle ,eshell-output-handle
815 'append nextproc)
816 (eshell-set-output-handle ,eshell-error-handle
817 'append nextproc)
818 (set 'tailproc (or tailproc nextproc)))))
819 ,(let ((head (car pipeline)))
820 (if (memq (car head) '(let progn))
821 (setq head (car (last head))))
822 (when (memq (car head) eshell-deferrable-commands)
823 (ignore
824 (setcar head
825 (intern-soft
826 (concat (symbol-name (car head)) "*"))))))
827 ,(car pipeline)))))
828
829(defmacro eshell-do-pipelines-synchronously (pipeline)
830 "Execute the commands in PIPELINE in sequence synchronously.
831Output of each command is passed as input to the next one in the pipeline.
832This is used on systems where `start-process' is not supported."
833 (when (setq pipeline (cadr pipeline))
834 `(let (result)
788 (progn 835 (progn
789 ,(when (cdr pipeline) 836 ,(when (cdr pipeline)
790 `(let (nextproc) 837 `(let (output-marker)
791 (progn 838 (progn
792 (set 'nextproc 839 (set 'output-marker ,(point-marker))
793 (eshell-do-pipelines (quote ,(cdr pipeline))))
794 (eshell-set-output-handle ,eshell-output-handle 840 (eshell-set-output-handle ,eshell-output-handle
795 'append nextproc) 841 'append output-marker)
796 (eshell-set-output-handle ,eshell-error-handle 842 (eshell-set-output-handle ,eshell-error-handle
797 'append nextproc) 843 'append output-marker))))
798 (set 'tailproc (or tailproc nextproc)))))
799 ,(let ((head (car pipeline))) 844 ,(let ((head (car pipeline)))
800 (if (memq (car head) '(let progn)) 845 (if (memq (car head) '(let progn))
801 (setq head (car (last head)))) 846 (setq head (car (last head))))
847 ;;; FIXME: is deferrable significant here?
802 (when (memq (car head) eshell-deferrable-commands) 848 (when (memq (car head) eshell-deferrable-commands)
803 (ignore 849 (ignore
804 (setcar head 850 (setcar head
805 (intern-soft 851 (intern-soft
806 (concat (symbol-name (car head)) "*")))))) 852 (concat (symbol-name (car head)) "*"))))))
807 ,(car pipeline))))) 853 ;; The last process in the pipe should get its handles
854 ;; redirected as we found them before running the pipe.
855 ,(if (null (cdr pipeline))
856 `(progn
857 (set 'eshell-current-handles tail-handles)
858 (set 'eshell-in-pipeline-p nil)))
859 (set 'result ,(car pipeline))
860 ;; tailproc gets the result of the last successful process in
861 ;; the pipeline.
862 (set 'tailproc (or result tailproc))
863 ,(if (cdr pipeline)
864 `(eshell-do-pipelines-synchronously (quote ,(cdr pipeline))))
865 result))))
808 866
809(defalias 'eshell-process-identity 'identity) 867(defalias 'eshell-process-identity 'identity)
810 868
@@ -812,7 +870,14 @@ this grossness will be made to disappear by using `call/cc'..."
812 "Execute the commands in PIPELINE, connecting each to one another." 870 "Execute the commands in PIPELINE, connecting each to one another."
813 `(let ((eshell-in-pipeline-p t) tailproc) 871 `(let ((eshell-in-pipeline-p t) tailproc)
814 (progn 872 (progn
815 (eshell-do-pipelines ,pipeline) 873 ,(if (fboundp 'start-process)
874 `(eshell-do-pipelines ,pipeline)
875 `(let ((tail-handles (eshell-create-handles
876 (car (aref eshell-current-handles
877 ,eshell-output-handle)) nil
878 (car (aref eshell-current-handles
879 ,eshell-error-handle)) nil)))
880 (eshell-do-pipelines-synchronously ,pipeline)))
816 (eshell-process-identity tailproc)))) 881 (eshell-process-identity tailproc))))
817 882
818(defmacro eshell-as-subcommand (command) 883(defmacro eshell-as-subcommand (command)
@@ -919,12 +984,19 @@ at the moment are:
919 (erase-buffer) 984 (erase-buffer)
920 (insert "command: \"" input "\"\n")))) 985 (insert "command: \"" input "\"\n"))))
921 (setq eshell-current-command command) 986 (setq eshell-current-command command)
922 (eshell-resume-eval))) 987 (let ((delim (catch 'eshell-incomplete
988 (eshell-resume-eval))))
989 (if delim
990 (error "Unmatched delimiter: %c"
991 (if (listp delim)
992 (car delim)
993 delim))))))
923 994
924(defun eshell-resume-command (proc status) 995(defun eshell-resume-command (proc status)
925 "Resume the current command when a process ends." 996 "Resume the current command when a process ends."
926 (when proc 997 (when proc
927 (unless (or (string= "stopped" status) 998 (unless (or (not (stringp status))
999 (string= "stopped" status)
928 (string-match eshell-reset-signals status)) 1000 (string-match eshell-reset-signals status))
929 (if (eq proc (eshell-interactive-process)) 1001 (if (eq proc (eshell-interactive-process))
930 (eshell-resume-eval))))) 1002 (eshell-resume-eval)))))
@@ -941,7 +1013,7 @@ at the moment are:
941 (setq retval 1013 (setq retval
942 (eshell-do-eval 1014 (eshell-do-eval
943 eshell-current-command)))))) 1015 eshell-current-command))))))
944 (if proc 1016 (if (eshell-processp proc)
945 (ignore (setq eshell-last-async-proc proc)) 1017 (ignore (setq eshell-last-async-proc proc))
946 (cadr retval))))) 1018 (cadr retval)))))
947 (error 1019 (error
@@ -1019,38 +1091,31 @@ be finished later after the completion of an asynchronous subprocess."
1019 (when (car eshell-command-body) 1091 (when (car eshell-command-body)
1020 (assert (not synchronous-p)) 1092 (assert (not synchronous-p))
1021 (eshell-do-eval (car eshell-command-body)) 1093 (eshell-do-eval (car eshell-command-body))
1022 (setcar eshell-command-body nil)) 1094 (setcar eshell-command-body nil)
1095 (setcar eshell-test-body nil))
1023 (unless (car eshell-test-body) 1096 (unless (car eshell-test-body)
1024 (setcar eshell-test-body (eshell-copy-tree (car args)))) 1097 (setcar eshell-test-body (eshell-copy-tree (car args))))
1025 (if (and (car eshell-test-body) 1098 (while (cadr (eshell-do-eval (car eshell-test-body)))
1026 (not (eq (car eshell-test-body) 0))) 1099 (setcar eshell-command-body (eshell-copy-tree (cadr args)))
1027 (while (cadr (eshell-do-eval (car eshell-test-body))) 1100 (eshell-do-eval (car eshell-command-body) synchronous-p)
1028 (setcar eshell-test-body 0) 1101 (setcar eshell-command-body nil)
1029 (setcar eshell-command-body (eshell-copy-tree (cadr args))) 1102 (setcar eshell-test-body (eshell-copy-tree (car args))))
1030 (eshell-do-eval (car eshell-command-body) synchronous-p)
1031 (setcar eshell-command-body nil)
1032 (setcar eshell-test-body (eshell-copy-tree (car args)))))
1033 (setcar eshell-command-body nil)) 1103 (setcar eshell-command-body nil))
1034 ((eq (car form) 'if) 1104 ((eq (car form) 'if)
1035 ;; `eshell-copy-tree' is needed here so that the test argument 1105 ;; `eshell-copy-tree' is needed here so that the test argument
1036 ;; doesn't get modified and thus always yield the same result. 1106 ;; doesn't get modified and thus always yield the same result.
1037 (when (car eshell-command-body) 1107 (if (car eshell-command-body)
1038 (assert (not synchronous-p)) 1108 (progn
1039 (eshell-do-eval (car eshell-command-body)) 1109 (assert (not synchronous-p))
1040 (setcar eshell-command-body nil)) 1110 (eshell-do-eval (car eshell-command-body)))
1041 (unless (car eshell-test-body) 1111 (unless (car eshell-test-body)
1042 (setcar eshell-test-body (eshell-copy-tree (car args)))) 1112 (setcar eshell-test-body (eshell-copy-tree (car args))))
1043 (if (and (car eshell-test-body) 1113 (if (cadr (eshell-do-eval (car eshell-test-body)))
1044 (not (eq (car eshell-test-body) 0))) 1114 (setcar eshell-command-body (eshell-copy-tree (cadr args)))
1045 (if (cadr (eshell-do-eval (car eshell-test-body))) 1115 (setcar eshell-command-body (eshell-copy-tree (car (cddr args)))))
1046 (progn 1116 (eshell-do-eval (car eshell-command-body) synchronous-p))
1047 (setcar eshell-test-body 0) 1117 (setcar eshell-command-body nil)
1048 (setcar eshell-command-body (eshell-copy-tree (cadr args))) 1118 (setcar eshell-test-body nil))
1049 (eshell-do-eval (car eshell-command-body) synchronous-p))
1050 (setcar eshell-test-body 0)
1051 (setcar eshell-command-body (eshell-copy-tree (car (cddr args))))
1052 (eshell-do-eval (car eshell-command-body) synchronous-p)))
1053 (setcar eshell-command-body nil))
1054 ((eq (car form) 'setcar) 1119 ((eq (car form) 'setcar)
1055 (setcar (cdr args) (eshell-do-eval (cadr args) synchronous-p)) 1120 (setcar (cdr args) (eshell-do-eval (cadr args) synchronous-p))
1056 (eval form)) 1121 (eval form))
@@ -1131,7 +1196,7 @@ be finished later after the completion of an asynchronous subprocess."
1131 (if (and (memq (car form) eshell-deferrable-commands) 1196 (if (and (memq (car form) eshell-deferrable-commands)
1132 (not eshell-current-subjob-p) 1197 (not eshell-current-subjob-p)
1133 result 1198 result
1134 (processp result)) 1199 (eshell-processp result))
1135 (if synchronous-p 1200 (if synchronous-p
1136 (eshell/wait result) 1201 (eshell/wait result)
1137 (eshell-manipulate "inserting ignore form" 1202 (eshell-manipulate "inserting ignore form"
@@ -1172,7 +1237,8 @@ be finished later after the completion of an asynchronous subprocess."
1172 (setq desc (substring desc 0 1237 (setq desc (substring desc 0
1173 (1- (or (string-match "\n" desc) 1238 (1- (or (string-match "\n" desc)
1174 (length desc))))) 1239 (length desc)))))
1175 (kill-buffer "*Help*") 1240 (if (buffer-live-p (get-buffer "*Help*"))
1241 (kill-buffer "*Help*"))
1176 (setq program (or desc name)))))) 1242 (setq program (or desc name))))))
1177 (if (not program) 1243 (if (not program)
1178 (eshell-error (format "which: no %s in (%s)\n" 1244 (eshell-error (format "which: no %s in (%s)\n"
diff --git a/lisp/eshell/esh-ext.el b/lisp/eshell/esh-ext.el
index c4d031131a7..3aec7f22fd8 100644
--- a/lisp/eshell/esh-ext.el
+++ b/lisp/eshell/esh-ext.el
@@ -103,11 +103,9 @@ wholly ignored."
103 "Invoke a .BAT or .CMD file on DOS/Windows systems." 103 "Invoke a .BAT or .CMD file on DOS/Windows systems."
104 ;; since CMD.EXE can't handle forward slashes in the initial 104 ;; since CMD.EXE can't handle forward slashes in the initial
105 ;; argument... 105 ;; argument...
106 (setcar args (subst-char-in-string directory-sep-char 106 (setcar args (subst-char-in-string directory-sep-char ?\\ (car args)))
107 ?\\ (car args)))
108 (throw 'eshell-replace-command 107 (throw 'eshell-replace-command
109 (eshell-parse-command eshell-windows-shell-file 108 (eshell-parse-command eshell-windows-shell-file (cons "/c" args))))
110 (cons "/c" args))))
111 109
112(defcustom eshell-interpreter-alist 110(defcustom eshell-interpreter-alist
113 (if (eshell-under-windows-p) 111 (if (eshell-under-windows-p)
diff --git a/lisp/eshell/esh-io.el b/lisp/eshell/esh-io.el
index f59c1ef47b2..84dbbc18e07 100644
--- a/lisp/eshell/esh-io.el
+++ b/lisp/eshell/esh-io.el
@@ -132,8 +132,8 @@ the function is expected to return another function -- which is the
132output function. Otherwise, the second element itself is the output 132output function. Otherwise, the second element itself is the output
133function. 133function.
134 134
135The output function is then called repeatedly with a single strings, 135The output function is then called repeatedly with single strings,
136with represents success pieces of the output of the command, until nil 136which represents successive pieces of the output of the command, until nil
137is passed, meaning EOF. 137is passed, meaning EOF.
138 138
139NOTE: /dev/null is handled specially as a virtual target, and should 139NOTE: /dev/null is handled specially as a virtual target, and should
@@ -231,7 +231,9 @@ not be added to this variable."
231 (standard-output output-mode &optional standard-error error-mode) 231 (standard-output output-mode &optional standard-error error-mode)
232 "Create a new set of file handles for a command. 232 "Create a new set of file handles for a command.
233The default location for standard output and standard error will go to 233The default location for standard output and standard error will go to
234STANDARD-OUTPUT and STANDARD-ERROR, respectively." 234STANDARD-OUTPUT and STANDARD-ERROR, respectively.
235OUTPUT-MODE and ERROR-MODE are either `overwrite', `append' or `insert';
236a nil value of mode defaults to `insert'."
235 (let ((handles (make-vector eshell-number-of-handles nil)) 237 (let ((handles (make-vector eshell-number-of-handles nil))
236 (output-target (eshell-get-target standard-output output-mode)) 238 (output-target (eshell-get-target standard-output output-mode))
237 (error-target (eshell-get-target standard-error error-mode))) 239 (error-target (eshell-get-target standard-error error-mode)))
@@ -272,7 +274,7 @@ STATUS should be non-nil on successful termination of the output."
272 274
273 ;; If we're redirecting to a process (via a pipe, or process 275 ;; If we're redirecting to a process (via a pipe, or process
274 ;; redirection), send it EOF so that it knows we're finished. 276 ;; redirection), send it EOF so that it knows we're finished.
275 ((processp target) 277 ((eshell-processp target)
276 (if (eq (process-status target) 'run) 278 (if (eq (process-status target) 'run)
277 (process-send-eof target))) 279 (process-send-eof target)))
278 280
@@ -326,7 +328,8 @@ last execution result should not be changed."
326 328
327(defun eshell-get-target (target &optional mode) 329(defun eshell-get-target (target &optional mode)
328 "Convert TARGET, which is a raw argument, into a valid output target. 330 "Convert TARGET, which is a raw argument, into a valid output target.
329MODE is either `overwrite', `append' or `insert'." 331MODE is either `overwrite', `append' or `insert'; if it is omitted or nil,
332it defaults to `insert'."
330 (setq mode (or mode 'insert)) 333 (setq mode (or mode 'insert))
331 (cond 334 (cond
332 ((stringp target) 335 ((stringp target)
@@ -367,7 +370,7 @@ MODE is either `overwrite', `append' or `insert'."
367 (if (eq mode 'overwrite) 370 (if (eq mode 'overwrite)
368 (set target nil)) 371 (set target nil))
369 target) 372 target)
370 ((or (processp target) 373 ((or (eshell-processp target)
371 (markerp target)) 374 (markerp target))
372 target) 375 target)
373 (t 376 (t
@@ -394,7 +397,7 @@ MODE is either `overwrite', `append' or `insert'."
394 (if (and (listp current) 397 (if (and (listp current)
395 (not (member where current))) 398 (not (member where current)))
396 (setq current (append current (list where))) 399 (setq current (append current (list where)))
397 (setq current (list where))) 400 (setq current where))
398 (if (not (aref eshell-current-handles index)) 401 (if (not (aref eshell-current-handles index))
399 (aset eshell-current-handles index (cons nil 1))) 402 (aset eshell-current-handles index (cons nil 1)))
400 (setcar (aref eshell-current-handles index) current))))) 403 (setcar (aref eshell-current-handles index) current)))))
@@ -438,20 +441,20 @@ after all printing is over with no argument."
438 eshell-print-queue-count (1+ eshell-print-queue-count)))) 441 eshell-print-queue-count (1+ eshell-print-queue-count))))
439 442
440(defsubst eshell-print (object) 443(defsubst eshell-print (object)
441 "Output OBJECT to the error handle." 444 "Output OBJECT to the standard output handle."
442 (eshell-output-object object eshell-output-handle)) 445 (eshell-output-object object eshell-output-handle))
443 446
444(defsubst eshell-error (object) 447(defsubst eshell-error (object)
445 "Output OBJECT to the error handle." 448 "Output OBJECT to the standard error handle."
446 (eshell-output-object object eshell-error-handle)) 449 (eshell-output-object object eshell-error-handle))
447 450
448(defsubst eshell-errorn (object) 451(defsubst eshell-errorn (object)
449 "Output OBJECT to the error handle." 452 "Output OBJECT followed by a newline to the standard error handle."
450 (eshell-error object) 453 (eshell-error object)
451 (eshell-error "\n")) 454 (eshell-error "\n"))
452 455
453(defsubst eshell-printn (object) 456(defsubst eshell-printn (object)
454 "Output OBJECT to the error handle." 457 "Output OBJECT followed by a newline to the standard output handle."
455 (eshell-print object) 458 (eshell-print object)
456 (eshell-print "\n")) 459 (eshell-print "\n"))
457 460
@@ -485,7 +488,7 @@ Returns what was actually sent, or nil if nothing was sent."
485 (if moving 488 (if moving
486 (goto-char target)))))) 489 (goto-char target))))))
487 490
488 ((processp target) 491 ((eshell-processp target)
489 (when (eq (process-status target) 'run) 492 (when (eq (process-status target) 'run)
490 (setq object (eshell-stringify object)) 493 (setq object (eshell-stringify object))
491 (process-send-string target object))) 494 (process-send-string target object)))
diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el
index 0bb07734c14..2db4f2a10b6 100644
--- a/lisp/eshell/esh-mode.el
+++ b/lisp/eshell/esh-mode.el
@@ -474,6 +474,7 @@ sessions, such as when using `eshell-command'.")
474(defun eshell-find-tag (&optional tagname next-p regexp-p) 474(defun eshell-find-tag (&optional tagname next-p regexp-p)
475 "A special version of `find-tag' that ignores read-onlyness." 475 "A special version of `find-tag' that ignores read-onlyness."
476 (interactive) 476 (interactive)
477 (require 'etags)
477 (let ((inhibit-read-only t) 478 (let ((inhibit-read-only t)
478 (no-default (eobp))) 479 (no-default (eobp)))
479 (setq tagname (find-tag-interactive "Find tag: " no-default)) 480 (setq tagname (find-tag-interactive "Find tag: " no-default))
diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el
index ead49e1942f..ddb2c986a96 100644
--- a/lisp/eshell/esh-proc.el
+++ b/lisp/eshell/esh-proc.el
@@ -125,14 +125,15 @@ information, for example."
125 "Reset the command input location after a process terminates. 125 "Reset the command input location after a process terminates.
126The signals which will cause this to happen are matched by 126The signals which will cause this to happen are matched by
127`eshell-reset-signals'." 127`eshell-reset-signals'."
128 (if (string-match eshell-reset-signals status) 128 (if (and (stringp status)
129 (string-match eshell-reset-signals status))
129 (eshell-reset))) 130 (eshell-reset)))
130 131
131(defun eshell-wait-for-process (&rest procs) 132(defun eshell-wait-for-process (&rest procs)
132 "Wait until PROC has successfully completed." 133 "Wait until PROC has successfully completed."
133 (while procs 134 (while procs
134 (let ((proc (car procs))) 135 (let ((proc (car procs)))
135 (when (processp proc) 136 (when (eshell-processp proc)
136 ;; NYI: If the process gets stopped here, that's bad. 137 ;; NYI: If the process gets stopped here, that's bad.
137 (while (assq proc eshell-process-list) 138 (while (assq proc eshell-process-list)
138 (if (input-pending-p) 139 (if (input-pending-p)
@@ -145,7 +146,8 @@ The signals which will cause this to happen are matched by
145 146
146(defun eshell/jobs (&rest args) 147(defun eshell/jobs (&rest args)
147 "List processes, if there are any." 148 "List processes, if there are any."
148 (and (process-list) 149 (and (fboundp 'process-list)
150 (process-list)
149 (list-processes))) 151 (list-processes)))
150 152
151(defun eshell/kill (&rest args) 153(defun eshell/kill (&rest args)
@@ -153,7 +155,7 @@ The signals which will cause this to happen are matched by
153 (let ((ptr args) 155 (let ((ptr args)
154 (signum 'SIGINT)) 156 (signum 'SIGINT))
155 (while ptr 157 (while ptr
156 (if (or (processp (car ptr)) 158 (if (or (eshell-processp (car ptr))
157 (and (stringp (car ptr)) 159 (and (stringp (car ptr))
158 (string-match "^[A-Za-z/][A-Za-z0-9<>/]+$" 160 (string-match "^[A-Za-z/][A-Za-z0-9<>/]+$"
159 (car ptr)))) 161 (car ptr))))
@@ -162,7 +164,7 @@ The signals which will cause this to happen are matched by
162 (setcar ptr (get-process (car ptr)))) 164 (setcar ptr (get-process (car ptr))))
163 (setq ptr (cdr ptr))) 165 (setq ptr (cdr ptr)))
164 (while args 166 (while args
165 (let ((id (if (processp (car args)) 167 (let ((id (if (eshell-processp (car args))
166 (process-id (car args)) 168 (process-id (car args))
167 (car args)))) 169 (car args))))
168 (when id 170 (when id
@@ -206,7 +208,7 @@ The prompt will be set to PROMPT."
206 208
207(defsubst eshell-record-process-object (object) 209(defsubst eshell-record-process-object (object)
208 "Record OBJECT as now running." 210 "Record OBJECT as now running."
209 (if (and (processp object) 211 (if (and (eshell-processp object)
210 eshell-current-subjob-p) 212 eshell-current-subjob-p)
211 (eshell-interactive-print 213 (eshell-interactive-print
212 (format "[%s] %d\n" (process-name object) (process-id object)))) 214 (format "[%s] %d\n" (process-name object) (process-id object))))
@@ -217,7 +219,7 @@ The prompt will be set to PROMPT."
217 219
218(defun eshell-remove-process-entry (entry) 220(defun eshell-remove-process-entry (entry)
219 "Record the process ENTRY as fully completed." 221 "Record the process ENTRY as fully completed."
220 (if (and (processp (car entry)) 222 (if (and (eshell-processp (car entry))
221 (nth 2 entry) 223 (nth 2 entry)
222 eshell-done-messages-in-minibuffer) 224 eshell-done-messages-in-minibuffer)
223 (message (format "[%s]+ Done %s" (process-name (car entry)) 225 (message (format "[%s]+ Done %s" (process-name (car entry))
@@ -225,6 +227,12 @@ The prompt will be set to PROMPT."
225 (setq eshell-process-list 227 (setq eshell-process-list
226 (delq entry eshell-process-list))) 228 (delq entry eshell-process-list)))
227 229
230(defvar eshell-scratch-buffer " *eshell-scratch*"
231 "Scratch buffer for holding Eshell's input/output.")
232(defvar eshell-last-sync-output-start nil
233 "A marker that tracks the beginning of output of the last subprocess.
234Used only on systems which do not support async subprocesses.")
235
228(defun eshell-gather-process-output (command args) 236(defun eshell-gather-process-output (command args)
229 "Gather the output from COMMAND + ARGS." 237 "Gather the output from COMMAND + ARGS."
230 (unless (and (file-executable-p command) 238 (unless (and (file-executable-p command)
@@ -235,39 +243,88 @@ The prompt will be set to PROMPT."
235 eshell-delete-exited-processes 243 eshell-delete-exited-processes
236 delete-exited-processes)) 244 delete-exited-processes))
237 (process-environment (eshell-environment-variables)) 245 (process-environment (eshell-environment-variables))
238 (proc (apply 'start-process 246 proc decoding encoding changed)
239 (file-name-nondirectory command) nil 247 (cond
240 ;; `start-process' can't deal with relative 248 ((fboundp 'start-process)
241 ;; filenames 249 (setq proc
242 (append (list (expand-file-name command)) args))) 250 (apply 'start-process
243 decoding encoding changed) 251 (file-name-nondirectory command) nil
244 (eshell-record-process-object proc) 252 ;; `start-process' can't deal with relative
245 (set-process-buffer proc (current-buffer)) 253 ;; filenames
246 (if (eshell-interactive-output-p) 254 (append (list (expand-file-name command)) args)))
247 (set-process-filter proc 'eshell-output-filter) 255 (eshell-record-process-object proc)
248 (set-process-filter proc 'eshell-insertion-filter)) 256 (set-process-buffer proc (current-buffer))
249 (set-process-sentinel proc 'eshell-sentinel) 257 (if (eshell-interactive-output-p)
250 (run-hook-with-args 'eshell-exec-hook proc) 258 (set-process-filter proc 'eshell-output-filter)
251 (when (fboundp 'process-coding-system) 259 (set-process-filter proc 'eshell-insertion-filter))
252 (let ((coding-systems (process-coding-system proc))) 260 (set-process-sentinel proc 'eshell-sentinel)
253 (setq decoding (car coding-systems) 261 (run-hook-with-args 'eshell-exec-hook proc)
254 encoding (cdr coding-systems))) 262 (when (fboundp 'process-coding-system)
255 ;; If start-process decided to use some coding system for 263 (let ((coding-systems (process-coding-system proc)))
256 ;; decoding data sent from the process and the coding system 264 (setq decoding (car coding-systems)
257 ;; doesn't specify EOL conversion, we had better convert CRLF 265 encoding (cdr coding-systems)))
258 ;; to LF. 266 ;; If start-process decided to use some coding system for
259 (if (vectorp (coding-system-eol-type decoding)) 267 ;; decoding data sent from the process and the coding system
260 (setq decoding (coding-system-change-eol-conversion decoding 'dos) 268 ;; doesn't specify EOL conversion, we had better convert CRLF
261 changed t)) 269 ;; to LF.
262 ;; Even if start-process left the coding system for encoding 270 (if (vectorp (coding-system-eol-type decoding))
263 ;; data sent from the process undecided, we had better use the 271 (setq decoding (coding-system-change-eol-conversion decoding 'dos)
264 ;; same one as what we use for decoding. But, we should 272 changed t))
265 ;; suppress EOL conversion. 273 ;; Even if start-process left the coding system for encoding
266 (if (and decoding (not encoding)) 274 ;; data sent from the process undecided, we had better use the
267 (setq encoding (coding-system-change-eol-conversion decoding 'unix) 275 ;; same one as what we use for decoding. But, we should
268 changed t)) 276 ;; suppress EOL conversion.
269 (if changed 277 (if (and decoding (not encoding))
270 (set-process-coding-system proc decoding encoding))) 278 (setq encoding (coding-system-change-eol-conversion decoding 'unix)
279 changed t))
280 (if changed
281 (set-process-coding-system proc decoding encoding))))
282 (t
283 ;; No async subprocesses...
284 (let ((oldbuf (current-buffer))
285 (interact-p (eshell-interactive-output-p))
286 lbeg lend line proc-buf exit-status)
287 (and (not (markerp eshell-last-sync-output-start))
288 (setq eshell-last-sync-output-start (point-marker)))
289 (setq proc-buf
290 (set-buffer (get-buffer-create eshell-scratch-buffer)))
291 (erase-buffer)
292 (set-buffer oldbuf)
293 (run-hook-with-args 'eshell-exec-hook command)
294 (setq exit-status
295 (apply 'call-process-region
296 (append (list eshell-last-sync-output-start (point)
297 command t
298 eshell-scratch-buffer nil)
299 args)))
300 ;; When in a pipeline, record the place where the output of
301 ;; this process will begin.
302 (and eshell-in-pipeline-p
303 (set-marker eshell-last-sync-output-start (point)))
304 ;; Simulate the effect of the process filter.
305 (when (numberp exit-status)
306 (set-buffer proc-buf)
307 (goto-char (point-min))
308 (setq lbeg (point))
309 (while (eq 0 (forward-line 1))
310 (setq lend (point)
311 line (buffer-substring-no-properties lbeg lend))
312 (set-buffer oldbuf)
313 (if interact-p
314 (eshell-output-filter nil line)
315 (eshell-output-object line))
316 (setq lbeg lend)
317 (set-buffer proc-buf))
318 (set-buffer oldbuf))
319 (eshell-update-markers eshell-last-output-end)
320 ;; Simulate the effect of eshell-sentinel.
321 (eshell-close-handles (if (numberp exit-status) exit-status -1))
322 (run-hook-with-args 'eshell-kill-hook command exit-status)
323 (or eshell-in-pipeline-p
324 (setq eshell-last-sync-output-start nil))
325 (if (not (numberp exit-status))
326 (error "%s: external command failed: %s" command exit-status))
327 (setq proc t))))
271 proc)) 328 proc))
272 329
273(defun eshell-insertion-filter (proc string) 330(defun eshell-insertion-filter (proc string)
diff --git a/lisp/eshell/esh-util.el b/lisp/eshell/esh-util.el
index de19b636100..3d650928c62 100644
--- a/lisp/eshell/esh-util.el
+++ b/lisp/eshell/esh-util.el
@@ -262,7 +262,7 @@ If N or M is nil, it means the end of the list."
262 262
263(put 'eshell-for 'lisp-indent-function 2) 263(put 'eshell-for 'lisp-indent-function 2)
264 264
265(defsubst eshell-flatten-list (args) 265(defun eshell-flatten-list (args)
266 "Flatten any lists within ARGS, so that there are no sublists." 266 "Flatten any lists within ARGS, so that there are no sublists."
267 (let ((new-list (list t))) 267 (let ((new-list (list t)))
268 (eshell-for a args 268 (eshell-for a args
diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el
index 133239703b6..34994630251 100644
--- a/lisp/eshell/esh-var.el
+++ b/lisp/eshell/esh-var.el
@@ -264,7 +264,7 @@ function), and the arguments passed to this function would be the list
264 "Parse a variable interpolation. 264 "Parse a variable interpolation.
265This function is explicit for adding to `eshell-parse-argument-hook'." 265This function is explicit for adding to `eshell-parse-argument-hook'."
266 (when (and (eq (char-after) ?$) 266 (when (and (eq (char-after) ?$)
267 (not (= (1+ (point)) (point-max)))) 267 (/= (1+ (point)) (point-max)))
268 (forward-char) 268 (forward-char)
269 (list 'eshell-escape-arg 269 (list 'eshell-escape-arg
270 (eshell-parse-variable)))) 270 (eshell-parse-variable))))
@@ -293,11 +293,19 @@ This function is explicit for adding to `eshell-parse-argument-hook'."
293(defun eshell/export (&rest sets) 293(defun eshell/export (&rest sets)
294 "This alias allows the 'export' command to act as bash users expect." 294 "This alias allows the 'export' command to act as bash users expect."
295 (while sets 295 (while sets
296 (if (string-match "^\\([^=]+\\)=\\(.*\\)" (car sets)) 296 (if (and (stringp (car sets))
297 (string-match "^\\([^=]+\\)=\\(.*\\)" (car sets)))
297 (setenv (match-string 1 (car sets)) 298 (setenv (match-string 1 (car sets))
298 (match-string 2 (car sets)))) 299 (match-string 2 (car sets))))
299 (setq sets (cdr sets)))) 300 (setq sets (cdr sets))))
300 301
302(defun eshell/unset (&rest args)
303 "Unset an environment variable."
304 (while args
305 (if (stringp (car args))
306 (setenv (car args) nil t))
307 (setq args (cdr args))))
308
301(defun pcomplete/eshell-mode/export () 309(defun pcomplete/eshell-mode/export ()
302 "Completion function for Eshell's `export'." 310 "Completion function for Eshell's `export'."
303 (while (pcomplete-here 311 (while (pcomplete-here
diff --git a/lisp/pcmpl-gnu.el b/lisp/pcmpl-gnu.el
index f390f541e25..f7a681c803e 100644
--- a/lisp/pcmpl-gnu.el
+++ b/lisp/pcmpl-gnu.el
@@ -33,7 +33,7 @@
33;; User Variables: 33;; User Variables:
34 34
35(defcustom pcmpl-gnu-makefile-regexps 35(defcustom pcmpl-gnu-makefile-regexps
36 '("\\`Makefile\\." "\\.mak\\'") 36 '("\\`GNUmakefile" "\\`Makefile" "\\.mak\\'")
37 "*A list of regexps that will match Makefile names." 37 "*A list of regexps that will match Makefile names."
38 :type '(repeat regexp) 38 :type '(repeat regexp)
39 :group 'pcmpl-gnu) 39 :group 'pcmpl-gnu)
@@ -111,7 +111,10 @@
111(defun pcmpl-gnu-make-rule-names () 111(defun pcmpl-gnu-make-rule-names ()
112 "Return a list of possible make rule names in MAKEFILE." 112 "Return a list of possible make rule names in MAKEFILE."
113 (let* ((minus-f (member "-f" pcomplete-args)) 113 (let* ((minus-f (member "-f" pcomplete-args))
114 (makefile (or (cadr minus-f) "Makefile")) 114 (makefile (or (cadr minus-f)
115 (if (file-exists-p "GNUmakefile")
116 "GNUmakefile"
117 "Makefile")))
115 rules) 118 rules)
116 (if (not (file-readable-p makefile)) 119 (if (not (file-readable-p makefile))
117 (unless minus-f (list "-f")) 120 (unless minus-f (list "-f"))
diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el
index 2b66b1d45b9..4f506212230 100644
--- a/lisp/pcomplete.el
+++ b/lisp/pcomplete.el
@@ -303,6 +303,14 @@ This function is used to generate completions for every argument."
303 :type 'function 303 :type 'function
304 :group 'pcomplete) 304 :group 'pcomplete)
305 305
306(defcustom pcomplete-use-paring t
307 "*If t, pare alternatives that have already been used.
308If nil, you will always see the completion set of possible options, no
309matter which of those options have already been used in previous
310command arguments."
311 :type 'boolean
312 :group 'pcomplete)
313
306;;; Internal Variables: 314;;; Internal Variables:
307 315
308;; for cycling completion support 316;; for cycling completion support
@@ -1017,7 +1025,7 @@ extra checking, and munging of the COMPLETIONS list."
1017 (message "No completions of %s" stub) 1025 (message "No completions of %s" stub)
1018 (message "No completions"))) 1026 (message "No completions")))
1019 ;; pare it down, if applicable 1027 ;; pare it down, if applicable
1020 (if pcomplete-seen 1028 (if (and pcomplete-use-paring pcomplete-seen)
1021 (let* ((arg (pcomplete-arg)) 1029 (let* ((arg (pcomplete-arg))
1022 (prefix 1030 (prefix
1023 (file-name-as-directory 1031 (file-name-as-directory