From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Tino Calancha Newsgroups: gmane.emacs.devel Subject: 26.0.50; Extend dired-do-shell-command substitutions Date: Tue, 27 Jun 2017 00:38:00 +0900 Message-ID: <87r2y6sqsn.fsf@calancha-pc> NNTP-Posting-Host: blaine.gmane.org X-Trace: blaine.gmane.org 1498491504 4385 195.159.176.226 (26 Jun 2017 15:38:24 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Mon, 26 Jun 2017 15:38:24 +0000 (UTC) Cc: tino.calancha@gmail.com To: Emacs developers Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Jun 26 17:38:19 2017 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dPW5g-0000fd-EP for ged-emacs-devel@m.gmane.org; Mon, 26 Jun 2017 17:38:16 +0200 Original-Received: from localhost ([::1]:47256 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPW5k-0001W4-73 for ged-emacs-devel@m.gmane.org; Mon, 26 Jun 2017 11:38:20 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:35995) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dPW5d-0001UW-N1 for emacs-devel@gnu.org; Mon, 26 Jun 2017 11:38:15 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dPW5a-0006aR-G2 for emacs-devel@gnu.org; Mon, 26 Jun 2017 11:38:13 -0400 Original-Received: from mail-pg0-x244.google.com ([2607:f8b0:400e:c05::244]:34359) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dPW5a-0006a8-7l for emacs-devel@gnu.org; Mon, 26 Jun 2017 11:38:10 -0400 Original-Received: by mail-pg0-x244.google.com with SMTP id j186so569339pge.1 for ; Mon, 26 Jun 2017 08:38:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:message-id:from:to:cc:subject; bh=En8zT4lhwltiX92GKcXBSQoCOCGcH5OZjGj9othm0Is=; b=vBqWnVjNUtQFQYCSxzDTYKe0vx69IZyssC+oWrC0GDe16SfvsIZyc+keluBWzjrALH yhZWRbcI4wYdHP1Cz1SfKf/ABqvtR4zvhMrnCoY2RB1Vw71yoa3W4i/B9c8X/eTva6Z+ XWEERervsAlt0igPkAs1+4Nc5cMm9PVlL8OhdFX3bKWpJxOJHXfwBMCq2+QE8qE7HyK8 FEKlHz0IBBy1li33B0NSdPYojiOO0YNYj3BG/YJucHU6QffQ3fZXw9AI58aUuaj5ksei qmwESeRAXnzQJCEdA1rZ6ADvyOKaAQXZSImI9s0ozg9VOUDzmfZFqfVrgS6hlyKPiz2G v3Zw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:from:to:cc:subject; bh=En8zT4lhwltiX92GKcXBSQoCOCGcH5OZjGj9othm0Is=; b=gStXF9oiSLE30M9bG3ydOeqVdfTPw5ltmIg3G4/dVlDCH+z3ko/vnYfu6rD3ucbPhc rx4U3RyA67GJSGUFBVA2BZ7CcpJq6xA/C39fkr74s8qXpC6n+8xPks50fW2x/3taUA6F ozalz0pHoLYoLwD1loAc6RThBH/SaM1kguiTNtTJNwas4evQR4j1otAfv7vcrVAIX8i7 cYivKM3SE0vsghSAbUr1gKBRihFenu1OPyfACqjjCxphlZY9jjdgqwqdS2lYoHdAhBRN k5ilZLU8n0+SFTL9ygahLbbhlNuAUZwaKjltMtSqLDZX4rkANgxf8P0pHT6ENZjsSCJe jpmQ== X-Gm-Message-State: AKS2vOzNzE8NeZsZWRZRNfmzh6mkWuZVBjTymaNyEqlhZfaX78A119yJ 8oTfLbVNOZp2woQU X-Received: by 10.99.167.79 with SMTP id w15mr742156pgo.228.1498491489124; Mon, 26 Jun 2017 08:38:09 -0700 (PDT) Original-Received: from calancha-pc (222.139.137.133.dy.bbexcite.jp. [133.137.139.222]) by smtp.gmail.com with ESMTPSA id j27sm508960pgn.63.2017.06.26.08.38.07 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 26 Jun 2017 08:38:08 -0700 (PDT) X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::244 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:215998 Archived-At: I find convenient to extend the wildcards with one not requiring whitespaces. For example, *) Assuming "`?`" is that new wildcard, *) and there is a file "foo" at point. Then, ! cp ? `?`-new RET g ;; Must copy "foo" into "foo-new". How do you think? Tino --8<-----------------------------cut here---------------start------------->8--- commit cd9877d16edec71e7ea9b1eedd4194d67c1b092e Author: Tino Calancha Date: Tue Jun 27 00:18:45 2017 +0900 Extend dired-do-shell-command substitutions Substitute "`?`" inside command with the current file name. * lisp/dired-aux.el (dired-quark-subst-regexp, dired-star-subst-regexp): Delete them. (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. diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi index 22b0fcd467..28cb51d88b 100644 --- a/doc/emacs/dired.texi +++ b/doc/emacs/dired.texi @@ -875,27 +875,33 @@ Shell Commands in Dired @item Otherwise, if the command string contains @samp{?} surrounded by -whitespace, Emacs runs the shell command once @emph{for each file}, -substituting the current file name for @samp{?} each time. You can -use @samp{?} more than once in the command; the same file name -replaces each occurrence. +whitespace or @samp{`?`}, Emacs runs the shell command once +@emph{for each file}, substituting the current file name for @samp{?} +and @samp{`?`} each time. You can use both @samp{?} or @samp{`?`} more +than once in the command; the same file name replaces each occurrence. +If you mix them with @samp{*} the command signals an error. @item -If the command string contains neither @samp{*} nor @samp{?}, Emacs -runs the shell command once for each file, adding the file name at the +If the command string contains neither @samp{*} nor @samp{?} nor @samp{`?`}, +Emacs runs the shell command once for each file, adding the file name at the end. For example, @kbd{! uudecode @key{RET}} runs @code{uudecode} on each file. @end itemize - To iterate over the file names in a more complicated fashion, use an -explicit shell loop. For example, here is how to uuencode each file, -making the output file name by appending @samp{.uu} to the input file -name: + To iterate over the file names in a more complicated fashion, you might +prefer to use an explicit shell loop. For example, here is how to uuencode +each file, making the output file name by appending @samp{.uu} to the input +file name: @example for file in * ; do uuencode "$file" "$file" >"$file".uu; done @end example +The same example with @samp{`?`} notation: +@example +uuencode ? ? > `?`.uu +@end example + The @kbd{!} and @kbd{&} commands do not attempt to update the Dired buffer to show new or modified files, because they don't know what files will be changed. Use the @kbd{g} command to update the Dired diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index 121bebeb65..1265fe3501 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -49,8 +49,30 @@ dired-create-files-failures ;;;###begin dired-cmd.el ;; Diffing and compressing -(defconst dired-star-subst-regexp "\\(^\\|[ \t]\\)\\*\\([ \t]\\|$\\)") -(defconst dired-quark-subst-regexp "\\(^\\|[ \t]\\)\\?\\([ \t]\\|$\\)") +(defun dired-isolated-string-re (string) + "Return a regexp to match STRING isolated. +Isolated means that STRING is surrounded by spaces or at the beginning/end +of a string followed/prefixed with an space. +The regexp capture the preceding blank, STRING and the following blank as +the groups 1, 2 and 3 respectively." + (format "\\(\\`\\|[ \t]\\)\\(%s\\)\\([ \t]\\|\\'\\)" string)) + +(defun dired--star-or-qmark-p (string match &optional keep) + "Return non-nil if STRING contains isolated MATCH or \"\\=`?\\=`\". +MATCH should be the strings \"?\", \"\\=`?\\=`\", \"*\" or nil. The latter +means STRING contains either \"?\" or \"\\=`?\\=`\" or \"*\". +If optional arg KEEP is non-nil, then preserve the match data. Otherwise, +this function changes it and saves MATCH as the second match group. + +Isolated means that MATCH is surrounded by spaces or at the beginning/end +of STRING followed/prefixed with an space. A match to \"\\=`?\\=`\", +isolated or not, is also valid." + (let ((regexps (list (dired-isolated-string-re (if match (regexp-quote match) "[*?]"))))) + (when (or (null match) (equal match "?")) + (setq regexps (append (list "\\(\\)\\(`\\?`\\)\\(\\)") regexps))) + (cl-some (lambda (x) + (funcall (if keep #'string-match-p #'string-match) x string)) + regexps))) ;;;###autoload (defun dired-diff (file &optional switches) @@ -704,8 +726,8 @@ dired-do-shell-command (dired-read-shell-command "! on %s: " current-prefix-arg files) current-prefix-arg files))) - (let* ((on-each (not (string-match-p dired-star-subst-regexp command))) - (no-subst (not (string-match-p dired-quark-subst-regexp command))) + (let* ((on-each (not (dired--star-or-qmark-p command "*" 'keep))) + (no-subst (not (dired--star-or-qmark-p command "?" 'keep))) (star (string-match-p "\\*" command)) (qmark (string-match-p "\\?" command)) ;; Get confirmation for wildcards that may have been meant @@ -768,12 +790,10 @@ dired-shell-stuff-it ";" "&")) (stuff-it - (if (or (string-match-p dired-star-subst-regexp command) - (string-match-p dired-quark-subst-regexp command)) + (if (dired--star-or-qmark-p command nil 'keep) (lambda (x) (let ((retval (concat cmd-prefix command))) - (while (string-match - "\\(^\\|[ \t]\\)\\([*?]\\)\\([ \t]\\|$\\)" retval) + (while (dired--star-or-qmark-p retval nil) (setq retval (replace-match x t t retval 2))) retval)) (lambda (x) (concat cmd-prefix command dired-mark-separator x))))) --8<-----------------------------cut here---------------end--------------->8--- In GNU Emacs 26.0.50 (build 13, x86_64-pc-linux-gnu, GTK+ Version 3.22.11) of 2017-06-27 built Repository revision: 1771d9b8082cf967e3f8b6a436d8766560be9e8d