diff options
author | John Wiegley <johnw@newartisans.com> | 2000-08-29 00:47:45 +0000 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2000-08-29 00:47:45 +0000 |
commit | ca7aae916bab6783c5133d8432b61d97b8ffa923 (patch) | |
tree | 1b36d8d391a6a0c166fd27a01acbc92a92020530 /lisp | |
parent | b4bd214e74d885552fe38051253dbc2b362bfe67 (diff) | |
download | emacs-ca7aae916bab6783c5133d8432b61d97b8ffa923.tar.gz |
See ChangeLog
Diffstat (limited to 'lisp')
-rw-r--r-- | lisp/ChangeLog | 4 | ||||
-rw-r--r-- | lisp/align.el | 6 | ||||
-rw-r--r-- | lisp/eshell/em-cmpl.el | 9 | ||||
-rw-r--r-- | lisp/eshell/em-dirs.el | 6 | ||||
-rw-r--r-- | lisp/eshell/em-hist.el | 14 | ||||
-rw-r--r-- | lisp/eshell/em-ls.el | 2 | ||||
-rw-r--r-- | lisp/eshell/em-rebind.el | 2 | ||||
-rw-r--r-- | lisp/eshell/em-smart.el | 23 | ||||
-rw-r--r-- | lisp/eshell/em-unix.el | 94 | ||||
-rw-r--r-- | lisp/eshell/em-xtra.el | 2 | ||||
-rw-r--r-- | lisp/eshell/esh-cmd.el | 162 | ||||
-rw-r--r-- | lisp/eshell/esh-ext.el | 6 | ||||
-rw-r--r-- | lisp/eshell/esh-io.el | 27 | ||||
-rw-r--r-- | lisp/eshell/esh-mode.el | 1 | ||||
-rw-r--r-- | lisp/eshell/esh-proc.el | 137 | ||||
-rw-r--r-- | lisp/eshell/esh-util.el | 2 | ||||
-rw-r--r-- | lisp/eshell/esh-var.el | 12 | ||||
-rw-r--r-- | lisp/pcmpl-gnu.el | 7 | ||||
-rw-r--r-- | lisp/pcomplete.el | 10 |
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 @@ 2000-08-28 John Wiegley <johnw@gnu.org> + * eshell/esh-util.el (eshell-flatten-list): It's not too wise to + have a defsubst call itself. Made `eshell-flatten-list' back into + a function again. + * eshell/em-smart.el (eshell-smart-redisplay): Added a safety catch, in case re-centering point at bottom messes up the display. 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." (interactive "r") (let ((separator (or separate - (if (symbolp align-region-separate) + (if (and (symbolp align-region-separate) + (boundp align-region-separate)) (symbol-value align-region-separate) align-region-separate) 'entire))) @@ -1038,7 +1039,8 @@ to be colored." (defun align-newline-and-indent () "A replacement function for `newline-and-indent', aligning as it goes." (interactive) - (let ((separate (or (if (symbolp align-region-separate) + (let ((separate (or (if (and (symbolp align-region-separate) + (boundp align-region-separate)) (symbol-value align-region-separate) align-region-separate) '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." (documentation-property 'pcomplete-default-completion-function 'variable-documentation) :type (get 'pcomplete-default-completion-function 'custom-type) - :group 'pcomplete) + :group 'eshell-cmpl) + +(defcustom eshell-cmpl-use-paring t + (documentation-property 'pcomplete-use-paring 'variable-documentation) + :type (get 'pcomplete-use-paring 'custom-type) + :group 'eshell-cmpl) ;;; Functions: @@ -265,6 +270,8 @@ to writing a completion function." eshell-cmpl-cycle-cutoff-length) (set (make-local-variable 'pcomplete-restore-window-delay) eshell-cmpl-restore-window-delay) + (set (make-local-variable 'pcomplete-use-paring) + eshell-cmpl-use-paring) ;; `pcomplete-arg-quote-list' should only be set after all the ;; load-hooks for any other extension modules have been run, which ;; 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: (index 0)) (if (= len 0) (error "Directory ring empty")) + (eshell-init-print-buffer) (while (< index len) - (eshell-printn + (eshell-buffered-print (concat (number-to-string index) ": " - (ring-ref eshell-last-dir-ring index))) + (ring-ref eshell-last-dir-ring index) "\n")) (setq index (1+ index))) + (eshell-flush) (setq handled t))))) (path (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.") (defun eshell-put-history (input &optional ring at-beginning) "Put a new input line into the history ring." (unless ring (setq ring eshell-history-ring)) - (subst-char-in-string ?\n ?\177 input t) (if at-beginning (ring-insert-at-beginning ring input) (ring-insert ring input))) (defun eshell-get-history (index &optional ring) "Get an input line from the history ring." - (unless ring (setq ring eshell-history-ring)) - (let ((input (concat (ring-ref ring index)))) - (subst-char-in-string ?\177 ?\n input t) - input)) + (ring-ref (or ring eshell-history-ring) index)) (defun eshell-add-to-history () "Add INPUT to the history ring. @@ -419,7 +415,8 @@ line, with the most recent command last. See also (if (or (null ignore-dups) (ring-empty-p ring) (not (string-equal (ring-ref ring 0) history))) - (ring-insert-at-beginning ring history))) + (ring-insert-at-beginning + ring (subst-char-in-string ?\177 ?\n history)))) (setq count (1+ count)))) (setq eshell-history-ring ring eshell-history-index nil)))))) @@ -451,7 +448,9 @@ See also `eshell-read-history'." (with-temp-buffer (while (> index 0) (setq index (1- index)) - (insert (ring-ref ring index) ?\n)) + (let ((start (point))) + (insert (ring-ref ring index) ?\n) + (subst-char-in-region start (1- (point)) ?\n ?\177))) (eshell-with-private-file-modes (write-region (point-min) (point-max) file append 'no-message)))))))) @@ -891,7 +890,6 @@ If N is negative, search backwards for the -Nth previous match." (goto-char eshell-last-output-end) (delete-region (point) (point-max)) (when (and text (> (length text) 0)) - (subst-char-in-string ?\177 ?\n text t) (insert text) (put-text-property (1- (point)) (point) '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." ((not (eshell-ls-filetype-p (cdr file) ?-)) 'eshell-ls-special-face) - ((and (not (= (user-uid) 0)) ; root can execute anything + ((and (/= (user-uid) 0) ; root can execute anything (eshell-ls-applicable (cdr file) 3 'file-executable-p (car file))) '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." (let ((proc (get-buffer-process (current-buffer)))) (if (eobp) (cond - ((not (= (point) eshell-last-output-end)) + ((/= (point) eshell-last-output-end) (beep)) (proc (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." "Display as much output as possible, smartly." (if (eobp) (recenter -1) - (and (memq 'eshell-smart-display-move pre-command-hook) - (>= (point) eshell-last-input-start) - (< (point) eshell-last-input-end) - (set-window-start (selected-window) - (line-beginning-position) t)) - (if (pos-visible-in-window-p (point-max)) - (save-excursion - (goto-char (point-max)) - (recenter -1))))) + (let ((top-point (point))) + (and (memq 'eshell-smart-display-move pre-command-hook) + (>= (point) eshell-last-input-start) + (< (point) eshell-last-input-end) + (set-window-start (selected-window) + (line-beginning-position) t)) + (if (pos-visible-in-window-p (point-max)) + (save-excursion + (goto-char (point-max)) + (recenter -1) + (unless (pos-visible-in-window-p top-point) + (goto-char top-point) + (set-window-start (selected-window) + (line-beginning-position) t))))))) (defun eshell-smart-goto-end () "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." :type 'boolean :group 'eshell-unix) -(defcustom eshell-ln-overwrite-files t +(defcustom eshell-ln-overwrite-files nil "*If non-nil, `ln' will overwrite files without warning." :type 'boolean :group 'eshell-unix) @@ -224,7 +224,7 @@ Remove (unlink) the FILE(s).") (not (y-or-n-p (format "rm: delete buffer `%s'? " entry))))) (eshell-funcalln 'kill-buffer entry))) - ((processp entry) + ((eshell-processp entry) (if verbose (eshell-printn (format "rm: killing process `%s'" entry))) (unless (or preview @@ -353,13 +353,14 @@ Remove the DIRECTORY(ies), if they are empty.") command target))) (unless preview (eshell-funcalln 'make-directory target))) - (eshell-shuffle-files command action - (mapcar - (function - (lambda (file) - (concat source "/" file))) - (directory-files source)) - target func t args) + (apply 'eshell-shuffle-files + command action + (mapcar + (function + (lambda (file) + (concat source "/" file))) + (directory-files source)) + target func t args) (when (eq func 'rename-file) (if verbose (eshell-printn @@ -527,7 +528,7 @@ with '--symbolic'. When creating hard links, each TARGET must exist.") "Implementation of cat in Lisp." (if eshell-in-pipeline-p (throw 'eshell-replace-command - (eshell-parse-command "*cat" args)) + (eshell-parse-command "*cat" (eshell-flatten-list args))) (eshell-init-print-buffer) (eshell-eval-using-options "cat" args @@ -568,7 +569,7 @@ Concatenate FILE(s), or standard input, to standard output.") (list 'quote (eshell-copy-environment)))))) (compile (concat "make " (eshell-flatten-and-stringify args)))) (throw 'eshell-replace-command - (eshell-parse-command "*make" args)))) + (eshell-parse-command "*make" (eshell-flatten-list args))))) (defun eshell-occur-mode-goto-occurrence () "Go to the occurrence the current line describes." @@ -644,7 +645,8 @@ external command." (not eshell-in-pipeline-p) (not eshell-in-subcommand-p)))) (throw 'eshell-replace-command - (eshell-parse-command (concat "*" command) args)) + (eshell-parse-command (concat "*" command) + (eshell-flatten-list args))) (let* ((compilation-process-setup-function (list 'lambda nil (list 'setq 'process-environment @@ -745,8 +747,8 @@ external command." (cadr (car entries))))) (unless (or (and symlink (not dereference-links)) (and only-one-filesystem - (not (= only-one-filesystem - (nth 12 (car entries)))))) + (/= only-one-filesystem + (nth 12 (car entries))))) (if symlink (setq entry symlink)) (setq size @@ -769,10 +771,10 @@ external command." size)) (defun eshell/du (&rest args) - "Implementation of \"du\" in Lisp, passing RAGS." + "Implementation of \"du\" in Lisp, passing ARGS." (if (eshell-search-path "du") (throw 'eshell-replace-command - (eshell-parse-command "*du" args)) + (eshell-parse-command "*du" (eshell-flatten-list args))) (eshell-eval-using-options "du" args '((?a "all" nil show-all @@ -875,32 +877,38 @@ Show wall-clock time elapsed during execution of COMMAND.") (defun eshell/diff (&rest args) "Alias \"diff\" to call Emacs `diff' function." - (if (or eshell-plain-diff-behavior - (not (and (eshell-interactive-output-p) - (not eshell-in-pipeline-p) - (not eshell-in-subcommand-p)))) - (throw 'eshell-replace-command - (eshell-parse-command "*diff" args)) - (setq args (eshell-flatten-list args)) - (if (< (length args) 2) - (error "diff: missing operand")) - (let ((old (car (last args 2))) - (new (car (last args))) - (config (current-window-configuration))) - (if (= (length args) 2) - (setq args nil) - (setcdr (last args 3) nil)) - (with-current-buffer - (diff old new (eshell-flatten-and-stringify args)) - (when (fboundp 'diff-mode) - (diff-mode) - (set (make-local-variable 'eshell-diff-window-config) config) - (local-set-key [?q] 'eshell-diff-quit) - (if (fboundp 'turn-on-font-lock-if-enabled) - (turn-on-font-lock-if-enabled)))) - (other-window 1) - (goto-char (point-min)) - nil))) + (let ((orig-args (eshell-flatten-list args))) + (if (or eshell-plain-diff-behavior + (not (and (eshell-interactive-output-p) + (not eshell-in-pipeline-p) + (not eshell-in-subcommand-p)))) + (throw 'eshell-replace-command + (eshell-parse-command "*diff" orig-args)) + (setq args (eshell-copy-list orig-args)) + (if (< (length args) 2) + (throw 'eshell-replace-command + (eshell-parse-command "*diff" orig-args))) + (let ((old (car (last args 2))) + (new (car (last args))) + (config (current-window-configuration))) + (if (= (length args) 2) + (setq args nil) + (setcdr (last args 3) nil)) + (with-current-buffer + (condition-case err + (diff old new (eshell-flatten-and-stringify args)) + (error + (throw 'eshell-replace-command + (eshell-parse-command "*diff" orig-args)))) + (when (fboundp 'diff-mode) + (diff-mode) + (set (make-local-variable 'eshell-diff-window-config) config) + (local-set-key [?q] 'eshell-diff-quit) + (if (fboundp 'turn-on-font-lock-if-enabled) + (turn-on-font-lock-if-enabled)))) + (other-window 1) + (goto-char (point-min)) + nil)))) (defun eshell/locate (&rest args) "Alias \"locate\" to call Emacs `locate' function." @@ -911,7 +919,7 @@ Show wall-clock time elapsed during execution of COMMAND.") (and (stringp (car args)) (string-match "^-" (car args)))) (throw 'eshell-replace-command - (eshell-parse-command "*locate" args)) + (eshell-parse-command "*locate" (eshell-flatten-list args))) (save-selected-window (let ((locate-history-list (list (car args)))) (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." "Implementation of expr, using the calc package." (if (not (fboundp 'calc-eval)) (throw 'eshell-replace-command - (eshell-parse-command "*expr" args)) + (eshell-parse-command "*expr" (eshell-flatten-list args))) ;; to fool the byte-compiler... (let ((func 'calc-eval)) (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." (list 'car (list 'symbol-value (list 'quote 'for-items))))) - (list 'eshell-protect - (eshell-invokify-arg body t))) + (list 'eshell-copy-handles + (eshell-invokify-arg body t))) (list 'setcar 'for-items (list 'cadr (list 'symbol-value @@ -581,7 +581,7 @@ must be implemented via rewriting, rather than as a function." (eshell-structure-basic-command 'while '("while" "until") (car terms) (eshell-invokify-arg (cadr terms) nil t) - (list 'eshell-protect + (list 'eshell-copy-handles (eshell-invokify-arg (car (last terms)) t))))) (defun eshell-rewrite-if-command (terms) @@ -770,6 +770,31 @@ this grossness will be made to disappear by using `call/cc'..." (eshell-errorn (error-message-string err)) (eshell-close-handles 1))))) +;; (defun eshell-copy-or-protect-handles () +;; (if (eshell-processp (car (aref eshell-current-handles +;; eshell-output-handle))) +;; (eshell-protect-handles eshell-current-handles) +;; (eshell-create-handles +;; (car (aref eshell-current-handles +;; eshell-output-handle)) nil +;; (car (aref eshell-current-handles +;; eshell-error-handle)) nil))) + +;; (defmacro eshell-copy-handles (object) +;; "Duplicate current I/O handles, so OBJECT works with its own copy." +;; `(let ((eshell-current-handles (eshell-copy-or-protect-handles))) +;; ,object)) + +(defmacro eshell-copy-handles (object) + "Duplicate current I/O handles, so OBJECT works with its own copy." + `(let ((eshell-current-handles + (eshell-create-handles + (car (aref eshell-current-handles + eshell-output-handle)) nil + (car (aref eshell-current-handles + eshell-error-handle)) nil))) + ,object)) + (defmacro eshell-protect (object) "Protect I/O handles, so they aren't get closed after eval'ing OBJECT." `(progn @@ -779,32 +804,65 @@ this grossness will be made to disappear by using `call/cc'..." (defmacro eshell-do-pipelines (pipeline) "Execute the commands in PIPELINE, connecting each to one another." (when (setq pipeline (cadr pipeline)) - `(let ((eshell-current-handles - (eshell-create-handles - (car (aref eshell-current-handles - eshell-output-handle)) nil - (car (aref eshell-current-handles - eshell-error-handle)) nil))) + `(eshell-copy-handles + (progn + ,(when (cdr pipeline) + `(let (nextproc) + (progn + (set 'nextproc + (eshell-do-pipelines (quote ,(cdr pipeline)))) + (eshell-set-output-handle ,eshell-output-handle + 'append nextproc) + (eshell-set-output-handle ,eshell-error-handle + 'append nextproc) + (set 'tailproc (or tailproc nextproc))))) + ,(let ((head (car pipeline))) + (if (memq (car head) '(let progn)) + (setq head (car (last head)))) + (when (memq (car head) eshell-deferrable-commands) + (ignore + (setcar head + (intern-soft + (concat (symbol-name (car head)) "*")))))) + ,(car pipeline))))) + +(defmacro eshell-do-pipelines-synchronously (pipeline) + "Execute the commands in PIPELINE in sequence synchronously. +Output of each command is passed as input to the next one in the pipeline. +This is used on systems where `start-process' is not supported." + (when (setq pipeline (cadr pipeline)) + `(let (result) (progn ,(when (cdr pipeline) - `(let (nextproc) + `(let (output-marker) (progn - (set 'nextproc - (eshell-do-pipelines (quote ,(cdr pipeline)))) + (set 'output-marker ,(point-marker)) (eshell-set-output-handle ,eshell-output-handle - 'append nextproc) + 'append output-marker) (eshell-set-output-handle ,eshell-error-handle - 'append nextproc) - (set 'tailproc (or tailproc nextproc))))) + 'append output-marker)))) ,(let ((head (car pipeline))) (if (memq (car head) '(let progn)) (setq head (car (last head)))) + ;;; FIXME: is deferrable significant here? (when (memq (car head) eshell-deferrable-commands) (ignore (setcar head (intern-soft (concat (symbol-name (car head)) "*")))))) - ,(car pipeline))))) + ;; The last process in the pipe should get its handles + ;; redirected as we found them before running the pipe. + ,(if (null (cdr pipeline)) + `(progn + (set 'eshell-current-handles tail-handles) + (set 'eshell-in-pipeline-p nil))) + (set 'result ,(car pipeline)) + ;; tailproc gets the result of the last successful process in + ;; the pipeline. + (set 'tailproc (or result tailproc)) + ,(if (cdr pipeline) + `(eshell-do-pipelines-synchronously (quote ,(cdr pipeline)))) + result)))) (defalias 'eshell-process-identity 'identity) @@ -812,7 +870,14 @@ this grossness will be made to disappear by using `call/cc'..." "Execute the commands in PIPELINE, connecting each to one another." `(let ((eshell-in-pipeline-p t) tailproc) (progn - (eshell-do-pipelines ,pipeline) + ,(if (fboundp 'start-process) + `(eshell-do-pipelines ,pipeline) + `(let ((tail-handles (eshell-create-handles + (car (aref eshell-current-handles + ,eshell-output-handle)) nil + (car (aref eshell-current-handles + ,eshell-error-handle)) nil))) + (eshell-do-pipelines-synchronously ,pipeline))) (eshell-process-identity tailproc)))) (defmacro eshell-as-subcommand (command) @@ -919,12 +984,19 @@ at the moment are: (erase-buffer) (insert "command: \"" input "\"\n")))) (setq eshell-current-command command) - (eshell-resume-eval))) + (let ((delim (catch 'eshell-incomplete + (eshell-resume-eval)))) + (if delim + (error "Unmatched delimiter: %c" + (if (listp delim) + (car delim) + delim)))))) (defun eshell-resume-command (proc status) "Resume the current command when a process ends." (when proc - (unless (or (string= "stopped" status) + (unless (or (not (stringp status)) + (string= "stopped" status) (string-match eshell-reset-signals status)) (if (eq proc (eshell-interactive-process)) (eshell-resume-eval))))) @@ -941,7 +1013,7 @@ at the moment are: (setq retval (eshell-do-eval eshell-current-command)))))) - (if proc + (if (eshell-processp proc) (ignore (setq eshell-last-async-proc proc)) (cadr retval))))) (error @@ -1019,38 +1091,31 @@ be finished later after the completion of an asynchronous subprocess." (when (car eshell-command-body) (assert (not synchronous-p)) (eshell-do-eval (car eshell-command-body)) - (setcar eshell-command-body nil)) + (setcar eshell-command-body nil) + (setcar eshell-test-body nil)) (unless (car eshell-test-body) (setcar eshell-test-body (eshell-copy-tree (car args)))) - (if (and (car eshell-test-body) - (not (eq (car eshell-test-body) 0))) - (while (cadr (eshell-do-eval (car eshell-test-body))) - (setcar eshell-test-body 0) - (setcar eshell-command-body (eshell-copy-tree (cadr args))) - (eshell-do-eval (car eshell-command-body) synchronous-p) - (setcar eshell-command-body nil) - (setcar eshell-test-body (eshell-copy-tree (car args))))) + (while (cadr (eshell-do-eval (car eshell-test-body))) + (setcar eshell-command-body (eshell-copy-tree (cadr args))) + (eshell-do-eval (car eshell-command-body) synchronous-p) + (setcar eshell-command-body nil) + (setcar eshell-test-body (eshell-copy-tree (car args)))) (setcar eshell-command-body nil)) ((eq (car form) 'if) ;; `eshell-copy-tree' is needed here so that the test argument ;; doesn't get modified and thus always yield the same result. - (when (car eshell-command-body) - (assert (not synchronous-p)) - (eshell-do-eval (car eshell-command-body)) - (setcar eshell-command-body nil)) - (unless (car eshell-test-body) - (setcar eshell-test-body (eshell-copy-tree (car args)))) - (if (and (car eshell-test-body) - (not (eq (car eshell-test-body) 0))) - (if (cadr (eshell-do-eval (car eshell-test-body))) - (progn - (setcar eshell-test-body 0) - (setcar eshell-command-body (eshell-copy-tree (cadr args))) - (eshell-do-eval (car eshell-command-body) synchronous-p)) - (setcar eshell-test-body 0) - (setcar eshell-command-body (eshell-copy-tree (car (cddr args)))) - (eshell-do-eval (car eshell-command-body) synchronous-p))) - (setcar eshell-command-body nil)) + (if (car eshell-command-body) + (progn + (assert (not synchronous-p)) + (eshell-do-eval (car eshell-command-body))) + (unless (car eshell-test-body) + (setcar eshell-test-body (eshell-copy-tree (car args)))) + (if (cadr (eshell-do-eval (car eshell-test-body))) + (setcar eshell-command-body (eshell-copy-tree (cadr args))) + (setcar eshell-command-body (eshell-copy-tree (car (cddr args))))) + (eshell-do-eval (car eshell-command-body) synchronous-p)) + (setcar eshell-command-body nil) + (setcar eshell-test-body nil)) ((eq (car form) 'setcar) (setcar (cdr args) (eshell-do-eval (cadr args) synchronous-p)) (eval form)) @@ -1131,7 +1196,7 @@ be finished later after the completion of an asynchronous subprocess." (if (and (memq (car form) eshell-deferrable-commands) (not eshell-current-subjob-p) result - (processp result)) + (eshell-processp result)) (if synchronous-p (eshell/wait result) (eshell-manipulate "inserting ignore form" @@ -1172,7 +1237,8 @@ be finished later after the completion of an asynchronous subprocess." (setq desc (substring desc 0 (1- (or (string-match "\n" desc) (length desc))))) - (kill-buffer "*Help*") + (if (buffer-live-p (get-buffer "*Help*")) + (kill-buffer "*Help*")) (setq program (or desc name)))))) (if (not program) (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." "Invoke a .BAT or .CMD file on DOS/Windows systems." ;; since CMD.EXE can't handle forward slashes in the initial ;; argument... - (setcar args (subst-char-in-string directory-sep-char - ?\\ (car args))) + (setcar args (subst-char-in-string directory-sep-char ?\\ (car args))) (throw 'eshell-replace-command - (eshell-parse-command eshell-windows-shell-file - (cons "/c" args)))) + (eshell-parse-command eshell-windows-shell-file (cons "/c" args)))) (defcustom eshell-interpreter-alist (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 output function. Otherwise, the second element itself is the output function. -The output function is then called repeatedly with a single strings, -with represents success pieces of the output of the command, until nil +The output function is then called repeatedly with single strings, +which represents successive pieces of the output of the command, until nil is passed, meaning EOF. NOTE: /dev/null is handled specially as a virtual target, and should @@ -231,7 +231,9 @@ not be added to this variable." (standard-output output-mode &optional standard-error error-mode) "Create a new set of file handles for a command. The default location for standard output and standard error will go to -STANDARD-OUTPUT and STANDARD-ERROR, respectively." +STANDARD-OUTPUT and STANDARD-ERROR, respectively. +OUTPUT-MODE and ERROR-MODE are either `overwrite', `append' or `insert'; +a nil value of mode defaults to `insert'." (let ((handles (make-vector eshell-number-of-handles nil)) (output-target (eshell-get-target standard-output output-mode)) (error-target (eshell-get-target standard-error error-mode))) @@ -272,7 +274,7 @@ STATUS should be non-nil on successful termination of the output." ;; If we're redirecting to a process (via a pipe, or process ;; redirection), send it EOF so that it knows we're finished. - ((processp target) + ((eshell-processp target) (if (eq (process-status target) 'run) (process-send-eof target))) @@ -326,7 +328,8 @@ last execution result should not be changed." (defun eshell-get-target (target &optional mode) "Convert TARGET, which is a raw argument, into a valid output target. -MODE is either `overwrite', `append' or `insert'." +MODE is either `overwrite', `append' or `insert'; if it is omitted or nil, +it defaults to `insert'." (setq mode (or mode 'insert)) (cond ((stringp target) @@ -367,7 +370,7 @@ MODE is either `overwrite', `append' or `insert'." (if (eq mode 'overwrite) (set target nil)) target) - ((or (processp target) + ((or (eshell-processp target) (markerp target)) target) (t @@ -394,7 +397,7 @@ MODE is either `overwrite', `append' or `insert'." (if (and (listp current) (not (member where current))) (setq current (append current (list where))) - (setq current (list where))) + (setq current where)) (if (not (aref eshell-current-handles index)) (aset eshell-current-handles index (cons nil 1))) (setcar (aref eshell-current-handles index) current))))) @@ -438,20 +441,20 @@ after all printing is over with no argument." eshell-print-queue-count (1+ eshell-print-queue-count)))) (defsubst eshell-print (object) - "Output OBJECT to the error handle." + "Output OBJECT to the standard output handle." (eshell-output-object object eshell-output-handle)) (defsubst eshell-error (object) - "Output OBJECT to the error handle." + "Output OBJECT to the standard error handle." (eshell-output-object object eshell-error-handle)) (defsubst eshell-errorn (object) - "Output OBJECT to the error handle." + "Output OBJECT followed by a newline to the standard error handle." (eshell-error object) (eshell-error "\n")) (defsubst eshell-printn (object) - "Output OBJECT to the error handle." + "Output OBJECT followed by a newline to the standard output handle." (eshell-print object) (eshell-print "\n")) @@ -485,7 +488,7 @@ Returns what was actually sent, or nil if nothing was sent." (if moving (goto-char target)))))) - ((processp target) + ((eshell-processp target) (when (eq (process-status target) 'run) (setq object (eshell-stringify object)) (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'.") (defun eshell-find-tag (&optional tagname next-p regexp-p) "A special version of `find-tag' that ignores read-onlyness." (interactive) + (require 'etags) (let ((inhibit-read-only t) (no-default (eobp))) (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." "Reset the command input location after a process terminates. The signals which will cause this to happen are matched by `eshell-reset-signals'." - (if (string-match eshell-reset-signals status) + (if (and (stringp status) + (string-match eshell-reset-signals status)) (eshell-reset))) (defun eshell-wait-for-process (&rest procs) "Wait until PROC has successfully completed." (while procs (let ((proc (car procs))) - (when (processp proc) + (when (eshell-processp proc) ;; NYI: If the process gets stopped here, that's bad. (while (assq proc eshell-process-list) (if (input-pending-p) @@ -145,7 +146,8 @@ The signals which will cause this to happen are matched by (defun eshell/jobs (&rest args) "List processes, if there are any." - (and (process-list) + (and (fboundp 'process-list) + (process-list) (list-processes))) (defun eshell/kill (&rest args) @@ -153,7 +155,7 @@ The signals which will cause this to happen are matched by (let ((ptr args) (signum 'SIGINT)) (while ptr - (if (or (processp (car ptr)) + (if (or (eshell-processp (car ptr)) (and (stringp (car ptr)) (string-match "^[A-Za-z/][A-Za-z0-9<>/]+$" (car ptr)))) @@ -162,7 +164,7 @@ The signals which will cause this to happen are matched by (setcar ptr (get-process (car ptr)))) (setq ptr (cdr ptr))) (while args - (let ((id (if (processp (car args)) + (let ((id (if (eshell-processp (car args)) (process-id (car args)) (car args)))) (when id @@ -206,7 +208,7 @@ The prompt will be set to PROMPT." (defsubst eshell-record-process-object (object) "Record OBJECT as now running." - (if (and (processp object) + (if (and (eshell-processp object) eshell-current-subjob-p) (eshell-interactive-print (format "[%s] %d\n" (process-name object) (process-id object)))) @@ -217,7 +219,7 @@ The prompt will be set to PROMPT." (defun eshell-remove-process-entry (entry) "Record the process ENTRY as fully completed." - (if (and (processp (car entry)) + (if (and (eshell-processp (car entry)) (nth 2 entry) eshell-done-messages-in-minibuffer) (message (format "[%s]+ Done %s" (process-name (car entry)) @@ -225,6 +227,12 @@ The prompt will be set to PROMPT." (setq eshell-process-list (delq entry eshell-process-list))) +(defvar eshell-scratch-buffer " *eshell-scratch*" + "Scratch buffer for holding Eshell's input/output.") +(defvar eshell-last-sync-output-start nil + "A marker that tracks the beginning of output of the last subprocess. +Used only on systems which do not support async subprocesses.") + (defun eshell-gather-process-output (command args) "Gather the output from COMMAND + ARGS." (unless (and (file-executable-p command) @@ -235,39 +243,88 @@ The prompt will be set to PROMPT." eshell-delete-exited-processes delete-exited-processes)) (process-environment (eshell-environment-variables)) - (proc (apply 'start-process - (file-name-nondirectory command) nil - ;; `start-process' can't deal with relative - ;; filenames - (append (list (expand-file-name command)) args))) - decoding encoding changed) - (eshell-record-process-object proc) - (set-process-buffer proc (current-buffer)) - (if (eshell-interactive-output-p) - (set-process-filter proc 'eshell-output-filter) - (set-process-filter proc 'eshell-insertion-filter)) - (set-process-sentinel proc 'eshell-sentinel) - (run-hook-with-args 'eshell-exec-hook proc) - (when (fboundp 'process-coding-system) - (let ((coding-systems (process-coding-system proc))) - (setq decoding (car coding-systems) - encoding (cdr coding-systems))) - ;; If start-process decided to use some coding system for - ;; decoding data sent from the process and the coding system - ;; doesn't specify EOL conversion, we had better convert CRLF - ;; to LF. - (if (vectorp (coding-system-eol-type decoding)) - (setq decoding (coding-system-change-eol-conversion decoding 'dos) - changed t)) - ;; Even if start-process left the coding system for encoding - ;; data sent from the process undecided, we had better use the - ;; same one as what we use for decoding. But, we should - ;; suppress EOL conversion. - (if (and decoding (not encoding)) - (setq encoding (coding-system-change-eol-conversion decoding 'unix) - changed t)) - (if changed - (set-process-coding-system proc decoding encoding))) + proc decoding encoding changed) + (cond + ((fboundp 'start-process) + (setq proc + (apply 'start-process + (file-name-nondirectory command) nil + ;; `start-process' can't deal with relative + ;; filenames + (append (list (expand-file-name command)) args))) + (eshell-record-process-object proc) + (set-process-buffer proc (current-buffer)) + (if (eshell-interactive-output-p) + (set-process-filter proc 'eshell-output-filter) + (set-process-filter proc 'eshell-insertion-filter)) + (set-process-sentinel proc 'eshell-sentinel) + (run-hook-with-args 'eshell-exec-hook proc) + (when (fboundp 'process-coding-system) + (let ((coding-systems (process-coding-system proc))) + (setq decoding (car coding-systems) + encoding (cdr coding-systems))) + ;; If start-process decided to use some coding system for + ;; decoding data sent from the process and the coding system + ;; doesn't specify EOL conversion, we had better convert CRLF + ;; to LF. + (if (vectorp (coding-system-eol-type decoding)) + (setq decoding (coding-system-change-eol-conversion decoding 'dos) + changed t)) + ;; Even if start-process left the coding system for encoding + ;; data sent from the process undecided, we had better use the + ;; same one as what we use for decoding. But, we should + ;; suppress EOL conversion. + (if (and decoding (not encoding)) + (setq encoding (coding-system-change-eol-conversion decoding 'unix) + changed t)) + (if changed + (set-process-coding-system proc decoding encoding)))) + (t + ;; No async subprocesses... + (let ((oldbuf (current-buffer)) + (interact-p (eshell-interactive-output-p)) + lbeg lend line proc-buf exit-status) + (and (not (markerp eshell-last-sync-output-start)) + (setq eshell-last-sync-output-start (point-marker))) + (setq proc-buf + (set-buffer (get-buffer-create eshell-scratch-buffer))) + (erase-buffer) + (set-buffer oldbuf) + (run-hook-with-args 'eshell-exec-hook command) + (setq exit-status + (apply 'call-process-region + (append (list eshell-last-sync-output-start (point) + command t + eshell-scratch-buffer nil) + args))) + ;; When in a pipeline, record the place where the output of + ;; this process will begin. + (and eshell-in-pipeline-p + (set-marker eshell-last-sync-output-start (point))) + ;; Simulate the effect of the process filter. + (when (numberp exit-status) + (set-buffer proc-buf) + (goto-char (point-min)) + (setq lbeg (point)) + (while (eq 0 (forward-line 1)) + (setq lend (point) + line (buffer-substring-no-properties lbeg lend)) + (set-buffer oldbuf) + (if interact-p + (eshell-output-filter nil line) + (eshell-output-object line)) + (setq lbeg lend) + (set-buffer proc-buf)) + (set-buffer oldbuf)) + (eshell-update-markers eshell-last-output-end) + ;; Simulate the effect of eshell-sentinel. + (eshell-close-handles (if (numberp exit-status) exit-status -1)) + (run-hook-with-args 'eshell-kill-hook command exit-status) + (or eshell-in-pipeline-p + (setq eshell-last-sync-output-start nil)) + (if (not (numberp exit-status)) + (error "%s: external command failed: %s" command exit-status)) + (setq proc t)))) proc)) (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." (put 'eshell-for 'lisp-indent-function 2) -(defsubst eshell-flatten-list (args) +(defun eshell-flatten-list (args) "Flatten any lists within ARGS, so that there are no sublists." (let ((new-list (list t))) (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 "Parse a variable interpolation. This function is explicit for adding to `eshell-parse-argument-hook'." (when (and (eq (char-after) ?$) - (not (= (1+ (point)) (point-max)))) + (/= (1+ (point)) (point-max))) (forward-char) (list 'eshell-escape-arg (eshell-parse-variable)))) @@ -293,11 +293,19 @@ This function is explicit for adding to `eshell-parse-argument-hook'." (defun eshell/export (&rest sets) "This alias allows the 'export' command to act as bash users expect." (while sets - (if (string-match "^\\([^=]+\\)=\\(.*\\)" (car sets)) + (if (and (stringp (car sets)) + (string-match "^\\([^=]+\\)=\\(.*\\)" (car sets))) (setenv (match-string 1 (car sets)) (match-string 2 (car sets)))) (setq sets (cdr sets)))) +(defun eshell/unset (&rest args) + "Unset an environment variable." + (while args + (if (stringp (car args)) + (setenv (car args) nil t)) + (setq args (cdr args)))) + (defun pcomplete/eshell-mode/export () "Completion function for Eshell's `export'." (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 @@ ;; User Variables: (defcustom pcmpl-gnu-makefile-regexps - '("\\`Makefile\\." "\\.mak\\'") + '("\\`GNUmakefile" "\\`Makefile" "\\.mak\\'") "*A list of regexps that will match Makefile names." :type '(repeat regexp) :group 'pcmpl-gnu) @@ -111,7 +111,10 @@ (defun pcmpl-gnu-make-rule-names () "Return a list of possible make rule names in MAKEFILE." (let* ((minus-f (member "-f" pcomplete-args)) - (makefile (or (cadr minus-f) "Makefile")) + (makefile (or (cadr minus-f) + (if (file-exists-p "GNUmakefile") + "GNUmakefile" + "Makefile"))) rules) (if (not (file-readable-p makefile)) (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." :type 'function :group 'pcomplete) +(defcustom pcomplete-use-paring t + "*If t, pare alternatives that have already been used. +If nil, you will always see the completion set of possible options, no +matter which of those options have already been used in previous +command arguments." + :type 'boolean + :group 'pcomplete) + ;;; Internal Variables: ;; for cycling completion support @@ -1017,7 +1025,7 @@ extra checking, and munging of the COMPLETIONS list." (message "No completions of %s" stub) (message "No completions"))) ;; pare it down, if applicable - (if pcomplete-seen + (if (and pcomplete-use-paring pcomplete-seen) (let* ((arg (pcomplete-arg)) (prefix (file-name-as-directory |