Add 2012 to FSF copyright years for Emacs files
[bpt/emacs.git] / lisp / dired-x.el
index 202b4e7..f775fd9 100644 (file)
@@ -1,6 +1,6 @@
 ;;; dired-x.el --- extra Dired functionality
 
-;; Copyright (C) 1993-1994, 1997, 2001-2011 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 1997, 2001-2012 Free Software Foundation, Inc.
 
 ;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
 ;;     Lawrence R. Dodd <dodd@roebling.poly.edu>
 ;;                       ;; (dired-omit-mode 1)
 ;;                       ))
 ;;
-;; At load time dired-x.el will install itself, redefine some functions, and
-;; bind some dired keys.
+;; At load time dired-x.el will install itself and bind some dired keys.
+;; Some dired.el and dired-aux.el functions have extra features if
+;; dired-x is loaded.
 
 ;; User customization: M-x customize-group RET dired-x RET.
 
-;; When loaded this code redefines the following functions of GNU Emacs:
-;; From dired.el: dired-clean-up-after-deletion, dired-find-buffer-nocreate,
-;; and dired-initial-position.
-;; From dired-aux.el: dired-add-entry and dired-read-shell-command.
-
 ;; *Please* see the `dired-x' info pages for more details.
 
 \f
 ;;; Code:
 
-;; LOAD.
-
 ;; This is a no-op if dired-x is being loaded via `dired-load-hook',
 ;; but maybe not if a dired-x function is being autoloaded.
 (require 'dired)
 
-;; We will redefine some functions and also need some macros.
-(require 'dired-aux)
-
 ;;; User-defined variables.
 
 (defgroup dired-x nil
@@ -135,17 +126,27 @@ files not writable by you are visited read-only."
                 (other :tag "non-writable only" if-file-read-only))
   :group 'dired-x)
 
+(defcustom dired-omit-size-limit 30000
+  "Maximum size for the \"omitting\" feature.
+If nil, there is no maximum size."
+  :type '(choice (const :tag "no maximum" nil) integer)
+  :group 'dired-x)
+
 (define-minor-mode dired-omit-mode
-  "Toggle Dired-Omit mode.
-With numeric ARG, enable Dired-Omit mode if ARG is positive, disable
-otherwise.  Enabling and disabling is buffer-local.
-If enabled, \"uninteresting\" files are not listed.
-Uninteresting files are those whose filenames match regexp `dired-omit-files',
-plus those ending with extensions in `dired-omit-extensions'.
+  "Toggle omission of uninteresting files in Dired (Dired-Omit mode).
+With a prefix argument ARG, enable Dired-Omit mode if ARG is
+positive, and disable it otherwise.  If called from Lisp, enable
+the mode if ARG is omitted or nil.
+
+Dired-Omit mode is a buffer-local minor mode.  When enabled in a
+Dired buffer, Dired does not list files whose filenames match
+regexp `dired-omit-files', nor files ending with extensions in
+`dired-omit-extensions'.
 
-To enable omitting in every Dired buffer, you can put in your ~/.emacs
+To enable omitting in every Dired buffer, you can put this in
+your init file:
 
-  (add-hook 'dired-mode-hook (lambda () (dired-omit-mode 1)))
+  (add-hook 'dired-mode-hook (lambda () (dired-omit-mode)))
 
 See Info node `(dired-x) Omitting Variables' for more information."
   :group 'dired-x
@@ -154,6 +155,8 @@ See Info node `(dired-x) Omitting Variables' for more information."
       (let ((dired-omit-size-limit nil)) (dired-omit-expunge))
     (revert-buffer)))
 
+(put 'dired-omit-mode 'safe-local-variable 'booleanp)
+
 ;; For backward compatibility
 (define-obsolete-variable-alias 'dired-omit-files-p 'dired-omit-mode "22.1")
 
@@ -186,23 +189,21 @@ toggle between those two."
   :type 'boolean
   :group 'dired-x)
 
-(defcustom dired-omit-size-limit 30000
-  "Maximum size for the \"omitting\" feature.
-If nil, there is no maximum size."
-  :type '(choice (const :tag "no maximum" nil) integer)
-  :group 'dired-x)
-
 (defcustom dired-enable-local-variables t
   "Control use of local-variables lists in Dired.
-The value can be t, nil or something else.
-A value of t means local-variables lists are obeyed;
-nil means they are ignored; anything else means query.
-
 This temporarily overrides the value of `enable-local-variables' when
 listing a directory.  See also `dired-local-variables-file'."
-  :type 'boolean
+  :risky t
+  :type '(choice (const :tag "Query Unsafe" t)
+                (const :tag "Safe Only" :safe)
+                (const :tag "Do all" :all)
+                (const :tag "Ignore" nil)
+                (other :tag "Query" other))
   :group 'dired-x)
 
+(make-obsolete-variable 'dired-enable-local-variables
+                        "use a standard `dir-locals-file' instead." "24.1")
+
 (defcustom dired-guess-shell-gnutar
   (catch 'found
     (dolist (exe '("tar" "gtar"))
@@ -324,32 +325,6 @@ See also the functions:
   (dired-omit-startup))
 
 \f
-;;; BUFFER CLEANING.
-
-;; REDEFINE.
-(defun dired-clean-up-after-deletion (fn)
-  "Clean up after a deleted file or directory FN.
-Remove expanded subdir of deleted dir, if any."
-  (save-excursion (and (cdr dired-subdir-alist)
-                       (dired-goto-subdir fn)
-                       (dired-kill-subdir)))
-  ;; Offer to kill buffer of deleted file FN.
-  (when dired-clean-up-buffers-too
-    (let ((buf (get-file-buffer fn)))
-      (and buf
-           (funcall (function y-or-n-p)
-                    (format "Kill buffer of %s, too? "
-                            (file-name-nondirectory fn)))
-           (kill-buffer buf)))
-    (let ((buf-list (dired-buffers-for-dir (expand-file-name fn))))
-      (and buf-list
-           (y-or-n-p (format "Kill dired buffer%s of %s, too? "
-                             (dired-plural-s (length buf-list))
-                             (file-name-nondirectory fn)))
-           (dolist (buf buf-list)
-             (kill-buffer buf))))))
-
-\f
 ;;; EXTENSION MARKING FUNCTIONS.
 
 ;; Mark files with some extension.
@@ -465,6 +440,7 @@ move to its line in dired."
                 (dired-omit-mode)
                 (dired-goto-file file)))))))
 
+;;;###autoload
 (defun dired-jump-other-window (&optional file-name)
   "Like \\[dired-jump] (`dired-jump') but in other window."
   (interactive
@@ -574,11 +550,14 @@ This functions works by temporarily binding `dired-marker-char' to
 ;; Returns t if any work was done, nil otherwise.
 (defun dired-mark-unmarked-files (regexp msg &optional unflag-p localp)
   "Mark unmarked files matching REGEXP, displaying MSG.
-REGEXP is matched against the entire file name.
-Does not re-mark files which already have a mark.
+REGEXP is matched against the entire file name.  When called
+interactively, prompt for REGEXP.
 With prefix argument, unflag all those files.
 Optional fourth argument LOCALP is as in `dired-get-filename'."
-  (interactive "P")
+  (interactive
+   (list (dired-read-regexp
+         "Mark unmarked files matching regexp (default all): ")
+        nil current-prefix-arg nil))
   (let ((dired-marker-char (if unflag-p ?\s dired-marker-char)))
     (dired-mark-if
      (and
@@ -589,45 +568,6 @@ Optional fourth argument LOCALP is as in `dired-get-filename'."
         (and fn (string-match regexp fn))))
      msg)))
 
-;; Compiler does not get fset.
-(declare-function dired-omit-old-add-entry "dired-x")
-
-;; REDEFINE.
-;; Redefine dired-aux.el's version of `dired-add-entry'
-;; Save old defun if not already done:
-(or (fboundp 'dired-omit-old-add-entry)
-    (fset 'dired-omit-old-add-entry (symbol-function 'dired-add-entry)))
-
-;; REDEFINE.
-(defun dired-omit-new-add-entry (filename &optional marker-char relative)
-  ;; This redefines dired-aux.el's dired-add-entry to avoid calling ls for
-  ;; files that are going to be omitted anyway.
-  (if dired-omit-mode
-      ;; perhaps return t without calling ls
-      (let ((omit-re (dired-omit-regexp)))
-        (if (or (string= omit-re "")
-                (not
-                 (string-match omit-re
-                               (cond
-                                ((eq 'no-dir dired-omit-localp)
-                                 filename)
-                                ((eq t dired-omit-localp)
-                                 (dired-make-relative filename))
-                                (t
-                                 (dired-make-absolute
-                                  filename
-                                  (file-name-directory filename)))))))
-            ;; if it didn't match, go ahead and add the entry
-            (dired-omit-old-add-entry filename marker-char relative)
-          ;; dired-add-entry returns t for success, perhaps we should
-          ;; return file-exists-p
-          t))
-    ;; omitting is not turned on at all
-    (dired-omit-old-add-entry filename marker-char relative)))
-
-;; Redefine it.
-(fset 'dired-add-entry 'dired-omit-new-add-entry)
-
 \f
 ;;; VIRTUAL DIRED MODE.
 
@@ -726,7 +666,7 @@ nil."
            nil))))
 
 
-(defun dired-virtual-revert (&optional arg noconfirm)
+(defun dired-virtual-revert (&optional _arg _noconfirm)
   (if (not
        (y-or-n-p "Cannot revert a Virtual Dired buffer - switch to Real Dired mode? "))
       (error "Cannot revert a Virtual Dired buffer")
@@ -772,15 +712,26 @@ Also useful for `auto-mode-alist' like this:
                       (dired-current-directory)
                     default-directory)))
   "Alist of major modes and their opinion on `default-directory'.
-This is given as a Lisp expression to evaluate.  A resulting value of
-nil is ignored in favor of `default-directory'.")
+Each element has the form (MAJOR . EXPRESSION).
+The function `dired-default-directory' evaluates EXPRESSION to
+determine a default directory.")
+
+(put 'dired-default-directory-alist 'risky-local-variable t) ; gets eval'd
+(make-obsolete-variable 'dired-default-directory-alist
+                        "this feature is due to be removed." "24.1")
 
 (defun dired-default-directory ()
-  "Usage like variable `default-directory'.
-Knows about the special cases in variable `dired-default-directory-alist'."
+  "Return the `dired-default-directory-alist' entry for the current major-mode.
+If none, return `default-directory'."
   (or (eval (cdr (assq major-mode dired-default-directory-alist)))
       default-directory))
 
+;; It looks like this was intended to be something of a "general" feature,
+;; but it only ever seems to have been used in dired-smart-shell-command,
+;; and does not seem worth keeping around (?).
+(make-obsolete 'dired-default-directory
+               "this feature is due to be removed." "24.1")
+
 (defun dired-smart-shell-command (command &optional output-buffer error-buffer)
   "Like function `shell-command', but in the current Virtual Dired directory."
   (interactive
@@ -791,32 +742,33 @@ Knows about the special cases in variable `dired-default-directory-alist'."
                         ((eq major-mode 'dired-mode) (dired-get-filename t t))))
     current-prefix-arg
     shell-command-default-error-buffer))
-  (let ((default-directory (dired-default-directory)))
+  (let ((default-directory (or (and (eq major-mode 'dired-mode)
+                                    (dired-current-directory))
+                               default-directory)))
     (shell-command command output-buffer error-buffer)))
 
 \f
 ;;; LOCAL VARIABLES FOR DIRED BUFFERS.
 
-;; Brief Description:
-;;;
+;; Brief Description  (This feature is obsolete as of Emacs 24.1)
+;;
 ;; * `dired-extra-startup' is part of the `dired-mode-hook'.
-;;;
+;;
 ;; * `dired-extra-startup' calls `dired-hack-local-variables'
-;;;
+;;
 ;; * `dired-hack-local-variables' checks the value of
-;;;   `dired-local-variables-file'
-;;;
+;;   `dired-local-variables-file'
+;;
 ;; * Check if `dired-local-variables-file' is a non-nil string and is a
-;;;   filename found in the directory of the Dired Buffer being created.
-;;;
+;;   filename found in the directory of the Dired Buffer being created.
+;;
 ;; * If `dired-local-variables-file' satisfies the above, then temporarily
-;;;   include it in the Dired Buffer at the bottom.
-;;;
+;;   include it in the Dired Buffer at the bottom.
+;;
 ;; * Set `enable-local-variables' temporarily to the user variable
-;;;   `dired-enable-local-variables' and run `hack-local-variables' on the
-;;;   Dired Buffer.
+;;   `dired-enable-local-variables' and run `hack-local-variables' on the
+;;   Dired Buffer.
 
-;; FIXME do standard dir-locals obsolete this?
 (defcustom dired-local-variables-file (convert-standard-filename ".dired")
   "Filename, as string, containing local dired buffer variables to be hacked.
 If this file found in current directory, then it will be inserted into dired
@@ -826,57 +778,69 @@ See also `dired-enable-local-variables'."
   :type 'file
   :group 'dired)
 
+(make-obsolete-variable 'dired-local-variables-file 'dir-locals-file "24.1")
+
 (defun dired-hack-local-variables ()
   "Evaluate local variables in `dired-local-variables-file' for dired buffer."
-  (if (and dired-local-variables-file
-           (stringp dired-local-variables-file)
-           (file-exists-p dired-local-variables-file))
-      (let ((opoint (point-max))
-            buffer-read-only
-            ;; In case user has `enable-local-variables' set to nil we
-            ;; override it locally with dired's variable.
-            (enable-local-variables dired-enable-local-variables))
-        ;; Insert 'em.
-        (save-excursion
-          (goto-char opoint)
-          (insert "\^L\n")
-          (insert-file-contents dired-local-variables-file))
-        ;; Hack 'em.
-        (let ((buffer-file-name dired-local-variables-file))
-          (hack-local-variables))
-        ;; Make sure that the modeline shows the proper information.
-        (dired-sort-set-modeline)
-        ;; Delete this stuff: `eobp' is used to find last subdir by dired.el.
-        (delete-region opoint (point-max)))))
-
+  (and (stringp dired-local-variables-file)
+       (file-exists-p dired-local-variables-file)
+       (let ((opoint (point-max))
+             (inhibit-read-only t)
+             ;; In case user has `enable-local-variables' set to nil we
+             ;; override it locally with dired's variable.
+             (enable-local-variables dired-enable-local-variables))
+         ;; Insert 'em.
+         (save-excursion
+           (goto-char opoint)
+           (insert "\^L\n")
+           (insert-file-contents dired-local-variables-file))
+         ;; Hack 'em.
+         (unwind-protect
+             (let ((buffer-file-name dired-local-variables-file))
+               (hack-local-variables))
+           ;; Delete this stuff: `eobp' is used to find last subdir by dired.el.
+           (delete-region opoint (point-max)))
+         ;; Make sure that the modeline shows the proper information.
+         (dired-sort-set-modeline))))
+
+(make-obsolete 'dired-hack-local-variables
+               'hack-dir-local-variables-non-file-buffer "24.1")
+
+;; Does not seem worth a dedicated command.
+;; See the more general features in files-x.el.
 (defun dired-omit-here-always ()
-  "Create `dired-local-variables-file' for omitting and reverts directory.
-Sets `dired-omit-mode' to t in a local variables file that is readable by
-dired."
+  "Create `dir-locals-file' setting `dired-omit-mode' to t in `dired-mode'.
+If in a Dired buffer, reverts it."
   (interactive)
   (if (file-exists-p dired-local-variables-file)
-      (message "File `./%s' already exists." dired-local-variables-file)
-
-    ;; Create `dired-local-variables-file'.
-    (with-current-buffer (get-buffer-create " *dot-dired*")
-      (erase-buffer)
-      (insert "Local Variables:\ndired-omit-mode: t\nEnd:\n")
-      (write-file dired-local-variables-file)
-      (kill-buffer (current-buffer)))
-
+      (error "Old-style dired-local-variables-file `./%s' found;
+replace it with a dir-locals-file `./%s'"
+             dired-local-variables-file
+             dir-locals-file))
+  (if (file-exists-p dir-locals-file)
+      (message "File `./%s' already exists." dir-locals-file)
+    (with-temp-buffer
+      (insert "\
+\((dired-mode . ((subdirs . nil)
+                (dired-omit-mode . t))))\n")
+      (write-file dir-locals-file))
     ;; Run extra-hooks and revert directory.
-    (dired-extra-startup)
-    (dired-revert)))
+    (when (derived-mode-p 'dired-mode)
+      (hack-dir-local-variables-non-file-buffer)
+      (dired-extra-startup)
+      (dired-revert))))
+
+(make-obsolete 'dired-omit-here-always 'add-dir-local-variable "24.1")
 
 \f
 ;;; GUESS SHELL COMMAND.
 
 ;; Brief Description:
 ;;;
-;; `dired-do-shell-command' is bound to `!' by dired.el.
+;; `dired-do-shell-command' is bound to `!' by dired.el.
 ;;;
-;; * Redefine `dired-read-shell-command' so it calls
-;;;   `dired-guess-shell-command'.
+;; * `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.
@@ -903,11 +867,11 @@ dired."
 ;; NOTE: Use `gunzip -c' instead of `zcat' on `.gz' files.  Some do not
 ;; install GNU zip's version of zcat.
 
-(declare-function Man-support-local-filenames "man" ())
+(autoload 'Man-support-local-filenames "man")
 
 (defvar dired-guess-shell-alist-default
   (list
-   (list "\\.tar$"
+   (list "\\.tar\\'"
         '(if dired-guess-shell-gnutar
              (concat dired-guess-shell-gnutar " xvf")
            "tar xvf")
@@ -925,7 +889,7 @@ dired."
 
    ;; REGEXPS for compressed archives must come before the .Z rule to
    ;; be recognized:
-   (list "\\.tar\\.Z$"
+   (list "\\.tar\\.Z\\'"
         ;; Untar it.
         '(if dired-guess-shell-gnutar
              (concat dired-guess-shell-gnutar " zxvf")
@@ -935,7 +899,7 @@ dired."
                  " " dired-guess-shell-znew-switches))
 
    ;; gzip'ed archives
-   (list "\\.t\\(ar\\.\\)?gz$"
+   (list "\\.t\\(ar\\.\\)?gz\\'"
         '(if dired-guess-shell-gnutar
              (concat dired-guess-shell-gnutar " zxvf")
            (concat "gunzip -qc * | tar xvf -"))
@@ -955,7 +919,7 @@ dired."
            (concat "gunzip -qc * | tar tvf -")))
 
    ;; bzip2'ed archives
-   (list "\\.t\\(ar\\.bz2\\|bz\\)$"
+   (list "\\.t\\(ar\\.bz2\\|bz\\)\\'"
         "bunzip2 -c * | tar xvf -"
         ;; Extract files into a separate subdirectory
         '(concat "mkdir " (file-name-sans-extension file)
@@ -965,7 +929,7 @@ dired."
         "bunzip2")
 
    ;; xz'ed archives
-   (list "\\.t\\(ar\\.\\)?xz$"
+   (list "\\.t\\(ar\\.\\)?xz\\'"
         "unxz -c * | tar xvf -"
         ;; Extract files into a separate subdirectory
         '(concat "mkdir " (file-name-sans-extension file)
@@ -974,94 +938,103 @@ dired."
         ;; Optional decompression.
         "unxz")
 
-   '("\\.shar\\.Z$" "zcat * | unshar")
-   '("\\.shar\\.g?z$" "gunzip -qc * | unshar")
+   '("\\.shar\\.Z\\'" "zcat * | unshar")
+   '("\\.shar\\.g?z\\'" "gunzip -qc * | unshar")
 
-   '("\\.e?ps$" "ghostview" "xloadimage" "lpr")
-   (list "\\.e?ps\\.g?z$" "gunzip -qc * | ghostview -"
+   '("\\.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 -"
+   (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))
 
-   '("\\.patch$" "cat * | patch")
-   (list "\\.patch\\.g?z$" "gunzip -qc * | patch"
+   '("\\.patch\\'" "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"
+   (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)
-   (list "\\.\\(?:[0-9]\\|man\\)$" '(progn (require 'man)
-                                          (if (Man-support-local-filenames)
-                                              "man -l"
-                                            "cat * | tbl | nroff -man -h")))
-   (list "\\.\\(?:[0-9]\\|man\\)\\.g?z$" '(progn (require 'man)
-                                                (if (Man-support-local-filenames)
-                                                    "man -l"
-                                                  "gunzip -qc * | tbl | nroff -man -h"))
+   ;; 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"))))
+   (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")))
         ;; Optional decompression.
         '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
-   (list "\\.[0-9]\\.Z$" '(progn (require 'man)
-                                (if (Man-support-local-filenames)
-                                    "man -l"
-                                  "zcat * | tbl | nroff -man -h"))
+   (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")))
         ;; 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")
+   '("\\.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"
+   (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")
+   '("\\.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"
+   (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"))
+   '("\\.sign?\\'" "gpg --verify"))
 
   "Default alist used for shell command guessing.
 See `dired-guess-shell-alist-user'.")
@@ -1087,12 +1060,11 @@ You can set this variable in your ~/.emacs.  For example, to add rules for
 `.foo' and `.bar' files, write
 
  \(setq dired-guess-shell-alist-user
-       (list (list \"\\\\.foo\\\\'\" \"FOO-COMMAND\");; fixed rule
-              ;; possibly more rules ...
-              (list \"\\\\.bar\\\\'\";; rule with condition test
-                    '(if condition
-                          \"BAR-COMMAND-1\"
-                        \"BAR-COMMAND-2\")))\)"
+        '((\"\\\\.foo\\\\'\" \"FOO-COMMAND\")
+          (\"\\\\.bar\\\\'\"
+           (if condition
+              \"BAR-COMMAND-1\"
+            \"BAR-COMMAND-2\"))))"
   :group 'dired-x
   :type '(alist :key-type regexp :value-type (repeat sexp)))
 
@@ -1103,7 +1075,7 @@ You can set this variable in your ~/.emacs.  For example, to add rules for
   :type 'boolean)
 
 (defun dired-guess-default (files)
-  "Guess a shell commands for FILES.  Return command or list of commands.
+  "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)
@@ -1134,10 +1106,9 @@ See `dired-guess-shell-alist-user'."
 
     ;; Return commands or nil if flist is still non-nil.
     ;; Evaluate the commands in order that any logical testing will be done.
-    (cond ((not (cdr cmds))
-           (eval (car cmds))) ; single command
-          (t
-           (mapcar (function eval) cmds)))))
+    (if (cdr cmds)
+       (delete-dups (mapcar #'eval cmds))
+      (eval (car cmds)))))             ; single command
 
 (defun dired-guess-shell-command (prompt files)
   "Ask user with PROMPT for a shell command, guessing a default from FILES."
@@ -1164,23 +1135,6 @@ See `dired-guess-shell-alist-user'."
       ;; If we got a return, then return default.
       (if (equal val "") default val))))
 
-;; REDEFINE.
-;; Redefine dired-aux.el's version:
-(defun dired-read-shell-command (prompt arg files)
-  "Read a dired shell command prompting with PROMPT (using `read-shell-command').
-ARG is the prefix arg and may be used to indicate in the prompt which
-FILES are affected.
-This is an extra function so that you can redefine it."
-  (minibuffer-with-setup-hook
-      (lambda ()
-        (set (make-local-variable 'minibuffer-default-add-function)
-             'minibuffer-default-add-dired-shell-commands))
-    (dired-mark-pop-up
-     nil 'shell files
-     'dired-guess-shell-command
-     (format prompt (dired-mark-prompt arg files)) ; PROMPT
-     files)))                                      ; FILES
-
 \f
 ;;; RELATIVE SYMBOLIC LINKS.
 
@@ -1207,8 +1161,7 @@ results in
     ;; Find common initial file name components:
     (let (next)
       (while (and (setq next (string-match "/" file1 index))
-                  (setq next (1+ next))
-                  (< next (min len1 len2))
+                  (< (setq next (1+ next)) (min len1 len2))
                   ;; For the comparison, both substrings must end in
                   ;; `/', so NEXT is *one plus* the result of the
                   ;; string-match.
@@ -1233,14 +1186,15 @@ results in
           (setq count (1+ count)
                 start (1+ start)))
         ;; ... and prepend a "../" for each slash found:
-        (while (> count 0)
-          (setq count (1- count)
-                name1 (concat "../" name1)))))
+        (dotimes (_n count)
+          (setq name1 (concat "../" name1)))))
     (make-symbolic-link
      (directory-file-name name1)        ; must not link to foo/
                                         ; (trailing slash!)
      name2 ok-if-already-exists)))
 
+(autoload 'dired-do-create-files "dired-aux")
+
 ;;;###autoload
 (defun dired-do-relsymlink (&optional arg)
    "Relative symlink all marked (or next ARG) files into a directory.
@@ -1255,16 +1209,19 @@ not absolute ones like
 
 For absolute symlinks, use \\[dired-do-symlink]."
   (interactive "P")
-  (dired-do-create-files 'relsymlink (function dired-make-relative-symlink)
+  (dired-do-create-files 'relsymlink #'dired-make-relative-symlink
                            "RelSymLink" arg dired-keep-marker-relsymlink))
 
+(autoload 'dired-mark-read-regexp "dired-aux")
+(autoload 'dired-do-create-files-regexp "dired-aux")
+
 (defun dired-do-relsymlink-regexp (regexp newname &optional arg whole-name)
   "RelSymlink all marked files containing REGEXP to NEWNAME.
 See functions `dired-do-rename-regexp' and `dired-do-relsymlink'
 for more info."
   (interactive (dired-mark-read-regexp "RelSymLink"))
   (dired-do-create-files-regexp
-   (function dired-make-relative-symlink)
+   #'dired-make-relative-symlink
    "RelSymLink" arg regexp newname whole-name dired-keep-marker-relsymlink))
 
 \f
@@ -1302,52 +1259,38 @@ Remaining lines go to bottom-most window.  The number of files that can be
 displayed this way is restricted by the height of the current window and
 `window-min-height'.
 
-To keep dired buffer displayed, type \\[split-window-vertically] first.
+To keep dired buffer displayed, type \\[split-window-below] first.
 To display just marked files, type \\[delete-other-windows] first."
-
   (interactive "P")
   (dired-simultaneous-find-file (dired-get-marked-files) noselect))
 
 (defun dired-simultaneous-find-file (file-list noselect)
-
   "Visit all files in FILE-LIST and display them simultaneously.
 The current window is split across all files in FILE-LIST, as evenly as
 possible.  Remaining lines go to the bottom-most window.  The number of
 files that can be displayed this way is restricted by the height of the
 current window and the variable `window-min-height'.  With non-nil
 NOSELECT the files are merely found but not selected."
-
   ;; We don't make this function interactive because it is usually too clumsy
   ;; to specify FILE-LIST interactively unless via dired.
-
   (let (size)
-
     (if noselect
         ;; Do not select the buffer.
         (find-file-noselect (car file-list))
-
       ;; We will have to select the buffer.  Calculate and check window size.
       (setq size (/ (window-height) (length file-list)))
       (or (<= window-min-height size)
           (error "Too many files to visit simultaneously.  Try C-u prefix"))
       (find-file (car file-list)))
-
     ;; Decrement.
-    (setq file-list (cdr file-list))
-
-    (while file-list
-
+    (dolist (file (cdr file-list))
       (if noselect
           ;; Do not select the buffer.
-          (find-file-noselect (car file-list))
-
+          (find-file-noselect file)
         ;; Vertically split off a window of desired size.  Upper window will
         ;; have SIZE lines.  Select lower (larger) window.  We split it again.
         (select-window (split-window nil size))
-        (find-file (car file-list)))
-
-      ;; Decrement.
-      (setq file-list (cdr file-list)))))
+        (find-file file)))))
 
 \f
 ;;; MISCELLANEOUS COMMANDS.
@@ -1356,6 +1299,8 @@ NOSELECT the files are merely found but not selected."
 
 (declare-function Man-getpage-in-background "man" (topic))
 
+(defvar manual-program) ; from man.el
+
 (defun dired-man ()
   "Run `man' on this file."
 ;; Used also to say: "Display old buffer if buffer name matches filename."
@@ -1411,31 +1356,6 @@ Otherwise obeys the value of `dired-vm-read-only-folders'."
 \f
 ;;; MISCELLANEOUS INTERNAL FUNCTIONS.
 
-(declare-function dired-old-find-buffer-nocreate "dired-x")
-
-(or (fboundp 'dired-old-find-buffer-nocreate)
-    (fset 'dired-old-find-buffer-nocreate
-          (symbol-function 'dired-find-buffer-nocreate)))
-
-;; REDEFINE.
-;; Redefines dired.el's version of `dired-find-buffer-nocreate'
-(defun dired-find-buffer-nocreate (dirname &optional mode)
-  (if (and dired-find-subdir
-          ;; don't try to find a wildcard as a subdirectory
-          (string-equal dirname (file-name-directory dirname)))
-      (let* ((cur-buf (current-buffer))
-            (buffers (nreverse
-                      (dired-buffers-for-dir (expand-file-name dirname))))
-            (cur-buf-matches (and (memq cur-buf buffers)
-                                  ;; wildcards must match, too:
-                                  (equal dired-directory dirname))))
-       ;; We don't want to switch to the same buffer---
-       (setq buffers (delq cur-buf buffers));;need setq with delq
-       (or (car (sort buffers (function dired-buffer-more-recently-used-p)))
-           ;; ---unless it's the only possibility:
-           (and cur-buf-matches cur-buf)))
-    (dired-old-find-buffer-nocreate dirname mode)))
-
 ;; This should be a builtin
 (defun dired-buffer-more-recently-used-p (buffer1 buffer2)
   "Return t if BUFFER1 is more recently used than BUFFER2.
@@ -1467,22 +1387,29 @@ Considers buffers closer to the car of `buffer-list' to be more recent."
 ;;           (setq dired-buffers (delq elt dired-buffers)))))
 ;;     result))
 
-;; REDEFINE.
-;; Redefines dired.el's version of `dired-initial-position'
-(defun dired-initial-position (dirname)
-  "Where point should go in a new listing of DIRNAME.
-Point assumed at beginning of new subdir line.
-You may redefine this function as you wish, e.g. like in `dired-x.el'."
-  (end-of-line)
-  (if dired-find-subdir (dired-goto-subdir dirname)) ; new
-  (if dired-trivial-filenames (dired-goto-next-nontrivial-file)))
-
 \f
 ;; Does anyone use this? - lrd 6/29/93.
 ;; Apparently people do use it. - lrd 12/22/97.
+
+(with-no-warnings
+  ;; Warnings are suppressed to avoid "global/dynamic var `X' lacks a prefix".
+  ;; This is unbearably ugly, but not more than having global variables
+  ;; named size, time, name or s, however practical it can be while writing
+  ;; `dired-mark-sexp' predicates.
+  (defvar inode)
+  (defvar s)
+  (defvar mode)
+  (defvar nlink)
+  (defvar uid)
+  (defvar gid)
+  (defvar size)
+  (defvar time)
+  (defvar name)
+  (defvar sym))
+
 (defun dired-mark-sexp (predicate &optional unflag-p)
   "Mark files for which PREDICATE returns non-nil.
-With a prefix arg, unflag those files instead.
+With a prefix arg, unmark or unflag those files instead.
 
 PREDICATE is a lisp expression that can refer to the following symbols:
 
@@ -1522,130 +1449,105 @@ to mark all zero length files."
         ;; there is no file line.  Upon success, all variables are set, either
         ;; to nil or the appropriate value, so they need not be initialized.
         ;; Moves point within the current line.
-        (if (dired-move-to-filename)
-            (let (pos
-                  (mode-len 10) ; length of mode string
-                  ;; like in dired.el, but with subexpressions \1=inode, \2=s:
-                  (dired-re-inode-size "\\s *\\([0-9]*\\)\\s *\\([0-9]*\\) ?"))
-              (beginning-of-line)
-              (forward-char 2)
-              (if (looking-at dired-re-inode-size)
-                  (progn
-                    (goto-char (match-end 0))
-                    (setq inode (string-to-number (buffer-substring (match-beginning 1)
-                                                                    (match-end 1)))
-                          s (string-to-number (buffer-substring (match-beginning 2)
-                                                                (match-end 2)))))
-                (setq inode nil
-                      s nil))
-              (setq mode (buffer-substring (point) (+ mode-len (point))))
-              (forward-char mode-len)
-              (setq nlink (read (current-buffer)))
-              ;; Karsten Wenger <kw@cis.uni-muenchen.de> fixed uid.
-              (setq uid (buffer-substring (1+ (point))
-                                         (progn (forward-word 1) (point))))
-              (re-search-forward directory-listing-before-filename-regexp)
-              (goto-char (match-beginning 1))
-              (forward-char -1)
-              (setq size (string-to-number (buffer-substring (save-excursion
-                                                               (backward-word 1)
-                                                               (setq pos (point)))
-                                                             (point))))
-              (goto-char pos)
-              (backward-word 1)
-              ;; 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  (progn
-                           (if (looking-at " -> ")
-                               (buffer-substring
-                               (progn (forward-char 4) (point))
-                               (progn (end-of-line) (point)))
-                             "")))
-              t)
-          nil)
-                      (eval predicate)))
+        (dired-move-to-filename)
+        (let (pos
+              (mode-len 10) ; length of mode string
+              ;; like in dired.el, but with subexpressions \1=inode, \2=s:
+              (dired-re-inode-size "\\s *\\([0-9]*\\)\\s *\\([0-9]*\\) ?"))
+          (beginning-of-line)
+          (forward-char 2)
+          (if (looking-at dired-re-inode-size)
+              (progn
+                (goto-char (match-end 0))
+                (setq inode (string-to-number
+                             (buffer-substring (match-beginning 1)
+                                               (match-end 1)))
+                      s (string-to-number
+                         (buffer-substring (match-beginning 2)
+                                           (match-end 2)))))
+            (setq inode nil
+                  s nil))
+          (setq mode (buffer-substring (point) (+ mode-len (point))))
+          (forward-char mode-len)
+          (setq nlink (read (current-buffer)))
+          ;; Karsten Wenger <kw@cis.uni-muenchen.de> fixed uid.
+          (setq uid (buffer-substring (1+ (point))
+                                      (progn (forward-word 1) (point))))
+          (re-search-forward directory-listing-before-filename-regexp)
+          (goto-char (match-beginning 1))
+          (forward-char -1)
+          (setq size (string-to-number
+                      (buffer-substring (save-excursion
+                                          (backward-word 1)
+                                          (setq pos (point)))
+                                        (point))))
+          (goto-char pos)
+          (backward-word 1)
+          ;; 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 (looking-at " -> ")
+                        (buffer-substring (progn (forward-char 4) (point))
+                                          (line-end-position))
+                      ""))
+          t)
+        (eval predicate)))
      (format "'%s file" predicate))))
 
 \f
 ;;; FIND FILE AT POINT.
 
 (defcustom dired-x-hands-off-my-keys t
-  "Non-nil means don't bind `dired-x-find-file' over `find-file' on keyboard.
-Similarly for `dired-x-find-file-other-window' over `find-file-other-window'.
+  "Non-nil means don't remap `find-file' to `dired-x-find-file'.
+Similarly for `find-file-other-window' and `dired-x-find-file-other-window'.
 If you change this variable without using \\[customize] after `dired-x.el'
 is loaded then call \\[dired-x-bind-find-file]."
   :type 'boolean
   :initialize 'custom-initialize-default
-  :set (lambda (sym val)
-         (set sym val)
+  :set (lambda (symbol value)
+         (set symbol value)
          (dired-x-bind-find-file))
   :group 'dired-x)
 
-;; Bind `dired-x-find-file{-other-window}' over wherever
-;; `find-file{-other-window}' is bound?
 (defun dired-x-bind-find-file ()
-  "Bind `dired-x-find-file' in place of `find-file' \(or reverse\).
+  "Bind `dired-x-find-file' in place of `find-file' (or vice-versa).
 Similarly for `dired-x-find-file-other-window' and `find-file-other-window'.
-Binding direction based on `dired-x-hands-off-my-keys'.
-This function is part of `after-init-hook'."
+Binding direction based on `dired-x-hands-off-my-keys'."
   (interactive)
   (if (called-interactively-p 'interactive)
       (setq dired-x-hands-off-my-keys
             (not (y-or-n-p "Bind dired-x-find-file over find-file? "))))
-  (cond ((not dired-x-hands-off-my-keys)
-         (substitute-key-definition 'find-file
-                                    'dired-x-find-file
-                                    (current-global-map))
-         (substitute-key-definition 'find-file-other-window
-                                    'dired-x-find-file-other-window
-                                    (current-global-map)))
-        (t
-         (substitute-key-definition 'dired-x-find-file
-                                    'find-file
-                                    (current-global-map))
-         (substitute-key-definition 'dired-x-find-file-other-window
-                                    'find-file-other-window
-                                    (current-global-map))))
-  ;; Clear mini-buffer.
-  (message nil))
-
-;; Now call it so binding is correct and put on `after-init-hook' in case
-;; user changes binding.
+  (define-key (current-global-map) [remap find-file]
+    (if (not dired-x-hands-off-my-keys) 'dired-x-find-file))
+  (define-key (current-global-map) [remap find-file-other-window]
+    (if (not dired-x-hands-off-my-keys) 'dired-x-find-file-other-window)))
+
+;; Now call it so binding is correct.  This could go in the :initialize
+;; slot, but then dired-x-bind-find-file has to be defined before the
+;; defcustom, and we get free variable warnings.
 (dired-x-bind-find-file)
-(add-hook 'after-init-hook 'dired-x-bind-find-file)
 
 (defun dired-x-find-file (filename)
   "Edit file FILENAME.
-May create a new window, or reuse an existing one.
-See the function `display-buffer'.
-
-Identical to `find-file' except when called interactively, with a prefix arg
-\(e.g., \\[universal-argument]\), in which case it guesses filename near point.
-Useful for editing file mentioned in buffer you are viewing,
-or to test if that file exists.  Use minibuffer after snatching filename."
+Like `find-file', except that when called interactively with a
+prefix argument, it offers the filename near point as a default."
   (interactive (list (dired-x-read-filename-at-point "Find file: ")))
-  (find-file (expand-file-name filename)))
+  (find-file filename))
 
 (defun dired-x-find-file-other-window (filename)
   "Edit file FILENAME, in another window.
-May create a new window, or reuse an existing one.
-See the function `display-buffer'.
-
-Identical to `find-file-other-window' except when called interactively, with
-a prefix arg \(e.g., \\[universal-argument]\), in which case it guesses filename near point.
-Useful for editing file mentioned in buffer you are viewing,
-or to test if that file exists.  Use minibuffer after snatching filename."
+Like `find-file-other-window', except that when called interactively with
+a prefix argument, when it offers the filename near point as a default."
   (interactive (list (dired-x-read-filename-at-point "Find file: ")))
-  (find-file-other-window (expand-file-name filename)))
+  (find-file-other-window filename))
 
 ;;; Internal functions.
 
@@ -1653,14 +1555,14 @@ or to test if that file exists.  Use minibuffer after snatching filename."
 (defun dired-filename-at-point ()
   "Return the filename closest to point, expanded.
 Point should be in or after a filename."
-  (let ((filename-chars "-.[:alnum:]_/:$+@")
-        start end filename prefix)
-    (save-excursion
-      ;; First see if just past a filename.
-      (or (eobp)                             ; why?
-          (when (looking-at "[] \t\n[{}()]") ; whitespace or some parens
-            (skip-chars-backward " \n\t\r({[]})")
-            (or (bobp) (backward-char 1))))
+  (save-excursion
+    ;; First see if just past a filename.
+    (or (eobp)                             ; why?
+        (when (looking-at "[] \t\n[{}()]") ; whitespace or some parens
+          (skip-chars-backward " \n\t\r({[]})")
+          (or (bobp) (backward-char 1))))
+    (let ((filename-chars "-.[:alnum:]_/:$+@")
+          start prefix)
       (if (looking-at (format "[%s]" filename-chars))
           (progn
             (skip-chars-backward filename-chars)