emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master a6412b96e7 1/3: Move dired-guess commands from dired-x to dired


From: Stefan Kangas
Subject: master a6412b96e7 1/3: Move dired-guess commands from dired-x to dired
Date: Wed, 17 Aug 2022 10:32:53 -0400 (EDT)

branch: master
commit a6412b96e72c32ee981f469a564c8d2155d575aa
Author: Stefan Kangas <stefankangas@gmail.com>
Commit: Stefan Kangas <stefankangas@gmail.com>

    Move dired-guess commands from dired-x to dired
    
    * lisp/dired-x.el (dired-shell-command-history)
    (dired-guess-shell-alist-default, dired-guess-default)
    (dired-guess-shell-command): Move from here...
    * lisp/dired-aux.el (dired-shell-command-history)
    (dired-guess-shell-alist-default, dired-guess-default)
    (dired-guess-shell-command): ...to here.  (Bug#21981)
    
    * lisp/dired-x.el (dired-guess-shell-gnutar)
    (dired-guess-shell-gzip-quiet, dired-guess-shell-znew-switches)
    (dired-guess-shell-case-fold-search, dired-guess-shell-alist-user):
    Move from here...
    * lisp/dired.el (dired-guess-shell-gnutar)
    (dired-guess-shell-gzip-quiet, dired-guess-shell-znew-switches)
    (dired-guess-shell-case-fold-search, dired-guess-shell-alist-user):
    ...to here.  Change :group to dired-guess.
    (dired-guess): New defgroup.
    
    * test/lisp/dired-x-tests.el (dired-guess-default): Move from here...
    * test/lisp/dired-aux-tests.el (dired-guess-default): ...to here.
    
    * doc/misc/dired-x.texi (Features, Technical Details, Installation):
    Delete any mention of shell command guessing.
    (Shell Command Guessing): Move from here...
    * doc/emacs/dired.texi (Shell Command Guessing): ...to here.  Adapt to
    better fit the Emacs Manual conventions.
    * lisp/dired-aux.el (dired-do-shell-command): Doc fix to adjust for
    above changes.
    * etc/NEWS: Announce the above change.
---
 doc/emacs/dired.texi         | 104 ++++++++++++++
 doc/misc/dired-x.texi        | 112 ---------------
 etc/NEWS                     |   6 +
 lisp/dired-aux.el            | 259 ++++++++++++++++++++++++++++++++++
 lisp/dired-x.el              | 325 -------------------------------------------
 lisp/dired.el                |  71 ++++++++++
 test/lisp/dired-aux-tests.el |  13 ++
 test/lisp/dired-x-tests.el   |  13 --
 8 files changed, 453 insertions(+), 450 deletions(-)

diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi
index 292c986c1c..00028cac0f 100644
--- a/doc/emacs/dired.texi
+++ b/doc/emacs/dired.texi
@@ -41,6 +41,7 @@ you to operate on the listed files.  @xref{Directories}.
 * Operating on Files::        How to copy, rename, print, compress, etc.
                                 either one file or several files.
 * Shell Commands in Dired::   Running a shell command on the marked files.
+* Shell Command Guessing::    Guessing shell commands for files.
 * Transforming File Names::   Using patterns to rename multiple files.
 * Comparison in Dired::       Running @code{diff} by way of Dired.
 * Subdirectories in Dired::   Adding subdirectories to the Dired buffer.
@@ -1121,6 +1122,109 @@ buffer (@pxref{Dired Updating}).
   @xref{Single Shell}, for information about running shell commands
 outside Dired.
 
+@node Shell Command Guessing
+@section Shell Command Guessing
+@cindex guessing shell commands for files (in Dired)
+
+Based upon the name of a file, Dired tries to guess what shell command
+you might want to apply to it.  For example, if you have point on a
+file named @file{foo.tar} and you press @kbd{!}, Dired will guess that
+you want to run @samp{tar xvf}, and suggest that as the default shell
+command.
+
+The default is mentioned in brackets and you can type @kbd{M-n} to get
+the default into the minibuffer for editing.  If there are several
+commands for a given file, e.g., @samp{xtex} and @samp{dvips} for a
+@file{.dvi} file, you can type @kbd{M-n} several times to see each of
+the matching commands.
+
+Dired only tries to guess a command for a single file, never for a
+list of marked files.
+
+The following variables control guessing of shell commands:
+
+@defvar dired-guess-shell-alist-default
+This variable specifies the predefined rules for guessing shell
+commands suitable for certain files.  Set this to @code{nil} to turn
+guessing off.  The elements of @code{dired-guess-shell-alist-user}
+(defined by the user) will override these rules.
+@end defvar
+
+@defvar dired-guess-shell-alist-user
+If non-@code{nil}, this variables specifies the user-defined alist of
+file regexps and their suggested commands.  These rules take
+precedence over the predefined rules in the variable
+@code{dired-guess-shell-alist-default} (to which they are prepended)
+when @code{dired-do-shell-command} is run).  The default is
+@code{nil}.
+
+Each element of the alist looks like
+
+@example
+(@var{regexp} @var{command}@dots{})
+@end example
+
+@noindent
+where each @var{command} can either be a string or a Lisp expression
+that evaluates to a string.  If several commands are given, all of
+them will temporarily be pushed onto the history.
+
+A @samp{*} in the shell command stands for the file name that matched
+@var{regexp}.  When Emacs invokes the @var{command}, it replaces each
+instance of @samp{*} with the matched file name.
+
+You can set this variable in your Init file.  For example, to add
+rules for @samp{.foo} and @samp{.bar} file extensions:
+
+@example
+(setq dired-guess-shell-alist-user
+      (list
+       (list "\\.foo$" "@var{foo-command}")  ; fixed rule
+       ;; possibly more rules...
+       (list "\\.bar$"  ; rule with condition test
+             '(if @var{condition}
+                  "@var{bar-command-1}"
+                "@var{bar-command-2}"))))
+@end example
+
+@noindent
+This will override any predefined rules for the same extensions.
+@end defvar
+
+@defvar dired-guess-shell-case-fold-search
+If this variable is non-@code{nil},
+@code{dired-guess-shell-alist-default} and
+@code{dired-guess-shell-alist-user} are matched case-insensitively.
+The default is @code{t}.
+@end defvar
+
+@defvar dired-guess-shell-gnutar
+If this variable is non-@code{nil}, it specifies the name of the GNU
+Tar executable (e.g., @file{tar} or @file{gtar}).  GNU Tar's @samp{z}
+switch is used for compressed archives.  If you don't have GNU Tar,
+set this to @code{nil}: a pipe using @command{zcat} is then used
+instead.
+@end defvar
+
+@defvar dired-guess-shell-gzip-quiet
+A non-@code{nil} value of this variable means that @samp{-q} is passed
+to @command{gzip}, possibly overriding a verbose option in the
+@env{GZIP} environment variable.  The default is @code{t}.
+@end defvar
+
+@defvar dired-guess-shell-znew-switches nil
+This variable specifies a string of switches passed to @command{znew}.
+An example is @samp{-K} which will make @command{znew} keep a
+@file{.Z} file when it is smaller than the @file{.gz} file.  The
+default is @code{nil}: no additional switches are passed to
+@command{znew}.
+@end defvar
+
+@defvar dired-shell-command-history nil
+This variable holds the history list for commands that read
+dired-shell commands.
+@end defvar
+
 @node Transforming File Names
 @section Transforming File Names in Dired
 
diff --git a/doc/misc/dired-x.texi b/doc/misc/dired-x.texi
index 50d9914081..002164ed91 100644
--- a/doc/misc/dired-x.texi
+++ b/doc/misc/dired-x.texi
@@ -92,7 +92,6 @@ For @file{dired-x.el} as distributed with GNU Emacs 
@value{EMACSVER}.
 * Introduction::
 * Installation::
 * Omitting Files in Dired::
-* Shell Command Guessing::
 * Virtual Dired::
 * Advanced Mark Commands::
 * Multiple Dired Directories::
@@ -135,9 +134,6 @@ Some features provided by Dired Extra:
 Omitting uninteresting files from Dired listing
 (@pxref{Omitting Files in Dired}).
 @item
-Guessing shell commands in Dired buffers
-(@pxref{Shell Command Guessing}).
-@item
 Running Dired command in non-Dired buffers
 (@pxref{Virtual Dired}).
 @item
@@ -165,8 +161,6 @@ When @file{dired-x.el} is loaded, some standard Dired 
functions from
 Dired}), if it is active.  @code{dired-find-buffer-nocreate} and
 @code{dired-initial-position} respect the value of
 @code{dired-find-subdir} (@pxref{Miscellaneous Commands}).
-@code{dired-read-shell-command} uses @code{dired-guess-shell-command}
-(@pxref{Shell Command Guessing}) to offer a smarter default command.
 
 @node Installation
 @chapter Installation
@@ -184,7 +178,6 @@ In your @file{~/.emacs} file, or in the system-wide 
initialization file
 (with-eval-after-load 'dired
   (require 'dired-x)
   ;; Set dired-x global variables here.  For example:
-  ;; (setq dired-guess-shell-gnutar "gtar")
   ;; (setq dired-x-hands-off-my-keys nil)
   ))
 (add-hook 'dired-mode-hook
@@ -436,111 +429,6 @@ Loading @file{dired-x.el} will install Dired Omit by 
putting
 call @code{dired-extra-startup}, which in turn calls @code{dired-omit-startup}
 in your @code{dired-mode-hook}.
 
-@node Shell Command Guessing
-@chapter Shell Command Guessing
-@cindex guessing shell commands for files.
-
-Based upon the name of a file, Dired tries to guess what shell
-command you might want to apply to it.  For example, if you have point
-on a file named @file{foo.tar} and you press @kbd{!}, Dired will guess
-you want to @samp{tar xvf} it and suggest that as the default shell
-command.
-
-The default is mentioned in brackets and you can type @kbd{M-n} to get
-the default into the minibuffer and then edit it, e.g., to change
-@samp{tar xvf} to @samp{tar tvf}.  If there are several commands for a given
-file, e.g., @samp{xtex} and @samp{dvips} for a @file{.dvi} file, you can type
-@kbd{M-n} several times to see each of the matching commands.
-
-Dired only tries to guess a command for a single file, never for a list
-of marked files.
-
-The following variables control guessing of shell commands:
-
-@defvar dired-guess-shell-alist-default
-This variable specifies the predefined rules for guessing shell
-commands suitable for certain files.  Set this to @code{nil} to turn
-guessing off.  The elements of @code{dired-guess-shell-alist-user}
-(defined by the user) will override these rules.
-@end defvar
-
-@defvar dired-guess-shell-alist-user
-If non-@code{nil}, this variables specifies the user-defined alist of
-file regexps and their suggested commands.  These rules take
-precedence over the predefined rules in the variable
-@code{dired-guess-shell-alist-default} (to which they are prepended)
-when @code{dired-do-shell-command} is run).  The default is
-@code{nil}.
-
-Each element of the alist looks like
-
-@example
-(@var{regexp} @var{command}@dots{})
-@end example
-
-@noindent
-where each @var{command} can either be a string or a Lisp expression
-that evaluates to a string.  If several commands are given, all of
-them will temporarily be pushed onto the history.
-
-A @samp{*} in the shell command stands for the file name that matched
-@var{regexp}.  When Emacs invokes the @var{command}, it replaces each
-instance of @samp{*} with the matched file name.
-
-You can set this variable in your @file{~/.emacs}.  For example,
-to add rules for @samp{.foo} and @samp{.bar} file extensions, write
-
-@example
-(setq dired-guess-shell-alist-user
-      (list
-       (list "\\.foo$" "@var{foo-command}");; fixed rule
-       ;; possibly more rules...
-       (list "\\.bar$";; rule with condition test
-              '(if @var{condition}
-                   "@var{bar-command-1}"
-                 "@var{bar-command-2}"))))
-@end example
-
-@noindent
-This will override any predefined rules for the same extensions.
-@end defvar
-
-@defvar dired-guess-shell-case-fold-search
-If this variable is non-@code{nil},
-@code{dired-guess-shell-alist-default} and
-@code{dired-guess-shell-alist-user} are matched case-insensitively.
-The default is @code{t}.
-@end defvar
-
-@cindex passing GNU Tar its @samp{z} switch.
-@defvar dired-guess-shell-gnutar
-If this variable is non-@code{nil}, it specifies the name of the GNU
-Tar executable (e.g., @file{tar} or @file{gnutar}).  GNU Tar's
-@samp{z} switch is used for compressed archives.  If you don't have
-GNU Tar, set this to @code{nil}: a pipe using @command{zcat} is then
-used instead.  The default is @code{nil}.
-@end defvar
-
-@cindex @code{gzip}
-@defvar dired-guess-shell-gzip-quiet
-A non-@code{nil} value of this variable means that @samp{-q} is passed
-to @command{gzip}, possibly overriding a verbose option in the @env{GZIP}
-environment variable.  The default is @code{t}.
-@end defvar
-
-@cindex @code{znew}
-@defvar dired-guess-shell-znew-switches nil
-This variable specifies a string of switches passed to @command{znew}.
-An example is @samp{-K} which will make @command{znew} keep a @file{.Z}
-file when it is smaller than the @file{.gz} file.  The default is
-@code{nil}: no additional switches are passed to @command{znew}.
-@end defvar
-
-@defvar dired-shell-command-history nil
-This variable holds the history list for commands that read
-dired-shell commands.
-@end defvar
-
 @node Virtual Dired
 @chapter Virtual Dired
 
diff --git a/etc/NEWS b/etc/NEWS
index 5d87bc9e2e..4b3a48a820 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1159,6 +1159,12 @@ change the input method's translation rules, customize 
the user option
 
 ** Dired
 
++++
+*** 'dired-guess-shell-command' moved from dired-x to dired.
+This means that 'dired-do-shell-command' will now provide smarter
+defaults without first having to require 'dired-x'.  See the node
+"(emacs) Shell Command Guessing" in the Emacs manual for more details.
+
 ---
 *** 'dired-clean-up-buffers-too' moved from dired-x to dired.
 This means that Dired now offers to kill buffers visiting files and
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index 7ff3e33351..426273f65e 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -1071,6 +1071,265 @@ Return the result of `process-file' - zero for success."
          res)))))
 
 
+;;; Guess shell command
+
+;; * `dired-guess-shell-command' provides smarter defaults for
+;;    `dired-read-shell-command'.
+;;
+;; * `dired-guess-shell-command' calls `dired-guess-default' with list of
+;;    marked files.
+;;
+;; * Parse `dired-guess-shell-alist-user' and
+;;   `dired-guess-shell-alist-default' (in that order) for the first REGEXP
+;;   that matches the first file in the file list.
+;;
+;; * If the REGEXP matches all the entries of the file list then evaluate
+;;   COMMAND, which is either a string or a Lisp expression returning a
+;;   string.  COMMAND may be a list of commands.
+;;
+;; * Return this command to `dired-guess-shell-command' which prompts user
+;;   with it.  The list of commands is put into the list of default values.
+;;   If a command is used successfully then it is stored permanently in
+;;   `dired-shell-command-history'.
+
+;; Guess what shell command to apply to a file.
+(defvar dired-shell-command-history nil
+  "History list for commands that read dired-shell commands.")
+
+;; Default list of shell commands.
+
+;; NOTE: Use `gunzip -c' instead of `zcat' on `.gz' files.  Some do not
+;; install GNU zip's version of zcat.
+
+(autoload 'Man-support-local-filenames "man")
+(autoload 'vc-responsible-backend "vc")
+
+(defvar dired-guess-shell-alist-default
+  (list
+   (list "\\.tar\\'"
+         '(if dired-guess-shell-gnutar
+              (concat dired-guess-shell-gnutar " xvf")
+            "tar xvf")
+         ;; Extract files into a separate subdirectory
+         '(if dired-guess-shell-gnutar
+              (concat "mkdir " (file-name-sans-extension file)
+                      "; " dired-guess-shell-gnutar " -C "
+                      (file-name-sans-extension file) " -xvf")
+            (concat "mkdir " (file-name-sans-extension file)
+                    "; tar -C " (file-name-sans-extension file) " -xvf"))
+         ;; List archive contents.
+         '(if dired-guess-shell-gnutar
+              (concat dired-guess-shell-gnutar " tvf")
+            "tar tvf"))
+
+   ;; REGEXPS for compressed archives must come before the .Z rule to
+   ;; be recognized:
+   (list "\\.tar\\.Z\\'"
+         ;; Untar it.
+         '(if dired-guess-shell-gnutar
+              (concat dired-guess-shell-gnutar " zxvf")
+            (concat "zcat * | tar xvf -"))
+         ;; Optional conversion to gzip format.
+         '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
+                  " " dired-guess-shell-znew-switches))
+
+   ;; gzip'ed archives
+   (list "\\.t\\(ar\\.\\)?gz\\'"
+         '(if dired-guess-shell-gnutar
+              (concat dired-guess-shell-gnutar " zxvf")
+            (concat "gunzip -qc * | tar xvf -"))
+         ;; Extract files into a separate subdirectory
+         '(if dired-guess-shell-gnutar
+              (concat "mkdir " (file-name-sans-extension file)
+                      "; " dired-guess-shell-gnutar " -C "
+                      (file-name-sans-extension file) " -zxvf")
+            (concat "mkdir " (file-name-sans-extension file)
+                    "; gunzip -qc * | tar -C "
+                    (file-name-sans-extension file) " -xvf -"))
+         ;; Optional decompression.
+         '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q" ""))
+         ;; List archive contents.
+         '(if dired-guess-shell-gnutar
+              (concat dired-guess-shell-gnutar " ztvf")
+            (concat "gunzip -qc * | tar tvf -")))
+
+   ;; bzip2'ed archives
+   (list "\\.t\\(ar\\.bz2\\|bz\\)\\'"
+         "bunzip2 -c * | tar xvf -"
+         ;; Extract files into a separate subdirectory
+         '(concat "mkdir " (file-name-sans-extension file)
+                  "; bunzip2 -c * | tar -C "
+                  (file-name-sans-extension file) " -xvf -")
+         ;; Optional decompression.
+         "bunzip2")
+
+   ;; xz'ed archives
+   (list "\\.t\\(ar\\.\\)?xz\\'"
+         "unxz -c * | tar xvf -"
+         ;; Extract files into a separate subdirectory
+         '(concat "mkdir " (file-name-sans-extension file)
+                  "; unxz -c * | tar -C "
+                  (file-name-sans-extension file) " -xvf -")
+         ;; Optional decompression.
+         "unxz")
+
+   '("\\.shar\\.Z\\'" "zcat * | unshar")
+   '("\\.shar\\.g?z\\'" "gunzip -qc * | unshar")
+
+   '("\\.e?ps\\'" "ghostview" "xloadimage" "lpr")
+   (list "\\.e?ps\\.g?z\\'" "gunzip -qc * | ghostview -"
+         ;; Optional decompression.
+         '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
+   (list "\\.e?ps\\.Z\\'" "zcat * | ghostview -"
+         ;; Optional conversion to gzip format.
+         '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
+                  " " dired-guess-shell-znew-switches))
+
+   (list "\\.patch\\'"
+         '(if (eq (ignore-errors (vc-responsible-backend default-directory)) 
'Git)
+              "cat * | git apply"
+            "cat * | patch"))
+   (list "\\.patch\\.g?z\\'" "gunzip -qc * | patch"
+         ;; Optional decompression.
+         '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
+   (list "\\.patch\\.Z\\'" "zcat * | patch"
+         ;; Optional conversion to gzip format.
+         '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
+                  " " dired-guess-shell-znew-switches))
+
+   ;; The following four extensions are useful with dired-man ("N" key)
+   ;; FIXME "man ./" does not work with dired-do-shell-command,
+   ;; because there seems to be no way for us to modify the filename,
+   ;; only the command.  Hmph.  `dired-man' works though.
+   (list "\\.\\(?:[0-9]\\|man\\)\\'"
+         '(let ((loc (Man-support-local-filenames)))
+            (cond ((eq loc 'man-db) "man -l")
+                  ((eq loc 'man) "man ./")
+                  (t
+                   "cat * | tbl | nroff -man -h | col -b"))))
+   (list "\\.\\(?:[0-9]\\|man\\)\\.g?z\\'"
+         '(let ((loc (Man-support-local-filenames)))
+            (cond ((eq loc 'man-db)
+                   "man -l")
+                  ((eq loc 'man)
+                   "man ./")
+                  (t "gunzip -qc * | tbl | nroff -man -h | col -b")))
+         ;; Optional decompression.
+         '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
+   (list "\\.[0-9]\\.Z\\'"
+         '(let ((loc (Man-support-local-filenames)))
+            (cond ((eq loc 'man-db) "man -l")
+                  ((eq loc 'man) "man ./")
+                  (t "zcat * | tbl | nroff -man -h | col -b")))
+         ;; Optional conversion to gzip format.
+         '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
+                  " " dired-guess-shell-znew-switches))
+   '("\\.pod\\'" "perldoc" "pod2man * | nroff -man")
+
+   '("\\.dvi\\'" "xdvi" "dvips")       ; preview and printing
+   '("\\.au\\'" "play")                        ; play Sun audiofiles
+   '("\\.mpe?g\\'\\|\\.avi\\'" "xine -p")
+   '("\\.ogg\\'" "ogg123")
+   '("\\.mp3\\'" "mpg123")
+   '("\\.wav\\'" "play")
+   '("\\.uu\\'" "uudecode")            ; for uudecoded files
+   '("\\.hqx\\'" "mcvert")
+   '("\\.sh\\'" "sh")                  ; execute shell scripts
+   '("\\.xbm\\'" "bitmap")             ; view X11 bitmaps
+   '("\\.gp\\'" "gnuplot")
+   '("\\.p[bgpn]m\\'" "xloadimage")
+   '("\\.gif\\'" "xloadimage")         ; view gif pictures
+   '("\\.tif\\'" "xloadimage")
+   '("\\.png\\'" "display")            ; xloadimage 4.1 doesn't grok PNG
+   '("\\.jpe?g\\'" "xloadimage")
+   '("\\.fig\\'" "xfig")               ; edit fig pictures
+   '("\\.out\\'" "xgraph")             ; for plotting purposes.
+   '("\\.tex\\'" "latex" "tex")
+   '("\\.texi\\(nfo\\)?\\'" "makeinfo" "texi2dvi")
+   '("\\.pdf\\'" "xpdf")
+   '("\\.doc\\'" "antiword" "strings")
+   '("\\.rpm\\'" "rpm -qilp" "rpm -ivh")
+   '("\\.dia\\'" "dia")
+   '("\\.mgp\\'" "mgp")
+
+   ;; Some other popular archivers.
+   (list "\\.zip\\'" "unzip" "unzip -l"
+         ;; Extract files into a separate subdirectory
+         '(concat "unzip" (if dired-guess-shell-gzip-quiet " -q")
+                  " -d " (file-name-sans-extension file)))
+   '("\\.zoo\\'" "zoo x//")
+   '("\\.lzh\\'" "lharc x")
+   '("\\.arc\\'" "arc x")
+   '("\\.shar\\'" "unshar")
+   '("\\.rar\\'" "unrar x")
+   '("\\.7z\\'" "7z x")
+
+   ;; Compression.
+   (list "\\.g?z\\'" '(concat "gunzip" (if dired-guess-shell-gzip-quiet " 
-q")))
+   (list "\\.dz\\'" "dictunzip")
+   (list "\\.bz2\\'" "bunzip2")
+   (list "\\.xz\\'" "unxz")
+   (list "\\.Z\\'" "uncompress"
+         ;; Optional conversion to gzip format.
+         '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
+                  " " dired-guess-shell-znew-switches))
+
+   '("\\.sign?\\'" "gpg --verify"))
+  "Default alist used for shell command guessing.
+See `dired-guess-shell-alist-user'.")
+
+(defun dired-guess-default (files)
+  "Return a shell command, or a list of commands, appropriate for FILES.
+See `dired-guess-shell-alist-user'."
+  (let* ((case-fold-search dired-guess-shell-case-fold-search)
+         (programs
+          (delete-dups
+           (mapcar
+            (lambda (command)
+              (eval command `((file . ,(car files)))))
+            (seq-reduce
+             #'append
+             (mapcar #'cdr
+                     (seq-filter (lambda (elem)
+                                   (seq-every-p
+                                    (lambda (file)
+                                      (string-match-p (car elem) file))
+                                    files))
+                                 (append dired-guess-shell-alist-user
+                                         dired-guess-shell-alist-default)))
+             nil)))))
+    (if (length= programs 1)
+        (car programs)
+      programs)))
+
+;;;###autoload
+(defun dired-guess-shell-command (prompt files)
+  "Ask user with PROMPT for a shell command, guessing a default from FILES."
+  (let ((default (dired-guess-default files))
+        default-list val)
+    (if (null default)
+        ;; Nothing to guess
+        (read-shell-command prompt nil 'dired-shell-command-history)
+      (setq prompt (replace-regexp-in-string ": $" " " prompt))
+      (if (listp default)
+          ;; More than one guess
+          (setq default-list default
+                default (car default)
+                prompt (concat
+                        prompt
+                        (format "{%d guesses} " (length default-list))))
+        ;; Just one guess
+        (setq default-list (list default)))
+      ;; Put the first guess in the prompt but not in the initial value.
+      (setq prompt (concat prompt (format "[%s]: " default)))
+      ;; All guesses can be retrieved with M-n
+      (setq val (read-shell-command prompt nil
+                                    'dired-shell-command-history
+                                    default-list))
+      ;; If we got a return, then return default.
+      (if (equal val "") default val))))
+
+
 ;;; Commands that delete or redisplay part of the dired buffer
 
 (defun dired-kill-line (&optional arg)
diff --git a/lisp/dired-x.el b/lisp/dired-x.el
index 9edf837481..cf1ef37694 100644
--- a/lisp/dired-x.el
+++ b/lisp/dired-x.el
@@ -196,35 +196,6 @@ toggle between those two."
   :type 'boolean
   :group 'dired-x)
 
-(defcustom dired-guess-shell-gnutar
-  (catch 'found
-    (dolist (exe '("tar" "gtar"))
-      (if (with-temp-buffer
-            (ignore-errors (call-process exe nil t nil "--version"))
-            (and (re-search-backward "GNU tar" nil t) t))
-          (throw 'found exe))))
-  "If non-nil, name of GNU tar executable.
-\(E.g., \"tar\" or \"gtar\").  The `z' switch will be used with it for
-compressed or gzip'ed tar files.  If you don't have GNU tar, set this
-to nil: a pipe using `zcat' or `gunzip -c' will be used."
-  ;; Changed from system-type test to testing --version output.
-  ;; Maybe test --help for -z instead?
-  :version "24.1"
-  :type '(choice (const :tag "Not GNU tar" nil)
-                (string :tag "Command name"))
-  :group 'dired-x)
-
-(defcustom dired-guess-shell-gzip-quiet t
-  "Non-nil says pass -q to gzip overriding verbose GZIP environment."
-  :type 'boolean
-  :group 'dired-x)
-
-(defcustom dired-guess-shell-znew-switches nil
-  "If non-nil, then string of switches passed to `znew', example: \"-K\"."
-  :type '(choice (const :tag "None" nil)
-                (string :tag "Switches"))
-  :group 'dired-x)
-
 
 ;;; Key bindings
 
@@ -727,302 +698,6 @@ Also useful for `auto-mode-alist' like this:
     (shell-command command output-buffer error-buffer)))
 
 
-;;; Guess shell command
-
-;; Brief Description:
-;;
-;; * `dired-do-shell-command' is bound to `!' by dired.el.
-;;
-;; * `dired-guess-shell-command' provides smarter defaults for
-;;    dired-aux.el's `dired-read-shell-command'.
-;;
-;; * `dired-guess-shell-command' calls `dired-guess-default' with list of
-;;    marked files.
-;;
-;; * Parse `dired-guess-shell-alist-user' and
-;;   `dired-guess-shell-alist-default' (in that order) for the first REGEXP
-;;   that matches the first file in the file list.
-;;
-;; * If the REGEXP matches all the entries of the file list then evaluate
-;;   COMMAND, which is either a string or a Lisp expression returning a
-;;   string.  COMMAND may be a list of commands.
-;;
-;; * Return this command to `dired-guess-shell-command' which prompts user
-;;   with it.  The list of commands is put into the list of default values.
-;;   If a command is used successfully then it is stored permanently in
-;;   `dired-shell-command-history'.
-
-;; Guess what shell command to apply to a file.
-(defvar dired-shell-command-history nil
-  "History list for commands that read dired-shell commands.")
-
-;; Default list of shell commands.
-
-;; NOTE: Use `gunzip -c' instead of `zcat' on `.gz' files.  Some do not
-;; install GNU zip's version of zcat.
-
-(autoload 'Man-support-local-filenames "man")
-(autoload 'vc-responsible-backend "vc")
-
-(defvar dired-guess-shell-alist-default
-  (list
-   (list "\\.tar\\'"
-        '(if dired-guess-shell-gnutar
-             (concat dired-guess-shell-gnutar " xvf")
-           "tar xvf")
-        ;; Extract files into a separate subdirectory
-        '(if dired-guess-shell-gnutar
-             (concat "mkdir " (file-name-sans-extension file)
-                     "; " dired-guess-shell-gnutar " -C "
-                     (file-name-sans-extension file) " -xvf")
-           (concat "mkdir " (file-name-sans-extension file)
-                   "; tar -C " (file-name-sans-extension file) " -xvf"))
-        ;; List archive contents.
-        '(if dired-guess-shell-gnutar
-             (concat dired-guess-shell-gnutar " tvf")
-           "tar tvf"))
-
-   ;; REGEXPS for compressed archives must come before the .Z rule to
-   ;; be recognized:
-   (list "\\.tar\\.Z\\'"
-        ;; Untar it.
-        '(if dired-guess-shell-gnutar
-             (concat dired-guess-shell-gnutar " zxvf")
-           (concat "zcat * | tar xvf -"))
-        ;; Optional conversion to gzip format.
-        '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
-                 " " dired-guess-shell-znew-switches))
-
-   ;; gzip'ed archives
-   (list "\\.t\\(ar\\.\\)?gz\\'"
-        '(if dired-guess-shell-gnutar
-             (concat dired-guess-shell-gnutar " zxvf")
-           (concat "gunzip -qc * | tar xvf -"))
-        ;; Extract files into a separate subdirectory
-        '(if dired-guess-shell-gnutar
-             (concat "mkdir " (file-name-sans-extension file)
-                     "; " dired-guess-shell-gnutar " -C "
-                     (file-name-sans-extension file) " -zxvf")
-           (concat "mkdir " (file-name-sans-extension file)
-                   "; gunzip -qc * | tar -C "
-                   (file-name-sans-extension file) " -xvf -"))
-        ;; Optional decompression.
-        '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q" ""))
-        ;; List archive contents.
-        '(if dired-guess-shell-gnutar
-             (concat dired-guess-shell-gnutar " ztvf")
-           (concat "gunzip -qc * | tar tvf -")))
-
-   ;; bzip2'ed archives
-   (list "\\.t\\(ar\\.bz2\\|bz\\)\\'"
-        "bunzip2 -c * | tar xvf -"
-        ;; Extract files into a separate subdirectory
-        '(concat "mkdir " (file-name-sans-extension file)
-                 "; bunzip2 -c * | tar -C "
-                 (file-name-sans-extension file) " -xvf -")
-        ;; Optional decompression.
-        "bunzip2")
-
-   ;; xz'ed archives
-   (list "\\.t\\(ar\\.\\)?xz\\'"
-        "unxz -c * | tar xvf -"
-        ;; Extract files into a separate subdirectory
-        '(concat "mkdir " (file-name-sans-extension file)
-                 "; unxz -c * | tar -C "
-                 (file-name-sans-extension file) " -xvf -")
-        ;; Optional decompression.
-        "unxz")
-
-   '("\\.shar\\.Z\\'" "zcat * | unshar")
-   '("\\.shar\\.g?z\\'" "gunzip -qc * | unshar")
-
-   '("\\.e?ps\\'" "ghostview" "xloadimage" "lpr")
-   (list "\\.e?ps\\.g?z\\'" "gunzip -qc * | ghostview -"
-        ;; Optional decompression.
-        '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
-   (list "\\.e?ps\\.Z\\'" "zcat * | ghostview -"
-        ;; Optional conversion to gzip format.
-        '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
-                 " " dired-guess-shell-znew-switches))
-
-   (list "\\.patch\\'"
-         '(if (eq (ignore-errors (vc-responsible-backend default-directory)) 
'Git)
-              "cat * | git apply"
-            "cat * | patch"))
-   (list "\\.patch\\.g?z\\'" "gunzip -qc * | patch"
-        ;; Optional decompression.
-        '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
-   (list "\\.patch\\.Z\\'" "zcat * | patch"
-        ;; Optional conversion to gzip format.
-        '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
-                 " " dired-guess-shell-znew-switches))
-
-   ;; The following four extensions are useful with dired-man ("N" key)
-   ;; FIXME "man ./" does not work with dired-do-shell-command,
-   ;; because there seems to be no way for us to modify the filename,
-   ;; only the command.  Hmph.  `dired-man' works though.
-   (list "\\.\\(?:[0-9]\\|man\\)\\'"
-         '(let ((loc (Man-support-local-filenames)))
-            (cond ((eq loc 'man-db) "man -l")
-                  ((eq loc 'man) "man ./")
-                  (t
-                   "cat * | tbl | nroff -man -h | col -b"))))
-   (list "\\.\\(?:[0-9]\\|man\\)\\.g?z\\'"
-         '(let ((loc (Man-support-local-filenames)))
-            (cond ((eq loc 'man-db)
-                   "man -l")
-                  ((eq loc 'man)
-                   "man ./")
-                  (t "gunzip -qc * | tbl | nroff -man -h | col -b")))
-        ;; Optional decompression.
-        '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
-   (list "\\.[0-9]\\.Z\\'"
-         '(let ((loc (Man-support-local-filenames)))
-            (cond ((eq loc 'man-db) "man -l")
-                  ((eq loc 'man) "man ./")
-                  (t "zcat * | tbl | nroff -man -h | col -b")))
-        ;; Optional conversion to gzip format.
-        '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
-                 " " dired-guess-shell-znew-switches))
-   '("\\.pod\\'" "perldoc" "pod2man * | nroff -man")
-
-   '("\\.dvi\\'" "xdvi" "dvips")       ; preview and printing
-   '("\\.au\\'" "play")                        ; play Sun audiofiles
-   '("\\.mpe?g\\'\\|\\.avi\\'" "xine -p")
-   '("\\.ogg\\'" "ogg123")
-   '("\\.mp3\\'" "mpg123")
-   '("\\.wav\\'" "play")
-   '("\\.uu\\'" "uudecode")            ; for uudecoded files
-   '("\\.hqx\\'" "mcvert")
-   '("\\.sh\\'" "sh")                  ; execute shell scripts
-   '("\\.xbm\\'" "bitmap")             ; view X11 bitmaps
-   '("\\.gp\\'" "gnuplot")
-   '("\\.p[bgpn]m\\'" "xloadimage")
-   '("\\.gif\\'" "xloadimage")         ; view gif pictures
-   '("\\.tif\\'" "xloadimage")
-   '("\\.png\\'" "display")            ; xloadimage 4.1 doesn't grok PNG
-   '("\\.jpe?g\\'" "xloadimage")
-   '("\\.fig\\'" "xfig")               ; edit fig pictures
-   '("\\.out\\'" "xgraph")             ; for plotting purposes.
-   '("\\.tex\\'" "latex" "tex")
-   '("\\.texi\\(nfo\\)?\\'" "makeinfo" "texi2dvi")
-   '("\\.pdf\\'" "xpdf")
-   '("\\.doc\\'" "antiword" "strings")
-   '("\\.rpm\\'" "rpm -qilp" "rpm -ivh")
-   '("\\.dia\\'" "dia")
-   '("\\.mgp\\'" "mgp")
-
-   ;; Some other popular archivers.
-   (list "\\.zip\\'" "unzip" "unzip -l"
-        ;; Extract files into a separate subdirectory
-        '(concat "unzip" (if dired-guess-shell-gzip-quiet " -q")
-                 " -d " (file-name-sans-extension file)))
-   '("\\.zoo\\'" "zoo x//")
-   '("\\.lzh\\'" "lharc x")
-   '("\\.arc\\'" "arc x")
-   '("\\.shar\\'" "unshar")
-   '("\\.rar\\'" "unrar x")
-   '("\\.7z\\'" "7z x")
-
-   ;; Compression.
-   (list "\\.g?z\\'" '(concat "gunzip" (if dired-guess-shell-gzip-quiet " 
-q")))
-   (list "\\.dz\\'" "dictunzip")
-   (list "\\.bz2\\'" "bunzip2")
-   (list "\\.xz\\'" "unxz")
-   (list "\\.Z\\'" "uncompress"
-        ;; Optional conversion to gzip format.
-        '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
-                 " " dired-guess-shell-znew-switches))
-
-   '("\\.sign?\\'" "gpg --verify"))
-
-  "Default alist used for shell command guessing.
-See `dired-guess-shell-alist-user'.")
-
-(defcustom dired-guess-shell-alist-user nil
-  "User-defined alist of rules for suggested commands.
-These rules take precedence over the predefined rules in the variable
-`dired-guess-shell-alist-default' (to which they are prepended).
-
-Each element of this list looks like
-
-    (REGEXP COMMAND...)
-
-COMMAND will be used if REGEXP matches the file to be processed.
-If several files are to be processed, REGEXP has to match all the
-files.
-
-Each COMMAND can either be a string or a Lisp expression that evaluates
-to a string.  If this expression needs to consult the name of the file for
-which the shell commands are being requested, it can access that file name
-as the variable `file'.
-
-If several COMMANDs are given, the first one will be the default
-and the rest will be added temporarily to the history and can be retrieved
-with `previous-history-element' 
(\\<minibuffer-mode-map>\\[previous-history-element]).
-
-The variable `dired-guess-shell-case-fold-search' controls whether
-REGEXP is matched case-sensitively."
-  :group 'dired-x
-  :type '(alist :key-type regexp :value-type (repeat sexp)))
-
-(defcustom dired-guess-shell-case-fold-search t
-  "If non-nil, `dired-guess-shell-alist-default' and
-`dired-guess-shell-alist-user' are matched case-insensitively."
-  :group 'dired-x
-  :type 'boolean)
-
-(defun dired-guess-default (files)
-  "Return a shell command, or a list of commands, appropriate for FILES.
-See `dired-guess-shell-alist-user'."
-  (let* ((case-fold-search dired-guess-shell-case-fold-search)
-         (programs
-          (delete-dups
-           (mapcar
-            (lambda (command)
-              (eval command `((file . ,(car files)))))
-            (seq-reduce
-             #'append
-             (mapcar #'cdr
-                     (seq-filter (lambda (elem)
-                                   (seq-every-p
-                                    (lambda (file)
-                                      (string-match-p (car elem) file))
-                                    files))
-                                 (append dired-guess-shell-alist-user
-                                         dired-guess-shell-alist-default)))
-             nil)))))
-    (if (length= programs 1)
-        (car programs)
-      programs)))
-
-(defun dired-guess-shell-command (prompt files)
-  "Ask user with PROMPT for a shell command, guessing a default from FILES."
-  (let ((default (dired-guess-default files))
-        default-list val)
-    (if (null default)
-        ;; Nothing to guess
-        (read-shell-command prompt nil 'dired-shell-command-history)
-      (setq prompt (replace-regexp-in-string ": $" " " prompt))
-      (if (listp default)
-          ;; More than one guess
-          (setq default-list default
-                default (car default)
-                prompt (concat
-                        prompt
-                        (format "{%d guesses} " (length default-list))))
-        ;; Just one guess
-        (setq default-list (list default)))
-      ;; Put the first guess in the prompt but not in the initial value.
-      (setq prompt (concat prompt (format "[%s]: " default)))
-      ;; All guesses can be retrieved with M-n
-      (setq val (read-shell-command prompt nil
-                                    'dired-shell-command-history
-                                    default-list))
-      ;; If we got a return, then return default.
-      (if (equal val "") default val))))
-
-
 ;;; Visit all marked files simultaneously
 
 ;; Brief Description:
diff --git a/lisp/dired.el b/lisp/dired.el
index 10813e56df..799a9f4716 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -53,6 +53,11 @@
   :prefix "dired-"
   :group 'dired)
 
+(defgroup dired-guess nil
+  "Guess shell command in Dired."
+  :prefix "dired-"
+  :group 'dired)
+
 ;;;###autoload
 (defcustom dired-listing-switches (purecopy "-al")
   "Switches passed to `ls' for Dired.  MUST contain the `l' option.
@@ -419,6 +424,72 @@ is anywhere on its Dired line, except the beginning of the 
line."
   :type 'boolean
   :version "28.1")
 
+(defcustom dired-guess-shell-case-fold-search t
+  "If non-nil, `dired-guess-shell-alist-default' and
+`dired-guess-shell-alist-user' are matched case-insensitively."
+  :group 'dired-guess
+  :type 'boolean
+  :version "29.1")
+
+(defcustom dired-guess-shell-alist-user nil
+  "User-defined alist of rules for suggested commands.
+These rules take precedence over the predefined rules in the variable
+`dired-guess-shell-alist-default' (to which they are prepended).
+
+Each element of this list looks like
+
+    (REGEXP COMMAND...)
+
+COMMAND will be used if REGEXP matches the file to be processed.
+If several files are to be processed, REGEXP has to match all the
+files.
+
+Each COMMAND can either be a string or a Lisp expression that evaluates
+to a string.  If this expression needs to consult the name of the file for
+which the shell commands are being requested, it can access that file name
+as the variable `file'.
+
+If several COMMANDs are given, the first one will be the default
+and the rest will be added temporarily to the history and can be retrieved
+with `previous-history-element' 
(\\<minibuffer-mode-map>\\[previous-history-element]).
+
+The variable `dired-guess-shell-case-fold-search' controls whether
+REGEXP is matched case-sensitively."
+  :group 'dired-guess
+  :type '(alist :key-type regexp :value-type (repeat sexp))
+  :version "29.1")
+
+(defcustom dired-guess-shell-gnutar
+  (catch 'found
+    (dolist (exe '("tar" "gtar"))
+      (if (with-temp-buffer
+            (ignore-errors (call-process exe nil t nil "--version"))
+            (and (re-search-backward "GNU tar" nil t) t))
+          (throw 'found exe))))
+  "If non-nil, name of GNU tar executable.
+\(E.g., \"tar\" or \"gtar\").  The `z' switch will be used with it for
+compressed or gzip'ed tar files.  If you don't have GNU tar, set this
+to nil: a pipe using `zcat' or `gunzip -c' will be used."
+  ;; Changed from system-type test to testing --version output.
+  ;; Maybe test --help for -z instead?
+  :group 'dired-guess
+  :type '(choice (const :tag "Not GNU tar" nil)
+                 (string :tag "Command name"))
+  :version "29.1")
+
+(defcustom dired-guess-shell-gzip-quiet t
+  "Non-nil says pass -q to gzip overriding verbose GZIP environment."
+  :group 'dired-guess
+  :type 'boolean
+  :version "29.1")
+
+(defcustom dired-guess-shell-znew-switches nil
+  "If non-nil, then string of switches passed to `znew', example: \"-K\"."
+  :group 'dired-guess
+  :type '(choice (const :tag "None" nil)
+                 (string :tag "Switches"))
+  :version "29.1")
+
 
 ;;; Internal variables
 
diff --git a/test/lisp/dired-aux-tests.el b/test/lisp/dired-aux-tests.el
index 694deaae4c..e70898ab74 100644
--- a/test/lisp/dired-aux-tests.el
+++ b/test/lisp/dired-aux-tests.el
@@ -154,5 +154,18 @@
     (should (string-match (regexp-quote command) (nth 0 lines)))
     (dired-test--check-highlighting (nth 0 lines) '(8))))
 
+(ert-deftest dired-guess-default ()
+  (let ((dired-guess-shell-alist-user nil)
+        (dired-guess-shell-alist-default
+         '(("\\.png\\'" "display")
+           ("\\.gif\\'" "display" "xloadimage")
+           ("\\.gif\\'" "feh")
+           ("\\.jpe?g\\'" "xloadimage"))))
+    (should (equal (dired-guess-default '("/tmp/foo.png")) "display"))
+    (should (equal (dired-guess-default '("/tmp/foo.gif"))
+                   '("display" "xloadimage" "feh")))
+    (should (equal (dired-guess-default '("/tmp/foo.png" "/tmp/foo.txt"))
+                   nil))))
+
 (provide 'dired-aux-tests)
 ;;; dired-aux-tests.el ends here
diff --git a/test/lisp/dired-x-tests.el b/test/lisp/dired-x-tests.el
index cec266b0ef..7acaa3c131 100644
--- a/test/lisp/dired-x-tests.el
+++ b/test/lisp/dired-x-tests.el
@@ -47,19 +47,6 @@
       (should (equal all-but-c
                      (sort (dired-get-marked-files 'local) #'string<))))))
 
-(ert-deftest dired-guess-default ()
-  (let ((dired-guess-shell-alist-user nil)
-        (dired-guess-shell-alist-default
-         '(("\\.png\\'" "display")
-           ("\\.gif\\'" "display" "xloadimage")
-           ("\\.gif\\'" "feh")
-           ("\\.jpe?g\\'" "xloadimage"))))
-    (should (equal (dired-guess-default '("/tmp/foo.png")) "display"))
-    (should (equal (dired-guess-default '("/tmp/foo.gif"))
-                   '("display" "xloadimage" "feh")))
-    (should (equal (dired-guess-default '("/tmp/foo.png" "/tmp/foo.txt"))
-                   nil))))
-
 (ert-deftest dired-x--string-to-number ()
   (should (= (dired-x--string-to-number "2.4K") 2457.6))
   (should (= (dired-x--string-to-number "2400") 2400))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]