From d802719cffb4836eed3524ee8f6905068d6ac16f Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Tue, 26 Mar 2019 11:58:20 +0000 Subject: [PATCH] Update vendored dired+ package --- vendor/dired+.el | 1740 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 1373 insertions(+), 367 deletions(-) diff --git a/vendor/dired+.el b/vendor/dired+.el index 0855d24..0f6ed1f 100644 --- a/vendor/dired+.el +++ b/vendor/dired+.el @@ -4,13 +4,13 @@ ;; Description: Extensions to Dired. ;; Author: Drew Adams ;; Maintainer: Drew Adams (concat "drew.adams" "@" "oracle" ".com") -;; Copyright (C) 1999-2018, Drew Adams, all rights reserved. +;; Copyright (C) 1999-2019, Drew Adams, all rights reserved. ;; Created: Fri Mar 19 15:58:58 1999 ;; Version: 2017.10.23 ;; Package-Requires: () -;; Last-Updated: Sun Mar 25 11:18:04 2018 (-0700) +;; Last-Updated: Wed Mar 20 20:35:35 2019 (-0700) ;; By: dradams -;; Update #: 10917 +;; Update #: 11516 ;; URL: https://www.emacswiki.org/emacs/download/dired%2b.el ;; Doc URL: https://www.emacswiki.org/emacs/DiredPlus ;; Keywords: unix, mouse, directories, diredp, dired @@ -18,15 +18,21 @@ ;; ;; Features that might be required by this library: ;; -;; `apropos', `apropos+', `autofit-frame', `avoid', `bookmark', -;; `bookmark+', `bookmark+-1', `bookmark+-bmu', `bookmark+-key', -;; `bookmark+-lit', `dired', `dired+', `dired-aux', `dired-x', -;; `easymenu', `ffap', `fit-frame', `frame-fns', `help+20', -;; `highlight', `image-dired', `image-file', `info', `info+20', -;; `kmacro', `menu-bar', `menu-bar+', `misc-cmds', `misc-fns', -;; `naked', `pp', `pp+', `second-sel', `strings', `subr-21', -;; `thingatpt', `thingatpt+', `unaccent', `w32-browser', -;; `w32browser-dlgopen', `wid-edit', `wid-edit+', `widget'. +;; `apropos', `apropos+', `autofit-frame', `avoid', `backquote', +;; `bookmark', `bookmark+', `bookmark+-1', `bookmark+-bmu', +;; `bookmark+-key', `bookmark+-lit', `button', `bytecomp', `cconv', +;; `cl', `cl-lib', `cmds-menu', `col-highlight', `crosshairs', +;; `dired', `dired+', `dired-aux', `dired-loaddefs', `dired-x', +;; `easymenu', `fit-frame', `font-lock', `font-lock+', +;; `format-spec', `frame-fns', `gv', `help+', `help-fns', +;; `help-fns+', `help-macro', `help-macro+', `help-mode', +;; `highlight', `hl-line', `hl-line+', `image', `image-dired', +;; `image-file', `image-mode', `info', `info+', `kmacro', +;; `macroexp', `menu-bar', `menu-bar+', `misc-cmds', `misc-fns', +;; `naked', `pp', `pp+', `radix-tree', `replace', `second-sel', +;; `strings', `syntax', `text-mode', `thingatpt', `thingatpt+', +;; `vline', `w32-browser', `w32browser-dlgopen', `wid-edit', +;; `wid-edit+', `widget'. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; @@ -63,6 +69,23 @@ ;; `diredp-prev-subdir' - `C-M-p' ;; ;; +;; Quick Viewing While Navigating +;; ------------------------------ +;; +;; You can use key `C-down' or `C-up' to navigate to the next or +;; previous file line, respectively, and at the same time show its +;; file in another window. The focus remains on the Dired buffer. +;; A numeric prefix arg means move that many lines first. +;; +;; Names of files and directories that match either of the options +;; `diredp-visit-ignore-extensions' or `diredp-visit-ignore-regexps' +;; are skipped. +;; +;; You can use `e' to show the file of the current line. If it is +;; already shown in the same frame, and if Dired is the only other +;; window there, then the file is hidden (its window is deleted). +;; +;; ;; Font-Lock Highlighting ;; ---------------------- ;; @@ -76,9 +99,10 @@ ;; font-locking, and this effect is established only when Dired+ is ;; loaded, which defines the font-lock keywords for Dired. These ;; options include `diredp-compressed-extensions', -;; `diredp-ignore-compressed-flag', and `dired-omit-extensions'. -;; This means that if you change the value of such an option then you -;; will see the change only in a new Emacs session. +;; `diredp-ignore-compressed-flag', `dired-omit-extensions', and +;; `diredp-omit-files-regexp'. This means that if you change the +;; value of such an option then you will see the change only in a new +;; Emacs session. ;; ;; (You can see the effect in the same session if you use `C-M-x' on ;; the `defvar' sexp for `diredp-font-lock-keywords-1', and then you @@ -158,7 +182,7 @@ ;; from subdirs themselves. ;; ;; All of the `diredp-*-recursive' commands are on prefix key `M-+', -;; and all are available on submenu `Marked Here and Below' of the +;; and most are available on submenu `Marked Here and Below' of the ;; `Multiple' menu-bar menu. The commands that unmark and change ;; marks are also in submenu `Here and Below' of menu-bar menu ;; `Marks'. @@ -420,9 +444,10 @@ ;; `diredp-flag-mark-line', `diredp-get-file-or-dir-name', ;; `diredp-ignored-file-name', `diredp-link-priv', ;; `diredp-mode-line-flagged', `diredp-mode-line-marked' -;; `diredp-no-priv', `diredp-number', `diredp-other-priv', -;; `diredp-rare-priv', `diredp-read-priv', `diredp-symlink', -;; `diredp-tagged-autofile-name', `diredp-write-priv'. +;; `diredp-omit-file-name', `diredp-no-priv', `diredp-number', +;; `diredp-other-priv', `diredp-rare-priv', `diredp-read-priv', +;; `diredp-symlink', `diredp-tagged-autofile-name', +;; `diredp-write-priv'. ;; ;; Commands defined here: ;; @@ -505,23 +530,24 @@ ;; `diredp-marked-recursive', ;; `diredp-marked-recursive-other-window', ;; `diredp-mark-extension-recursive', +;; `diredp-mark-files-containing-regexp-recursive', ;; `diredp-mark-files-regexp-recursive', ;; `diredp-mark-files-tagged-all', `diredp-mark-files-tagged-none', ;; `diredp-mark-files-tagged-not-all', ;; `diredp-mark-files-tagged-some', ;; `diredp-mark-files-tagged-regexp', `diredp-mark-region-files', -;; `diredp-mark/unmark-autofiles', `diredp-mark/unmark-extension', -;; `diredp-mouse-3-menu', `diredp-mouse-backup-diff', -;; `diredp-mouse-copy-tags', `diredp-mouse-describe-autofile', -;; `diredp-mouse-describe-file', `diredp-mouse-diff', -;; `diredp-mouse-do-bookmark', `diredp-mouse-do-byte-compile', -;; `diredp-mouse-do-chgrp', `diredp-mouse-do-chmod', -;; `diredp-mouse-do-chown', `diredp-mouse-do-compress', -;; `diredp-mouse-do-copy', `diredp-mouse-do-delete', -;; `diredp-mouse-do-grep', `diredp-mouse-do-hardlink', -;; `diredp-mouse-do-load', `diredp-mouse-do-print', -;; `diredp-mouse-do-remove-all-tags', `diredp-mouse-do-rename', -;; `diredp-mouse-do-set-tag-value', +;; `diredp-mark-sexp-recursive', `diredp-mark/unmark-autofiles', +;; `diredp-mark/unmark-extension', `diredp-mouse-3-menu', +;; `diredp-mouse-backup-diff', `diredp-mouse-copy-tags', +;; `diredp-mouse-describe-autofile', `diredp-mouse-describe-file', +;; `diredp-mouse-diff', `diredp-mouse-do-bookmark', +;; `diredp-mouse-do-byte-compile', `diredp-mouse-do-chgrp', +;; `diredp-mouse-do-chmod', `diredp-mouse-do-chown', +;; `diredp-mouse-do-compress', `diredp-mouse-do-copy', +;; `diredp-mouse-do-delete', `diredp-mouse-do-grep', +;; `diredp-mouse-do-hardlink', `diredp-mouse-do-load', +;; `diredp-mouse-do-print', `diredp-mouse-do-remove-all-tags', +;; `diredp-mouse-do-rename', `diredp-mouse-do-set-tag-value', ;; `diredp-mouse-do-shell-command', `diredp-mouse-do-symlink', ;; `diredp-mouse-do-tag', `diredp-mouse-do-untag', ;; `diredp-mouse-downcase', `diredp-mouse-ediff', @@ -531,7 +557,7 @@ ;; `diredp-mouse-flag-file-deletion', `diredp-mouse-mark', ;; `diredp-mouse-mark-region-files', `diredp-mouse-mark/unmark', ;; `diredp-mouse-unmark', `diredp-mouse-upcase', -;; `diredp-mouse-view-file', +;; `diredp-mouse-view-file', `diredp-move-file' (Emacs 24+), ;; `diredp-multiple-w32-browser-recursive', ;; `diredp-nb-marked-in-mode-name', `diredp-next-dirline', ;; `diredp-next-line', `diredp-next-subdir', `diredp-omit-marked', @@ -559,9 +585,11 @@ ;; `diredp-untag-this-file', `diredp-upcase-recursive', ;; `diredp-up-directory', `diredp-up-directory-reuse-dir-buffer', ;; `diredp-upcase-this-file', `diredp-verify-this-file', -;; `diredp-w32-drives', `diredp-w32-drives-mode', -;; `diredp-yank-files', `global-dired-hide-details-mode' (Emacs -;; 24.4+), `toggle-diredp-find-file-reuse-dir'. +;; `diredp-visit-next-file', `diredp-visit-previous-file', +;; `diredp-visit-this-file', `diredp-w32-drives', +;; `diredp-w32-drives-mode', `diredp-yank-files', +;; `global-dired-hide-details-mode' (Emacs 24.4+), +;; `toggle-diredp-find-file-reuse-dir'. ;; ;; User options defined here: ;; @@ -575,7 +603,10 @@ ;; `diredp-hide-details-propagate-flag' (Emacs 24.4+), ;; `diredp-ignore-compressed-flag', ;; `diredp-image-show-this-file-use-frame-flag' (Emacs 22+), -;; `diredp-max-frames', `diredp-prompt-for-bookmark-prefix-flag', +;; `diredp-max-frames', `diredp-move-file-dirs' (Emacs 24+), +;; `diredp-omit-files-regexp' +;; `diredp-prompt-for-bookmark-prefix-flag', +;; `diredp-visit-ignore-extensions', `diredp-visit-ignore-regexps', ;; `diredp-w32-local-drives', `diredp-wrap-around-flag'. ;; ;; Non-interactive functions defined here: @@ -583,8 +614,8 @@ ;; `derived-mode-p' (Emacs < 22), `diredp-all-files', ;; `diredp-ancestor-dirs', `diredp-bookmark', ;; `diredp-create-files-non-directory-recursive', -;; `diredp-delete-dups', `diredp-directories-within', -;; `diredp-dired-plus-description', +;; `diredp-delete-dups', `diredp-delete-if-not', +;; `diredp-directories-within', `diredp-dired-plus-description', ;; `diredp-dired-plus-description+links', ;; `diredp-dired-plus-help-link', `diredp-dired-union-1', ;; `diredp-dired-union-interactive-spec', `diredp-display-image' @@ -602,7 +633,7 @@ ;; `diredp-hide/show-details' (Emacs 24.4+), ;; `diredp-highlight-autofiles', `diredp-image-dired-required-msg', ;; `diredp-get-image-filename', `diredp-internal-do-deletions', -;; `diredp-list-files', `diredp-looking-at-p', +;; `diredp-list-file', `diredp-list-files', `diredp-looking-at-p', ;; `diredp-make-find-file-keys-reuse-dirs', ;; `diredp-make-find-file-keys-not-reuse-dirs', `diredp-maplist', ;; `diredp-marked-here', `diredp-mark-files-tagged-all/none', @@ -618,7 +649,8 @@ ;; `diredp--set-up-font-locking', `diredp-string-match-p', ;; `diredp-tag', `diredp-this-file-marked-p', ;; `diredp-this-file-unmarked-p', `diredp-this-subdir', -;; `diredp-untag', `diredp-y-or-n-files-p'. +;; `diredp-untag', `diredp-visit-ignore-regexp', +;; `diredp-y-or-n-files-p'. ;; ;; Variables defined here: ;; @@ -724,9 +756,12 @@ ;; `dired-do-isearch', `dired-do-isearch-regexp', ;; `dired-do-query-replace-regexp', `dired-do-search' - ;; Use new `dired-get-marked-files'. -;; `dired-insert-subdir-newpos' - If not a descendent, put at eob. +;; `dired-insert-subdir-newpos' - If not a descendant, put at eob. ;; `dired-insert-subdir-validate' - Do nothing: no restrictions. ;; `dired-maybe-insert-subdir' - Go back to subdir line if in listing. +;; `dired-handle-overwrite' - Added optional arg FROM, for listing. +;; `dired-copy-file(-recursive)', `dired-hardlink', `dired-query', +;; `dired-rename-file' - You can list (`l') the files involved. ;; ;; ;; ***** NOTE: The following functions defined in `dired-x.el' have @@ -755,6 +790,57 @@ ;; ;;; Change Log: ;; +;; 2019/03/20 dadams +;; Added option diredp-omit-files-regexp. +;; Face diredp-omit-file-name: Added strike-through. +;; diredp-font-lock-keywords-1, for face diredp-omit-file-name: +;; Move to file name. Use diredp-omit-files-regexp. Append * for executable flag. Highlight whole line. +;; 2019/03/17 dadams +;; diredp-font-lock-keywords-1: +;; Use just dired-omit-files as regexp - its components already have ^...$. +;; Removed superfluous execute *'s in regexps and superfluous concat for compressed extensions. +;; Face diredp-omit-file-name: Removed :strike-through for default value. +;; 2019/03/16 dadms +;; Added face diredp-omit-file-name. +;; diredp-font-lock-keywords-1: Use face diredp-omit-file-name for dired-omit-files matches. +;; 2019/03/15 dadams +;; diredp-font-lock-keywords-1: Treat dired-omit-files like dired-omit-extensions. +;; 2019/01/27 dadams +;; Added: diredp-mark-files-containing-regexp-recursive. +;; Bound to M-+ % g. Added to diredp-marks-recursive-menu, diredp-regexp-recursive-menu. +;; 2019/01/17 dadams +;; Added: diredp-mark-sexp-recursive. Bound to M-+ M-(, M-+ * (. Added to diredp-marks-recursive-menu. +;; dired-query: Use dired-query-alist only when available. +;; diredp-move-file: Fix format string in error call. +;; diredp-mark-symlinks-recursive: Added missing DETAILS arg for diredp-mark-recursive-1. +;; 2019/01/01 dadams +;; Added: diredp-list-file. +;; Added redefinitions of dired-query, dired-handle-overwrite, dired-copy-file(-recursive), dired-rename-file, +;; dired-hardlink. +;; Added optional arg DETAILS to these functions: diredp-get-(subdirs|files), diredp-y-or-n-files-p, +;; diredp-list-(marked|files), diredp-yank-files, diredp-describe-marked-autofiles, plus all functions with +;; "recursive" in their name except diredp-get-confirmation-recursive. +;; Added optional arg DETAILS. +;; diredp-get-(subdirs|files), diredp-y-or-n-files-p, diredp-list-(marked|files), diredp-yank-files, +;; diredp-describe-marked-autofiles: +;; Added optional arg DETAILS. +;; diredp-list-files: Use dired-list-file, to optionally show details. +;; diredp-yank-files: Non-positive prefix arg shows details now. +;; 2018/12/02 dadams +;; dired-mark-pop-up: Work around Emacs 22 bug in dired-pop-to-buffer which can exit in Dired buffer. +;; 2018/10/17 dadams +;; dired-read-dir-and-switches: Removed mention of icicle-file-sort-first-time-p (no longer used in Icicles). +;; 2018/09/21 dadams +;; diredp-image-dired-edit-comment-and-tags, diredp-w32-drives: +;; Use pop-to-buffer-same-window, not switch-to-buffer. +;; 2018/09/14 dadams +;; Added: diredp-move-file-dirs, diredp-move-file. +;; 2018/06/30 dadams +;; Added: diredp-delete-if-not. +;; 2018/06/16 dadams +;; Added: diredp-visit-ignore-extensions, diredp-visit-ignore-regexps, diredp-visit-next-file, +;; diredp-visit-previous-file, diredp-visit-this-file, diredp-visit-ignore-regexp. +;; Bind the commands to C-down, C-up, e. ;; 2018/03/25 dadams ;; Added: diredp-user-error. ;; Updated for Emacs 27-pretest-2 change in dired-get-marked-files signature. @@ -1869,8 +1955,12 @@ rather than FUN itself, to `minibuffer-setup-hook'." (defvar delete-by-moving-to-trash) ; Built-in, Emacs 23+ (defvar dired-always-read-filesystem) ; In `dired.el', Emacs 26+ (defvar dired-auto-revert-buffer) ; In `dired.el', Emacs 23+ +(defvar dired-create-files-failures) ; In `dired-aux.el', Emacs 22+ (defvar dired-details-state) ; In `dired-details+.el' (defvar dired-keep-marker-hardlink) ; In `dired-x.el' +(defvar dired-overwrite-confirmed) ; In `dired-aux.el' +(defvar dired-query-alist) ; In `dired-aux.el', Emacs < 24 +(defvar dired-recursive-copies) ; In `dired-aux.el', Emacs 22+ (defvar dired-recursive-deletes) ; In `dired.el', Emacs 22+ (defvar dired-shrink-to-fit) ; In `dired.el' (defvar dired-switches-alist) ; In `dired.el' @@ -1887,12 +1977,13 @@ rather than FUN itself, to `minibuffer-setup-hook'." (defvar diredp-menu-bar-images-recursive-menu) ; Here (old name) (defvar diredp-menu-bar-regexp-recursive-menu) ; Here (old name) (defvar diredp-menu-bar-subdir-menu) ; Here (old name) +(defvar diredp-move-file-dirs) ; Here, Emacs 24+ (defvar diredp-single-bookmarks-menu) ; Here, if Bookmark+ is available (defvar filesets-data) ; In `filesets.el' (defvar grep-use-null-device) ; In `grep.el' (defvar header-line-format) ; Emacs 22+ (defvar icicle-file-sort) ; In `icicles-opt.el' -(defvar icicle-file-sort-first-time-p) ; In `icicles-var.el' +;; $$$$ (defvar icicle-file-sort-first-time-p) ; In `icicles-var.el' (defvar icicle-files-ido-like-flag) ; In `icicles-opt.el' (defvar icicle-ignored-directories) ; In `icicles-opt.el' (defvar icicle-sort-comparer) ; In `icicles-opt.el' @@ -1965,7 +2056,10 @@ support the use of such keys then customize this option to nil." ;;;###autoload (defcustom diredp-compressed-extensions '(".tar" ".taz" ".tgz" ".arj" ".lzh" ".lzma" ".xz" ".zip" ".z" ".Z" ".gz" ".bz2") - "*List of compressed-file extensions, for highlighting." + "*List of compressed-file extensions, for highlighting. + +Note: If you change the value of this option then you need to restart +Emacs to see the effect of the new value on font-locking." :type '(repeat string) :group 'Dired-Plus) (when (> emacs-major-version 21) ; Emacs 22+ @@ -2030,7 +2124,10 @@ This option has no effect unless you use libraries `Bookmark and "*Non-nil means to font-lock names of compressed files as ignored files. This applies to filenames whose extensions are in `diredp-compressed-extensions'. If nil they are highlighted using -face `diredp-compressed-file-name'." +face `diredp-compressed-file-name'. + +Note: If you change the value of this option then you need to restart +Emacs to see the effect of the new value on font-locking." :type 'boolean :group 'Dired-Plus) ;;;###autoload @@ -2078,11 +2175,74 @@ the circumstances in which they show the files in separate frames." :type '(restricted-sexp :match-alternatives ((lambda (x) (and (wholenump x) (not (zerop x)))))) :group 'Dired-Plus) +(when (fboundp 'file-equal-p) ; Emacs 24+ + (defcustom diredp-move-file-dirs () + "Alist of names of files and preferred directories to move them to. +File names should be relative (no directory component). +Target directory names should be absolute." + :group 'files :type '(alist :key-type file :value-type directory))) + +;; (Not used - just use the body directly in the option default value. +;; (defun diredp-omit-files-regexp () +;; "Return regexp to use for font-locking, using `dired-omit-files' as base." +;; (let* ((strg dired-omit-files) +;; (strg (if (eq ?^ (aref strg 0)) (substring strg 1) strg)) ; Remove initial ^ +;; (strg (replace-regexp-in-string "\\(\\\\[|]\\)\\^" "\\1" strg 'FIXEDCASE nil)) ; Remove other ^'s +;; (strg (replace-regexp-in-string "\\([$]\\)" "" strg 'FIXEDCASE nil))) ; Remove $'s +;; strg)) + +;;;###autoload +(defcustom diredp-omit-files-regexp (let* ((strg dired-omit-files) + (strg (if (eq ?^ (aref strg 0)) ; Remove initial ^ + (substring strg 1) + strg)) + (strg (replace-regexp-in-string "\\(\\\\[|]\\)\\^" ; Remove other ^'s + "\\1" + strg + 'FIXEDCASE + nil)) + (strg (replace-regexp-in-string "\\([$]\\)" ; Remove $'s + "" + strg + 'FIXEDCASE + nil))) + strg) + "Regexp for font-locking file names to be omitted by `dired-omit-mode'. +The regexp is matched only against the file name, but the entire line +is highlighted (with face `diredp-omit-file-name'). + +The default value of this option differs from that of +`dired-omit-files' by removing \"^\" from the beginning, and \"$\" +from the end, of each regexp choice. (The default value of +`dired-omit-files', at least prior to Emacs 27, uses \"^\" and \"$\", +but it should not.) + +If you want to control the beginning and end of choice matches then +use \"\\`\" and \"\\'\" instead of \"^\" and \"$\". + +Note: If you change the value of this option then you need to restart +Emacs to see the effect of the new value on font-locking." + :group 'Dired-Plus :type 'regexp) + ;;;###autoload (defcustom diredp-prompt-for-bookmark-prefix-flag nil "*Non-nil means prompt for a prefix string for bookmark names." :type 'boolean :group 'Dired-Plus) +;;;###autoload +(defcustom diredp-visit-ignore-regexps () + "Regexps matching file names for `diredp-visit-(next|previous)' to skip. +A file or directory name matching one of these regexps is skipped, +along with those with an extension in `diredp-visit-ignore-extensions'." + :type '(repeat regexp) :group 'Dired-Plus) + +;;;###autoload +(defcustom diredp-visit-ignore-extensions '("elc") + "Extensions of file names for `diredp-visit-(next|previous)' to skip. +A file name with one of these extensions is skipped, along with those +matching a regexp in `diredp-visit-ignore-regexps'." + :type '(repeat string) :group 'Dired-Plus) + ;;;###autoload (defcustom diredp-w32-local-drives '(("C:" "Local disk")) "*Local MS Windows drives that you want to use for `diredp-w32-drives'. @@ -2290,6 +2450,18 @@ If DISTINGUISH-ONE-MARKED is non-nil, then return (t FILENAME) instead ;;; Utility functions +;; Same as `imenup-delete-if-not'. +;; +(defun diredp-delete-if-not (predicate xs) + "Remove all elements of list XS that do not satisfy PREDICATE. +This operation is destructive, reusing conses of XS whenever possible." + (while (and xs (not (funcall predicate (car xs)))) + (setq xs (cdr xs))) + (let ((cl-p xs)) + (while (cdr cl-p) + (if (not (funcall predicate (cadr cl-p))) (setcdr cl-p (cddr cl-p)) (setq cl-p (cdr cl-p))))) + xs) + ;; Same as `tap-string-match-p' in `thingatpt+.el'. (if (fboundp 'string-match-p) (defalias 'diredp-string-match-p 'string-match-p) ; Emacs 23+ @@ -2667,9 +2839,9 @@ additional multi-command keys. See `dired' (defadvice doc)." (icicle-delete-candidate-object 'icicle-delete-file-or-directory) (icicle-sort-orders-alist (and (boundp 'icicle-sort-orders-alist) - (progn (when (and icicle-file-sort-first-time-p icicle-file-sort) - (setq icicle-sort-comparer icicle-file-sort - icicle-file-sort-first-time-p nil)) + (progn (when t ; $$$$ (and icicle-file-sort-first-time-p icicle-file-sort) + (setq icicle-sort-comparer icicle-file-sort)) + ; $$$$ (setq icicle-file-sort-first-time-p nil)) (if icicle-file-sort (let ((already-there (rassq icicle-file-sort icicle--temp-orders))) (if already-there @@ -3121,7 +3293,9 @@ Uses `image-dired-get-exif-file-name' to name the new file." (interactive (progn (diredp-image-dired-required-msg) ())) (setq image-dired-widget-list ()) (let ((file (dired-get-filename))) - (switch-to-buffer "*Image-Dired Edit Meta Data*") + (if (fboundp 'pop-to-buffer-same-window) + (pop-to-buffer-same-window "*Image-Dired Edit Meta Data*") + (switch-to-buffer "*Image-Dired Edit Meta Data*")) (kill-all-local-variables) (make-local-variable 'widget-example-repeat) (let ((inhibit-read-only t)) @@ -3337,11 +3511,10 @@ This means the `.' plus the file extension. Example: `.elc'." (defvar diredp-flag-mark-line 'diredp-flag-mark-line) (defface diredp-ignored-file-name - '(;; (((background dark)) (:foreground "#FFFF921F921F")) ; ~ salmon - ;; (((background dark)) (:foreground "#A71F5F645F64")) ; ~ dark salmon - (((background dark)) (:foreground "#C29D6F156F15")) ; ~ salmon - (t (:foreground "#00006DE06DE0"))) ; ~ dark cyan - "*Face used for ignored file names in Dired buffers." + '((((background dark)) (:foreground "#C29D6F156F15")) ; ~ salmon + (t (:foreground "#00006DE06DE0"))) ; ~ dark cyan + "*Face used for files whose names are omitted based on the extension. +See also face `diredp-omit-file-name'." :group 'Dired-Plus :group 'font-lock-highlighting-faces) (defvar diredp-ignored-file-name 'diredp-ignored-file-name) @@ -3378,6 +3551,19 @@ In particular, inode number, number of hard links, and file size." :group 'Dired-Plus :group 'font-lock-highlighting-faces) (defvar diredp-number 'diredp-number) +(defface diredp-omit-file-name + (if (assq :inherit custom-face-attributes) ; Emacs 22+ + '((((background dark)) (:inherit diredp-ignored-file-name :strike-through "#555555555555")) ; ~ dark gray + (t (:inherit diredp-ignored-file-name :strike-through "#AAAAAAAAAAAA"))) ; ~ light gray + '((((background dark)) (:foreground "#C29D6F156F15")) ; ~ salmon + (t (:foreground "#00006DE06DE0")))) ; ~ dark cyan + "*Face used for files whose names will be omitted in `dired-omit-mode'. +This means file names that match regexp `diredp-omit-files-regexp'. +\(File names matching `dired-omit-extensions' are highlighted with face +`diredp-ignored-file-name' instead.)" + :group 'Dired-Plus :group 'font-lock-highlighting-faces) +(defvar diredp-omit-file-name 'diredp-omit-file-name) + (defface diredp-other-priv '((((background dark)) (:background "#111117175555")) ; ~ dark blue (t (:background "PaleGoldenrod"))) @@ -3431,10 +3617,10 @@ In particular, inode number, number of hard links, and file size." (defvar diredp-font-lock-keywords-1 (list '("^ \\(.+:\\)$" 1 diredp-dir-heading) ; Directory headers - '("^ wildcard.*$" 0 'default) ; Override others, e.g. `l' for `diredp-other-priv'. - '("^ (No match).*$" 0 'default) ; Override others, e.g. `t' for `diredp-other-priv'. + '("^ wildcard.*$" 0 'default) ; Override others, e.g. `l' for `diredp-other-priv'. + '("^ (No match).*$" 0 'default) ; Override others, e.g. `t' for `diredp-other-priv'. '("[^ .]\\(\\.[^. /]+\\)$" 1 diredp-file-suffix) ; Suffix, including `.'. - '("\\([^ ]+\\) -> .+$" 1 diredp-symlink) ; Symbolic links + '("\\([^ ]+\\) -> .+$" 1 diredp-symlink) ; Symbolic links ;; 1) Date/time and 2) filename w/o suffix. ;; This is a bear, and it is fragile - Emacs can change `dired-move-to-filename-regexp'. @@ -3445,8 +3631,8 @@ In particular, inode number, number of hard links, and file size." "\\)[*]?$")) ; Compressed-file name nil nil (list 0 diredp-compressed-file-name 'keep t))) `(,dired-move-to-filename-regexp - (7 diredp-date-time t t) ; Date/time, locale (western or eastern) - (2 diredp-date-time t t) ; Date/time, ISO + (7 diredp-date-time t t) ; Date/time, locale (western or eastern) + (2 diredp-date-time t t) ; Date/time, ISO (,(concat "\\(.+\\)\\(" (concat (funcall #'regexp-opt diredp-compressed-extensions) "\\)[*]?$")) nil nil (0 diredp-compressed-file-name keep t)))) ; Compressed-file suffix @@ -3455,22 +3641,26 @@ In particular, inode number, number of hard links, and file size." (list 1 'diredp-date-time t t) ; Date/time (list "\\(.+\\)$" nil nil (list 0 diredp-file-name 'keep t))) ; Filename `(,dired-move-to-filename-regexp - (7 diredp-date-time t t) ; Date/time, locale (western or eastern) - (2 diredp-date-time t t) ; Date/time, ISO + (7 diredp-date-time t t) ; Date/time, locale (western or eastern) + (2 diredp-date-time t t) ; Date/time, ISO ("\\(.+\\)$" nil nil (0 diredp-file-name keep t)))) ; Filename (not a compressed file) - ;; Files to ignore - (list (concat "^ \\(.*\\(" - (mapconcat #'regexp-quote (or (and (boundp 'dired-omit-extensions) dired-omit-extensions) - completion-ignored-extensions) - "[*]?\\|") - (and diredp-ignore-compressed-flag - (concat "\\|" (mapconcat #'regexp-quote diredp-compressed-extensions "[*]?\\|"))) - "[*]?\\)\\)$") ; Allow for executable flag (*). - 1 diredp-ignored-file-name t) + ;; Files to ignore. + ;; Use face `diredp-ignored-file-name' for omission by file-name extension. + ;; Use face `diredp-omit-file-name' for omission by entire file name. + (let* ((omit-exts (or (and (boundp 'dired-omit-extensions) dired-omit-extensions) + completion-ignored-extensions)) + (omit-exts (and omit-exts (mapconcat #'regexp-quote omit-exts "\\|"))) + (compr-exts (and diredp-ignore-compressed-flag + (concat "\\|" (mapconcat #'regexp-quote diredp-compressed-extensions "\\|"))))) + (list (concat "^ \\(.*\\(" omit-exts compr-exts "\\)[*]?\\)$") ; [*]? allows for executable flag (*). + 1 diredp-ignored-file-name t)) + `(,(concat "^.*" dired-move-to-filename-regexp + "\\(" diredp-omit-files-regexp "\\).*[*]?$") ; [*]? allows for executable flag (*). + (0 diredp-omit-file-name t)) ;; Compressed-file (suffix) - (list (concat "\\(" (concat (funcall #'regexp-opt diredp-compressed-extensions) "\\)[*]?$")) + (list (concat "\\(" (funcall #'regexp-opt diredp-compressed-extensions) "\\)[*]?$") 1 diredp-compressed-file-suffix t) '("\\([*]\\)$" 1 diredp-executable-tag t) ; Executable (*) @@ -3593,7 +3783,9 @@ In particular, inode number, number of hard links, and file size." ;;; (when (consp arg) ;;; (let ((buf (dired-find-buffer-nocreate (car arg)))) ; Respect file list. ;;; (when buf (kill-buffer buf)))) -;;; (switch-to-buffer (dired-noselect arg switches))) +;;; (if (fboundp 'pop-to-buffer-same-window) +;;; (pop-to-buffer-same-window (dired-noselect arg switches)) +;;; (switch-to-buffer (dired-noselect arg switches)))) ;;; (defun diredp-dired-files-other-window (arg &optional switches) ; Not bound ;;; "Same as `diredp-dired-files' except uses another window." @@ -3742,7 +3934,7 @@ A new list is returned - list THINGS is not modified." ;;; (read-string "Dired listing switches: " dired-listing-switches)))) ;;;###autoload -(defun diredp-dired-union (dired-name dirbufs &optional switches extra) ; Bound to `C-x 4 D U' +(defun diredp-dired-union (dired-name dirbufs &optional switches extra) ; Bound to `C-x D U' "Create a Dired buffer that is the union of some existing Dired buffers. With a non-negative prefix arg, you are prompted for `ls' switches. With a non-positive prefix arg, you are prompted for file and dir @@ -4097,22 +4289,22 @@ Markings and current Dired switches are preserved." ;;; Actions on marked files and subdirs, recursively. -(defun diredp-get-subdirs (&optional ignore-marks-p predicate) +(defun diredp-get-subdirs (&optional ignore-marks-p predicate details) "Return subdirs from this Dired buffer and from marked subdirs, recursively. If optional arg IGNORE-MARKS-P is non-nil then include all subdirectories. Otherwise, include only those that are marked. Non-nil optional arg PREDICATE means include only subdirectory names for which the PREDICATE returns non-nil. PREDICATE must accept a file -name as its only required argument." - (diredp-get-files ignore-marks-p - (if predicate - `(lambda (name) (and (file-directory-p name) (funcall ,predicate name))) - #'file-directory-p) - 'INCLUDE-DIRS-P 'DONT-ASKP 'ONLY-MARKED-P)) +name as its only required argument. -(defun diredp-get-files (&optional ignore-marks-p predicate include-dirs-p - dont-askp only-marked-p) +Optional arg DETAILS is passed to `diredp-get-files'." + (diredp-get-files ignore-marks-p (if predicate + `(lambda (name) (and (file-directory-p name) (funcall ,predicate name))) + #'file-directory-p) + 'INCLUDE-DIRS-P 'DONT-ASKP 'ONLY-MARKED-P details)) + +(defun diredp-get-files (&optional ignore-marks-p predicate include-dirs-p dont-askp only-marked-p details) "Return file names from this Dired buffer and subdirectories, recursively. The names are those that are marked in the current Dired buffer, or all files in the directory if none are marked. Marked subdirectories @@ -4147,7 +4339,9 @@ instead of all. Act as if the user was asked and replied `y'. Non-nil optional arg ONLY-MARKED-P means collect only marked files, instead of collecting all files if none are marked. This argument is -ignored if IGNORE-MARKS-P is non-nil." +ignored if IGNORE-MARKS-P is non-nil. + +Optional arg DETAILS is passed to `diredp-y-or-n-files-p'." ;;;;@@@@@@@@@ ;; Set IGNORE-MARKS-P to non-nil if nothing marked here. ;;;; (let ((dired-marker-char ?*)) ;;;; (save-excursion @@ -4166,8 +4360,7 @@ ignored if IGNORE-MARKS-P is non-nil." (if (or dont-askp (not (car askp)) (diredp-y-or-n-files-p "Use marked (instead of all) in subdir Dired buffers? " - files - predicate)) + files predicate details)) (if predicate (diredp-remove-if-not predicate files) files) (setq files ()) (dolist (file (diredp-marked-here)) @@ -4230,7 +4423,7 @@ Non-nil optional arg NO-DOT-DOT-P means do not include marked `..'." (t (and (not only-marked-p) ; None marked (directory-files default-directory 'FULL diredp-re-no-dot 'NOSORT)))))) -(defun diredp-y-or-n-files-p (prompt files &optional predicate) +(defun diredp-y-or-n-files-p (prompt files &optional predicate details) "PROMPT user with a \"y or n\" question about a list of FILES. Return t if answer is \"y\". Otherwise, return nil. @@ -4244,7 +4437,9 @@ hidden and buried otherwise. Thus, if it was shown then it is still available to revisit afterward (even if you quit using `C-g'). PREDICATE is passed to `diredp-list-files', to list only file names -for which it returns non-nil." +for which it returns non-nil. + +DETAILS is passed to `diredp-list-files', to show details about FILES." (let ((answer 'recenter)) (cond (noninteractive (setq prompt (concat prompt @@ -4264,43 +4459,43 @@ for which it returns non-nil." (let ((list-buf (generate-new-buffer-name "*Files*")) (list-was-shown nil)) (unwind-protect - (progn - (define-key query-replace-map "l" 'show) - (setq prompt (concat prompt - (and (eq ?\ (aref prompt (1- (length prompt)))) - "" " ") - "(y or n; l to show file list) ")) - (while (let* ((reprompt-actions '(recenter scroll-up scroll-down - scroll-other-window scroll-other-window-down)) - (key (let ((cursor-in-echo-area t)) - (when minibuffer-auto-raise - (raise-frame (window-frame (minibuffer-window)))) - (if (fboundp 'read-key) - (read-key (propertize - (if (memq answer reprompt-actions) - prompt - (concat "Please answer y or n. " prompt)) - 'face 'minibuffer-prompt)) - (read-char-exclusive - (if (memq answer reprompt-actions) - prompt - (concat "Please answer y or n. " prompt))))))) - (setq answer (lookup-key query-replace-map (vector key) t)) - (case answer - ((skip act) nil) - (recenter (recenter) t) - (show (diredp-list-files files nil list-buf predicate) - (setq list-was-shown t)) ; Record showing it. - (help (message "Use `l' to show file list") (sit-for 1)) - (scroll-up (condition-case nil (scroll-up-command) (error nil)) t) - (scroll-down (condition-case nil (scroll-down-command) (error nil)) t) - (scroll-other-window (condition-case nil (scroll-other-window) (error nil)) t) - (scroll-other-window-down (condition-case nil (scroll-other-window-down nil) - (error nil)) t) - ((exit-prefix quit) (signal 'quit nil) t) - (t (or (not (eq key ?\e)) (progn (signal 'quit nil) t))))) - (ding) - (discard-input))) + (progn + (define-key query-replace-map "l" 'show) + (setq prompt (concat prompt + (and (eq ?\ (aref prompt (1- (length prompt)))) + "" " ") + "(y or n; l to show file list) ")) + (while (let* ((reprompt-actions '(recenter scroll-up scroll-down + scroll-other-window scroll-other-window-down)) + (key (let ((cursor-in-echo-area t)) + (when minibuffer-auto-raise + (raise-frame (window-frame (minibuffer-window)))) + (if (fboundp 'read-key) + (read-key (propertize + (if (memq answer reprompt-actions) + prompt + (concat "Please answer y or n. " prompt)) + 'face 'minibuffer-prompt)) + (read-char-exclusive + (if (memq answer reprompt-actions) + prompt + (concat "Please answer y or n. " prompt))))))) + (setq answer (lookup-key query-replace-map (vector key) t)) + (case answer + ((skip act) nil) + (recenter (recenter) t) + (show (diredp-list-files files nil list-buf predicate details) + (setq list-was-shown t)) ; Record showing it. + (help (message "Use `l' to show file list") (sit-for 1)) + (scroll-up (condition-case nil (scroll-up-command) (error nil)) t) + (scroll-down (condition-case nil (scroll-down-command) (error nil)) t) + (scroll-other-window (condition-case nil (scroll-other-window) (error nil)) t) + (scroll-other-window-down (condition-case nil (scroll-other-window-down nil) + (error nil)) t) + ((exit-prefix quit) (signal 'quit nil) t) + (t (or (not (eq key ?\e)) (progn (signal 'quit nil) t))))) + (ding) + (discard-input))) (when (get-buffer list-buf) (save-window-excursion (pop-to-buffer list-buf) (condition-case nil ; Ignore error if user already deleted. @@ -4337,7 +4532,7 @@ The full text of the line is used as the file name." (save-excursion (mouse-set-point e) (diredp-find-line-file-other-window))) ;;;###autoload -(defun diredp-list-marked (&optional arg predicate interactivep) ; Bound to `C-M-l' +(defun diredp-list-marked (&optional arg predicate interactivep details) ; Bound to `C-M-l' "List the marked files in this Dired buffer. A prefix arg specifies files to use instead of the marked files: @@ -4351,13 +4546,15 @@ You can use `RET' or `mouse-2' to visit any of the files. If `tooltip-mode' is on then moving the mouse over image-file names shows image previews. -Non-interactively, non-nil arg PREDICATE is a file-name predicate. -List only the files for which it returns non-nil." +When called from Lisp: + Non-nil optional arg PREDICATE is a file-name predicate. List only + the files for which it returns non-nil. + Non-nil optional arg DETAILS is passed to `diredp-list-files'." (interactive (progn (diredp-ensure-mode) (list current-prefix-arg nil t))) (let ((files (dired-get-marked-files nil arg predicate 'DISTINGUISH-ONE interactivep))) - (diredp-list-files files))) + (diredp-list-files files nil nil nil details))) -(defun diredp-list-files (files &optional dir bufname predicate) +(defun diredp-list-files (files &optional dir bufname predicate details) "Display FILES, a list of file names. Wildcard patterns are expanded. The files are shown in a new buffer, `*Files*' by default. @@ -4370,25 +4567,28 @@ Optional arg BUFNAME is the name of the buffer for the display. Optional arg PREDICATE is a predicate used to filter FILES: only files satisfying PREDICATE are listed. +Non-nil arg DETAILS means show details about each file, in addition to +the file name. It is passed to `diredp-list-file' (which see). + File names listed are absolute. Mouseover gives help or an image-file preview, and you can use `RET' or `mouse-2' to visit files." (unless bufname (setq bufname (generate-new-buffer-name "*Files*"))) - (diredp-with-help-window bufname - (princ "Files\n-----\n\n") - (let ((all-files-no-wildcards ()) - file-alist file-dir) - (dolist (file files) - (unless (or (string= file "") ; Ignore empty file names. - (and predicate (not (funcall predicate file)))) - (if (not (diredp-string-match-p "[[?*]" file)) - (add-to-list 'all-files-no-wildcards (expand-file-name file)) - (setq file-dir (or (file-name-directory file) default-directory) - file-alist (directory-files-and-attributes file-dir 'FULL "[[?*]" 'NOSORT)) - (dolist (ff file-alist) - (add-to-list 'all-files-no-wildcards (expand-file-name (car ff) file-dir)))))) - (save-excursion (dolist (fff (nreverse all-files-no-wildcards)) - (princ fff) - (terpri))))) + (diredp-with-help-window + bufname + (princ "Files\n-----\n\n") + (let ((all-files-no-wildcards ()) + file-alist file-dir) + (dolist (file files) + (unless (or (string= file "") ; Ignore empty file names. + (and predicate (not (funcall predicate file)))) + (if (not (diredp-string-match-p "[[?*]" file)) + (add-to-list 'all-files-no-wildcards (diredp-list-file file details)) + (setq file-dir (or (file-name-directory file) default-directory) + file-alist (directory-files-and-attributes file-dir 'FULL "[[?*]" 'NOSORT)) + (dolist (ff file-alist) + (add-to-list 'all-files-no-wildcards (diredp-list-file file details)))))) + (save-excursion (dolist (fff (nreverse all-files-no-wildcards)) + (princ fff) (terpri))))) (with-current-buffer bufname (let ((buffer-read-only nil)) (save-excursion @@ -4396,17 +4596,58 @@ preview, and you can use `RET' or `mouse-2' to visit files." (forward-line 3) (while (not (eobp)) (add-text-properties (line-beginning-position) (line-end-position) - '(mouse-face highlight - help-echo diredp-mouseover-help - dired-filename t - ;; `keymap' does not work for Emacs 20. Could use `local-map' - ;; but that still leaves `RET' bound to `help-follow'. - keymap diredp-list-files-map)) + '(mouse-face highlight help-echo diredp-mouseover-help dired-filename t + ;; `keymap' does not work for Emacs 20. Could use `local-map' + ;; but that still leaves `RET' bound to `help-follow'. + keymap diredp-list-files-map)) (forward-line 1)))) (set-buffer-modified-p nil) (setq buffer-read-only t) (buffer-enable-undo))) +(defun diredp-list-file (file &optional details) + "Return FILE name, expanded. +Non-nil optional arg DETAILS means append details about FILE to the +returned string. + +If DETAILS is a list of file attribute numbers then include only the +values of those attributes. Otherwise, include all attribute values." + (let ((file-dir (and details (or (file-name-directory file) default-directory))) + attrs) + (setq file (expand-file-name file file-dir)) + (when (and details (atom details)) (setq details '(0 1 2 3 4 5 6 7 8 9 10 11))) + (concat + file + (and details + (setq attrs (file-attributes file)) + (concat + "\n" + (and (memq 0 details) + (format " File Type: %s\n" + (cond ((eq t (nth 0 attrs)) "Directory") + ((stringp (nth 0 attrs)) (format "Symbolic link to `%s'" (nth 0 attrs))) + (t "Normal file")))) + (and (memq 8 details) + (format " Permissions: %s\n" (nth 8 attrs))) + (and (memq 7 details) (not (eq t (nth 0 attrs))) + (format " Size in bytes: %g\n" (nth 7 attrs))) + (and (memq 4 details) + (format-time-string " Time of last access: %a %b %e %T %Y (%Z)\n" (nth 4 attrs))) + (and (memq 5 details) + (format-time-string " Time of last modification: %a %b %e %T %Y (%Z)\n" (nth 5 attrs))) + (and (memq 6 details) + (format-time-string " Time of last status change: %a %b %e %T %Y (%Z)\n" (nth 6 attrs))) + (and (memq 1 details) + (format " Number of links: %d\n" (nth 1 attrs))) + (and (memq 2 details) + (format " User ID (UID): %s\n" (nth 2 attrs))) + (and (memq 3 details) + (format " Group ID (GID): %s\n" (nth 3 attrs))) + (and (memq 10 details) + (format " Inode: %S\n" (nth 10 attrs))) + (and (memq 11 details) + (format " Device number: %s\n" (nth 11 attrs)))))))) + (defvar diredp-files-within-dirs-done () "Directories already processed by `diredp-files-within'.") @@ -4524,7 +4765,7 @@ the subdir listing in the ancestor Dired buffer. Note: If you use Icicles, then you can use `icicle-dired-insert-as-subdir' instead: it is a multi-command. It -does the same thing, but it lets you insert any number of descendent +does the same thing, but it lets you insert any number of descendant directories into a given ancestor-directory Dired buffer. Non-interactively: @@ -4590,6 +4831,23 @@ function; it copies the data if necessary." (setq list2 (cdr list2))) list1))) +(when (fboundp 'file-equal-p) ; Emacs 24+ + (defun diredp-move-file (file &optional prompt-anyway) + "Move FILE to associated directory in `diredp-move-file-dirs'. +If no association, or if you use a prefix arg, prompt for directory." + (interactive (list (dired-get-filename) current-prefix-arg)) + (unless file (error "No file specified")) + (let* ((file-sans (file-name-nondirectory file)) + (dir (file-name-as-directory + (or (and (not prompt-anyway) + (cdr (assoc file-sans diredp-move-file-dirs))) + (read-directory-name "Move to: "))))) + (when (file-equal-p dir (file-name-directory file)) + (error "Cannot move to same directory: %s" dir)) + (dired-rename-file file dir nil) + (dired-add-file (expand-file-name file-sans dir)) + (message "Moved `%s' to `%s'" file-sans dir)))) + (defvar diredp-last-copied-filenames () "String list of file names last copied to the `kill-ring'. Copying is done by `dired-copy-filename-as-kill' and related commands.") @@ -4641,9 +4899,13 @@ This is the same as using a zero prefix arg with command ;;;###autoload (defalias 'diredp-paste-files 'diredp-yank-files) ; Bound to `C-y'. ;;;###autoload -(defun diredp-yank-files (&optional dir no-confirm-p) +(defun diredp-yank-files (&optional dir no-confirm-p details) "Paste files, whose absolute names you copied, to the current directory. -With a prefix arg you are instead prompted for the target directory. +With a non-negative prefix arg you are instead prompted for the target + directory. +With a non-positive prefix arg you can see details about the copied + files if you hit `l' when prompted to confirm pasting. Otherwise you + see only the file names. You should have copied the list of file names as a string to the kill ring using \\`M-0 \\[dired-copy-filename-as-kill]' or \ @@ -4652,21 +4914,24 @@ Those commands also set variable `diredp-last-copied-filenames' to the same string. `diredp-yank-files' uses the value of that variable, not whatever is currently at the head of the kill ring. -When called from Lisp, optional arg NO-CONFIRM-P means do not ask for -confirmation to copy." - (interactive (and current-prefix-arg - (list (expand-file-name (read-directory-name "Yank files to directory: "))))) +When called from Lisp: + +Optional arg NO-CONFIRM-P means do not ask for confirmation to copy. +Optional arg DETAILS is passed to `diredp-y-or-n-files-p'." + (interactive (list (and current-prefix-arg (natnump (prefix-numeric-value current-prefix-arg)) + (expand-file-name (read-directory-name "Yank files to directory: "))) + nil + (and current-prefix-arg (<= (prefix-numeric-value current-prefix-arg) 0) '(5 8)))) (setq dir (or dir (and (derived-mode-p 'dired-mode) (dired-current-directory)))) (unless (file-directory-p dir) (error "Not a directory: `%s'" dir)) (let ((files diredp-last-copied-filenames)) (unless (stringp files) (error "No copied file names")) - (setq files (delete-if-not (lambda (file) (file-name-absolute-p file)) (split-string files))) + (setq files (diredp-delete-if-not (lambda (file) (file-name-absolute-p file)) (split-string files))) (unless files (error "No copied absolute file names (Did you use `M-0 w'?)")) (if (and (not no-confirm-p) - (diredp-y-or-n-files-p "Paste files whose names you copied? " files)) + (diredp-y-or-n-files-p "Paste files whose names you copied? " files nil details)) (dired-create-files #'dired-copy-file "Copy" files - (lambda (from) - (expand-file-name (file-name-nondirectory from) dir))) + (lambda (from) (expand-file-name (file-name-nondirectory from) dir))) (message "OK, file-pasting canceled")))) @@ -4708,7 +4973,7 @@ Like using \\`\\[dired-maybe-insert-subdir]' at each marked dire (dired-maybe-insert-subdir subdir switches))) ;;;###autoload -(defun diredp-insert-subdirs-recursive (&optional ignore-marks-p) ; Bound to `M-+ M-i' +(defun diredp-insert-subdirs-recursive (&optional ignore-marks-p details) ; Bound to `M-+ M-i' "Insert the marked subdirs, including those in marked subdirs. Like `diredp-insert-subdirs', but act recursively on subdirs. The subdirs inserted are those that are marked in the current Dired @@ -4717,13 +4982,16 @@ subdirectories are handled recursively in the same way (their marked subdirs are inserted...). With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive 'subdirs) (list current-prefix-arg))) - (dolist (subdir (diredp-get-files ignore-marks-p #'file-directory-p 'INCLUDE-SUBDIRS-P)) + (dolist (subdir (diredp-get-files ignore-marks-p #'file-directory-p 'INCLUDE-SUBDIRS-P nil nil details)) (dired-maybe-insert-subdir subdir))) ;;;###autoload -(defun diredp-do-shell-command-recursive (command &optional ignore-marks-p) ; Bound to `M-+ !' +(defun diredp-do-shell-command-recursive (command &optional ignore-marks-p details) ; Bound to `M-+ !' "Run shell COMMAND on the marked files, including those in marked subdirs. Like `dired-do-shell-command', but act recursively on subdirs. The files included are those that are marked in the current Dired @@ -4731,7 +4999,10 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive) (let* ((prompt "! on *: ") @@ -4745,10 +5016,11 @@ Dired buffer and all subdirs, recursively." (dired-guess-shell-command prompt (dired-get-marked-files t)) (read-shell-command prompt nil nil)))))) (list cmd current-prefix-arg)))) - (dired-do-shell-command command nil (diredp-get-files ignore-marks-p))) + (dired-do-shell-command command nil (diredp-get-files ignore-marks-p nil nil nil nil details))) (when (fboundp 'dired-do-async-shell-command) ; Emacs 23+ - (defun diredp-do-async-shell-command-recursive (command &optional ignore-marks-p) + + (defun diredp-do-async-shell-command-recursive (command &optional ignore-marks-p details) ; Bound to `M-+ &' "Run async shell COMMAND on marked files, including in marked subdirs. Like `dired-do-async-shell-command', but act recursively on subdirs. @@ -4757,7 +5029,10 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive) (let* ((prompt "! on *: ") @@ -4771,10 +5046,10 @@ Dired buffer and all subdirs, recursively." (dired-guess-shell-command prompt (dired-get-marked-files t)) (read-shell-command prompt nil nil)))))) (list cmd current-prefix-arg)))) - (dired-do-async-shell-command command nil (diredp-get-files ignore-marks-p)))) + (dired-do-async-shell-command command nil (diredp-get-files ignore-marks-p nil nil nil nil details)))) ;;;###autoload -(defun diredp-do-symlink-recursive (&optional ignore-marks-p) ; Bound to `M-+ S' +(defun diredp-do-symlink-recursive (&optional ignore-marks-p details) ; Bound to `M-+ S' "Make symbolic links to marked files, including those in marked subdirs. Like `dired-do-symlink', but act recursively on subdirs to pick up the files to link. @@ -4784,12 +5059,16 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-do-create-files-recursive'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) - (diredp-do-create-files-recursive #'make-symbolic-link "Symlink" ignore-marks-p)) + (diredp-do-create-files-recursive #'make-symbolic-link "Symlink" ignore-marks-p details)) (when (fboundp 'dired-do-relsymlink) - (defun diredp-do-relsymlink-recursive (&optional ignore-marks-p) ; Bound to `M-+ Y' + + (defun diredp-do-relsymlink-recursive (&optional ignore-marks-p details) ; Bound to `M-+ Y' "Relative symlink all marked files, including those in marked subdirs into a dir. Like `dired-do-relsymlink', but act recursively on subdirs to pick up the files to link. @@ -4801,12 +5080,17 @@ subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this Dired buffer and all subdirs, recursively. -For absolute symlinks, use \\[diredp-do-symlink-recursive]." +For absolute symlinks, use \\[diredp-do-symlink-recursive]. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-do-create-files-recursive'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) - (diredp-do-create-files-recursive #'dired-make-relative-symlink "RelSymLink" ignore-marks-p))) + (diredp-do-create-files-recursive #'dired-make-relative-symlink "RelSymLink" ignore-marks-p details)) + + ) ;;;###autoload -(defun diredp-do-hardlink-recursive (&optional ignore-marks-p) ; Bound to `M-+ H' +(defun diredp-do-hardlink-recursive (&optional ignore-marks-p details) ; Bound to `M-+ H' "Add hard links for marked files, including those in marked subdirs. Like `dired-do-hardlink', but act recursively on subdirs to pick up the files to link. @@ -4816,12 +5100,15 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-do-create-files-recursive'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) - (diredp-do-create-files-recursive #'dired-hardlink "Hardlink" ignore-marks-p)) + (diredp-do-create-files-recursive #'dired-hardlink "Hardlink" ignore-marks-p details)) ;;;###autoload -(defun diredp-do-print-recursive (&optional ignore-marks-p) ; Bound to `M-+ P' +(defun diredp-do-print-recursive (&optional ignore-marks-p details) ; Bound to `M-+ P' "Print the marked files, including those in marked subdirs. Like `dired-do-print', but act recursively on subdirs to pick up the files to print. @@ -4831,9 +5118,12 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) - (let* ((file-list (diredp-get-files ignore-marks-p)) + (let* ((file-list (diredp-get-files ignore-marks-p nil nil nil nil details)) (command (dired-mark-read-string "Print %s with: " (mapconcat #'identity @@ -4843,7 +5133,7 @@ Dired buffer and all subdirs, recursively." (dired-run-shell-command (dired-shell-stuff-it command file-list nil)))) ;;;###autoload -(defun diredp-image-dired-display-thumbs-recursive (&optional ignore-marks-p append do-not-pop) +(defun diredp-image-dired-display-thumbs-recursive (&optional ignore-marks-p append do-not-pop details) ; Bound to `M-+ C-t d' "Display thumbnails of marked files, including those in marked subdirs. Like `image-dired-display-thumbs', but act recursively on subdirs. @@ -4855,13 +5145,16 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-image-dired-required-msg) (diredp-get-confirmation-recursive) (list current-prefix-arg))) (let ((buf (image-dired-create-thumbnail-buffer)) thumb-name files dired-buf) - (setq files (diredp-get-files ignore-marks-p) + (setq files (diredp-get-files ignore-marks-p nil nil nil nil details) dired-buf (current-buffer)) (with-current-buffer buf (let ((inhibit-read-only t)) @@ -4884,7 +5177,7 @@ Dired buffer and all subdirs, recursively." (pop-to-buffer image-dired-thumbnail-buffer)))) ;;;###autoload -(defun diredp-image-dired-tag-files-recursive (&optional ignore-marks-p) ; Bound to `M-+ C-t t' +(defun diredp-image-dired-tag-files-recursive (&optional ignore-marks-p details) ; Bound to `M-+ C-t t' "Tag marked files with an `image-dired' tag, including in marked subdirs. Like `image-dired-tag-files', but act recursively on subdirs. The files included are those that are marked in the current Dired @@ -4892,15 +5185,19 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-image-dired-required-msg) (diredp-get-confirmation-recursive) (list current-prefix-arg))) (let ((tag (read-string "Tags to add (separate tags with a semicolon): "))) - (image-dired-write-tags (mapcar (lambda (x) (cons x tag)) (diredp-get-files ignore-marks-p))))) + (image-dired-write-tags (mapcar (lambda (x) (cons x tag)) + (diredp-get-files ignore-marks-p nil nil nil nil details))))) ;;;###autoload -(defun diredp-image-dired-delete-tag-recursive (&optional ignore-marks-p) ; Bound to `M-+ C-t r' +(defun diredp-image-dired-delete-tag-recursive (&optional ignore-marks-p details) ; Bound to `M-+ C-t r' "Remove `image-dired' tag for marked files, including in marked subdirs. Like `image-dired-delete-tag', but act recursively on subdirs. The files included are those that are marked in the current Dired @@ -4908,14 +5205,18 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-image-dired-required-msg) (diredp-get-confirmation-recursive) (list current-prefix-arg))) - (image-dired-remove-tag (diredp-get-files ignore-marks-p) (read-string "Tag to remove: "))) + (image-dired-remove-tag (diredp-get-files ignore-marks-p nil nil nil nil details) + (read-string "Tag to remove: "))) ;;;###autoload -(defun diredp-image-dired-comment-files-recursive (&optional ignore-marks-p) +(defun diredp-image-dired-comment-files-recursive (&optional ignore-marks-p details) ; Bound to `M-+ C-t c' "Add comment to marked files in dired, including those in marked subdirs. Like `image-dired-dired-comment-files' but act recursively on subdirs. @@ -4924,16 +5225,19 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-image-dired-required-msg) (diredp-get-confirmation-recursive) (list current-prefix-arg))) (let ((comment (image-dired-read-comment))) (image-dired-write-comments (mapcar (lambda (curr-file) (cons curr-file comment)) - (diredp-get-files ignore-marks-p))))) + (diredp-get-files ignore-marks-p nil nil nil nil details))))) (when (> emacs-major-version 22) - (defun diredp-do-decrypt-recursive (&optional ignore-marks-p) ; Bound to `M-+ : d' + (defun diredp-do-decrypt-recursive (&optional ignore-marks-p details) ; Bound to `M-+ : d' "Decrypt marked files, including those in marked subdirs. Like `epa-dired-do-decrypt', but act recursively on subdirs to pick up the files to decrypt. @@ -4943,14 +5247,17 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) - (dolist (file (diredp-get-files ignore-marks-p)) + (dolist (file (diredp-get-files ignore-marks-p nil nil nil nil details)) (epa-decrypt-file (expand-file-name file))) (revert-buffer)) - (defun diredp-do-verify-recursive (&optional ignore-marks-p) ; Bound to `M-+ : v' + (defun diredp-do-verify-recursive (&optional ignore-marks-p details) ; Bound to `M-+ : v' "Verify marked files, including those in marked subdirs. Like `epa-dired-do-verify', but act recursively on subdirs to pick up the files to verify. @@ -4960,13 +5267,16 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) - (dolist (file (diredp-get-files ignore-marks-p)) + (dolist (file (diredp-get-files ignore-marks-p nil nil nil nil details)) (epa-verify-file (expand-file-name file))) (revert-buffer)) - (defun diredp-do-sign-recursive (&optional ignore-marks-p) ; Bound to `M-+ : s' + (defun diredp-do-sign-recursive (&optional ignore-marks-p details) ; Bound to `M-+ : s' "Sign marked files, including those in marked subdirs. Like `epa-dired-do-sign', but act recursively on subdirs to pick up the files to sign. @@ -4976,16 +5286,19 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) - (dolist (file (diredp-get-files ignore-marks-p)) + (dolist (file (diredp-get-files ignore-marks-p nil nil nil nil details)) (epa-sign-file (expand-file-name file) (epa-select-keys (epg-make-context) "Select keys for signing. If none are selected, the default secret key is used. ") (y-or-n-p "Make a detached signature? "))) (revert-buffer)) - (defun diredp-do-encrypt-recursive (&optional ignore-marks-p) ; Bound to `M-+ : e' + (defun diredp-do-encrypt-recursive (&optional ignore-marks-p details) ; Bound to `M-+ : e' "Encrypt marked files, including those in marked subdirs. Like `epa-dired-do-encrypt', but act recursively on subdirs to pick up the files to encrypt. @@ -4995,16 +5308,19 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) - (dolist (file (diredp-get-files ignore-marks-p)) + (dolist (file (diredp-get-files ignore-marks-p nil nil nil nil details)) (epa-encrypt-file (expand-file-name file) (epa-select-keys (epg-make-context) "Select recipients for encryption. If none are selected, symmetric encryption is performed. "))) (revert-buffer))) ;;;###autoload -(defun diredp-do-bookmark-recursive (&optional ignore-marks-p prefix) ; Bound to `M-+ M-b' +(defun diredp-do-bookmark-recursive (&optional ignore-marks-p prefix details) ; Bound to `M-+ M-b' "Bookmark the marked files, including those in marked subdirs. Like `diredp-do-bookmark', but act recursively on subdirs. The files included are those that are marked in the current Dired @@ -5012,16 +5328,19 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg (and diredp-prompt-for-bookmark-prefix-flag (read-string "Prefix for bookmark name: "))))) - (dolist (file (diredp-get-files ignore-marks-p)) + (dolist (file (diredp-get-files ignore-marks-p nil nil nil nil details)) (diredp-bookmark prefix file 'NO-MSG-P))) ;;;###autoload -(defun diredp-do-bookmark-dirs-recursive (ignore-marks-p &optional msg-p) +(defun diredp-do-bookmark-dirs-recursive (ignore-marks-p &optional details msgp) "Bookmark this Dired buffer and marked subdirectory Dired buffers, recursively. Create a Dired bookmark for this directory and for each of its marked subdirectories. Handle each of the marked subdirectory similarly: @@ -5046,16 +5365,19 @@ Note: * This command creates new bookmarks. It never updates or overwrites an existing bookmark. -You need library `Bookmark+' for this command." +You need library `Bookmark+' for this command. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-subdirs'." (interactive (progn (unless (featurep 'bookmark+) (error "You need library `Bookmark+' for this command")) (diredp-get-confirmation-recursive 'subdirs) (list current-prefix-arg t))) (diredp-ensure-mode) - (let ((sdirs (diredp-get-subdirs ignore-marks-p)) + (let ((sdirs (diredp-get-subdirs ignore-marks-p nil details)) (snames ()) dbufs) - (when (and msg-p sdirs) (message "Checking descendent directories...")) + (when (and msgp sdirs) (message "Checking descendant directories...")) (dolist (dir (cons default-directory sdirs)) (when (setq dbufs (dired-buffers-for-dir (expand-file-name dir))) ; Dirs with Dired buffers only. (with-current-buffer (car dbufs) @@ -5072,8 +5394,7 @@ You need library `Bookmark+' for this command." ;;;###autoload (defun diredp-do-bookmark-in-bookmark-file-recursive (bookmark-file ; Bound to `M-+ C-M-B', aka `M-+ C-M-S-b') - &optional prefix ignore-marks-p - bfile-bookmarkp) + &optional prefix ignore-marks-p bfile-bookmarkp details) "Bookmark files here and below in BOOKMARK-FILE and save BOOKMARK-FILE. Like `diredp-do-bookmark-in-bookmark-file', but act recursively on subdirs. The files included are those that are marked in the current @@ -5081,17 +5402,19 @@ Dired buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive) (let ((d-r-b-f-args (diredp-read-bookmark-file-args))) (list (car d-r-b-f-args) (cadr d-r-b-f-args) (car (cddr d-r-b-f-args)))))) (diredp-do-bookmark-in-bookmark-file bookmark-file prefix nil bfile-bookmarkp - (diredp-get-files ignore-marks-p))) + (diredp-get-files ignore-marks-p nil nil nil nil details))) ;;;###autoload -(defun diredp-set-bookmark-file-bookmark-for-marked-recursive (bookmark-file - &optional prefix arg) +(defun diredp-set-bookmark-file-bookmark-for-marked-recursive (bookmark-file &optional prefix arg details) ; Bound to `M-+ C-M-b' "Bookmark the marked files and create a bookmark-file bookmark for them. Like `diredp-set-bookmark-file-bookmark-for-marked', but act @@ -5102,14 +5425,17 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-do-bookmark-in-bookmark-file-recursive'." (interactive (progn (diredp-get-confirmation-recursive) (diredp-read-bookmark-file-args))) (diredp-ensure-bookmark+) - (diredp-do-bookmark-in-bookmark-file-recursive bookmark-file prefix arg 'CREATE-BOOKMARK-FILE-BOOKMARK)) + (diredp-do-bookmark-in-bookmark-file-recursive bookmark-file prefix arg 'CREATE-BOOKMARK-FILE-BOOKMARK details)) ;;;###autoload -(defun diredp-do-find-marked-files-recursive (&optional arg) ; Bound to `M-+ F' +(defun diredp-do-find-marked-files-recursive (&optional arg details) ; Bound to `M-+ F' "Find marked files simultaneously, including those in marked subdirs. Like `dired-do-find-marked-files', but act recursively on subdirs. The files included are those that are marked in the current Dired @@ -5126,41 +5452,55 @@ Note that prefix-argument behavior is different for this command than for `dired-do-find-marked-files'. In particular, a negative numeric prefix arg does not cause the files to be shown in separate frames. Only non-nil `pop-up-frames' (or equivalent configuration) causes -the files to be shown in separate frames." +the files to be shown in separate frames. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) (let ((narg (prefix-numeric-value arg))) - (dired-simultaneous-find-file (diredp-get-files (<= narg 0)) (and arg (>= narg 0) narg)))) + (dired-simultaneous-find-file (diredp-get-files (<= narg 0) nil nil nil nil details) + (and arg (>= narg 0) narg)))) (when (fboundp 'dired-do-isearch-regexp) ; Emacs 23+ - (defun diredp-do-isearch-recursive (&optional ignore-marks-p) ; Bound to `M-+ M-s a C-s' + + (defun diredp-do-isearch-recursive (&optional ignore-marks-p details) ; Bound to `M-+ M-s a C-s' "Isearch the marked files, including those in marked subdirs. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." - (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) - (multi-isearch-files (diredp-get-files ignore-marks-p))) +Dired buffer and all subdirs, recursively. - (defun diredp-do-isearch-regexp-recursive (&optional ignore-marks-p) ; `M-+ M-s a C-M-s' +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." + (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) + (multi-isearch-files (diredp-get-files ignore-marks-p nil nil nil nil details))) + + (defun diredp-do-isearch-regexp-recursive (&optional ignore-marks-p details) ; `M-+ M-s a C-M-s' "Regexp-Isearch the marked files, including those in marked subdirs. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." - (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) - (multi-isearch-files-regexp (diredp-get-files ignore-marks-p)))) +Dired buffer and all subdirs, recursively. -(defun diredp-do-search-recursive (regexp &optional ignore-marks-p) ; Bound to `M-+ A' +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." + (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) + (multi-isearch-files-regexp (diredp-get-files ignore-marks-p nil nil nil nil details)))) + +(defun diredp-do-search-recursive (regexp &optional ignore-marks-p details) ; Bound to `M-+ A' "Regexp-search the marked files, including those in marked subdirs. With a prefix argument, ignore all marks - include all files in this Dired buffer and all subdirs, recursively. Stops when a match is found. -To continue searching for the next match, use `\\[tags-loop-continue]'." +To continue searching for the next match, use `\\[tags-loop-continue]'. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive) (list (read-string "Search marked files (regexp): ") current-prefix-arg))) - (tags-search regexp '(diredp-get-files ignore-marks-p))) + (tags-search regexp '(diredp-get-files ignore-marks-p nil nil nil nil details))) ;;;###autoload -(defun diredp-do-query-replace-regexp-recursive (from to &optional arg) +(defun diredp-do-query-replace-regexp-recursive (from to &optional arg details) ; Bound to `M-+ Q' "Do `query-replace-regexp' on marked files, including in marked subdirs. Query-replace FROM with TO. @@ -5178,7 +5518,10 @@ With an (explicit) numeric prefix argument: * <= 0 means replace only word-delimited matches. If you exit (`\\[keyboard-quit]', `RET' or `q'), you can resume the query replacement -using `\\[tags-loop-continue]'." +using `\\[tags-loop-continue]'. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive) (let ((common (query-replace-read-args "Query replace regexp in marked files" t t))) (list (nth 0 common) @@ -5187,7 +5530,7 @@ using `\\[tags-loop-continue]'." (let* ((narg (and arg (prefix-numeric-value arg))) (delimited (and narg (<= narg 0))) (ignore-marks-p (and narg (>= narg 0))) - (files (diredp-get-files ignore-marks-p)) + (files (diredp-get-files ignore-marks-p nil nil nil nil details)) (fit-frame-min-width 30) (fit-frame-min-height 15)) (dolist (file files) @@ -5197,7 +5540,7 @@ using `\\[tags-loop-continue]'." (tags-query-replace from to delimited `',files))) ;;;###autoload -(defun diredp-do-grep-recursive (command-args) ; Bound to `M+ C-M-G' +(defun diredp-do-grep-recursive (command-args &optional details) ; Bound to `M+ C-M-G' "Run `grep' on marked files, including those in marked subdirs. Like `diredp-do-grep', but act recursively on subdirs. The files included are those that are marked in the current Dired @@ -5205,17 +5548,20 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive) (unless (if (< emacs-major-version 22) grep-command (and grep-command (or (not grep-use-null-device) (eq grep-use-null-device t)))) (grep-compute-defaults)) - (list (diredp-do-grep-1 (diredp-get-files current-prefix-arg))))) + (list (diredp-do-grep-1 (diredp-get-files current-prefix-arg nil nil nil nil details))))) (grep command-args)) ;;;###autoload -(defun diredp-marked-recursive (dirname &optional ignore-marks-p) ; Not bound to a key +(defun diredp-marked-recursive (dirname &optional ignore-marks-p details) ; Not bound to a key "Open Dired on marked files, including those in marked subdirs. Like `diredp-marked', but act recursively on subdirs. @@ -5227,52 +5573,65 @@ With a prefix argument, ignore all marks - include all files in this Dired buffer and all subdirs, recursively. When called from Lisp, DIRNAME here must be a string, not a cons. It -is used as the name of the new Dired buffer." +is used as the name of the new Dired buffer. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive) (list nil current-prefix-arg))) - (dired (cons (or dirname (generate-new-buffer-name (buffer-name))) (diredp-get-files ignore-marks-p)))) + (dired (cons (or dirname (generate-new-buffer-name (buffer-name))) + (diredp-get-files ignore-marks-p nil nil nil nil details)))) ;;;###autoload -(defun diredp-marked-recursive-other-window (dirname &optional ignore-marks-p) ; Bound to `M-+ C-M-*' - "Same as `diredp-marked-recursive', but uses a different window." +(defun diredp-marked-recursive-other-window (dirname &optional ignore-marks-p details) ; Bound to `M-+ C-M-*' + "Same as `diredp-marked-recursive', but uses a different window. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive) (list nil current-prefix-arg))) (dired-other-window - (cons (or dirname (generate-new-buffer-name (buffer-name))) (diredp-get-files ignore-marks-p)))) + (cons (or dirname (generate-new-buffer-name (buffer-name))) + (diredp-get-files ignore-marks-p nil nil nil nil details)))) ;;;###autoload -(defun diredp-list-marked-recursive (&optional ignore-marks-p predicate) ; Bound to `M-+ C-M-l' +(defun diredp-list-marked-recursive (&optional ignore-marks-p predicate details) ; Bound to `M-+ C-M-l' "List the files marked here and in marked subdirs, recursively. The files included are those that are marked in the current Dired buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, all marks are ignored: all files in this Dired -buffer and all descendent directories are included. +buffer and all descendant directories are included. You can use `RET' or `mouse-2' to visit any of the files. If `tooltip-mode' is on then moving the mouse over image-file names shows image previews. -Non-interactively, non-nil arg PREDICATE is a file-name predicate. -List only the files for which it returns non-nil." - (interactive ; No need for `diredp-get-confirmation-recursive' here. +When called from Lisp: + Non-nil optional arg PREDICATE is a file-name predicate. List only + the files for which it returns non-nil. + Non-nil optional arg DETAILS is passed to `diredp-list-files'." + (interactive ; No need for `diredp-get-confirmation-recursive' here. (progn (diredp-ensure-mode) (list current-prefix-arg))) - (let ((files (diredp-get-files ignore-marks-p predicate))) (diredp-list-files files))) + (let ((files (diredp-get-files ignore-marks-p predicate))) (diredp-list-files files nil nil nil details))) ;;;###autoload -(defun diredp-flag-auto-save-files-recursive (&optional arg) ; `M-+ #' +(defun diredp-flag-auto-save-files-recursive (&optional arg details) ; `M-+ #' "Flag all auto-save files for deletion, including in marked subdirs. A non-negative prefix arg means to unmark (unflag) them instead. A non-positive prefix arg means to ignore subdir markings and act instead on ALL subdirs. That is, flag all in this directory and all -descendant directories." +descendant directories. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-mark-recursive-1'." (interactive "P") (let ((dired-marker-char dired-del-marker)) - (diredp-mark-recursive-1 arg "auto-save files" "auto-save file" '(diredp-looking-at-p "^.* #.+#$")))) + (diredp-mark-recursive-1 arg "auto-save files" "auto-save file" '(diredp-looking-at-p "^.* #.+#$") details))) (when (fboundp 'char-displayable-p) ; Emacs 22+ - (defun diredp-change-marks-recursive (old new &optional arg predicate) ; `M-+ * c' + (defun diredp-change-marks-recursive (old new &optional arg predicate details) ; `M-+ * c' "Change all OLD marks to NEW marks, including those in marked subdirs. The files included are those that are marked in the current Dired buffer, or all files in the directory if none are marked. Marked @@ -5287,8 +5646,10 @@ subdirectories are handled recursively in the same way. Note: If there is more than one Dired buffer for a given subdirectory then only the first such is used. -Non-interactively, non-nil arg PREDICATE is a file-name predicate. -Act on only the files for which it returns non-nil." +When called from Lisp: + Non-nil arg PREDICATE is a file-name predicate. Act on only the + files for which it returns non-nil. + DETAILS is passed to `diredp-get-subdirs'." (interactive (progn (diredp-get-confirmation-recursive) (let* ((cursor-in-echo-area t) @@ -5299,7 +5660,7 @@ Act on only the files for which it returns non-nil." (nosubs (natnump numarg)) (ignore-marks (and numarg (<= numarg 0))) (dired-marker-char new) - (sdirs (diredp-get-subdirs ignore-marks)) + (sdirs (diredp-get-subdirs ignore-marks details)) (old-strg (format "\n%c" old)) (count 0) dbufs) @@ -5323,16 +5684,19 @@ Act on only the files for which it returns non-nil." (setq count (1+ count)))))))))) (message "%d mark%s changed from `%c' to `%c'" count (dired-plural-s count) old new))) - (defun diredp-unmark-all-marks-recursive (&optional arg) ; `M-+ U' + (defun diredp-unmark-all-marks-recursive (&optional arg details) ; `M-+ U' "Remove ALL marks everywhere, including in marked subdirs. A prefix arg is as for `diredp-unmark-all-files-recursive'. Note that a negative prefix arg (e.g. `C--') removes all marks from this Dired buffer and then does the same recursively for each of its -subdirs." - (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) - (diredp-unmark-all-files-recursive ?\r arg)) +subdirs. - (defun diredp-unmark-all-files-recursive (mark &optional arg predicate) ; `M-+ M-DEL' +When called from Lisp, optional arg DETAILS is passed to +`diredp-unmark-all-files-recursive'." + (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) + (diredp-unmark-all-files-recursive ?\r arg details)) + + (defun diredp-unmark-all-files-recursive (mark &optional arg predicate details) ; `M-+ M-DEL' "Remove a given mark (or ALL) everywhere, including in marked subdirs. You are prompted for the mark character to remove. If you hit `RET' instead then ALL mark characters are removed. @@ -5350,8 +5714,10 @@ subdirectories are handled recursively in the same way. Note: If there is more than one Dired buffer for a given subdirectory then only the first such is used. -Non-interactively, non-nil arg PREDICATE is a file-name predicate. -Act on only the files for which it returns non-nil." +When called from Lisp: + Non-nil arg PREDICATE is a file-name predicate. Act on only the + files for which it returns non-nil. + DETAILS is passed to `diredp-get-subdirs'." (interactive (progn (diredp-get-confirmation-recursive) (let* ((cursor-in-echo-area t) @@ -5361,7 +5727,7 @@ Act on only the files for which it returns non-nil." (nosubs (natnump numarg)) (ignore-marks (and numarg (<= numarg 0))) (dired-marker-char ?\ ) ; Unmark - (sdirs (diredp-get-subdirs ignore-marks)) + (sdirs (diredp-get-subdirs ignore-marks details)) (mrk-strg (format "\n%c" mark)) (count 0) dbufs) @@ -5389,22 +5755,28 @@ Act on only the files for which it returns non-nil." ) (when (and (memq system-type '(windows-nt ms-dos)) (fboundp 'w32-browser)) - (defun diredp-multiple-w32-browser-recursive (&optional ignore-marks-p) + + (defun diredp-multiple-w32-browser-recursive (&optional ignore-marks-p details) "Run Windows apps for with marked files, including those in marked subdirs. Like `dired-multiple-w32-browser', but act recursively on subdirs. See `diredp-do-find-marked-files-recursive' for a description of the files included. In particular, if no files are marked here or in a -marked subdir, then all files in the directory are included." +marked subdir, then all files in the directory are included. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) - (let ((files (diredp-get-files ignore-marks-p))) + (let ((files (diredp-get-files ignore-marks-p nil nil nil nil details))) (while files (w32-browser (car files)) (sleep-for w32-browser-wait-time) - (setq files (cdr files)))))) + (setq files (cdr files))))) + + ) ;;;###autoload -(defun diredp-copy-filename-as-kill-recursive (&optional arg) ; Bound to `M-+ M-w' +(defun diredp-copy-filename-as-kill-recursive (&optional arg details) ; Bound to `M-+ M-w' "Copy names of marked files here and in marked subdirs, to `kill-ring'. The names are separated by a space. @@ -5424,14 +5796,17 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. The names are copied to the kill ring and to variable -`diredp-last-copied-filenames'." +`diredp-last-copied-filenames'. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive ; No need for `diredp-get-confirmation-recursive' here. (progn (diredp-ensure-mode) (list current-prefix-arg))) (let* ((files (mapcar (cond ((zerop (prefix-numeric-value arg)) #'identity) ((consp arg) (lambda (fn) (concat (dired-current-directory t) (file-name-nondirectory fn)))) (t (lambda (fn) (file-name-nondirectory fn)))) - (diredp-get-files))) + (diredp-get-files nil nil nil nil nil details))) (string (mapconcat #'identity files " "))) (unless (string= "" string) (if (eq last-command 'kill-region) (kill-append string nil) (kill-new string)) @@ -5439,7 +5814,7 @@ The names are copied to the kill ring and to variable (message "%s" string))) ;;;###autoload -(defun diredp-copy-abs-filenames-as-kill-recursive (&optional ignore-marks-p) ; Not bound. +(defun diredp-copy-abs-filenames-as-kill-recursive (&optional ignore-marks-p details) ; Not bound. "Copy absolute names of files marked here and in marked subdirs, recursively. The names are copied to the kill ring and to variable `dired-copy-filename-as-kill'. @@ -5447,14 +5822,18 @@ The names are copied to the kill ring and to variable The files whose names are copied are those that are marked in the current Dired buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same -way." +way. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-copy-filename-as-kill-recursive'." (interactive ; No need for `diredp-get-confirmation-recursive' here. (progn (diredp-ensure-mode) (list current-prefix-arg))) - (diredp-copy-filename-as-kill-recursive 0) + (diredp-copy-filename-as-kill-recursive 0 details) (setq diredp-last-copied-filenames (car kill-ring-yank-pointer))) ;;;###autoload -(defun diredp-mark-files-regexp-recursive (regexp &optional marker-char ignore-marks-p) ; Bound to `M-+ % m' +(defun diredp-mark-files-regexp-recursive (regexp + &optional marker-char ignore-marks-p details) ; Bound to `M-+ % m' "Mark all files matching REGEXP, including those in marked subdirs. Like `dired-mark-files-regexp' but act recursively on marked subdirs. @@ -5478,7 +5857,9 @@ object files--just `.o' will mark more than you might think. REGEXP is added to `regexp-search-ring', for regexp search. Note: If there is more than one Dired buffer for a given subdirectory -then only the first such is used." +then only the first such is used. + +When called from Lisp, DETAILS is passed to `diredp-get-subdirs'." (interactive (let* ((numarg (and current-prefix-arg (prefix-numeric-value current-prefix-arg))) (unmark (and numarg (>= numarg 0))) (ignorep (and numarg (<= numarg 0)))) @@ -5487,7 +5868,7 @@ then only the first such is used." ignorep))) (add-to-list 'regexp-search-ring regexp) ; Add REGEXP to `regexp-search-ring'. (let ((dired-marker-char (or marker-char dired-marker-char)) - (sdirs (diredp-get-subdirs ignore-marks-p)) + (sdirs (diredp-get-subdirs ignore-marks-p details)) (matched 0) (changed 0) dbufs chg.mtch) @@ -5509,7 +5890,80 @@ then only the first such is used." (if (not (= matched changed)) changed "") (if (eq ?\040 dired-marker-char) "unmarked" "marked")))) -(defun diredp-mark-extension-recursive (extension &optional arg) ; Bound to `M-+ * .' +;;;###autoload +(defun diredp-mark-files-containing-regexp-recursive (regexp + &optional marker-char ignore-marks-p details) ; `M-+ % g' + "Mark files with contents containing a REGEXP match, including in marked subdirs. +Like `dired-mark-files-containing-regexp' but act recursively on +marked subdirs. + +A non-negative prefix arg means to UNmark the files instead. + +A non-positive prefix arg means to ignore subdir markings and act +instead on ALL subdirs. That is, mark all matching files in this +directory and all descendant directories. + +REGEXP is added to `regexp-search-ring', for regexp search. + +Note: If there is more than one Dired buffer for a given subdirectory +then only the first such is used. + +If a file is visited in a buffer and `dired-always-read-filesystem' is +nil, this looks in the buffer without revisiting the file, so the +results might be inconsistent with the file on disk if its contents +have changed since it was last visited. + +When called from Lisp, DETAILS is passed to `diredp-get-subdirs'." + + (interactive (let* ((numarg (and current-prefix-arg (prefix-numeric-value current-prefix-arg))) + (unmark (and numarg (>= numarg 0))) + (ignorep (and numarg (<= numarg 0)))) + (list (diredp-read-regexp (concat (if unmark "UNmark" "Mark") " files containing (regexp): ")) + (and unmark ?\040) + ignorep))) + (add-to-list 'regexp-search-ring regexp) ; Add REGEXP to `regexp-search-ring'. + + + (let ((dired-marker-char (or marker-char dired-marker-char)) + (sdirs (diredp-get-subdirs ignore-marks-p details)) + (matched 0) + (changed 0) + dbufs chg.mtch) + (message "%s files..." (if (eq ?\040 dired-marker-char) "UNmarking" "Marking")) + (dolist (dir (cons default-directory sdirs)) + (when (setq dbufs (dired-buffers-for-dir (expand-file-name dir))) ; Dirs with Dired buffers only. + (with-current-buffer (car dbufs) + (setq chg.mtch + (diredp-mark-if + (and (not (diredp-looking-at-p dired-re-dot)) + (not (eolp)) + (let ((fname (dired-get-filename nil t))) + + (and fname + (file-readable-p fname) + (not (file-directory-p fname)) + (let ((prebuf (get-file-buffer fname))) + (message "Checking %s" fname) + ;; For now, do it inside Emacs. Grep might be better if there are lots of files. + (if (and prebuf (or (not (boundp 'dired-always-read-filesystem)) + (not dired-always-read-filesystem))) ; Emacs 26+ + (with-current-buffer prebuf + (save-excursion (goto-char (point-min)) (re-search-forward regexp nil t))) + (with-temp-buffer + (insert-file-contents fname) + (goto-char (point-min)) + (re-search-forward regexp nil t))))))) + "file") + changed (+ changed (or (car chg.mtch) 0)) + matched (+ matched (or (cdr chg.mtch) 0)))))) + (message "%s file%s%s%s newly %s" + matched + (dired-plural-s matched) + (if (not (= matched changed)) " matched, " "") + (if (not (= matched changed)) changed "") + (if (eq ?\040 dired-marker-char) "unmarked" "marked")))) + +(defun diredp-mark-extension-recursive (extension &optional arg details) ; Bound to `M-+ * .' "Mark all files with a certain EXTENSION, including in marked subdirs. A `.' is not automatically prepended to the string entered. @@ -5524,7 +5978,9 @@ descendant directories. Non-interactively, EXTENSION is the extension (a string). It can also be a list of extension strings. -Optional argument ARG is the prefix arg." +Optional argument ARG is the prefix arg. + +When called from Lisp, DETAILS is passed to `diredp-mark-files-regexp-recursive'." (interactive (let* ((numarg (and current-prefix-arg (prefix-numeric-value current-prefix-arg))) (unmark (and numarg (>= numarg 0)))) (list (diredp-read-regexp (concat (if unmark "UNmark" "Mark") " extension: ")) @@ -5537,27 +5993,221 @@ Optional argument ARG is the prefix arg." (mapconcat #'regexp-quote extension "\\|") "\\)$") (if unmark ?\040 dired-marker-char) - ignorep))) + ignorep + details))) + +;; FIXME: Factor out code that is common with `dired-mark-sexp'. +;; +;;;###autoload +(defun diredp-mark-sexp-recursive (predicate &optional arg details) ; Bound to `M-+ M-(', `M-+ * (' + "Mark files here and below for which PREDICATE returns non-nil. +Like `diredp-mark-sexp', but act recursively on subdirs. + +A non-negative prefix arg means to unmark those files instead. + +A non-positive prefix arg means to ignore subdir markings and act +instead on ALL subdirs. That is, mark all in this directory and all +descendant directories. + +PREDICATE is a lisp sexp that can refer to the following symbols as +variables: + + `mode' [string] file permission bits, e.g. \"-rw-r--r--\" + `nlink' [integer] number of links to file + `size' [integer] file size in bytes + `uid' [string] owner + `gid' [string] group (If the gid is not displayed by `ls', + this will still be set (to the same as uid)) + `time' [string] the time that `ls' displays, e.g. \"Feb 12 14:17\" + `name' [string] the name of the file + `sym' [string] if file is a symbolic link, the linked-to name, + else \"\" + `inode' [integer] the inode of the file (only for `ls -i' output) + `blks' [integer] the size of the file for `ls -s' output + (ususally in blocks or, with `-k', in Kbytes) +Examples: + Mark zero-length files: `(equal 0 size)' + Mark files last modified on Feb 2: `(string-match \"Feb 2\" time)' + Mark uncompiled Emacs Lisp files (`.el' file without a `.elc' file): + First, Dired just the source files: `dired *.el'. + Then, use \\[diredp-mark-sexp-recursive] with this sexp: + (not (file-exists-p (concat name \"c\"))) + +There's an ambiguity when a single integer not followed by a unit +prefix precedes the file mode: It is then parsed as inode number +and not as block size (this always works for GNU coreutils ls). + +Another limitation is that the uid field is needed for the +function to work correctly. In particular, the field is not +present for some values of `ls-lisp-emulation'. + +This function operates only on the Dired buffer content. It does not +refer at all to the underlying file system. Contrast this with +`find-dired', which might be preferable for the task at hand. + +When called from Lisp, DETAILS is passed to `diredp-get-subdirs'." + ;; Using `sym' = "", instead of nil, for non-linked files avoids the trap of + ;; (string-match "foo" sym) into which a user would soon fall. + ;; Use `equal' instead of `=' in the example, as it works on integers and strings. + ;;@@@ (interactive "xMark if (vars: inode,blks,mode,nlink,uid,gid,size,time,name,sym): \nP") + + (interactive + (let* ((numarg (and current-prefix-arg (prefix-numeric-value current-prefix-arg))) + (unmark (and numarg (>= numarg 0)))) + (diredp-get-confirmation-recursive) + (list (diredp-read-expression (format "%s if (Lisp expr): " (if current-prefix-arg "UNmark" "Mark"))) + current-prefix-arg))) + + (message "%s" predicate) + (let* ((numarg (and arg (prefix-numeric-value arg))) + (unmark (and numarg (>= numarg 0))) + (ignorep (and numarg (<= numarg 0))) + (dired-marker-char (if unmark ?\040 dired-marker-char)) + (inode nil) + (blks ()) + (matched 0) + (changed 0) + dbufs chg.mtch mode nlink uid gid size time name sym) + (dolist (dir (cons default-directory (diredp-get-subdirs ignorep details))) + (when (setq dbufs (dired-buffers-for-dir (expand-file-name dir))) ; Dirs with Dired buffers only. + (with-current-buffer (car dbufs) + (setq chg.mtch + (diredp-mark-if + (save-excursion + (and + ;; Sets vars INODE BLKS MODE NLINK UID GID SIZE TIME NAME and SYM + ;; according to current file line. Returns `t' for success, nil if + ;; there is no file line. Upon success, these vars are set, to either + ;; nil or the appropriate value, so they need not be initialized. + ;; Moves point within the current line. + (dired-move-to-filename) + (let ((mode-len 10) ; Length of `mode' string. + ;; As in `dired.el', but with subexpressions \1=inode, \2=blks: + ;; GNU `ls -hs' suffixes the block count with a unit and prints it as a float + ;; FreeBSD does neither. + ;; $$$$$$ (dired-re-inode-size "\\s *\\([0-9]*\\)\\s *\\([0-9]*\\) ?") + (dired-re-inode-size (if (> emacs-major-version 24) + "\\=\\s *\\([0-9]+\\s +\\)?\ +\\(?:\\([0-9]+\\(?:\\.[0-9]*\\)?[BkKMGTPEZY]?\\)? ?\\)" + "\\s *\\([0-9]*\\)\\s *\\([0-9]*\\) ?")) + pos) + (beginning-of-line) + (forward-char 2) + (search-forward-regexp dired-re-inode-size nil t) + ;; `INODE', `BLKS', `MODE' + ;; XXX Might be a size not followed by a unit prefix. + ;; Could set `blks' to `inode' if it were otherwise nil, with similar reasoning + ;; as for setting `gid' to `uid', but it would be even more whimsical. + (setq inode (and (match-string 1) (string-to-number (match-string 1))) + blks (and (match-string 2) (if (fboundp 'dired-x--string-to-number) ; Emacs 25+ + (dired-x--string-to-number (match-string 2)) + (string-to-number (match-string 2)))) + mode (buffer-substring (point) (+ mode-len (point)))) + (forward-char mode-len) + ;; Skip any extended attributes marker ("." or "+"). + (unless (diredp-looking-at-p " ") (forward-char 1)) + (setq nlink (read (current-buffer))) ; `NLINK' + + ;; `UID' + ;; Another issue is that GNU `ls -n' right-justifies numerical UIDs and GIDs, + ;; while FreeBSD left-justifies them, so do not rely on a specific whitespace + ;; layout. Both of them right-justify all other numbers, though. + ;; XXX Return a number if the `uid' or `gid' seems to be numerical? + ;; $$$$$$ (setq uid (buffer-substring (+ (point) 1) (progn (forward-word 1) (point)))) + (setq uid (buffer-substring (progn (skip-chars-forward " \t") (point)) + (progn (skip-chars-forward "^ \t") (point)))) + (cond ((> emacs-major-version 24) + (dired-move-to-filename) + (save-excursion + (setq time ; `TIME' + ;; The regexp below tries to match from the last digit of the size + ;; field through a space after the date. Also, dates may have + ;; different formats depending on file age, so the date column need + ;; not be aligned to the right. + (buffer-substring + (save-excursion (skip-chars-backward " \t") (point)) + (progn (re-search-backward directory-listing-before-filename-regexp) + (skip-chars-forward "^ \t") + (1+ (point)))) + + size ; `SIZE' + (dired-x--string-to-number + ;; We know that there's some kind of number before point because + ;; the regexp search above succeeded. Not worth doing an extra + ;; check for leading garbage. + (buffer-substring (point) (progn (skip-chars-backward "^ \t") (point)))) + ;; If no `gid' is displayed, `gid' will be set to `uid' but user + ;; will then not reference it anyway in PREDICATE. + + gid ; `GID' + (buffer-substring (progn (skip-chars-backward " \t") (point)) + (progn (skip-chars-backward "^ \t") (point))))) + ;; `NAME', `SYM' + (setq name (buffer-substring (point) + (or (dired-move-to-end-of-filename t) (point))) + sym (if (diredp-looking-at-p " -> ") + (buffer-substring (progn (forward-char 4) (point)) + (line-end-position)) + ""))) + (t + (re-search-forward + (if (< emacs-major-version 20) + "\\(Jan\\|Feb\\|Mar\\|Apr\\|May\\|Jun\\|Jul\\|Aug\\|Sep\\|Oct\\|Nov\\|Dec\\)" + dired-move-to-filename-regexp)) + (goto-char (match-beginning 1)) + (forward-char -1) + (setq size ; `SIZE' + (string-to-number (buffer-substring (save-excursion (backward-word 1) + (setq pos (point))) + (point)))) + (goto-char pos) + (backward-word 1) + ;; `GID', `TIME', `NAME', `SYM' + ;; if no `gid' is displayed, `gid' will be set to `uid' but user will then + ;; not reference it anyway in PREDICATE. + (setq gid (buffer-substring (save-excursion (forward-word 1) (point)) (point)) + time (buffer-substring (match-beginning 1) (1- (dired-move-to-filename))) + name (buffer-substring (point) (or (dired-move-to-end-of-filename t) + (point))) + sym (if (diredp-looking-at-p " -> ") + (buffer-substring (progn (forward-char 4) (point)) + (line-end-position)) + ""))))) + ;; Vanilla Emacs uses `lexical-binding' = t, and it passes bindings to `eval' + ;; as a second arg. We use `lexical-binding' = nil, and anyway there should + ;; be no need to pass the bindings. + (eval predicate))) + (format "'%s file" predicate))) + (setq changed (+ changed (or (car chg.mtch) 0)) + matched (+ matched (or (cdr chg.mtch) 0)))))) + (message "%s file%s%s%s newly %s" matched (dired-plural-s matched) + (if (not (= matched changed)) " matched, " "") + (if (not (= matched changed)) changed "") + (if (eq ?\040 dired-marker-char) "unmarked" "marked")))) ;;;###autoload -(defun diredp-mark-autofiles-recursive (&optional arg) ; Bound to `M-+ * B' +(defun diredp-mark-autofiles-recursive (&optional arg details) ; Bound to `M-+ * B' "Mark all autofiles, including in marked subdirs. Autofiles are files that have an autofile bookmark. A non-negative prefix arg means to unmark them instead. A non-positive prefix arg means to ignore subdir markings and act instead on ALL subdirs. That is, mark all in this directory and all -descendant directories." +descendant directories. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-mark-recursive-1'." (interactive "P") (diredp-ensure-bookmark+) (diredp-ensure-mode) (diredp-mark-recursive-1 arg "autofiles" "autofile" '(and (not (diredp-looking-at-p dired-re-dot)) (not (eolp)) (let ((fname (dired-get-filename nil t))) - (and fname (bmkp-get-autofile-bookmark fname)))))) + (and fname (bmkp-get-autofile-bookmark fname)))) + details)) ;;;###autoload -(defun diredp-mark-executables-recursive (&optional arg) ; Bound to `M-+ * *' +(defun diredp-mark-executables-recursive (&optional arg details) ; Bound to `M-+ * *' "Mark all executable files, including in marked subdirs. The files included are those that are marked in the current Dired buffer, or all files in the directory if none are marked. Marked @@ -5567,12 +6217,15 @@ A non-negative prefix arg means to unmark them instead. A non-positive prefix arg means to ignore subdir markings and act instead on ALL subdirs. That is, mark all in this directory and all -descendant directories." +descendant directories. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-mark-recursive-1'." (interactive "P") - (diredp-mark-recursive-1 arg "executable files" "executable file" '(diredp-looking-at-p dired-re-exe))) + (diredp-mark-recursive-1 arg "executable files" "executable file" '(diredp-looking-at-p dired-re-exe) details)) ;;;###autoload -(defun diredp-mark-directories-recursive (&optional arg) ; Bound to `M-+ * /' +(defun diredp-mark-directories-recursive (&optional arg details) ; Bound to `M-+ * /' "Mark all directories except `.' and `..', including in marked subdirs. The directories included are those that are marked in the current Dired buffer, or all subdirs in the directory if none are marked. @@ -5582,12 +6235,16 @@ A non-negative prefix arg means to unmark them instead. A non-positive prefix arg means to ignore subdir markings and act instead on ALL subdirs. That is, mark all in this directory and all -descendant directories." +descendant directories. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-mark-recursive-1'." (interactive "P") (diredp-mark-recursive-1 arg "directories" "directory" '(and (diredp-looking-at-p dired-re-dir) - (not (diredp-looking-at-p dired-re-dot))))) + (not (diredp-looking-at-p dired-re-dot))) + details)) ;;;###autoload -(defun diredp-mark-symlinks-recursive (&optional arg) ; Bound to `M-+ * @' +(defun diredp-mark-symlinks-recursive (&optional arg details) ; Bound to `M-+ * @' "Mark all symbolic links, including in marked subdirs. The symlinks included are those that are marked in the current Dired buffer, or all symlinks in the directory if none are marked. Marked @@ -5597,17 +6254,22 @@ A non-negative prefix arg means to unmark them instead. A non-positive prefix arg means to ignore subdir markings and act instead on ALL subdirs. That is, mark all in this directory and all -descendant directories." - (interactive "P") - (diredp-mark-recursive-1 arg "symlinks" "symbolic link" '(diredp-looking-at-p dired-re-sym))) +descendant directories. -(defun diredp-mark-recursive-1 (arg plural singular predicate-sexp) - "Helper for `diredp-mark-*-recursive' commands." +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-subdirs'." + (interactive "P") + (diredp-mark-recursive-1 arg "symlinks" "symbolic link" '(diredp-looking-at-p dired-re-sym) details)) + +(defun diredp-mark-recursive-1 (arg plural singular predicate-sexp details) + "Helper for `diredp-mark-*-recursive' commands. +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-subdirs'." (let* ((numarg (and arg (prefix-numeric-value arg))) (unmark (and numarg (>= numarg 0))) (ignorep (and numarg (<= numarg 0))) (dired-marker-char (if unmark ?\040 dired-marker-char)) - (sdirs (diredp-get-subdirs ignorep)) + (sdirs (diredp-get-subdirs ignorep details)) (changed 0) (matched 0) dbufs chg.mtch) @@ -5626,7 +6288,7 @@ descendant directories." (if (eq ?\040 dired-marker-char) "unmarked" "marked")))) ;;;###autoload -(defun diredp-capitalize-recursive (&optional ignore-marks-p) ; Bound to `M-+ % c' +(defun diredp-capitalize-recursive (&optional ignore-marks-p details) ; Bound to `M-+ % c' "Rename marked files, including in marked subdirs, by capitalizing them. Like `diredp-capitalize', but act recursively on subdirs. @@ -5635,13 +6297,16 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-create-files-non-directory-recursive'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) (diredp-create-files-non-directory-recursive - #'dired-rename-file #'capitalize "Rename by capitalizing:" ignore-marks-p)) + #'dired-rename-file #'capitalize "Rename by capitalizing:" ignore-marks-p details)) ;;;###autoload -(defun diredp-upcase-recursive (&optional ignore-marks-p) ; Bound to `M-+ % u' +(defun diredp-upcase-recursive (&optional ignore-marks-p details) ; Bound to `M-+ % u' "Rename marked files, including in marked subdirs, making them uppercase. Like `dired-upcase', but act recursively on subdirs. @@ -5650,13 +6315,16 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-create-files-non-directory-recursive'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) (diredp-create-files-non-directory-recursive - #'dired-rename-file #'upcase "Rename to uppercase:" ignore-marks-p)) + #'dired-rename-file #'upcase "Rename to uppercase:" ignore-marks-p details)) ;;;###autoload -(defun diredp-downcase-recursive (&optional ignore-marks-p) ; Bound to `M-+ % l' +(defun diredp-downcase-recursive (&optional ignore-marks-p details) ; Bound to `M-+ % l' "Rename marked files, including in marked subdirs, making them lowercase. Like `dired-downcase', but act recursively on subdirs. @@ -5665,13 +6333,16 @@ buffer, or all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-create-files-non-directory-recursive'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) (diredp-create-files-non-directory-recursive - #'dired-rename-file #'downcase "Rename to lowercase:" ignore-marks-p)) + #'dired-rename-file #'downcase "Rename to lowercase:" ignore-marks-p details)) ;;;###autoload -(defun diredp-do-apply-function-recursive (function &optional arg) ; Bound to `M-+ @' +(defun diredp-do-apply-function-recursive (function &optional arg details) ; Bound to `M-+ @' "Apply FUNCTION to the marked files. Like `diredp-do-apply-function' but act recursively on subdirs. @@ -5685,29 +6356,35 @@ Otherwise, apply FUNCTION to each file name. Any other prefix arg behaves according to the ARG argument of `dired-get-marked-files'. In particular, `C-u C-u' operates on all -files in the Dired buffer." +files in the Dired buffer. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-get-confirmation-recursive) (list (read (completing-read "Function: " obarray 'functionp nil nil (and (boundp 'function-name-history) 'function-name-history))) current-prefix-arg))) (if (and (consp arg) (< (car arg) 16)) (dolist (file (diredp-get-files)) (with-current-buffer (find-file-noselect file) (funcall function))) - (dolist (file (diredp-get-files arg)) (funcall function file)))) + (dolist (file (diredp-get-files arg nil nil nil nil details)) (funcall function file)))) ;;;###autoload -(defun diredp-do-delete-recursive (arg) ; Bound to `M-+ D' +(defun diredp-do-delete-recursive (arg &optional details) ; Bound to `M-+ D' "Delete marked (not flagged) files, including in marked subdirs. Like `dired-do-delete' but act recursively on subdirs. The files to be deleted are those that are marked in the current Dired buffer, or all files in the directory if none are marked. Marked -subdirectories are handled recursively in the same way." +subdirectories are handled recursively in the same way. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files' and `diredp-get-subdirs'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) (unless arg (ding) (message "NOTE: Deletion of files marked `%c' (not those flagged `%c')." dired-marker-char dired-del-marker)) - (let* ((files (diredp-get-files nil nil nil nil 'ONLY-MARKED-P)) + (let* ((files (diredp-get-files nil nil nil nil 'ONLY-MARKED-P details)) (count (length files)) (trashing (and (boundp 'delete-by-moving-to-trash) delete-by-moving-to-trash)) (succ 0)) @@ -5740,7 +6417,7 @@ subdirectories are handled recursively in the same way." (if (fboundp 'progress-reporter-done) (progress-reporter-done progress-reporter) (message "Deleting...done"))) - (let ((sdirs (diredp-get-subdirs)) + (let ((sdirs (diredp-get-subdirs nil nil details)) dbufs) (dolist (dir (cons default-directory sdirs)) (when (setq dbufs (dired-buffers-for-dir (expand-file-name dir))) ; Dirs with Dired buffers only. @@ -5748,7 +6425,7 @@ subdirectories are handled recursively in the same way." (message "OK. NO deletions performed")))) ;;;###autoload -(defun diredp-do-move-recursive (&optional ignore-marks-p) ; Bound to `M-+ R' +(defun diredp-do-move-recursive (&optional ignore-marks-p details) ; Bound to `M-+ R' "Move marked files, including in marked subdirs, to a given directory. Like `dired-do-rename', but act recursively on subdirs to pick up the files to move. @@ -5769,10 +6446,10 @@ Renames any buffers that are visiting the files. The default suggested for the target directory depends on the value of `dired-dwim-target', which see." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) - (diredp-do-create-files-recursive #'dired-rename-file "Move" ignore-marks-p)) + (diredp-do-create-files-recursive #'dired-rename-file "Move" ignore-marks-p details)) ;;;###autoload -(defun diredp-do-copy-recursive (&optional ignore-marks-p) ; Bound to `M-+ C' +(defun diredp-do-copy-recursive (&optional ignore-marks-p details) ; Bound to `M-+ C' "Copy marked files, including in marked subdirs, to a given directory. Like `dired-do-copy', but act recursively on subdirs to pick up the files to copy. @@ -5795,20 +6472,26 @@ The default suggested for the target directory depends on the value of `dired-dwim-target', which see. This command copies symbolic links by creating new ones, like UNIX -command `cp -d'." +command `cp -d'. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-do-create-files-recursive'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) (let ((dired-recursive-copies nil)) ; Doesn't have to be nil, but let's not go overboard now. - (diredp-do-create-files-recursive #'dired-copy-file "Copy" ignore-marks-p))) + (diredp-do-create-files-recursive #'dired-copy-file "Copy" ignore-marks-p details))) -(defun diredp-do-create-files-recursive (file-creator operation ignore-marks-p) +(defun diredp-do-create-files-recursive (file-creator operation ignore-marks-p &optional details) "Create a new file for each marked file, including those in marked subdirs. Like `dired-do-create-files', but act recursively on subdirs, and always keep markings. Prompts for the target directory, in which to create the files. FILE-CREATOR OPERATION is as in `dired-create-files'. Non-nil IGNORE-MARKS-P means ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." - (lexical-let* ((fn-list (diredp-get-files ignore-marks-p)) +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." + (lexical-let* ((fn-list (diredp-get-files ignore-marks-p nil nil nil nil details)) (target-dir (dired-dwim-target-directory)) (defaults (and (fboundp 'dired-dwim-target-defaults) ; Emacs 23+ (dired-dwim-target-defaults fn-list target-dir))) @@ -5838,7 +6521,7 @@ Dired buffer and all subdirs, recursively." ?*))) (defun diredp-create-files-non-directory-recursive (file-creator basename-constructor operation - &optional ignore-marks-p) + &optional ignore-marks-p details) "Apply FILE-CREATOR + BASENAME-CONSTRUCTOR to non-dir part of marked names. Like `dired-create-files-non-directory', but act recursively on subdirs. @@ -5847,12 +6530,15 @@ all files in the directory if none are marked. Marked subdirectories are handled recursively in the same way. With non-nil IGNORE-MARKS-P, ignore all marks - include all files in -this Dired buffer and all subdirs, recursively." +this Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (let (rename-non-directory-query) (dired-create-files file-creator operation - (diredp-get-files ignore-marks-p) + (diredp-get-files ignore-marks-p nil nil nil nil details) #'(lambda (from) (let ((to (concat (file-name-directory from) (funcall basename-constructor (file-name-nondirectory from))))) @@ -5868,7 +6554,7 @@ Type SPC or `y' to %s one file, DEL or `n' to skip to next, ;; `dired-file-marker', which only works in the current Dired directory. ?*))) -(defun diredp-do-chxxx-recursive (attribute-name program op-symbol &optional ignore-marks-p default) +(defun diredp-do-chxxx-recursive (attribute-name program op-symbol &optional ignore-marks-p default details) "Change attributes of the marked files, including those in marked subdirs. Refresh their file lines. @@ -5881,13 +6567,15 @@ ATTRIBUTE-NAME is a string describing the attribute to the user. PROGRAM is the program used to change the attribute. OP-SYMBOL is the type of operation (for use in `dired-mark-pop-up'). Non-nil IGNORE-MARKS-P means ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." + Dired buffer and all subdirs, recursively. +DEFAULT is the default value for reading the mark string. +DETAILS is passed to `diredp-get-files' and + `diredp-do-redisplay-recursive'." (let* ((this-buff (current-buffer)) - (files (diredp-get-files ignore-marks-p)) + (files (diredp-get-files ignore-marks-p nil nil nil nil details)) (prompt (concat "Change " attribute-name " of %s to: ")) (new-attribute (if (> emacs-major-version 22) - (dired-mark-read-string prompt nil op-symbol - ignore-marks-p files default) + (dired-mark-read-string prompt nil op-symbol ignore-marks-p files default) (dired-mark-read-string prompt nil op-symbol ignore-marks-p files))) (operation (concat program " " new-attribute)) failures) @@ -5900,11 +6588,11 @@ Dired buffer and all subdirs, recursively." (and (diredp-string-match-p "gnu" system-configuration) '("--"))) ; -------------------------------- files)) - (with-current-buffer this-buff (diredp-do-redisplay-recursive 'MSGP)) + (with-current-buffer this-buff (diredp-do-redisplay-recursive details 'MSGP)) (when failures (dired-log-summary (format "%s: error" operation) nil)))) ;;;###autoload -(defun diredp-do-chmod-recursive (&optional ignore-marks-p) ; Bound to `M-+ M' +(defun diredp-do-chmod-recursive (&optional ignore-marks-p details) ; Bound to `M-+ M' "Change the mode of the marked files, including those in marked subdirs. Symbolic modes like `g+w' are allowed. @@ -5912,9 +6600,12 @@ Note that marked subdirs are not changed. Their markings are used only to indicate that some of their files are to be changed. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files' and `diredp-do-redisplay-recursive'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) - (let* ((files (diredp-get-files ignore-marks-p)) + (let* ((files (diredp-get-files ignore-marks-p nil nil nil nil details)) (modestr (and (stringp (car files)) (nth 8 (file-attributes (car files))))) (default (and (stringp modestr) (string-match "^.\\(...\\)\\(...\\)\\(...\\)$" modestr) @@ -5933,26 +6624,32 @@ Dired buffer and all subdirs, recursively." (dolist (file files) (set-file-modes file (or (and (diredp-string-match-p "^[0-7]+" modes) (string-to-number modes 8)) (file-modes-symbolic-to-number modes (file-modes file))))) - (diredp-do-redisplay-recursive 'MSGP))) + (diredp-do-redisplay-recursive details 'MSGP))) (unless (memq system-type '(windows-nt ms-dos)) - (defun diredp-do-chgrp-recursive (&optional ignore-marks-p) + (defun diredp-do-chgrp-recursive (&optional ignore-marks-p details) "Change the group of the marked (or next ARG) files. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-do-chxxx-recursive'." (interactive "P") - (diredp-do-chxxx-recursive "Group" "chgrp" 'chgrp ignore-marks-p))) + (diredp-do-chxxx-recursive "Group" "chgrp" 'chgrp ignore-marks-p nil details))) (unless (memq system-type '(windows-nt ms-dos)) - (defun diredp-do-chown-recursive (&optional ignore-marks-p) + (defun diredp-do-chown-recursive (&optional ignore-marks-p details) "Change the owner of the marked (or next ARG) files. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-do-chxxx-recursive'." (interactive "P") - (diredp-do-chxxx-recursive "Owner" dired-chown-program 'chown ignore-marks-p))) + (diredp-do-chxxx-recursive "Owner" dired-chown-program 'chown ignore-marks-p nil details))) ;;;###autoload -(defun diredp-do-touch-recursive (&optional ignore-marks-p) +(defun diredp-do-touch-recursive (&optional ignore-marks-p details) "Change the timestamp of marked files, including those in marked subdirs. This calls `touch'. Like `dired-do-touch', but act recursively on subdirs. The subdirs inserted are those that are marked in the @@ -5961,28 +6658,35 @@ marked. Marked subdirectories are handled recursively in the same way. With a prefix argument, ignore all marks - include all files in this -Dired buffer and all subdirs, recursively." +Dired buffer and all subdirs, recursively. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-do-chxxx-recursive'." (interactive (progn (diredp-get-confirmation-recursive) (list current-prefix-arg))) (diredp-do-chxxx-recursive "Timestamp" (if (boundp 'dired-touch-program) dired-touch-program ; Emacs 22+ "touch") 'touch ignore-marks-p - (format-time-string "%Y%m%d%H%M.%S" (current-time)))) + (format-time-string "%Y%m%d%H%M.%S" (current-time)) + details)) ;;;###autoload -(defun diredp-do-redisplay-recursive (&optional msgp) +(defun diredp-do-redisplay-recursive (&optional details msgp) "Redisplay marked file lines, including those in marked subdirs. Non-nil MSGP means show status messages. Like `dired-do-redisplay' with no args, but act recursively on -subdirs." +subdirs. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive (progn (diredp-ensure-mode) (unless (y-or-n-p "Act on all marked file lines in and UNDER this dir? ") (error "OK, canceled")) - (list t))) + (list nil t))) (when msgp (message "Redisplaying...")) (dolist (dir (cons default-directory - (diredp-get-files nil #'file-directory-p 'INCLUDE-SUBDIRS 'DONT-ASK))) + (diredp-get-files nil #'file-directory-p 'INCLUDE-SUBDIRS 'DONT-ASK nil details))) (with-current-buffer (dired-noselect dir) ;; `message' is much faster than making `dired-map-over-marks' show progress (dired-uncache (if (consp dired-directory) (car dired-directory) dired-directory)) @@ -7510,7 +8214,9 @@ Note: When you are in Dired at the root of a drive (e.g. directory (setq drive (cons (split-string (match-string 0)) drive)))) (if other-window-p (pop-to-buffer "*Windows Drives*") - (switch-to-buffer "*Windows Drives*")) + (if (fboundp 'pop-to-buffer-same-window) + (pop-to-buffer-same-window "*Windows Drives*") + (switch-to-buffer "*Windows Drives*"))) (erase-buffer) (widget-minor-mode 1) (dolist (drv (sort drive (lambda (a b) (string-lessp (car a) (car b))))) @@ -7548,6 +8254,110 @@ Directories are not included." (lambda (s1 s2) (string-lessp (upcase s1) (upcase s2))) 'string-lessp)))))) +(when (fboundp 'read-char-choice) ; Emacs 24+ + + + ;; REPLACE ORIGINAL in `dired-aux.el' + ;; + ;; `l' lists the files involved and prompts again. + ;; + (defun dired-query (sym prompt &rest args) + "Format PROMPT with ARGS, query user, and store the result in SYM. +The return value is either nil or t. + +The user can type: + `y' or `SPC' to accept once + `n' or `DEL' to skip once + `!' to accept this and subsequent queries + `l' list the files + `q' or `ESC' to decline this and subsequent queries + +If SYM is already bound to a non-nil value, this function may return +automatically without querying the user. If SYM is `!', return t; if +SYM is `q' or ESC, return nil." + (let* ((char (symbol-value sym)) + (char-choices '(?y ?\ ?n ?\177 ?! ?l ?q ?\e)) ; Use ?\ , not ?\s, for Emacs 20 byte-compiler. + (list-buf (generate-new-buffer-name "*Files*")) + (list-was-shown nil)) + (unwind-protect + (cond ((eq char ?!) t) ; Accept, and don't ask again. + ((memq char '(?q ?\e)) nil) ; Skip, and don't ask again. + (t ; No previous answer - ask now + (setq prompt (concat (apply (if (fboundp 'format-message) #'format-message #'format) + prompt + args) + (if help-form + (format " [Type ynlq! or %s] " (key-description (vector help-char))) + " [Type y, n, l, q or !] "))) + (set sym (setq char (read-char-choice prompt char-choices))) + (when (eq char ?l) ; List files and prompt again. + (diredp-list-files args nil nil nil '(5 8)) + (set sym (setq char (read-char-choice prompt char-choices)))) + (and (memq char '(?y ?\ ?!)) t))) ; Use ?\ , not ?\s, for Emacs 20. + (when (get-buffer list-buf) + (save-window-excursion + (pop-to-buffer list-buf) + (condition-case nil ; Ignore error if user already deleted. + (if (one-window-p) (delete-frame) (delete-window)) + (error nil)) + (if list-was-shown (bury-buffer list-buf) (kill-buffer list-buf))))))) + + ) + +(unless (fboundp 'read-char-choice) ; Emacs 20-23 (modified the Emacs 23 version). Needs `dired-query-alist'. + + + ;; REPLACE ORIGINAL in `dired-aux.el' + ;; + ;; 1. `l' lists the files involved and prompts again. + ;; 2. Compatible with older Emacs versions (before Emacs 24): can use `dired-query-alist'. + ;; + (defun dired-query (qs-var qs-prompt &rest qs-args) + "Query user and return nil or t. +The user can type: + `y' or `SPC' to accept once + `n' or `DEL' to skip once + `!' to accept this and subsequent queries + `l' list the files + `q' or `ESC' to decline this and subsequent queries + +Store answer in symbol VAR (which must initially be bound to nil). +Format PROMPT with ARGS. +Binding variable `help-form' will help the user who types the help key." + (let* ((char (symbol-value qs-var)) + (dired-query-alist (cons '(?l . l) dired-query-alist)) + (action (cdr (assoc char dired-query-alist)))) + (cond ((eq 'yes action) t) ; Accept, and don't ask again. + ((eq 'no action) nil) ; Skip, and don't ask again. + (t ; No lasting effects from last time we asked - ask now. + (let ((cursor-in-echo-area t) + (executing-kbd-macro executing-kbd-macro) + (qprompt (concat qs-prompt + (if help-form + (format " [Type ynl!q or %s] " + (key-description (char-to-string help-char))) + " [Type y, n, l, q or !] "))) + done result elt) + (while (not done) + (apply #'message qprompt qs-args) + (setq char (set qs-var (read-event))) + (when (eq char ?l) ; List files and prompt again. + (diredp-list-files qs-args nil nil nil '(5 8)) + (apply #'message qprompt qs-args) + (setq char (set qs-var (read-event)))) + (if (numberp char) + (cond ((and executing-kbd-macro (= char -1)) + ;; `read-event' returns -1 if we are in a keyboard macro and there are no more + ;; events in the macro. Try to get an event interactively. + (setq executing-kbd-macro nil)) + ((eq (key-binding (vector char)) 'keyboard-quit) (keyboard-quit)) + (t (setq done (setq elt (assoc char dired-query-alist))))))) + ;; Display the question with the answer. + (message "%s" (concat (apply #'format qprompt qs-args) (char-to-string char))) + (memq (cdr elt) '(t y yes))))))) + + ) + ;; REPLACE ORIGINAL in `dired-aux.el'. ;; @@ -7628,6 +8438,109 @@ Else return a singleton list of a directory name, which is as follows: (list (dired-current-directory)))) +;; REPLACE ORIGINAL in `dired-aux.el' +;; +;; 1. Added optional arg FROM, which is also listed by `l' when prompted. +;; 2. Added missing doc string. +;; +(defun dired-handle-overwrite (to &optional from) + "Save old version of file TO that is to be overwritten. +`dired-overwrite-confirmed' and `overwrite-backup-query' are fluid vars +from `dired-create-files'. + +Optional arg FROM is a file being copied or renamed to TO. It is used +only when a user hits `l' to list files when asked whether to +overwrite." + (let (backup) + (when (and dired-backup-overwrite + dired-overwrite-confirmed + (setq backup (car (find-backup-file-name to))) + (or (eq 'always dired-backup-overwrite) + (dired-query 'overwrite-backup-query "Make backup for existing file `%s'? " to from))) + (rename-file to backup 0) ; Confirm overwrite of old backup. + (dired-relist-entry backup)))) + + +(when (fboundp 'dired-copy-file-recursive) ; Emacs 22+ + + + ;; REPLACE ORIGINAL in `dired-aux.el' + ;; + ;; 1. Pass also FROM to `dired-handle-overwrite', so `l' lists it too. + ;; 2. Added missing doc string. + ;; + (defun dired-copy-file (from to ok-if-already-exists) + "Copy file FROM to location TO. +Non-nil arg OK-IF-ALREADY-EXISTS is passed to `copy-file' or + `make-symbolic-link'. +Preserves the last-modified date when copying, unless +`dired-copy-preserve-time' is nil." + (dired-handle-overwrite to from) + (dired-copy-file-recursive from to ok-if-already-exists dired-copy-preserve-time t dired-recursive-copies)) + + + ;; REPLACE ORIGINAL in `dired-aux.el' + ;; + ;; 1. Pass also FROM to `dired-handle-overwrite', so `l' lists it too. + ;; 2. Added missing doc string. + ;; + (defun dired-copy-file-recursive (from to ok-if-already-exists &optional keep-time top recursive) + "Copy file FROM to location TO, handling directories in FROM recursively. +Non-nil arg OK-IF-ALREADY-EXISTS is passed to `copy-file' or + `make-symbolic-link'. +Non-nil optional arg KEEP-TIME is passed to `copy-file' or + `copy-directory'. +Non-nil optional arg TOP means do not bother with `dired-handle-overwrite'. +Non-nil optional arg RECURSIVE means recurse on any directories in + FROM, after confirmation if RECURSIVE is not `always'." + (when (and (eq t (car (file-attributes from))) (file-in-directory-p to from)) + (error "Cannot copy `%s' into its subdirectory `%s'" from to)) + (let ((attrs (file-attributes from))) + (if (and recursive + (eq t (car attrs)) + (or (eq recursive 'always) (yes-or-no-p (format "Recursive copies of %s? " from)))) + (copy-directory from to keep-time) + (or top (dired-handle-overwrite to from)) + (condition-case err + (if (stringp (car attrs)) ; It is a symlink + (make-symbolic-link (car attrs) to ok-if-already-exists) + (copy-file from to ok-if-already-exists keep-time)) + (file-date-error + (push (dired-make-relative from) dired-create-files-failures) + (dired-log "Can't set date on %s:\n%s\n" from err)))))) + + ) + + +;; REPLACE ORIGINAL in `dired-aux.el' +;; +;; 1. Pass also FILE to `dired-handle-overwrite', so `l' lists it too. +;; 2. Added missing doc string. +;; +(defun dired-rename-file (file newname ok-if-already-exists) + "Rename FILE to NEWNAME. +Non-nil arg OK-IF-ALREADY-EXISTS is passed to `rename-file'." + (dired-handle-overwrite newname file) + (rename-file file newname ok-if-already-exists) ; Error is caught in `-create-files'. + ;; Silently rename the visited file of any buffer visiting this file. + (and (get-file-buffer file) (with-current-buffer (get-file-buffer file) (set-visited-file-name newname nil t))) + (dired-remove-file file) + ;; See if it's an inserted subdir, and rename that, too. + (dired-rename-subdir file newname)) + + +;; REPLACE ORIGINAL in `dired-aux.el' +;; +;; Pass also FILE to `dired-handle-overwrite', so `l' lists it too. +;; +(defun dired-hardlink (file newname &optional ok-if-already-exists) + "Give FILE additional name NEWNAME. +Non-nil arg OK-IF-ALREADY-EXISTS is passed to `add-name-to-file'." + (dired-handle-overwrite newname file) + (add-name-to-file file newname ok-if-already-exists) ; Error is caught in -create-files'. + (dired-relist-file file)) ; Update the link count. + + ;; REPLACE ORIGINAL in `dired.el'. ;; ;; No-op: does nothing now. @@ -7657,12 +8570,12 @@ Else return a singleton list of a directory name, which is as follows: ;; REPLACE ORIGINAL in `dired-aux.el'. ;; -;; If NEW-DIR is not a descendent of a directory in the buffer, put it at eob. +;; If NEW-DIR is not a descendant of a directory in the buffer, put it at eob. ;; (defun dired-insert-subdir-newpos (new-dir) "Move to the proper position for inserting NEW-DIR, and return it. Respect the order within each directory tree. But if NEW-DIR is not a -descendent of any directory in the buffer, then put it at the end." +descendant of any directory in the buffer, then put it at the end." (let ((alist dired-subdir-alist) elt dir new-pos) (while alist @@ -8640,6 +9553,8 @@ FUNCTION should not manipulate the files. It should just read input (default-frame-alist (cons '(menu-bar-lines . 0) default-frame-alist))) (dired-pop-to-buffer buffer-or-name) + ;; Work around Emacs 22 bug in `dired-pop-to-buffer', which can exit with Dired buffer current. + (set-buffer buffer-or-name) (goto-char (point-min))) (setq result (apply function args))) (save-excursion @@ -9153,12 +10068,15 @@ You need library `bookmark+.el' for this command." ;;;###autoload (defalias 'diredp-show-metadata-for-marked 'diredp-describe-marked-autofiles) ;;;###autoload -(defun diredp-describe-marked-autofiles (&optional internal-form-p interactivep) +(defun diredp-describe-marked-autofiles (&optional internal-form-p interactivep details) "Show metadata for the marked files. If no file is marked, describe ALL autofiles in this directory. With a prefix argument, show the internal (Lisp) form of the metadata. When invoked interactively, raise an error if no files are marked. -You need library `bookmark+.el' for this command." +You need library `bookmark+.el' for this command. + +When called from Lisp, optional arg DETAILS is passed to +`diredp-get-files'." (interactive "P\np") (diredp-ensure-bookmark+) (let ((help-xref-following nil)) @@ -9173,7 +10091,7 @@ You need library `bookmark+.el' for this command." (let ((marked (dired-get-marked-files nil nil nil 'DISTINGUISH-ONE-MARKED interactivep))) (unless (cdr marked) (message "Describing ALL autofiles here (none are marked)...") - (setq marked (diredp-get-files 'IGNORE-MARKS-P))) + (setq marked (diredp-get-files 'IGNORE-MARKS-P nil nil nil nil details))) (if (eq t (car marked)) (diredp-describe-autofile internal-form-p) (dolist (bmk (delq nil (mapcar #'bmkp-get-autofile-bookmark marked))) @@ -9293,11 +10211,11 @@ refer at all to the underlying file system. Contrast this with (search-forward-regexp dired-re-inode-size nil t) ;; XXX Might be a size not followed by a unit prefix. Could set `blks' to `inode' if it were otherwise ;; nil, with similar reasoning as for setting `gid' to `uid', but it would be even more whimsical. - (setq inode (and (match-string 1) (string-to-number (match-string 1)))) - (setq blks (and (match-string 2) (if (fboundp 'dired-x--string-to-number) + (setq inode (and (match-string 1) (string-to-number (match-string 1))) + blks (and (match-string 2) (if (fboundp 'dired-x--string-to-number) (dired-x--string-to-number (match-string 2)) ; Emacs 25+ - (string-to-number (match-string 2))))) - (setq mode (buffer-substring (point) (+ mode-len (point)))) + (string-to-number (match-string 2)))) + mode (buffer-substring (point) (+ mode-len (point)))) (forward-char mode-len) (unless (diredp-looking-at-p " ") (forward-char 1)) ; Skip any extended attributes marker ("." or "+"). (setq nlink (read (current-buffer))) @@ -9619,7 +10537,7 @@ With non-nil prefix arg, mark them instead." ;; Allow `.' and `..', by using non-nil second arg to `dired-get-filename'. ;; (when (< emacs-major-version 21) - (defun dired-find-file () ; Bound to `e', `RET' + (defun dired-find-file () ; Bound to `RET' "In Dired, visit the file or directory named on this line." (interactive) (let* ((dgf-result (or (dired-get-filename nil t) (error "No file on this line"))) @@ -10452,7 +11370,8 @@ Here and below (in marked subdirs) \\[diredp-mark-directories-recursive]\t\t- Mark directories \\[diredp-mark-executables-recursive]\t\t- Mark executables \\[diredp-mark-symlinks-recursive]\t\t- Mark symbolic links - \\[diredp-mark-files-regexp-recursive]\t\t- Mark regexp matches + \\[diredp-mark-files-containing-regexp-recursive]\t\t- Mark content regexp matches + \\[diredp-mark-files-regexp-recursive]\t\t- Mark filename regexp matches " (and (featurep 'bookmark+) " \\[diredp-mark-autofiles-recursive]\t\t- Mark autofiles @@ -10615,6 +11534,78 @@ Dired+ bug: \ File `dired+.el' has a header `Update #' that you can use to identify it.\ %%0A%%0AEmacs version: %s.") (emacs-version)))) + +(defun diredp-visit-ignore-regexp () ; Taken from `image-file-name-regexp'. + "Return a regular expression matching file names to skip. +This is used by `dired-visit-(next|previous)'." + (let ((exts-regexp (and diredp-visit-ignore-extensions + (concat "\\." (regexp-opt (nconc (mapcar #'upcase diredp-visit-ignore-extensions) + diredp-visit-ignore-extensions) + t) + "\\'")))) + (if diredp-visit-ignore-regexps + (mapconcat #'identity (if exts-regexp + (cons exts-regexp diredp-visit-ignore-regexps) + diredp-visit-ignore-regexps) + "\\|") + exts-regexp))) + +;;;###autoload +(defun diredp-visit-next-file (&optional arg) ; Bound to `C-down' + "Move down a line and visit its file in another window. +With numeric prefix arg N, move down N-1 lines first. + +After moving N lines, skip any lines with file names that match either +`diredp-visit-ignore-extensions' or `diredp-visit-ignore-regexps'. + +Kill the last buffer visited by a `dired-visit-*' command." + (interactive "p") + (dired-next-line arg) + (while (diredp-string-match-p (diredp-visit-ignore-regexp) (dired-get-file-for-visit)) + (dired-next-line 1)) + (diredp-visit-this-file)) + +;;;###autoload +(defun diredp-visit-previous-file (&optional arg) ; Bound to `C-up' + "Move up a line and visit its file in another window. +With numeric prefix arg N, move up N-1 lines first. + +After moving N lines, skip any lines with file names that match either +`diredp-visit-ignore-extensions' or `diredp-visit-ignore-regexps'. + +Kill the last buffer visited by a `dired-visit-*' command." + (interactive "p") + (dired-previous-line arg) + (while (diredp-string-match-p (diredp-visit-ignore-regexp) (dired-get-file-for-visit)) + (dired-previous-line 1)) + (diredp-visit-this-file)) + +;;;###autoload +(defun diredp-visit-this-file () ; Bound to `e' (replaces `dired-find-file' binding) + "View the file on this line in another window in the same frame. +If it was not already shown there then kill the previous buffer +visited by a `dired-visit-*' command. + +If it was already shown there, and if it and Dired are the only +windows there, then delete its window (toggle : show/hide the file)." + (interactive) + (let ((file (dired-get-file-for-visit)) + (obuf (current-buffer)) + (shown nil) + fwin) + (unless (or (and (fboundp 'window-parent) (window-parent)) + (not (one-window-p 'NOMINI))) + (split-window)) + (save-selected-window + (other-window 1) + (setq fwin (selected-window)) + (unless (or (setq shown (or (equal (current-buffer) (get-file-buffer file)) + (memq (current-buffer) (dired-buffers-for-dir file)))) + (equal obuf (current-buffer))) + (kill-buffer (current-buffer)))) + (if shown + (when (= 2 (count-windows 'NOMINI)) (delete-window fwin)) + (set-window-buffer fwin (find-file-noselect file))))) ;;; Key Bindings. @@ -11577,8 +12568,11 @@ If no one is selected, symmetric encryption will be performed. " (define-key diredp-menu-bar-regexp-menu [mark-recursive] (cons "Here and Below" diredp-regexp-recursive-menu)) (define-key diredp-regexp-recursive-menu [diredp-mark-files-regexp-recursive] - '(menu-item "Mark..." diredp-mark-files-regexp-recursive - :help "Mark all files matching a regexp, including those in marked subdirs")) + '(menu-item "Mark Named..." diredp-mark-files-regexp-recursive + :help "Mark all file names matching a regexp, including those in marked subdirs")) +(define-key diredp-regexp-recursive-menu [diredp-mark-files-containing-regexp-recursive] + '(menu-item "Mark Containing..." diredp-mark-files-containing-regexp-recursive + :help "Mark all files with content matching a regexp, including in marked subdirs")) ;; We don't use `define-obsolete-variable-alias' so that byte-compilation in older Emacs ;; works for newer Emacs too. @@ -11739,7 +12733,7 @@ If no one is selected, symmetric encryption will be performed. " (when (fboundp 'dired-mark-sexp) (define-key diredp-marks-mark-menu [marks-mark-sexp] ; In `dired-x.el'. '(menu-item "Mark If..." dired-mark-sexp - :help "Mark files for which specified condition is true"))) + :help "Mark files that satisfy specified condition"))) (define-key diredp-marks-mark-menu [marks-image-dired-mark-tagged-files] '(menu-item "Mark Image Files Tagged..." image-dired-mark-tagged-files :enable (fboundp 'image-dired-mark-tagged-files) @@ -11804,9 +12798,15 @@ If no one is selected, symmetric encryption will be performed. " '(menu-item "Unmark All..." diredp-unmark-all-marks-recursive :help "Remove ALL marks everywhere, including in marked subdirs")) (define-key diredp-marks-recursive-menu [separator-1] '("--"))) ; ------------ +(define-key diredp-marks-recursive-menu [diredp-mark-sexp-recursive] + '(menu-item "If..." diredp-mark-sexp-recursive + :help "Mark files satisfying specified condition, including those in marked subdirs")) +(define-key diredp-marks-recursive-menu [diredp-mark-files-containing-regexp-recursive] + '(menu-item "Containing Regexp..." diredp-mark-files-containing-regexp-recursive + :help "Mark all files with content matching a regexp, including in marked subdirs")) (define-key diredp-marks-recursive-menu [diredp-mark-files-regexp-recursive] - '(menu-item "Regexp..." diredp-mark-files-regexp-recursive - :help "Mark all files matching a regexp, including those in marked subdirs")) + '(menu-item "Named Regexp..." diredp-mark-files-regexp-recursive + :help "Mark all file names matching a regexp, including those in marked subdirs")) (define-key diredp-marks-recursive-menu [diredp-mark-extension-recursive] '(menu-item "Extension..." diredp-mark-extension-recursive :help "Mark all files with a given extension, including those in marked subdirs")) @@ -12064,6 +13064,9 @@ If no one is selected, symmetric encryption will be performed. " (when diredp-bind-problematic-terminal-keys (define-key dired-mode-map [(control meta shift ?b)] ; `C-M-B' (aka `C-M-S-b') 'diredp-do-bookmark-in-bookmark-file)) +(define-key dired-mode-map "e" 'diredp-visit-this-file) ; `e' (was `dired-find-file') +(define-key dired-mode-map [C-down] 'diredp-visit-next-file) ; `C-down' (was `forward-paragraph') +(define-key dired-mode-map [C-up] 'diredp-visit-previous-file) ; `C-up' (was `backward-paragraph') (define-key dired-mode-map "\C-\M-G" 'diredp-do-grep) ; `C-M-G' (when (fboundp 'mkhtml-dired-files) ; In `mkhtml.el'. (define-key dired-mode-map "\M-h" 'mkhtml-dired-files)) ; `M-h' @@ -12177,6 +13180,7 @@ If no one is selected, symmetric encryption will be performed. " (define-key diredp-recursive-map "**" 'diredp-mark-executables-recursive) ; `* *' (define-key diredp-recursive-map "*/" 'diredp-mark-directories-recursive) ; `* /' (define-key diredp-recursive-map "*." 'diredp-mark-extension-recursive) ; `* .' +(define-key diredp-recursive-map "*(" 'diredp-mark-sexp-recursive) ; `* (' (define-key diredp-recursive-map "*B" 'diredp-mark-autofiles-recursive) ; `* B' (when (fboundp 'char-displayable-p) ; Emacs 22+ (define-key diredp-recursive-map "*c" 'diredp-change-marks-recursive)) ; `* c' @@ -12187,6 +13191,7 @@ If no one is selected, symmetric encryption will be performed. " (define-key diredp-recursive-map ":s" 'diredp-do-sign-recursive) ; `: s' (define-key diredp-recursive-map ":v" 'diredp-do-verify-recursive)) ; `: v' (define-key diredp-recursive-map "%c" 'diredp-capitalize-recursive) ; `% c' +(define-key diredp-recursive-map "%g" 'diredp-mark-files-containing-regexp-recursive) ; `% g' (define-key diredp-recursive-map "%l" 'diredp-downcase-recursive) ; `% l' (define-key diredp-recursive-map "%m" 'diredp-mark-files-regexp-recursive) ; `% m' (define-key diredp-recursive-map "%u" 'diredp-upcase-recursive) ; `% u' @@ -12233,6 +13238,7 @@ If no one is selected, symmetric encryption will be performed. " (define-key diredp-recursive-map "\C-tt" 'diredp-image-dired-tag-files-recursive) ; `C-t t' (when (fboundp 'char-displayable-p) ; Emacs 22+ (define-key diredp-recursive-map "U" 'diredp-unmark-all-marks-recursive)) ; `U' +(define-key diredp-recursive-map "\M-(" 'diredp-mark-sexp-recursive) ; `M-(' (define-key diredp-recursive-map "\M-w" 'diredp-copy-filename-as-kill-recursive) ; `M-w' (define-key diredp-recursive-map "Y" 'diredp-do-relsymlink-recursive) ; `Y'