summaryrefslogtreecommitdiff
path: root/lisp/dired-aux.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/dired-aux.el')
-rw-r--r--lisp/dired-aux.el148
1 files changed, 104 insertions, 44 deletions
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index 204ee13006a..f94e0537aa6 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -54,19 +54,23 @@ into this list; they also should call `dired-log' to log the errors.")
;;;###autoload
(defun dired-diff (file &optional switches)
- "Compare file at point with file FILE using `diff'.
-If called interactively, prompt for FILE. If the file at point
-has a backup file, use that as the default. If the file at point
-is a backup file, use its original. If the mark is active
-in Transient Mark mode, use the file at the mark as the default.
-\(That's the mark set by \\[set-mark-command], not by Dired's
-\\[dired-mark] command.)
-
-FILE is the first file given to `diff'. The file at point
-is the second file given to `diff'.
+ "Compare file at point with FILE using `diff'.
+If called interactively, prompt for FILE.
+If the mark is active in Transient Mark mode, use the file at the mark
+as the default for FILE. (That's the mark set by \\[set-mark-command],
+not by Dired's \\[dired-mark] command.)
+If the file at point has a backup file, use that as the default FILE.
+If the file at point is a backup file, use its original, if that exists
+and can be found. Note that customizations of `backup-directory-alist'
+and `make-backup-file-name-function' change where this function searches
+for the backup file, and affect its ability to find the original of a
+backup file.
+
+FILE is the first argument given to the `diff' function. The file at
+point is the second argument given to `diff'.
With prefix arg, prompt for second argument SWITCHES, which is
-the string of command switches for the third argument of `diff'."
+the string of command switches used as the third argument of `diff'."
(interactive
(let* ((current (dired-get-filename t))
;; Get the latest existing backup file or its original.
@@ -77,8 +81,20 @@ the string of command switches for the third argument of `diff'."
(file-at-mark (if (and transient-mark-mode mark-active)
(save-excursion (goto-char (mark t))
(dired-get-filename t t))))
+ (separate-dir (and oldf
+ (not (equal (file-name-directory oldf)
+ (dired-current-directory)))))
(default-file (or file-at-mark
- (and oldf (file-name-nondirectory oldf))))
+ ;; If the file with which to compare
+ ;; doesn't exist, or we cannot intuit it,
+ ;; we forget that name and don't show it
+ ;; as the default, as an indication to the
+ ;; user that she should type the file
+ ;; name.
+ (and (if (and oldf (file-readable-p oldf)) oldf)
+ (if separate-dir
+ oldf
+ (file-name-nondirectory oldf)))))
;; Use it as default if it's not the same as the current file,
;; and the target dir is current or there is a default file.
(default (if (and (not (equal default-file current))
@@ -87,7 +103,9 @@ the string of command switches for the third argument of `diff'."
default-file))
default-file))
(target-dir (if default
- (dired-current-directory)
+ (if separate-dir
+ (file-name-directory default)
+ (dired-current-directory))
(dired-dwim-target-directory)))
(defaults (dired-dwim-target-defaults (list current) target-dir)))
(list
@@ -279,6 +297,14 @@ List has a form of (file-name full-file-name (attribute-list))."
((eq op-symbol 'chgrp)
(system-groups)))))
(operation (concat program " " new-attribute))
+ ;; When file-name-coding-system is set to something different
+ ;; from locale-coding-system, leaving the encoding
+ ;; determination to call-process will do the wrong thing,
+ ;; because the arguments in this case are file names, not
+ ;; just some arbitrary text. (This must be bound last, to
+ ;; avoid adverse effects on any of the preceding forms.)
+ (coding-system-for-write (or file-name-coding-system
+ default-file-name-coding-system))
failures)
(setq failures
(dired-bunch-files 10000
@@ -729,26 +755,52 @@ can be produced by `dired-get-marked-files', for example."
(command (if sequentially
(substring command 0 (match-beginning 0))
command))
+ (parallel-in-background
+ (and in-background (not sequentially) (not (eq system-type 'ms-dos))))
+ (w32-shell (and (fboundp 'w32-shell-dos-semantics)
+ (w32-shell-dos-semantics)))
+ ;; The way to run a command in background in Windows shells
+ ;; is to use the START command. The /B switch means not to
+ ;; create a new window for the command.
+ (cmd-prefix (if w32-shell "start /b " ""))
+ ;; Windows shells don't support chaining with ";", they use
+ ;; "&" instead.
+ (cmd-sep (if (and (not w32-shell) (not parallel-in-background))
+ ";"
+ "&"))
(stuff-it
(if (or (string-match-p dired-star-subst-regexp command)
(string-match-p dired-quark-subst-regexp command))
(lambda (x)
- (let ((retval command))
+ (let ((retval (concat cmd-prefix command)))
(while (string-match
"\\(^\\|[ \t]\\)\\([*?]\\)\\([ \t]\\|$\\)" retval)
(setq retval (replace-match x t t retval 2)))
retval))
- (lambda (x) (concat command dired-mark-separator x)))))
+ (lambda (x) (concat cmd-prefix command dired-mark-separator x)))))
(concat
- (if on-each
- (mapconcat stuff-it (mapcar 'shell-quote-argument file-list)
- (if (and in-background (not sequentially)) "&" ";"))
- (let ((files (mapconcat 'shell-quote-argument
- file-list dired-mark-separator)))
- (if (> (length file-list) 1)
- (setq files (concat dired-mark-prefix files dired-mark-postfix)))
- (funcall stuff-it files)))
- (if in-background "&" ""))))
+ (cond (on-each
+ (format "%s%s"
+ (mapconcat stuff-it (mapcar 'shell-quote-argument file-list)
+ cmd-sep)
+ ;; POSIX shells running a list of commands in the background
+ ;; (LIST = cmd_1 & [cmd_2 & ... cmd_i & ... cmd_N &])
+ ;; return once cmd_N ends, i.e., the shell does not
+ ;; wait for cmd_i to finish before executing cmd_i+1.
+ ;; That means, running (shell-command LIST) may not show
+ ;; the output of all the commands (Bug#23206).
+ ;; Add 'wait' to force those POSIX shells to wait until
+ ;; all commands finish.
+ (or (and parallel-in-background (not w32-shell)
+ "&wait")
+ "")))
+ (t
+ (let ((files (mapconcat 'shell-quote-argument
+ file-list dired-mark-separator)))
+ (when (cdr file-list)
+ (setq files (concat dired-mark-prefix files dired-mark-postfix)))
+ (funcall stuff-it files))))
+ (or (and in-background "&") ""))))
;; This is an extra function so that it can be redefined by ange-ftp.
;;;###autoload
@@ -890,8 +942,8 @@ command with a prefix argument (the value does not matter)."
;; Solaris10 version of tar. Solaris10 becomes obsolete in 2021.
;; Same thing on AIX 7.1.
("\\.tar\\.gz\\'" "" "gzip -dc %i | tar -xv")
+ ("\\.tgz\\'" "" "gzip -dc %i | tar -xv")
("\\.gz\\'" "" "gunzip")
- ("\\.tgz\\'" ".tar" "gunzip")
("\\.Z\\'" "" "uncompress")
;; For .z, try gunzip. It might be an old gzip file,
;; or it might be from compact? pack? (which?) but gunzip handles both.
@@ -901,6 +953,7 @@ command with a prefix argument (the value does not matter)."
("\\.bz2\\'" "" "bunzip2")
("\\.xz\\'" "" "unxz")
("\\.zip\\'" "" "unzip -o -d %o %i")
+ ("\\.7z\\'" "" "7z x -aoa -o%o %i")
;; This item controls naming for compression.
("\\.tar\\'" ".tgz" nil)
;; This item controls the compression of directories
@@ -959,11 +1012,13 @@ and `dired-compress-files-alist'."
(t
(when (zerop
(dired-shell-command
- (replace-regexp-in-string
- "%o" out-file
- (replace-regexp-in-string
- "%i" (mapconcat #'file-name-nondirectory in-files " ")
- (cdr rule)))))
+ (format-spec (cdr rule)
+ `((?\o . ,(shell-quote-argument out-file))
+ (?\i . ,(mapconcat
+ (lambda (file-desc)
+ (shell-quote-argument (file-name-nondirectory
+ file-desc)))
+ in-files " "))))))
(message "Compressed %d file(s) to %s"
(length in-files)
(file-name-nondirectory out-file)))))))
@@ -996,10 +1051,12 @@ Return nil if no change in files."
(prog1 (setq newname (file-name-as-directory newname))
(dired-shell-command
(replace-regexp-in-string
- "%o" newname
+ "%o" (shell-quote-argument newname)
(replace-regexp-in-string
- "%i" file
- command))))
+ "%i" (shell-quote-argument file)
+ command
+ nil t)
+ nil t)))
;; We found an uncompression rule.
(when (not
(dired-check-process
@@ -1019,10 +1076,12 @@ Return nil if no change in files."
(default-directory (file-name-directory file)))
(dired-shell-command
(replace-regexp-in-string
- "%o" out-name
+ "%o" (shell-quote-argument out-name)
(replace-regexp-in-string
- "%i" (file-name-nondirectory file)
- (cadr suffix))))
+ "%i" (shell-quote-argument (file-name-nondirectory file))
+ (cadr suffix)
+ nil t)
+ nil t))
out-name)))
(let ((out-name (concat file ".gz")))
(and (or (not (file-exists-p out-name))
@@ -1742,13 +1801,14 @@ Optional arg HOW-TO determines how to treat the target.
(concat (if dired-one-file op1 operation) " %s to: ")
target-dir op-symbol arg rfn-list default))))
(into-dir (cond ((null how-to)
- ;; Allow DOS/Windows users to change the letter
- ;; case of a directory. If we don't test these
- ;; conditions up front, file-directory-p below
- ;; will return t because the filesystem is
- ;; case-insensitive, and Emacs will try to move
+ ;; Allow users to change the letter case of
+ ;; a directory on a case-insensitive
+ ;; filesystem. If we don't test these
+ ;; conditions up front, file-directory-p
+ ;; below will return t on a case-insensitive
+ ;; filesystem, and Emacs will try to move
;; foo -> foo/foo, which fails.
- (if (and (memq system-type '(ms-dos windows-nt cygwin))
+ (if (and (file-name-case-insensitive-p (car fn-list))
(eq op-symbol 'move)
dired-one-file
(string= (downcase
@@ -2735,7 +2795,7 @@ REGEXP should use constructs supported by your local `grep' command."
(lambda (s) (concat s "/"))
grep-find-ignored-directories)
grep-find-ignored-files))
- (xrefs (cl-mapcan
+ (xrefs (mapcan
(lambda (file)
(xref-collect-matches regexp "*" file
(and (file-directory-p file)
@@ -2785,7 +2845,7 @@ instead."
;; Local Variables:
;; byte-compile-dynamic: t
-;; generated-autoload-file: "dired.el"
+;; generated-autoload-file: "dired-loaddefs.el"
;; End:
;;; dired-aux.el ends here