summaryrefslogtreecommitdiff
path: root/lisp/eshell/em-dirs.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/eshell/em-dirs.el')
-rw-r--r--lisp/eshell/em-dirs.el176
1 files changed, 88 insertions, 88 deletions
diff --git a/lisp/eshell/em-dirs.el b/lisp/eshell/em-dirs.el
index 0d87f2a599e..00880b9f281 100644
--- a/lisp/eshell/em-dirs.el
+++ b/lisp/eshell/em-dirs.el
@@ -1,6 +1,6 @@
;;; em-dirs.el --- directory navigation commands -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2017 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2022 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -42,7 +42,8 @@
;;; Code:
-(require 'eshell)
+(require 'esh-mode) ;For eshell-directory-name
+(require 'esh-var) ;For eshell-variable-aliases-list
(require 'ring)
(require 'esh-opt)
@@ -62,12 +63,11 @@ they lack somewhat in feel from the typical shell equivalents."
(defcustom eshell-dirs-load-hook nil
"A hook that gets run when `eshell-dirs' is loaded."
:version "24.1" ; removed eshell-dirs-initialize
- :type 'hook
- :group 'eshell-dirs)
+ :type 'hook)
(defcustom eshell-pwd-convert-function (if (eshell-under-windows-p)
- 'expand-file-name
- 'identity)
+ #'expand-file-name
+ #'identity)
"The function used to normalize the value of Eshell's `pwd'.
The value returned by `pwd' is also used when recording the
last-visited directory in the last-dir-ring, so it will affect the
@@ -75,8 +75,7 @@ form of the list used by `cd ='."
:type '(radio (function-item file-truename)
(function-item expand-file-name)
(function-item identity)
- (function :tag "Other"))
- :group 'eshell-dirs)
+ (function :tag "Other")))
(defcustom eshell-ask-to-save-last-dir 'always
"Determine if the last-dir-ring should be automatically saved.
@@ -88,63 +87,53 @@ If set to t, always ask if any Eshell buffers are open at exit time.
If set to `always', the list-dir-ring will always be saved, silently."
:type '(choice (const :tag "Never" nil)
(const :tag "Ask" t)
- (const :tag "Always save" always))
- :group 'eshell-dirs)
+ (const :tag "Always save" always)))
(defcustom eshell-cd-shows-directory nil
"If non-nil, using `cd' will report the directory it changes to."
- :type 'boolean
- :group 'eshell-dirs)
+ :type 'boolean)
(defcustom eshell-cd-on-directory t
"If non-nil, do a cd if a directory is in command position."
- :type 'boolean
- :group 'eshell-dirs)
+ :type 'boolean)
(defcustom eshell-directory-change-hook nil
"A hook to run when the current directory changes."
- :type 'hook
- :group 'eshell-dirs)
+ :type 'hook)
(defcustom eshell-list-files-after-cd nil
"If non-nil, call \"ls\" with any remaining args after doing a cd.
This is provided for convenience, since the same effect is easily
achieved by adding a function to `eshell-directory-change-hook' that
calls \"ls\" and references `eshell-last-arguments'."
- :type 'boolean
- :group 'eshell-dirs)
+ :type 'boolean)
(defcustom eshell-pushd-tohome nil
"If non-nil, make pushd with no arg behave as `pushd ~' (like `cd').
This mirrors the optional behavior of tcsh."
- :type 'boolean
- :group 'eshell-dirs)
+ :type 'boolean)
(defcustom eshell-pushd-dextract nil
"If non-nil, make \"pushd +n\" pop the nth dir to the stack top.
This mirrors the optional behavior of tcsh."
- :type 'boolean
- :group 'eshell-dirs)
+ :type 'boolean)
(defcustom eshell-pushd-dunique nil
"If non-nil, make pushd only add unique directories to the stack.
This mirrors the optional behavior of tcsh."
- :type 'boolean
- :group 'eshell-dirs)
+ :type 'boolean)
(defcustom eshell-dirtrack-verbose t
"If non-nil, show the directory stack following directory change.
This is effective only if directory tracking is enabled."
- :type 'boolean
- :group 'eshell-dirs)
+ :type 'boolean)
(defcustom eshell-last-dir-ring-file-name
(expand-file-name "lastdir" eshell-directory-name)
"If non-nil, name of the file to read/write the last-dir-ring.
See also `eshell-read-last-dir-ring' and `eshell-write-last-dir-ring'.
If it is nil, the last-dir-ring will not be written to disk."
- :type 'file
- :group 'eshell-dirs)
+ :type 'file)
(defcustom eshell-last-dir-ring-size 32
"If non-nil, the size of the directory history ring.
@@ -164,13 +153,11 @@ directories gets pushed, and its size is unlimited.
explicitly very much, but every once in a while would like to return to
a previously visited directory without having to type in the whole
thing again."
- :type 'integer
- :group 'eshell-dirs)
+ :type 'integer)
(defcustom eshell-last-dir-unique t
"If non-nil, `eshell-last-dir-ring' contains only unique entries."
- :type 'boolean
- :group 'eshell-dirs)
+ :type 'boolean)
;;; Internal Variables:
@@ -183,44 +170,48 @@ Thus, this does not include the current directory.")
;;; Functions:
-(defun eshell-dirs-initialize ()
+(defun eshell-dirs-initialize () ;Called from `eshell-mode' via intern-soft!
"Initialize the builtin functions for Eshell."
- (make-local-variable 'eshell-variable-aliases-list)
- (setq eshell-variable-aliases-list
+ (setq-local eshell-variable-aliases-list
(append
eshell-variable-aliases-list
- '(("-" (lambda (indices)
- (if (not indices)
- (unless (ring-empty-p eshell-last-dir-ring)
- (expand-file-name
- (ring-ref eshell-last-dir-ring 0)))
- (expand-file-name
- (eshell-apply-indices eshell-last-dir-ring indices)))))
- ("+" "PWD")
- ("PWD" (lambda (indices)
- (expand-file-name (eshell/pwd))) t)
- ("OLDPWD" (lambda (indices)
- (unless (ring-empty-p eshell-last-dir-ring)
- (expand-file-name
- (ring-ref eshell-last-dir-ring 0)))) t))))
+ `(("-" ,(lambda (indices quoted)
+ (if (not indices)
+ (unless (ring-empty-p eshell-last-dir-ring)
+ (expand-file-name
+ (ring-ref eshell-last-dir-ring 0)))
+ ;; Apply the first index, expand the file name,
+ ;; and then apply the rest of the indices.
+ (eshell-apply-indices
+ (expand-file-name
+ (eshell-apply-indices eshell-last-dir-ring
+ (list (car indices)) quoted))
+ (cdr indices) quoted))))
+ ("+" "PWD")
+ ("PWD" ,(lambda () (expand-file-name (eshell/pwd)))
+ t t)
+ ("OLDPWD" ,(lambda ()
+ (unless (ring-empty-p eshell-last-dir-ring)
+ (expand-file-name
+ (ring-ref eshell-last-dir-ring 0))))
+ t t))))
(when eshell-cd-on-directory
- (make-local-variable 'eshell-interpreter-alist)
- (setq eshell-interpreter-alist
- (cons (cons #'(lambda (file args)
- (eshell-lone-directory-p file))
- 'eshell-dirs-substitute-cd)
- eshell-interpreter-alist)))
+ (setq-local eshell-interpreter-alist
+ (cons (cons (lambda (file _args)
+ (eshell-lone-directory-p file))
+ 'eshell-dirs-substitute-cd)
+ eshell-interpreter-alist)))
(add-hook 'eshell-parse-argument-hook
- 'eshell-parse-user-reference nil t)
+ #'eshell-parse-user-reference nil t)
(if (eshell-under-windows-p)
(add-hook 'eshell-parse-argument-hook
- 'eshell-parse-drive-letter nil t))
+ #'eshell-parse-drive-letter nil t))
(when (eshell-using-module 'eshell-cmpl)
(add-hook 'pcomplete-try-first-hook
- 'eshell-complete-user-reference nil t))
+ #'eshell-complete-user-reference nil t))
(make-local-variable 'eshell-dirstack)
(make-local-variable 'eshell-last-dir-ring)
@@ -230,9 +221,9 @@ Thus, this does not include the current directory.")
(unless eshell-last-dir-ring
(setq eshell-last-dir-ring (make-ring eshell-last-dir-ring-size)))
- (add-hook 'eshell-exit-hook 'eshell-write-last-dir-ring nil t)
+ (add-hook 'eshell-exit-hook #'eshell-write-last-dir-ring nil t)
- (add-hook 'kill-emacs-hook 'eshell-save-some-last-dir))
+ (add-hook 'kill-emacs-query-functions #'eshell-save-some-last-dir))
(defun eshell-save-some-last-dir ()
"Save the list-dir-ring for any open Eshell buffers."
@@ -246,7 +237,8 @@ Thus, this does not include the current directory.")
(format-message
"Save last dir ring for Eshell buffer `%s'? "
(buffer-name buf)))))
- (eshell-write-last-dir-ring))))))
+ (eshell-write-last-dir-ring)))))
+ t)
(defun eshell-lone-directory-p (file)
"Test whether FILE is just a directory name, and not a command name."
@@ -259,7 +251,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."
@@ -272,7 +264,7 @@ Thus, this does not include the current directory.")
(defun eshell-parse-drive-letter ()
"An argument beginning with X:[^/] is a drive letter reference."
(when (and (not eshell-current-argument)
- (looking-at "\\([A-Za-z]:\\)\\([^/\\\\]\\|\\'\\)"))
+ (looking-at "\\([A-Za-z]:\\)\\([^/\\]\\|\\'\\)"))
(goto-char (match-end 1))
(let* ((letter (match-string 1))
(regexp (concat "\\`" letter))
@@ -282,7 +274,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,47 +285,47 @@ 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))))
+ (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)))
(if (and (> len 1)
(eq (aref path (1- len)) ?/)
(not (and (eshell-under-windows-p)
- (string-match "\\`[A-Za-z]:[\\\\/]\\'" path))))
+ (string-match "\\`[A-Za-z]:[\\/]\\'" path))))
(setq path (substring path 0 (1- (length path)))))
- (if eshell-pwd-convert-function
- (funcall eshell-pwd-convert-function path)
- path)))
+ (funcall (or eshell-pwd-convert-function #'identity) path)))
-(defun eshell-expand-multiple-dots (path)
+(defun eshell-expand-multiple-dots (filename)
+ ;; 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)))"
- (while (string-match "\\(?:^\\|/\\)\\.\\.\\(\\.+\\)\\(?:$\\|/\\)" path)
- (let* ((extra-dots (match-string 1 path))
+ (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 "\\(?:\\`\\|/\\)\\.\\.\\(\\.+\\)\\(?:\\'\\|/\\)"
+ filename)
+ (let* ((extra-dots (match-string 1 filename))
(len (length extra-dots))
replace-text)
(while (> len 0)
(setq replace-text (concat replace-text "/..")
len (1- len)))
- (setq path
- (replace-match replace-text t t path 1))))
- path)
+ (setq filename
+ (replace-match replace-text t t filename 1))))
+ filename)
(defun eshell-find-previous-directory (regexp)
"Find the most recent last-dir matching REGEXP."
@@ -351,7 +343,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))
@@ -398,6 +390,10 @@ in the minibuffer:
(unless (equal curdir newdir)
(eshell-add-to-dir-ring curdir))
(let ((result (cd newdir)))
+ ;; If we're in "/" and cd to ".." or the like, make things
+ ;; less confusing by changing "/.." to "/".
+ (when (equal (file-truename result) "/")
+ (setq result (cd "/")))
(and eshell-cd-shows-directory
(eshell-printn result)))
(run-hooks 'eshell-directory-change-hook)
@@ -407,6 +403,7 @@ in the minibuffer:
nil))))
(put 'eshell/cd 'eshell-no-numeric-conversions t)
+(put 'eshell/cd 'eshell-filename-arguments t)
(defun eshell-add-to-dir-ring (path)
"Add PATH to the last-dir-ring, if applicable."
@@ -470,6 +467,7 @@ in the minibuffer:
nil)
(put 'eshell/pushd 'eshell-no-numeric-conversions t)
+(put 'eshell/pushd 'eshell-filename-arguments t)
;;; popd [+n]
(defun eshell/popd (&rest args)
@@ -500,6 +498,7 @@ in the minibuffer:
nil)
(put 'eshell/popd 'eshell-no-numeric-conversions t)
+(put 'eshell/pop 'eshell-filename-arguments t)
(defun eshell/dirs (&optional if-verbose)
"Implementation of dirs in Lisp."
@@ -547,15 +546,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)))
@@ -565,7 +565,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)