]> code.delx.au - gnu-emacs/blob - lisp/dired.el
Merge from emacs-24; up to 2012-04-30T11:57:47Z!sdl.web@gmail.com
[gnu-emacs] / lisp / dired.el
1 ;;; dired.el --- directory-browsing commands -*- lexical-binding: t -*-
2
3 ;; Copyright (C) 1985-1986, 1992-1997, 2000-2012
4 ;; Free Software Foundation, Inc.
5
6 ;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
7 ;; Maintainer: FSF
8 ;; Keywords: files
9 ;; Package: emacs
10
11 ;; This file is part of GNU Emacs.
12
13 ;; GNU Emacs is free software: you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation, either version 3 of the License, or
16 ;; (at your option) any later version.
17
18 ;; GNU Emacs is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ;; GNU General Public License for more details.
22
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
25
26 ;;; Commentary:
27
28 ;; This is a major mode for directory browsing and editing.
29 ;; It is documented in the Emacs manual.
30
31 ;; Rewritten in 1990/1991 to add tree features, file marking and
32 ;; sorting by Sebastian Kremer <sk@thp.uni-koeln.de>.
33 ;; Finished up by rms in 1992.
34
35 ;;; Code:
36
37 (eval-when-compile (require 'cl))
38
39 ;;; Customizable variables
40
41 (defgroup dired nil
42 "Directory editing."
43 :link '(custom-manual "(emacs)Dired")
44 :group 'files)
45
46 (defgroup dired-mark nil
47 "Handling marks in Dired."
48 :prefix "dired-"
49 :group 'dired)
50
51
52 ;;;###autoload
53 (defcustom dired-listing-switches (purecopy "-al")
54 "Switches passed to `ls' for Dired. MUST contain the `l' option.
55 May contain all other options that don't contradict `-l';
56 may contain even `F', `b', `i' and `s'. See also the variable
57 `dired-ls-F-marks-symlinks' concerning the `F' switch.
58 On systems such as MS-DOS and MS-Windows, which use `ls' emulation in Lisp,
59 some of the `ls' switches are not supported; see the doc string of
60 `insert-directory' in `ls-lisp.el' for more details."
61 :type 'string
62 :group 'dired)
63
64 (defcustom dired-subdir-switches nil
65 "If non-nil, switches passed to `ls' for inserting subdirectories.
66 If nil, `dired-listing-switches' is used."
67 :group 'dired
68 :type '(choice (const :tag "Use dired-listing-switches" nil)
69 (string :tag "Switches")))
70
71 (defcustom dired-chown-program
72 (purecopy (cond ((executable-find "chown") "chown")
73 ((file-executable-p "/usr/sbin/chown") "/usr/sbin/chown")
74 ((file-executable-p "/etc/chown") "/etc/chown")
75 (t "chown")))
76 "Name of chown command (usually `chown')."
77 :group 'dired
78 :type 'file)
79
80 (defcustom dired-use-ls-dired 'unspecified
81 "Non-nil means Dired should pass the \"--dired\" option to \"ls\".
82 The special value of `unspecified' means to check explicitly, and
83 save the result in this variable. This is performed the first
84 time `dired-insert-directory' is called.
85
86 Note that if you set this option to nil, either through choice or
87 because your \"ls\" program does not support \"--dired\", Dired
88 will fail to parse some \"unusual\" file names, e.g. those with leading
89 spaces. You might want to install ls from GNU Coreutils, which does
90 support this option. Alternatively, you might want to use Emacs's
91 own emulation of \"ls\", by using:
92 \(setq ls-lisp-use-insert-directory-program nil)
93 \(require 'ls-lisp)
94 This is used by default on MS Windows, which does not have an \"ls\" program.
95 Note that `ls-lisp' does not support as many options as GNU ls, though.
96 For more details, see Info node `(emacs)ls in Lisp'."
97 :group 'dired
98 :type '(choice (const :tag "Check for --dired support" unspecified)
99 (const :tag "Do not use --dired" nil)
100 (other :tag "Use --dired" t)))
101
102 (defcustom dired-chmod-program "chmod"
103 "Name of chmod command (usually `chmod')."
104 :group 'dired
105 :type 'file)
106
107 (defcustom dired-touch-program "touch"
108 "Name of touch command (usually `touch')."
109 :group 'dired
110 :type 'file)
111
112 (defcustom dired-ls-F-marks-symlinks nil
113 "Informs Dired about how `ls -lF' marks symbolic links.
114 Set this to t if `ls' (or whatever program is specified by
115 `insert-directory-program') with `-lF' marks the symbolic link
116 itself with a trailing @ (usually the case under Ultrix).
117
118 Example: if `ln -s foo bar; ls -F bar' gives `bar -> foo', set it to
119 nil (the default), if it gives `bar@ -> foo', set it to t.
120
121 Dired checks if there is really a @ appended. Thus, if you have a
122 marking `ls' program on one host and a non-marking on another host, and
123 don't care about symbolic links which really end in a @, you can
124 always set this variable to t."
125 :type 'boolean
126 :group 'dired-mark)
127
128 (defcustom dired-trivial-filenames (purecopy "^\\.\\.?$\\|^#")
129 "Regexp of files to skip when finding first file of a directory.
130 A value of nil means move to the subdir line.
131 A value of t means move to first file."
132 :type '(choice (const :tag "Move to subdir" nil)
133 (const :tag "Move to first" t)
134 regexp)
135 :group 'dired)
136
137 (defcustom dired-keep-marker-rename t
138 ;; Use t as default so that moved files "take their markers with them".
139 "Controls marking of renamed files.
140 If t, files keep their previous marks when they are renamed.
141 If a character, renamed files (whether previously marked or not)
142 are afterward marked with that character."
143 :type '(choice (const :tag "Keep" t)
144 (character :tag "Mark"))
145 :group 'dired-mark)
146
147 (defcustom dired-keep-marker-copy ?C
148 "Controls marking of copied files.
149 If t, copied files are marked if and as the corresponding original files were.
150 If a character, copied files are unconditionally marked with that character."
151 :type '(choice (const :tag "Keep" t)
152 (character :tag "Mark"))
153 :group 'dired-mark)
154
155 (defcustom dired-keep-marker-hardlink ?H
156 "Controls marking of newly made hard links.
157 If t, they are marked if and as the files linked to were marked.
158 If a character, new links are unconditionally marked with that character."
159 :type '(choice (const :tag "Keep" t)
160 (character :tag "Mark"))
161 :group 'dired-mark)
162
163 (defcustom dired-keep-marker-symlink ?Y
164 "Controls marking of newly made symbolic links.
165 If t, they are marked if and as the files linked to were marked.
166 If a character, new links are unconditionally marked with that character."
167 :type '(choice (const :tag "Keep" t)
168 (character :tag "Mark"))
169 :group 'dired-mark)
170
171 (defcustom dired-dwim-target nil
172 "If non-nil, Dired tries to guess a default target directory.
173 This means: if there is a Dired buffer displayed in the next
174 window, use its current directory, instead of this Dired buffer's
175 current directory.
176
177 The target is used in the prompt for file copy, rename etc."
178 :type 'boolean
179 :group 'dired)
180
181 (defcustom dired-copy-preserve-time t
182 "If non-nil, Dired preserves the last-modified time in a file copy.
183 \(This works on only some systems.)"
184 :type 'boolean
185 :group 'dired)
186
187 ; These variables were deleted and the replacements are on files.el.
188 ; We leave aliases behind for back-compatibility.
189 (defvaralias 'dired-free-space-program 'directory-free-space-program)
190 (defvaralias 'dired-free-space-args 'directory-free-space-args)
191
192 ;;; Hook variables
193
194 (defcustom dired-load-hook nil
195 "Run after loading Dired.
196 You can customize key bindings or load extensions with this."
197 :group 'dired
198 :type 'hook)
199
200 (defcustom dired-mode-hook nil
201 "Run at the very end of `dired-mode'."
202 :group 'dired
203 :type 'hook)
204
205 (defcustom dired-before-readin-hook nil
206 "This hook is run before a dired buffer is read in (created or reverted)."
207 :group 'dired
208 :type 'hook)
209
210 (defcustom dired-after-readin-hook nil
211 "Hook run after each time a file or directory is read by Dired.
212 After each listing of a file or directory, this hook is run
213 with the buffer narrowed to the listing."
214 :group 'dired
215 :type 'hook)
216 ;; Note this can't simply be run inside function `dired-ls' as the hook
217 ;; functions probably depend on the dired-subdir-alist to be OK.
218
219 (defcustom dired-dnd-protocol-alist
220 '(("^file:///" . dired-dnd-handle-local-file)
221 ("^file://" . dired-dnd-handle-file)
222 ("^file:" . dired-dnd-handle-local-file))
223 "The functions to call when a drop in `dired-mode' is made.
224 See `dnd-protocol-alist' for more information. When nil, behave
225 as in other buffers. Changing this option is effective only for
226 new dired buffers."
227 :type '(choice (repeat (cons (regexp) (function)))
228 (const :tag "Behave as in other buffers" nil))
229 :version "22.1"
230 :group 'dired)
231
232 ;; Internal variables
233
234 (defvar dired-marker-char ?* ; the answer is 42
235 ;; so that you can write things like
236 ;; (let ((dired-marker-char ?X))
237 ;; ;; great code using X markers ...
238 ;; )
239 ;; For example, commands operating on two sets of files, A and B.
240 ;; Or marking files with digits 0-9. This could implicate
241 ;; concentric sets or an order for the marked files.
242 ;; The code depends on dynamic scoping on the marker char.
243 "In Dired, the current mark character.
244 This is what the do-commands look for, and what the mark-commands store.")
245
246 (defvar dired-del-marker ?D
247 "Character used to flag files for deletion.")
248
249 (defvar dired-shrink-to-fit t
250 ;; I see no reason ever to make this nil -- rms.
251 ;; (> baud-rate search-slow-speed)
252 "Non-nil means Dired shrinks the display buffer to fit the marked files.")
253
254 (defvar dired-file-version-alist)
255
256 ;;;###autoload
257 (defvar dired-directory nil
258 "The directory name or wildcard spec that this dired directory lists.
259 Local to each dired buffer. May be a list, in which case the car is the
260 directory name and the cdr is the list of files to mention.
261 The directory name must be absolute, but need not be fully expanded.")
262
263 ;; Beware of "-l;reboot" etc. See bug#3230.
264 (defun dired-safe-switches-p (switches)
265 "Return non-nil if string SWITCHES does not look risky for dired."
266 (or (not switches)
267 (and (stringp switches)
268 (< (length switches) 100) ; arbitrary
269 (string-match "\\` *-[- [:alnum:]]+\\'" switches))))
270
271 (defvar dired-actual-switches nil
272 "The value of `dired-listing-switches' used to make this buffer's text.")
273
274 (put 'dired-actual-switches 'safe-local-variable 'dired-safe-switches-p)
275
276 (defvar dired-re-inode-size "[0-9 \t]*"
277 "Regexp for optional initial inode and file size as made by `ls -i -s'.")
278
279 ;; These regexps must be tested at beginning-of-line, but are also
280 ;; used to search for next matches, so neither omitting "^" nor
281 ;; replacing "^" by "\n" (to make it slightly faster) will work.
282
283 (defvar dired-re-mark "^[^ \n]")
284 ;; "Regexp matching a marked line.
285 ;; Important: the match ends just after the marker."
286 (defvar dired-re-maybe-mark "^. ")
287 ;; The [^:] part after "d" and "l" is to avoid confusion with the
288 ;; DOS/Windows-style drive letters in directory names, like in "d:/foo".
289 (defvar dired-re-dir (concat dired-re-maybe-mark dired-re-inode-size "d[^:]"))
290 (defvar dired-re-sym (concat dired-re-maybe-mark dired-re-inode-size "l[^:]"))
291 (defvar dired-re-exe;; match ls permission string of an executable file
292 (mapconcat (function
293 (lambda (x)
294 (concat dired-re-maybe-mark dired-re-inode-size x)))
295 '("-[-r][-w][xs][-r][-w].[-r][-w]."
296 "-[-r][-w].[-r][-w][xs][-r][-w]."
297 "-[-r][-w].[-r][-w].[-r][-w][xst]")
298 "\\|"))
299 (defvar dired-re-perms "[-bcdlps][-r][-w].[-r][-w].[-r][-w].")
300 (defvar dired-re-dot "^.* \\.\\.?/?$")
301
302 ;; The subdirectory names in the next two lists are expanded.
303 (defvar dired-subdir-alist nil
304 "Association list of subdirectories and their buffer positions.
305 Each subdirectory has an element: (DIRNAME . STARTMARKER).
306 The order of elements is the reverse of the order in the buffer.
307 In simple cases, this list contains one element.")
308
309 (defvar dired-switches-alist nil
310 "Keeps track of which switches to use for inserted subdirectories.
311 This is an alist of the form (SUBDIR . SWITCHES).")
312 (make-variable-buffer-local 'dired-switches-alist)
313
314 (defvaralias 'dired-move-to-filename-regexp
315 'directory-listing-before-filename-regexp)
316
317 (defvar dired-subdir-regexp "^. \\([^\n\r]+\\)\\(:\\)[\n\r]"
318 "Regexp matching a maybe hidden subdirectory line in `ls -lR' output.
319 Subexpression 1 is the subdirectory proper, no trailing colon.
320 The match starts at the beginning of the line and ends after the end
321 of the line (\\n or \\r).
322 Subexpression 2 must end right before the \\n or \\r.")
323
324 (defgroup dired-faces nil
325 "Faces used by Dired."
326 :group 'dired
327 :group 'faces)
328
329 (defface dired-header
330 '((t (:inherit font-lock-type-face)))
331 "Face used for directory headers."
332 :group 'dired-faces
333 :version "22.1")
334 (defvar dired-header-face 'dired-header
335 "Face name used for directory headers.")
336
337 (defface dired-mark
338 '((t (:inherit font-lock-constant-face)))
339 "Face used for dired marks."
340 :group 'dired-faces
341 :version "22.1")
342 (defvar dired-mark-face 'dired-mark
343 "Face name used for dired marks.")
344
345 (defface dired-marked
346 '((t (:inherit warning)))
347 "Face used for marked files."
348 :group 'dired-faces
349 :version "22.1")
350 (defvar dired-marked-face 'dired-marked
351 "Face name used for marked files.")
352
353 (defface dired-flagged
354 '((t (:inherit error)))
355 "Face used for files flagged for deletion."
356 :group 'dired-faces
357 :version "22.1")
358 (defvar dired-flagged-face 'dired-flagged
359 "Face name used for files flagged for deletion.")
360
361 (defface dired-warning
362 ;; Inherit from font-lock-warning-face since with min-colors 8
363 ;; font-lock-comment-face is not colored any more.
364 '((t (:inherit font-lock-warning-face)))
365 "Face used to highlight a part of a buffer that needs user attention."
366 :group 'dired-faces
367 :version "22.1")
368 (defvar dired-warning-face 'dired-warning
369 "Face name used for a part of a buffer that needs user attention.")
370
371 (defface dired-perm-write
372 '((((type w32 pc)) :inherit default) ;; These default to rw-rw-rw.
373 ;; Inherit from font-lock-comment-delimiter-face since with min-colors 8
374 ;; font-lock-comment-face is not colored any more.
375 (t (:inherit font-lock-comment-delimiter-face)))
376 "Face used to highlight permissions of group- and world-writable files."
377 :group 'dired-faces
378 :version "22.2")
379 (defvar dired-perm-write-face 'dired-perm-write
380 "Face name used for permissions of group- and world-writable files.")
381
382 (defface dired-directory
383 '((t (:inherit font-lock-function-name-face)))
384 "Face used for subdirectories."
385 :group 'dired-faces
386 :version "22.1")
387 (defvar dired-directory-face 'dired-directory
388 "Face name used for subdirectories.")
389
390 (defface dired-symlink
391 '((t (:inherit font-lock-keyword-face)))
392 "Face used for symbolic links."
393 :group 'dired-faces
394 :version "22.1")
395 (defvar dired-symlink-face 'dired-symlink
396 "Face name used for symbolic links.")
397
398 (defface dired-ignored
399 '((t (:inherit shadow)))
400 "Face used for files suffixed with `completion-ignored-extensions'."
401 :group 'dired-faces
402 :version "22.1")
403 (defvar dired-ignored-face 'dired-ignored
404 "Face name used for files suffixed with `completion-ignored-extensions'.")
405
406 (defvar dired-font-lock-keywords
407 (list
408 ;;
409 ;; Dired marks.
410 (list dired-re-mark '(0 dired-mark-face))
411 ;;
412 ;; We make heavy use of MATCH-ANCHORED, since the regexps don't identify the
413 ;; file name itself. We search for Dired defined regexps, and then use the
414 ;; Dired defined function `dired-move-to-filename' before searching for the
415 ;; simple regexp ".+". It is that regexp which matches the file name.
416 ;;
417 ;; Marked files.
418 (list (concat "^[" (char-to-string dired-marker-char) "]")
419 '(".+" (dired-move-to-filename) nil (0 dired-marked-face)))
420 ;;
421 ;; Flagged files.
422 (list (concat "^[" (char-to-string dired-del-marker) "]")
423 '(".+" (dired-move-to-filename) nil (0 dired-flagged-face)))
424 ;; People who are paranoid about security would consider this more
425 ;; important than other things such as whether it is a directory.
426 ;; But we don't want to encourage paranoia, so our default
427 ;; should be what's most useful for non-paranoids. -- rms.
428 ;;; ;;
429 ;;; ;; Files that are group or world writable.
430 ;;; (list (concat dired-re-maybe-mark dired-re-inode-size
431 ;;; "\\([-d]\\(....w....\\|.......w.\\)\\)")
432 ;;; '(1 dired-warning-face)
433 ;;; '(".+" (dired-move-to-filename) nil (0 dired-warning-face)))
434 ;; However, we don't need to highlight the file name, only the
435 ;; permissions, to win generally. -- fx.
436 ;; Fixme: we could also put text properties on the permission
437 ;; fields with keymaps to frob the permissions, somewhat a la XEmacs.
438 (list (concat dired-re-maybe-mark dired-re-inode-size
439 "[-d]....\\(w\\)....") ; group writable
440 '(1 dired-perm-write-face))
441 (list (concat dired-re-maybe-mark dired-re-inode-size
442 "[-d].......\\(w\\).") ; world writable
443 '(1 dired-perm-write-face))
444 ;;
445 ;; Subdirectories.
446 (list dired-re-dir
447 '(".+" (dired-move-to-filename) nil (0 dired-directory-face)))
448 ;;
449 ;; Symbolic links.
450 (list dired-re-sym
451 '(".+" (dired-move-to-filename) nil (0 dired-symlink-face)))
452 ;;
453 ;; Files suffixed with `completion-ignored-extensions'.
454 '(eval .
455 ;; It is quicker to first find just an extension, then go back to the
456 ;; start of that file name. So we do this complex MATCH-ANCHORED form.
457 (list (concat "\\(" (regexp-opt completion-ignored-extensions) "\\|#\\)$")
458 '(".+" (dired-move-to-filename) nil (0 dired-ignored-face))))
459 ;;
460 ;; Files suffixed with `completion-ignored-extensions'
461 ;; plus a character put in by -F.
462 '(eval .
463 (list (concat "\\(" (regexp-opt completion-ignored-extensions)
464 "\\|#\\)[*=|]$")
465 '(".+" (progn
466 (end-of-line)
467 ;; If the last character is not part of the filename,
468 ;; move back to the start of the filename
469 ;; so it can be fontified.
470 ;; Otherwise, leave point at the end of the line;
471 ;; that way, nothing is fontified.
472 (unless (get-text-property (1- (point)) 'mouse-face)
473 (dired-move-to-filename)))
474 nil (0 dired-ignored-face))))
475 ;;
476 ;; Explicitly put the default face on file names ending in a colon to
477 ;; avoid fontifying them as directory header.
478 (list (concat dired-re-maybe-mark dired-re-inode-size dired-re-perms ".*:$")
479 '(".+" (dired-move-to-filename) nil (0 'default)))
480 ;;
481 ;; Directory headers.
482 (list dired-subdir-regexp '(1 dired-header-face))
483 )
484 "Additional expressions to highlight in Dired mode.")
485
486 (defvar dnd-protocol-alist)
487 \f
488 ;;; Macros must be defined before they are used, for the byte compiler.
489
490 (defmacro dired-mark-if (predicate msg)
491 "Mark all files for which PREDICATE evals to non-nil.
492 PREDICATE is evaluated on each line, with point at beginning of line.
493 MSG is a noun phrase for the type of files being marked.
494 It should end with a noun that can be pluralized by adding `s'.
495 Return value is the number of files marked, or nil if none were marked."
496 `(let ((inhibit-read-only t) count)
497 (save-excursion
498 (setq count 0)
499 (when ,msg
500 (message "%s %ss%s..."
501 (cond ((eq dired-marker-char ?\040) "Unmarking")
502 ((eq dired-del-marker dired-marker-char)
503 "Flagging")
504 (t "Marking"))
505 ,msg
506 (if (eq dired-del-marker dired-marker-char)
507 " for deletion"
508 "")))
509 (goto-char (point-min))
510 (while (not (eobp))
511 (if ,predicate
512 (progn
513 (delete-char 1)
514 (insert dired-marker-char)
515 (setq count (1+ count))))
516 (forward-line 1))
517 (if ,msg (message "%s %s%s %s%s."
518 count
519 ,msg
520 (dired-plural-s count)
521 (if (eq dired-marker-char ?\040) "un" "")
522 (if (eq dired-marker-char dired-del-marker)
523 "flagged" "marked"))))
524 (and (> count 0) count)))
525
526 (defmacro dired-map-over-marks (body arg &optional show-progress
527 distinguish-one-marked)
528 "Eval BODY with point on each marked line. Return a list of BODY's results.
529 If no marked file could be found, execute BODY on the current
530 line. ARG, if non-nil, specifies the files to use instead of the
531 marked files.
532
533 If ARG is an integer, use the next ARG (or previous -ARG, if
534 ARG<0) files. In that case, point is dragged along. This is so
535 that commands on the next ARG (instead of the marked) files can
536 be chained easily.
537 For any other non-nil value of ARG, use the current file.
538
539 If optional third arg SHOW-PROGRESS evaluates to non-nil,
540 redisplay the dired buffer after each file is processed.
541
542 No guarantee is made about the position on the marked line. BODY
543 must ensure this itself if it depends on this.
544
545 Search starts at the beginning of the buffer, thus the car of the
546 list corresponds to the line nearest to the buffer's bottom.
547 This is also true for (positive and negative) integer values of
548 ARG.
549
550 BODY should not be too long as it is expanded four times.
551
552 If DISTINGUISH-ONE-MARKED is non-nil, then if we find just one
553 marked file, return (t FILENAME) instead of (FILENAME)."
554 ;;
555 ;;Warning: BODY must not add new lines before point - this may cause an
556 ;;endless loop.
557 ;;This warning should not apply any longer, sk 2-Sep-1991 14:10.
558 `(prog1
559 (let ((inhibit-read-only t) case-fold-search found results)
560 (if ,arg
561 (if (integerp ,arg)
562 (progn ;; no save-excursion, want to move point.
563 (dired-repeat-over-lines
564 ,arg
565 (function (lambda ()
566 (if ,show-progress (sit-for 0))
567 (setq results (cons ,body results)))))
568 (if (< ,arg 0)
569 (nreverse results)
570 results))
571 ;; non-nil, non-integer ARG means use current file:
572 (list ,body))
573 (let ((regexp (dired-marker-regexp)) next-position)
574 (save-excursion
575 (goto-char (point-min))
576 ;; remember position of next marked file before BODY
577 ;; can insert lines before the just found file,
578 ;; confusing us by finding the same marked file again
579 ;; and again and...
580 (setq next-position (and (re-search-forward regexp nil t)
581 (point-marker))
582 found (not (null next-position)))
583 (while next-position
584 (goto-char next-position)
585 (if ,show-progress (sit-for 0))
586 (setq results (cons ,body results))
587 ;; move after last match
588 (goto-char next-position)
589 (forward-line 1)
590 (set-marker next-position nil)
591 (setq next-position (and (re-search-forward regexp nil t)
592 (point-marker)))))
593 (if (and ,distinguish-one-marked (= (length results) 1))
594 (setq results (cons t results)))
595 (if found
596 results
597 (list ,body)))))
598 ;; save-excursion loses, again
599 (dired-move-to-filename)))
600
601 (defun dired-get-marked-files (&optional localp arg filter distinguish-one-marked)
602 "Return the marked files' names as list of strings.
603 The list is in the same order as the buffer, that is, the car is the
604 first marked file.
605 Values returned are normally absolute file names.
606 Optional arg LOCALP as in `dired-get-filename'.
607 Optional second argument ARG, if non-nil, specifies files near
608 point instead of marked files. It usually comes from the prefix
609 argument.
610 If ARG is an integer, use the next ARG files.
611 Any other non-nil value means to use the current file instead.
612 Optional third argument FILTER, if non-nil, is a function to select
613 some of the files--those for which (funcall FILTER FILENAME) is non-nil.
614
615 If DISTINGUISH-ONE-MARKED is non-nil, then if we find just one marked file,
616 return (t FILENAME) instead of (FILENAME).
617 Don't use that together with FILTER."
618 (let* ((all-of-them
619 (save-excursion
620 (dired-map-over-marks
621 (dired-get-filename localp)
622 arg nil distinguish-one-marked)))
623 result)
624 (if (not filter)
625 (if (and distinguish-one-marked (eq (car all-of-them) t))
626 all-of-them
627 (nreverse all-of-them))
628 (dolist (file all-of-them)
629 (if (funcall filter file)
630 (push file result)))
631 result)))
632 \f
633 ;; The dired command
634
635 (defun dired-read-dir-and-switches (str)
636 ;; For use in interactive.
637 (reverse (list
638 (if current-prefix-arg
639 (read-string "Dired listing switches: "
640 dired-listing-switches))
641 ;; If a dialog is used, call `read-directory-name' so the
642 ;; dialog code knows we want directories. Some dialogs
643 ;; can only select directories or files when popped up,
644 ;; not both. If no dialog is used, call `read-file-name'
645 ;; because the user may want completion of file names for
646 ;; use in a wildcard pattern.
647 (if (next-read-file-uses-dialog-p)
648 (read-directory-name (format "Dired %s(directory): " str)
649 nil default-directory nil)
650 (read-file-name (format "Dired %s(directory): " str)
651 nil default-directory nil)))))
652
653 ;; We want to switch to a more sophisticated version of
654 ;; dired-read-dir-and-switches like the following, if there is a way
655 ;; to make it more intuitive. See bug#1285.
656
657 ;; (defun dired-read-dir-and-switches (str)
658 ;; ;; For use in interactive.
659 ;; (reverse
660 ;; (list
661 ;; (if current-prefix-arg
662 ;; (read-string "Dired listing switches: "
663 ;; dired-listing-switches))
664 ;; ;; If a dialog is about to be used, call read-directory-name so
665 ;; ;; the dialog code knows we want directories. Some dialogs can
666 ;; ;; only select directories or files when popped up, not both.
667 ;; (if (next-read-file-uses-dialog-p)
668 ;; (read-directory-name (format "Dired %s(directory): " str)
669 ;; nil default-directory nil)
670 ;; (let ((cie ()))
671 ;; (dolist (ext completion-ignored-extensions)
672 ;; (if (eq ?/ (aref ext (1- (length ext)))) (push ext cie)))
673 ;; (setq cie (concat (regexp-opt cie "\\(?:") "\\'"))
674 ;; (let* ((default (and buffer-file-name
675 ;; (abbreviate-file-name buffer-file-name)))
676 ;; (cie cie)
677 ;; (completion-table
678 ;; ;; We need a mix of read-file-name and
679 ;; ;; read-directory-name so that completion to directories
680 ;; ;; is preferred, but if the user wants to enter a global
681 ;; ;; pattern, he can still use completion on filenames to
682 ;; ;; help him write the pattern.
683 ;; ;; Essentially, we want to use
684 ;; ;; (completion-table-with-predicate
685 ;; ;; 'read-file-name-internal 'file-directory-p nil)
686 ;; ;; but that doesn't work because read-file-name-internal
687 ;; ;; does not obey its `predicate' argument.
688 ;; (completion-table-in-turn
689 ;; (lambda (str pred action)
690 ;; (let ((read-file-name-predicate
691 ;; (lambda (f)
692 ;; (and (not (member f '("./" "../")))
693 ;; ;; Hack! Faster than file-directory-p!
694 ;; (eq (aref f (1- (length f))) ?/)
695 ;; (not (string-match cie f))))))
696 ;; (complete-with-action
697 ;; action 'read-file-name-internal str nil)))
698 ;; 'read-file-name-internal)))
699 ;; (minibuffer-with-setup-hook
700 ;; (lambda ()
701 ;; (setq minibuffer-default default)
702 ;; (setq minibuffer-completion-table completion-table))
703 ;; (read-file-name (format "Dired %s(directory): " str)
704 ;; nil default-directory nil))))))))
705
706 (defun dired-file-name-at-point ()
707 "Try to get a file name at point in the current dired buffer.
708 This hook is intended to be put in `file-name-at-point-functions'."
709 (let ((filename (dired-get-filename nil t)))
710 (when filename
711 (if (file-directory-p filename)
712 (file-name-as-directory (abbreviate-file-name filename))
713 (abbreviate-file-name filename)))))
714
715 ;;;###autoload (define-key ctl-x-map "d" 'dired)
716 ;;;###autoload
717 (defun dired (dirname &optional switches)
718 "\"Edit\" directory DIRNAME--delete, rename, print, etc. some files in it.
719 Optional second argument SWITCHES specifies the `ls' options used.
720 \(Interactively, use a prefix argument to be able to specify SWITCHES.)
721 Dired displays a list of files in DIRNAME (which may also have
722 shell wildcards appended to select certain files). If DIRNAME is a cons,
723 its first element is taken as the directory name and the rest as an explicit
724 list of files to make directory entries for.
725 \\<dired-mode-map>\
726 You can flag files for deletion with \\[dired-flag-file-deletion] and then
727 delete them by typing \\[dired-do-flagged-delete].
728 Type \\[describe-mode] after entering Dired for more info.
729
730 If DIRNAME is already in a dired buffer, that buffer is used without refresh."
731 ;; Cannot use (interactive "D") because of wildcards.
732 (interactive (dired-read-dir-and-switches ""))
733 (switch-to-buffer (dired-noselect dirname switches)))
734
735 ;;;###autoload (define-key ctl-x-4-map "d" 'dired-other-window)
736 ;;;###autoload
737 (defun dired-other-window (dirname &optional switches)
738 "\"Edit\" directory DIRNAME. Like `dired' but selects in another window."
739 (interactive (dired-read-dir-and-switches "in other window "))
740 (switch-to-buffer-other-window (dired-noselect dirname switches)))
741
742 ;;;###autoload (define-key ctl-x-5-map "d" 'dired-other-frame)
743 ;;;###autoload
744 (defun dired-other-frame (dirname &optional switches)
745 "\"Edit\" directory DIRNAME. Like `dired' but makes a new frame."
746 (interactive (dired-read-dir-and-switches "in other frame "))
747 (switch-to-buffer-other-frame (dired-noselect dirname switches)))
748
749 ;;;###autoload
750 (defun dired-noselect (dir-or-list &optional switches)
751 "Like `dired' but returns the dired buffer as value, does not select it."
752 (or dir-or-list (setq dir-or-list default-directory))
753 ;; This loses the distinction between "/foo/*/" and "/foo/*" that
754 ;; some shells make:
755 (let (dirname initially-was-dirname)
756 (if (consp dir-or-list)
757 (setq dirname (car dir-or-list))
758 (setq dirname dir-or-list))
759 (setq initially-was-dirname
760 (string= (file-name-as-directory dirname) dirname))
761 (setq dirname (abbreviate-file-name
762 (expand-file-name (directory-file-name dirname))))
763 (if find-file-visit-truename
764 (setq dirname (file-truename dirname)))
765 ;; If the argument was syntactically a directory name not a file name,
766 ;; or if it happens to name a file that is a directory,
767 ;; convert it syntactically to a directory name.
768 ;; The reason for checking initially-was-dirname
769 ;; and not just file-directory-p
770 ;; is that file-directory-p is slow over ftp.
771 (if (or initially-was-dirname (file-directory-p dirname))
772 (setq dirname (file-name-as-directory dirname)))
773 (if (consp dir-or-list)
774 (setq dir-or-list (cons dirname (cdr dir-or-list)))
775 (setq dir-or-list dirname))
776 (dired-internal-noselect dir-or-list switches)))
777
778 ;; The following is an internal dired function. It returns non-nil if
779 ;; the directory visited by the current dired buffer has changed on
780 ;; disk. DIRNAME should be the directory name of that directory.
781 (defun dired-directory-changed-p (dirname)
782 (not (let ((attributes (file-attributes dirname))
783 (modtime (visited-file-modtime)))
784 (or (eq modtime 0)
785 (not (eq (car attributes) t))
786 (equal (nth 5 attributes) modtime)))))
787
788 (defun dired-buffer-stale-p (&optional noconfirm)
789 "Return non-nil if current dired buffer needs updating.
790 If NOCONFIRM is non-nil, then this function always returns nil
791 for a remote directory. This feature is used by Auto Revert Mode."
792 (let ((dirname
793 (if (consp dired-directory) (car dired-directory) dired-directory)))
794 (and (stringp dirname)
795 (not (when noconfirm (file-remote-p dirname)))
796 (file-readable-p dirname)
797 ;; Do not auto-revert when the dired buffer can be currently
798 ;; written by the user as in `wdired-mode'.
799 buffer-read-only
800 (dired-directory-changed-p dirname))))
801
802 (defcustom dired-auto-revert-buffer nil
803 "Automatically revert dired buffer on revisiting.
804 If t, revisiting an existing dired buffer automatically reverts it.
805 If its value is a function, call this function with the directory
806 name as single argument and revert the buffer if it returns non-nil.
807 Otherwise, a message offering to revert the changed dired buffer
808 is displayed.
809 Note that this is not the same as `auto-revert-mode' that
810 periodically reverts at specified time intervals."
811 :type '(choice
812 (const :tag "Don't revert" nil)
813 (const :tag "Always revert visited dired buffer" t)
814 (const :tag "Revert changed dired buffer" dired-directory-changed-p)
815 (function :tag "Predicate function"))
816 :group 'dired
817 :version "23.2")
818
819 (defun dired-internal-noselect (dir-or-list &optional switches mode)
820 ;; If there is an existing dired buffer for DIRNAME, just leave
821 ;; buffer as it is (don't even call dired-revert).
822 ;; This saves time especially for deep trees or with ange-ftp.
823 ;; The user can type `g' easily, and it is more consistent with find-file.
824 ;; But if SWITCHES are given they are probably different from the
825 ;; buffer's old value, so call dired-sort-other, which does
826 ;; revert the buffer.
827 ;; A pity we can't possibly do "Directory has changed - refresh? "
828 ;; like find-file does.
829 ;; Optional argument MODE is passed to dired-find-buffer-nocreate,
830 ;; see there.
831 (let* ((old-buf (current-buffer))
832 (dirname (if (consp dir-or-list) (car dir-or-list) dir-or-list))
833 ;; Look for an existing buffer.
834 (buffer (dired-find-buffer-nocreate dirname mode))
835 ;; Note that buffer already is in dired-mode, if found.
836 (new-buffer-p (null buffer)))
837 (or buffer
838 (setq buffer (create-file-buffer (directory-file-name dirname))))
839 (set-buffer buffer)
840 (if (not new-buffer-p) ; existing buffer ...
841 (cond (switches ; ... but new switches
842 ;; file list may have changed
843 (setq dired-directory dir-or-list)
844 ;; this calls dired-revert
845 (dired-sort-other switches))
846 ;; Always revert regardless of whether it has changed or not.
847 ((eq dired-auto-revert-buffer t)
848 (revert-buffer))
849 ;; Revert when predicate function returns non-nil.
850 ((functionp dired-auto-revert-buffer)
851 (when (funcall dired-auto-revert-buffer dirname)
852 (revert-buffer)
853 (message "Changed directory automatically updated")))
854 ;; If directory has changed on disk, offer to revert.
855 ((when (dired-directory-changed-p dirname)
856 (message "%s"
857 (substitute-command-keys
858 "Directory has changed on disk; type \\[revert-buffer] to update Dired")))))
859 ;; Else a new buffer
860 (setq default-directory
861 ;; We can do this unconditionally
862 ;; because dired-noselect ensures that the name
863 ;; is passed in directory name syntax
864 ;; if it was the name of a directory at all.
865 (file-name-directory dirname))
866 (or switches (setq switches dired-listing-switches))
867 (if mode (funcall mode)
868 (dired-mode dir-or-list switches))
869 ;; default-directory and dired-actual-switches are set now
870 ;; (buffer-local), so we can call dired-readin:
871 (let ((failed t))
872 (unwind-protect
873 (progn (dired-readin)
874 (setq failed nil))
875 ;; dired-readin can fail if parent directories are inaccessible.
876 ;; Don't leave an empty buffer around in that case.
877 (if failed (kill-buffer buffer))))
878 (goto-char (point-min))
879 (dired-initial-position dirname))
880 (set-buffer old-buf)
881 buffer))
882
883 (defvar dired-buffers nil
884 ;; Enlarged by dired-advertise
885 ;; Queried by function dired-buffers-for-dir. When this detects a
886 ;; killed buffer, it is removed from this list.
887 "Alist of expanded directories and their associated dired buffers.")
888
889 (defvar dired-find-subdir)
890
891 ;; FIXME add a doc-string, and document dired-x extensions.
892 (defun dired-find-buffer-nocreate (dirname &optional mode)
893 ;; This differs from dired-buffers-for-dir in that it does not consider
894 ;; subdirs of default-directory and searches for the first match only.
895 ;; Also, the major mode must be MODE.
896 (if (and (featurep 'dired-x)
897 dired-find-subdir
898 ;; Don't try to find a wildcard as a subdirectory.
899 (string-equal dirname (file-name-directory dirname)))
900 (let* ((cur-buf (current-buffer))
901 (buffers (nreverse
902 (dired-buffers-for-dir (expand-file-name dirname))))
903 (cur-buf-matches (and (memq cur-buf buffers)
904 ;; Wildcards must match, too:
905 (equal dired-directory dirname))))
906 ;; We don't want to switch to the same buffer---
907 (setq buffers (delq cur-buf buffers))
908 (or (car (sort buffers #'dired-buffer-more-recently-used-p))
909 ;; ---unless it's the only possibility:
910 (and cur-buf-matches cur-buf)))
911 ;; No dired-x, or dired-find-subdir nil.
912 (setq dirname (expand-file-name dirname))
913 (let (found (blist dired-buffers)) ; was (buffer-list)
914 (or mode (setq mode 'dired-mode))
915 (while blist
916 (if (null (buffer-name (cdr (car blist))))
917 (setq blist (cdr blist))
918 (with-current-buffer (cdr (car blist))
919 (if (and (eq major-mode mode)
920 dired-directory ;; nil during find-alternate-file
921 (equal dirname
922 (expand-file-name
923 (if (consp dired-directory)
924 (car dired-directory)
925 dired-directory))))
926 (setq found (cdr (car blist))
927 blist nil)
928 (setq blist (cdr blist))))))
929 found)))
930
931 \f
932 ;; Read in a new dired buffer
933
934 (defun dired-readin ()
935 "Read in a new dired buffer.
936 Differs from `dired-insert-subdir' in that it accepts
937 wildcards, erases the buffer, and builds the subdir-alist anew
938 \(including making it buffer-local and clearing it first)."
939
940 ;; default-directory and dired-actual-switches must be buffer-local
941 ;; and initialized by now.
942 (let (dirname
943 ;; This makes readin much much faster.
944 ;; In particular, it prevents the font lock hook from running
945 ;; until the directory is all read in.
946 (inhibit-modification-hooks t))
947 (if (consp dired-directory)
948 (setq dirname (car dired-directory))
949 (setq dirname dired-directory))
950 (setq dirname (expand-file-name dirname))
951 (save-excursion
952 ;; This hook which may want to modify dired-actual-switches
953 ;; based on dired-directory, e.g. with ange-ftp to a SysV host
954 ;; where ls won't understand -Al switches.
955 (run-hooks 'dired-before-readin-hook)
956 (if (consp buffer-undo-list)
957 (setq buffer-undo-list nil))
958 (make-local-variable 'file-name-coding-system)
959 (setq file-name-coding-system
960 (or coding-system-for-read file-name-coding-system))
961 (let ((inhibit-read-only t)
962 ;; Don't make undo entries for readin.
963 (buffer-undo-list t))
964 (widen)
965 (erase-buffer)
966 (dired-readin-insert))
967 (goto-char (point-min))
968 ;; Must first make alist buffer local and set it to nil because
969 ;; dired-build-subdir-alist will call dired-clear-alist first
970 (set (make-local-variable 'dired-subdir-alist) nil)
971 (dired-build-subdir-alist)
972 (let ((attributes (file-attributes dirname)))
973 (if (eq (car attributes) t)
974 (set-visited-file-modtime (nth 5 attributes))))
975 (set-buffer-modified-p nil)
976 ;; No need to narrow since the whole buffer contains just
977 ;; dired-readin's output, nothing else. The hook can
978 ;; successfully use dired functions (e.g. dired-get-filename)
979 ;; as the subdir-alist has been built in dired-readin.
980 (run-hooks 'dired-after-readin-hook))))
981
982 ;; Subroutines of dired-readin
983
984 (defun dired-readin-insert ()
985 ;; Insert listing for the specified dir (and maybe file list)
986 ;; already in dired-directory, assuming a clean buffer.
987 (let (dir file-list)
988 (if (consp dired-directory)
989 (setq dir (car dired-directory)
990 file-list (cdr dired-directory))
991 (setq dir dired-directory
992 file-list nil))
993 (setq dir (expand-file-name dir))
994 (if (and (equal "" (file-name-nondirectory dir))
995 (not file-list))
996 ;; If we are reading a whole single directory...
997 (dired-insert-directory dir dired-actual-switches nil nil t)
998 (if (not (file-readable-p
999 (directory-file-name (file-name-directory dir))))
1000 (error "Directory %s inaccessible or nonexistent" dir)
1001 ;; Else treat it as a wildcard spec
1002 ;; unless we have an explicit list of files.
1003 (dired-insert-directory dir dired-actual-switches
1004 file-list (not file-list) t)))))
1005
1006 (defun dired-align-file (beg end)
1007 "Align the fields of a file to the ones of surrounding lines.
1008 BEG..END is the line where the file info is located."
1009 ;; Some versions of ls try to adjust the size of each field so as to just
1010 ;; hold the largest element ("largest" in the current invocation, of
1011 ;; course). So when a single line is output, the size of each field is
1012 ;; just big enough for that one output. Thus when dired refreshes one
1013 ;; line, the alignment if this line w.r.t the rest is messed up because
1014 ;; the fields of that one line will generally be smaller.
1015 ;;
1016 ;; To work around this problem, we here add spaces to try and
1017 ;; re-align the fields as needed. Since this is purely aesthetic,
1018 ;; it is of utmost importance that it doesn't mess up anything like
1019 ;; `dired-move-to-filename'. To this end, we limit ourselves to
1020 ;; adding spaces only, and to only add them at places where there
1021 ;; was already at least one space. This way, as long as
1022 ;; `directory-listing-before-filename-regexp' always matches spaces
1023 ;; with "*" or "+", we know we haven't made anything worse. There
1024 ;; is one spot where the exact number of spaces is important, which
1025 ;; is just before the actual filename, so we refrain from adding
1026 ;; spaces there (and within the filename as well, of course).
1027 (save-excursion
1028 (let (file file-col other other-col)
1029 ;; Check that there is indeed a file, and that there is another adjacent
1030 ;; file with which to align, and that additional spaces are needed to
1031 ;; align the filenames.
1032 (when (and (setq file (progn (goto-char beg)
1033 (dired-move-to-filename nil end)))
1034 (setq file-col (current-column))
1035 (setq other
1036 (or (and (goto-char beg)
1037 (zerop (forward-line -1))
1038 (dired-move-to-filename))
1039 (and (goto-char beg)
1040 (zerop (forward-line 1))
1041 (dired-move-to-filename))))
1042 (setq other-col (current-column))
1043 (/= file other)
1044 ;; Make sure there is some work left to do.
1045 (> other-col file-col))
1046 ;; If we've only looked at the line above, check to see if the line
1047 ;; below exists as well and if so, align with the shorter one.
1048 (when (and (< other file)
1049 (goto-char beg)
1050 (zerop (forward-line 1))
1051 (dired-move-to-filename))
1052 (let ((alt-col (current-column)))
1053 (when (< alt-col other-col)
1054 (setq other-col alt-col)
1055 (setq other (point)))))
1056 ;; Keep positions uptodate when we insert stuff.
1057 (if (> other file) (setq other (copy-marker other)))
1058 (setq file (copy-marker file))
1059 ;; Main loop.
1060 (goto-char beg)
1061 (skip-chars-forward " ") ;Skip to the first field.
1062 (while (and (> other-col file-col)
1063 ;; Don't touch anything just before (and after) the
1064 ;; beginning of the filename.
1065 (> file (point)))
1066 ;; We're now just in front of a field, with a space behind us.
1067 (let* ((curcol (current-column))
1068 ;; Nums are right-aligned.
1069 (num-align (looking-at "[0-9]"))
1070 ;; Let's look at the other line, in the same column: we
1071 ;; should be either near the end of the previous field, or
1072 ;; in the space between that field and the next.
1073 ;; [ Of course, it's also possible that we're already within
1074 ;; the next field or even past it, but that's unlikely since
1075 ;; other-col > file-col. ]
1076 ;; Let's find the distance to the alignment-point (either
1077 ;; the beginning or the end of the next field, depending on
1078 ;; whether this field is left or right aligned).
1079 (align-pt-offset
1080 (save-excursion
1081 (goto-char other)
1082 (move-to-column curcol)
1083 (when (looking-at
1084 (concat
1085 (if (eq (char-before) ?\s) " *" "[^ ]* *")
1086 (if num-align "[0-9][^ ]*")))
1087 (- (match-end 0) (match-beginning 0)))))
1088 ;; Now, the number of spaces to insert is align-pt-offset
1089 ;; minus the distance to the equivalent point on the
1090 ;; current line.
1091 (spaces
1092 (if (not num-align)
1093 align-pt-offset
1094 (and align-pt-offset
1095 (save-excursion
1096 (skip-chars-forward "^ ")
1097 (- align-pt-offset (- (current-column) curcol)))))))
1098 (when (and spaces (> spaces 0))
1099 (setq file-col (+ spaces file-col))
1100 (if (> file-col other-col)
1101 (setq spaces (- spaces (- file-col other-col))))
1102 (insert-char ?\s spaces)
1103 ;; Let's just make really sure we did not mess up.
1104 (unless (save-excursion
1105 (eq (dired-move-to-filename) (marker-position file)))
1106 ;; Damn! We messed up: let's revert the change.
1107 (delete-char (- spaces)))))
1108 ;; Now skip to next field.
1109 (skip-chars-forward "^ ") (skip-chars-forward " "))
1110 (set-marker file nil)))))
1111
1112
1113 (defvar ls-lisp-use-insert-directory-program)
1114
1115 (defun dired-switches-escape-p (switches)
1116 "Return non-nil if the string SWITCHES contains -b or --escape."
1117 ;; Do not match things like "--block-size" that happen to contain "b".
1118 (string-match "\\(\\`\\| \\)-[[:alnum:]]*b\\|--escape\\>" switches))
1119
1120 (defun dired-insert-directory (dir switches &optional file-list wildcard hdr)
1121 "Insert a directory listing of DIR, Dired style.
1122 Use SWITCHES to make the listings.
1123 If FILE-LIST is non-nil, list only those files.
1124 Otherwise, if WILDCARD is non-nil, expand wildcards;
1125 in that case, DIR should be a file name that uses wildcards.
1126 In other cases, DIR should be a directory name or a directory filename.
1127 If HDR is non-nil, insert a header line with the directory name."
1128 (let ((opoint (point))
1129 (process-environment (copy-sequence process-environment))
1130 end)
1131 (if (and
1132 ;; Don't try to invoke `ls' if we are on DOS/Windows where
1133 ;; ls-lisp emulation is used, except if they want to use `ls'
1134 ;; as indicated by `ls-lisp-use-insert-directory-program'.
1135 (not (and (featurep 'ls-lisp)
1136 (null ls-lisp-use-insert-directory-program)))
1137 (or (if (eq dired-use-ls-dired 'unspecified)
1138 ;; Check whether "ls --dired" gives exit code 0, and
1139 ;; save the answer in `dired-use-ls-dired'.
1140 (or (setq dired-use-ls-dired
1141 (eq 0 (call-process insert-directory-program
1142 nil nil nil "--dired")))
1143 (progn
1144 (message "ls does not support --dired; \
1145 see `dired-use-ls-dired' for more details.")
1146 nil))
1147 dired-use-ls-dired)
1148 (file-remote-p dir)))
1149 (setq switches (concat "--dired " switches)))
1150 ;; We used to specify the C locale here, to force English month names;
1151 ;; but this should not be necessary any more,
1152 ;; with the new value of `directory-listing-before-filename-regexp'.
1153 (if file-list
1154 (dolist (f file-list)
1155 (let ((beg (point)))
1156 (insert-directory f switches nil nil)
1157 ;; Re-align fields, if necessary.
1158 (dired-align-file beg (point))))
1159 (insert-directory dir switches wildcard (not wildcard)))
1160 ;; Quote certain characters, unless ls quoted them for us.
1161 (if (not (dired-switches-escape-p dired-actual-switches))
1162 (save-excursion
1163 (setq end (point-marker))
1164 (goto-char opoint)
1165 (while (search-forward "\\" end t)
1166 (replace-match (apply #'propertize
1167 "\\\\"
1168 (text-properties-at (match-beginning 0)))
1169 nil t))
1170 (goto-char opoint)
1171 (while (search-forward "\^m" end t)
1172 (replace-match (apply #'propertize
1173 "\\015"
1174 (text-properties-at (match-beginning 0)))
1175 nil t))
1176 (set-marker end nil))
1177 ;; Replace any newlines in DIR with literal "\n"s, for the sake
1178 ;; of the header line. To disambiguate a literal "\n" in the
1179 ;; actual dirname, we also replace "\" with "\\".
1180 ;; Personally, I think this should always be done, irrespective
1181 ;; of the value of dired-actual-switches, because:
1182 ;; i) Dired simply does not work with an unescaped newline in
1183 ;; the directory name used in the header (bug=10469#28), and
1184 ;; ii) "\" is always replaced with "\\" in the listing, so doing
1185 ;; it in the header as well makes things consistent.
1186 ;; But at present it is only done if "-b" is in ls-switches,
1187 ;; because newlines in dirnames are uncommon, and people may
1188 ;; have gotten used to seeing unescaped "\" in the headers.
1189 ;; Note: adjust dired-build-subdir-alist if you change this.
1190 (setq dir (replace-regexp-in-string "\\\\" "\\\\" dir nil t)
1191 dir (replace-regexp-in-string "\n" "\\n" dir nil t)))
1192 (dired-insert-set-properties opoint (point))
1193 ;; If we used --dired and it worked, the lines are already indented.
1194 ;; Otherwise, indent them.
1195 (unless (save-excursion
1196 (goto-char opoint)
1197 (looking-at " "))
1198 (let ((indent-tabs-mode nil))
1199 (indent-rigidly opoint (point) 2)))
1200 ;; Insert text at the beginning to standardize things.
1201 (save-excursion
1202 (goto-char opoint)
1203 (if (and (or hdr wildcard)
1204 (not (and (looking-at "^ \\(.*\\):$")
1205 (file-name-absolute-p (match-string 1)))))
1206 ;; Note that dired-build-subdir-alist will replace the name
1207 ;; by its expansion, so it does not matter whether what we insert
1208 ;; here is fully expanded, but it should be absolute.
1209 (insert " " (directory-file-name (file-name-directory dir)) ":\n"))
1210 (when wildcard
1211 ;; Insert "wildcard" line where "total" line would be for a full dir.
1212 (insert " wildcard " (file-name-nondirectory dir) "\n")))))
1213
1214 (defun dired-insert-set-properties (beg end)
1215 "Add various text properties to the lines in the region."
1216 (save-excursion
1217 (goto-char beg)
1218 (while (< (point) end)
1219 (condition-case nil
1220 (if (dired-move-to-filename)
1221 (add-text-properties
1222 (point)
1223 (save-excursion
1224 (dired-move-to-end-of-filename)
1225 (point))
1226 '(mouse-face highlight
1227 dired-filename t
1228 help-echo "mouse-2: visit this file in other window")))
1229 (error nil))
1230 (forward-line 1))))
1231 \f
1232 ;; Reverting a dired buffer
1233
1234 (defun dired-revert (&optional _arg _noconfirm)
1235 "Reread the dired buffer.
1236 Must also be called after `dired-actual-switches' have changed.
1237 Should not fail even on completely garbaged buffers.
1238 Preserves old cursor, marks/flags, hidden-p.
1239
1240 Dired sets `revert-buffer-function' to this function. The args
1241 ARG and NOCONFIRM, passed from `revert-buffer', are ignored."
1242 (widen) ; just in case user narrowed
1243 (let ((modflag (buffer-modified-p))
1244 (positions (dired-save-positions))
1245 (mark-alist nil) ; save marked files
1246 (hidden-subdirs (dired-remember-hidden))
1247 (old-subdir-alist (cdr (reverse dired-subdir-alist))) ; except pwd
1248 (case-fold-search nil) ; we check for upper case ls flags
1249 (inhibit-read-only t))
1250 (goto-char (point-min))
1251 (setq mark-alist;; only after dired-remember-hidden since this unhides:
1252 (dired-remember-marks (point-min) (point-max)))
1253 ;; treat top level dir extra (it may contain wildcards)
1254 (if (not (consp dired-directory))
1255 (dired-uncache dired-directory)
1256 (dired-uncache (car dired-directory))
1257 (dolist (dir (cdr dired-directory))
1258 (if (file-name-absolute-p dir)
1259 (dired-uncache dir))))
1260 ;; Run dired-after-readin-hook just once, below.
1261 (let ((dired-after-readin-hook nil))
1262 (dired-readin)
1263 (dired-insert-old-subdirs old-subdir-alist))
1264 (dired-mark-remembered mark-alist) ; mark files that were marked
1265 ;; ... run the hook for the whole buffer, and only after markers
1266 ;; have been reinserted (else omitting in dired-x would omit marked files)
1267 (run-hooks 'dired-after-readin-hook) ; no need to narrow
1268 (dired-restore-positions positions)
1269 (save-excursion ; hide subdirs that were hidden
1270 (dolist (dir hidden-subdirs)
1271 (if (dired-goto-subdir dir)
1272 (dired-hide-subdir 1))))
1273 (unless modflag (restore-buffer-modified-p nil)))
1274 ;; outside of the let scope
1275 ;;; Might as well not override the user if the user changed this.
1276 ;;; (setq buffer-read-only t)
1277 )
1278
1279 ;; Subroutines of dired-revert
1280 ;; Some of these are also used when inserting subdirs.
1281
1282 (defun dired-save-positions ()
1283 "Return current positions in the buffer and all windows with this directory.
1284 The positions have the form (BUFFER-POSITION WINDOW-POSITIONS).
1285
1286 BUFFER-POSITION is the point position in the current dired buffer.
1287 It has the form (BUFFER DIRED-FILENAME BUFFER-POINT).
1288
1289 WINDOW-POSITIONS are current positions in all windows displaying
1290 this dired buffer. The window positions have the form (WINDOW
1291 DIRED-FILENAME WINDOW-POINT)."
1292 (list
1293 (list (current-buffer) (dired-get-filename nil t) (point))
1294 (mapcar (lambda (w)
1295 (list w
1296 (with-selected-window w
1297 (dired-get-filename nil t))
1298 (window-point w)))
1299 (get-buffer-window-list nil 0 t))))
1300
1301 (defun dired-restore-positions (positions)
1302 "Restore POSITIONS saved with `dired-save-positions'."
1303 (let* ((buf-file-pos (nth 0 positions))
1304 (buffer (nth 0 buf-file-pos)))
1305 (unless (and (nth 1 buf-file-pos)
1306 (dired-goto-file (nth 1 buf-file-pos)))
1307 (goto-char (nth 2 buf-file-pos))
1308 (dired-move-to-filename))
1309 (dolist (win-file-pos (nth 1 positions))
1310 ;; Ensure that window still displays the original buffer.
1311 (when (eq (window-buffer (nth 0 win-file-pos)) buffer)
1312 (with-selected-window (nth 0 win-file-pos)
1313 (unless (and (nth 1 win-file-pos)
1314 (dired-goto-file (nth 1 win-file-pos)))
1315 (goto-char (nth 2 win-file-pos))
1316 (dired-move-to-filename)))))))
1317
1318 (defun dired-remember-marks (beg end)
1319 "Return alist of files and their marks, from BEG to END."
1320 (if selective-display ; must unhide to make this work.
1321 (let ((inhibit-read-only t))
1322 (subst-char-in-region beg end ?\r ?\n)))
1323 (let (fil chr alist)
1324 (save-excursion
1325 (goto-char beg)
1326 (while (re-search-forward dired-re-mark end t)
1327 (if (setq fil (dired-get-filename nil t))
1328 (setq chr (preceding-char)
1329 alist (cons (cons fil chr) alist)))))
1330 alist))
1331
1332 (defun dired-mark-remembered (alist)
1333 "Mark all files remembered in ALIST.
1334 Each element of ALIST looks like (FILE . MARKERCHAR)."
1335 (let (elt fil chr)
1336 (while alist
1337 (setq elt (car alist)
1338 alist (cdr alist)
1339 fil (car elt)
1340 chr (cdr elt))
1341 (if (dired-goto-file fil)
1342 (save-excursion
1343 (beginning-of-line)
1344 (delete-char 1)
1345 (insert chr))))))
1346
1347 (defun dired-remember-hidden ()
1348 "Return a list of names of subdirs currently hidden."
1349 (let ((l dired-subdir-alist) dir pos result)
1350 (while l
1351 (setq dir (car (car l))
1352 pos (cdr (car l))
1353 l (cdr l))
1354 (goto-char pos)
1355 (skip-chars-forward "^\r\n")
1356 (if (eq (following-char) ?\r)
1357 (setq result (cons dir result))))
1358 result))
1359
1360 (defun dired-insert-old-subdirs (old-subdir-alist)
1361 "Try to insert all subdirs that were displayed before.
1362 Do so according to the former subdir alist OLD-SUBDIR-ALIST."
1363 (or (string-match "R" dired-actual-switches)
1364 (let (elt dir)
1365 (while old-subdir-alist
1366 (setq elt (car old-subdir-alist)
1367 old-subdir-alist (cdr old-subdir-alist)
1368 dir (car elt))
1369 (condition-case ()
1370 (progn
1371 (dired-uncache dir)
1372 (dired-insert-subdir dir))
1373 (error nil))))))
1374
1375 (defun dired-uncache (dir)
1376 "Remove directory DIR from any directory cache."
1377 (let ((handler (find-file-name-handler dir 'dired-uncache)))
1378 (if handler
1379 (funcall handler 'dired-uncache dir))))
1380 \f
1381 ;; dired mode key bindings and initialization
1382
1383 (defvar dired-mode-map
1384 ;; This looks ugly when substitute-command-keys uses C-d instead d:
1385 ;; (define-key dired-mode-map "\C-d" 'dired-flag-file-deletion)
1386 (let ((map (make-keymap)))
1387 (set-keymap-parent map special-mode-map)
1388 (define-key map [mouse-2] 'dired-mouse-find-file-other-window)
1389 (define-key map [follow-link] 'mouse-face)
1390 ;; Commands to mark or flag certain categories of files
1391 (define-key map "#" 'dired-flag-auto-save-files)
1392 (define-key map "." 'dired-clean-directory)
1393 (define-key map "~" 'dired-flag-backup-files)
1394 ;; Upper case keys (except !) for operating on the marked files
1395 (define-key map "A" 'dired-do-search)
1396 (define-key map "C" 'dired-do-copy)
1397 (define-key map "B" 'dired-do-byte-compile)
1398 (define-key map "D" 'dired-do-delete)
1399 (define-key map "G" 'dired-do-chgrp)
1400 (define-key map "H" 'dired-do-hardlink)
1401 (define-key map "L" 'dired-do-load)
1402 (define-key map "M" 'dired-do-chmod)
1403 (define-key map "O" 'dired-do-chown)
1404 (define-key map "P" 'dired-do-print)
1405 (define-key map "Q" 'dired-do-query-replace-regexp)
1406 (define-key map "R" 'dired-do-rename)
1407 (define-key map "S" 'dired-do-symlink)
1408 (define-key map "T" 'dired-do-touch)
1409 (define-key map "X" 'dired-do-shell-command)
1410 (define-key map "Z" 'dired-do-compress)
1411 (define-key map "!" 'dired-do-shell-command)
1412 (define-key map "&" 'dired-do-async-shell-command)
1413 ;; Comparison commands
1414 (define-key map "=" 'dired-diff)
1415 (define-key map "\M-=" 'dired-backup-diff)
1416 ;; Tree Dired commands
1417 (define-key map "\M-\C-?" 'dired-unmark-all-files)
1418 (define-key map "\M-\C-d" 'dired-tree-down)
1419 (define-key map "\M-\C-u" 'dired-tree-up)
1420 (define-key map "\M-\C-n" 'dired-next-subdir)
1421 (define-key map "\M-\C-p" 'dired-prev-subdir)
1422 ;; move to marked files
1423 (define-key map "\M-{" 'dired-prev-marked-file)
1424 (define-key map "\M-}" 'dired-next-marked-file)
1425 ;; Make all regexp commands share a `%' prefix:
1426 ;; We used to get to the submap via a symbol dired-regexp-prefix,
1427 ;; but that seems to serve little purpose, and copy-keymap
1428 ;; does a better job without it.
1429 (define-key map "%" nil)
1430 (define-key map "%u" 'dired-upcase)
1431 (define-key map "%l" 'dired-downcase)
1432 (define-key map "%d" 'dired-flag-files-regexp)
1433 (define-key map "%g" 'dired-mark-files-containing-regexp)
1434 (define-key map "%m" 'dired-mark-files-regexp)
1435 (define-key map "%r" 'dired-do-rename-regexp)
1436 (define-key map "%C" 'dired-do-copy-regexp)
1437 (define-key map "%H" 'dired-do-hardlink-regexp)
1438 (define-key map "%R" 'dired-do-rename-regexp)
1439 (define-key map "%S" 'dired-do-symlink-regexp)
1440 (define-key map "%&" 'dired-flag-garbage-files)
1441 ;; Commands for marking and unmarking.
1442 (define-key map "*" nil)
1443 (define-key map "**" 'dired-mark-executables)
1444 (define-key map "*/" 'dired-mark-directories)
1445 (define-key map "*@" 'dired-mark-symlinks)
1446 (define-key map "*%" 'dired-mark-files-regexp)
1447 (define-key map "*c" 'dired-change-marks)
1448 (define-key map "*s" 'dired-mark-subdir-files)
1449 (define-key map "*m" 'dired-mark)
1450 (define-key map "*u" 'dired-unmark)
1451 (define-key map "*?" 'dired-unmark-all-files)
1452 (define-key map "*!" 'dired-unmark-all-marks)
1453 (define-key map "U" 'dired-unmark-all-marks)
1454 (define-key map "*\177" 'dired-unmark-backward)
1455 (define-key map "*\C-n" 'dired-next-marked-file)
1456 (define-key map "*\C-p" 'dired-prev-marked-file)
1457 (define-key map "*t" 'dired-toggle-marks)
1458 ;; Lower keys for commands not operating on all the marked files
1459 (define-key map "a" 'dired-find-alternate-file)
1460 (define-key map "d" 'dired-flag-file-deletion)
1461 (define-key map "e" 'dired-find-file)
1462 (define-key map "f" 'dired-find-file)
1463 (define-key map "\C-m" 'dired-find-file)
1464 (put 'dired-find-file :advertised-binding "\C-m")
1465 (define-key map "g" 'revert-buffer)
1466 (define-key map "i" 'dired-maybe-insert-subdir)
1467 (define-key map "j" 'dired-goto-file)
1468 (define-key map "k" 'dired-do-kill-lines)
1469 (define-key map "l" 'dired-do-redisplay)
1470 (define-key map "m" 'dired-mark)
1471 (define-key map "n" 'dired-next-line)
1472 (define-key map "o" 'dired-find-file-other-window)
1473 (define-key map "\C-o" 'dired-display-file)
1474 (define-key map "p" 'dired-previous-line)
1475 (define-key map "s" 'dired-sort-toggle-or-edit)
1476 (define-key map "t" 'dired-toggle-marks)
1477 (define-key map "u" 'dired-unmark)
1478 (define-key map "v" 'dired-view-file)
1479 (define-key map "w" 'dired-copy-filename-as-kill)
1480 (define-key map "x" 'dired-do-flagged-delete)
1481 (define-key map "y" 'dired-show-file-type)
1482 (define-key map "+" 'dired-create-directory)
1483 ;; moving
1484 (define-key map "<" 'dired-prev-dirline)
1485 (define-key map ">" 'dired-next-dirline)
1486 (define-key map "^" 'dired-up-directory)
1487 (define-key map " " 'dired-next-line)
1488 (define-key map [remap next-line] 'dired-next-line)
1489 (define-key map [remap previous-line] 'dired-previous-line)
1490 ;; hiding
1491 (define-key map "$" 'dired-hide-subdir)
1492 (define-key map "\M-$" 'dired-hide-all)
1493 ;; isearch
1494 (define-key map (kbd "M-s a C-s") 'dired-do-isearch)
1495 (define-key map (kbd "M-s a M-C-s") 'dired-do-isearch-regexp)
1496 (define-key map (kbd "M-s f C-s") 'dired-isearch-filenames)
1497 (define-key map (kbd "M-s f M-C-s") 'dired-isearch-filenames-regexp)
1498 ;; misc
1499 (define-key map [remap toggle-read-only] 'dired-toggle-read-only)
1500 (define-key map "?" 'dired-summary)
1501 (define-key map "\177" 'dired-unmark-backward)
1502 (define-key map [remap undo] 'dired-undo)
1503 (define-key map [remap advertised-undo] 'dired-undo)
1504 ;; thumbnail manipulation (image-dired)
1505 (define-key map "\C-td" 'image-dired-display-thumbs)
1506 (define-key map "\C-tt" 'image-dired-tag-files)
1507 (define-key map "\C-tr" 'image-dired-delete-tag)
1508 (define-key map "\C-tj" 'image-dired-jump-thumbnail-buffer)
1509 (define-key map "\C-ti" 'image-dired-dired-display-image)
1510 (define-key map "\C-tx" 'image-dired-dired-display-external)
1511 (define-key map "\C-ta" 'image-dired-display-thumbs-append)
1512 (define-key map "\C-t." 'image-dired-display-thumb)
1513 (define-key map "\C-tc" 'image-dired-dired-comment-files)
1514 (define-key map "\C-tf" 'image-dired-mark-tagged-files)
1515 (define-key map "\C-t\C-t" 'image-dired-dired-toggle-marked-thumbs)
1516 (define-key map "\C-te" 'image-dired-dired-edit-comment-and-tags)
1517 ;; encryption and decryption (epa-dired)
1518 (define-key map ":d" 'epa-dired-do-decrypt)
1519 (define-key map ":v" 'epa-dired-do-verify)
1520 (define-key map ":s" 'epa-dired-do-sign)
1521 (define-key map ":e" 'epa-dired-do-encrypt)
1522
1523 ;; Make menu bar items.
1524
1525 ;; No need to fo this, now that top-level items are fewer.
1526 ;;;;
1527 ;; Get rid of the Edit menu bar item to save space.
1528 ;(define-key map [menu-bar edit] 'undefined)
1529
1530 (define-key map [menu-bar subdir]
1531 (cons "Subdir" (make-sparse-keymap "Subdir")))
1532
1533 (define-key map [menu-bar subdir hide-all]
1534 '(menu-item "Hide All" dired-hide-all
1535 :help "Hide all subdirectories, leave only header lines"))
1536 (define-key map [menu-bar subdir hide-subdir]
1537 '(menu-item "Hide/UnHide Subdir" dired-hide-subdir
1538 :help "Hide or unhide current directory listing"))
1539 (define-key map [menu-bar subdir tree-down]
1540 '(menu-item "Tree Down" dired-tree-down
1541 :help "Go to first subdirectory header down the tree"))
1542 (define-key map [menu-bar subdir tree-up]
1543 '(menu-item "Tree Up" dired-tree-up
1544 :help "Go to first subdirectory header up the tree"))
1545 (define-key map [menu-bar subdir up]
1546 '(menu-item "Up Directory" dired-up-directory
1547 :help "Edit the parent directory"))
1548 (define-key map [menu-bar subdir prev-subdir]
1549 '(menu-item "Prev Subdir" dired-prev-subdir
1550 :help "Go to previous subdirectory header line"))
1551 (define-key map [menu-bar subdir next-subdir]
1552 '(menu-item "Next Subdir" dired-next-subdir
1553 :help "Go to next subdirectory header line"))
1554 (define-key map [menu-bar subdir prev-dirline]
1555 '(menu-item "Prev Dirline" dired-prev-dirline
1556 :help "Move to next directory-file line"))
1557 (define-key map [menu-bar subdir next-dirline]
1558 '(menu-item "Next Dirline" dired-next-dirline
1559 :help "Move to previous directory-file line"))
1560 (define-key map [menu-bar subdir insert]
1561 '(menu-item "Insert This Subdir" dired-maybe-insert-subdir
1562 :help "Insert contents of subdirectory"
1563 :enable (let ((f (dired-get-filename nil t)))
1564 (and f (file-directory-p f)))))
1565 (define-key map [menu-bar immediate]
1566 (cons "Immediate" (make-sparse-keymap "Immediate")))
1567
1568 (define-key map
1569 [menu-bar immediate image-dired-dired-display-external]
1570 '(menu-item "Display Image Externally" image-dired-dired-display-external
1571 :help "Display image in external viewer"))
1572 (define-key map
1573 [menu-bar immediate image-dired-dired-display-image]
1574 '(menu-item "Display Image" image-dired-dired-display-image
1575 :help "Display sized image in a separate window"))
1576 (define-key map
1577 [menu-bar immediate image-dired-dired-toggle-marked-thumbs]
1578 '(menu-item "Toggle Image Thumbnails in This Buffer" image-dired-dired-toggle-marked-thumbs
1579 :help "Add or remove image thumbnails in front of marked file names"))
1580
1581 (define-key map [menu-bar immediate revert-buffer]
1582 '(menu-item "Refresh" revert-buffer
1583 :help "Update contents of shown directories"))
1584
1585 (define-key map [menu-bar immediate dashes]
1586 '("--"))
1587
1588 (define-key map [menu-bar immediate isearch-filenames-regexp]
1589 '(menu-item "Isearch Regexp in File Names..." dired-isearch-filenames-regexp
1590 :help "Incrementally search for regexp in file names only"))
1591 (define-key map [menu-bar immediate isearch-filenames]
1592 '(menu-item "Isearch in File Names..." dired-isearch-filenames
1593 :help "Incrementally search for string in file names only."))
1594 (define-key map [menu-bar immediate compare-directories]
1595 '(menu-item "Compare Directories..." dired-compare-directories
1596 :help "Mark files with different attributes in two dired buffers"))
1597 (define-key map [menu-bar immediate backup-diff]
1598 '(menu-item "Compare with Backup" dired-backup-diff
1599 :help "Diff file at cursor with its latest backup"))
1600 (define-key map [menu-bar immediate diff]
1601 '(menu-item "Diff..." dired-diff
1602 :help "Compare file at cursor with another file"))
1603 (define-key map [menu-bar immediate view]
1604 '(menu-item "View This File" dired-view-file
1605 :help "Examine file at cursor in read-only mode"))
1606 (define-key map [menu-bar immediate display]
1607 '(menu-item "Display in Other Window" dired-display-file
1608 :help "Display file at cursor in other window"))
1609 (define-key map [menu-bar immediate find-file-other-window]
1610 '(menu-item "Find in Other Window" dired-find-file-other-window
1611 :help "Edit file at cursor in other window"))
1612 (define-key map [menu-bar immediate find-file]
1613 '(menu-item "Find This File" dired-find-file
1614 :help "Edit file at cursor"))
1615 (define-key map [menu-bar immediate create-directory]
1616 '(menu-item "Create Directory..." dired-create-directory
1617 :help "Create a directory"))
1618 (define-key map [menu-bar immediate wdired-mode]
1619 '(menu-item "Edit File Names" wdired-change-to-wdired-mode
1620 :help "Put a dired buffer in a mode in which filenames are editable"
1621 :keys "C-x C-q"
1622 :filter (lambda (x) (if (eq major-mode 'dired-mode) x))))
1623
1624 (define-key map [menu-bar regexp]
1625 (cons "Regexp" (make-sparse-keymap "Regexp")))
1626
1627 (define-key map
1628 [menu-bar regexp image-dired-mark-tagged-files]
1629 '(menu-item "Mark From Image Tag..." image-dired-mark-tagged-files
1630 :help "Mark files whose image tags matches regexp"))
1631
1632 (define-key map [menu-bar regexp dashes-1]
1633 '("--"))
1634
1635 (define-key map [menu-bar regexp downcase]
1636 '(menu-item "Downcase" dired-downcase
1637 ;; When running on plain MS-DOS, there's only one
1638 ;; letter-case for file names.
1639 :enable (or (not (fboundp 'msdos-long-file-names))
1640 (msdos-long-file-names))
1641 :help "Rename marked files to lower-case name"))
1642 (define-key map [menu-bar regexp upcase]
1643 '(menu-item "Upcase" dired-upcase
1644 :enable (or (not (fboundp 'msdos-long-file-names))
1645 (msdos-long-file-names))
1646 :help "Rename marked files to upper-case name"))
1647 (define-key map [menu-bar regexp hardlink]
1648 '(menu-item "Hardlink..." dired-do-hardlink-regexp
1649 :help "Make hard links for files matching regexp"))
1650 (define-key map [menu-bar regexp symlink]
1651 '(menu-item "Symlink..." dired-do-symlink-regexp
1652 :visible (fboundp 'make-symbolic-link)
1653 :help "Make symbolic links for files matching regexp"))
1654 (define-key map [menu-bar regexp rename]
1655 '(menu-item "Rename..." dired-do-rename-regexp
1656 :help "Rename marked files matching regexp"))
1657 (define-key map [menu-bar regexp copy]
1658 '(menu-item "Copy..." dired-do-copy-regexp
1659 :help "Copy marked files matching regexp"))
1660 (define-key map [menu-bar regexp flag]
1661 '(menu-item "Flag..." dired-flag-files-regexp
1662 :help "Flag files matching regexp for deletion"))
1663 (define-key map [menu-bar regexp mark]
1664 '(menu-item "Mark..." dired-mark-files-regexp
1665 :help "Mark files matching regexp for future operations"))
1666 (define-key map [menu-bar regexp mark-cont]
1667 '(menu-item "Mark Containing..." dired-mark-files-containing-regexp
1668 :help "Mark files whose contents matches regexp"))
1669
1670 (define-key map [menu-bar mark]
1671 (cons "Mark" (make-sparse-keymap "Mark")))
1672
1673 (define-key map [menu-bar mark prev]
1674 '(menu-item "Previous Marked" dired-prev-marked-file
1675 :help "Move to previous marked file"))
1676 (define-key map [menu-bar mark next]
1677 '(menu-item "Next Marked" dired-next-marked-file
1678 :help "Move to next marked file"))
1679 (define-key map [menu-bar mark marks]
1680 '(menu-item "Change Marks..." dired-change-marks
1681 :help "Replace marker with another character"))
1682 (define-key map [menu-bar mark unmark-all]
1683 '(menu-item "Unmark All" dired-unmark-all-marks))
1684 (define-key map [menu-bar mark symlinks]
1685 '(menu-item "Mark Symlinks" dired-mark-symlinks
1686 :visible (fboundp 'make-symbolic-link)
1687 :help "Mark all symbolic links"))
1688 (define-key map [menu-bar mark directories]
1689 '(menu-item "Mark Directories" dired-mark-directories
1690 :help "Mark all directories except `.' and `..'"))
1691 (define-key map [menu-bar mark directory]
1692 '(menu-item "Mark Old Backups" dired-clean-directory
1693 :help "Flag old numbered backups for deletion"))
1694 (define-key map [menu-bar mark executables]
1695 '(menu-item "Mark Executables" dired-mark-executables
1696 :help "Mark all executable files"))
1697 (define-key map [menu-bar mark garbage-files]
1698 '(menu-item "Flag Garbage Files" dired-flag-garbage-files
1699 :help "Flag unneeded files for deletion"))
1700 (define-key map [menu-bar mark backup-files]
1701 '(menu-item "Flag Backup Files" dired-flag-backup-files
1702 :help "Flag all backup files for deletion"))
1703 (define-key map [menu-bar mark auto-save-files]
1704 '(menu-item "Flag Auto-save Files" dired-flag-auto-save-files
1705 :help "Flag auto-save files for deletion"))
1706 (define-key map [menu-bar mark deletion]
1707 '(menu-item "Flag" dired-flag-file-deletion
1708 :help "Flag current line's file for deletion"))
1709 (define-key map [menu-bar mark unmark]
1710 '(menu-item "Unmark" dired-unmark
1711 :help "Unmark or unflag current line's file"))
1712 (define-key map [menu-bar mark mark]
1713 '(menu-item "Mark" dired-mark
1714 :help "Mark current line's file for future operations"))
1715 (define-key map [menu-bar mark toggle-marks]
1716 '(menu-item "Toggle Marks" dired-toggle-marks
1717 :help "Mark unmarked files, unmark marked ones"))
1718
1719 (define-key map [menu-bar operate]
1720 (cons "Operate" (make-sparse-keymap "Operate")))
1721
1722 (define-key map
1723 [menu-bar operate image-dired-delete-tag]
1724 '(menu-item "Delete Image Tag..." image-dired-delete-tag
1725 :help "Delete image tag from current or marked files"))
1726 (define-key map
1727 [menu-bar operate image-dired-tag-files]
1728 '(menu-item "Add Image Tags..." image-dired-tag-files
1729 :help "Add image tags to current or marked files"))
1730 (define-key map
1731 [menu-bar operate image-dired-dired-comment-files]
1732 '(menu-item "Add Image Comment..." image-dired-dired-comment-files
1733 :help "Add image comment to current or marked files"))
1734 (define-key map
1735 [menu-bar operate image-dired-display-thumbs]
1736 '(menu-item "Display Image Thumbnails" image-dired-display-thumbs
1737 :help "Display image thumbnails for current or marked image files"))
1738
1739 (define-key map [menu-bar operate dashes-4]
1740 '("--"))
1741
1742 (define-key map
1743 [menu-bar operate epa-dired-do-decrypt]
1744 '(menu-item "Decrypt" epa-dired-do-decrypt
1745 :help "Decrypt file at cursor"))
1746
1747 (define-key map
1748 [menu-bar operate epa-dired-do-verify]
1749 '(menu-item "Verify" epa-dired-do-verify
1750 :help "Verify digital signature of file at cursor"))
1751
1752 (define-key map
1753 [menu-bar operate epa-dired-do-sign]
1754 '(menu-item "Sign" epa-dired-do-sign
1755 :help "Create digital signature of file at cursor"))
1756
1757 (define-key map
1758 [menu-bar operate epa-dired-do-encrypt]
1759 '(menu-item "Encrypt" epa-dired-do-encrypt
1760 :help "Encrypt file at cursor"))
1761
1762 (define-key map [menu-bar operate dashes-3]
1763 '("--"))
1764
1765 (define-key map [menu-bar operate query-replace]
1766 '(menu-item "Query Replace in Files..." dired-do-query-replace-regexp
1767 :help "Replace regexp in marked files"))
1768 (define-key map [menu-bar operate search]
1769 '(menu-item "Search Files..." dired-do-search
1770 :help "Search marked files for regexp"))
1771 (define-key map [menu-bar operate isearch-regexp]
1772 '(menu-item "Isearch Regexp Files..." dired-do-isearch-regexp
1773 :help "Incrementally search marked files for regexp"))
1774 (define-key map [menu-bar operate isearch]
1775 '(menu-item "Isearch Files..." dired-do-isearch
1776 :help "Incrementally search marked files for string"))
1777 (define-key map [menu-bar operate chown]
1778 '(menu-item "Change Owner..." dired-do-chown
1779 :visible (not (memq system-type '(ms-dos windows-nt)))
1780 :help "Change the owner of marked files"))
1781 (define-key map [menu-bar operate chgrp]
1782 '(menu-item "Change Group..." dired-do-chgrp
1783 :visible (not (memq system-type '(ms-dos windows-nt)))
1784 :help "Change the group of marked files"))
1785 (define-key map [menu-bar operate chmod]
1786 '(menu-item "Change Mode..." dired-do-chmod
1787 :help "Change mode (attributes) of marked files"))
1788 (define-key map [menu-bar operate touch]
1789 '(menu-item "Change Timestamp..." dired-do-touch
1790 :help "Change timestamp of marked files"))
1791 (define-key map [menu-bar operate load]
1792 '(menu-item "Load" dired-do-load
1793 :help "Load marked Emacs Lisp files"))
1794 (define-key map [menu-bar operate compile]
1795 '(menu-item "Byte-compile" dired-do-byte-compile
1796 :help "Byte-compile marked Emacs Lisp files"))
1797 (define-key map [menu-bar operate compress]
1798 '(menu-item "Compress" dired-do-compress
1799 :help "Compress/uncompress marked files"))
1800 (define-key map [menu-bar operate print]
1801 '(menu-item "Print..." dired-do-print
1802 :help "Ask for print command and print marked files"))
1803 (define-key map [menu-bar operate hardlink]
1804 '(menu-item "Hardlink to..." dired-do-hardlink
1805 :help "Make hard links for current or marked files"))
1806 (define-key map [menu-bar operate symlink]
1807 '(menu-item "Symlink to..." dired-do-symlink
1808 :visible (fboundp 'make-symbolic-link)
1809 :help "Make symbolic links for current or marked files"))
1810 (define-key map [menu-bar operate async-command]
1811 '(menu-item "Asynchronous Shell Command..." dired-do-async-shell-command
1812 :help "Run a shell command asynchronously on current or marked files"))
1813 (define-key map [menu-bar operate command]
1814 '(menu-item "Shell Command..." dired-do-shell-command
1815 :help "Run a shell command on current or marked files"))
1816 (define-key map [menu-bar operate delete]
1817 '(menu-item "Delete" dired-do-delete
1818 :help "Delete current file or all marked files"))
1819 (define-key map [menu-bar operate rename]
1820 '(menu-item "Rename to..." dired-do-rename
1821 :help "Rename current file or move marked files"))
1822 (define-key map [menu-bar operate copy]
1823 '(menu-item "Copy to..." dired-do-copy
1824 :help "Copy current file or all marked files"))
1825
1826 map)
1827 "Local keymap for `dired-mode' buffers.")
1828 \f
1829 ;; Dired mode is suitable only for specially formatted data.
1830 (put 'dired-mode 'mode-class 'special)
1831
1832 ;; Autoload cookie needed by desktop.el
1833 ;;;###autoload
1834 (defun dired-mode (&optional dirname switches)
1835 "\
1836 Mode for \"editing\" directory listings.
1837 In Dired, you are \"editing\" a list of the files in a directory and
1838 \(optionally) its subdirectories, in the format of `ls -lR'.
1839 Each directory is a page: use \\[backward-page] and \\[forward-page] to move pagewise.
1840 \"Editing\" means that you can run shell commands on files, visit,
1841 compress, load or byte-compile them, change their file attributes
1842 and insert subdirectories into the same buffer. You can \"mark\"
1843 files for later commands or \"flag\" them for deletion, either file
1844 by file or all files matching certain criteria.
1845 You can move using the usual cursor motion commands.\\<dired-mode-map>
1846 The buffer is read-only. Digits are prefix arguments.
1847 Type \\[dired-flag-file-deletion] to flag a file `D' for deletion.
1848 Type \\[dired-mark] to Mark a file or subdirectory for later commands.
1849 Most commands operate on the marked files and use the current file
1850 if no files are marked. Use a numeric prefix argument to operate on
1851 the next ARG (or previous -ARG if ARG<0) files, or just `1'
1852 to operate on the current file only. Prefix arguments override marks.
1853 Mark-using commands display a list of failures afterwards. Type \\[dired-summary]
1854 to see why something went wrong.
1855 Type \\[dired-unmark] to Unmark a file or all files of an inserted subdirectory.
1856 Type \\[dired-unmark-backward] to back up one line and unmark or unflag.
1857 Type \\[dired-do-flagged-delete] to delete (eXecute) the files flagged `D'.
1858 Type \\[dired-find-file] to Find the current line's file
1859 (or dired it in another buffer, if it is a directory).
1860 Type \\[dired-find-file-other-window] to find file or dired directory in Other window.
1861 Type \\[dired-maybe-insert-subdir] to Insert a subdirectory in this buffer.
1862 Type \\[dired-do-rename] to Rename a file or move the marked files to another directory.
1863 Type \\[dired-do-copy] to Copy files.
1864 Type \\[dired-sort-toggle-or-edit] to toggle Sorting by name/date or change the `ls' switches.
1865 Type \\[revert-buffer] to read all currently expanded directories aGain.
1866 This retains all marks and hides subdirs again that were hidden before.
1867 Use `SPC' and `DEL' to move down and up by lines.
1868
1869 If Dired ever gets confused, you can either type \\[revert-buffer] \
1870 to read the
1871 directories again, type \\[dired-do-redisplay] \
1872 to relist the file at point or the marked files or a
1873 subdirectory, or type \\[dired-build-subdir-alist] to parse the buffer
1874 again for the directory tree.
1875
1876 Customization variables (rename this buffer and type \\[describe-variable] on each line
1877 for more info):
1878
1879 `dired-listing-switches'
1880 `dired-trivial-filenames'
1881 `dired-shrink-to-fit'
1882 `dired-marker-char'
1883 `dired-del-marker'
1884 `dired-keep-marker-rename'
1885 `dired-keep-marker-copy'
1886 `dired-keep-marker-hardlink'
1887 `dired-keep-marker-symlink'
1888
1889 Hooks (use \\[describe-variable] to see their documentation):
1890
1891 `dired-before-readin-hook'
1892 `dired-after-readin-hook'
1893 `dired-mode-hook'
1894 `dired-load-hook'
1895
1896 Keybindings:
1897 \\{dired-mode-map}"
1898 ;; Not to be called interactively (e.g. dired-directory will be set
1899 ;; to default-directory, which is wrong with wildcards).
1900 (kill-all-local-variables)
1901 (use-local-map dired-mode-map)
1902 (dired-advertise) ; default-directory is already set
1903 (setq major-mode 'dired-mode
1904 mode-name "Dired"
1905 ;; case-fold-search nil
1906 buffer-read-only t
1907 selective-display t ; for subdirectory hiding
1908 mode-line-buffer-identification
1909 (propertized-buffer-identification "%17b"))
1910 (set (make-local-variable 'revert-buffer-function)
1911 (function dired-revert))
1912 (set (make-local-variable 'buffer-stale-function)
1913 (function dired-buffer-stale-p))
1914 (set (make-local-variable 'page-delimiter)
1915 "\n\n")
1916 (set (make-local-variable 'dired-directory)
1917 (or dirname default-directory))
1918 ;; list-buffers uses this to display the dir being edited in this buffer.
1919 (setq list-buffers-directory
1920 (expand-file-name (if (listp dired-directory)
1921 (car dired-directory)
1922 dired-directory)))
1923 (set (make-local-variable 'dired-actual-switches)
1924 (or switches dired-listing-switches))
1925 (set (make-local-variable 'font-lock-defaults)
1926 '(dired-font-lock-keywords t nil nil beginning-of-line))
1927 (set (make-local-variable 'desktop-save-buffer)
1928 'dired-desktop-buffer-misc-data)
1929 (setq dired-switches-alist nil)
1930 (hack-dir-local-variables-non-file-buffer) ; before sorting
1931 (dired-sort-other dired-actual-switches t)
1932 (when (featurep 'dnd)
1933 (set (make-local-variable 'dnd-protocol-alist)
1934 (append dired-dnd-protocol-alist dnd-protocol-alist)))
1935 (add-hook 'file-name-at-point-functions 'dired-file-name-at-point nil t)
1936 (add-hook 'isearch-mode-hook 'dired-isearch-filenames-setup nil t)
1937 (run-mode-hooks 'dired-mode-hook))
1938 \f
1939 ;; Idiosyncratic dired commands that don't deal with marks.
1940
1941 (defun dired-summary ()
1942 "Summarize basic Dired commands and show recent dired errors."
1943 (interactive)
1944 (dired-why)
1945 ;>> this should check the key-bindings and use substitute-command-keys if non-standard
1946 (message
1947 "d-elete, u-ndelete, x-punge, f-ind, o-ther window, R-ename, C-opy, h-elp"))
1948
1949 (defun dired-undo ()
1950 "Undo in a dired buffer.
1951 This doesn't recover lost files, it just undoes changes in the buffer itself.
1952 You can use it to recover marks, killed lines or subdirs."
1953 (interactive)
1954 (let ((inhibit-read-only t))
1955 (undo))
1956 (dired-build-subdir-alist)
1957 (message "Change in dired buffer undone.
1958 Actual changes in files cannot be undone by Emacs."))
1959
1960 (defun dired-toggle-read-only ()
1961 "Edit dired buffer with Wdired, or set it read-only.
1962 Call `wdired-change-to-wdired-mode' in dired buffers whose editing is
1963 supported by Wdired (the major mode of the dired buffer is `dired-mode').
1964 Otherwise, for buffers inheriting from dired-mode, call `toggle-read-only'."
1965 (interactive)
1966 (if (eq major-mode 'dired-mode)
1967 (wdired-change-to-wdired-mode)
1968 (with-no-warnings
1969 (toggle-read-only))))
1970
1971 (defun dired-next-line (arg)
1972 "Move down lines then position at filename.
1973 Optional prefix ARG says how many lines to move; default is one line."
1974 (interactive "p")
1975 (forward-line arg)
1976 (dired-move-to-filename))
1977
1978 (defun dired-previous-line (arg)
1979 "Move up lines then position at filename.
1980 Optional prefix ARG says how many lines to move; default is one line."
1981 (interactive "p")
1982 (forward-line (- arg))
1983 (dired-move-to-filename))
1984
1985 (defun dired-next-dirline (arg &optional opoint)
1986 "Goto ARG'th next directory file line."
1987 (interactive "p")
1988 (or opoint (setq opoint (point)))
1989 (if (if (> arg 0)
1990 (re-search-forward dired-re-dir nil t arg)
1991 (beginning-of-line)
1992 (re-search-backward dired-re-dir nil t (- arg)))
1993 (dired-move-to-filename) ; user may type `i' or `f'
1994 (goto-char opoint)
1995 (error "No more subdirectories")))
1996
1997 (defun dired-prev-dirline (arg)
1998 "Goto ARG'th previous directory file line."
1999 (interactive "p")
2000 (dired-next-dirline (- arg)))
2001
2002 (defun dired-up-directory (&optional other-window)
2003 "Run Dired on parent directory of current directory.
2004 Find the parent directory either in this buffer or another buffer.
2005 Creates a buffer if necessary."
2006 (interactive "P")
2007 (let* ((dir (dired-current-directory))
2008 (up (file-name-directory (directory-file-name dir))))
2009 (or (dired-goto-file (directory-file-name dir))
2010 ;; Only try dired-goto-subdir if buffer has more than one dir.
2011 (and (cdr dired-subdir-alist)
2012 (dired-goto-subdir up))
2013 (progn
2014 (if other-window
2015 (dired-other-window up)
2016 (dired up))
2017 (dired-goto-file dir)))))
2018
2019 (defun dired-get-file-for-visit ()
2020 "Get the current line's file name, with an error if file does not exist."
2021 (interactive)
2022 ;; We pass t for second arg so that we don't get error for `.' and `..'.
2023 (let ((raw (dired-get-filename nil t))
2024 file-name)
2025 (if (null raw)
2026 (error "No file on this line"))
2027 (setq file-name (file-name-sans-versions raw t))
2028 (if (file-exists-p file-name)
2029 file-name
2030 (if (file-symlink-p file-name)
2031 (error "File is a symlink to a nonexistent target")
2032 (error "File no longer exists; type `g' to update dired buffer")))))
2033
2034 ;; Force C-m keybinding rather than `f' or `e' in the mode doc:
2035 (define-obsolete-function-alias 'dired-advertised-find-file 'dired-find-file "23.2")
2036 (defun dired-find-file ()
2037 "In Dired, visit the file or directory named on this line."
2038 (interactive)
2039 ;; Bind `find-file-run-dired' so that the command works on directories
2040 ;; too, independent of the user's setting.
2041 (let ((find-file-run-dired t))
2042 (find-file (dired-get-file-for-visit))))
2043
2044 (defun dired-find-alternate-file ()
2045 "In Dired, visit this file or directory instead of the dired buffer."
2046 (interactive)
2047 (set-buffer-modified-p nil)
2048 (find-alternate-file (dired-get-file-for-visit)))
2049 ;; Don't override the setting from .emacs.
2050 ;;;###autoload (put 'dired-find-alternate-file 'disabled t)
2051
2052 (defun dired-mouse-find-file-other-window (event)
2053 "In Dired, visit the file or directory name you click on."
2054 (interactive "e")
2055 (let (window pos file)
2056 (save-excursion
2057 (setq window (posn-window (event-end event))
2058 pos (posn-point (event-end event)))
2059 (if (not (windowp window))
2060 (error "No file chosen"))
2061 (set-buffer (window-buffer window))
2062 (goto-char pos)
2063 (setq file (dired-get-file-for-visit)))
2064 (if (file-directory-p file)
2065 (or (and (cdr dired-subdir-alist)
2066 (dired-goto-subdir file))
2067 (progn
2068 (select-window window)
2069 (dired-other-window file)))
2070 (select-window window)
2071 (find-file-other-window (file-name-sans-versions file t)))))
2072
2073 (defun dired-view-file ()
2074 "In Dired, examine a file in view mode, returning to Dired when done.
2075 When file is a directory, show it in this buffer if it is inserted.
2076 Otherwise, display it in another buffer."
2077 (interactive)
2078 (let ((file (dired-get-file-for-visit)))
2079 (if (file-directory-p file)
2080 (or (and (cdr dired-subdir-alist)
2081 (dired-goto-subdir file))
2082 (dired file))
2083 (view-file file))))
2084
2085 (defun dired-find-file-other-window ()
2086 "In Dired, visit this file or directory in another window."
2087 (interactive)
2088 (find-file-other-window (dired-get-file-for-visit)))
2089
2090 (defun dired-display-file ()
2091 "In Dired, display this file or directory in another window."
2092 (interactive)
2093 (display-buffer (find-file-noselect (dired-get-file-for-visit))))
2094 \f
2095 ;;; Functions for extracting and manipulating file names in Dired buffers.
2096
2097 (defun dired-get-filename (&optional localp no-error-if-not-filep)
2098 "In Dired, return name of file mentioned on this line.
2099 Value returned normally includes the directory name.
2100 Optional arg LOCALP with value `no-dir' means don't include directory
2101 name in result. A value of `verbatim' means to return the name exactly as
2102 it occurs in the buffer, and a value of t means construct name relative to
2103 `default-directory', which still may contain slashes if in a subdirectory.
2104 Optional arg NO-ERROR-IF-NOT-FILEP means treat `.' and `..' as
2105 regular filenames and return nil if no filename on this line.
2106 Otherwise, an error occurs in these cases."
2107 (let (case-fold-search file p1 p2 already-absolute)
2108 (save-excursion
2109 (if (setq p1 (dired-move-to-filename (not no-error-if-not-filep)))
2110 (setq p2 (dired-move-to-end-of-filename no-error-if-not-filep))))
2111 ;; nil if no file on this line, but no-error-if-not-filep is t:
2112 (if (setq file (and p1 p2 (buffer-substring p1 p2)))
2113 (progn
2114 ;; Get rid of the mouse-face property that file names have.
2115 (set-text-properties 0 (length file) nil file)
2116 ;; Unquote names quoted by ls or by dired-insert-directory.
2117 ;; This code was written using `read' to unquote, because
2118 ;; it's faster than substituting \007 (4 chars) -> ^G (1
2119 ;; char) etc. in a lisp loop. Unfortunately, this decision
2120 ;; has necessitated hacks such as dealing with filenames
2121 ;; with quotation marks in their names.
2122 (while (string-match "\\(?:[^\\]\\|\\`\\)\\(\"\\)" file)
2123 (setq file (replace-match "\\\"" nil t file 1)))
2124 ;; Unescape any spaces escaped by ls -b (bug#10469).
2125 ;; Other -b quotes, eg \t, \n, work transparently.
2126 (if (dired-switches-escape-p dired-actual-switches)
2127 (let ((start 0)
2128 (rep "")
2129 (shift -1))
2130 (if (eq localp 'verbatim)
2131 (setq rep "\\\\"
2132 shift +1))
2133 (while (string-match "\\(\\\\\\) " file start)
2134 (setq file (replace-match rep nil t file 1)
2135 start (+ shift (match-end 0))))))
2136 (when (eq system-type 'windows-nt)
2137 (save-match-data
2138 (let ((start 0))
2139 (while (string-match "\\\\" file start)
2140 (aset file (match-beginning 0) ?/)
2141 (setq start (match-end 0))))))
2142
2143 ;; Hence we don't need to worry about converting `\\' back to `\'.
2144 (setq file (read (concat "\"" file "\"")))
2145 ;; The above `read' will return a unibyte string if FILE
2146 ;; contains eight-bit-control/graphic characters.
2147 (if (and enable-multibyte-characters
2148 (not (multibyte-string-p file)))
2149 (setq file (string-to-multibyte file)))))
2150 (and file (file-name-absolute-p file)
2151 ;; A relative file name can start with ~.
2152 ;; Don't treat it as absolute in this context.
2153 (not (eq (aref file 0) ?~))
2154 (setq already-absolute t))
2155 (cond
2156 ((null file)
2157 nil)
2158 ((eq localp 'verbatim)
2159 file)
2160 ((and (not no-error-if-not-filep)
2161 (member file '("." "..")))
2162 (error "Cannot operate on `.' or `..'"))
2163 ((and (eq localp 'no-dir) already-absolute)
2164 (file-name-nondirectory file))
2165 (already-absolute
2166 (let ((handler (find-file-name-handler file nil)))
2167 ;; check for safe-magic property so that we won't
2168 ;; put /: for names that don't really need them.
2169 ;; For instance, .gz files when auto-compression-mode is on.
2170 (if (and handler (not (get handler 'safe-magic)))
2171 (concat "/:" file)
2172 file)))
2173 ((eq localp 'no-dir)
2174 file)
2175 ((equal (dired-current-directory) "/")
2176 (setq file (concat (dired-current-directory localp) file))
2177 (let ((handler (find-file-name-handler file nil)))
2178 ;; check for safe-magic property so that we won't
2179 ;; put /: for names that don't really need them.
2180 ;; For instance, .gz files when auto-compression-mode is on.
2181 (if (and handler (not (get handler 'safe-magic)))
2182 (concat "/:" file)
2183 file)))
2184 (t
2185 (concat (dired-current-directory localp) file)))))
2186
2187 (defun dired-string-replace-match (regexp string newtext
2188 &optional literal global)
2189 "Replace first match of REGEXP in STRING with NEWTEXT.
2190 If it does not match, nil is returned instead of the new string.
2191 Optional arg LITERAL means to take NEWTEXT literally.
2192 Optional arg GLOBAL means to replace all matches."
2193 (if global
2194 (let ((start 0) ret)
2195 (while (string-match regexp string start)
2196 (let ((from-end (- (length string) (match-end 0))))
2197 (setq ret (setq string (replace-match newtext t literal string)))
2198 (setq start (- (length string) from-end))))
2199 ret)
2200 (if (not (string-match regexp string 0))
2201 nil
2202 (replace-match newtext t literal string))))
2203
2204 (defun dired-make-absolute (file &optional dir)
2205 ;;"Convert FILE (a file name relative to DIR) to an absolute file name."
2206 ;; We can't always use expand-file-name as this would get rid of `.'
2207 ;; or expand in / instead default-directory if DIR=="".
2208 ;; This should be good enough for ange-ftp.
2209 ;; It should be reasonably fast, though, as it is called in
2210 ;; dired-get-filename.
2211 (concat (or dir default-directory) file))
2212
2213 (defun dired-make-relative (file &optional dir)
2214 "Convert FILE (an absolute file name) to a name relative to DIR.
2215 If DIR is omitted or nil, it defaults to `default-directory'.
2216 If FILE is not in the directory tree of DIR, return FILE
2217 unchanged."
2218 (or dir (setq dir default-directory))
2219 ;; This case comes into play if default-directory is set to
2220 ;; use ~.
2221 (if (and (> (length dir) 0) (= (aref dir 0) ?~))
2222 (setq dir (expand-file-name dir)))
2223 (if (string-match (concat "^" (regexp-quote dir)) file)
2224 (substring file (match-end 0))
2225 file))
2226 \f
2227 ;;; Functions for finding the file name in a dired buffer line.
2228
2229 (defvar dired-permission-flags-regexp
2230 "\\([^ ]\\)[-r][-w]\\([^ ]\\)[-r][-w]\\([^ ]\\)[-r][-w]\\([^ ]\\)"
2231 "Regular expression to match the permission flags in `ls -l'.")
2232
2233 ;; Move to first char of filename on this line.
2234 ;; Returns position (point) or nil if no filename on this line."
2235 (defun dired-move-to-filename (&optional raise-error eol)
2236 "Move to the beginning of the filename on the current line.
2237 Return the position of the beginning of the filename, or nil if none found."
2238 ;; This is the UNIX version.
2239 (or eol (setq eol (line-end-position)))
2240 (beginning-of-line)
2241 ;; First try assuming `ls --dired' was used.
2242 (let ((change (next-single-property-change (point) 'dired-filename nil eol)))
2243 (cond
2244 ((and change (< change eol))
2245 (goto-char change))
2246 ((re-search-forward directory-listing-before-filename-regexp eol t)
2247 (goto-char (match-end 0)))
2248 ((re-search-forward dired-permission-flags-regexp eol t)
2249 ;; Ha! There *is* a file. Our regexp-from-hell just failed to find it.
2250 (if raise-error
2251 (error "Unrecognized line! Check directory-listing-before-filename-regexp"))
2252 (beginning-of-line)
2253 nil)
2254 (raise-error
2255 (error "No file on this line")))))
2256
2257 (defun dired-move-to-end-of-filename (&optional no-error)
2258 ;; Assumes point is at beginning of filename,
2259 ;; thus the rwx bit re-search-backward below will succeed in *this*
2260 ;; line if at all. So, it should be called only after
2261 ;; (dired-move-to-filename t).
2262 ;; On failure, signals an error (with non-nil NO-ERROR just returns nil).
2263 ;; This is the UNIX version.
2264 (if (get-text-property (point) 'dired-filename)
2265 (goto-char (next-single-property-change (point) 'dired-filename))
2266 (let (opoint file-type executable symlink hidden case-fold-search used-F eol)
2267 ;; case-fold-search is nil now, so we can test for capital F:
2268 (setq used-F (string-match "F" dired-actual-switches)
2269 opoint (point)
2270 eol (line-end-position)
2271 hidden (and selective-display
2272 (save-excursion (search-forward "\r" eol t))))
2273 (if hidden
2274 nil
2275 (save-excursion ;; Find out what kind of file this is:
2276 ;; Restrict perm bits to be non-blank,
2277 ;; otherwise this matches one char to early (looking backward):
2278 ;; "l---------" (some systems make symlinks that way)
2279 ;; "----------" (plain file with zero perms)
2280 (if (re-search-backward
2281 dired-permission-flags-regexp nil t)
2282 (setq file-type (char-after (match-beginning 1))
2283 symlink (eq file-type ?l)
2284 ;; Only with -F we need to know whether it's an executable
2285 executable (and
2286 used-F
2287 (string-match
2288 "[xst]" ;; execute bit set anywhere?
2289 (concat
2290 (match-string 2)
2291 (match-string 3)
2292 (match-string 4)))))
2293 (or no-error (error "No file on this line"))))
2294 ;; Move point to end of name:
2295 (if symlink
2296 (if (search-forward " -> " eol t)
2297 (progn
2298 (forward-char -4)
2299 (and used-F
2300 dired-ls-F-marks-symlinks
2301 (eq (preceding-char) ?@) ;; did ls really mark the link?
2302 (forward-char -1))))
2303 (goto-char eol) ;; else not a symbolic link
2304 ;; ls -lF marks dirs, sockets, fifos and executables with exactly
2305 ;; one trailing character. (Executable bits on symlinks ain't mean
2306 ;; a thing, even to ls, but we know it's not a symlink.)
2307 (and used-F
2308 (or (memq file-type '(?d ?s ?p))
2309 executable)
2310 (forward-char -1))))
2311 (or no-error
2312 (not (eq opoint (point)))
2313 (error "%s" (if hidden
2314 (substitute-command-keys
2315 "File line is hidden, type \\[dired-hide-subdir] to unhide")
2316 "No file on this line")))
2317 (if (eq opoint (point))
2318 nil
2319 (point)))))
2320
2321 \f
2322 ;;; COPY NAMES OF MARKED FILES INTO KILL-RING.
2323
2324 (defun dired-copy-filename-as-kill (&optional arg)
2325 "Copy names of marked (or next ARG) files into the kill ring.
2326 The names are separated by a space.
2327 With a zero prefix arg, use the absolute file name of each marked file.
2328 With \\[universal-argument], use the file name relative to the dired buffer's
2329 `default-directory'. (This still may contain slashes if in a subdirectory.)
2330
2331 If on a subdir headerline, use absolute subdirname instead;
2332 prefix arg and marked files are ignored in this case.
2333
2334 You can then feed the file name(s) to other commands with \\[yank]."
2335 (interactive "P")
2336 (let ((string
2337 (or (dired-get-subdir)
2338 (mapconcat (function identity)
2339 (if arg
2340 (cond ((zerop (prefix-numeric-value arg))
2341 (dired-get-marked-files))
2342 ((consp arg)
2343 (dired-get-marked-files t))
2344 (t
2345 (dired-get-marked-files
2346 'no-dir (prefix-numeric-value arg))))
2347 (dired-get-marked-files 'no-dir))
2348 " "))))
2349 (if (eq last-command 'kill-region)
2350 (kill-append string nil)
2351 (kill-new string))
2352 (message "%s" string)))
2353
2354 \f
2355 ;; Keeping Dired buffers in sync with the filesystem and with each other
2356
2357 (defun dired-buffers-for-dir (dir &optional file)
2358 ;; Return a list of buffers for DIR (top level or in-situ subdir).
2359 ;; If FILE is non-nil, include only those whose wildcard pattern (if any)
2360 ;; matches FILE.
2361 ;; The list is in reverse order of buffer creation, most recent last.
2362 ;; As a side effect, killed dired buffers for DIR are removed from
2363 ;; dired-buffers.
2364 (setq dir (file-name-as-directory dir))
2365 (let (result buf)
2366 (dolist (elt dired-buffers)
2367 (setq buf (cdr elt))
2368 (cond
2369 ((null (buffer-name buf))
2370 ;; Buffer is killed - clean up:
2371 (setq dired-buffers (delq elt dired-buffers)))
2372 ((dired-in-this-tree dir (car elt))
2373 (with-current-buffer buf
2374 (and (assoc dir dired-subdir-alist)
2375 (or (null file)
2376 (if (stringp dired-directory)
2377 (let ((wildcards (file-name-nondirectory
2378 dired-directory)))
2379 (or (= 0 (length wildcards))
2380 (string-match (dired-glob-regexp wildcards)
2381 file)))
2382 (member (expand-file-name file dir)
2383 (cdr dired-directory))))
2384 (setq result (cons buf result)))))))
2385 result))
2386
2387 (defun dired-glob-regexp (pattern)
2388 "Convert glob-pattern PATTERN to a regular expression."
2389 (let ((matched-in-pattern 0) ;; How many chars of PATTERN we've handled.
2390 regexp)
2391 (while (string-match "[[?*]" pattern matched-in-pattern)
2392 (let ((op-end (match-end 0))
2393 (next-op (aref pattern (match-beginning 0))))
2394 (setq regexp (concat regexp
2395 (regexp-quote
2396 (substring pattern matched-in-pattern
2397 (match-beginning 0)))))
2398 (cond ((= next-op ??)
2399 (setq regexp (concat regexp "."))
2400 (setq matched-in-pattern op-end))
2401 ((= next-op ?\[)
2402 ;; Fails to handle ^ yet ????
2403 (let* ((set-start (match-beginning 0))
2404 (set-cont
2405 (if (= (aref pattern (1+ set-start)) ?^)
2406 (+ 3 set-start)
2407 (+ 2 set-start)))
2408 (set-end (string-match "]" pattern set-cont))
2409 (set (substring pattern set-start (1+ set-end))))
2410 (setq regexp (concat regexp set))
2411 (setq matched-in-pattern (1+ set-end))))
2412 ((= next-op ?*)
2413 (setq regexp (concat regexp ".*"))
2414 (setq matched-in-pattern op-end)))))
2415 (concat "\\`"
2416 regexp
2417 (regexp-quote
2418 (substring pattern matched-in-pattern))
2419 "\\'")))
2420
2421
2422
2423 (defun dired-advertise ()
2424 ;;"Advertise in variable `dired-buffers' that we dired `default-directory'."
2425 ;; With wildcards we actually advertise too much.
2426 (let ((expanded-default (expand-file-name default-directory)))
2427 (if (memq (current-buffer) (dired-buffers-for-dir expanded-default))
2428 t ; we have already advertised ourselves
2429 (setq dired-buffers
2430 (cons (cons expanded-default (current-buffer))
2431 dired-buffers)))))
2432
2433 (defun dired-unadvertise (dir)
2434 ;; Remove DIR from the buffer alist in variable dired-buffers.
2435 ;; This has the effect of removing any buffer whose main directory is DIR.
2436 ;; It does not affect buffers in which DIR is a subdir.
2437 ;; Removing is also done as a side-effect in dired-buffer-for-dir.
2438 (setq dired-buffers
2439 (delq (assoc (expand-file-name dir) dired-buffers) dired-buffers)))
2440 \f
2441 ;; Tree Dired
2442
2443 ;;; utility functions
2444
2445 (defun dired-in-this-tree (file dir)
2446 ;;"Is FILE part of the directory tree starting at DIR?"
2447 (let (case-fold-search)
2448 (string-match (concat "^" (regexp-quote dir)) file)))
2449
2450 (defun dired-normalize-subdir (dir)
2451 ;; Prepend default-directory to DIR if relative file name.
2452 ;; dired-get-filename must be able to make a valid file name from a
2453 ;; file and its directory DIR.
2454 (file-name-as-directory
2455 (if (file-name-absolute-p dir)
2456 dir
2457 (expand-file-name dir default-directory))))
2458
2459 (defun dired-get-subdir ()
2460 ;;"Return the subdir name on this line, or nil if not on a headerline."
2461 ;; Look up in the alist whether this is a headerline.
2462 (save-excursion
2463 (let ((cur-dir (dired-current-directory)))
2464 (beginning-of-line) ; alist stores b-o-l positions
2465 (and (zerop (- (point)
2466 (dired-get-subdir-min (assoc cur-dir
2467 dired-subdir-alist))))
2468 cur-dir))))
2469
2470 ;; can't use macro, must be redefinable for other alist format in dired-nstd.
2471 (defalias 'dired-get-subdir-min 'cdr)
2472
2473 (defun dired-get-subdir-max (elt)
2474 (save-excursion
2475 (goto-char (dired-get-subdir-min elt))
2476 (dired-subdir-max)))
2477
2478 (defun dired-clear-alist ()
2479 (while dired-subdir-alist
2480 (set-marker (dired-get-subdir-min (car dired-subdir-alist)) nil)
2481 (setq dired-subdir-alist (cdr dired-subdir-alist))))
2482
2483 (defun dired-subdir-index (dir)
2484 ;; Return an index into alist for use with nth
2485 ;; for the sake of subdir moving commands.
2486 (let (found (index 0) (alist dired-subdir-alist))
2487 (while alist
2488 (if (string= dir (car (car alist)))
2489 (setq alist nil found t)
2490 (setq alist (cdr alist) index (1+ index))))
2491 (if found index nil)))
2492
2493 (defun dired-next-subdir (arg &optional no-error-if-not-found no-skip)
2494 "Go to next subdirectory, regardless of level."
2495 ;; Use 0 arg to go to this directory's header line.
2496 ;; NO-SKIP prevents moving to end of header line, returning whatever
2497 ;; position was found in dired-subdir-alist.
2498 (interactive "p")
2499 (let ((this-dir (dired-current-directory))
2500 pos index)
2501 ;; nth with negative arg does not return nil but the first element
2502 (setq index (- (dired-subdir-index this-dir) arg))
2503 (setq pos (if (>= index 0)
2504 (dired-get-subdir-min (nth index dired-subdir-alist))))
2505 (if pos
2506 (progn
2507 (goto-char pos)
2508 (or no-skip (skip-chars-forward "^\n\r"))
2509 (point))
2510 (if no-error-if-not-found
2511 nil ; return nil if not found
2512 (error "%s directory" (if (> arg 0) "Last" "First"))))))
2513
2514 (defun dired-build-subdir-alist (&optional switches)
2515 "Build `dired-subdir-alist' by parsing the buffer.
2516 Returns the new value of the alist.
2517 If optional arg SWITCHES is non-nil, use its value
2518 instead of `dired-actual-switches'."
2519 (interactive)
2520 (dired-clear-alist)
2521 (save-excursion
2522 (let* ((count 0)
2523 (inhibit-read-only t)
2524 (buffer-undo-list t)
2525 (switches (or switches dired-actual-switches))
2526 new-dir-name
2527 (R-ftp-base-dir-regex
2528 ;; Used to expand subdirectory names correctly in recursive
2529 ;; ange-ftp listings.
2530 (and (string-match "R" switches)
2531 (string-match "\\`/.*:\\(/.*\\)" default-directory)
2532 (concat "\\`" (match-string 1 default-directory)))))
2533 (goto-char (point-min))
2534 (setq dired-subdir-alist nil)
2535 (while (re-search-forward dired-subdir-regexp nil t)
2536 ;; Avoid taking a file name ending in a colon
2537 ;; as a subdir name.
2538 (unless (save-excursion
2539 (goto-char (match-beginning 0))
2540 (beginning-of-line)
2541 (forward-char 2)
2542 (save-match-data (looking-at dired-re-perms)))
2543 (save-excursion
2544 (goto-char (match-beginning 1))
2545 (setq new-dir-name
2546 (buffer-substring-no-properties (point) (match-end 1))
2547 new-dir-name
2548 (save-match-data
2549 (if (and R-ftp-base-dir-regex
2550 (not (string= new-dir-name default-directory))
2551 (string-match R-ftp-base-dir-regex new-dir-name))
2552 (concat default-directory
2553 (substring new-dir-name (match-end 0)))
2554 (expand-file-name new-dir-name))))
2555 (delete-region (point) (match-end 1))
2556 (insert new-dir-name))
2557 (setq count (1+ count))
2558 ;; Undo any escaping of newlines and \ by dired-insert-directory.
2559 ;; Convert "n" preceded by odd number of \ to newline, and \\ to \.
2560 (when (and (dired-switches-escape-p switches)
2561 (string-match-p "\\\\" new-dir-name))
2562 (let (temp res)
2563 (mapc (lambda (char)
2564 (cond ((equal char ?\\)
2565 (if temp
2566 (setq res (concat res "\\")
2567 temp nil)
2568 (setq temp "\\")))
2569 ((and temp (equal char ?n))
2570 (setq res (concat res "\n")
2571 temp nil))
2572 (t
2573 (setq res (concat res temp (char-to-string char))
2574 temp nil))))
2575 new-dir-name)
2576 (setq new-dir-name res)))
2577 (dired-alist-add-1 new-dir-name
2578 ;; Place a sub directory boundary between lines.
2579 (save-excursion
2580 (goto-char (match-beginning 0))
2581 (beginning-of-line)
2582 (point-marker)))))
2583 (if (and (> count 1) (called-interactively-p 'interactive))
2584 (message "Buffer includes %d directories" count)))
2585 ;; We don't need to sort it because it is in buffer order per
2586 ;; constructionem. Return new alist:
2587 dired-subdir-alist))
2588
2589 (defun dired-alist-add-1 (dir new-marker)
2590 ;; Add new DIR at NEW-MARKER. Don't sort.
2591 (setq dired-subdir-alist
2592 (cons (cons (dired-normalize-subdir dir) new-marker)
2593 dired-subdir-alist)))
2594
2595 (defun dired-goto-next-nontrivial-file ()
2596 ;; Position point on first nontrivial file after point.
2597 (dired-goto-next-file);; so there is a file to compare with
2598 (if (stringp dired-trivial-filenames)
2599 (while (and (not (eobp))
2600 (string-match dired-trivial-filenames
2601 (file-name-nondirectory
2602 (or (dired-get-filename nil t) ""))))
2603 (forward-line 1)
2604 (dired-move-to-filename))))
2605
2606 (defun dired-goto-next-file ()
2607 (let ((max (1- (dired-subdir-max))))
2608 (while (and (not (dired-move-to-filename)) (< (point) max))
2609 (forward-line 1))))
2610
2611 (defun dired-goto-file (file)
2612 "Go to line describing file FILE in this dired buffer."
2613 ;; Return value of point on success, else nil.
2614 ;; FILE must be an absolute file name.
2615 ;; Loses if FILE contains control chars like "\007" for which ls
2616 ;; either inserts "?" or "\\007" into the buffer, so we won't find
2617 ;; it in the buffer.
2618 (interactive
2619 (prog1 ; let push-mark display its message
2620 (list (expand-file-name
2621 (read-file-name "Goto file: "
2622 (dired-current-directory))))
2623 (push-mark)))
2624 (unless (file-name-absolute-p file)
2625 (error "File name `%s' is not absolute" file))
2626 (setq file (directory-file-name file)) ; does no harm if not a directory
2627 (let* ((case-fold-search nil)
2628 (dir (file-name-directory file))
2629 (found (or
2630 ;; First, look for a listing under the absolute name.
2631 (save-excursion
2632 (goto-char (point-min))
2633 (dired-goto-file-1 file file (point-max)))
2634 ;; Otherwise, look for it as a relative name. The
2635 ;; hair is to get the result of `dired-goto-subdir'
2636 ;; without calling it if we don't have any subdirs.
2637 (save-excursion
2638 (when (if (string= dir (expand-file-name default-directory))
2639 (goto-char (point-min))
2640 (and (cdr dired-subdir-alist)
2641 (dired-goto-subdir dir)))
2642 (dired-goto-file-1 (file-name-nondirectory file)
2643 file
2644 (dired-subdir-max)))))))
2645 ;; Return buffer position, if found.
2646 (if found
2647 (goto-char found))))
2648
2649 (defun dired-goto-file-1 (file full-name limit)
2650 "Advance to the Dired listing labeled by FILE; return its position.
2651 Return nil if the listing is not found. If FILE contains
2652 characters that would not appear in a Dired buffer, search using
2653 the quoted forms of those characters.
2654
2655 FULL-NAME specifies the actual file name the listing must have,
2656 as returned by `dired-get-filename'. LIMIT is the search limit."
2657 (let (str)
2658 (setq str (replace-regexp-in-string "\^m" "\\^m" file nil t))
2659 (setq str (replace-regexp-in-string "\\\\" "\\\\" str nil t))
2660 (and (dired-switches-escape-p dired-actual-switches)
2661 (string-match "[ \t\n]" str)
2662 ;; FIXME: to fix this for embedded control characters etc, we
2663 ;; should escape everything that `ls -b' does.
2664 (setq str (replace-regexp-in-string " " "\\ " str nil t)
2665 str (replace-regexp-in-string "\t" "\\t" str nil t)
2666 str (replace-regexp-in-string "\n" "\\n" str nil t)))
2667 (let ((found nil)
2668 ;; filenames are preceded by SPC, this makes the search faster
2669 ;; (e.g. for the filename "-").
2670 (search-string (concat " " str)))
2671 (while (and (not found)
2672 (search-forward search-string limit 'move))
2673 ;; Check that we are in the right place. Match could have
2674 ;; BASE just as initial substring or in permission bits etc.
2675 (if (equal full-name (dired-get-filename nil t))
2676 (setq found (dired-move-to-filename))
2677 (forward-line 1)))
2678 found)))
2679
2680 (defvar dired-find-subdir)
2681
2682 ;; FIXME document whatever dired-x is doing.
2683 (defun dired-initial-position (dirname)
2684 "Where point should go in a new listing of DIRNAME.
2685 Point assumed at beginning of new subdir line."
2686 (end-of-line)
2687 (and (featurep 'dired-x) dired-find-subdir
2688 (dired-goto-subdir dirname))
2689 (if dired-trivial-filenames (dired-goto-next-nontrivial-file)))
2690 \f
2691 ;; These are hooks which make tree dired work.
2692 ;; They are in this file because other parts of dired need to call them.
2693 ;; But they don't call the rest of tree dired unless there are subdirs loaded.
2694
2695 ;; This function is called for each retrieved filename.
2696 ;; It could stand to be faster, though it's mostly function call
2697 ;; overhead. Avoiding the function call seems to save about 10% in
2698 ;; dired-get-filename. Make it a defsubst?
2699 (defun dired-current-directory (&optional localp)
2700 "Return the name of the subdirectory to which this line belongs.
2701 This returns a string with trailing slash, like `default-directory'.
2702 Optional argument means return a file name relative to `default-directory'."
2703 (let ((here (point))
2704 (alist (or dired-subdir-alist
2705 ;; probably because called in a non-dired buffer
2706 (error "No subdir-alist in %s" (current-buffer))))
2707 elt dir)
2708 (while alist
2709 (setq elt (car alist)
2710 dir (car elt)
2711 ;; use `<=' (not `<') as subdir line is part of subdir
2712 alist (if (<= (dired-get-subdir-min elt) here)
2713 nil ; found
2714 (cdr alist))))
2715 (if localp
2716 (dired-make-relative dir default-directory)
2717 dir)))
2718
2719 ;; Subdirs start at the beginning of their header lines and end just
2720 ;; before the beginning of the next header line (or end of buffer).
2721
2722 (defun dired-subdir-max ()
2723 (save-excursion
2724 (if (or (null (cdr dired-subdir-alist)) (not (dired-next-subdir 1 t t)))
2725 (point-max)
2726 (point))))
2727 \f
2728 ;; Deleting files
2729
2730 (defcustom dired-recursive-deletes 'top
2731 "Whether Dired deletes directories recursively.
2732 If nil, Dired will not delete non-empty directories.
2733 `always' means to delete non-empty directories recursively,
2734 without asking. This is dangerous!
2735 `top' means to ask for each top-level directory specified by the
2736 Dired deletion command, and delete its subdirectories without
2737 asking.
2738 Any other value means to ask for each directory."
2739 :type '(choice :tag "Delete non-empty directories"
2740 (const :tag "Yes" always)
2741 (const :tag "No--only delete empty directories" nil)
2742 (const :tag "Confirm for each directory" t)
2743 (const :tag "Confirm for each top directory only" top))
2744 :group 'dired)
2745
2746 ;; Match anything but `.' and `..'.
2747 (defvar dired-re-no-dot "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")
2748
2749 ;; Delete file, possibly delete a directory and all its files.
2750 ;; This function is useful outside of dired. One could change its name
2751 ;; to e.g. recursive-delete-file and put it somewhere else.
2752 (defun dired-delete-file (file &optional recursive trash) "\
2753 Delete FILE or directory (possibly recursively if optional RECURSIVE is true.)
2754 RECURSIVE determines what to do with a non-empty directory. If RECURSIVE is:
2755 nil, do not delete.
2756 `always', delete recursively without asking.
2757 `top', ask for each directory at top level.
2758 Anything else, ask for each sub-directory."
2759 ;; This test is equivalent to
2760 ;; (and (file-directory-p fn) (not (file-symlink-p fn)))
2761 ;; but more efficient
2762 (if (not (eq t (car (file-attributes file))))
2763 (delete-file file trash)
2764 (if (and recursive
2765 (directory-files file t dired-re-no-dot) ; Not empty.
2766 (or (eq recursive 'always)
2767 (yes-or-no-p (format "Recursively %s %s? "
2768 (if (and trash
2769 delete-by-moving-to-trash)
2770 "trash"
2771 "delete")
2772 (dired-make-relative file)))))
2773 (if (eq recursive 'top) (setq recursive 'always)) ; Don't ask again.
2774 (setq recursive nil))
2775 (delete-directory file recursive trash)))
2776
2777 (defun dired-do-flagged-delete (&optional nomessage)
2778 "In Dired, delete the files flagged for deletion.
2779 If NOMESSAGE is non-nil, we don't display any message
2780 if there are no flagged files.
2781 `dired-recursive-deletes' controls whether deletion of
2782 non-empty directories is allowed."
2783 (interactive)
2784 (let* ((dired-marker-char dired-del-marker)
2785 (regexp (dired-marker-regexp))
2786 case-fold-search)
2787 (if (save-excursion (goto-char (point-min))
2788 (re-search-forward regexp nil t))
2789 (dired-internal-do-deletions
2790 ;; this can't move point since ARG is nil
2791 (dired-map-over-marks (cons (dired-get-filename) (point))
2792 nil)
2793 nil t)
2794 (or nomessage
2795 (message "(No deletions requested)")))))
2796
2797 (defun dired-do-delete (&optional arg)
2798 "Delete all marked (or next ARG) files.
2799 `dired-recursive-deletes' controls whether deletion of
2800 non-empty directories is allowed."
2801 ;; This is more consistent with the file marking feature than
2802 ;; dired-do-flagged-delete.
2803 (interactive "P")
2804 (dired-internal-do-deletions
2805 ;; this may move point if ARG is an integer
2806 (dired-map-over-marks (cons (dired-get-filename) (point))
2807 arg)
2808 arg t))
2809
2810 (defvar dired-deletion-confirmer 'yes-or-no-p) ; or y-or-n-p?
2811
2812 (defun dired-internal-do-deletions (l arg &optional trash)
2813 ;; L is an alist of files to delete, with their buffer positions.
2814 ;; ARG is the prefix arg.
2815 ;; Filenames are absolute.
2816 ;; (car L) *must* be the *last* (bottommost) file in the dired buffer.
2817 ;; That way as changes are made in the buffer they do not shift the
2818 ;; lines still to be changed, so the (point) values in L stay valid.
2819 ;; Also, for subdirs in natural order, a subdir's files are deleted
2820 ;; before the subdir itself - the other way around would not work.
2821 (let* ((files (mapcar (function car) l))
2822 (count (length l))
2823 (succ 0)
2824 (trashing (and trash delete-by-moving-to-trash))
2825 (progress-reporter
2826 (make-progress-reporter
2827 (if trashing "Trashing..." "Deleting...")
2828 succ count)))
2829 ;; canonicalize file list for pop up
2830 (setq files (nreverse (mapcar (function dired-make-relative) files)))
2831 (if (dired-mark-pop-up
2832 " *Deletions*" 'delete files dired-deletion-confirmer
2833 (format "%s %s "
2834 (if trashing "Trash" "Delete")
2835 (dired-mark-prompt arg files)))
2836 (save-excursion
2837 (let (failures);; files better be in reverse order for this loop!
2838 (while l
2839 (goto-char (cdr (car l)))
2840 (let ((inhibit-read-only t))
2841 (condition-case err
2842 (let ((fn (car (car l))))
2843 (dired-delete-file fn dired-recursive-deletes trash)
2844 ;; if we get here, removing worked
2845 (setq succ (1+ succ))
2846 (progress-reporter-update progress-reporter succ)
2847 (dired-fun-in-all-buffers
2848 (file-name-directory fn) (file-name-nondirectory fn)
2849 (function dired-delete-entry) fn))
2850 (error;; catch errors from failed deletions
2851 (dired-log "%s\n" err)
2852 (setq failures (cons (car (car l)) failures)))))
2853 (setq l (cdr l)))
2854 (if (not failures)
2855 (progress-reporter-done progress-reporter)
2856 (dired-log-summary
2857 (format "%d of %d deletion%s failed"
2858 (length failures) count
2859 (dired-plural-s count))
2860 failures))))
2861 (message "(No deletions performed)")))
2862 (dired-move-to-filename))
2863
2864 (defun dired-fun-in-all-buffers (directory file fun &rest args)
2865 ;; In all buffers dired'ing DIRECTORY, run FUN with ARGS.
2866 ;; If the buffer has a wildcard pattern, check that it matches FILE.
2867 ;; (FILE does not include a directory component.)
2868 ;; FILE may be nil, in which case ignore it.
2869 ;; Return list of buffers where FUN succeeded (i.e., returned non-nil).
2870 (let (success-list)
2871 (dolist (buf (dired-buffers-for-dir (expand-file-name directory)
2872 file))
2873 (with-current-buffer buf
2874 (if (apply fun args)
2875 (setq success-list (cons (buffer-name buf) success-list)))))
2876 success-list))
2877
2878 ;; Delete the entry for FILE from
2879 (defun dired-delete-entry (file)
2880 (save-excursion
2881 (and (dired-goto-file file)
2882 (let ((inhibit-read-only t))
2883 (delete-region (progn (beginning-of-line) (point))
2884 (save-excursion (forward-line 1) (point))))))
2885 (dired-clean-up-after-deletion file))
2886
2887 (defvar dired-clean-up-buffers-too)
2888
2889 (defun dired-clean-up-after-deletion (fn)
2890 "Clean up after a deleted file or directory FN.
2891 Removes any expanded subdirectory of deleted directory.
2892 If `dired-x' is loaded and `dired-clean-up-buffers-too' is non-nil,
2893 also offers to kill buffers visiting deleted files and directories."
2894 (save-excursion (and (cdr dired-subdir-alist)
2895 (dired-goto-subdir fn)
2896 (dired-kill-subdir)))
2897 ;; Offer to kill buffer of deleted file FN.
2898 (when (and (featurep 'dired-x) dired-clean-up-buffers-too)
2899 (let ((buf (get-file-buffer fn)))
2900 (and buf
2901 (funcall #'y-or-n-p
2902 (format "Kill buffer of %s, too? "
2903 (file-name-nondirectory fn)))
2904 (kill-buffer buf)))
2905 (let ((buf-list (dired-buffers-for-dir (expand-file-name fn))))
2906 (and buf-list
2907 (y-or-n-p (format "Kill dired buffer%s of %s, too? "
2908 (dired-plural-s (length buf-list))
2909 (file-name-nondirectory fn)))
2910 (dolist (buf buf-list)
2911 (kill-buffer buf))))))
2912
2913 \f
2914 ;; Confirmation
2915
2916 (defun dired-marker-regexp ()
2917 (concat "^" (regexp-quote (char-to-string dired-marker-char))))
2918
2919 (defun dired-plural-s (count)
2920 (if (= 1 count) "" "s"))
2921
2922 (defun dired-mark-prompt (arg files)
2923 "Return a string suitable for use in a Dired prompt.
2924 ARG is normally the prefix argument for the calling command.
2925 FILES should be a list of file names.
2926
2927 The return value has a form like \"foo.txt\", \"[next 3 files]\",
2928 or \"* [3 files]\"."
2929 ;; distinguish-one-marked can cause the first element to be just t.
2930 (if (eq (car files) t) (setq files (cdr files)))
2931 (let ((count (length files)))
2932 (if (= count 1)
2933 (car files)
2934 ;; more than 1 file:
2935 (if (integerp arg)
2936 ;; abs(arg) = count
2937 ;; Perhaps this is nicer, but it also takes more screen space:
2938 ;;(format "[%s %d files]" (if (> arg 0) "next" "previous")
2939 ;; count)
2940 (format "[next %d files]" arg)
2941 (format "%c [%d files]" dired-marker-char count)))))
2942
2943 (defun dired-pop-to-buffer (buf)
2944 "Pop up buffer BUF in a way suitable for Dired."
2945 (let ((split-window-preferred-function
2946 (lambda (window)
2947 (or (and (let ((split-height-threshold 0))
2948 (window-splittable-p (selected-window)))
2949 ;; Try to split the selected window vertically if
2950 ;; that's possible. (Bug#1806)
2951 (split-window-below))
2952 ;; Otherwise, try to split WINDOW sensibly.
2953 (split-window-sensibly window))))
2954 pop-up-frames)
2955 (pop-to-buffer (get-buffer-create buf)))
2956 ;; If dired-shrink-to-fit is t, make its window fit its contents.
2957 (when dired-shrink-to-fit
2958 ;; Try to not delete window when we want to display less than
2959 ;; `window-min-height' lines.
2960 (fit-window-to-buffer (get-buffer-window buf) nil 1)))
2961
2962 (defcustom dired-no-confirm nil
2963 "A list of symbols for commands Dired should not confirm, or t.
2964 Command symbols are `byte-compile', `chgrp', `chmod', `chown', `compress',
2965 `copy', `delete', `hardlink', `load', `move', `print', `shell', `symlink',
2966 `touch' and `uncompress'.
2967 If t, confirmation is never needed."
2968 :group 'dired
2969 :type '(choice (const :tag "Confirmation never needed" t)
2970 (set (const byte-compile) (const chgrp)
2971 (const chmod) (const chown) (const compress)
2972 (const copy) (const delete) (const hardlink)
2973 (const load) (const move) (const print)
2974 (const shell) (const symlink) (const touch)
2975 (const uncompress))))
2976
2977 (defun dired-mark-pop-up (bufname op-symbol files function &rest args)
2978 "Return FUNCTION's result on ARGS after showing which files are marked.
2979 Displays the file names in a buffer named BUFNAME;
2980 nil gives \" *Marked Files*\".
2981 This uses function `dired-pop-to-buffer' to do that.
2982
2983 FUNCTION should not manipulate files, just read input
2984 (an argument or confirmation).
2985 The window is not shown if there is just one file or
2986 OP-SYMBOL is a member of the list in `dired-no-confirm'.
2987 FILES is the list of marked files. It can also be (t FILENAME)
2988 in the case of one marked file, to distinguish that from using
2989 just the current file."
2990 (or bufname (setq bufname " *Marked Files*"))
2991 (if (or (eq dired-no-confirm t)
2992 (memq op-symbol dired-no-confirm)
2993 ;; If FILES defaulted to the current line's file.
2994 (= (length files) 1))
2995 (apply function args)
2996 (with-current-buffer (get-buffer-create bufname)
2997 (erase-buffer)
2998 ;; Handle (t FILE) just like (FILE), here.
2999 ;; That value is used (only in some cases), to mean
3000 ;; just one file that was marked, rather than the current line file.
3001 (dired-format-columns-of-files (if (eq (car files) t) (cdr files) files))
3002 (remove-text-properties (point-min) (point-max)
3003 '(mouse-face nil help-echo nil)))
3004 (save-window-excursion
3005 (dired-pop-to-buffer bufname)
3006 (apply function args))))
3007
3008 (defun dired-format-columns-of-files (files)
3009 (let ((beg (point)))
3010 (completion--insert-strings files)
3011 (put-text-property beg (point) 'mouse-face nil)))
3012 \f
3013 ;; Commands to mark or flag file(s) at or near current line.
3014
3015 (defun dired-repeat-over-lines (arg function)
3016 ;; This version skips non-file lines.
3017 (let ((pos (make-marker)))
3018 (beginning-of-line)
3019 (while (and (> arg 0) (not (eobp)))
3020 (setq arg (1- arg))
3021 (beginning-of-line)
3022 (while (and (not (eobp)) (dired-between-files)) (forward-line 1))
3023 (save-excursion
3024 (forward-line 1)
3025 (move-marker pos (1+ (point))))
3026 (save-excursion (funcall function))
3027 ;; Advance to the next line--actually, to the line that *was* next.
3028 ;; (If FUNCTION inserted some new lines in between, skip them.)
3029 (goto-char pos))
3030 (while (and (< arg 0) (not (bobp)))
3031 (setq arg (1+ arg))
3032 (forward-line -1)
3033 (while (and (not (bobp)) (dired-between-files)) (forward-line -1))
3034 (beginning-of-line)
3035 (save-excursion (funcall function)))
3036 (move-marker pos nil)
3037 (dired-move-to-filename)))
3038
3039 (defun dired-between-files ()
3040 ;; This used to be a regexp match of the `total ...' line output by
3041 ;; ls, which is slightly faster, but that is not very robust; notably,
3042 ;; it fails for non-english locales.
3043 (save-excursion (not (dired-move-to-filename))))
3044
3045 (defun dired-next-marked-file (arg &optional wrap opoint)
3046 "Move to the next marked file, wrapping around the end of the buffer."
3047 (interactive "p\np")
3048 (or opoint (setq opoint (point)));; return to where interactively started
3049 (if (if (> arg 0)
3050 (re-search-forward dired-re-mark nil t arg)
3051 (beginning-of-line)
3052 (re-search-backward dired-re-mark nil t (- arg)))
3053 (dired-move-to-filename)
3054 (if (null wrap)
3055 (progn
3056 (goto-char opoint)
3057 (error "No next marked file"))
3058 (message "(Wraparound for next marked file)")
3059 (goto-char (if (> arg 0) (point-min) (point-max)))
3060 (dired-next-marked-file arg nil opoint))))
3061
3062 (defun dired-prev-marked-file (arg &optional wrap)
3063 "Move to the previous marked file, wrapping around the end of the buffer."
3064 (interactive "p\np")
3065 (dired-next-marked-file (- arg) wrap))
3066
3067 (defun dired-file-marker (file)
3068 ;; Return FILE's marker, or nil if unmarked.
3069 (save-excursion
3070 (and (dired-goto-file file)
3071 (progn
3072 (beginning-of-line)
3073 (if (not (equal ?\040 (following-char)))
3074 (following-char))))))
3075
3076 (defun dired-mark-files-in-region (start end)
3077 (let ((inhibit-read-only t))
3078 (if (> start end)
3079 (error "start > end"))
3080 (goto-char start) ; assumed at beginning of line
3081 (while (< (point) end)
3082 ;; Skip subdir line and following garbage like the `total' line:
3083 (while (and (< (point) end) (dired-between-files))
3084 (forward-line 1))
3085 (if (and (not (looking-at dired-re-dot))
3086 (dired-get-filename nil t))
3087 (progn
3088 (delete-char 1)
3089 (insert dired-marker-char)))
3090 (forward-line 1))))
3091
3092 (defun dired-mark (arg)
3093 "Mark the current (or next ARG) files.
3094 If on a subdir headerline, mark all its files except `.' and `..'.
3095
3096 Use \\[dired-unmark-all-files] to remove all marks
3097 and \\[dired-unmark] on a subdir to remove the marks in
3098 this subdir."
3099 (interactive "P")
3100 (if (dired-get-subdir)
3101 (save-excursion (dired-mark-subdir-files))
3102 (let ((inhibit-read-only t))
3103 (dired-repeat-over-lines
3104 (prefix-numeric-value arg)
3105 (function (lambda () (delete-char 1) (insert dired-marker-char)))))))
3106
3107 (defun dired-unmark (arg)
3108 "Unmark the current (or next ARG) files.
3109 If looking at a subdir, unmark all its files except `.' and `..'."
3110 (interactive "P")
3111 (let ((dired-marker-char ?\040))
3112 (dired-mark arg)))
3113
3114 (defun dired-flag-file-deletion (arg)
3115 "In Dired, flag the current line's file for deletion.
3116 With prefix arg, repeat over several lines.
3117
3118 If on a subdir headerline, mark all its files except `.' and `..'."
3119 (interactive "P")
3120 (let ((dired-marker-char dired-del-marker))
3121 (dired-mark arg)))
3122
3123 (defun dired-unmark-backward (arg)
3124 "In Dired, move up lines and remove marks or deletion flags there.
3125 Optional prefix ARG says how many lines to unmark/unflag; default
3126 is one line."
3127 (interactive "p")
3128 (dired-unmark (- arg)))
3129
3130 (defun dired-toggle-marks ()
3131 "Toggle marks: marked files become unmarked, and vice versa.
3132 Files marked with other flags (such as `D') are not affected.
3133 `.' and `..' are never toggled.
3134 As always, hidden subdirs are not affected."
3135 (interactive)
3136 (save-excursion
3137 (goto-char (point-min))
3138 (let ((inhibit-read-only t))
3139 (while (not (eobp))
3140 (or (dired-between-files)
3141 (looking-at dired-re-dot)
3142 ;; use subst instead of insdel because it does not move
3143 ;; the gap and thus should be faster and because
3144 ;; other characters are left alone automatically
3145 (apply 'subst-char-in-region
3146 (point) (1+ (point))
3147 (if (eq ?\040 (following-char)) ; SPC
3148 (list ?\040 dired-marker-char)
3149 (list dired-marker-char ?\040))))
3150 (forward-line 1)))))
3151 \f
3152 ;;; Commands to mark or flag files based on their characteristics or names.
3153
3154 (defvar dired-regexp-history nil
3155 "History list of regular expressions used in Dired commands.")
3156
3157 (defun dired-read-regexp (prompt)
3158 (read-from-minibuffer prompt nil nil nil 'dired-regexp-history))
3159
3160 (defun dired-mark-files-regexp (regexp &optional marker-char)
3161 "Mark all files matching REGEXP for use in later commands.
3162 A prefix argument means to unmark them instead.
3163 `.' and `..' are never marked.
3164
3165 REGEXP is an Emacs regexp, not a shell wildcard. Thus, use `\\.o$' for
3166 object files--just `.o' will mark more than you might think."
3167 (interactive
3168 (list (dired-read-regexp (concat (if current-prefix-arg "Unmark" "Mark")
3169 " files (regexp): "))
3170 (if current-prefix-arg ?\040)))
3171 (let ((dired-marker-char (or marker-char dired-marker-char)))
3172 (dired-mark-if
3173 (and (not (looking-at dired-re-dot))
3174 (not (eolp)) ; empty line
3175 (let ((fn (dired-get-filename t t)))
3176 (and fn (string-match regexp fn))))
3177 "matching file")))
3178
3179 (defun dired-mark-files-containing-regexp (regexp &optional marker-char)
3180 "Mark all files with contents containing REGEXP for use in later commands.
3181 A prefix argument means to unmark them instead.
3182 `.' and `..' are never marked."
3183 (interactive
3184 (list (dired-read-regexp (concat (if current-prefix-arg "Unmark" "Mark")
3185 " files containing (regexp): "))
3186 (if current-prefix-arg ?\040)))
3187 (let ((dired-marker-char (or marker-char dired-marker-char)))
3188 (dired-mark-if
3189 (and (not (looking-at dired-re-dot))
3190 (not (eolp)) ; empty line
3191 (let ((fn (dired-get-filename nil t)))
3192 (when (and fn (file-readable-p fn)
3193 (not (file-directory-p fn)))
3194 (let ((prebuf (get-file-buffer fn)))
3195 (message "Checking %s" fn)
3196 ;; For now we do it inside emacs
3197 ;; Grep might be better if there are a lot of files
3198 (if prebuf
3199 (with-current-buffer prebuf
3200 (save-excursion
3201 (goto-char (point-min))
3202 (re-search-forward regexp nil t)))
3203 (with-temp-buffer
3204 (insert-file-contents fn)
3205 (goto-char (point-min))
3206 (re-search-forward regexp nil t))))
3207 )))
3208 "matching file")))
3209
3210 (defun dired-flag-files-regexp (regexp)
3211 "In Dired, flag all files containing the specified REGEXP for deletion.
3212 The match is against the non-directory part of the filename. Use `^'
3213 and `$' to anchor matches. Exclude subdirs by hiding them.
3214 `.' and `..' are never flagged."
3215 (interactive (list (dired-read-regexp "Flag for deletion (regexp): ")))
3216 (dired-mark-files-regexp regexp dired-del-marker))
3217
3218 (defun dired-mark-symlinks (unflag-p)
3219 "Mark all symbolic links.
3220 With prefix argument, unmark or unflag all those files."
3221 (interactive "P")
3222 (let ((dired-marker-char (if unflag-p ?\040 dired-marker-char)))
3223 (dired-mark-if (looking-at dired-re-sym) "symbolic link")))
3224
3225 (defun dired-mark-directories (unflag-p)
3226 "Mark all directory file lines except `.' and `..'.
3227 With prefix argument, unmark or unflag all those files."
3228 (interactive "P")
3229 (let ((dired-marker-char (if unflag-p ?\040 dired-marker-char)))
3230 (dired-mark-if (and (looking-at dired-re-dir)
3231 (not (looking-at dired-re-dot)))
3232 "directory file")))
3233
3234 (defun dired-mark-executables (unflag-p)
3235 "Mark all executable files.
3236 With prefix argument, unmark or unflag all those files."
3237 (interactive "P")
3238 (let ((dired-marker-char (if unflag-p ?\040 dired-marker-char)))
3239 (dired-mark-if (looking-at dired-re-exe) "executable file")))
3240
3241 ;; dired-x.el has a dired-mark-sexp interactive command: mark
3242 ;; files for which PREDICATE returns non-nil.
3243
3244 (defun dired-flag-auto-save-files (&optional unflag-p)
3245 "Flag for deletion files whose names suggest they are auto save files.
3246 A prefix argument says to unmark or unflag those files instead."
3247 (interactive "P")
3248 (let ((dired-marker-char (if unflag-p ?\040 dired-del-marker)))
3249 (dired-mark-if
3250 ;; It is less than general to check for # here,
3251 ;; but it's the only way this runs fast enough.
3252 (and (save-excursion (end-of-line)
3253 (or
3254 (eq (preceding-char) ?#)
3255 ;; Handle executables in case of -F option.
3256 ;; We need not worry about the other kinds
3257 ;; of markings that -F makes, since they won't
3258 ;; appear on real auto-save files.
3259 (if (eq (preceding-char) ?*)
3260 (progn
3261 (forward-char -1)
3262 (eq (preceding-char) ?#)))))
3263 (not (looking-at dired-re-dir))
3264 (let ((fn (dired-get-filename t t)))
3265 (if fn (auto-save-file-name-p
3266 (file-name-nondirectory fn)))))
3267 "auto save file")))
3268
3269 (defcustom dired-garbage-files-regexp
3270 ;; `log' here is dubious, since it's typically used for useful log
3271 ;; files, not just TeX stuff. -- fx
3272 (concat (regexp-opt
3273 '(".log" ".toc" ".dvi" ".bak" ".orig" ".rej" ".aux"))
3274 "\\'")
3275 "Regular expression to match \"garbage\" files for `dired-flag-garbage-files'."
3276 :type 'regexp
3277 :group 'dired)
3278
3279 (defun dired-flag-garbage-files ()
3280 "Flag for deletion all files that match `dired-garbage-files-regexp'."
3281 (interactive)
3282 (dired-flag-files-regexp dired-garbage-files-regexp))
3283
3284 (defun dired-flag-backup-files (&optional unflag-p)
3285 "Flag all backup files (names ending with `~') for deletion.
3286 With prefix argument, unmark or unflag these files."
3287 (interactive "P")
3288 (let ((dired-marker-char (if unflag-p ?\s dired-del-marker)))
3289 (dired-mark-if
3290 ;; Don't call backup-file-name-p unless the last character looks like
3291 ;; it might be the end of a backup file name. This isn't very general,
3292 ;; but it's the only way this runs fast enough.
3293 (and (save-excursion (end-of-line)
3294 ;; Handle executables in case of -F option.
3295 ;; We need not worry about the other kinds
3296 ;; of markings that -F makes, since they won't
3297 ;; appear on real backup files.
3298 (if (eq (preceding-char) ?*)
3299 (forward-char -1))
3300 (eq (preceding-char) ?~))
3301 (not (looking-at dired-re-dir))
3302 (let ((fn (dired-get-filename t t)))
3303 (if fn (backup-file-name-p fn))))
3304 "backup file")))
3305
3306 (defun dired-change-marks (&optional old new)
3307 "Change all OLD marks to NEW marks.
3308 OLD and NEW are both characters used to mark files."
3309 (interactive
3310 (let* ((cursor-in-echo-area t)
3311 (old (progn (message "Change (old mark): ") (read-char)))
3312 (new (progn (message "Change %c marks to (new mark): " old)
3313 (read-char))))
3314 (list old new)))
3315 (if (or (eq old ?\r) (eq new ?\r))
3316 (ding)
3317 (let ((string (format "\n%c" old))
3318 (inhibit-read-only t))
3319 (save-excursion
3320 (goto-char (point-min))
3321 (while (search-forward string nil t)
3322 (if (if (= old ?\s)
3323 (save-match-data
3324 (dired-get-filename 'no-dir t))
3325 t)
3326 (subst-char-in-region (match-beginning 0)
3327 (match-end 0) old new)))))))
3328
3329 (defun dired-unmark-all-marks ()
3330 "Remove all marks from all files in the dired buffer."
3331 (interactive)
3332 (dired-unmark-all-files ?\r))
3333
3334 (defun dired-unmark-all-files (mark &optional arg)
3335 "Remove a specific mark (or any mark) from every file.
3336 After this command, type the mark character to remove,
3337 or type RET to remove all marks.
3338 With prefix arg, query for each marked file.
3339 Type \\[help-command] at that time for help."
3340 (interactive "cRemove marks (RET means all): \nP")
3341 (save-excursion
3342 (let* ((count 0)
3343 (inhibit-read-only t) case-fold-search
3344 (string (format "\n%c" mark))
3345 (help-form "\
3346 Type SPC or `y' to unmark one file, DEL or `n' to skip to next,
3347 `!' to unmark all remaining files with no more questions."))
3348 (goto-char (point-min))
3349 (while (if (eq mark ?\r)
3350 (re-search-forward dired-re-mark nil t)
3351 (search-forward string nil t))
3352 (if (or (not arg)
3353 (let ((file (dired-get-filename t t)))
3354 (and file
3355 (dired-query 'query "Unmark file `%s'? "
3356 file))))
3357 (progn (subst-char-in-region (1- (point)) (point)
3358 (preceding-char) ?\s)
3359 (setq count (1+ count)))))
3360 (message (if (= count 1) "1 mark removed"
3361 "%d marks removed")
3362 count))))
3363 \f
3364 ;; Logging failures operating on files, and showing the results.
3365
3366 (defvar dired-log-buffer "*Dired log*")
3367
3368 (defun dired-why ()
3369 "Pop up a buffer with error log output from Dired.
3370 A group of errors from a single command ends with a formfeed.
3371 Thus, use \\[backward-page] to find the beginning of a group of errors."
3372 (interactive)
3373 (if (get-buffer dired-log-buffer)
3374 (let ((owindow (selected-window))
3375 (window (display-buffer (get-buffer dired-log-buffer))))
3376 (unwind-protect
3377 (progn
3378 (select-window window)
3379 (goto-char (point-max))
3380 (forward-line -1)
3381 (backward-page 1)
3382 (recenter 0))
3383 (select-window owindow)))))
3384
3385 (defun dired-log (log &rest args)
3386 ;; Log a message or the contents of a buffer.
3387 ;; If LOG is a string and there are more args, it is formatted with
3388 ;; those ARGS. Usually the LOG string ends with a \n.
3389 ;; End each bunch of errors with (dired-log t):
3390 ;; this inserts the current time and buffer at the start of the page,
3391 ;; and \f (formfeed) at the end.
3392 (let ((obuf (current-buffer)))
3393 (with-current-buffer (get-buffer-create dired-log-buffer)
3394 (goto-char (point-max))
3395 (let ((inhibit-read-only t))
3396 (cond ((stringp log)
3397 (insert (if args
3398 (apply (function format) log args)
3399 log)))
3400 ((bufferp log)
3401 (insert-buffer-substring log))
3402 ((eq t log)
3403 (backward-page 1)
3404 (unless (bolp)
3405 (insert "\n"))
3406 (insert (current-time-string)
3407 "\tBuffer `" (buffer-name obuf) "'\n")
3408 (goto-char (point-max))
3409 (insert "\f\n")))))))
3410
3411 (defun dired-log-summary (string failures)
3412 "State a summary of a command's failures, in echo area and log buffer.
3413 STRING is an overall summary of the failures.
3414 FAILURES is a list of file names that we failed to operate on,
3415 or nil if file names are not applicable."
3416 (if (= (length failures) 1)
3417 (message "%s"
3418 (with-current-buffer dired-log-buffer
3419 (goto-char (point-max))
3420 (backward-page 1)
3421 (if (eolp) (forward-line 1))
3422 (buffer-substring (point) (point-max))))
3423 (message (if failures "%s--type ? for details (%s)"
3424 "%s--type ? for details")
3425 string failures))
3426 ;; Log a summary describing a bunch of errors.
3427 (dired-log (concat "\n" string "\n"))
3428 (dired-log t))
3429 \f
3430 ;;; Sorting
3431
3432 ;; Most ls can only sort by name or by date (with -t), nothing else.
3433 ;; GNU ls sorts on size with -S, on extension with -X, and unsorted with -U.
3434 ;; So anything that does not contain these is sort "by name".
3435
3436 (defvar dired-ls-sorting-switches "SXU"
3437 "String of `ls' switches \(single letters\) except \"t\" that influence sorting.
3438
3439 This indicates to Dired which option switches to watch out for because they
3440 will change the sorting order behavior of `ls'.
3441
3442 To change the default sorting order \(e.g. add a `-v' option\), see the
3443 variable `dired-listing-switches'. To temporarily override the listing
3444 format, use `\\[universal-argument] \\[dired]'.")
3445
3446 (defvar dired-sort-by-date-regexp
3447 (concat "\\(\\`\\| \\)-[^- ]*t"
3448 ;; `dired-ls-sorting-switches' after -t overrides -t.
3449 "[^ " dired-ls-sorting-switches "]*"
3450 "\\(\\(\\`\\| +\\)\\(--[^ ]+\\|-[^- t"
3451 dired-ls-sorting-switches "]+\\)\\)* *$")
3452 "Regexp recognized by Dired to set `by date' mode.")
3453
3454 (defvar dired-sort-by-name-regexp
3455 (concat "\\`\\(\\(\\`\\| +\\)\\(--[^ ]+\\|"
3456 "-[^- t" dired-ls-sorting-switches "]+\\)\\)* *$")
3457 "Regexp recognized by Dired to set `by name' mode.")
3458
3459 (defvar dired-sort-inhibit nil
3460 "Non-nil means the Dired sort command is disabled.
3461 The idea is to set this buffer-locally in special dired buffers.")
3462
3463 (defun dired-sort-set-mode-line ()
3464 ;; Set mode line display according to dired-actual-switches.
3465 ;; Mode line display of "by name" or "by date" guarantees the user a
3466 ;; match with the corresponding regexps. Non-matching switches are
3467 ;; shown literally.
3468 (when (eq major-mode 'dired-mode)
3469 (setq mode-name
3470 (let (case-fold-search)
3471 (cond ((string-match
3472 dired-sort-by-name-regexp dired-actual-switches)
3473 "Dired by name")
3474 ((string-match
3475 dired-sort-by-date-regexp dired-actual-switches)
3476 "Dired by date")
3477 (t
3478 (concat "Dired " dired-actual-switches)))))
3479 (force-mode-line-update)))
3480
3481 (define-obsolete-function-alias 'dired-sort-set-modeline
3482 'dired-sort-set-mode-line "24.2")
3483
3484 (defun dired-sort-toggle-or-edit (&optional arg)
3485 "Toggle sorting by date, and refresh the Dired buffer.
3486 With a prefix argument, edit the current listing switches instead."
3487 (interactive "P")
3488 (when dired-sort-inhibit
3489 (error "Cannot sort this dired buffer"))
3490 (if arg
3491 (dired-sort-other
3492 (read-string "ls switches (must contain -l): " dired-actual-switches))
3493 (dired-sort-toggle)))
3494
3495 (defun dired-sort-toggle ()
3496 ;; Toggle between sort by date/name. Reverts the buffer.
3497 (let ((sorting-by-date (string-match dired-sort-by-date-regexp
3498 dired-actual-switches))
3499 ;; Regexp for finding (possibly embedded) -t switches.
3500 (switch-regexp "\\(\\`\\| \\)-\\([a-su-zA-Z]*\\)\\(t\\)\\([^ ]*\\)")
3501 case-fold-search)
3502 ;; Remove the -t switch.
3503 (while (string-match switch-regexp dired-actual-switches)
3504 (if (and (equal (match-string 2 dired-actual-switches) "")
3505 (equal (match-string 4 dired-actual-switches) ""))
3506 ;; Remove a stand-alone -t switch.
3507 (setq dired-actual-switches
3508 (replace-match "" t t dired-actual-switches))
3509 ;; Remove a switch of the form -XtY for some X and Y.
3510 (setq dired-actual-switches
3511 (replace-match "" t t dired-actual-switches 3))))
3512 ;; Now, if we weren't sorting by date before, add the -t switch.
3513 (unless sorting-by-date
3514 (setq dired-actual-switches (concat dired-actual-switches " -t"))))
3515 (dired-sort-set-mode-line)
3516 (revert-buffer))
3517
3518 ;; Some user code loads dired especially for this.
3519 ;; Don't do that--use replace-regexp-in-string instead.
3520 (defun dired-replace-in-string (regexp newtext string)
3521 ;; Replace REGEXP with NEWTEXT everywhere in STRING and return result.
3522 ;; NEWTEXT is taken literally---no \\DIGIT escapes will be recognized.
3523 (let ((result "") (start 0) mb me)
3524 (while (string-match regexp string start)
3525 (setq mb (match-beginning 0)
3526 me (match-end 0)
3527 result (concat result (substring string start mb) newtext)
3528 start me))
3529 (concat result (substring string start))))
3530
3531 (defun dired-sort-other (switches &optional no-revert)
3532 "Specify new `ls' SWITCHES for current dired buffer.
3533 Values matching `dired-sort-by-date-regexp' or `dired-sort-by-name-regexp'
3534 set the minor mode accordingly, others appear literally in the mode line.
3535 With optional second arg NO-REVERT, don't refresh the listing afterwards."
3536 (dired-sort-R-check switches)
3537 (setq dired-actual-switches switches)
3538 (dired-sort-set-mode-line)
3539 (or no-revert (revert-buffer)))
3540
3541 (defvar dired-subdir-alist-pre-R nil
3542 "Value of `dired-subdir-alist' before -R switch added.")
3543 (make-variable-buffer-local 'dired-subdir-alist-pre-R)
3544
3545 (defun dired-sort-R-check (switches)
3546 "Additional processing of -R in ls option string SWITCHES.
3547 Saves `dired-subdir-alist' when R is set and restores saved value
3548 minus any directories explicitly deleted when R is cleared.
3549 To be called first in body of `dired-sort-other', etc."
3550 (cond
3551 ((and (string-match "R" switches)
3552 (not (string-match "R" dired-actual-switches)))
3553 ;; Adding -R to ls switches -- save `dired-subdir-alist':
3554 (setq dired-subdir-alist-pre-R dired-subdir-alist))
3555 ((and (string-match "R" dired-actual-switches)
3556 (not (string-match "R" switches)))
3557 ;; Deleting -R from ls switches -- revert to pre-R subdirs
3558 ;; that are still present:
3559 (setq dired-subdir-alist
3560 (if dired-subdir-alist-pre-R
3561 (let (subdirs)
3562 (while dired-subdir-alist-pre-R
3563 (if (assoc (caar dired-subdir-alist-pre-R)
3564 dired-subdir-alist)
3565 ;; subdir still present...
3566 (setq subdirs
3567 (cons (car dired-subdir-alist-pre-R)
3568 subdirs)))
3569 (setq dired-subdir-alist-pre-R
3570 (cdr dired-subdir-alist-pre-R)))
3571 (reverse subdirs))
3572 ;; No pre-R subdir alist, so revert to main directory
3573 ;; listing:
3574 (list (car (reverse dired-subdir-alist))))))))
3575 \f
3576
3577 ;;;; Drag and drop support
3578
3579 (defcustom dired-recursive-copies 'top
3580 "Whether Dired copies directories recursively.
3581 If nil, never copy recursively.
3582 `always' means to copy recursively without asking.
3583 `top' means to ask for each directory at top level.
3584 Any other value means to ask for each directory."
3585 :type '(choice :tag "Copy directories"
3586 (const :tag "No recursive copies" nil)
3587 (const :tag "Ask for each directory" t)
3588 (const :tag "Ask for each top directory only" top)
3589 (const :tag "Copy directories without asking" always))
3590 :group 'dired)
3591
3592 (defun dired-dnd-popup-notice ()
3593 (message-box
3594 "Dired recursive copies are currently disabled.\nSee the variable `dired-recursive-copies'."))
3595
3596 (declare-function x-popup-menu "menu.c" (position menu))
3597
3598 (defun dired-dnd-do-ask-action (uri)
3599 ;; No need to get actions and descriptions from the source,
3600 ;; we only have three actions anyway.
3601 (let ((action (x-popup-menu
3602 t
3603 (list "What action?"
3604 (cons ""
3605 '(("Copy here" . copy)
3606 ("Move here" . move)
3607 ("Link here" . link)
3608 "--"
3609 ("Cancel" . nil)))))))
3610 (if action
3611 (dired-dnd-handle-local-file uri action)
3612 nil)))
3613
3614 (declare-function dired-relist-entry "dired-aux" (file))
3615 (declare-function make-symbolic-link "fileio.c")
3616
3617 ;; Only used when (featurep 'dnd).
3618 (declare-function dnd-get-local-file-name "dnd" (uri &optional must-exist))
3619 (declare-function dnd-get-local-file-uri "dnd" (uri))
3620
3621 (defvar dired-overwrite-confirmed) ;Defined in dired-aux.
3622
3623 (defun dired-dnd-handle-local-file (uri action)
3624 "Copy, move or link a file to the dired directory.
3625 URI is the file to handle, ACTION is one of copy, move, link or ask.
3626 Ask means pop up a menu for the user to select one of copy, move or link."
3627 (require 'dired-aux)
3628 (let* ((from (dnd-get-local-file-name uri t))
3629 (to (when from
3630 (concat (dired-current-directory)
3631 (file-name-nondirectory from)))))
3632 (when from
3633 (cond ((eq action 'ask)
3634 (dired-dnd-do-ask-action uri))
3635 ;; If copying a directory and dired-recursive-copies is
3636 ;; nil, dired-copy-file fails. Pop up a notice.
3637 ((and (memq action '(copy private))
3638 (file-directory-p from)
3639 (not dired-recursive-copies))
3640 (dired-dnd-popup-notice))
3641 ((memq action '(copy private move link))
3642 (let ((overwrite (and (file-exists-p to)
3643 (y-or-n-p
3644 (format "Overwrite existing file `%s'? " to))))
3645 ;; Binding dired-overwrite-confirmed to nil makes
3646 ;; dired-handle-overwrite a no-op. We instead use
3647 ;; y-or-n-p, which pops a graphical menu.
3648 dired-overwrite-confirmed backup-file)
3649 (when (and overwrite
3650 ;; d-b-o is defined in dired-aux.
3651 (boundp 'dired-backup-overwrite)
3652 dired-backup-overwrite
3653 (setq backup-file
3654 (car (find-backup-file-name to)))
3655 (or (eq dired-backup-overwrite 'always)
3656 (y-or-n-p
3657 (format
3658 "Make backup for existing file `%s'? " to))))
3659 (rename-file to backup-file 0)
3660 (dired-relist-entry backup-file))
3661 (cond ((memq action '(copy private))
3662 (dired-copy-file from to overwrite))
3663 ((eq action 'move)
3664 (dired-rename-file from to overwrite))
3665 ((eq action 'link)
3666 (make-symbolic-link from to overwrite)))
3667 (dired-relist-entry to)
3668 action))))))
3669
3670 (defun dired-dnd-handle-file (uri action)
3671 "Copy, move or link a file to the dired directory if it is a local file.
3672 URI is the file to handle. If the hostname in the URI isn't local, do nothing.
3673 ACTION is one of copy, move, link or ask.
3674 Ask means pop up a menu for the user to select one of copy, move or link."
3675 (let ((local-file (dnd-get-local-file-uri uri)))
3676 (if local-file (dired-dnd-handle-local-file local-file action)
3677 nil)))
3678 \f
3679
3680 ;;;; Desktop support
3681
3682 (eval-when-compile (require 'desktop))
3683
3684 (defun dired-desktop-buffer-misc-data (dirname)
3685 "Auxiliary information to be saved in desktop file."
3686 (cons
3687 ;; Value of `dired-directory'.
3688 (if (consp dired-directory)
3689 ;; Directory name followed by list of files.
3690 (cons (desktop-file-name (car dired-directory) dirname)
3691 (cdr dired-directory))
3692 ;; Directory name, optionally with shell wildcard.
3693 (desktop-file-name dired-directory dirname))
3694 ;; Subdirectories in `dired-subdir-alist'.
3695 (cdr
3696 (nreverse
3697 (mapcar
3698 (function (lambda (f) (desktop-file-name (car f) dirname)))
3699 dired-subdir-alist)))))
3700
3701 (defun dired-restore-desktop-buffer (_file-name
3702 _buffer-name
3703 misc-data)
3704 "Restore a dired buffer specified in a desktop file."
3705 ;; First element of `misc-data' is the value of `dired-directory'.
3706 ;; This value is a directory name, optionally with shell wildcard or
3707 ;; a directory name followed by list of files.
3708 (let* ((dired-dir (car misc-data))
3709 (dir (if (consp dired-dir) (car dired-dir) dired-dir)))
3710 (if (file-directory-p (file-name-directory dir))
3711 (progn
3712 (dired dired-dir)
3713 ;; The following elements of `misc-data' are the keys
3714 ;; from `dired-subdir-alist'.
3715 (mapc 'dired-maybe-insert-subdir (cdr misc-data))
3716 (current-buffer))
3717 (message "Desktop: Directory %s no longer exists." dir)
3718 (when desktop-missing-file-warning (sit-for 1))
3719 nil)))
3720
3721 (add-to-list 'desktop-buffer-mode-handlers
3722 '(dired-mode . dired-restore-desktop-buffer))
3723
3724 \f
3725 ;;; Start of automatically extracted autoloads.
3726 \f
3727 ;;;### (autoloads (dired-show-file-type dired-do-query-replace-regexp
3728 ;;;;;; dired-do-search dired-do-isearch-regexp dired-do-isearch
3729 ;;;;;; dired-isearch-filenames-regexp dired-isearch-filenames dired-isearch-filenames-setup
3730 ;;;;;; dired-hide-all dired-hide-subdir dired-tree-down dired-tree-up
3731 ;;;;;; dired-kill-subdir dired-mark-subdir-files dired-goto-subdir
3732 ;;;;;; dired-prev-subdir dired-insert-subdir dired-maybe-insert-subdir
3733 ;;;;;; dired-downcase dired-upcase dired-do-symlink-regexp dired-do-hardlink-regexp
3734 ;;;;;; dired-do-copy-regexp dired-do-rename-regexp dired-do-rename
3735 ;;;;;; dired-do-hardlink dired-do-symlink dired-do-copy dired-create-directory
3736 ;;;;;; dired-rename-file dired-copy-file dired-relist-file dired-remove-file
3737 ;;;;;; dired-add-file dired-do-redisplay dired-do-load dired-do-byte-compile
3738 ;;;;;; dired-do-compress dired-query dired-compress-file dired-do-kill-lines
3739 ;;;;;; dired-run-shell-command dired-do-shell-command dired-do-async-shell-command
3740 ;;;;;; dired-clean-directory dired-do-print dired-do-touch dired-do-chown
3741 ;;;;;; dired-do-chgrp dired-do-chmod dired-compare-directories dired-backup-diff
3742 ;;;;;; dired-diff) "dired-aux" "dired-aux.el" "91d39bd8f7e9ce93dc752fe74bea78c2")
3743 ;;; Generated autoloads from dired-aux.el
3744
3745 (autoload 'dired-diff "dired-aux" "\
3746 Compare file at point with file FILE using `diff'.
3747 FILE defaults to the file at the mark. (That's the mark set by
3748 \\[set-mark-command], not by Dired's \\[dired-mark] command.)
3749 The prompted-for FILE is the first file given to `diff'.
3750 With prefix arg, prompt for second argument SWITCHES,
3751 which is the string of command switches for `diff'.
3752
3753 \(fn FILE &optional SWITCHES)" t nil)
3754
3755 (autoload 'dired-backup-diff "dired-aux" "\
3756 Diff this file with its backup file or vice versa.
3757 Uses the latest backup, if there are several numerical backups.
3758 If this file is a backup, diff it with its original.
3759 The backup file is the first file given to `diff'.
3760 With prefix arg, prompt for argument SWITCHES which is options for `diff'.
3761
3762 \(fn &optional SWITCHES)" t nil)
3763
3764 (autoload 'dired-compare-directories "dired-aux" "\
3765 Mark files with different file attributes in two dired buffers.
3766 Compare file attributes of files in the current directory
3767 with file attributes in directory DIR2 using PREDICATE on pairs of files
3768 with the same name. Mark files for which PREDICATE returns non-nil.
3769 Mark files with different names if PREDICATE is nil (or interactively
3770 with empty input at the predicate prompt).
3771
3772 PREDICATE is a Lisp expression that can refer to the following variables:
3773
3774 size1, size2 - file size in bytes
3775 mtime1, mtime2 - last modification time in seconds, as a float
3776 fa1, fa2 - list of file attributes
3777 returned by function `file-attributes'
3778
3779 where 1 refers to attribute of file in the current dired buffer
3780 and 2 to attribute of file in second dired buffer.
3781
3782 Examples of PREDICATE:
3783
3784 (> mtime1 mtime2) - mark newer files
3785 (not (= size1 size2)) - mark files with different sizes
3786 (not (string= (nth 8 fa1) (nth 8 fa2))) - mark files with different modes
3787 (not (and (= (nth 2 fa1) (nth 2 fa2)) - mark files with different UID
3788 (= (nth 3 fa1) (nth 3 fa2)))) and GID.
3789
3790 \(fn DIR2 PREDICATE)" t nil)
3791
3792 (autoload 'dired-do-chmod "dired-aux" "\
3793 Change the mode of the marked (or next ARG) files.
3794 Symbolic modes like `g+w' are allowed.
3795
3796 \(fn &optional ARG)" t nil)
3797
3798 (autoload 'dired-do-chgrp "dired-aux" "\
3799 Change the group of the marked (or next ARG) files.
3800
3801 \(fn &optional ARG)" t nil)
3802
3803 (autoload 'dired-do-chown "dired-aux" "\
3804 Change the owner of the marked (or next ARG) files.
3805
3806 \(fn &optional ARG)" t nil)
3807
3808 (autoload 'dired-do-touch "dired-aux" "\
3809 Change the timestamp of the marked (or next ARG) files.
3810 This calls touch.
3811
3812 \(fn &optional ARG)" t nil)
3813
3814 (autoload 'dired-do-print "dired-aux" "\
3815 Print the marked (or next ARG) files.
3816 Uses the shell command coming from variables `lpr-command' and
3817 `lpr-switches' as default.
3818
3819 \(fn &optional ARG)" t nil)
3820
3821 (autoload 'dired-clean-directory "dired-aux" "\
3822 Flag numerical backups for deletion.
3823 Spares `dired-kept-versions' latest versions, and `kept-old-versions' oldest.
3824 Positive prefix arg KEEP overrides `dired-kept-versions';
3825 Negative prefix arg KEEP overrides `kept-old-versions' with KEEP made positive.
3826
3827 To clear the flags on these files, you can use \\[dired-flag-backup-files]
3828 with a prefix argument.
3829
3830 \(fn KEEP)" t nil)
3831
3832 (autoload 'dired-do-async-shell-command "dired-aux" "\
3833 Run a shell command COMMAND on the marked files asynchronously.
3834
3835 Like `dired-do-shell-command' but if COMMAND doesn't end in ampersand,
3836 adds `* &' surrounded by whitespace and executes the command asynchronously.
3837 The output appears in the buffer `*Async Shell Command*'.
3838
3839 \(fn COMMAND &optional ARG FILE-LIST)" t nil)
3840
3841 (autoload 'dired-do-shell-command "dired-aux" "\
3842 Run a shell command COMMAND on the marked files.
3843 If no files are marked or a specific numeric prefix arg is given,
3844 the next ARG files are used. Just \\[universal-argument] means the current file.
3845 The prompt mentions the file(s) or the marker, as appropriate.
3846
3847 If there is a `*' in COMMAND, surrounded by whitespace, this runs
3848 COMMAND just once with the entire file list substituted there.
3849
3850 If there is no `*', but there is a `?' in COMMAND, surrounded by
3851 whitespace, this runs COMMAND on each file individually with the
3852 file name substituted for `?'.
3853
3854 Otherwise, this runs COMMAND on each file individually with the
3855 file name added at the end of COMMAND (separated by a space).
3856
3857 `*' and `?' when not surrounded by whitespace have no special
3858 significance for `dired-do-shell-command', and are passed through
3859 normally to the shell, but you must confirm first.
3860
3861 If you want to use `*' as a shell wildcard with whitespace around
3862 it, write `*\"\"' in place of just `*'. This is equivalent to just
3863 `*' in the shell, but avoids Dired's special handling.
3864
3865 If COMMAND produces output, it goes to a separate buffer.
3866
3867 This feature does not try to redisplay Dired buffers afterward, as
3868 there's no telling what files COMMAND may have changed.
3869 Type \\[dired-do-redisplay] to redisplay the marked files.
3870
3871 When COMMAND runs, its working directory is the top-level directory
3872 of the Dired buffer, so output files usually are created there
3873 instead of in a subdir.
3874
3875 In a noninteractive call (from Lisp code), you must specify
3876 the list of file names explicitly with the FILE-LIST argument, which
3877 can be produced by `dired-get-marked-files', for example.
3878
3879 \(fn COMMAND &optional ARG FILE-LIST)" t nil)
3880
3881 (autoload 'dired-run-shell-command "dired-aux" "\
3882
3883
3884 \(fn COMMAND)" nil nil)
3885
3886 (autoload 'dired-do-kill-lines "dired-aux" "\
3887 Kill all marked lines (not the files).
3888 With a prefix argument, kill that many lines starting with the current line.
3889 \(A negative argument kills backward.)
3890 If you use this command with a prefix argument to kill the line
3891 for a file that is a directory, which you have inserted in the
3892 Dired buffer as a subdirectory, then it deletes that subdirectory
3893 from the buffer as well.
3894 To kill an entire subdirectory (without killing its line in the
3895 parent directory), go to its directory header line and use this
3896 command with a prefix argument (the value does not matter).
3897
3898 \(fn &optional ARG FMT)" t nil)
3899
3900 (autoload 'dired-compress-file "dired-aux" "\
3901
3902
3903 \(fn FILE)" nil nil)
3904
3905 (autoload 'dired-query "dired-aux" "\
3906 Format PROMPT with ARGS, query user, and store the result in SYM.
3907 The return value is either nil or t.
3908
3909 The user may type y or SPC to accept once; n or DEL to skip once;
3910 ! to accept this and subsequent queries; or q or ESC to decline
3911 this and subsequent queries.
3912
3913 If SYM is already bound to a non-nil value, this function may
3914 return automatically without querying the user. If SYM is !,
3915 return t; if SYM is q or ESC, return nil.
3916
3917 \(fn SYM PROMPT &rest ARGS)" nil nil)
3918
3919 (autoload 'dired-do-compress "dired-aux" "\
3920 Compress or uncompress marked (or next ARG) files.
3921
3922 \(fn &optional ARG)" t nil)
3923
3924 (autoload 'dired-do-byte-compile "dired-aux" "\
3925 Byte compile marked (or next ARG) Emacs Lisp files.
3926
3927 \(fn &optional ARG)" t nil)
3928
3929 (autoload 'dired-do-load "dired-aux" "\
3930 Load the marked (or next ARG) Emacs Lisp files.
3931
3932 \(fn &optional ARG)" t nil)
3933
3934 (autoload 'dired-do-redisplay "dired-aux" "\
3935 Redisplay all marked (or next ARG) files.
3936 If on a subdir line, redisplay that subdirectory. In that case,
3937 a prefix arg lets you edit the `ls' switches used for the new listing.
3938
3939 Dired remembers switches specified with a prefix arg, so that reverting
3940 the buffer will not reset them. However, using `dired-undo' to re-insert
3941 or delete subdirectories can bypass this machinery. Hence, you sometimes
3942 may have to reset some subdirectory switches after a `dired-undo'.
3943 You can reset all subdirectory switches to the default using
3944 \\<dired-mode-map>\\[dired-reset-subdir-switches].
3945 See Info node `(emacs)Subdir switches' for more details.
3946
3947 \(fn &optional ARG TEST-FOR-SUBDIR)" t nil)
3948
3949 (autoload 'dired-add-file "dired-aux" "\
3950
3951
3952 \(fn FILENAME &optional MARKER-CHAR)" nil nil)
3953
3954 (autoload 'dired-remove-file "dired-aux" "\
3955
3956
3957 \(fn FILE)" nil nil)
3958
3959 (autoload 'dired-relist-file "dired-aux" "\
3960 Create or update the line for FILE in all Dired buffers it would belong in.
3961
3962 \(fn FILE)" nil nil)
3963
3964 (autoload 'dired-copy-file "dired-aux" "\
3965
3966
3967 \(fn FROM TO OK-FLAG)" nil nil)
3968
3969 (autoload 'dired-rename-file "dired-aux" "\
3970
3971
3972 \(fn FILE NEWNAME OK-IF-ALREADY-EXISTS)" nil nil)
3973
3974 (autoload 'dired-create-directory "dired-aux" "\
3975 Create a directory called DIRECTORY.
3976 If DIRECTORY already exists, signal an error.
3977
3978 \(fn DIRECTORY)" t nil)
3979
3980 (autoload 'dired-do-copy "dired-aux" "\
3981 Copy all marked (or next ARG) files, or copy the current file.
3982 When operating on just the current file, prompt for the new name.
3983
3984 When operating on multiple or marked files, prompt for a target
3985 directory, and make the new copies in that directory, with the
3986 same names as the original files. The initial suggestion for the
3987 target directory is the Dired buffer's current directory (or, if
3988 `dired-dwim-target' is non-nil, the current directory of a
3989 neighboring Dired window).
3990
3991 If `dired-copy-preserve-time' is non-nil, this command preserves
3992 the modification time of each old file in the copy, similar to
3993 the \"-p\" option for the \"cp\" shell command.
3994
3995 This command copies symbolic links by creating new ones, similar
3996 to the \"-d\" option for the \"cp\" shell command.
3997
3998 \(fn &optional ARG)" t nil)
3999
4000 (autoload 'dired-do-symlink "dired-aux" "\
4001 Make symbolic links to current file or all marked (or next ARG) files.
4002 When operating on just the current file, you specify the new name.
4003 When operating on multiple or marked files, you specify a directory
4004 and new symbolic links are made in that directory
4005 with the same names that the files currently have. The default
4006 suggested for the target directory depends on the value of
4007 `dired-dwim-target', which see.
4008
4009 For relative symlinks, use \\[dired-do-relsymlink].
4010
4011 \(fn &optional ARG)" t nil)
4012
4013 (autoload 'dired-do-hardlink "dired-aux" "\
4014 Add names (hard links) current file or all marked (or next ARG) files.
4015 When operating on just the current file, you specify the new name.
4016 When operating on multiple or marked files, you specify a directory
4017 and new hard links are made in that directory
4018 with the same names that the files currently have. The default
4019 suggested for the target directory depends on the value of
4020 `dired-dwim-target', which see.
4021
4022 \(fn &optional ARG)" t nil)
4023
4024 (autoload 'dired-do-rename "dired-aux" "\
4025 Rename current file or all marked (or next ARG) files.
4026 When renaming just the current file, you specify the new name.
4027 When renaming multiple or marked files, you specify a directory.
4028 This command also renames any buffers that are visiting the files.
4029 The default suggested for the target directory depends on the value
4030 of `dired-dwim-target', which see.
4031
4032 \(fn &optional ARG)" t nil)
4033
4034 (autoload 'dired-do-rename-regexp "dired-aux" "\
4035 Rename selected files whose names match REGEXP to NEWNAME.
4036
4037 With non-zero prefix argument ARG, the command operates on the next ARG
4038 files. Otherwise, it operates on all the marked files, or the current
4039 file if none are marked.
4040
4041 As each match is found, the user must type a character saying
4042 what to do with it. For directions, type \\[help-command] at that time.
4043 NEWNAME may contain \\=\\<n> or \\& as in `query-replace-regexp'.
4044 REGEXP defaults to the last regexp used.
4045
4046 With a zero prefix arg, renaming by regexp affects the absolute file name.
4047 Normally, only the non-directory part of the file name is used and changed.
4048
4049 \(fn REGEXP NEWNAME &optional ARG WHOLE-NAME)" t nil)
4050
4051 (autoload 'dired-do-copy-regexp "dired-aux" "\
4052 Copy selected files whose names match REGEXP to NEWNAME.
4053 See function `dired-do-rename-regexp' for more info.
4054
4055 \(fn REGEXP NEWNAME &optional ARG WHOLE-NAME)" t nil)
4056
4057 (autoload 'dired-do-hardlink-regexp "dired-aux" "\
4058 Hardlink selected files whose names match REGEXP to NEWNAME.
4059 See function `dired-do-rename-regexp' for more info.
4060
4061 \(fn REGEXP NEWNAME &optional ARG WHOLE-NAME)" t nil)
4062
4063 (autoload 'dired-do-symlink-regexp "dired-aux" "\
4064 Symlink selected files whose names match REGEXP to NEWNAME.
4065 See function `dired-do-rename-regexp' for more info.
4066
4067 \(fn REGEXP NEWNAME &optional ARG WHOLE-NAME)" t nil)
4068
4069 (autoload 'dired-upcase "dired-aux" "\
4070 Rename all marked (or next ARG) files to upper case.
4071
4072 \(fn &optional ARG)" t nil)
4073
4074 (autoload 'dired-downcase "dired-aux" "\
4075 Rename all marked (or next ARG) files to lower case.
4076
4077 \(fn &optional ARG)" t nil)
4078
4079 (autoload 'dired-maybe-insert-subdir "dired-aux" "\
4080 Insert this subdirectory into the same dired buffer.
4081 If it is already present, just move to it (type \\[dired-do-redisplay] to refresh),
4082 else inserts it at its natural place (as `ls -lR' would have done).
4083 With a prefix arg, you may edit the ls switches used for this listing.
4084 You can add `R' to the switches to expand the whole tree starting at
4085 this subdirectory.
4086 This function takes some pains to conform to `ls -lR' output.
4087
4088 Dired remembers switches specified with a prefix arg, so that reverting
4089 the buffer will not reset them. However, using `dired-undo' to re-insert
4090 or delete subdirectories can bypass this machinery. Hence, you sometimes
4091 may have to reset some subdirectory switches after a `dired-undo'.
4092 You can reset all subdirectory switches to the default using
4093 \\<dired-mode-map>\\[dired-reset-subdir-switches].
4094 See Info node `(emacs)Subdir switches' for more details.
4095
4096 \(fn DIRNAME &optional SWITCHES NO-ERROR-IF-NOT-DIR-P)" t nil)
4097
4098 (autoload 'dired-insert-subdir "dired-aux" "\
4099 Insert this subdirectory into the same Dired buffer.
4100 If it is already present, overwrite the previous entry;
4101 otherwise, insert it at its natural place (as `ls -lR' would
4102 have done).
4103 With a prefix arg, you may edit the `ls' switches used for this listing.
4104 You can add `R' to the switches to expand the whole tree starting at
4105 this subdirectory.
4106 This function takes some pains to conform to `ls -lR' output.
4107
4108 \(fn DIRNAME &optional SWITCHES NO-ERROR-IF-NOT-DIR-P)" t nil)
4109
4110 (autoload 'dired-prev-subdir "dired-aux" "\
4111 Go to previous subdirectory, regardless of level.
4112 When called interactively and not on a subdir line, go to this subdir's line.
4113
4114 \(fn ARG &optional NO-ERROR-IF-NOT-FOUND NO-SKIP)" t nil)
4115
4116 (autoload 'dired-goto-subdir "dired-aux" "\
4117 Go to end of header line of DIR in this dired buffer.
4118 Return value of point on success, otherwise return nil.
4119 The next char is either \\n, or \\r if DIR is hidden.
4120
4121 \(fn DIR)" t nil)
4122
4123 (autoload 'dired-mark-subdir-files "dired-aux" "\
4124 Mark all files except `.' and `..' in current subdirectory.
4125 If the Dired buffer shows multiple directories, this command
4126 marks the files listed in the subdirectory that point is in.
4127
4128 \(fn)" t nil)
4129
4130 (autoload 'dired-kill-subdir "dired-aux" "\
4131 Remove all lines of current subdirectory.
4132 Lower levels are unaffected.
4133
4134 \(fn &optional REMEMBER-MARKS)" t nil)
4135
4136 (autoload 'dired-tree-up "dired-aux" "\
4137 Go up ARG levels in the dired tree.
4138
4139 \(fn ARG)" t nil)
4140
4141 (autoload 'dired-tree-down "dired-aux" "\
4142 Go down in the dired tree.
4143
4144 \(fn)" t nil)
4145
4146 (autoload 'dired-hide-subdir "dired-aux" "\
4147 Hide or unhide the current subdirectory and move to next directory.
4148 Optional prefix arg is a repeat factor.
4149 Use \\[dired-hide-all] to (un)hide all directories.
4150
4151 \(fn ARG)" t nil)
4152
4153 (autoload 'dired-hide-all "dired-aux" "\
4154 Hide all subdirectories, leaving only their header lines.
4155 If there is already something hidden, make everything visible again.
4156 Use \\[dired-hide-subdir] to (un)hide a particular subdirectory.
4157
4158 \(fn &optional IGNORED)" t nil)
4159
4160 (autoload 'dired-isearch-filenames-setup "dired-aux" "\
4161 Set up isearch to search in Dired file names.
4162 Intended to be added to `isearch-mode-hook'.
4163
4164 \(fn)" nil nil)
4165
4166 (autoload 'dired-isearch-filenames "dired-aux" "\
4167 Search for a string using Isearch only in file names in the Dired buffer.
4168
4169 \(fn)" t nil)
4170
4171 (autoload 'dired-isearch-filenames-regexp "dired-aux" "\
4172 Search for a regexp using Isearch only in file names in the Dired buffer.
4173
4174 \(fn)" t nil)
4175
4176 (autoload 'dired-do-isearch "dired-aux" "\
4177 Search for a string through all marked files using Isearch.
4178
4179 \(fn)" t nil)
4180
4181 (autoload 'dired-do-isearch-regexp "dired-aux" "\
4182 Search for a regexp through all marked files using Isearch.
4183
4184 \(fn)" t nil)
4185
4186 (autoload 'dired-do-search "dired-aux" "\
4187 Search through all marked files for a match for REGEXP.
4188 Stops when a match is found.
4189 To continue searching for next match, use command \\[tags-loop-continue].
4190
4191 \(fn REGEXP)" t nil)
4192
4193 (autoload 'dired-do-query-replace-regexp "dired-aux" "\
4194 Do `query-replace-regexp' of FROM with TO, on all marked files.
4195 Third arg DELIMITED (prefix arg) means replace only word-delimited matches.
4196 If you exit (\\[keyboard-quit], RET or q), you can resume the query replace
4197 with the command \\[tags-loop-continue].
4198
4199 \(fn FROM TO &optional DELIMITED)" t nil)
4200
4201 (autoload 'dired-show-file-type "dired-aux" "\
4202 Print the type of FILE, according to the `file' command.
4203 If you give a prefix to this command, and FILE is a symbolic
4204 link, then the type of the file linked to by FILE is printed
4205 instead.
4206
4207 \(fn FILE &optional DEREF-SYMLINKS)" t nil)
4208
4209 ;;;***
4210 \f
4211 ;;;### (autoloads (dired-do-relsymlink dired-jump-other-window dired-jump)
4212 ;;;;;; "dired-x" "dired-x.el" "d2461aa6efb8c1d7de8f245728ab448e")
4213 ;;; Generated autoloads from dired-x.el
4214
4215 (autoload 'dired-jump "dired-x" "\
4216 Jump to dired buffer corresponding to current buffer.
4217 If in a file, dired the current directory and move to file's line.
4218 If in Dired already, pop up a level and goto old directory's line.
4219 In case the proper dired file line cannot be found, refresh the dired
4220 buffer and try again.
4221 When OTHER-WINDOW is non-nil, jump to dired buffer in other window.
4222 Interactively with prefix argument, read FILE-NAME and
4223 move to its line in dired.
4224
4225 \(fn &optional OTHER-WINDOW FILE-NAME)" t nil)
4226
4227 (autoload 'dired-jump-other-window "dired-x" "\
4228 Like \\[dired-jump] (`dired-jump') but in other window.
4229
4230 \(fn &optional FILE-NAME)" t nil)
4231
4232 (autoload 'dired-do-relsymlink "dired-x" "\
4233 Relative symlink all marked (or next ARG) files into a directory.
4234 Otherwise make a relative symbolic link to the current file.
4235 This creates relative symbolic links like
4236
4237 foo -> ../bar/foo
4238
4239 not absolute ones like
4240
4241 foo -> /ugly/file/name/that/may/change/any/day/bar/foo
4242
4243 For absolute symlinks, use \\[dired-do-symlink].
4244
4245 \(fn &optional ARG)" t nil)
4246
4247 ;;;***
4248 \f
4249 ;;; End of automatically extracted autoloads.
4250
4251 (provide 'dired)
4252
4253 (run-hooks 'dired-load-hook) ; for your customizations
4254
4255 ;;; dired.el ends here