diff options
| author | Tino Calancha | 2017-07-02 22:09:02 +0900 |
|---|---|---|
| committer | Tino Calancha | 2017-07-02 22:09:02 +0900 |
| commit | a8b71b3dc53883a2dcb3339bf4c7e1232c42d276 (patch) | |
| tree | fd9972fc07854be2f6e26f10e4d51b94ffc5381e | |
| parent | 80e200c0a08805771d1c709546d79088be188021 (diff) | |
| download | emacs-a8b71b3dc53883a2dcb3339bf4c7e1232c42d276.tar.gz emacs-a8b71b3dc53883a2dcb3339bf4c7e1232c42d276.zip | |
Extend dired-do-shell-command substitutions
Substitute "`?`" inside command with the current file name.
See details in:
https://lists.gnu.org/archive/html/emacs-devel/2017-06/msg00618.html
* lisp/dired-aux.el (dired-quark-subst-regexp, dired-star-subst-regexp):
Mark as obsolete.
(dired-isolated-string-re): New defun.
(dired--star-or-qmark-p): New predicate.
(dired-do-shell-command): Use dired--star-or-qmark-p. Substitute "`?`"
with the current file name.
* doc/emacs/dired.texi (Shell Commands in Dired): Update manual.
; * etc/NEWS: Mention it.
| -rw-r--r-- | doc/emacs/dired.texi | 26 | ||||
| -rw-r--r-- | etc/NEWS | 4 | ||||
| -rw-r--r-- | lisp/dired-aux.el | 43 |
3 files changed, 54 insertions, 19 deletions
diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi index 22b0fcd4676..28cb51d88bb 100644 --- a/doc/emacs/dired.texi +++ b/doc/emacs/dired.texi | |||
| @@ -875,27 +875,33 @@ treat it specially. | |||
| 875 | 875 | ||
| 876 | @item | 876 | @item |
| 877 | Otherwise, if the command string contains @samp{?} surrounded by | 877 | Otherwise, if the command string contains @samp{?} surrounded by |
| 878 | whitespace, Emacs runs the shell command once @emph{for each file}, | 878 | whitespace or @samp{`?`}, Emacs runs the shell command once |
| 879 | substituting the current file name for @samp{?} each time. You can | 879 | @emph{for each file}, substituting the current file name for @samp{?} |
| 880 | use @samp{?} more than once in the command; the same file name | 880 | and @samp{`?`} each time. You can use both @samp{?} or @samp{`?`} more |
| 881 | replaces each occurrence. | 881 | than once in the command; the same file name replaces each occurrence. |
| 882 | If you mix them with @samp{*} the command signals an error. | ||
| 882 | 883 | ||
| 883 | @item | 884 | @item |
| 884 | If the command string contains neither @samp{*} nor @samp{?}, Emacs | 885 | If the command string contains neither @samp{*} nor @samp{?} nor @samp{`?`}, |
| 885 | runs the shell command once for each file, adding the file name at the | 886 | Emacs runs the shell command once for each file, adding the file name at the |
| 886 | end. For example, @kbd{! uudecode @key{RET}} runs @code{uudecode} on | 887 | end. For example, @kbd{! uudecode @key{RET}} runs @code{uudecode} on |
| 887 | each file. | 888 | each file. |
| 888 | @end itemize | 889 | @end itemize |
| 889 | 890 | ||
| 890 | To iterate over the file names in a more complicated fashion, use an | 891 | To iterate over the file names in a more complicated fashion, you might |
| 891 | explicit shell loop. For example, here is how to uuencode each file, | 892 | prefer to use an explicit shell loop. For example, here is how to uuencode |
| 892 | making the output file name by appending @samp{.uu} to the input file | 893 | each file, making the output file name by appending @samp{.uu} to the input |
| 893 | name: | 894 | file name: |
| 894 | 895 | ||
| 895 | @example | 896 | @example |
| 896 | for file in * ; do uuencode "$file" "$file" >"$file".uu; done | 897 | for file in * ; do uuencode "$file" "$file" >"$file".uu; done |
| 897 | @end example | 898 | @end example |
| 898 | 899 | ||
| 900 | The same example with @samp{`?`} notation: | ||
| 901 | @example | ||
| 902 | uuencode ? ? > `?`.uu | ||
| 903 | @end example | ||
| 904 | |||
| 899 | The @kbd{!} and @kbd{&} commands do not attempt to update the Dired | 905 | The @kbd{!} and @kbd{&} commands do not attempt to update the Dired |
| 900 | buffer to show new or modified files, because they don't know what | 906 | buffer to show new or modified files, because they don't know what |
| 901 | files will be changed. Use the @kbd{g} command to update the Dired | 907 | files will be changed. Use the @kbd{g} command to update the Dired |
| @@ -483,6 +483,10 @@ properties as intact as possible. | |||
| 483 | 483 | ||
| 484 | * Changes in Specialized Modes and Packages in Emacs 26.1 | 484 | * Changes in Specialized Modes and Packages in Emacs 26.1 |
| 485 | 485 | ||
| 486 | ** Dired | ||
| 487 | You can now use '`?`' in 'dired-do-shell-command'; as ' ? ', it gets replaced | ||
| 488 | by the current file name. | ||
| 489 | |||
| 486 | *** html2text is now marked obsolete. | 490 | *** html2text is now marked obsolete. |
| 487 | 491 | ||
| 488 | *** smerge-refine-regions can refine regions in separate buffers | 492 | *** smerge-refine-regions can refine regions in separate buffers |
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index 121bebeb651..a57e5db17b7 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el | |||
| @@ -51,6 +51,33 @@ into this list; they also should call `dired-log' to log the errors.") | |||
| 51 | 51 | ||
| 52 | (defconst dired-star-subst-regexp "\\(^\\|[ \t]\\)\\*\\([ \t]\\|$\\)") | 52 | (defconst dired-star-subst-regexp "\\(^\\|[ \t]\\)\\*\\([ \t]\\|$\\)") |
| 53 | (defconst dired-quark-subst-regexp "\\(^\\|[ \t]\\)\\?\\([ \t]\\|$\\)") | 53 | (defconst dired-quark-subst-regexp "\\(^\\|[ \t]\\)\\?\\([ \t]\\|$\\)") |
| 54 | (make-obsolete-variable 'dired-star-subst-regexp nil "26.1") | ||
| 55 | (make-obsolete-variable 'dired-quark-subst-regexp nil "26.1") | ||
| 56 | |||
| 57 | (defun dired-isolated-string-re (string) | ||
| 58 | "Return a regexp to match STRING isolated. | ||
| 59 | Isolated means that STRING is surrounded by spaces or at the beginning/end | ||
| 60 | of a string followed/prefixed with an space. | ||
| 61 | The regexp capture the preceding blank, STRING and the following blank as | ||
| 62 | the groups 1, 2 and 3 respectively." | ||
| 63 | (format "\\(\\`\\|[ \t]\\)\\(%s\\)\\([ \t]\\|\\'\\)" string)) | ||
| 64 | |||
| 65 | (defun dired--star-or-qmark-p (string match &optional keep) | ||
| 66 | "Return non-nil if STRING contains isolated MATCH or `\\=`?\\=`'. | ||
| 67 | MATCH should be the strings \"?\", `\\=`?\\=`', \"*\" or nil. The latter | ||
| 68 | means STRING contains either \"?\" or `\\=`?\\=`' or \"*\". | ||
| 69 | If optional arg KEEP is non-nil, then preserve the match data. Otherwise, | ||
| 70 | this function changes it and saves MATCH as the second match group. | ||
| 71 | |||
| 72 | Isolated means that MATCH is surrounded by spaces or at the beginning/end | ||
| 73 | of STRING followed/prefixed with an space. A match to `\\=`?\\=`', | ||
| 74 | isolated or not, is also valid." | ||
| 75 | (let ((regexps (list (dired-isolated-string-re (if match (regexp-quote match) "[*?]"))))) | ||
| 76 | (when (or (null match) (equal match "?")) | ||
| 77 | (setq regexps (append (list "\\(\\)\\(`\\?`\\)\\(\\)") regexps))) | ||
| 78 | (cl-some (lambda (x) | ||
| 79 | (funcall (if keep #'string-match-p #'string-match) x string)) | ||
| 80 | regexps))) | ||
| 54 | 81 | ||
| 55 | ;;;###autoload | 82 | ;;;###autoload |
| 56 | (defun dired-diff (file &optional switches) | 83 | (defun dired-diff (file &optional switches) |
| @@ -658,13 +685,13 @@ If there is a `*' in COMMAND, surrounded by whitespace, this runs | |||
| 658 | COMMAND just once with the entire file list substituted there. | 685 | COMMAND just once with the entire file list substituted there. |
| 659 | 686 | ||
| 660 | If there is no `*', but there is a `?' in COMMAND, surrounded by | 687 | If there is no `*', but there is a `?' in COMMAND, surrounded by |
| 661 | whitespace, this runs COMMAND on each file individually with the | 688 | whitespace, or a `\\=`?\\=`' this runs COMMAND on each file |
| 662 | file name substituted for `?'. | 689 | individually with the file name substituted for `?' or `\\=`?\\=`'. |
| 663 | 690 | ||
| 664 | Otherwise, this runs COMMAND on each file individually with the | 691 | Otherwise, this runs COMMAND on each file individually with the |
| 665 | file name added at the end of COMMAND (separated by a space). | 692 | file name added at the end of COMMAND (separated by a space). |
| 666 | 693 | ||
| 667 | `*' and `?' when not surrounded by whitespace have no special | 694 | `*' and `?' when not surrounded by whitespace nor `\\=`' have no special |
| 668 | significance for `dired-do-shell-command', and are passed through | 695 | significance for `dired-do-shell-command', and are passed through |
| 669 | normally to the shell, but you must confirm first. | 696 | normally to the shell, but you must confirm first. |
| 670 | 697 | ||
| @@ -704,8 +731,8 @@ can be produced by `dired-get-marked-files', for example." | |||
| 704 | (dired-read-shell-command "! on %s: " current-prefix-arg files) | 731 | (dired-read-shell-command "! on %s: " current-prefix-arg files) |
| 705 | current-prefix-arg | 732 | current-prefix-arg |
| 706 | files))) | 733 | files))) |
| 707 | (let* ((on-each (not (string-match-p dired-star-subst-regexp command))) | 734 | (let* ((on-each (not (dired--star-or-qmark-p command "*" 'keep))) |
| 708 | (no-subst (not (string-match-p dired-quark-subst-regexp command))) | 735 | (no-subst (not (dired--star-or-qmark-p command "?" 'keep))) |
| 709 | (star (string-match-p "\\*" command)) | 736 | (star (string-match-p "\\*" command)) |
| 710 | (qmark (string-match-p "\\?" command)) | 737 | (qmark (string-match-p "\\?" command)) |
| 711 | ;; Get confirmation for wildcards that may have been meant | 738 | ;; Get confirmation for wildcards that may have been meant |
| @@ -768,12 +795,10 @@ can be produced by `dired-get-marked-files', for example." | |||
| 768 | ";" | 795 | ";" |
| 769 | "&")) | 796 | "&")) |
| 770 | (stuff-it | 797 | (stuff-it |
| 771 | (if (or (string-match-p dired-star-subst-regexp command) | 798 | (if (dired--star-or-qmark-p command nil 'keep) |
| 772 | (string-match-p dired-quark-subst-regexp command)) | ||
| 773 | (lambda (x) | 799 | (lambda (x) |
| 774 | (let ((retval (concat cmd-prefix command))) | 800 | (let ((retval (concat cmd-prefix command))) |
| 775 | (while (string-match | 801 | (while (dired--star-or-qmark-p retval nil) |
| 776 | "\\(^\\|[ \t]\\)\\([*?]\\)\\([ \t]\\|$\\)" retval) | ||
| 777 | (setq retval (replace-match x t t retval 2))) | 802 | (setq retval (replace-match x t t retval 2))) |
| 778 | retval)) | 803 | retval)) |
| 779 | (lambda (x) (concat cmd-prefix command dired-mark-separator x))))) | 804 | (lambda (x) (concat cmd-prefix command dired-mark-separator x))))) |