See ChangeLog

This commit is contained in:
John Wiegley 2000-08-29 00:47:45 +00:00
parent b4bd214e74
commit ca7aae916b
19 changed files with 348 additions and 178 deletions

View file

@ -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

View file

@ -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))

View file

@ -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

View file

@ -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))))

View file

@ -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)

View file

@ -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)

View file

@ -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))

View file

@ -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."

View file

@ -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))))))

View file

@ -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)))))

View file

@ -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"

View file

@ -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)

View file

@ -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)))

View file

@ -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))

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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"))

View file

@ -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