aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTino Calancha2017-07-02 22:09:02 +0900
committerTino Calancha2017-07-02 22:09:02 +0900
commita8b71b3dc53883a2dcb3339bf4c7e1232c42d276 (patch)
treefd9972fc07854be2f6e26f10e4d51b94ffc5381e
parent80e200c0a08805771d1c709546d79088be188021 (diff)
downloademacs-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.texi26
-rw-r--r--etc/NEWS4
-rw-r--r--lisp/dired-aux.el43
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
877Otherwise, if the command string contains @samp{?} surrounded by 877Otherwise, if the command string contains @samp{?} surrounded by
878whitespace, Emacs runs the shell command once @emph{for each file}, 878whitespace or @samp{`?`}, Emacs runs the shell command once
879substituting the current file name for @samp{?} each time. You can 879@emph{for each file}, substituting the current file name for @samp{?}
880use @samp{?} more than once in the command; the same file name 880and @samp{`?`} each time. You can use both @samp{?} or @samp{`?`} more
881replaces each occurrence. 881than once in the command; the same file name replaces each occurrence.
882If you mix them with @samp{*} the command signals an error.
882 883
883@item 884@item
884If the command string contains neither @samp{*} nor @samp{?}, Emacs 885If the command string contains neither @samp{*} nor @samp{?} nor @samp{`?`},
885runs the shell command once for each file, adding the file name at the 886Emacs runs the shell command once for each file, adding the file name at the
886end. For example, @kbd{! uudecode @key{RET}} runs @code{uudecode} on 887end. For example, @kbd{! uudecode @key{RET}} runs @code{uudecode} on
887each file. 888each 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
891explicit shell loop. For example, here is how to uuencode each file, 892prefer to use an explicit shell loop. For example, here is how to uuencode
892making the output file name by appending @samp{.uu} to the input file 893each file, making the output file name by appending @samp{.uu} to the input
893name: 894file name:
894 895
895@example 896@example
896for file in * ; do uuencode "$file" "$file" >"$file".uu; done 897for file in * ; do uuencode "$file" "$file" >"$file".uu; done
897@end example 898@end example
898 899
900The same example with @samp{`?`} notation:
901@example
902uuencode ? ? > `?`.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
900buffer to show new or modified files, because they don't know what 906buffer to show new or modified files, because they don't know what
901files will be changed. Use the @kbd{g} command to update the Dired 907files will be changed. Use the @kbd{g} command to update the Dired
diff --git a/etc/NEWS b/etc/NEWS
index 0ba48f38aed..b9a492cb5ce 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -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
487You can now use '`?`' in 'dired-do-shell-command'; as ' ? ', it gets replaced
488by 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.
59Isolated means that STRING is surrounded by spaces or at the beginning/end
60of a string followed/prefixed with an space.
61The regexp capture the preceding blank, STRING and the following blank as
62the 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 `\\=`?\\=`'.
67MATCH should be the strings \"?\", `\\=`?\\=`', \"*\" or nil. The latter
68means STRING contains either \"?\" or `\\=`?\\=`' or \"*\".
69If optional arg KEEP is non-nil, then preserve the match data. Otherwise,
70this function changes it and saves MATCH as the second match group.
71
72Isolated means that MATCH is surrounded by spaces or at the beginning/end
73of STRING followed/prefixed with an space. A match to `\\=`?\\=`',
74isolated 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
658COMMAND just once with the entire file list substituted there. 685COMMAND just once with the entire file list substituted there.
659 686
660If there is no `*', but there is a `?' in COMMAND, surrounded by 687If there is no `*', but there is a `?' in COMMAND, surrounded by
661whitespace, this runs COMMAND on each file individually with the 688whitespace, or a `\\=`?\\=`' this runs COMMAND on each file
662file name substituted for `?'. 689individually with the file name substituted for `?' or `\\=`?\\=`'.
663 690
664Otherwise, this runs COMMAND on each file individually with the 691Otherwise, this runs COMMAND on each file individually with the
665file name added at the end of COMMAND (separated by a space). 692file 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
668significance for `dired-do-shell-command', and are passed through 695significance for `dired-do-shell-command', and are passed through
669normally to the shell, but you must confirm first. 696normally 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)))))