diff options
author | Stefan Monnier <monnier@iro.umontreal.ca> | 2022-09-25 16:15:16 -0400 |
---|---|---|
committer | Stefan Monnier <monnier@iro.umontreal.ca> | 2022-09-25 16:15:16 -0400 |
commit | 650c20f1ca4e07591a727e1cfcc74b3363d15985 (patch) | |
tree | 85d11f6437cde22f410c25e0e5f71a3131ebd07d /lisp/dired-x.el | |
parent | 8869332684c2302b5ba1ead4568bbc7ba1c0183e (diff) | |
parent | 4b85ae6a24380fb67a3315eaec9233f17a872473 (diff) | |
download | emacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.tar.gz emacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.tar.bz2 emacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.zip |
Merge 'master' into noverlay
Diffstat (limited to 'lisp/dired-x.el')
-rw-r--r-- | lisp/dired-x.el | 1074 |
1 files changed, 226 insertions, 848 deletions
diff --git a/lisp/dired-x.el b/lisp/dired-x.el index 78fa5ed7788..cf1ef37694f 100644 --- a/lisp/dired-x.el +++ b/lisp/dired-x.el @@ -1,7 +1,6 @@ ;;; dired-x.el --- extra Dired functionality -*- lexical-binding:t -*- -;; Copyright (C) 1993-1994, 1997, 2001-2017 Free Software Foundation, -;; Inc. +;; Copyright (C) 1993-2022 Free Software Foundation, Inc. ;; Author: Sebastian Kremer <sk@thp.uni-koeln.de> ;; Lawrence R. Dodd <dodd@roebling.poly.edu> @@ -27,7 +26,7 @@ ;;; Commentary: ;; This is based on Sebastian Kremer's excellent dired-x.el (Dired Extra), -;; version 1.191, adapted for GNU Emacs. See the `dired-x' info pages. +;; version 1.191, adapted for GNU Emacs. See the `dired-x' Info manual. ;; At load time dired-x.el will install itself and bind some dired keys. ;; Some dired.el and dired-aux.el functions have extra features if @@ -35,7 +34,7 @@ ;; User customization: M-x customize-group RET dired-x RET. -;; *Please* see the `dired-x' info pages for more details. +;; *Please* see the `dired-x' Info manual for more details. ;;; Code: @@ -44,65 +43,30 @@ ;; but maybe not if a dired-x function is being autoloaded. (require 'dired) -;;; User-defined variables. + +;;; User-defined variables (defgroup dired-x nil "Extended directory editing (dired-x)." :group 'dired) -(defgroup dired-keys nil - "Dired keys customizations." - :prefix "dired-" - :group 'dired-x) - (defcustom dired-bind-vm nil "Non-nil means \"V\" runs `dired-vm', otherwise \"V\" runs `dired-rmail'. -RMAIL files in the old Babyl format (used before before Emacs 23.1) +RMAIL files in the old Babyl format (used before Emacs 23.1) contain \"-*- rmail -*-\" at the top, so `dired-find-file' will run `rmail' on these files. New RMAIL files use the standard mbox format, and so cannot be distinguished in this way." :type 'boolean - :group 'dired-keys) + :group 'dired-x) -(defcustom dired-bind-jump t - "Non-nil means bind `dired-jump' to C-x C-j, otherwise do not. -Setting this variable directly after dired-x is loaded has no effect - -use \\[customize]." - :type 'boolean - :set (lambda (sym val) - (if (set sym val) - (progn - (define-key ctl-x-map "\C-j" 'dired-jump) - (define-key ctl-x-4-map "\C-j" 'dired-jump-other-window)) - (if (eq 'dired-jump (lookup-key ctl-x-map "\C-j")) - (define-key ctl-x-map "\C-j" nil)) - (if (eq 'dired-jump-other-window (lookup-key ctl-x-4-map "\C-j")) - (define-key ctl-x-4-map "\C-j" nil)))) - :group 'dired-keys) - -(defcustom dired-bind-man t - "Non-nil means bind `dired-man' to \"N\" in Dired, otherwise do not. -Setting this variable directly after dired-x is loaded has no effect - -use \\[customize]." - :type 'boolean - :set (lambda (sym val) - (if (set sym val) - (define-key dired-mode-map "N" 'dired-man) - (if (eq 'dired-man (lookup-key dired-mode-map "N")) - (define-key dired-mode-map "N" nil)))) - :group 'dired-keys) - -(defcustom dired-bind-info t - "Non-nil means bind `dired-info' to \"I\" in Dired, otherwise do not. -Setting this variable directly after dired-x is loaded has no effect - -use \\[customize]." - :type 'boolean - :set (lambda (sym val) - (if (set sym val) - (define-key dired-mode-map "I" 'dired-info) - (if (eq 'dired-info (lookup-key dired-mode-map "I")) - (define-key dired-mode-map "I" nil)))) - :group 'dired-keys) +(defvar dired-bind-jump t) +(make-obsolete-variable 'dired-bind-jump "not used." "28.1") + +(defvar dired-bind-man t) +(make-obsolete-variable 'dired-bind-man "not used." "29.1") + +(defvar dired-bind-info t) +(make-obsolete-variable 'dired-bind-info "not used." "29.1") (defcustom dired-vm-read-only-folders nil "If non-nil, \\[dired-vm] will visit all folders read-only. @@ -113,11 +77,12 @@ files not writable by you are visited read-only." (other :tag "non-writable only" if-file-read-only)) :group 'dired-x) -(defcustom dired-omit-size-limit 30000 +(defcustom dired-omit-size-limit 100000 "Maximum size for the \"omitting\" feature. If nil, there is no maximum size." :type '(choice (const :tag "no maximum" nil) integer) - :group 'dired-x) + :group 'dired-x + :version "29.1") (defcustom dired-omit-case-fold 'filesystem "Determine whether \"omitting\" patterns are case-sensitive. @@ -137,18 +102,49 @@ folding to be used on case-insensitive filesystems only." (file-name-case-insensitive-p dir) dired-omit-case-fold)) -;; For backward compatibility -(define-obsolete-variable-alias 'dired-omit-files-p 'dired-omit-mode "22.1") +(defcustom dired-omit-lines nil + "Regexp matching lines to be omitted by `dired-omit-mode'. +The value can also be a variable whose value is such a regexp. +The value can also be nil, which means do no line matching. + +Some predefined regexp variables for Dired, which you can use as the +option value: + +* `dired-re-inode-size' +* `dired-re-mark' +* `dired-re-maybe-mark' +* `dired-re-dir' +* `dired-re-sym' +* `dired-re-exe' +* `dired-re-perms' +* `dired-re-dot' +* `dired-re-no-dot'" + :type `(choice + (const :tag "Do not match lines to omit" nil) + (regexp + :tag "Regexp to match lines to omit (default omits executables)" + :value ,dired-re-exe) + (restricted-sexp + :tag "Variable with regexp value (default: `dired-re-exe')" + :match-alternatives + ((lambda (obj) (and (symbolp obj) (boundp obj)))) + :value dired-re-exe)) + :group 'dired-x) + +;;;###autoload (define-minor-mode dired-omit-mode "Toggle omission of uninteresting files in Dired (Dired-Omit mode). -With a prefix argument ARG, enable Dired-Omit mode if ARG is -positive, and disable it otherwise. If called from Lisp, enable -the mode if ARG is omitted or nil. +With prefix argument ARG, enable Dired-Omit mode if ARG is positive, +and disable it otherwise. + +If called from Lisp, enable the mode if ARG is omitted or nil. + +Dired-Omit mode is a buffer-local minor mode. -Dired-Omit mode is a buffer-local minor mode. When enabled in a -Dired buffer, Dired does not list files whose filenames match -regexp `dired-omit-files', nor files ending with extensions in -`dired-omit-extensions'. +When enabled in a Dired buffer, Dired does not list files whose +filenames match regexp `dired-omit-files', files ending with +extensions in `dired-omit-extensions', or files listed on lines +matching `dired-omit-lines'. To enable omitting in every Dired buffer, you can put this in your init file: @@ -157,14 +153,20 @@ your init file: See Info node `(dired-x) Omitting Variables' for more information." :group 'dired-x - (if dired-omit-mode - ;; This will mention how many lines were omitted: - (let ((dired-omit-size-limit nil)) (dired-omit-expunge)) - (revert-buffer))) + (if (not dired-omit-mode) + (revert-buffer) + (let ((dired-omit-size-limit nil) + (file-count 0)) + ;; Omit by file-name match, then omit by line match. + ;; Use count of file-name match as INIT-COUNT for line match. + ;; Return total count. (Return value is not used anywhere, so far). + (setq file-count (dired-omit-expunge)) + (when dired-omit-lines + (dired-omit-expunge dired-omit-lines 'LINEP file-count))))) (put 'dired-omit-mode 'safe-local-variable 'booleanp) -(defcustom dired-omit-files "^\\.?#\\|^\\.$\\|^\\.\\.$" +(defcustom dired-omit-files "\\`[.]?#\\|\\`[.][.]?\\'" "Filenames matching this regexp will not be displayed. This only has effect when `dired-omit-mode' is t. See interactive function `dired-omit-mode' (\\[dired-omit-mode]) and variable @@ -194,90 +196,28 @@ toggle between those two." :type 'boolean :group 'dired-x) -(defcustom dired-enable-local-variables t - "Control use of local-variables lists in Dired. -This temporarily overrides the value of `enable-local-variables' when -listing a directory. See also `dired-local-variables-file'." - :risky t - :type '(choice (const :tag "Query Unsafe" t) - (const :tag "Safe Only" :safe) - (const :tag "Do all" :all) - (const :tag "Ignore" nil) - (other :tag "Query" other)) - :group 'dired-x) - -(make-obsolete-variable 'dired-enable-local-variables - "use a standard `dir-locals-file' instead." "24.1") - -(defcustom dired-guess-shell-gnutar - (catch 'found - (dolist (exe '("tar" "gtar")) - (if (with-temp-buffer - (ignore-errors (call-process exe nil t nil "--version")) - (and (re-search-backward "GNU tar" nil t) t)) - (throw 'found exe)))) - "If non-nil, name of GNU tar executable. -\(E.g., \"tar\" or \"gtar\"). The `z' switch will be used with it for -compressed or gzip'ed tar files. If you don't have GNU tar, set this -to nil: a pipe using `zcat' or `gunzip -c' will be used." - ;; Changed from system-type test to testing --version output. - ;; Maybe test --help for -z instead? - :version "24.1" - :type '(choice (const :tag "Not GNU tar" nil) - (string :tag "Command name")) - :group 'dired-x) - -(defcustom dired-guess-shell-gzip-quiet t - "Non-nil says pass -q to gzip overriding verbose GZIP environment." - :type 'boolean - :group 'dired-x) - -(defcustom dired-guess-shell-znew-switches nil - "If non-nil, then string of switches passed to `znew', example: \"-K\"." - :type '(choice (const :tag "None" nil) - (string :tag "Switches")) - :group 'dired-x) - -(defcustom dired-clean-up-buffers-too t - "Non-nil means offer to kill buffers visiting files and dirs deleted in Dired." - :type 'boolean - :group 'dired-x) - -(defcustom dired-clean-confirm-killing-deleted-buffers t - "If nil, don't ask whether to kill buffers visiting deleted files." - :version "26.1" - :type 'boolean - :group 'dired-x) + +;;; Key bindings -;;; KEY BINDINGS. +(when (keymapp (lookup-key dired-mode-map "*")) + (define-key dired-mode-map "*(" 'dired-mark-sexp) + (define-key dired-mode-map "*O" 'dired-mark-omitted) + (define-key dired-mode-map "*." 'dired-mark-extension)) (define-key dired-mode-map "\C-x\M-o" 'dired-omit-mode) -(define-key dired-mode-map "*O" 'dired-mark-omitted) (define-key dired-mode-map "\M-(" 'dired-mark-sexp) -(define-key dired-mode-map "*(" 'dired-mark-sexp) -(define-key dired-mode-map "*." 'dired-mark-extension) (define-key dired-mode-map "\M-!" 'dired-smart-shell-command) -(define-key dired-mode-map "\M-G" 'dired-goto-subdir) (define-key dired-mode-map "F" 'dired-do-find-marked-files) -(define-key dired-mode-map "Y" 'dired-do-relsymlink) -(define-key dired-mode-map "%Y" 'dired-do-relsymlink-regexp) (define-key dired-mode-map "V" 'dired-do-run-mail) -;;; MENU BINDINGS - -(require 'easymenu) + +;;; Menu bindings -(let ((menu (lookup-key dired-mode-map [menu-bar]))) +(when-let ((menu (lookup-key dired-mode-map [menu-bar]))) (easy-menu-add-item menu '("Operate") ["Find Files" dired-do-find-marked-files :help "Find current or marked files"] "Shell Command...") - (easy-menu-add-item menu '("Operate") - ["Relative Symlink to..." dired-do-relsymlink - :visible (fboundp 'make-symbolic-link) - :help "Make relative symbolic links for current or \ -marked files"] - "Hardlink to...") (easy-menu-add-item menu '("Mark") ["Flag Extension..." dired-flag-extension :help "Flag files with a certain extension for deletion"] @@ -291,12 +231,6 @@ marked files"] :help "Mark files matching `dired-omit-files' \ and `dired-omit-extensions'"] "Unmark All") - (easy-menu-add-item menu '("Regexp") - ["Relative Symlink..." dired-do-relsymlink-regexp - :visible (fboundp 'make-symbolic-link) - :help "Make relative symbolic links for files \ -matching regexp"] - "Hardlink...") (easy-menu-add-item menu '("Immediate") ["Omit Mode" dired-omit-mode :style toggle :selected dired-omit-mode @@ -305,7 +239,7 @@ files"] "Refresh")) -;; Install into appropriate hooks. +;;; Install into appropriate hooks (add-hook 'dired-mode-hook 'dired-extra-startup) (add-hook 'dired-after-readin-hook 'dired-omit-expunge) @@ -314,29 +248,23 @@ files"] "Automatically put on `dired-mode-hook' to get extra Dired features: \\<dired-mode-map> \\[dired-do-run-mail]\t-- run mail on folder (see `dired-bind-vm') - \\[dired-info]\t-- run info on file - \\[dired-man]\t-- run man on file \\[dired-do-find-marked-files]\t-- visit all marked files simultaneously \\[dired-omit-mode]\t-- toggle omitting of files \\[dired-mark-sexp]\t-- mark by Lisp expression -To see the options you can set, use M-x customize-group RET dired-x RET. +To see the options you can set, use \\[customize-group] RET dired-x RET. See also the functions: `dired-flag-extension' `dired-virtual' - `dired-jump' - `dired-man' `dired-vm' `dired-rmail' - `dired-info' `dired-do-find-marked-files'" (interactive) ;; These must be done in each new dired buffer. - (dired-hack-local-variables) (dired-omit-startup)) -;;; EXTENSION MARKING FUNCTIONS. +;;; Extension marking functions (defun dired--mark-suffix-interactive-spec () (let* ((default @@ -344,21 +272,19 @@ See also the functions: (when file (file-name-extension file)))) (suffix - (read-string (format "%s extension%s: " - (if (equal current-prefix-arg '(4)) - "UNmarking" - "Marking") - (if default - (format " (default %s)" default) - "")) nil nil default)) + (read-string (format-prompt + "%s extension" default + (if (equal current-prefix-arg '(4)) + "UNmarking" + "Marking")) + nil nil default)) (marker (pcase current-prefix-arg ('(4) ?\s) ('(16) (let* ((dflt (char-to-string dired-marker-char)) (input (read-string - (format - "Marker character to use (default %s): " dflt) + (format-prompt "Marker character to use" dflt) nil nil dflt))) (aref input 0))) (_ dired-marker-char)))) @@ -371,8 +297,8 @@ A `.' is automatically prepended to EXTENSION when not present. EXTENSION may also be a list of extensions instead of a single one. Optional MARKER-CHAR is marker to use. Interactively, ask for EXTENSION. -Prefixed with one C-u, unmark files instead. -Prefixed with two C-u's, prompt for MARKER-CHAR and mark files with it." +Prefixed with one \\[universal-argument], unmark files instead. +Prefixed with two \\[universal-argument]'s, prompt for MARKER-CHAR and mark files with it." (interactive (dired--mark-suffix-interactive-spec)) (unless (listp extension) (setq extension (list extension))) @@ -396,8 +322,8 @@ prepends `.' when not present. SUFFIX may also be a list of suffixes instead of a single one. Optional MARKER-CHAR is marker to use. Interactively, ask for SUFFIX. -Prefixed with one C-u, unmark files instead. -Prefixed with two C-u's, prompt for MARKER-CHAR and mark files with it." +Prefixed with one \\[universal-argument], unmark files instead. +Prefixed with two \\[universal-argument]'s, prompt for MARKER-CHAR and mark files with it." (interactive (dired--mark-suffix-interactive-spec)) (unless (listp suffix) (setq suffix (list suffix))) @@ -465,63 +391,9 @@ See variables `dired-texinfo-unclean-extensions', dired-bibtex-unclean-extensions dired-tex-unclean-extensions (list ".dvi")))) - -(defvar tar-superior-buffer) -;;; JUMP. -;;;###autoload -(defun dired-jump (&optional other-window file-name) - "Jump to Dired buffer corresponding to current buffer. -If in a file, Dired the current directory and move to file's line. -If in Dired already, pop up a level and goto old directory's line. -In case the proper Dired file line cannot be found, refresh the dired -buffer and try again. -When OTHER-WINDOW is non-nil, jump to Dired buffer in other window. -When FILE-NAME is non-nil, jump to its line in Dired. -Interactively with prefix argument, read FILE-NAME." - (interactive - (list nil (and current-prefix-arg - (read-file-name "Jump to Dired file: ")))) - (if (bound-and-true-p tar-subfile-mode) - (switch-to-buffer tar-superior-buffer) - ;; Expand file-name before `dired-goto-file' call: - ;; `dired-goto-file' requires its argument to be an absolute - ;; file name; the result of `read-file-name' could be - ;; an abbreviated file name (Bug#24409). - (let* ((file (or (and file-name (expand-file-name file-name)) - buffer-file-name)) - (dir (if file (file-name-directory file) default-directory))) - (if (and (eq major-mode 'dired-mode) (null file-name)) - (progn - (setq dir (dired-current-directory)) - (dired-up-directory other-window) - (unless (dired-goto-file dir) - ;; refresh and try again - (dired-insert-subdir (file-name-directory dir)) - (dired-goto-file dir))) - (if other-window - (dired-other-window dir) - (dired dir)) - (if file - (or (dired-goto-file file) - ;; refresh and try again - (progn - (dired-insert-subdir (file-name-directory file)) - (dired-goto-file file)) - ;; Toggle omitting, if it is on, and try again. - (when dired-omit-mode - (dired-omit-mode) - (dired-goto-file file)))))))) - -;;;###autoload -(defun dired-jump-other-window (&optional file-name) - "Like \\[dired-jump] (`dired-jump') but in other window." - (interactive - (list (and current-prefix-arg - (read-file-name "Jump to Dired file: ")))) - (dired-jump t file-name)) -;;; OMITTING. +;;; Omitting ;; Enhanced omitting of lines from directory listings. ;; Marked files are never omitted. @@ -534,7 +406,7 @@ If it is `no-dir', omitting is much faster, but you can only match against the non-directory part of the file name. Set it to nil if you need to match the entire file name.") -;; \017=^O for Omit - other packages can chose other control characters. +;; \017=^O for Omit - other packages can choose other control characters. (defvar dired-omit-marker-char ?\017 "Temporary marker used by Dired-Omit. Should never be used as marker by the user or other packages.") @@ -571,45 +443,61 @@ variables `dired-omit-mode' and `dired-omit-files'." :type '(repeat string) :group 'dired-x) -(defun dired-omit-expunge (&optional regexp) - "Erases all unmarked files matching REGEXP. -Does nothing if global variable `dired-omit-mode' is nil, or if called - non-interactively and buffer is bigger than `dired-omit-size-limit'. -If REGEXP is nil or not specified, uses `dired-omit-files', and also omits - filenames ending in `dired-omit-extensions'. -If REGEXP is the empty string, this function is a no-op. - -This functions works by temporarily binding `dired-marker-char' to -`dired-omit-marker-char' and calling `dired-do-kill-lines'." - (interactive "sOmit files (regexp): ") +(defun dired-omit-expunge (&optional regexp linep init-count) + "Erase all unmarked files whose names match REGEXP. +With a prefix arg (non-nil LINEP when called from Lisp), match REGEXP +against the whole line. Otherwise, match it against the file name. + +If REGEXP is nil, use `dired-omit-files', and also omit file names +ending in `dired-omit-extensions'. + +Do nothing if REGEXP is the empty string, `dired-omit-mode' is nil, or +if called from Lisp and buffer is bigger than `dired-omit-size-limit'. + +Optional arg INIT-COUNT is an initial count tha'is added to the number +of lines omitted by this invocation of `dired-omit-expunge', in the +status message." + (interactive "sOmit files (regexp): \nP") + ;; Bind `dired-marker-char' to `dired-omit-marker-char', + ;; then call `dired-do-kill-lines'. (if (and dired-omit-mode (or (called-interactively-p 'interactive) (not dired-omit-size-limit) (< (buffer-size) dired-omit-size-limit) - (progn - (when dired-omit-verbose - (message "Not omitting: directory larger than %d characters." - dired-omit-size-limit)) - (setq dired-omit-mode nil) - nil))) + (progn + (when dired-omit-verbose + (message "Not omitting: directory larger than %d characters." + dired-omit-size-limit)) + (setq dired-omit-mode nil) + nil))) (let ((omit-re (or regexp (dired-omit-regexp))) (old-modified-p (buffer-modified-p)) - count) - (or (string= omit-re "") - (let ((dired-marker-char dired-omit-marker-char)) - (when dired-omit-verbose (message "Omitting...")) - (if (dired-mark-unmarked-files omit-re nil nil dired-omit-localp - (dired-omit-case-fold-p (if (stringp dired-directory) - dired-directory - (car dired-directory)))) - (progn - (setq count (dired-do-kill-lines - nil - (if dired-omit-verbose "Omitted %d line%s." ""))) - (force-mode-line-update)) - (when dired-omit-verbose (message "(Nothing to omit)"))))) - ;; Try to preserve modified state of buffer. So `%*' doesn't appear - ;; in mode-line of omitted buffers. + (count (or init-count 0))) + (unless (string= omit-re "") + (let ((dired-marker-char dired-omit-marker-char)) + (when dired-omit-verbose (message "Omitting...")) + (if (not (if linep + (dired-mark-if + (and (= (following-char) ?\s) ; Not already marked + (string-match-p + omit-re (buffer-substring + (line-beginning-position) + (line-end-position)))) + nil) + (dired-mark-unmarked-files + omit-re nil nil dired-omit-localp + (dired-omit-case-fold-p (if (stringp dired-directory) + dired-directory + (car dired-directory)))))) + (when dired-omit-verbose (message "(Nothing to omit)")) + (setq count (+ count + (dired-do-kill-lines + nil + (if dired-omit-verbose "Omitted %d line%s" "") + init-count))) + (force-mode-line-update)))) + ;; Try to preserve modified state, so `%*' doesn't appear in + ;; `mode-line'. (set-buffer-modified-p (and old-modified-p (save-excursion (goto-char (point-min)) @@ -634,18 +522,23 @@ interactively, prompt for REGEXP. With prefix argument, unflag all those files. Optional fourth argument LOCALP is as in `dired-get-filename'. Optional fifth argument CASE-FOLD-P specifies the value of -`case-fold-search' used for matching REGEXP." +`case-fold-search' used for matching REGEXP. +If the region is active in Transient Mark mode, operate only on +files in the active region if `dired-mark-region' is non-nil." (interactive (list (read-regexp - "Mark unmarked files matching regexp (default all): " + (format-prompt "Mark unmarked files matching regexp" "all") nil 'dired-regexp-history) nil current-prefix-arg nil)) (let ((dired-marker-char (if unflag-p ?\s dired-marker-char))) (dired-mark-if (and - ;; not already marked - (= (following-char) ?\s) - ;; uninteresting + (if unflag-p + ;; Already marked. + (not (= (following-char) ?\s)) + ;; Not already marked. + (= (following-char) ?\s)) + ;; Interesting. (let ((fn (dired-get-filename localp t)) ;; Match patterns case-insensitively on case-insensitive ;; systems @@ -654,29 +547,30 @@ Optional fifth argument CASE-FOLD-P specifies the value of msg))) -;;; VIRTUAL DIRED MODE. +;;; Virtual dired mode ;; For browsing `ls -lR' listings in a dired-like fashion. (defalias 'virtual-dired 'dired-virtual) (defun dired-virtual (dirname &optional switches) - "Put this buffer into Virtual Dired mode. + "Treat the current buffer as a Dired buffer showing directory DIRNAME. +Interactively, prompt for DIRNAME. -In Virtual Dired mode, all commands that do not actually consult the -filesystem will work. +This command is rarely useful, but may be convenient if you want +to peruse and move around in the output you got from \"ls +-lR\" (or something similar), without having access to the actual +file system. -This is useful if you want to peruse and move around in an ls -lR -output file, for example one you got from an ftp server. With -ange-ftp, you can even Dired a directory containing an ls-lR file, -visit that file and turn on Virtual Dired mode. But don't try to save -this file, as dired-virtual indents the listing and thus changes the -buffer. +Most Dired commands that don't consult the file system will work +as advertised, but commands that try to alter the file system +will usually fail. (However, if the output is from the current +system, most of those commands will work fine.) -If you have save a Dired buffer in a file you can use \\[dired-virtual] to +If you have saved a Dired buffer in a file you can use \\[dired-virtual] to resume it in a later session. Type \\<dired-mode-map>\\[revert-buffer] \ -in the Virtual Dired buffer and answer `y' to convert +in the Virtual Dired buffer and answer \\`y' to convert the virtual to a real Dired buffer again. You don't have to do this, though: you can relist single subdirs using \\[dired-do-redisplay]." @@ -692,7 +586,8 @@ you can relist single subdirs using \\[dired-do-redisplay]." ;; hand if you want them. (interactive - (list (read-string "Virtual Dired directory: " (dired-virtual-guess-dir)))) + (list (read-directory-name "Virtual Dired directory: " + nil (dired-virtual-guess-dir)))) (goto-char (point-min)) (or (looking-at-p " ") ;; if not already indented, do it now: @@ -706,7 +601,7 @@ you can relist single subdirs using \\[dired-do-redisplay]." (and (looking-at "^ wildcard ") (buffer-substring (match-end 0) (line-end-position)))))) - (if wildcard + (if wildcard (setq dirname (expand-file-name wildcard default-directory)))) ;; If raw ls listing (not a saved old dired buffer), give it a ;; decent subdir headerline: @@ -717,8 +612,8 @@ you can relist single subdirs using \\[dired-do-redisplay]." ":\n")) (dired-mode dirname (or switches dired-listing-switches)) (setq mode-name "Virtual Dired" - revert-buffer-function 'dired-virtual-revert) - (set (make-local-variable 'dired-subdir-alist) nil) + revert-buffer-function 'dired-virtual-revert + dired-subdir-alist nil) (dired-build-subdir-alist) (goto-char (point-min)) (dired-initial-position dirname)) @@ -776,7 +671,7 @@ Also useful for `auto-mode-alist' like this: (dired-virtual (dired-virtual-guess-dir))) -;;; SMART SHELL. +;;; Smart shell ;; An Emacs buffer can have but one working directory, stored in the ;; buffer-local variable `default-directory'. A Dired buffer may have @@ -787,34 +682,6 @@ Also useful for `auto-mode-alist' like this: ;; mechanism is provided for special handling of the working directory in ;; special major modes. -(define-obsolete-variable-alias 'default-directory-alist - 'dired-default-directory-alist "24.1") - -;; It's easier to add to this alist than redefine function -;; default-directory while keeping the old information. -(defconst dired-default-directory-alist - '((dired-mode . (if (fboundp 'dired-current-directory) - (dired-current-directory) - default-directory))) - "Alist of major modes and their opinion on `default-directory'. -Each element has the form (MAJOR . EXPRESSION). -The function `dired-default-directory' evaluates EXPRESSION to -determine a default directory.") - -(put 'dired-default-directory-alist 'risky-local-variable t) ; gets eval'd -(make-obsolete-variable 'dired-default-directory-alist - "this feature is due to be removed." "24.1") - -(defun dired-default-directory () - "Return the `dired-default-directory-alist' entry for the current major-mode. -If none, return `default-directory'." - ;; It looks like this was intended to be something of a "general" - ;; feature, but it only ever seems to have been used in - ;; dired-smart-shell-command, and doesn't seem worth keeping around. - (declare (obsolete nil "24.1")) - (or (eval (cdr (assq major-mode dired-default-directory-alist))) - default-directory)) - (defun dired-smart-shell-command (command &optional output-buffer error-buffer) "Like function `shell-command', but in the current Virtual Dired directory." (interactive @@ -831,495 +698,30 @@ If none, return `default-directory'." (shell-command command output-buffer error-buffer))) -;;; LOCAL VARIABLES FOR DIRED BUFFERS. - -;; Brief Description (This feature is obsolete as of Emacs 24.1) -;; -;; * `dired-extra-startup' is part of the `dired-mode-hook'. -;; -;; * `dired-extra-startup' calls `dired-hack-local-variables' -;; -;; * `dired-hack-local-variables' checks the value of -;; `dired-local-variables-file' -;; -;; * Check if `dired-local-variables-file' is a non-nil string and is a -;; filename found in the directory of the Dired Buffer being created. -;; -;; * If `dired-local-variables-file' satisfies the above, then temporarily -;; include it in the Dired Buffer at the bottom. -;; -;; * Set `enable-local-variables' temporarily to the user variable -;; `dired-enable-local-variables' and run `hack-local-variables' on the -;; Dired Buffer. - -(defcustom dired-local-variables-file (convert-standard-filename ".dired") - "Filename, as string, containing local Dired buffer variables to be hacked. -If this file found in current directory, then it will be inserted into dired -buffer and `hack-local-variables' will be run. See Info node -`(emacs)File Variables' for more information on local variables. -See also `dired-enable-local-variables'." - :type 'file - :group 'dired) - -(make-obsolete-variable 'dired-local-variables-file 'dir-locals-file "24.1") - -(defun dired-hack-local-variables () - "Evaluate local variables in `dired-local-variables-file' for Dired buffer." - (declare (obsolete hack-dir-local-variables-non-file-buffer "24.1")) - (and (stringp dired-local-variables-file) - (file-exists-p dired-local-variables-file) - (let ((opoint (point-max)) - (inhibit-read-only t) - ;; In case user has `enable-local-variables' set to nil we - ;; override it locally with dired's variable. - (enable-local-variables dired-enable-local-variables)) - ;; Insert 'em. - (save-excursion - (goto-char opoint) - (insert "\^L\n") - (insert-file-contents dired-local-variables-file)) - ;; Hack 'em. - (unwind-protect - (let ((buffer-file-name dired-local-variables-file)) - (hack-local-variables)) - ;; Delete this stuff: `eobp' is used to find last subdir by dired.el. - (delete-region opoint (point-max))) - ;; Make sure that the mode line shows the proper information. - (dired-sort-set-mode-line)))) - -;; Does not seem worth a dedicated command. -;; See the more general features in files-x.el. -(defun dired-omit-here-always () - "Create `dir-locals-file' setting `dired-omit-mode' to t in `dired-mode'. -If in a Dired buffer, reverts it." - (declare (obsolete add-dir-local-variable "24.1")) - (interactive) - (if (file-exists-p dired-local-variables-file) - (error "Old-style dired-local-variables-file `./%s' found; -replace it with a dir-locals-file `./%s'" - dired-local-variables-file - dir-locals-file)) - (if (file-exists-p dir-locals-file) - (message "File `./%s' already exists." dir-locals-file) - (add-dir-local-variable 'dired-mode 'subdirs nil) - (add-dir-local-variable 'dired-mode 'dired-omit-mode t) - ;; Run extra-hooks and revert directory. - (when (derived-mode-p 'dired-mode) - (hack-dir-local-variables-non-file-buffer) - (dired-extra-startup) - (dired-revert)))) - - -;;; GUESS SHELL COMMAND. - -;; Brief Description: -;;; -;; * `dired-do-shell-command' is bound to `!' by dired.el. -;;; -;; * `dired-guess-shell-command' provides smarter defaults for -;;; dired-aux.el's `dired-read-shell-command'. -;;; -;; * `dired-guess-shell-command' calls `dired-guess-default' with list of -;;; marked files. -;;; -;; * Parse `dired-guess-shell-alist-user' and -;;; `dired-guess-shell-alist-default' (in that order) for the first REGEXP -;;; that matches the first file in the file list. -;;; -;; * If the REGEXP matches all the entries of the file list then evaluate -;;; COMMAND, which is either a string or a Lisp expression returning a -;;; string. COMMAND may be a list of commands. -;;; -;; * Return this command to `dired-guess-shell-command' which prompts user -;;; with it. The list of commands is put into the list of default values. -;;; If a command is used successfully then it is stored permanently in -;;; `dired-shell-command-history'. - -;; Guess what shell command to apply to a file. -(defvar dired-shell-command-history nil - "History list for commands that read dired-shell commands.") - -;; Default list of shell commands. - -;; NOTE: Use `gunzip -c' instead of `zcat' on `.gz' files. Some do not -;; install GNU zip's version of zcat. - -(autoload 'Man-support-local-filenames "man") - -(defvar dired-guess-shell-alist-default - (list - (list "\\.tar\\'" - '(if dired-guess-shell-gnutar - (concat dired-guess-shell-gnutar " xvf") - "tar xvf") - ;; Extract files into a separate subdirectory - '(if dired-guess-shell-gnutar - (concat "mkdir " (file-name-sans-extension file) - "; " dired-guess-shell-gnutar " -C " - (file-name-sans-extension file) " -xvf") - (concat "mkdir " (file-name-sans-extension file) - "; tar -C " (file-name-sans-extension file) " -xvf")) - ;; List archive contents. - '(if dired-guess-shell-gnutar - (concat dired-guess-shell-gnutar " tvf") - "tar tvf")) - - ;; REGEXPS for compressed archives must come before the .Z rule to - ;; be recognized: - (list "\\.tar\\.Z\\'" - ;; Untar it. - '(if dired-guess-shell-gnutar - (concat dired-guess-shell-gnutar " zxvf") - (concat "zcat * | tar xvf -")) - ;; Optional conversion to gzip format. - '(concat "znew" (if dired-guess-shell-gzip-quiet " -q") - " " dired-guess-shell-znew-switches)) - - ;; gzip'ed archives - (list "\\.t\\(ar\\.\\)?gz\\'" - '(if dired-guess-shell-gnutar - (concat dired-guess-shell-gnutar " zxvf") - (concat "gunzip -qc * | tar xvf -")) - ;; Extract files into a separate subdirectory - '(if dired-guess-shell-gnutar - (concat "mkdir " (file-name-sans-extension file) - "; " dired-guess-shell-gnutar " -C " - (file-name-sans-extension file) " -zxvf") - (concat "mkdir " (file-name-sans-extension file) - "; gunzip -qc * | tar -C " - (file-name-sans-extension file) " -xvf -")) - ;; Optional decompression. - '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q" "")) - ;; List archive contents. - '(if dired-guess-shell-gnutar - (concat dired-guess-shell-gnutar " ztvf") - (concat "gunzip -qc * | tar tvf -"))) - - ;; bzip2'ed archives - (list "\\.t\\(ar\\.bz2\\|bz\\)\\'" - "bunzip2 -c * | tar xvf -" - ;; Extract files into a separate subdirectory - '(concat "mkdir " (file-name-sans-extension file) - "; bunzip2 -c * | tar -C " - (file-name-sans-extension file) " -xvf -") - ;; Optional decompression. - "bunzip2") - - ;; xz'ed archives - (list "\\.t\\(ar\\.\\)?xz\\'" - "unxz -c * | tar xvf -" - ;; Extract files into a separate subdirectory - '(concat "mkdir " (file-name-sans-extension file) - "; unxz -c * | tar -C " - (file-name-sans-extension file) " -xvf -") - ;; Optional decompression. - "unxz") - - '("\\.shar\\.Z\\'" "zcat * | unshar") - '("\\.shar\\.g?z\\'" "gunzip -qc * | unshar") - - '("\\.e?ps\\'" "ghostview" "xloadimage" "lpr") - (list "\\.e?ps\\.g?z\\'" "gunzip -qc * | ghostview -" - ;; Optional decompression. - '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q"))) - (list "\\.e?ps\\.Z\\'" "zcat * | ghostview -" - ;; Optional conversion to gzip format. - '(concat "znew" (if dired-guess-shell-gzip-quiet " -q") - " " dired-guess-shell-znew-switches)) - - '("\\.patch\\'" "cat * | patch") - (list "\\.patch\\.g?z\\'" "gunzip -qc * | patch" - ;; Optional decompression. - '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q"))) - (list "\\.patch\\.Z\\'" "zcat * | patch" - ;; Optional conversion to gzip format. - '(concat "znew" (if dired-guess-shell-gzip-quiet " -q") - " " dired-guess-shell-znew-switches)) - - ;; The following four extensions are useful with dired-man ("N" key) - ;; FIXME "man ./" does not work with dired-do-shell-command, - ;; because there seems to be no way for us to modify the filename, - ;; only the command. Hmph. `dired-man' works though. - (list "\\.\\(?:[0-9]\\|man\\)\\'" - '(let ((loc (Man-support-local-filenames))) - (cond ((eq loc 'man-db) "man -l") - ((eq loc 'man) "man ./") - (t - "cat * | tbl | nroff -man -h | col -b")))) - (list "\\.\\(?:[0-9]\\|man\\)\\.g?z\\'" - '(let ((loc (Man-support-local-filenames))) - (cond ((eq loc 'man-db) - "man -l") - ((eq loc 'man) - "man ./") - (t "gunzip -qc * | tbl | nroff -man -h | col -b"))) - ;; Optional decompression. - '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q"))) - (list "\\.[0-9]\\.Z\\'" - '(let ((loc (Man-support-local-filenames))) - (cond ((eq loc 'man-db) "man -l") - ((eq loc 'man) "man ./") - (t "zcat * | tbl | nroff -man -h | col -b"))) - ;; Optional conversion to gzip format. - '(concat "znew" (if dired-guess-shell-gzip-quiet " -q") - " " dired-guess-shell-znew-switches)) - '("\\.pod\\'" "perldoc" "pod2man * | nroff -man") - - '("\\.dvi\\'" "xdvi" "dvips") ; preview and printing - '("\\.au\\'" "play") ; play Sun audiofiles - '("\\.mpe?g\\'\\|\\.avi\\'" "xine -p") - '("\\.ogg\\'" "ogg123") - '("\\.mp3\\'" "mpg123") - '("\\.wav\\'" "play") - '("\\.uu\\'" "uudecode") ; for uudecoded files - '("\\.hqx\\'" "mcvert") - '("\\.sh\\'" "sh") ; execute shell scripts - '("\\.xbm\\'" "bitmap") ; view X11 bitmaps - '("\\.gp\\'" "gnuplot") - '("\\.p[bgpn]m\\'" "xloadimage") - '("\\.gif\\'" "xloadimage") ; view gif pictures - '("\\.tif\\'" "xloadimage") - '("\\.png\\'" "display") ; xloadimage 4.1 doesn't grok PNG - '("\\.jpe?g\\'" "xloadimage") - '("\\.fig\\'" "xfig") ; edit fig pictures - '("\\.out\\'" "xgraph") ; for plotting purposes. - '("\\.tex\\'" "latex" "tex") - '("\\.texi\\(nfo\\)?\\'" "makeinfo" "texi2dvi") - '("\\.pdf\\'" "xpdf") - '("\\.doc\\'" "antiword" "strings") - '("\\.rpm\\'" "rpm -qilp" "rpm -ivh") - '("\\.dia\\'" "dia") - '("\\.mgp\\'" "mgp") - - ;; Some other popular archivers. - (list "\\.zip\\'" "unzip" "unzip -l" - ;; Extract files into a separate subdirectory - '(concat "unzip" (if dired-guess-shell-gzip-quiet " -q") - " -d " (file-name-sans-extension file))) - '("\\.zoo\\'" "zoo x//") - '("\\.lzh\\'" "lharc x") - '("\\.arc\\'" "arc x") - '("\\.shar\\'" "unshar") - '("\\.rar\\'" "unrar x") - '("\\.7z\\'" "7z x") - - ;; Compression. - (list "\\.g?z\\'" '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q"))) - (list "\\.dz\\'" "dictunzip") - (list "\\.bz2\\'" "bunzip2") - (list "\\.xz\\'" "unxz") - (list "\\.Z\\'" "uncompress" - ;; Optional conversion to gzip format. - '(concat "znew" (if dired-guess-shell-gzip-quiet " -q") - " " dired-guess-shell-znew-switches)) - - '("\\.sign?\\'" "gpg --verify")) - - "Default alist used for shell command guessing. -See `dired-guess-shell-alist-user'.") - -(defcustom dired-guess-shell-alist-user nil - "User-defined alist of rules for suggested commands. -These rules take precedence over the predefined rules in the variable -`dired-guess-shell-alist-default' (to which they are prepended). - -Each element of this list looks like - - (REGEXP COMMAND...) - -where each COMMAND can either be a string or a Lisp expression that evaluates -to a string. This expression can access the file name as the variable `file'. -If several COMMANDs are given, the first one will be the default -and the rest will be added temporarily to the history and can be retrieved -with \\[previous-history-element] (M-p) . - -The variable `dired-guess-shell-case-fold-search' controls whether -REGEXP is matched case-sensitively." - :group 'dired-x - :type '(alist :key-type regexp :value-type (repeat sexp))) - -(defcustom dired-guess-shell-case-fold-search t - "If non-nil, `dired-guess-shell-alist-default' and -`dired-guess-shell-alist-user' are matched case-insensitively." - :group 'dired-x - :type 'boolean) - -(defun dired-guess-default (files) - "Return a shell command, or a list of commands, appropriate for FILES. -See `dired-guess-shell-alist-user'." - - (let* ((case-fold-search dired-guess-shell-case-fold-search) - ;; Prepend the user's alist to the default alist. - (alist (append dired-guess-shell-alist-user - dired-guess-shell-alist-default)) - (file (car files)) - (flist (cdr files)) - elt regexp cmds) - - ;; Find the first match in the alist for first file in FILES. - (while alist - (setq elt (car alist) - regexp (car elt) - alist (cdr alist)) - (if (string-match-p regexp file) - (setq cmds (cdr elt) - alist nil))) - - ;; If more than one file, see if all of FILES match regular expression. - (while (and flist - (string-match-p regexp (car flist))) - (setq flist (cdr flist))) - - ;; If flist is still non-nil, then do not guess since this means that not - ;; all the files in FILES were matched by the regexp. - (setq cmds (and (not flist) cmds)) - - ;; Return commands or nil if flist is still non-nil. - ;; Evaluate the commands in order that any logical testing will be done. - (if (cdr cmds) - (delete-dups (mapcar (lambda (cmd) (eval cmd `((file . ,file)))) cmds)) - (eval (car cmds) `((file . ,file)))))) ; single command - -(defun dired-guess-shell-command (prompt files) - "Ask user with PROMPT for a shell command, guessing a default from FILES." - (let ((default (dired-guess-default files)) - default-list val) - (if (null default) - ;; Nothing to guess - (read-shell-command prompt nil 'dired-shell-command-history) - (setq prompt (replace-regexp-in-string ": $" " " prompt)) - (if (listp default) - ;; More than one guess - (setq default-list default - default (car default) - prompt (concat - prompt - (format "{%d guesses} " (length default-list)))) - ;; Just one guess - (setq default-list (list default))) - ;; Put the first guess in the prompt but not in the initial value. - (setq prompt (concat prompt (format "[%s]: " default))) - ;; All guesses can be retrieved with M-n - (setq val (read-shell-command prompt nil - 'dired-shell-command-history - default-list)) - ;; If we got a return, then return default. - (if (equal val "") default val)))) - - -;;; RELATIVE SYMBOLIC LINKS. - -(declare-function make-symbolic-link "fileio.c") - -(defvar dired-keep-marker-relsymlink ?S - "See variable `dired-keep-marker-move'.") - -(defun dired-make-relative-symlink (file1 file2 &optional ok-if-already-exists) - "Make a symbolic link (pointing to FILE1) in FILE2. -The link is relative (if possible), for example - - \"/vol/tex/bin/foo\" \"/vol/local/bin/foo\" - -results in - - \"../../tex/bin/foo\" \"/vol/local/bin/foo\"" - (interactive "FRelSymLink: \nFRelSymLink %s: \np") - (let (name1 name2 len1 len2 (index 0) sub) - (setq file1 (expand-file-name file1) - file2 (expand-file-name file2) - len1 (length file1) - len2 (length file2)) - ;; Find common initial file name components: - (let (next) - (while (and (setq next (string-match "/" file1 index)) - (< (setq next (1+ next)) (min len1 len2)) - ;; For the comparison, both substrings must end in - ;; `/', so NEXT is *one plus* the result of the - ;; string-match. - ;; E.g., consider the case of linking "/tmp/a/abc" - ;; to "/tmp/abc" erroneously giving "/tmp/a" instead - ;; of "/tmp/" as common initial component - (string-equal (substring file1 0 next) - (substring file2 0 next))) - (setq index next)) - (setq name2 file2 - sub (substring file1 0 index) - name1 (substring file1 index))) - (if (string-equal sub "/") - ;; No common initial file name found - (setq name1 file1) - ;; Else they have a common parent directory - (let ((tem (substring file2 index)) - (start 0) - (count 0)) - ;; Count number of slashes we must compensate for ... - (while (setq start (string-match "/" tem start)) - (setq count (1+ count) - start (1+ start))) - ;; ... and prepend a "../" for each slash found: - (dotimes (_ count) - (setq name1 (concat "../" name1))))) - (make-symbolic-link - (directory-file-name name1) ; must not link to foo/ - ; (trailing slash!) - name2 ok-if-already-exists))) - -(autoload 'dired-do-create-files "dired-aux") - -;;;###autoload -(defun dired-do-relsymlink (&optional arg) - "Relative symlink all marked (or next ARG) files into a directory. -Otherwise make a relative symbolic link to the current file. -This creates relative symbolic links like - - foo -> ../bar/foo - -not absolute ones like - - foo -> /ugly/file/name/that/may/change/any/day/bar/foo - -For absolute symlinks, use \\[dired-do-symlink]." - (interactive "P") - (dired-do-create-files 'relsymlink #'dired-make-relative-symlink - "RelSymLink" arg dired-keep-marker-relsymlink)) - -(autoload 'dired-mark-read-regexp "dired-aux") -(autoload 'dired-do-create-files-regexp "dired-aux") - -(defun dired-do-relsymlink-regexp (regexp newname &optional arg whole-name) - "RelSymlink all marked files containing REGEXP to NEWNAME. -See functions `dired-do-rename-regexp' and `dired-do-relsymlink' -for more info." - (interactive (dired-mark-read-regexp "RelSymLink")) - (dired-do-create-files-regexp - #'dired-make-relative-symlink - "RelSymLink" arg regexp newname whole-name dired-keep-marker-relsymlink)) - - -;;; VISIT ALL MARKED FILES SIMULTANEOUSLY. +;;; Visit all marked files simultaneously ;; Brief Description: -;;; +;; ;; `dired-do-find-marked-files' is bound to `F' by dired-x.el. -;;; +;; ;; * Use `dired-get-marked-files' to collect the marked files in the current -;;; Dired Buffer into a list of filenames `FILE-LIST'. -;;; +;; Dired Buffer into a list of filenames `FILE-LIST'. +;; ;; * Pass FILE-LIST to `dired-simultaneous-find-file' all with -;;; `dired-do-find-marked-files''s prefix argument NOSELECT. -;;; +;; `dired-do-find-marked-files''s prefix argument NOSELECT. +;; ;; * `dired-simultaneous-find-file' runs through FILE-LIST decrementing the -;;; list each time. -;;; +;; list each time. +;; ;; * If NOSELECT is non-nil then just run `find-file-noselect' on each -;;; element of FILE-LIST. -;;; +;; element of FILE-LIST. +;; ;; * If NOSELECT is nil then calculate the `size' of the window for each file -;;; by dividing the `window-height' by length of FILE-LIST. Thus, `size' is -;;; cognizant of the window-configuration. -;;; +;; by dividing the `window-height' by length of FILE-LIST. Thus, `size' is +;; cognizant of the window-configuration. +;; ;; * If `size' is too small abort, otherwise run `find-file' on each element -;;; of FILE-LIST giving each a window of height `size'. +;; of FILE-LIST giving each a window of height `size'. (defun dired-do-find-marked-files (&optional noselect) "Find all marked files displaying all of them simultaneously. @@ -1333,7 +735,8 @@ displayed this way is restricted by the height of the current window and To keep Dired buffer displayed, type \\[split-window-below] first. To display just marked files, type \\[delete-other-windows] first." (interactive "P") - (dired-simultaneous-find-file (dired-get-marked-files) noselect)) + (dired-simultaneous-find-file (dired-get-marked-files nil nil nil nil t) + noselect)) (defun dired-simultaneous-find-file (file-list noselect) "Visit all files in FILE-LIST and display them simultaneously. @@ -1364,32 +767,7 @@ NOSELECT the files are merely found but not selected." (find-file file))))) -;;; MISCELLANEOUS COMMANDS. - -;; Run man on files. - -(declare-function Man-getpage-in-background "man" (topic)) - -(defvar manual-program) ; from man.el - -(defun dired-man () - "Run `man' on this file." -;; Used also to say: "Display old buffer if buffer name matches filename." -;; but I have no idea what that means. - (interactive) - (require 'man) - (let* ((file (dired-get-filename)) - (manual-program (replace-regexp-in-string "\\*" "%s" - (dired-guess-shell-command - "Man command: " (list file))))) - (Man-getpage-in-background file))) - -;; Run Info on files. - -(defun dired-info () - "Run `info' on this file." - (interactive) - (info (dired-get-filename))) +;;; Miscellaneous commands ;; Run mail on mail folders. @@ -1408,7 +786,7 @@ Otherwise obeys the value of `dired-vm-read-only-folders'." (and dired-vm-read-only-folders (not (file-writable-p fil))))) ;; So that pressing `v' inside VM does prompt within current directory: - (set (make-local-variable 'vm-folder-directory) dir))) + (setq-local vm-folder-directory dir))) (defun dired-rmail () "Run RMAIL on this file." @@ -1432,17 +810,8 @@ otherwise." (dired-rmail))))) -;;; MISCELLANEOUS INTERNAL FUNCTIONS. - -;; This should be a builtin -(defun dired-buffer-more-recently-used-p (buffer1 buffer2) - "Return t if BUFFER1 is more recently used than BUFFER2. -Considers buffers closer to the car of `buffer-list' to be more recent." - (and (not (equal buffer1 buffer2)) - (memq buffer1 (buffer-list)) - (not (memq buffer1 (memq buffer2 (buffer-list)))))) +;;; Miscellaneous internal functions - ;; Needed if ls -lh is supported and also for GNU ls -ls. (defun dired-x--string-to-number (str) "Like `string-to-number' but recognize a trailing unit prefix. @@ -1451,13 +820,21 @@ sure that a trailing letter in STR is one of BKkMGTPEZY." (let* ((val (string-to-number str)) (u (unless (zerop val) (aref str (1- (length str)))))) - (when (and u (> u ?9)) - (when (= u ?k) - (setq u ?K)) - (let ((units '(?B ?K ?M ?G ?T ?P ?E ?Z ?Y))) - (while (and units (/= (pop units) u)) - (setq val (* 1024.0 val))))) - val)) + ;; If we don't have a unit at the end, but we have some + ;; non-numeric strings in the string, then the string may be + ;; something like "4.134" or "4,134" meant to represent 4134 + ;; (seen in some locales). + (if (and u + (<= ?0 u ?9) + (string-match-p "[^0-9]" str)) + (string-to-number (replace-regexp-in-string "[^0-9]+" "" str)) + (when (and u (> u ?9)) + (when (= u ?k) + (setq u ?K)) + (let ((units '(?B ?K ?M ?G ?T ?P ?E ?Z ?Y))) + (while (and units (/= (pop units) u)) + (setq val (* 1024.0 val))))) + val))) (defun dired-mark-sexp (predicate &optional unflag-p) "Mark files for which PREDICATE returns non-nil. @@ -1494,7 +871,9 @@ present for some values of `ls-lisp-emulation'. This function operates only on the buffer content and does not refer at all to the underlying file system. Contrast this with -`find-dired', which might be preferable for the task at hand." +`find-dired', which might be preferable for the task at hand. +If the region is active in Transient Mark mode, mark files +only in the active region if `dired-mark-region' is non-nil." ;; Using sym="" instead of nil avoids the trap of ;; (string-match "foo" sym) into which a user would soon fall. ;; Give `equal' instead of `=' in the example, as this works on @@ -1613,7 +992,7 @@ refer at all to the underlying file system. Contrast this with (format "'%s file" predicate)))) -;;; FIND FILE AT POINT. +;;; Find file at point (defcustom dired-x-hands-off-my-keys t "Non-nil means don't remap `find-file' to `dired-x-find-file'. @@ -1634,12 +1013,13 @@ Binding direction based on `dired-x-hands-off-my-keys'." (interactive) (if (called-interactively-p 'interactive) (setq dired-x-hands-off-my-keys - (not (y-or-n-p "Bind dired-x-find-file over find-file? ")))) + (not (y-or-n-p (format-message + "Bind `dired-x-find-file' over `find-file'?"))))) (unless dired-x-hands-off-my-keys - (define-key (current-global-map) [remap find-file] - 'dired-x-find-file) - (define-key (current-global-map) [remap find-file-other-window] - 'dired-x-find-file-other-window))) + (keymap-set (current-global-map) "<remap> <find-file>" + #'dired-x-find-file) + (keymap-set (current-global-map) "<remap> <find-file-other-window>" + #'dired-x-find-file-other-window))) ;; Now call it so binding is correct. This could go in the :initialize ;; slot, but then dired-x-bind-find-file has to be defined before the @@ -1660,12 +1040,15 @@ a prefix argument, when it offers the filename near point as a default." (interactive (list (dired-x-read-filename-at-point "Find file: "))) (find-file-other-window filename)) -;;; Internal functions. + +;;; Internal functions -;; Fixme: This should probably use `thing-at-point'. -- fx -(defun dired-filename-at-point () +(define-obsolete-function-alias 'dired-filename-at-point + #'dired-x-guess-file-name-at-point "28.1") +(defun dired-x-guess-file-name-at-point () "Return the filename closest to point, expanded. Point should be in or after a filename." + (declare (obsolete "use (thing-at-point 'filename) instead." "29.1")) (save-excursion ;; First see if just past a filename. (or (eobp) ; why? @@ -1697,26 +1080,21 @@ Point should be in or after a filename." "Return filename prompting with PROMPT with completion. If `current-prefix-arg' is non-nil, uses name at point as guess." (if current-prefix-arg - (let ((guess (dired-filename-at-point))) + (let ((guess (thing-at-point 'filename))) (read-file-name prompt (file-name-directory guess) guess nil (file-name-nondirectory guess))) (read-file-name prompt default-directory))) -(define-obsolete-function-alias 'read-filename-at-point - 'dired-x-read-filename-at-point "24.1") ; is this even needed? - -;;; BUG REPORTS - -(define-obsolete-function-alias 'dired-x-submit-report 'report-emacs-bug "24.1") +(define-obsolete-function-alias 'dired-man #'dired-do-man "29.1") +(define-obsolete-function-alias 'dired-info #'dired-do-info "29.1") ;; As Barry Warsaw would say: "This might be useful..." (provide 'dired-x) ;; Local Variables: -;; byte-compile-dynamic: t ;; generated-autoload-file: "dired-loaddefs.el" ;; End: |