summaryrefslogtreecommitdiff
path: root/lisp/eshell
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/eshell')
-rw-r--r--lisp/eshell/em-basic.el2
-rw-r--r--lisp/eshell/em-cmpl.el7
-rw-r--r--lisp/eshell/em-dirs.el31
-rw-r--r--lisp/eshell/em-hist.el72
-rw-r--r--lisp/eshell/em-ls.el40
-rw-r--r--lisp/eshell/em-pred.el19
-rw-r--r--lisp/eshell/em-prompt.el1
-rw-r--r--lisp/eshell/em-script.el2
-rw-r--r--lisp/eshell/em-term.el2
-rw-r--r--lisp/eshell/em-tramp.el6
-rw-r--r--lisp/eshell/em-unix.el73
-rw-r--r--lisp/eshell/em-xtra.el8
-rw-r--r--lisp/eshell/esh-cmd.el2
-rw-r--r--lisp/eshell/esh-ext.el4
-rw-r--r--lisp/eshell/esh-mode.el6
-rw-r--r--lisp/eshell/esh-opt.el38
-rw-r--r--lisp/eshell/esh-proc.el11
-rw-r--r--lisp/eshell/esh-util.el23
-rw-r--r--lisp/eshell/esh-var.el2
19 files changed, 194 insertions, 155 deletions
diff --git a/lisp/eshell/em-basic.el b/lisp/eshell/em-basic.el
index 346fb1c17b0..72a4e6bf801 100644
--- a/lisp/eshell/em-basic.el
+++ b/lisp/eshell/em-basic.el
@@ -118,7 +118,7 @@ or `eshell-printn' for display."
(defun eshell/printnl (&rest args)
"Print out each of the arguments, separated by newlines."
- (let ((elems (eshell-flatten-list args)))
+ (let ((elems (flatten-tree args)))
(while elems
(eshell-printn (eshell-echo (list (car elems))))
(setq elems (cdr elems)))))
diff --git a/lisp/eshell/em-cmpl.el b/lisp/eshell/em-cmpl.el
index f834882f7b6..cd5c14afbe6 100644
--- a/lisp/eshell/em-cmpl.el
+++ b/lisp/eshell/em-cmpl.el
@@ -262,8 +262,9 @@ to writing a completion function."
eshell-cmpl-ignore-case)
(set (make-local-variable 'pcomplete-autolist)
eshell-cmpl-autolist)
- (set (make-local-variable 'pcomplete-suffix-list)
- eshell-cmpl-suffix-list)
+ (if (boundp 'pcomplete-suffix-list)
+ (set (make-local-variable 'pcomplete-suffix-list)
+ eshell-cmpl-suffix-list))
(set (make-local-variable 'pcomplete-recexact)
eshell-cmpl-recexact)
(set (make-local-variable 'pcomplete-man-function)
@@ -437,7 +438,7 @@ to writing a completion function."
(setq comps-in-path (cdr comps-in-path)))
(setq paths (cdr paths)))
;; Add aliases which are currently visible, and Lisp functions.
- (pcomplete-uniqify-list
+ (pcomplete-uniquify-list
(if glob-name
completions
(setq completions
diff --git a/lisp/eshell/em-dirs.el b/lisp/eshell/em-dirs.el
index 4d8debb954f..8e79189acf5 100644
--- a/lisp/eshell/em-dirs.el
+++ b/lisp/eshell/em-dirs.el
@@ -207,7 +207,7 @@ Thus, this does not include the current directory.")
(when eshell-cd-on-directory
(make-local-variable 'eshell-interpreter-alist)
(setq eshell-interpreter-alist
- (cons (cons #'(lambda (file args)
+ (cons (cons #'(lambda (file _args)
(eshell-lone-directory-p file))
'eshell-dirs-substitute-cd)
eshell-interpreter-alist)))
@@ -259,7 +259,7 @@ Thus, this does not include the current directory.")
(if (> (length args) 1)
(error "%s: command not found" (car args))
(throw 'eshell-replace-command
- (eshell-parse-command "cd" (eshell-flatten-list args)))))
+ (eshell-parse-command "cd" (flatten-tree args)))))
(defun eshell-parse-user-reference ()
"An argument beginning with ~ is a filename to be expanded."
@@ -282,7 +282,7 @@ Thus, this does not include the current directory.")
(defvar pcomplete-stub)
(defvar pcomplete-last-completion-raw)
(declare-function pcomplete-actual-arg "pcomplete")
-(declare-function pcomplete-uniqify-list "pcomplete")
+(declare-function pcomplete-uniquify-list "pcomplete")
(defun eshell-complete-user-reference ()
"If there is a user reference, complete it."
@@ -293,14 +293,14 @@ Thus, this does not include the current directory.")
(throw 'pcomplete-completions
(progn
(eshell-read-user-names)
- (pcomplete-uniqify-list
+ (pcomplete-uniquify-list
(mapcar
(function
(lambda (user)
(file-name-as-directory (cdr user))))
eshell-user-names)))))))
-(defun eshell/pwd (&rest args)
+(defun eshell/pwd (&rest _args)
"Change output from `pwd' to be cleaner."
(let* ((path default-directory)
(len (length path)))
@@ -314,16 +314,18 @@ Thus, this does not include the current directory.")
path)))
(defun eshell-expand-multiple-dots (path)
+ ;; FIXME: This advice recommendation is rather odd: it's somewhat
+ ;; dangerous and it claims not to work with minibuffer-completion, which
+ ;; makes it much less interesting.
"Convert `...' to `../..', `....' to `../../..', etc..
With the following piece of advice, you can make this functionality
available in most of Emacs, with the exception of filename completion
in the minibuffer:
- (defadvice expand-file-name
- (before translate-multiple-dots
- (filename &optional directory) activate)
- (setq filename (eshell-expand-multiple-dots filename)))"
+ (advice-add 'expand-file-name :around #'my-expand-multiple-dots)
+ (defun my-expand-multiple-dots (orig-fun filename &rest args)
+ (apply orig-fun (eshell-expand-multiple-dots filename) args))"
(while (string-match "\\(?:^\\|/\\)\\.\\.\\(\\.+\\)\\(?:$\\|/\\)" path)
(let* ((extra-dots (match-string 1 path))
(len (length extra-dots))
@@ -351,7 +353,7 @@ in the minibuffer:
(defun eshell/cd (&rest args) ; all but first ignored
"Alias to extend the behavior of `cd'."
- (setq args (eshell-flatten-list args))
+ (setq args (flatten-tree args))
(let ((path (car args))
(subpath (car (cdr args)))
(case-fold-search (eshell-under-windows-p))
@@ -550,15 +552,16 @@ in the minibuffer:
(defun eshell-write-last-dir-ring ()
"Write the buffer's `eshell-last-dir-ring' to a history file."
- (let ((file eshell-last-dir-ring-file-name))
+ (let* ((file eshell-last-dir-ring-file-name)
+ (resolved-file (if (stringp file) (file-truename file))))
(cond
((or (null file)
(equal file "")
(null eshell-last-dir-ring)
(ring-empty-p eshell-last-dir-ring))
nil)
- ((not (file-writable-p file))
- (message "Cannot write last-dir-ring file %s" file))
+ ((not (file-writable-p resolved-file))
+ (message "Cannot write last-dir-ring file %s" resolved-file))
(t
(let* ((ring eshell-last-dir-ring)
(index (ring-length ring)))
@@ -568,7 +571,7 @@ in the minibuffer:
(insert (ring-ref ring index) ?\n))
(insert (eshell/pwd) ?\n)
(eshell-with-private-file-modes
- (write-region (point-min) (point-max) file nil
+ (write-region (point-min) (point-max) resolved-file nil
'no-message))))))))
(provide 'em-dirs)
diff --git a/lisp/eshell/em-hist.el b/lisp/eshell/em-hist.el
index f0aee6909ea..05579eed32a 100644
--- a/lisp/eshell/em-hist.el
+++ b/lisp/eshell/em-hist.el
@@ -218,9 +218,6 @@ Returns nil if INPUT is prepended by blank space, otherwise non-nil."
(defun eshell-hist-initialize ()
"Initialize the history management code for one Eshell buffer."
- (add-hook 'eshell-expand-input-functions
- 'eshell-expand-history-references nil t)
-
(when (eshell-using-module 'eshell-cmpl)
(add-hook 'pcomplete-try-first-hook
'eshell-complete-history-reference nil t))
@@ -469,15 +466,16 @@ lost if `eshell-history-ring' is not empty. If
Useful within process sentinels.
See also `eshell-read-history'."
- (let ((file (or filename eshell-history-file-name)))
+ (let* ((file (or filename eshell-history-file-name))
+ (resolved-file (if (stringp file) (file-truename file))))
(cond
((or (null file)
(equal file "")
(null eshell-history-ring)
(ring-empty-p eshell-history-ring))
nil)
- ((not (file-writable-p file))
- (message "Cannot write history file %s" file))
+ ((not (file-writable-p resolved-file))
+ (message "Cannot write history file %s" resolved-file))
(t
(let* ((ring eshell-history-ring)
(index (ring-length ring)))
@@ -492,7 +490,7 @@ See also `eshell-read-history'."
(insert (substring-no-properties (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
+ (write-region (point-min) (point-max) resolved-file append
'no-message))))))))
(defun eshell-list-history ()
@@ -584,21 +582,30 @@ See also `eshell-read-history'."
(defun eshell-expand-history-references (beg end)
"Parse and expand any history references in current input."
- (let ((result (eshell-hist-parse-arguments beg end)))
+ (let ((result (eshell-hist-parse-arguments beg end))
+ (full-line (buffer-substring-no-properties beg end)))
(when result
(let ((textargs (nreverse (nth 0 result)))
(posb (nreverse (nth 1 result)))
- (pose (nreverse (nth 2 result))))
+ (pose (nreverse (nth 2 result)))
+ (full-line-subst (eshell-history-substitution full-line)))
(save-excursion
- (while textargs
- (let ((str (eshell-history-reference (car textargs))))
- (unless (eq str (car textargs))
- (goto-char (car posb))
- (insert-and-inherit str)
- (delete-char (- (car pose) (car posb)))))
- (setq textargs (cdr textargs)
- posb (cdr posb)
- pose (cdr pose))))))))
+ (if full-line-subst
+ ;; Found a ^foo^bar substitution
+ (progn
+ (goto-char beg)
+ (insert-and-inherit full-line-subst)
+ (delete-char (- end beg)))
+ ;; Try to expand other substitutions
+ (while textargs
+ (let ((str (eshell-history-reference (car textargs))))
+ (unless (eq str (car textargs))
+ (goto-char (car posb))
+ (insert-and-inherit str)
+ (delete-char (- (car pose) (car posb)))))
+ (setq textargs (cdr textargs)
+ posb (cdr posb)
+ pose (cdr pose)))))))))
(defvar pcomplete-stub)
(defvar pcomplete-last-completion-raw)
@@ -633,20 +640,31 @@ See also `eshell-read-history'."
(setq history (cdr history)))
(cdr fhist)))))))
+(defun eshell-history-substitution (line)
+ "Expand quick hist substitutions formatted as ^foo^bar^.
+Returns nil if string does not match quick substitution format,
+and acts like !!:s/foo/bar/ otherwise."
+ ;; `^string1^string2^'
+ ;; Quick Substitution. Repeat the last command, replacing
+ ;; STRING1 with STRING2. Equivalent to `!!:s/string1/string2/'
+ (when (and (eshell-using-module 'eshell-pred)
+ (string-match
+ "^\\^\\([^^]+\\)\\^\\([^^]+\\)\\(?:\\^\\(.*\\)\\)?$"
+ line))
+ ;; Save trailing match as `eshell-history-reference' runs string-match.
+ (let ((matched-end (match-string 3 line)))
+ (concat
+ (eshell-history-reference
+ (format "!!:s/%s/%s/"
+ (match-string 1 line)
+ (match-string 2 line)))
+ matched-end))))
+
(defun eshell-history-reference (reference)
"Expand directory stack REFERENCE.
The syntax used here was taken from the Bash info manual.
Returns the resultant reference, or the same string REFERENCE if none
matched."
- ;; `^string1^string2^'
- ;; Quick Substitution. Repeat the last command, replacing
- ;; STRING1 with STRING2. Equivalent to `!!:s/string1/string2/'
- (if (and (eshell-using-module 'eshell-pred)
- (string-match "\\^\\([^^]+\\)\\^\\([^^]+\\)\\^?\\s-*$"
- reference))
- (setq reference (format "!!:s/%s/%s/"
- (match-string 1 reference)
- (match-string 2 reference))))
;; `!'
;; Start a history substitution, except when followed by a
;; space, tab, the end of the line, = or (.
diff --git a/lisp/eshell/em-ls.el b/lisp/eshell/em-ls.el
index a4118a0da30..5e4bbdc87ef 100644
--- a/lisp/eshell/em-ls.el
+++ b/lisp/eshell/em-ls.el
@@ -183,9 +183,9 @@ really need to stick around for very long."
"The face used for highlighting junk file names.")
(defsubst eshell-ls-filetype-p (attrs type)
- "Test whether ATTRS specifies a directory."
- (if (nth 8 attrs)
- (eq (aref (nth 8 attrs) 0) type)))
+ "Test whether ATTRS specifies a file of type TYPE."
+ (if (file-attribute-modes attrs)
+ (eq (aref (file-attribute-modes attrs) 0) type)))
(defmacro eshell-ls-applicable (attrs index func file)
"Test whether, for ATTRS, the user can do what corresponds to INDEX.
@@ -193,8 +193,8 @@ ATTRS is a string of file modes. See `file-attributes'.
If we cannot determine the answer using ATTRS (e.g., if we need
to know what group the user is in), compute the return value by
calling FUNC with FILE as an argument."
- `(let ((owner (nth 2 ,attrs))
- (modes (nth 8 ,attrs)))
+ `(let ((owner (file-attribute-user-id ,attrs))
+ (modes (file-attribute-modes ,attrs)))
(cond ((cond ((numberp owner)
(= owner (user-uid)))
((stringp owner)
@@ -346,7 +346,7 @@ instead."
"ls" (if eshell-ls-initial-args
(list eshell-ls-initial-args args)
args)
- `((?a "all" nil show-all
+ '((?a "all" nil show-all
"do not ignore entries starting with .")
(?A "almost-all" nil show-almost-all
"do not list implied . and ..")
@@ -437,7 +437,7 @@ Sort entries alphabetically across.")
(defsubst eshell-ls-size-string (attrs size-width)
"Return the size string for ATTRS length, using SIZE-WIDTH."
- (let* ((str (eshell-ls-printable-size (nth 7 attrs) t))
+ (let* ((str (eshell-ls-printable-size (file-attribute-size attrs) t))
(len (length str)))
(if (< len size-width)
(concat (make-string (- size-width len) ? ) str)
@@ -503,19 +503,19 @@ whose cdr is the list of file attributes."
(if numeric-uid-gid
"%s%4d %-8s %-8s "
"%s%4d %-14s %-8s ")
- (or (nth 8 attrs) "??????????")
- (or (nth 1 attrs) 0)
- (or (let ((user (nth 2 attrs)))
+ (or (file-attribute-modes attrs) "??????????")
+ (or (file-attribute-link-number attrs) 0)
+ (or (let ((user (file-attribute-user-id attrs)))
(and (stringp user)
(eshell-substring user 14)))
- (nth 2 attrs)
+ (file-attribute-user-id attrs)
"")
- (or (let ((group (nth 3 attrs)))
+ (or (let ((group (file-attribute-group-id attrs)))
(and (stringp group)
(eshell-substring group 8)))
- (nth 3 attrs)
+ (file-attribute-group-id attrs)
""))
- (let* ((str (eshell-ls-printable-size (nth 7 attrs)))
+ (let* ((str (eshell-ls-printable-size (file-attribute-size attrs)))
(len (length str)))
;; Let file sizes shorter than 9 align neatly.
(if (< len (or size-width 8))
@@ -585,12 +585,12 @@ relative to that directory."
(let ((total 0.0))
(setq size-width 0)
(dolist (e entries)
- (if (nth 7 (cdr e))
- (setq total (+ total (nth 7 (cdr e)))
+ (if (file-attribute-size (cdr e))
+ (setq total (+ total (file-attribute-size (cdr e)))
size-width
(max size-width
(length (eshell-ls-printable-size
- (nth 7 (cdr e))
+ (file-attribute-size (cdr e))
(not
;; If we are under -l, count length
;; of sizes in bytes, not in blocks.
@@ -700,7 +700,7 @@ Each member of FILES is either a string or a cons cell of the form
(if (not show-size)
(setq display-files (mapcar 'eshell-ls-annotate files))
(dolist (file files)
- (let* ((str (eshell-ls-printable-size (nth 7 (cdr file)) t))
+ (let* ((str (eshell-ls-printable-size (file-attribute-size (cdr file)) t))
(len (length str)))
(if (< len size-width)
(setq str (concat (make-string (- size-width len) ? ) str)))
@@ -766,14 +766,14 @@ need to be printed."
(if show-size
(max size-width
(length (eshell-ls-printable-size
- (nth 7 (cdr entry)) t))))))
+ (file-attribute-size (cdr entry)) t))))))
(setq dirs (cons entry dirs)))
(setq files (cons entry files)
size-width
(if show-size
(max size-width
(length (eshell-ls-printable-size
- (nth 7 (cdr entry)) t)))))))
+ (file-attribute-size (cdr entry)) t)))))))
(when files
(eshell-ls-files (eshell-ls-sort-entries files)
size-width show-recursive)
diff --git a/lisp/eshell/em-pred.el b/lisp/eshell/em-pred.el
index bfabda0ec77..1cbd2367f53 100644
--- a/lisp/eshell/em-pred.el
+++ b/lisp/eshell/em-pred.el
@@ -89,10 +89,12 @@ ordinary strings."
(?t . (eshell-pred-file-mode 1000)) ; sticky bit
(?U . #'(lambda (file) ; owned by effective uid
(if (file-exists-p file)
- (= (nth 2 (file-attributes file)) (user-uid)))))
+ (= (file-attribute-user-id (file-attributes file))
+ (user-uid)))))
;; (?G . #'(lambda (file) ; owned by effective gid
;; (if (file-exists-p file)
- ;; (= (nth 2 (file-attributes file)) (user-uid)))))
+ ;; (= (file-attribute-user-id (file-attributes file))
+ ;; (user-uid)))))
(?* . #'(lambda (file)
(and (file-regular-p file)
(not (file-symlink-p file))
@@ -131,7 +133,7 @@ The format of each entry is
(?e . #'(lambda (lst) (mapcar 'file-name-extension lst)))
(?t . #'(lambda (lst) (mapcar 'file-name-nondirectory lst)))
(?q . #'(lambda (lst) (mapcar 'eshell-escape-arg lst)))
- (?u . #'(lambda (lst) (eshell-uniqify-list lst)))
+ (?u . #'(lambda (lst) (eshell-uniquify-list lst)))
(?o . #'(lambda (lst) (sort lst 'string-lessp)))
(?O . #'(lambda (lst) (nreverse (sort lst 'string-lessp))))
(?j . (eshell-join-members))
@@ -460,7 +462,7 @@ that `ls -l' will show in the first column of its display. "
`(lambda (file)
(let ((attrs (eshell-file-attributes (directory-file-name file))))
(if attrs
- (memq (aref (nth 8 attrs) 0)
+ (memq (aref (file-attribute-modes attrs) 0)
,(if (eq type ?%)
'(?b ?c)
(list 'quote (list type))))))))
@@ -489,7 +491,8 @@ that `ls -l' will show in the first column of its display. "
'<
(if (eq qual ?+)
'>
- '=)) (nth 1 attrs) ,amount))))))
+ '=))
+ (file-attribute-link-number attrs) ,amount))))))
(defun eshell-pred-file-size ()
"Return a predicate to test whether a file is of a given size."
@@ -518,7 +521,8 @@ that `ls -l' will show in the first column of its display. "
'<
(if (eq qual ?+)
'>
- '=)) (nth 7 attrs) ,amount))))))
+ '=))
+ (file-attribute-size attrs) ,amount))))))
(defun eshell-pred-substitute (&optional repeat)
"Return a modifier function that will substitute matches."
@@ -545,7 +549,8 @@ that `ls -l' will show in the first column of its display. "
(function
(lambda (str)
(if (string-match ,match str)
- (setq str (replace-match ,replace t nil str)))
+ (setq str (replace-match ,replace t nil str))
+ (error (concat str ": substitution failed")))
str)) lst)))))
(defun eshell-include-members (&optional invert-p)
diff --git a/lisp/eshell/em-prompt.el b/lisp/eshell/em-prompt.el
index 3d15a441610..a3035205adb 100644
--- a/lisp/eshell/em-prompt.el
+++ b/lisp/eshell/em-prompt.el
@@ -80,7 +80,6 @@ re-entered for it to take effect."
For highlighting other kinds of strings -- similar to shell mode's
behavior -- simply use an output filer which changes text properties."
:group 'eshell-prompt)
-(define-obsolete-face-alias 'eshell-prompt-face 'eshell-prompt "22.1")
(defcustom eshell-before-prompt-hook nil
"A list of functions to call before outputting the prompt."
diff --git a/lisp/eshell/em-script.el b/lisp/eshell/em-script.el
index b8a5ecd9002..bab26222baf 100644
--- a/lisp/eshell/em-script.el
+++ b/lisp/eshell/em-script.el
@@ -61,7 +61,7 @@ This includes when running `eshell-command'."
"Initialize the script parsing code."
(make-local-variable 'eshell-interpreter-alist)
(setq eshell-interpreter-alist
- (cons (cons #'(lambda (file args)
+ (cons (cons #'(lambda (file _args)
(string= (file-name-nondirectory file)
"eshell"))
'eshell/source)
diff --git a/lisp/eshell/em-term.el b/lisp/eshell/em-term.el
index 1013bd2b89a..8af783eaf80 100644
--- a/lisp/eshell/em-term.el
+++ b/lisp/eshell/em-term.el
@@ -175,7 +175,7 @@ allowed."
(let* (eshell-interpreter-alist
(interp (eshell-find-interpreter (car args) (cdr args)))
(program (car interp))
- (args (eshell-flatten-list
+ (args (flatten-tree
(eshell-stringify-list (append (cdr interp)
(cdr args)))))
(term-buf
diff --git a/lisp/eshell/em-tramp.el b/lisp/eshell/em-tramp.el
index 81324800aef..603b7627d5d 100644
--- a/lisp/eshell/em-tramp.el
+++ b/lisp/eshell/em-tramp.el
@@ -26,6 +26,7 @@
;;; Code:
(require 'esh-util)
+(require 'esh-cmd)
(eval-when-compile
(require 'esh-mode)
@@ -61,7 +62,7 @@
"Alias \"su\" to call TRAMP.
Uses the system su through TRAMP's su method."
- (setq args (eshell-stringify-list (eshell-flatten-list args)))
+ (setq args (eshell-stringify-list (flatten-tree args)))
(let ((orig-args (copy-tree args)))
(eshell-eval-using-options
"su" args
@@ -99,13 +100,14 @@ Become another USER during a login session.")
"Alias \"sudo\" to call Tramp.
Uses the system sudo through TRAMP's sudo method."
- (setq args (eshell-stringify-list (eshell-flatten-list args)))
+ (setq args (eshell-stringify-list (flatten-tree args)))
(let ((orig-args (copy-tree args)))
(eshell-eval-using-options
"sudo" args
'((?h "help" nil nil "show this usage screen")
(?u "user" t user "execute a command as another USER")
:show-usage
+ :parse-leading-options-only
:usage "[(-u | --user) USER] COMMAND
Execute a COMMAND as the superuser or another USER.")
(throw 'eshell-external
diff --git a/lisp/eshell/em-unix.el b/lisp/eshell/em-unix.el
index b4ad5a6532c..fca50d70ae7 100644
--- a/lisp/eshell/em-unix.el
+++ b/lisp/eshell/em-unix.el
@@ -231,7 +231,7 @@ Otherwise, Emacs will attempt to use rsh to invoke du on the remote machine."
This is implemented to call either `delete-file', `kill-buffer',
`kill-process', or `unintern', depending on the nature of the
argument."
- (setq args (eshell-flatten-list args))
+ (setq args (flatten-tree args))
(eshell-eval-using-options
"rm" args
'((?h "help" nil nil "show this usage screen")
@@ -370,12 +370,14 @@ Remove the DIRECTORY(ies), if they are empty.")
(or (not (eshell-under-windows-p))
(eq system-type 'ms-dos))
(setq attr (eshell-file-attributes (car files)))
- (nth 10 attr-target) (nth 10 attr)
- ;; Use equal, not -, since the inode and the device could
- ;; cons cells.
- (equal (nth 10 attr-target) (nth 10 attr))
- (nth 11 attr-target) (nth 11 attr)
- (equal (nth 11 attr-target) (nth 11 attr)))
+ (file-attribute-inode-number attr-target)
+ (file-attribute-inode-number attr)
+ (equal (file-attribute-inode-number attr-target)
+ (file-attribute-inode-number attr))
+ (file-attribute-device-number attr-target)
+ (file-attribute-device-number attr)
+ (equal (file-attribute-device-number attr-target)
+ (file-attribute-device-number attr)))
(eshell-error (format-message "%s: `%s' and `%s' are the same file\n"
command (car files) target)))
(t
@@ -397,16 +399,16 @@ Remove the DIRECTORY(ies), if they are empty.")
(let (eshell-warn-dot-directories)
(if (and (not deep)
(eq func 'rename-file)
- ;; Use equal, since the device might be a
- ;; cons cell.
- (equal (nth 11 (eshell-file-attributes
- (file-name-directory
- (directory-file-name
- (expand-file-name source)))))
- (nth 11 (eshell-file-attributes
- (file-name-directory
- (directory-file-name
- (expand-file-name target)))))))
+ (equal (file-attribute-device-number
+ (eshell-file-attributes
+ (file-name-directory
+ (directory-file-name
+ (expand-file-name source)))))
+ (file-attribute-device-number
+ (eshell-file-attributes
+ (file-name-directory
+ (directory-file-name
+ (expand-file-name target)))))))
(apply 'eshell-funcalln func source target args)
(unless (file-directory-p target)
(if em-verbose
@@ -479,7 +481,7 @@ Remove the DIRECTORY(ies), if they are empty.")
(error "%s: missing destination file or directory" ,command))
(if (= len 1)
(nconc args '(".")))
- (setq args (eshell-stringify-list (eshell-flatten-list args)))
+ (setq args (eshell-stringify-list (flatten-tree args)))
(if (and ,(not (equal command "ln"))
(string-match eshell-tar-regexp (car (last args)))
(or (> (length args) 2)
@@ -604,7 +606,7 @@ with `--symbolic'. When creating hard links, each TARGET must exist.")
"Implementation of cat in Lisp.
If in a pipeline, or the file is not a regular file, directory or
symlink, then revert to the system's definition of cat."
- (setq args (eshell-stringify-list (eshell-flatten-list args)))
+ (setq args (eshell-stringify-list (flatten-tree args)))
(if (or eshell-in-pipeline-p
(catch 'special
(dolist (arg args)
@@ -612,7 +614,8 @@ symlink, then revert to the system's definition of cat."
(> (length arg) 0)
(eq (aref arg 0) ?-))
(let ((attrs (eshell-file-attributes arg)))
- (and attrs (memq (aref (nth 8 attrs) 0)
+ (and attrs
+ (memq (aref (file-attribute-modes attrs) 0)
'(?d ?l ?-)))))
(throw 'special t)))))
(let ((ext-cat (eshell-search-path "cat")))
@@ -667,7 +670,7 @@ Fallback to standard make when called synchronously."
(compile (concat "make " (eshell-flatten-and-stringify args))))
(throw 'eshell-replace-command
(eshell-parse-command "*make" (eshell-stringify-list
- (eshell-flatten-list args))))))
+ (flatten-tree args))))))
(put 'eshell/make 'eshell-no-numeric-conversions t)
@@ -702,7 +705,7 @@ available..."
(erase-buffer)
(occur-mode)
(let ((files (eshell-stringify-list
- (eshell-flatten-list (cdr args))))
+ (flatten-tree (cdr args))))
(inhibit-redisplay t)
string)
(when (car args)
@@ -747,11 +750,11 @@ external command."
(throw 'eshell-replace-command
(eshell-parse-command (concat "*" command)
(eshell-stringify-list
- (eshell-flatten-list args))))
+ (flatten-tree args))))
(let* ((args (mapconcat 'identity
(mapcar 'shell-quote-argument
(eshell-stringify-list
- (eshell-flatten-list args)))
+ (flatten-tree args)))
" "))
(cmd (progn
(set-text-properties 0 (length args)
@@ -843,19 +846,19 @@ external command."
(unless (string-match "\\`\\.\\.?\\'" (caar entries))
(let* ((entry (concat path "/"
(caar entries)))
- (symlink (and (stringp (cadr (car entries)))
- (cadr (car entries)))))
+ (symlink (and (stringp (file-attribute-type (cdar entries)))
+ (file-attribute-type (cdar entries)))))
(unless (or (and symlink (not dereference-links))
(and only-one-filesystem
(/= only-one-filesystem
- (nth 12 (car entries)))))
+ (file-attribute-device-number (cdar entries)))))
(if symlink
(setq entry symlink))
(setq size
(+ size
- (if (eq t (cadr (car entries)))
+ (if (eq t (car (cdar entries)))
(eshell-du-sum-directory entry (1+ depth))
- (let ((file-size (nth 8 (car entries))))
+ (let ((file-size (file-attribute-size (cdar entries))))
(prog1
file-size
(if show-all
@@ -873,7 +876,7 @@ external command."
(defun eshell/du (&rest args)
"Implementation of \"du\" in Lisp, passing ARGS."
(setq args (if args
- (eshell-stringify-list (eshell-flatten-list args))
+ (eshell-stringify-list (flatten-tree args))
'(".")))
(let ((ext-du (eshell-search-path "du")))
(if (and ext-du
@@ -926,7 +929,7 @@ Summarize disk usage of each FILE, recursively for directories.")
(while args
(if only-one-filesystem
(setq only-one-filesystem
- (nth 11 (eshell-file-attributes
+ (file-attribute-device-number (eshell-file-attributes
(file-name-as-directory (car args))))))
(setq size (+ size (eshell-du-sum-directory
(directory-file-name (car args)) 0)))
@@ -973,9 +976,9 @@ Show wall-clock time elapsed during execution of COMMAND.")
(eshell-parse-command (car time-args)
;;; https://lists.gnu.org/r/bug-gnu-emacs/2007-08/msg00205.html
(eshell-stringify-list
- (eshell-flatten-list (cdr time-args))))))))
+ (flatten-tree (cdr time-args))))))))
-(defun eshell/whoami (&rest args)
+(defun eshell/whoami (&rest _args)
"Make \"whoami\" Tramp aware."
(or (file-remote-p default-directory 'user) (user-login-name)))
@@ -997,7 +1000,7 @@ Show wall-clock time elapsed during execution of COMMAND.")
(defun eshell/diff (&rest args)
"Alias \"diff\" to call Emacs `diff' function."
- (let ((orig-args (eshell-stringify-list (eshell-flatten-list args))))
+ (let ((orig-args (eshell-stringify-list (flatten-tree args))))
(if (or eshell-plain-diff-behavior
(not (and (eshell-interactive-output-p)
(not eshell-in-pipeline-p)
@@ -1053,7 +1056,7 @@ Show wall-clock time elapsed during execution of COMMAND.")
(string-match "^-" (car args))))
(throw 'eshell-replace-command
(eshell-parse-command "*locate" (eshell-stringify-list
- (eshell-flatten-list args))))
+ (flatten-tree 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 d4e5f1a092c..602e8417520 100644
--- a/lisp/eshell/em-xtra.el
+++ b/lisp/eshell/em-xtra.el
@@ -25,8 +25,10 @@
(require 'esh-util)
(eval-when-compile
- (require 'eshell)
- (require 'pcomplete))
+ (require 'eshell))
+;; Strictly speaking, should only be needed at compile time.
+;; Require at run-time too to silence compiler.
+(require 'pcomplete)
(require 'compile)
;; There are no items in this custom group, but eshell modules (ab)use
@@ -49,7 +51,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" (eshell-flatten-list args)))
+ (eshell-parse-command "*expr" (flatten-tree 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 8e1e936b63f..ee4dbd5550f 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -816,7 +816,7 @@ This is used on systems where async subprocesses are not supported."
;; The last process in the pipe should get its handles
;; redirected as we found them before running the pipe.
,(if (null (cdr pipeline))
- `(progn
+ '(progn
(setq eshell-current-handles tail-handles)
(setq eshell-in-pipeline-p nil)))
(let ((result ,(car pipeline)))
diff --git a/lisp/eshell/esh-ext.el b/lisp/eshell/esh-ext.el
index fccdb73b31e..35ebd36b291 100644
--- a/lisp/eshell/esh-ext.el
+++ b/lisp/eshell/esh-ext.el
@@ -37,8 +37,8 @@
(eval-when-compile
(require 'cl-lib)
- (require 'esh-io)
(require 'esh-cmd))
+(require 'esh-io)
(require 'esh-arg)
(require 'esh-opt)
(require 'esh-proc)
@@ -222,7 +222,7 @@ causing the user to wonder if anything's really going on..."
(defun eshell-external-command (command args)
"Insert output from an external COMMAND, using ARGS."
- (setq args (eshell-stringify-list (eshell-flatten-list args)))
+ (setq args (eshell-stringify-list (flatten-tree args)))
(let ((interp (eshell-find-interpreter
command
args
diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el
index be6123f21ba..30298763a53 100644
--- a/lisp/eshell/esh-mode.el
+++ b/lisp/eshell/esh-mode.el
@@ -182,10 +182,11 @@ inserted. They return the string as it should be inserted."
:group 'eshell-mode)
(defcustom eshell-password-prompt-regexp
- (format "\\(%s\\).*:\\s *\\'" (regexp-opt password-word-equivalents))
+ (format "\\(%s\\)[^::៖]*[::៖]\\s *\\'" (regexp-opt password-word-equivalents))
"Regexp matching prompts for passwords in the inferior process.
This is used by `eshell-watch-for-password-prompt'."
:type 'regexp
+ :version "27.1"
:group 'eshell-mode)
(defcustom eshell-skip-prompt-function nil
@@ -884,8 +885,7 @@ If SCROLLBACK is non-nil, clear the scrollback contents."
(interactive)
(if scrollback
(eshell/clear-scrollback)
- (let ((eshell-input-filter-functions
- (remq 'eshell-add-to-history eshell-input-filter-functions)))
+ (let ((eshell-input-filter-functions nil))
(insert (make-string (window-size) ?\n))
(eshell-send-input))))
diff --git a/lisp/eshell/esh-opt.el b/lisp/eshell/esh-opt.el
index 6f37a29004a..a023a3c5d2e 100644
--- a/lisp/eshell/esh-opt.el
+++ b/lisp/eshell/esh-opt.el
@@ -77,9 +77,13 @@ arguments, some do not. The recognized :KEYWORDS are:
arguments.
:preserve-args
- If present, do not pass MACRO-ARGS through `eshell-flatten-list'
+ If present, do not pass MACRO-ARGS through `flatten-tree'
and `eshell-stringify-list'.
+:parse-leading-options-only
+ If present, do not parse dash or switch arguments after the first
+positional argument. Instead, treat them as positional arguments themselves.
+
For example, OPTIONS might look like:
((?C nil nil multi-column \"multi-column display\")
@@ -95,14 +99,14 @@ BODY-FORMS. If instead an external command is run (because of
an unknown option), the tag `eshell-external' will be thrown with
the new process for its value.
-Lastly, any remaining arguments will be available in a locally
-interned variable `args' (created using a `let' form)."
+Lastly, any remaining arguments will be available in the locally
+let-bound variable `args'."
(declare (debug (form form sexp body)))
`(let* ((temp-args
,(if (memq ':preserve-args (cadr options))
macro-args
(list 'eshell-stringify-list
- (list 'eshell-flatten-list macro-args))))
+ (list 'flatten-tree macro-args))))
(processed-args (eshell--do-opts ,name ,options temp-args))
,@(delete-dups
(delq nil (mapcar (lambda (opt)
@@ -111,6 +115,8 @@ interned variable `args' (created using a `let' form)."
;; `options' is of the form (quote OPTS).
(cadr options))))
(args processed-args))
+ ;; Silence unused lexical variable warning if body does not use `args'.
+ (ignore args)
,@body-forms))
;;; Internal Functions:
@@ -194,11 +200,7 @@ will be modified."
(if (eq (nth 2 opt) t)
(if (> ai (length eshell--args))
(error "%s: missing option argument" name)
- (prog1 (nth ai eshell--args)
- (if (> ai 0)
- (setcdr (nthcdr (1- ai) eshell--args)
- (nthcdr (1+ ai) eshell--args))
- (setq eshell--args (cdr eshell--args)))))
+ (pop (nthcdr ai eshell--args)))
(or (nth 2 opt) t)))))
(defun eshell--process-option (name switch kind ai options opt-vals)
@@ -243,18 +245,22 @@ switch is unrecognized."
(list sym)))))
options)))
(ai 0) arg
- (eshell--args args))
- (while (< ai (length eshell--args))
+ (eshell--args args)
+ (pos-argument-found nil))
+ (while (and (< ai (length eshell--args))
+ ;; Abort if we saw the first pos argument and option is set
+ (not (and pos-argument-found
+ (memq :parse-leading-options-only options))))
(setq arg (nth ai eshell--args))
(if (not (and (stringp arg)
(string-match "^-\\(-\\)?\\(.*\\)" arg)))
- (setq ai (1+ ai))
+ ;; Positional argument found, skip
+ (setq ai (1+ ai)
+ pos-argument-found t)
+ ;; dash or switch argument found, parse
(let* ((dash (match-string 1 arg))
(switch (match-string 2 arg)))
- (if (= ai 0)
- (setq eshell--args (cdr eshell--args))
- (setcdr (nthcdr (1- ai) eshell--args)
- (nthcdr (1+ ai) eshell--args)))
+ (pop (nthcdr ai eshell--args))
(if dash
(if (> (length switch) 0)
(eshell--process-option name switch 1 ai options opt-vals)
diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el
index 33ec19ae36d..55251f5bfb2 100644
--- a/lisp/eshell/esh-proc.el
+++ b/lisp/eshell/esh-proc.el
@@ -158,7 +158,7 @@ The signals which will cause this to happen are matched by
(defalias 'eshell/wait 'eshell-wait-for-process)
-(defun eshell/jobs (&rest args)
+(defun eshell/jobs (&rest _args)
"List processes, if there are any."
(and (fboundp 'process-list)
(process-list)
@@ -167,7 +167,8 @@ The signals which will cause this to happen are matched by
(defun eshell/kill (&rest args)
"Kill processes.
Usage: kill [-<signal>] <pid>|<process> ...
-Accepts PIDs and process objects."
+Accepts PIDs and process objects. Optionally accept signals
+and signal names."
;; If the first argument starts with a dash, treat it as the signal
;; specifier.
(let ((signum 'SIGINT))
@@ -178,12 +179,12 @@ Accepts PIDs and process objects."
((string-match "\\`-[[:digit:]]+\\'" arg)
(setq signum (abs (string-to-number arg))))
((string-match "\\`-\\([[:upper:]]+\\|[[:lower:]]+\\)\\'" arg)
- (setq signum (abs (string-to-number arg)))))
+ (setq signum (intern (substring arg 1)))))
(setq args (cdr args))))
(while args
(let ((arg (if (eshell-processp (car args))
(process-id (car args))
- (car args))))
+ (string-to-number (car args)))))
(when arg
(cond
((null arg)
@@ -198,6 +199,8 @@ Accepts PIDs and process objects."
(setq args (cdr args))))
nil)
+(put 'eshell/kill 'eshell-no-numeric-conversions t)
+
(defun eshell-read-process-name (prompt)
"Read the name of a process from the minibuffer, using completion.
The prompt will be set to PROMPT."
diff --git a/lisp/eshell/esh-util.el b/lisp/eshell/esh-util.el
index f8dd6f08f45..7e6e39e74a3 100644
--- a/lisp/eshell/esh-util.el
+++ b/lisp/eshell/esh-util.el
@@ -285,17 +285,9 @@ Prepend remote identification of `default-directory', if any."
,@forms)
(setq list-iter (cdr list-iter)))))
-(defun eshell-flatten-list (args)
- "Flatten any lists within ARGS, so that there are no sublists."
- (let ((new-list (list t)))
- (dolist (a args)
- (if (and (listp a)
- (listp (cdr a)))
- (nconc new-list (eshell-flatten-list a))
- (nconc new-list (list a))))
- (cdr new-list)))
-
-(defun eshell-uniqify-list (l)
+(define-obsolete-function-alias 'eshell-flatten-list #'flatten-tree "27.1")
+
+(defun eshell-uniquify-list (l)
"Remove occurring multiples in L. You probably want to sort first."
(let ((m l))
(while m
@@ -305,6 +297,9 @@ Prepend remote identification of `default-directory', if any."
(setcdr m (cddr m)))
(setq m (cdr m))))
l)
+(define-obsolete-function-alias
+ 'eshell-uniqify-list
+ 'eshell-uniquify-list "27.1")
(defun eshell-stringify (object)
"Convert OBJECT into a string value."
@@ -327,7 +322,7 @@ Prepend remote identification of `default-directory', if any."
(defsubst eshell-flatten-and-stringify (&rest args)
"Flatten and stringify all of the ARGS into a single string."
- (mapconcat 'eshell-stringify (eshell-flatten-list args) " "))
+ (mapconcat 'eshell-stringify (flatten-tree args) " "))
(defsubst eshell-directory-files (regexp &optional directory)
"Return a list of files in the given DIRECTORY matching REGEXP."
@@ -444,7 +439,7 @@ list."
(not (symbol-value timestamp-var))
(time-less-p
(symbol-value timestamp-var)
- (nth 5 (file-attributes file))))
+ (file-attribute-modification-time (file-attributes file))))
(progn
(set result-var (eshell-read-passwd-file file))
(set timestamp-var (current-time))))
@@ -498,7 +493,7 @@ list."
(not (symbol-value timestamp-var))
(time-less-p
(symbol-value timestamp-var)
- (nth 5 (file-attributes file))))
+ (file-attribute-modification-time (file-attributes file))))
(progn
(set result-var (eshell-read-hosts-file file))
(set timestamp-var (current-time))))
diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el
index b3f54cf048d..133a4f9c713 100644
--- a/lisp/eshell/esh-var.el
+++ b/lisp/eshell/esh-var.el
@@ -343,6 +343,8 @@ This function is explicit for adding to `eshell-parse-argument-hook'."
obarray 'boundp))
(pcomplete-here))))
+;; FIXME the real "env" command does more than this, it runs a program
+;; in a modified environment.
(defun eshell/env (&rest args)
"Implementation of `env' in Lisp."
(eshell-init-print-buffer)