Commit ca7aae91 authored by John Wiegley's avatar John Wiegley

See ChangeLog

parent b4bd214e
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
......
......@@ -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))
......
......@@ -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
......
......@@ -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))))
......
......@@ -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)
......
......@@ -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)
......
......@@ -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))
......
......@@ -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."
......
......@@ -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))))))
......
......@@ -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)))))
......
......@@ -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"
......
......@@ -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)
......
......@@ -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,