Add "Package:" file headers to denote built-in packages.
[bpt/emacs.git] / lisp / dired-x.el
CommitLineData
276f1d00 1;;; dired-x.el --- extra Dired functionality
cb3fe1f0 2
70ee5ed1 3;; Copyright (C) 1993, 1994, 1997, 2001, 2002, 2003, 2004, 2005, 2006,
114f9c96 4;; 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
552939e4 5
cb3fe1f0
RS
6;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
7;; Lawrence R. Dodd <dodd@roebling.poly.edu>
2d29381c 8;; Maintainer: Romain Francoise <rfrancoise@gnu.org>
a443d46e 9;; Keywords: dired extensions files
bd78fa1d 10;; Package: emacs
cb3fe1f0 11
cb3fe1f0
RS
12;; This file is part of GNU Emacs.
13
eb3fa2cf 14;; GNU Emacs is free software: you can redistribute it and/or modify
cb3fe1f0 15;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
16;; the Free Software Foundation, either version 3 of the License, or
17;; (at your option) any later version.
cb3fe1f0
RS
18
19;; GNU Emacs is distributed in the hope that it will be useful,
20;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22;; GNU General Public License for more details.
23
24;; You should have received a copy of the GNU General Public License
eb3fa2cf 25;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
cb3fe1f0 26
9572a9dd 27;;; Commentary:
cb3fe1f0 28
b578f267 29;; This is Sebastian Kremer's excellent dired-x.el (Dired Extra), version
a443d46e
GM
30;; 1.191, hacked up for GNU Emacs. Redundant or conflicting material has
31;; been removed or renamed in order to work properly with dired of GNU
32;; Emacs. All suggestions or comments are most welcomed.
b578f267 33
71296446 34;;
b578f267 35;; Please, PLEASE, *PLEASE* see the info pages.
71296446 36;;
b578f267
EN
37
38;; BUGS: Type M-x dired-x-submit-report and a report will be generated.
39
40;; INSTALLATION: In your ~/.emacs,
41;;
42;; (add-hook 'dired-load-hook
43;; (function (lambda ()
44;; (load "dired-x")
d7af463c 45;; ;; Set global variables here. For example:
b578f267 46;; ;; (setq dired-guess-shell-gnutar "gtar")
d7af463c
RF
47;; )))
48;; (add-hook 'dired-mode-hook
49;; (function (lambda ()
50;; ;; Set buffer-local variables here. For example:
ce64e046 51;; ;; (dired-omit-mode 1)
b578f267
EN
52;; )))
53;;
54;; At load time dired-x.el will install itself, redefine some functions, and
55;; bind some dired keys. *Please* see the info pages for more details.
56
b847eb8c 57;; *Please* see the info pages for more details.
b578f267
EN
58
59;; User defined variables:
60;;
61;; dired-bind-vm
62;; dired-vm-read-only-folders
63;; dired-bind-jump
64;; dired-bind-info
65;; dired-bind-man
b847eb8c 66;; dired-x-hands-off-my-keys
b578f267
EN
67;; dired-find-subdir
68;; dired-enable-local-variables
69;; dired-local-variables-file
70;; dired-guess-shell-gnutar
71;; dired-guess-shell-gzip-quiet
72;; dired-guess-shell-znew-switches
73;; dired-guess-shell-alist-user
74;; dired-clean-up-buffers-too
ce64e046 75;; dired-omit-mode
b578f267
EN
76;; dired-omit-files
77;; dired-omit-extensions
ad8c4554 78;; dired-omit-size-limit
b578f267
EN
79;;
80;; To find out more about these variables, load this file, put your cursor at
81;; the end of any of the variable names, and hit C-h v [RET]. *Please* see
82;; the info pages for more details.
83
84;; When loaded this code redefines the following functions of GNU Emacs
85;;
86;; Function Found in this file of GNU Emacs
87;; -------- -------------------------------
88;; dired-clean-up-after-deletion ../lisp/dired.el
89;; dired-find-buffer-nocreate ../lisp/dired.el
90;; dired-initial-position ../lisp/dired.el
91;;
92;; dired-add-entry ../lisp/dired-aux.el
93;; dired-read-shell-command ../lisp/dired-aux.el
cb3fe1f0
RS
94
95\f
b578f267 96;;; Code:
cb3fe1f0 97
b578f267 98;; LOAD.
cb3fe1f0 99
b578f267
EN
100;; This is a no-op if dired-x is being loaded via `dired-load-hook'. It is
101;; here in case the user has autoloaded dired-x via the dired-jump key binding
102;; (instead of autoloading to dired as is suggested in the info-pages).
9572a9dd 103
d82cfc0c 104(require 'dired)
9572a9dd 105
b578f267
EN
106;; We will redefine some functions and also need some macros so we need to
107;; load dired stuff of GNU Emacs.
d82cfc0c
RS
108
109(require 'dired-aux)
9572a9dd 110
12ec3981 111(defvar vm-folder-directory)
670d3fce 112(eval-when-compile (require 'man))
12ec3981 113
b578f267 114;;; User-defined variables.
cb3fe1f0 115
286c247d
RS
116(defgroup dired-x nil
117 "Extended directory editing (dired-x)."
118 :group 'dired)
cb3fe1f0 119
286c247d
RS
120(defgroup dired-keys nil
121 "Dired keys customizations."
122 :prefix "dired-"
123 :group 'dired-x)
cb3fe1f0 124
286c247d 125(defcustom dired-bind-vm nil
9201cc28 126 "Non-nil means \"V\" runs `dired-vm', otherwise \"V\" runs `dired-rmail'.
3176a6a0
GM
127
128RMAIL files in the old Babyl format (used before before Emacs 23.1)
129contain \"-*- rmail -*-\" at the top, so `dired-find-file'
130will run `rmail' on these files. New RMAIL files use the standard
131mbox format, and so cannot be distinguished in this way."
286c247d
RS
132 :type 'boolean
133 :group 'dired-keys)
134
135(defcustom dired-bind-jump t
9201cc28 136 "Non-nil means bind `dired-jump' to C-x C-j, otherwise do not."
286c247d
RS
137 :type 'boolean
138 :group 'dired-keys)
139
140(defcustom dired-bind-man t
9201cc28 141 "Non-nil means bind `dired-man' to \"N\" in dired-mode, otherwise do not."
286c247d
RS
142 :type 'boolean
143 :group 'dired-keys)
144
145(defcustom dired-bind-info t
9201cc28 146 "Non-nil means bind `dired-info' to \"I\" in dired-mode, otherwise do not."
286c247d
RS
147 :type 'boolean
148 :group 'dired-keys)
149
150(defcustom dired-vm-read-only-folders nil
9201cc28 151 "If non-nil, \\[dired-vm] will visit all folders read-only.
cb3fe1f0
RS
152If neither nil nor t, e.g. the symbol `if-file-read-only', only
153files not writable by you are visited read-only.
154
286c247d
RS
155Read-only folders only work in VM 5, not in VM 4."
156 :type '(choice (const :tag "off" nil)
157 (const :tag "on" t)
e2c146c1 158 (other :tag "non-writable only" if-file-read-only))
286c247d 159 :group 'dired-x)
cb3fe1f0 160
ce64e046
LH
161(define-minor-mode dired-omit-mode
162 "Toggle Dired-Omit mode.
163With numeric ARG, enable Dired-Omit mode if ARG is positive, disable
6fbad7af 164otherwise. Enabling and disabling is buffer-local.
ce64e046 165If enabled, \"uninteresting\" files are not listed.
cb3fe1f0 166Uninteresting files are those whose filenames match regexp `dired-omit-files',
2223a1b3
JL
167plus those ending with extensions in `dired-omit-extensions'.
168
169To enable omitting in every Dired buffer, you can put in your ~/.emacs
170
171 (add-hook 'dired-mode-hook (lambda () (dired-omit-mode 1)))
172
173See Info node `(dired-x) Omitting Variables' for more information."
ce64e046
LH
174 :group 'dired-x
175 (if dired-omit-mode
176 ;; This will mention how many lines were omitted:
177 (let ((dired-omit-size-limit nil)) (dired-omit-expunge))
178 (revert-buffer)))
179
180;; For backward compatibility
cf24b82d 181(define-obsolete-variable-alias 'dired-omit-files-p 'dired-omit-mode "22.1")
cb3fe1f0 182
99358b97 183(defcustom dired-omit-files "^\\.?#\\|^\\.$\\|^\\.\\.$"
9201cc28 184 "Filenames matching this regexp will not be displayed.
ce64e046
LH
185This only has effect when `dired-omit-mode' is t. See interactive function
186`dired-omit-mode' \(\\[dired-omit-mode]\) and variable
99358b97
RS
187`dired-omit-extensions'. The default is to omit `.', `..', auto-save
188files and lock files."
286c247d
RS
189 :type 'regexp
190 :group 'dired-x)
cb3fe1f0 191
286c247d 192(defcustom dired-find-subdir nil ; t is pretty near to DWIM...
9201cc28 193 "If non-nil, Dired always finds a directory in a buffer of its own.
0a44133e
RS
194If nil, Dired finds the directory as a subdirectory in some other buffer
195if it is present as one.
cb3fe1f0 196
6fbad7af 197If there are several dired buffers for a directory, the most recently
cb3fe1f0
RS
198used is chosen.
199
200Dired avoids switching to the current buffer, so that if you have
b847eb8c 201a normal and a wildcard buffer for the same directory, \\[dired] will
286c247d
RS
202toggle between those two."
203 :type 'boolean
204 :group 'dired-x)
205
8e458944 206(defcustom dired-omit-size-limit 30000
9201cc28 207 "Maximum size for the \"omitting\" feature.
286c247d
RS
208If nil, there is no maximum size."
209 :type '(choice (const :tag "no maximum" nil) integer)
210 :group 'dired-x)
cb3fe1f0 211
286c247d 212(defcustom dired-enable-local-variables t
9201cc28 213 "Control use of local-variables lists in Dired.
cb3fe1f0
RS
214The value can be t, nil or something else.
215A value of t means local-variables lists are obeyed;
216nil means they are ignored; anything else means query.
217
5a0c3f56
JB
218This temporarily overrides the value of `enable-local-variables' when
219listing a directory. See also `dired-local-variables-file'."
286c247d
RS
220 :type 'boolean
221 :group 'dired-x)
cb3fe1f0 222
3f8105a1
RF
223(defcustom dired-guess-shell-gnutar (when (or (eq system-type 'gnu)
224 (eq system-type 'gnu/linux))
225 "tar")
9201cc28 226 "If non-nil, name of GNU tar executable.
b847eb8c
DL
227\(E.g., \"tar\" or \"gtar\"). The `z' switch will be used with it for
228compressed or gzip'ed tar files. If you don't have GNU tar, set this
286c247d 229to nil: a pipe using `zcat' or `gunzip -c' will be used."
b847eb8c
DL
230 :type '(choice (const :tag "Not GNU tar" nil)
231 (string :tag "Command name"))
286c247d
RS
232 :group 'dired-x)
233
234(defcustom dired-guess-shell-gzip-quiet t
9201cc28 235 "Non-nil says pass -q to gzip overriding verbose GZIP environment."
286c247d
RS
236 :type 'boolean
237 :group 'dired-x)
238
239(defcustom dired-guess-shell-znew-switches nil
9201cc28 240 "If non-nil, then string of switches passed to `znew', example: \"-K\"."
b847eb8c
DL
241 :type '(choice (const :tag "None" nil)
242 (string :tag "Switches"))
286c247d
RS
243 :group 'dired-x)
244
245(defcustom dired-clean-up-buffers-too t
9201cc28 246 "Non-nil means offer to kill buffers visiting files and dirs deleted in Dired."
286c247d
RS
247 :type 'boolean
248 :group 'dired-x)
cb3fe1f0 249
b578f267 250;;; KEY BINDINGS.
cb3fe1f0 251
ce64e046 252(define-key dired-mode-map "\M-o" 'dired-omit-mode)
71326638 253(define-key dired-mode-map "*O" 'dired-mark-omitted)
cb3fe1f0 254(define-key dired-mode-map "\M-(" 'dired-mark-sexp)
582bd36a
RS
255(define-key dired-mode-map "*(" 'dired-mark-sexp)
256(define-key dired-mode-map "*." 'dired-mark-extension)
cb3fe1f0 257(define-key dired-mode-map "\M-!" 'dired-smart-shell-command)
cb3fe1f0 258(define-key dired-mode-map "w" 'dired-copy-filename-as-kill)
cb3fe1f0
RS
259(define-key dired-mode-map "\M-G" 'dired-goto-subdir)
260(define-key dired-mode-map "F" 'dired-do-find-marked-files)
261(define-key dired-mode-map "Y" 'dired-do-relsymlink)
262(define-key dired-mode-map "%Y" 'dired-do-relsymlink-regexp)
263(define-key dired-mode-map "V" 'dired-do-run-mail)
264
265(if dired-bind-man
266 (define-key dired-mode-map "N" 'dired-man))
267
268(if dired-bind-info
269 (define-key dired-mode-map "I" 'dired-info))
270
438fc253
LH
271;;; MENU BINDINGS
272
273(let ((menu-bar (lookup-key dired-mode-map [menu-bar])))
274 (let ((menu (lookup-key menu-bar [operate])))
275 (define-key-after
276 menu
277 [find-files]
278 '(menu-item
279 "Find files"
280 dired-do-find-marked-files
281 :help "Find current or marked files")
282 'delete)
283 (define-key-after
284 menu
285 [relsymlink]
286 '(menu-item
287 "Relative symlink to..."
288 dired-do-relsymlink
289 :visible (fboundp 'make-symbolic-link)
290 :help "Make relative symbolic links for current or marked files")
291 'symlink))
292 (let ((menu (lookup-key menu-bar [mark])))
293 (define-key-after
294 menu
295 [flag-extension]
296 '(menu-item
297 "Flag extension..."
298 dired-flag-extension
299 :help "Flag files with a certain extension for deletion")
300 'garbage-files)
301 (define-key-after
302 menu
303 [mark-extension]
304 '(menu-item
305 "Mark extension..."
306 dired-mark-extension
307 :help "Mark files with a certain extension")
308 'symlinks)
309 (define-key-after
310 menu
311 [mark-omitted]
312 '(menu-item
313 "Mark omitted"
314 dired-mark-omitted
315 :help "Mark files matching `dired-omit-files' and `dired-omit-extensions'")
316 'mark-extension))
317 (let ((menu (lookup-key menu-bar [regexp])))
318 (define-key-after
319 menu
320 [relsymlink-regexp]
321 '(menu-item
322 "Relative symlink..."
323 dired-do-relsymlink-regexp
324 :visible (fboundp 'make-symbolic-link)
325 :help "Make relative symbolic links for files matching regexp")
326 'symlink))
327 (let ((menu (lookup-key menu-bar [immediate])))
328 (define-key-after
329 menu
330 [omit-mode]
331 '(menu-item
332 "Omit mode" dired-omit-mode
333 :button (:toggle . dired-omit-mode)
334 :help "Enable or disable omitting \"uninteresting\" files")
335 'dashes)))
336
9572a9dd 337;;; GLOBAL BINDING.
cb3fe1f0
RS
338(if dired-bind-jump
339 (progn
340 (define-key global-map "\C-x\C-j" 'dired-jump)
341 (define-key global-map "\C-x4\C-j" 'dired-jump-other-window)))
342
343\f
efcb74f6 344;; Install into appropriate hooks.
cb3fe1f0
RS
345
346(add-hook 'dired-mode-hook 'dired-extra-startup)
347(add-hook 'dired-after-readin-hook 'dired-omit-expunge)
348
349(defun dired-extra-startup ()
6fbad7af 350 "Automatically put on `dired-mode-hook' to get extra Dired features:
cb3fe1f0 351\\<dired-mode-map>
cb3fe1f0
RS
352 \\[dired-do-run-mail]\t-- run mail on folder (see `dired-bind-vm')
353 \\[dired-info]\t-- run info on file
354 \\[dired-man]\t-- run man on file
355 \\[dired-do-find-marked-files]\t-- visit all marked files simultaneously
ce64e046 356 \\[dired-omit-mode]\t-- toggle omitting of files
b847eb8c 357 \\[dired-mark-sexp]\t-- mark by Lisp expression
6fbad7af
JB
358 \\[dired-copy-filename-as-kill]\t-- copy the file or subdir names into the kill ring;
359 \t you can feed it to other commands using \\[yank]
cb3fe1f0
RS
360
361For more features, see variables
362
b847eb8c
DL
363 `dired-bind-vm'
364 `dired-bind-jump'
365 `dired-bind-info'
366 `dired-bind-man'
367 `dired-vm-read-only-folders'
ce64e046 368 `dired-omit-mode'
b847eb8c
DL
369 `dired-omit-files'
370 `dired-omit-extensions'
371 `dired-omit-size-limit'
372 `dired-find-subdir'
373 `dired-enable-local-variables'
374 `dired-local-variables-file'
375 `dired-guess-shell-gnutar'
376 `dired-guess-shell-gzip-quiet'
377 `dired-guess-shell-znew-switches'
378 `dired-guess-shell-alist-user'
379 `dired-clean-up-buffers-too'
cb3fe1f0
RS
380
381See also functions
382
b847eb8c
DL
383 `dired-flag-extension'
384 `dired-virtual'
385 `dired-jump'
386 `dired-man'
387 `dired-vm'
388 `dired-rmail'
389 `dired-info'
390 `dired-do-find-marked-files'"
cb3fe1f0
RS
391 (interactive)
392
393 ;; These must be done in each new dired buffer.
394 (dired-hack-local-variables)
395 (dired-omit-startup))
396
397\f
b578f267 398;;; BUFFER CLEANING.
cb3fe1f0 399
b578f267 400;; REDEFINE.
cb3fe1f0 401(defun dired-clean-up-after-deletion (fn)
b847eb8c
DL
402 "Clean up after a deleted file or directory FN.
403Remove expanded subdir of deleted dir, if any."
cb3fe1f0
RS
404 (save-excursion (and (cdr dired-subdir-alist)
405 (dired-goto-subdir fn)
406 (dired-kill-subdir)))
407
408 ;; Offer to kill buffer of deleted file FN.
409 (if dired-clean-up-buffers-too
410 (progn
411 (let ((buf (get-file-buffer fn)))
412 (and buf
413 (funcall (function y-or-n-p)
414 (format "Kill buffer of %s, too? "
415 (file-name-nondirectory fn)))
416 (save-excursion ; you never know where kill-buffer leaves you
417 (kill-buffer buf))))
12c38283 418 (let ((buf-list (dired-buffers-for-dir (expand-file-name fn)))
cb3fe1f0
RS
419 (buf nil))
420 (and buf-list
421 (y-or-n-p (format "Kill dired buffer%s of %s, too? "
422 (dired-plural-s (length buf-list))
423 (file-name-nondirectory fn)))
424 (while buf-list
425 (save-excursion (kill-buffer (car buf-list)))
426 (setq buf-list (cdr buf-list)))))))
9572a9dd 427 ;; Anything else?
cb3fe1f0
RS
428 )
429
430\f
b578f267 431;;; EXTENSION MARKING FUNCTIONS.
cb3fe1f0 432
efcb74f6 433;; Mark files with some extension.
cb3fe1f0 434(defun dired-mark-extension (extension &optional marker-char)
b847eb8c 435 "Mark all files with a certain EXTENSION for use in later commands.
6fbad7af 436A `.' is *not* automatically prepended to the string entered."
cb3fe1f0
RS
437 ;; EXTENSION may also be a list of extensions instead of a single one.
438 ;; Optional MARKER-CHAR is marker to use.
439 (interactive "sMarking extension: \nP")
440 (or (listp extension)
441 (setq extension (list extension)))
442 (dired-mark-files-regexp
443 (concat ".";; don't match names with nothing but an extension
444 "\\("
445 (mapconcat 'regexp-quote extension "\\|")
446 "\\)$")
447 marker-char))
448
449(defun dired-flag-extension (extension)
b847eb8c 450 "In dired, flag all files with a certain EXTENSION for deletion.
cb3fe1f0
RS
451A `.' is *not* automatically prepended to the string entered."
452 (interactive "sFlagging extension: ")
453 (dired-mark-extension extension dired-del-marker))
454
efcb74f6 455;; Define some unpopular file extensions. Used for cleaning and omitting.
cb3fe1f0
RS
456
457(defvar dired-patch-unclean-extensions
458 '(".rej" ".orig")
459 "List of extensions of dispensable files created by the `patch' program.")
460
461(defvar dired-tex-unclean-extensions
462 '(".toc" ".log" ".aux");; these are already in completion-ignored-extensions
463 "List of extensions of dispensable files created by TeX.")
464
465(defvar dired-latex-unclean-extensions
466 '(".idx" ".lof" ".lot" ".glo")
467 "List of extensions of dispensable files created by LaTeX.")
468
469(defvar dired-bibtex-unclean-extensions
470 '(".blg" ".bbl")
471 "List of extensions of dispensable files created by BibTeX.")
472
473(defvar dired-texinfo-unclean-extensions
474 '(".cp" ".cps" ".fn" ".fns" ".ky" ".kys" ".pg" ".pgs"
475 ".tp" ".tps" ".vr" ".vrs")
476 "List of extensions of dispensable files created by texinfo.")
477
478(defun dired-clean-patch ()
479 "Flag dispensable files created by patch for deletion.
480See variable `dired-patch-unclean-extensions'."
481 (interactive)
482 (dired-flag-extension dired-patch-unclean-extensions))
483
484(defun dired-clean-tex ()
9572a9dd 485 "Flag dispensable files created by [La]TeX etc. for deletion.
ca388882 486See variables `dired-tex-unclean-extensions',
9572a9dd
KH
487`dired-latex-unclean-extensions', `dired-bibtex-unclean-extensions' and
488`dired-texinfo-unclean-extensions'."
cb3fe1f0
RS
489 (interactive)
490 (dired-flag-extension (append dired-texinfo-unclean-extensions
491 dired-latex-unclean-extensions
492 dired-bibtex-unclean-extensions
493 dired-tex-unclean-extensions)))
494
9572a9dd
KH
495(defun dired-very-clean-tex ()
496 "Flag dispensable files created by [La]TeX *and* \".dvi\" for deletion.
497See variables `dired-texinfo-unclean-extensions',
498`dired-latex-unclean-extensions', `dired-bibtex-unclean-extensions' and
499`dired-texinfo-unclean-extensions'."
cb3fe1f0 500 (interactive)
9572a9dd
KH
501 (dired-flag-extension (append dired-texinfo-unclean-extensions
502 dired-latex-unclean-extensions
503 dired-bibtex-unclean-extensions
504 dired-tex-unclean-extensions
505 (list ".dvi"))))
cb3fe1f0 506\f
b578f267 507;;; JUMP.
cb3fe1f0 508
40c8b203 509;;;###autoload
f5d6548a 510(defun dired-jump (&optional other-window file-name)
cb3fe1f0
RS
511 "Jump to dired buffer corresponding to current buffer.
512If in a file, dired the current directory and move to file's line.
6fbad7af 513If in Dired already, pop up a level and goto old directory's line.
cb3fe1f0 514In case the proper dired file line cannot be found, refresh the dired
f5d6548a
JL
515buffer and try again.
516When OTHER-WINDOW is non-nil, jump to dired buffer in other window.
517Interactively with prefix argument, read FILE-NAME and
518move to its line in dired."
519 (interactive
520 (list nil (and current-prefix-arg
521 (read-file-name "Jump to dired file: "))))
522 (let* ((file (or file-name buffer-file-name))
cb3fe1f0 523 (dir (if file (file-name-directory file) default-directory)))
f5d6548a 524 (if (and (eq major-mode 'dired-mode) (null file-name))
cb3fe1f0
RS
525 (progn
526 (setq dir (dired-current-directory))
527 (dired-up-directory other-window)
528 (or (dired-goto-file dir)
529 ;; refresh and try again
9572a9dd 530 (progn
cb3fe1f0
RS
531 (dired-insert-subdir (file-name-directory dir))
532 (dired-goto-file dir))))
533 (if other-window
534 (dired-other-window dir)
535 (dired dir))
536 (if file
537 (or (dired-goto-file file)
538 ;; refresh and try again
9572a9dd 539 (progn
cb3fe1f0 540 (dired-insert-subdir (file-name-directory file))
7e90bcf5
RS
541 (dired-goto-file file))
542 ;; Toggle omitting, if it is on, and try again.
ce64e046 543 (if dired-omit-mode
7e90bcf5 544 (progn
ce64e046 545 (dired-omit-mode)
7e90bcf5 546 (dired-goto-file file))))))))
cb3fe1f0 547
f5d6548a 548(defun dired-jump-other-window (&optional file-name)
6fbad7af 549 "Like \\[dired-jump] (`dired-jump') but in other window."
f5d6548a
JL
550 (interactive
551 (list (and current-prefix-arg
552 (read-file-name "Jump to dired file: "))))
553 (dired-jump t file-name))
cb3fe1f0 554\f
b578f267 555;;; OMITTING.
cb3fe1f0 556
efcb74f6
SM
557;; Enhanced omitting of lines from directory listings.
558;; Marked files are never omitted.
cb3fe1f0
RS
559
560;; should probably get rid of this and always use 'no-dir.
561;; sk 28-Aug-1991 09:37
562(defvar dired-omit-localp 'no-dir
b847eb8c 563 "The LOCALP argument `dired-omit-expunge' passes to `dired-get-filename'.
6fbad7af 564If it is `no-dir', omitting is much faster, but you can only match
470fa6d1
KS
565against the non-directory part of the file name. Set it to nil if you
566need to match the entire file name.")
cb3fe1f0
RS
567
568;; \017=^O for Omit - other packages can chose other control characters.
569(defvar dired-omit-marker-char ?\017
5a0c3f56 570 "Temporary marker used by Dired-Omit.
cb3fe1f0
RS
571Should never be used as marker by the user or other packages.")
572
573(defun dired-omit-startup ()
ce64e046 574 (or (assq 'dired-omit-mode minor-mode-alist)
cb3fe1f0 575 (setq minor-mode-alist
ce64e046 576 (append '((dired-omit-mode
ab606888
GM
577 (:eval (if (eq major-mode 'dired-mode)
578 " Omit" ""))))
579 minor-mode-alist))))
cb3fe1f0 580
ce64e046
LH
581(defun dired-mark-omitted ()
582 "Mark files matching `dired-omit-files' and `dired-omit-extensions'."
583 (interactive)
584 (let ((dired-omit-mode nil)) (revert-buffer)) ;; Show omitted files
585 (dired-mark-unmarked-files (dired-omit-regexp) nil nil dired-omit-localp))
cb3fe1f0
RS
586
587(defvar dired-omit-extensions
588 (append completion-ignored-extensions
589 dired-latex-unclean-extensions
590 dired-bibtex-unclean-extensions
591 dired-texinfo-unclean-extensions)
b847eb8c 592 "If non-nil, a list of extensions \(strings\) to omit from Dired listings.
685ff9f8
RS
593Defaults to elements of `completion-ignored-extensions',
594`dired-latex-unclean-extensions', `dired-bibtex-unclean-extensions', and
b847eb8c 595`dired-texinfo-unclean-extensions'.
685ff9f8 596
ce64e046
LH
597See interactive function `dired-omit-mode' \(\\[dired-omit-mode]\) and
598variables `dired-omit-mode' and `dired-omit-files'.")
cb3fe1f0
RS
599
600(defun dired-omit-expunge (&optional regexp)
601 "Erases all unmarked files matching REGEXP.
ce64e046 602Does nothing if global variable `dired-omit-mode' is nil, or if called
ad8c4554 603 non-interactively and buffer is bigger than `dired-omit-size-limit'.
cb3fe1f0
RS
604If REGEXP is nil or not specified, uses `dired-omit-files', and also omits
605 filenames ending in `dired-omit-extensions'.
606If REGEXP is the empty string, this function is a no-op.
607
608This functions works by temporarily binding `dired-marker-char' to
609`dired-omit-marker-char' and calling `dired-do-kill-lines'."
610 (interactive "sOmit files (regexp): ")
ce64e046 611 (if (and dired-omit-mode
32226619 612 (or (called-interactively-p 'interactive)
ad8c4554 613 (not dired-omit-size-limit)
8e458944
RS
614 (< (buffer-size) dired-omit-size-limit)
615 (progn
616 (message "Not omitting: directory larger than %d characters."
617 dired-omit-size-limit)
ce64e046 618 (setq dired-omit-mode nil)
8e458944 619 nil)))
cb3fe1f0 620 (let ((omit-re (or regexp (dired-omit-regexp)))
9b5ef74b 621 (old-modified-p (buffer-modified-p))
cb3fe1f0
RS
622 count)
623 (or (string= omit-re "")
624 (let ((dired-marker-char dired-omit-marker-char))
625 (message "Omitting...")
626 (if (dired-mark-unmarked-files omit-re nil nil dired-omit-localp)
627 (progn
628 (setq count (dired-do-kill-lines nil "Omitted %d line%s."))
048ea441 629 (force-mode-line-update))
cb3fe1f0 630 (message "(Nothing to omit)"))))
9b5ef74b
RS
631 ;; Try to preserve modified state of buffer. So `%*' doesn't appear
632 ;; in mode-line of omitted buffers.
b847eb8c 633 (set-buffer-modified-p (and old-modified-p
9b5ef74b
RS
634 (save-excursion
635 (goto-char (point-min))
636 (re-search-forward dired-re-mark nil t))))
cb3fe1f0
RS
637 count)))
638
639(defun dired-omit-regexp ()
640 (concat (if dired-omit-files (concat "\\(" dired-omit-files "\\)") "")
641 (if (and dired-omit-files dired-omit-extensions) "\\|" "")
642 (if dired-omit-extensions
643 (concat ".";; a non-extension part should exist
644 "\\("
645 (mapconcat 'regexp-quote dired-omit-extensions "\\|")
646 "\\)$")
647 "")))
648
649;; Returns t if any work was done, nil otherwise.
650(defun dired-mark-unmarked-files (regexp msg &optional unflag-p localp)
b847eb8c 651 "Mark unmarked files matching REGEXP, displaying MSG.
470fa6d1 652REGEXP is matched against the entire file name.
cb3fe1f0
RS
653Does not re-mark files which already have a mark.
654With prefix argument, unflag all those files.
6fbad7af 655Optional fourth argument LOCALP is as in `dired-get-filename'."
cb3fe1f0 656 (interactive "P")
6fbad7af 657 (let ((dired-marker-char (if unflag-p ?\s dired-marker-char)))
cb3fe1f0
RS
658 (dired-mark-if
659 (and
660 ;; not already marked
661 (looking-at " ")
662 ;; uninteresting
663 (let ((fn (dired-get-filename localp t)))
664 (and fn (string-match regexp fn))))
665 msg)))
666
552939e4
GM
667;; Compiler does not get fset.
668(declare-function dired-omit-old-add-entry "dired-x")
669
efcb74f6
SM
670;; REDEFINE.
671;; Redefine dired-aux.el's version of `dired-add-entry'
672;; Save old defun if not already done:
552939e4
GM
673(or (fboundp 'dired-omit-old-add-entry)
674 (fset 'dired-omit-old-add-entry (symbol-function 'dired-add-entry)))
e637bdf8 675
efcb74f6 676;; REDEFINE.
c8225cbe 677(defun dired-omit-new-add-entry (filename &optional marker-char relative)
cb3fe1f0
RS
678 ;; This redefines dired-aux.el's dired-add-entry to avoid calling ls for
679 ;; files that are going to be omitted anyway.
ce64e046 680 (if dired-omit-mode
cb3fe1f0
RS
681 ;; perhaps return t without calling ls
682 (let ((omit-re (dired-omit-regexp)))
683 (if (or (string= omit-re "")
684 (not
685 (string-match omit-re
686 (cond
687 ((eq 'no-dir dired-omit-localp)
688 filename)
689 ((eq t dired-omit-localp)
690 (dired-make-relative filename))
691 (t
692 (dired-make-absolute
693 filename
694 (file-name-directory filename)))))))
695 ;; if it didn't match, go ahead and add the entry
c8225cbe 696 (dired-omit-old-add-entry filename marker-char relative)
cb3fe1f0
RS
697 ;; dired-add-entry returns t for success, perhaps we should
698 ;; return file-exists-p
699 t))
700 ;; omitting is not turned on at all
c8225cbe 701 (dired-omit-old-add-entry filename marker-char relative)))
cb3fe1f0 702
cb3fe1f0
RS
703;; Redefine it.
704(fset 'dired-add-entry 'dired-omit-new-add-entry)
705
706\f
b578f267 707;;; VIRTUAL DIRED MODE.
cb3fe1f0 708
efcb74f6 709;; For browsing `ls -lR' listings in a dired-like fashion.
cb3fe1f0 710
6fbad7af 711(defalias 'virtual-dired 'dired-virtual)
cb3fe1f0
RS
712(defun dired-virtual (dirname &optional switches)
713 "Put this buffer into Virtual Dired mode.
714
715In Virtual Dired mode, all commands that do not actually consult the
716filesystem will work.
717
718This is useful if you want to peruse and move around in an ls -lR
719output file, for example one you got from an ftp server. With
720ange-ftp, you can even dired a directory containing an ls-lR file,
721visit that file and turn on virtual dired mode. But don't try to save
722this file, as dired-virtual indents the listing and thus changes the
723buffer.
724
725If you have save a Dired buffer in a file you can use \\[dired-virtual] to
726resume it in a later session.
727
6fbad7af
JB
728Type \\<dired-mode-map>\\[revert-buffer] \
729in the Virtual Dired buffer and answer `y' to convert
730the virtual to a real dired buffer again. You don't have to do this, though:
731you can relist single subdirs using \\[dired-do-redisplay]."
cb3fe1f0
RS
732
733 ;; DIRNAME is the top level directory of the buffer. It will become
734 ;; its `default-directory'. If nil, the old value of
735 ;; default-directory is used.
736
737 ;; Optional SWITCHES are the ls switches to use.
738
739 ;; Shell wildcards will be used if there already is a `wildcard'
740 ;; line in the buffer (thus it is a saved Dired buffer), but there
741 ;; is no other way to get wildcards. Insert a `wildcard' line by
742 ;; hand if you want them.
743
744 (interactive
745 (list (read-string "Virtual Dired directory: " (dired-virtual-guess-dir))))
746 (goto-char (point-min))
747 (or (looking-at " ")
748 ;; if not already indented, do it now:
749 (indent-region (point-min) (point-max) 2))
750 (or dirname (setq dirname default-directory))
751 (setq dirname (expand-file-name (file-name-as-directory dirname)))
752 (setq default-directory dirname) ; contains no wildcards
753 (let ((wildcard (save-excursion
754 (goto-char (point-min))
755 (forward-line 1)
756 (and (looking-at "^ wildcard ")
757 (buffer-substring (match-end 0)
758 (progn (end-of-line) (point)))))))
759 (if wildcard
760 (setq dirname (expand-file-name wildcard default-directory))))
761 ;; If raw ls listing (not a saved old dired buffer), give it a
762 ;; decent subdir headerline:
763 (goto-char (point-min))
764 (or (looking-at dired-subdir-regexp)
e8425548 765 (insert " "
fc50a3be
MY
766 (directory-file-name (file-name-directory default-directory))
767 ":\n"))
cb3fe1f0
RS
768 (dired-mode dirname (or switches dired-listing-switches))
769 (setq mode-name "Virtual Dired"
770 revert-buffer-function 'dired-virtual-revert)
771 (set (make-local-variable 'dired-subdir-alist) nil)
772 (dired-build-subdir-alist)
773 (goto-char (point-min))
774 (dired-initial-position dirname))
775
776(defun dired-virtual-guess-dir ()
b847eb8c 777 "Guess and return appropriate working directory of this buffer.
4e6ef391 778The buffer is assumed to be in Dired or ls -lR format. The guess is
b847eb8c
DL
779based upon buffer contents. If nothing could be guessed, returns
780nil."
cb3fe1f0
RS
781
782 (let ((regexp "^\\( \\)?\\([^ \n\r]*\\)\\(:\\)[\n\r]")
783 (subexpr 2))
784 (goto-char (point-min))
785 (cond ((looking-at regexp)
786 ;; If a saved dired buffer, look to which dir and
787 ;; perhaps wildcard it belongs:
788 (let ((dir (buffer-substring (match-beginning subexpr)
789 (match-end subexpr))))
790 (file-name-as-directory dir)))
791 ;; Else no match for headerline found. It's a raw ls listing.
792 ;; In raw ls listings the directory does not have a headerline
793 ;; try parent of first subdir, if any
794 ((re-search-forward regexp nil t)
795 (file-name-directory
796 (directory-file-name
797 (file-name-as-directory
798 (buffer-substring (match-beginning subexpr)
799 (match-end subexpr))))))
800 (t ; if all else fails
801 nil))))
802
803
804(defun dired-virtual-revert (&optional arg noconfirm)
805 (if (not
806 (y-or-n-p "Cannot revert a Virtual Dired buffer - switch to Real Dired mode? "))
b847eb8c 807 (error "Cannot revert a Virtual Dired buffer")
cb3fe1f0
RS
808 (setq mode-name "Dired"
809 revert-buffer-function 'dired-revert)
810 (revert-buffer)))
811
812;; A zero-arg version of dired-virtual.
cb3fe1f0 813(defun dired-virtual-mode ()
6fbad7af 814 "Put current buffer into Virtual Dired mode (see `dired-virtual').
b94d76ae 815Useful on `magic-mode-alist' with the regexp
cb3fe1f0 816
b94d76ae 817 \"^ \\\\(/[^ /]+\\\\)+/?:$\"
cb3fe1f0 818
6fbad7af 819to put saved dired buffers automatically into Virtual Dired mode.
cb3fe1f0 820
b94d76ae 821Also useful for `auto-mode-alist' like this:
cb3fe1f0 822
b94d76ae
GM
823 (add-to-list 'auto-mode-alist
824 '(\"[^/]\\\\.dired\\\\'\" . dired-virtual-mode))"
cb3fe1f0
RS
825 (interactive)
826 (dired-virtual (dired-virtual-guess-dir)))
827
828\f
b578f267 829;;; SMART SHELL.
cb3fe1f0 830
efcb74f6
SM
831;; An Emacs buffer can have but one working directory, stored in the
832;; buffer-local variable `default-directory'. A Dired buffer may have
833;; several subdirectories inserted, but still has but one working directory:
834;; that of the top level Dired directory in that buffer. For some commands
835;; it is appropriate that they use the current Dired directory instead of
836;; `default-directory', e.g., `find-file' and `compile'. This is a general
837;; mechanism is provided for special handling of the working directory in
838;; special major modes.
cb3fe1f0
RS
839
840;; It's easier to add to this alist than redefine function
841;; default-directory while keeping the old information.
842(defconst default-directory-alist
843 '((dired-mode . (if (fboundp 'dired-current-directory)
844 (dired-current-directory)
845 default-directory)))
b847eb8c
DL
846 "Alist of major modes and their opinion on `default-directory'.
847This is given as a Lisp expression to evaluate. A resulting value of
848nil is ignored in favor of `default-directory'.")
cb3fe1f0 849
b847eb8c
DL
850(defun dired-default-directory ()
851 "Usage like variable `default-directory'.
852Knows about the special cases in variable `default-directory-alist'."
cb3fe1f0
RS
853 (or (eval (cdr (assq major-mode default-directory-alist)))
854 default-directory))
855
d3a89b9e 856(defun dired-smart-shell-command (command &optional output-buffer error-buffer)
6fbad7af 857 "Like function `shell-command', but in the current Virtual Dired directory."
d3a89b9e
JL
858 (interactive
859 (list
57199d9b
JL
860 (read-shell-command "Shell command: " nil nil
861 (cond
862 (buffer-file-name (file-relative-name buffer-file-name))
863 ((eq major-mode 'dired-mode) (dired-get-filename t t))))
d3a89b9e
JL
864 current-prefix-arg
865 shell-command-default-error-buffer))
b847eb8c 866 (let ((default-directory (dired-default-directory)))
d3a89b9e 867 (shell-command command output-buffer error-buffer)))
cb3fe1f0
RS
868
869\f
b578f267 870;;; LOCAL VARIABLES FOR DIRED BUFFERS.
cb3fe1f0 871
efcb74f6 872;; Brief Description:
9572a9dd 873;;;
efcb74f6 874;; * `dired-extra-startup' is part of the `dired-mode-hook'.
9572a9dd 875;;;
efcb74f6 876;; * `dired-extra-startup' calls `dired-hack-local-variables'
9572a9dd 877;;;
efcb74f6 878;; * `dired-hack-local-variables' checks the value of
9572a9dd
KH
879;;; `dired-local-variables-file'
880;;;
efcb74f6 881;; * Check if `dired-local-variables-file' is a non-nil string and is a
cb3fe1f0 882;;; filename found in the directory of the Dired Buffer being created.
9572a9dd 883;;;
efcb74f6 884;; * If `dired-local-variables-file' satisfies the above, then temporarily
cb3fe1f0 885;;; include it in the Dired Buffer at the bottom.
9572a9dd 886;;;
efcb74f6 887;; * Set `enable-local-variables' temporarily to the user variable
cb3fe1f0
RS
888;;; `dired-enable-local-variables' and run `hack-local-variables' on the
889;;; Dired Buffer.
890
db8f8812 891(defvar dired-local-variables-file (convert-standard-filename ".dired")
cb3fe1f0
RS
892 "Filename, as string, containing local dired buffer variables to be hacked.
893If this file found in current directory, then it will be inserted into dired
6fbad7af
JB
894buffer and `hack-local-variables' will be run. See Info node
895`(emacs)File Variables' for more information on local variables.
896See also `dired-enable-local-variables'.")
cb3fe1f0
RS
897
898(defun dired-hack-local-variables ()
899 "Evaluate local variables in `dired-local-variables-file' for dired buffer."
900 (if (and dired-local-variables-file
901 (stringp dired-local-variables-file)
902 (file-exists-p dired-local-variables-file))
903 (let ((opoint (point-max))
904 buffer-read-only
905 ;; In case user has `enable-local-variables' set to nil we
906 ;; override it locally with dired's variable.
907 (enable-local-variables dired-enable-local-variables))
908 ;; Insert 'em.
909 (save-excursion
910 (goto-char opoint)
911 (insert "\^L\n")
912 (insert-file-contents dired-local-variables-file))
913 ;; Hack 'em.
914 (let ((buffer-file-name dired-local-variables-file))
915 (hack-local-variables))
916 ;; Make sure that the modeline shows the proper information.
917 (dired-sort-set-modeline)
918 ;; Delete this stuff: `eobp' is used to find last subdir by dired.el.
9572a9dd 919 (delete-region opoint (point-max)))))
cb3fe1f0 920
9572a9dd 921(defun dired-omit-here-always ()
b847eb8c 922 "Create `dired-local-variables-file' for omitting and reverts directory.
6fbad7af 923Sets `dired-omit-mode' to t in a local variables file that is readable by
cb3fe1f0 924dired."
9572a9dd 925 (interactive)
cb3fe1f0
RS
926 (if (file-exists-p dired-local-variables-file)
927 (message "File `./%s' already exists." dired-local-variables-file)
928
929 ;; Create `dired-local-variables-file'.
efcb74f6 930 (with-current-buffer (get-buffer-create " *dot-dired*")
cb3fe1f0 931 (erase-buffer)
ce64e046 932 (insert "Local Variables:\ndired-omit-mode: t\nEnd:\n")
cb3fe1f0
RS
933 (write-file dired-local-variables-file)
934 (kill-buffer (current-buffer)))
935
936 ;; Run extra-hooks and revert directory.
937 (dired-extra-startup)
938 (dired-revert)))
939
940\f
b578f267 941;;; GUESS SHELL COMMAND.
cb3fe1f0 942
efcb74f6 943;; Brief Description:
9572a9dd 944;;;
efcb74f6 945;; `dired-do-shell-command' is bound to `!' by dired.el.
9572a9dd 946;;;
efcb74f6 947;; * Redefine `dired-read-shell-command' so it calls
cb3fe1f0 948;;; `dired-guess-shell-command'.
9572a9dd 949;;;
efcb74f6 950;; * `dired-guess-shell-command' calls `dired-guess-default' with list of
cb3fe1f0 951;;; marked files.
9572a9dd 952;;;
efcb74f6 953;; * Parse `dired-guess-shell-alist-user' and
cb3fe1f0
RS
954;;; `dired-guess-shell-alist-default' (in that order) for the first REGEXP
955;;; that matches the first file in the file list.
9572a9dd 956;;;
efcb74f6 957;; * If the REGEXP matches all the entries of the file list then evaluate
c0d79871 958;;; COMMAND, which is either a string or a Lisp expression returning a
cb3fe1f0 959;;; string. COMMAND may be a list of commands.
9572a9dd 960;;;
efcb74f6 961;; * Return this command to `dired-guess-shell-command' which prompts user
747e8ee2 962;;; with it. The list of commands is put into the list of default values.
cb3fe1f0
RS
963;;; If a command is used successfully then it is stored permanently in
964;;; `dired-shell-command-history'.
965
efcb74f6 966;; Guess what shell command to apply to a file.
cb3fe1f0
RS
967(defvar dired-shell-command-history nil
968 "History list for commands that read dired-shell commands.")
969
efcb74f6 970;; Default list of shell commands.
cb3fe1f0 971
efcb74f6
SM
972;; NOTE: Use `gunzip -c' instead of `zcat' on `.gz' files. Some do not
973;; install GNU zip's version of zcat.
cb3fe1f0
RS
974
975(defvar dired-guess-shell-alist-default
976 (list
ecd69427 977 (list "\\.tar$"
ca136496
RF
978 '(if dired-guess-shell-gnutar
979 (concat dired-guess-shell-gnutar " xvf")
980 "tar xvf")
981 ;; Extract files into a separate subdirectory
982 '(if dired-guess-shell-gnutar
983 (concat "mkdir " (file-name-sans-extension file)
984 "; " dired-guess-shell-gnutar " -C "
985 (file-name-sans-extension file) " -xvf")
986 (concat "mkdir " (file-name-sans-extension file)
987 "; tar -C " (file-name-sans-extension file) " -xvf"))
988 ;; List archive contents.
989 '(if dired-guess-shell-gnutar
990 (concat dired-guess-shell-gnutar " tvf")
991 "tar tvf"))
cb3fe1f0
RS
992
993 ;; REGEXPS for compressed archives must come before the .Z rule to
994 ;; be recognized:
995 (list "\\.tar\\.Z$"
ca136496
RF
996 ;; Untar it.
997 '(if dired-guess-shell-gnutar
998 (concat dired-guess-shell-gnutar " zxvf")
999 (concat "zcat * | tar xvf -"))
1000 ;; Optional conversion to gzip format.
1001 '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
1002 " " dired-guess-shell-znew-switches))
cb3fe1f0
RS
1003
1004 ;; gzip'ed archives
2f017676 1005 (list "\\.t\\(ar\\.\\)?gz$"
ca136496
RF
1006 '(if dired-guess-shell-gnutar
1007 (concat dired-guess-shell-gnutar " zxvf")
1008 (concat "gunzip -qc * | tar xvf -"))
1009 ;; Extract files into a separate subdirectory
1010 '(if dired-guess-shell-gnutar
1011 (concat "mkdir " (file-name-sans-extension file)
1012 "; " dired-guess-shell-gnutar " -C "
1013 (file-name-sans-extension file) " -zxvf")
1014 (concat "mkdir " (file-name-sans-extension file)
1015 "; gunzip -qc * | tar -C "
1016 (file-name-sans-extension file) " -xvf -"))
1017 ;; Optional decompression.
1018 '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q" ""))
1019 ;; List archive contents.
1020 '(if dired-guess-shell-gnutar
1021 (concat dired-guess-shell-gnutar " ztvf")
1022 (concat "gunzip -qc * | tar tvf -")))
ecd69427 1023
7ba7b794 1024 ;; bzip2'ed archives
ecd69427 1025 (list "\\.t\\(ar\\.bz2\\|bz\\)$"
7ba7b794 1026 "bunzip2 -c * | tar xvf -"
ca136496
RF
1027 ;; Extract files into a separate subdirectory
1028 '(concat "mkdir " (file-name-sans-extension file)
1029 "; bunzip2 -c * | tar -C "
1030 (file-name-sans-extension file) " -xvf -")
7ba7b794 1031 ;; Optional decompression.
ca136496 1032 "bunzip2")
cb3fe1f0 1033
c10e0633
GM
1034 ;; xz'ed archives
1035 (list "\\.t\\(ar\\.\\)?xz$"
1036 "unxz -c * | tar xvf -"
1037 ;; Extract files into a separate subdirectory
1038 '(concat "mkdir " (file-name-sans-extension file)
1039 "; unxz -c * | tar -C "
1040 (file-name-sans-extension file) " -xvf -")
1041 ;; Optional decompression.
1042 "unxz")
1043
ecd69427
JL
1044 '("\\.shar\\.Z$" "zcat * | unshar")
1045 '("\\.shar\\.g?z$" "gunzip -qc * | unshar")
cb3fe1f0 1046
85400f54 1047 '("\\.e?ps$" "ghostview" "xloadimage" "lpr")
ecd69427 1048 (list "\\.e?ps\\.g?z$" "gunzip -qc * | ghostview -"
ca136496
RF
1049 ;; Optional decompression.
1050 '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
ecd69427 1051 (list "\\.e?ps\\.Z$" "zcat * | ghostview -"
ca136496
RF
1052 ;; Optional conversion to gzip format.
1053 '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
1054 " " dired-guess-shell-znew-switches))
ecd69427 1055
cb3fe1f0 1056 '("\\.patch$" "cat * | patch")
ecd69427 1057 (list "\\.patch\\.g?z$" "gunzip -qc * | patch"
ca136496
RF
1058 ;; Optional decompression.
1059 '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
ecd69427 1060 (list "\\.patch\\.Z$" "zcat * | patch"
ca136496
RF
1061 ;; Optional conversion to gzip format.
1062 '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
1063 " " dired-guess-shell-znew-switches))
cb3fe1f0 1064
ecd69427 1065 ;; The following four extensions are useful with dired-man ("N" key)
d2ea84be 1066 (list "\\.\\(?:[0-9]\\|man\\)$" '(progn (require 'man)
ca136496
RF
1067 (if (Man-support-local-filenames)
1068 "man -l"
1069 "cat * | tbl | nroff -man -h")))
d2ea84be 1070 (list "\\.\\(?:[0-9]\\|man\\)\\.g?z$" '(progn (require 'man)
ca136496
RF
1071 (if (Man-support-local-filenames)
1072 "man -l"
1073 "gunzip -qc * | tbl | nroff -man -h"))
1074 ;; Optional decompression.
1075 '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
ecd69427 1076 (list "\\.[0-9]\\.Z$" '(progn (require 'man)
ca136496
RF
1077 (if (Man-support-local-filenames)
1078 "man -l"
1079 "zcat * | tbl | nroff -man -h"))
1080 ;; Optional conversion to gzip format.
1081 '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
1082 " " dired-guess-shell-znew-switches))
ecd69427
JL
1083 '("\\.pod$" "perldoc" "pod2man * | nroff -man")
1084
ca136496
RF
1085 '("\\.dvi$" "xdvi" "dvips") ; preview and printing
1086 '("\\.au$" "play") ; play Sun audiofiles
1087 '("\\.mpe?g$\\|\\.avi$" "xine -p")
70ee5ed1
GM
1088 '("\\.ogg$" "ogg123")
1089 '("\\.mp3$" "mpg123")
ca136496
RF
1090 '("\\.wav$" "play")
1091 '("\\.uu$" "uudecode") ; for uudecoded files
cb3fe1f0 1092 '("\\.hqx$" "mcvert")
ca136496
RF
1093 '("\\.sh$" "sh") ; execute shell scripts
1094 '("\\.xbm$" "bitmap") ; view X11 bitmaps
cb3fe1f0 1095 '("\\.gp$" "gnuplot")
85400f54 1096 '("\\.p[bgpn]m$" "xloadimage")
ca136496 1097 '("\\.gif$" "xloadimage") ; view gif pictures
85400f54 1098 '("\\.tif$" "xloadimage")
b847eb8c 1099 '("\\.png$" "display") ; xloadimage 4.1 doesn't grok PNG
ecd69427 1100 '("\\.jpe?g$" "xloadimage")
ca136496
RF
1101 '("\\.fig$" "xfig") ; edit fig pictures
1102 '("\\.out$" "xgraph") ; for plotting purposes.
cb3fe1f0
RS
1103 '("\\.tex$" "latex" "tex")
1104 '("\\.texi\\(nfo\\)?$" "makeinfo" "texi2dvi")
ca136496
RF
1105 '("\\.pdf$" "xpdf")
1106 '("\\.doc$" "antiword" "strings")
1107 '("\\.rpm$" "rpm -qilp" "rpm -ivh")
1108 '("\\.dia$" "dia")
1109 '("\\.mgp$" "mgp")
cb3fe1f0
RS
1110
1111 ;; Some other popular archivers.
ca136496
RF
1112 (list "\\.zip$" "unzip" "unzip -l"
1113 ;; Extract files into a separate subdirectory
1114 '(concat "unzip" (if dired-guess-shell-gzip-quiet " -q")
1115 " -d " (file-name-sans-extension file)))
cb3fe1f0 1116 '("\\.zoo$" "zoo x//")
cb3fe1f0
RS
1117 '("\\.lzh$" "lharc x")
1118 '("\\.arc$" "arc x")
1119 '("\\.shar$" "unshar")
1120
1121 ;; Compression.
1122 (list "\\.g?z$" '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
ecd69427 1123 (list "\\.dz$" "dictunzip")
7ba7b794 1124 (list "\\.bz2$" "bunzip2")
c10e0633 1125 (list "\\.xz$" "unxz")
cb3fe1f0 1126 (list "\\.Z$" "uncompress"
ca136496
RF
1127 ;; Optional conversion to gzip format.
1128 '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
1129 " " dired-guess-shell-znew-switches))
1130
1131 '("\\.sign?$" "gpg --verify"))
9572a9dd 1132
cb3fe1f0 1133 "Default alist used for shell command guessing.
b847eb8c 1134See `dired-guess-shell-alist-user'.")
cb3fe1f0 1135
b847eb8c
DL
1136(defcustom dired-guess-shell-alist-user nil
1137 "User-defined alist of rules for suggested commands.
1138These rules take precedence over the predefined rules in the variable
cb3fe1f0
RS
1139`dired-guess-shell-alist-default' (to which they are prepended).
1140
1141Each element of this list looks like
1142
1143 \(REGEXP COMMAND...\)
1144
6fbad7af 1145where each COMMAND can either be a string or a Lisp expression that evaluates
cb3fe1f0
RS
1146to a string. If several COMMANDs are given, the first one will be the default
1147and the rest will be added temporarily to the history and can be retrieved
1148with \\[previous-history-element] (M-p) .
1149
70ee5ed1
GM
1150The variable `dired-guess-shell-case-fold-search' controls whether
1151REGEXP is matched case-sensitively.
1152
cb3fe1f0
RS
1153You can set this variable in your ~/.emacs. For example, to add rules for
1154`.foo' and `.bar' files, write
1155
1156 \(setq dired-guess-shell-alist-user
b847eb8c 1157 (list (list \"\\\\.foo\\\\'\" \"FOO-COMMAND\");; fixed rule
cb3fe1f0 1158 ;; possibly more rules ...
de5af6bb 1159 (list \"\\\\.bar\\\\'\";; rule with condition test
cb3fe1f0
RS
1160 '(if condition
1161 \"BAR-COMMAND-1\"
b847eb8c
DL
1162 \"BAR-COMMAND-2\")))\)"
1163 :group 'dired-x
1164 :type '(alist :key-type regexp :value-type (repeat sexp)))
cb3fe1f0 1165
d7af463c
RF
1166(defcustom dired-guess-shell-case-fold-search t
1167 "If non-nil, `dired-guess-shell-alist-default' and
1168`dired-guess-shell-alist-user' are matched case-insensitively."
1169 :group 'dired-x
1170 :type 'boolean)
1171
cb3fe1f0 1172(defun dired-guess-default (files)
b847eb8c
DL
1173 "Guess a shell commands for FILES. Return command or list of commands.
1174See `dired-guess-shell-alist-user'."
cb3fe1f0 1175
d7af463c 1176 (let* ((case-fold-search dired-guess-shell-case-fold-search)
cb3fe1f0
RS
1177 ;; Prepend the user's alist to the default alist.
1178 (alist (append dired-guess-shell-alist-user
1179 dired-guess-shell-alist-default))
1180 (file (car files))
1181 (flist (cdr files))
1182 elt regexp cmds)
1183
1184 ;; Find the first match in the alist for first file in FILES.
1185 (while alist
1186 (setq elt (car alist)
1187 regexp (car elt)
1188 alist (cdr alist))
1189 (if (string-match regexp file)
1190 (setq cmds (cdr elt)
1191 alist nil)))
1192
1193 ;; If more than one file, see if all of FILES match regular expression.
1194 (while (and flist
1195 (string-match regexp (car flist)))
1196 (setq flist (cdr flist)))
9572a9dd 1197
cb3fe1f0
RS
1198 ;; If flist is still non-nil, then do not guess since this means that not
1199 ;; all the files in FILES were matched by the regexp.
1200 (setq cmds (and (not flist) cmds))
1201
9572a9dd
KH
1202 ;; Return commands or nil if flist is still non-nil.
1203 ;; Evaluate the commands in order that any logical testing will be done.
cb3fe1f0
RS
1204 (cond ((not (cdr cmds))
1205 (eval (car cmds))) ; single command
1206 (t
1207 (mapcar (function eval) cmds)))))
1208
1209(defun dired-guess-shell-command (prompt files)
b847eb8c 1210 "Ask user with PROMPT for a shell command, guessing a default from FILES."
cb3fe1f0 1211 (let ((default (dired-guess-default files))
5420b514 1212 default-list val)
cb3fe1f0
RS
1213 (if (null default)
1214 ;; Nothing to guess
c521381a 1215 (read-shell-command prompt nil 'dired-shell-command-history)
cb3fe1f0 1216 (if (listp default)
cb3fe1f0
RS
1217 ;; More than one guess
1218 (setq default-list default
1219 default (car default)
1220 prompt (concat
1221 prompt
1222 (format "{%d guesses} " (length default-list))))
cb3fe1f0
RS
1223 ;; Just one guess
1224 (setq default-list (list default)))
5420b514
JL
1225 ;; Put the first guess in the prompt but not in the initial value.
1226 (setq prompt (concat prompt (format "[%s] " default)))
1227 ;; All guesses can be retrieved with M-n
c521381a
JL
1228 (setq val (read-shell-command prompt nil
1229 'dired-shell-command-history
1230 default-list))
5420b514
JL
1231 ;; If we got a return, then return default.
1232 (if (equal val "") default val))))
cb3fe1f0 1233
efcb74f6
SM
1234;; REDEFINE.
1235;; Redefine dired-aux.el's version:
cb3fe1f0 1236(defun dired-read-shell-command (prompt arg files)
5a0c3f56 1237 "Read a dired shell command prompting with PROMPT (using `read-shell-command').
b847eb8c 1238ARG is the prefix arg and may be used to indicate in the prompt which
c521381a 1239FILES are affected.
b847eb8c 1240This is an extra function so that you can redefine it."
c521381a
JL
1241 (minibuffer-with-setup-hook
1242 (lambda ()
1243 (set (make-local-variable 'minibuffer-default-add-function)
1244 'minibuffer-default-add-dired-shell-commands))
1245 (dired-mark-pop-up
1246 nil 'shell files
1247 'dired-guess-shell-command
1248 (format prompt (dired-mark-prompt arg files)) ; PROMPT
1249 files))) ; FILES
cb3fe1f0
RS
1250
1251\f
b578f267 1252;;; RELATIVE SYMBOLIC LINKS.
cb3fe1f0 1253
e8425548
JB
1254(declare-function make-symbolic-link "fileio.c")
1255
cb3fe1f0
RS
1256(defvar dired-keep-marker-relsymlink ?S
1257 "See variable `dired-keep-marker-move'.")
1258
1259(defun dired-make-relative-symlink (file1 file2 &optional ok-if-already-exists)
b847eb8c 1260 "Make a symbolic link (pointing to FILE1) in FILE2.
cb3fe1f0
RS
1261The link is relative (if possible), for example
1262
1263 \"/vol/tex/bin/foo\" \"/vol/local/bin/foo\"
1264
1265results in
1266
b847eb8c 1267 \"../../tex/bin/foo\" \"/vol/local/bin/foo\""
cb3fe1f0
RS
1268 (interactive "FRelSymLink: \nFRelSymLink %s: \np")
1269 (let (name1 name2 len1 len2 (index 0) sub)
1270 (setq file1 (expand-file-name file1)
1271 file2 (expand-file-name file2)
1272 len1 (length file1)
1273 len2 (length file2))
470fa6d1 1274 ;; Find common initial file name components:
cb3fe1f0
RS
1275 (let (next)
1276 (while (and (setq next (string-match "/" file1 index))
1277 (setq next (1+ next))
1278 (< next (min len1 len2))
1279 ;; For the comparison, both substrings must end in
1280 ;; `/', so NEXT is *one plus* the result of the
1281 ;; string-match.
1282 ;; E.g., consider the case of linking "/tmp/a/abc"
34ff2275 1283 ;; to "/tmp/abc" erroneously giving "/tmp/a" instead
cb3fe1f0
RS
1284 ;; of "/tmp/" as common initial component
1285 (string-equal (substring file1 0 next)
1286 (substring file2 0 next)))
1287 (setq index next))
1288 (setq name2 file2
1289 sub (substring file1 0 index)
1290 name1 (substring file1 index)))
1291 (if (string-equal sub "/")
470fa6d1 1292 ;; No common initial file name found
cb3fe1f0
RS
1293 (setq name1 file1)
1294 ;; Else they have a common parent directory
1295 (let ((tem (substring file2 index))
1296 (start 0)
1297 (count 0))
1298 ;; Count number of slashes we must compensate for ...
1299 (while (setq start (string-match "/" tem start))
1300 (setq count (1+ count)
1301 start (1+ start)))
1302 ;; ... and prepend a "../" for each slash found:
1303 (while (> count 0)
1304 (setq count (1- count)
1305 name1 (concat "../" name1)))))
1306 (make-symbolic-link
1307 (directory-file-name name1) ; must not link to foo/
1308 ; (trailing slash!)
1309 name2 ok-if-already-exists)))
1310
5e5eaeda 1311;;;###autoload
cb3fe1f0 1312(defun dired-do-relsymlink (&optional arg)
b847eb8c
DL
1313 "Relative symlink all marked (or next ARG) files into a directory.
1314Otherwise make a relative symbolic link to the current file.
cb3fe1f0
RS
1315This creates relative symbolic links like
1316
1317 foo -> ../bar/foo
1318
1319not absolute ones like
1320
42496dc8
EZ
1321 foo -> /ugly/file/name/that/may/change/any/day/bar/foo
1322
4d4238cc 1323For absolute symlinks, use \\[dired-do-symlink]."
cb3fe1f0
RS
1324 (interactive "P")
1325 (dired-do-create-files 'relsymlink (function dired-make-relative-symlink)
1326 "RelSymLink" arg dired-keep-marker-relsymlink))
1327
d8e396ce 1328(defun dired-do-relsymlink-regexp (regexp newname &optional arg whole-name)
cb3fe1f0
RS
1329 "RelSymlink all marked files containing REGEXP to NEWNAME.
1330See functions `dired-do-rename-regexp' and `dired-do-relsymlink'
1331for more info."
1332 (interactive (dired-mark-read-regexp "RelSymLink"))
1333 (dired-do-create-files-regexp
1334 (function dired-make-relative-symlink)
d8e396ce 1335 "RelSymLink" arg regexp newname whole-name dired-keep-marker-relsymlink))
cb3fe1f0
RS
1336
1337\f
b578f267 1338;;; VISIT ALL MARKED FILES SIMULTANEOUSLY.
cb3fe1f0 1339
efcb74f6 1340;; Brief Description:
9572a9dd 1341;;;
efcb74f6 1342;; `dired-do-find-marked-files' is bound to `F' by dired-x.el.
9572a9dd 1343;;;
efcb74f6 1344;; * Use `dired-get-marked-files' to collect the marked files in the current
9572a9dd
KH
1345;;; Dired Buffer into a list of filenames `FILE-LIST'.
1346;;;
efcb74f6 1347;; * Pass FILE-LIST to `dired-simultaneous-find-file' all with
cb3fe1f0 1348;;; `dired-do-find-marked-files''s prefix argument NOSELECT.
9572a9dd 1349;;;
efcb74f6 1350;; * `dired-simultaneous-find-file' runs through FILE-LIST decrementing the
cb3fe1f0 1351;;; list each time.
9572a9dd 1352;;;
5a0c3f56 1353;; * If NOSELECT is non-nil then just run `find-file-noselect' on each
cb3fe1f0 1354;;; element of FILE-LIST.
9572a9dd 1355;;;
efcb74f6 1356;; * If NOSELECT is nil then calculate the `size' of the window for each file
cb3fe1f0
RS
1357;;; by dividing the `window-height' by length of FILE-LIST. Thus, `size' is
1358;;; cognizant of the window-configuration.
9572a9dd 1359;;;
efcb74f6 1360;; * If `size' is too small abort, otherwise run `find-file' on each element
cb3fe1f0
RS
1361;;; of FILE-LIST giving each a window of height `size'.
1362
1363(defun dired-do-find-marked-files (&optional noselect)
1364 "Find all marked files displaying all of them simultaneously.
1365With optional NOSELECT just find files but do not select them.
1366
1367The current window is split across all files marked, as evenly as possible.
1368Remaining lines go to bottom-most window. The number of files that can be
1369displayed this way is restricted by the height of the current window and
1370`window-min-height'.
1371
9572a9dd 1372To keep dired buffer displayed, type \\[split-window-vertically] first.
cb3fe1f0
RS
1373To display just marked files, type \\[delete-other-windows] first."
1374
1375 (interactive "P")
1376 (dired-simultaneous-find-file (dired-get-marked-files) noselect))
1377
1378(defun dired-simultaneous-find-file (file-list noselect)
1379
b847eb8c
DL
1380 "Visit all files in FILE-LIST and display them simultaneously.
1381The current window is split across all files in FILE-LIST, as evenly as
1382possible. Remaining lines go to the bottom-most window. The number of
1383files that can be displayed this way is restricted by the height of the
1384current window and the variable `window-min-height'. With non-nil
1385NOSELECT the files are merely found but not selected."
9572a9dd 1386
cb3fe1f0
RS
1387 ;; We don't make this function interactive because it is usually too clumsy
1388 ;; to specify FILE-LIST interactively unless via dired.
1389
1390 (let (size)
1391
1392 (if noselect
1393 ;; Do not select the buffer.
1394 (find-file-noselect (car file-list))
1395
1396 ;; We will have to select the buffer. Calculate and check window size.
1397 (setq size (/ (window-height) (length file-list)))
1398 (or (<= window-min-height size)
b847eb8c 1399 (error "Too many files to visit simultaneously. Try C-u prefix"))
cb3fe1f0
RS
1400 (find-file (car file-list)))
1401
1402 ;; Decrement.
1403 (setq file-list (cdr file-list))
1404
1405 (while file-list
1406
1407 (if noselect
1408 ;; Do not select the buffer.
1409 (find-file-noselect (car file-list))
1410
1411 ;; Vertically split off a window of desired size. Upper window will
1412 ;; have SIZE lines. Select lower (larger) window. We split it again.
1413 (select-window (split-window nil size))
1414 (find-file (car file-list)))
1415
1416 ;; Decrement.
1417 (setq file-list (cdr file-list)))))
1418
1419\f
b578f267 1420;;; MISCELLANEOUS COMMANDS.
cb3fe1f0 1421
efcb74f6 1422;; Run man on files.
9572a9dd 1423
cb3fe1f0 1424(defun dired-man ()
9572a9dd 1425 "Run man on this file. Display old buffer if buffer name matches filename.
6fbad7af 1426Uses `man.el' of \\[manual-entry] fame."
cb3fe1f0 1427 (interactive)
685ff9f8 1428 (require 'man)
ecd69427
JL
1429 (let* ((file (dired-get-filename))
1430 (manual-program (replace-regexp-in-string "\\*" "%s"
1431 (dired-guess-shell-command
1432 "Man command: " (list file)))))
685ff9f8 1433 (Man-getpage-in-background file)))
cb3fe1f0 1434
efcb74f6 1435;; Run Info on files.
cb3fe1f0
RS
1436
1437(defun dired-info ()
1438 "Run info on this file."
1439 (interactive)
1440 (info (dired-get-filename)))
1441
efcb74f6 1442;; Run mail on mail folders.
cb3fe1f0 1443
670d3fce
RF
1444;; Avoid compiler warning.
1445(eval-when-compile
1446 (when (not (fboundp 'vm-visit-folder))
1447 (defun vm-visit-folder (file &optional arg)
1448 nil)))
9572a9dd 1449
cb3fe1f0
RS
1450(defun dired-vm (&optional read-only)
1451 "Run VM on this file.
1452With prefix arg, visit folder read-only (this requires at least VM 5).
1453See also variable `dired-vm-read-only-folders'."
1454 (interactive "P")
1455 (let ((dir (dired-current-directory))
1456 (fil (dired-get-filename)))
1457 ;; take care to supply 2nd arg only if requested - may still run VM 4!
1458 (cond (read-only (vm-visit-folder fil t))
1459 ((eq t dired-vm-read-only-folders) (vm-visit-folder fil t))
1460 ((null dired-vm-read-only-folders) (vm-visit-folder fil))
1461 (t (vm-visit-folder fil (not (file-writable-p fil)))))
1462 ;; so that pressing `v' inside VM does prompt within current directory:
1463 (set (make-local-variable 'vm-folder-directory) dir)))
1464
1465(defun dired-rmail ()
1466 "Run RMAIL on this file."
1467 (interactive)
1468 (rmail (dired-get-filename)))
1469
1470(defun dired-do-run-mail ()
1471 "If `dired-bind-vm' is t, then function `dired-vm', otherwise `dired-rmail'."
1472 (interactive)
1473 (if dired-bind-vm
1474 ;; Read mail folder using vm.
1475 (dired-vm)
1476 ;; Read mail folder using rmail.
1477 (dired-rmail)))
1478
1479\f
b578f267 1480;;; MISCELLANEOUS INTERNAL FUNCTIONS.
cb3fe1f0 1481
552939e4 1482(declare-function dired-old-find-buffer-nocreate "dired-x")
e637bdf8 1483
cb3fe1f0
RS
1484(or (fboundp 'dired-old-find-buffer-nocreate)
1485 (fset 'dired-old-find-buffer-nocreate
1486 (symbol-function 'dired-find-buffer-nocreate)))
1487
efcb74f6
SM
1488;; REDEFINE.
1489;; Redefines dired.el's version of `dired-find-buffer-nocreate'
ac1ce341 1490(defun dired-find-buffer-nocreate (dirname &optional mode)
10774fb5
KH
1491 (if (and dired-find-subdir
1492 ;; don't try to find a wildcard as a subdirectory
1493 (string-equal dirname (file-name-directory dirname)))
cb3fe1f0 1494 (let* ((cur-buf (current-buffer))
10774fb5 1495 (buffers (nreverse
12c38283 1496 (dired-buffers-for-dir (expand-file-name dirname))))
10774fb5
KH
1497 (cur-buf-matches (and (memq cur-buf buffers)
1498 ;; wildcards must match, too:
1499 (equal dired-directory dirname))))
1500 ;; We don't want to switch to the same buffer---
1501 (setq buffers (delq cur-buf buffers));;need setq with delq
1502 (or (car (sort buffers (function dired-buffer-more-recently-used-p)))
1503 ;; ---unless it's the only possibility:
1504 (and cur-buf-matches cur-buf)))
ac1ce341 1505 (dired-old-find-buffer-nocreate dirname mode)))
cb3fe1f0
RS
1506
1507;; This should be a builtin
1508(defun dired-buffer-more-recently-used-p (buffer1 buffer2)
1509 "Return t if BUFFER1 is more recently used than BUFFER2."
1510 (if (equal buffer1 buffer2)
1511 nil
1512 (let ((more-recent nil)
1513 (list (buffer-list)))
1514 (while (and list
1515 (not (setq more-recent (equal buffer1 (car list))))
1516 (not (equal buffer2 (car list))))
1517 (setq list (cdr list)))
1518 more-recent)))
1519
efcb74f6
SM
1520;; Same thing as `dired-buffers-for-dir' of dired.el? - lrd 11/23/93
1521;; (defun dired-buffers-for-dir-exact (dir)
1522;; ;; Return a list of buffers that dired DIR (a directory or wildcard)
1523;; ;; at top level, or as subdirectory.
1524;; ;; Top level matches must match the wildcard part too, if any.
1525;; ;; The list is in reverse order of buffer creation, most recent last.
1526;; ;; As a side effect, killed dired buffers for DIR are removed from
1527;; ;; dired-buffers.
1528;; (let ((alist dired-buffers) result elt)
1529;; (while alist
1530;; (setq elt (car alist)
1531;; alist (cdr alist))
1532;; (let ((buf (cdr elt)))
1533;; (if (buffer-name buf)
1534;; ;; Top level must match exactly against dired-directory in
1535;; ;; case one of them is a wildcard.
1536;; (if (or (equal dir (with-current-buffer buf dired-directory))
1537;; (assoc dir (with-current-buffer buf dired-subdir-alist)))
1538;; (setq result (cons buf result)))
1539;; ;; else buffer is killed - clean up:
1540;; (setq dired-buffers (delq elt dired-buffers)))))
1541;; result))
1542
1543;; REDEFINE.
1544;; Redefines dired.el's version of `dired-initial-position'
cb3fe1f0 1545(defun dired-initial-position (dirname)
b847eb8c
DL
1546 "Where point should go in a new listing of DIRNAME.
1547Point assumed at beginning of new subdir line.
6fbad7af 1548You may redefine this function as you wish, e.g. like in `dired-x.el'."
cb3fe1f0
RS
1549 (end-of-line)
1550 (if dired-find-subdir (dired-goto-subdir dirname)) ; new
1551 (if dired-trivial-filenames (dired-goto-next-nontrivial-file)))
1552
1553\f
1554;; Does anyone use this? - lrd 6/29/93.
44c816da 1555;; Apparently people do use it. - lrd 12/22/97.
cb3fe1f0
RS
1556(defun dired-mark-sexp (predicate &optional unflag-p)
1557 "Mark files for which PREDICATE returns non-nil.
1558With a prefix arg, unflag those files instead.
1559
1560PREDICATE is a lisp expression that can refer to the following symbols:
1561
1562 inode [integer] the inode of the file (only for ls -i output)
1563 s [integer] the size of the file for ls -s output
34ff2275 1564 (usually in blocks or, with -k, in KByte)
cb3fe1f0
RS
1565 mode [string] file permission bits, e.g. \"-rw-r--r--\"
1566 nlink [integer] number of links to file
1567 uid [string] owner
1568 gid [string] group (If the gid is not displayed by ls,
1569 this will still be set (to the same as uid))
1570 size [integer] file size in bytes
1571 time [string] the time that ls displays, e.g. \"Feb 12 14:17\"
1572 name [string] the name of the file
1573 sym [string] if file is a symbolic link, the linked-to name, else \"\"
1574
1575For example, use
1576
1577 (equal 0 size)
1578
1579to mark all zero length files."
1580 ;; Using sym="" instead of nil avoids the trap of
1581 ;; (string-match "foo" sym) into which a user would soon fall.
1582 ;; Give `equal' instead of `=' in the example, as this works on
1583 ;; integers and strings.
1584 (interactive "xMark if (lisp expr): \nP")
1585 (message "%s" predicate)
1586 (let ((dired-marker-char (if unflag-p ?\040 dired-marker-char))
1587 inode s mode nlink uid gid size time name sym)
1588 (dired-mark-if
1589 (save-excursion
1590 (and
1591 ;; Sets vars
1592 ;; inode s mode nlink uid gid size time name sym
1593
1594 ;; according to current file line. Returns t for success, nil if
1595 ;; there is no file line. Upon success, all variables are set, either
1596 ;; to nil or the appropriate value, so they need not be initialized.
1597 ;; Moves point within the current line.
1598 (if (dired-move-to-filename)
1599 (let (pos
1600 (mode-len 10) ; length of mode string
1601 ;; like in dired.el, but with subexpressions \1=inode, \2=s:
1602 (dired-re-inode-size "\\s *\\([0-9]*\\)\\s *\\([0-9]*\\) ?"))
1603 (beginning-of-line)
1604 (forward-char 2)
1605 (if (looking-at dired-re-inode-size)
1606 (progn
1607 (goto-char (match-end 0))
027a4b6b
JB
1608 (setq inode (string-to-number (buffer-substring (match-beginning 1)
1609 (match-end 1)))
1610 s (string-to-number (buffer-substring (match-beginning 2)
1611 (match-end 2)))))
cb3fe1f0
RS
1612 (setq inode nil
1613 s nil))
1614 (setq mode (buffer-substring (point) (+ mode-len (point))))
1615 (forward-char mode-len)
1616 (setq nlink (read (current-buffer)))
44c816da 1617 ;; Karsten Wenger <kw@cis.uni-muenchen.de> fixed uid.
b847eb8c
DL
1618 (setq uid (buffer-substring (+ (point) 1)
1619 (progn (forward-word 1) (point))))
9bc260cf 1620 (re-search-forward directory-listing-before-filename-regexp)
cb3fe1f0
RS
1621 (goto-char (match-beginning 1))
1622 (forward-char -1)
027a4b6b
JB
1623 (setq size (string-to-number (buffer-substring (save-excursion
1624 (backward-word 1)
1625 (setq pos (point)))
1626 (point))))
cb3fe1f0
RS
1627 (goto-char pos)
1628 (backward-word 1)
1629 ;; if no gid is displayed, gid will be set to uid
1630 ;; but user will then not reference it anyway in PREDICATE.
b847eb8c
DL
1631 (setq gid (buffer-substring (save-excursion
1632 (forward-word 1) (point))
cb3fe1f0
RS
1633 (point))
1634 time (buffer-substring (match-beginning 1)
1635 (1- (dired-move-to-filename)))
1636 name (buffer-substring (point)
b847eb8c
DL
1637 (or
1638 (dired-move-to-end-of-filename t)
1639 (point)))
cb3fe1f0
RS
1640 sym (progn
1641 (if (looking-at " -> ")
b847eb8c
DL
1642 (buffer-substring
1643 (progn (forward-char 4) (point))
1644 (progn (end-of-line) (point)))
cb3fe1f0
RS
1645 "")))
1646 t)
1647 nil)
1648 (eval predicate)))
1649 (format "'%s file" predicate))))
1650
1651\f
b578f267 1652;;; FIND FILE AT POINT.
cb3fe1f0 1653
ccb1d39a 1654(defvar dired-x-hands-off-my-keys t
b847eb8c 1655 "*Non-nil means don't bind `dired-x-find-file' over `find-file' on keyboard.
ccb1d39a 1656Similarly for `dired-x-find-file-other-window' over `find-file-other-window'.
6fbad7af 1657If you change this variable after `dired-x.el' is loaded then do
ccb1d39a
RS
1658\\[dired-x-bind-find-file].")
1659
efcb74f6
SM
1660;; Bind `dired-x-find-file{-other-window}' over wherever
1661;; `find-file{-other-window}' is bound?
ccb1d39a
RS
1662(defun dired-x-bind-find-file ()
1663 "Bind `dired-x-find-file' in place of `find-file' \(or reverse\).
1664Similarly for `dired-x-find-file-other-window' and `find-file-other-window'.
1665Binding direction based on `dired-x-hands-off-my-keys'.
6fbad7af 1666This function is part of `after-init-hook'."
ccb1d39a 1667 (interactive)
32226619 1668 (if (called-interactively-p 'interactive)
ccb1d39a
RS
1669 (setq dired-x-hands-off-my-keys
1670 (not (y-or-n-p "Bind dired-x-find-file over find-file? "))))
1671 (cond ((not dired-x-hands-off-my-keys)
1672 (substitute-key-definition 'find-file
1673 'dired-x-find-file
1674 (current-global-map))
1675 (substitute-key-definition 'find-file-other-window
1676 'dired-x-find-file-other-window
1677 (current-global-map)))
1678 (t
1679 (substitute-key-definition 'dired-x-find-file
1680 'find-file
1681 (current-global-map))
1682 (substitute-key-definition 'dired-x-find-file-other-window
1683 'find-file-other-window
1684 (current-global-map))))
1685 ;; Clear mini-buffer.
1686 (message nil))
1687
efcb74f6
SM
1688;; Now call it so binding is correct and put on `after-init-hook' in case
1689;; user changes binding.
ccb1d39a
RS
1690(dired-x-bind-find-file)
1691(add-hook 'after-init-hook 'dired-x-bind-find-file)
1692
1693(defun dired-x-find-file (filename)
1694 "Edit file FILENAME.
1695May create a new window, or reuse an existing one.
1696See the function `display-buffer'.
1697
1698Identical to `find-file' except when called interactively, with a prefix arg
6fbad7af
JB
1699\(e.g., \\[universal-argument]\), in which case it guesses filename near point.
1700Useful for editing file mentioned in buffer you are viewing,
1701or to test if that file exists. Use minibuffer after snatching filename."
ccb1d39a
RS
1702 (interactive (list (read-filename-at-point "Find file: ")))
1703 (find-file (expand-file-name filename)))
1704
1705(defun dired-x-find-file-other-window (filename)
1706 "Edit file FILENAME, in another window.
1707May create a new window, or reuse an existing one.
1708See the function `display-buffer'.
1709
5a0c3f56
JB
1710Identical to `find-file-other-window' except when called interactively, with
1711a prefix arg \(e.g., \\[universal-argument]\), in which case it guesses filename near point.
6fbad7af
JB
1712Useful for editing file mentioned in buffer you are viewing,
1713or to test if that file exists. Use minibuffer after snatching filename."
ccb1d39a
RS
1714 (interactive (list (read-filename-at-point "Find file: ")))
1715 (find-file-other-window (expand-file-name filename)))
1716
1717;;; Internal functions.
cb3fe1f0 1718
1e56daa5 1719;; Fixme: This should probably use `thing-at-point'. -- fx
f53a06c3 1720(defun dired-filename-at-point ()
b847eb8c 1721 "Get the filename closest to point, but do not change position.
5a0c3f56
JB
1722Has a preference for looking backward when not directly on a symbol.
1723Not perfect - point must be in middle of or end of filename."
cb3fe1f0 1724
f53a06c3 1725 (let ((filename-chars "-.[:alnum:]_/:$+@")
6b622862 1726 start end filename prefix)
cb3fe1f0
RS
1727
1728 (save-excursion
1729 ;; First see if just past a filename.
1730 (if (not (eobp))
1731 (if (looking-at "[] \t\n[{}()]") ; whitespace or some parens
1732 (progn
1733 (skip-chars-backward " \n\t\r({[]})")
1734 (if (not (bobp))
1735 (backward-char 1)))))
9572a9dd 1736
cb3fe1f0
RS
1737 (if (string-match (concat "[" filename-chars "]")
1738 (char-to-string (following-char)))
1739 (progn
1e56daa5
DL
1740 (if (re-search-backward (concat "[^" filename-chars "]") nil t)
1741 (forward-char)
1742 (goto-char (point-min)))
cb3fe1f0 1743 (setq start (point))
6b622862 1744 (setq prefix
1e56daa5
DL
1745 (and (string-match
1746 "^\\w+@"
1747 (buffer-substring start (line-beginning-position)))
6b622862
GM
1748 "/"))
1749 (goto-char start)
cb3fe1f0
RS
1750 (if (string-match "[/~]" (char-to-string (preceding-char)))
1751 (setq start (1- start)))
1e56daa5 1752 (re-search-forward (concat "\\=[" filename-chars "]*") nil t))
cb3fe1f0
RS
1753
1754 (error "No file found around point!"))
1755
9572a9dd 1756 ;; Return string.
6b622862 1757 (expand-file-name (concat prefix (buffer-substring start (point)))))))
cb3fe1f0 1758
ccb1d39a 1759(defun read-filename-at-point (prompt)
b847eb8c
DL
1760 "Return filename prompting with PROMPT with completion.
1761If `current-prefix-arg' is non-nil, uses name at point as guess."
ccb1d39a
RS
1762 (if current-prefix-arg
1763 (let ((guess (dired-filename-at-point)))
1764 (read-file-name prompt
1765 (file-name-directory guess)
1766 guess
1767 nil (file-name-nondirectory guess)))
1768 (read-file-name prompt default-directory)))
cb3fe1f0 1769\f
b578f267 1770;;; BUG REPORTS
cb3fe1f0 1771
b847eb8c
DL
1772;; Fixme: get rid of this later.
1773
efcb74f6
SM
1774;; This section is provided for reports. It uses Barry A. Warsaw's
1775;; reporter.el which is bundled with GNU Emacs v19.
cb3fe1f0 1776
b847eb8c 1777(defconst dired-x-help-address "bug-gnu-emacs@gnu.org"
cb3fe1f0
RS
1778 "Address(es) accepting submission of reports on dired-x.el.")
1779
cb3fe1f0 1780(defconst dired-x-variable-list
9572a9dd 1781 (list
cb3fe1f0
RS
1782 'dired-bind-vm
1783 'dired-vm-read-only-folders
1784 'dired-bind-jump
1785 'dired-bind-info
1786 'dired-bind-man
1787 'dired-find-subdir
1788 'dired-enable-local-variables
1789 'dired-local-variables-file
1790 'dired-guess-shell-gnutar
1791 'dired-guess-shell-gzip-quiet
1792 'dired-guess-shell-znew-switches
1793 'dired-guess-shell-alist-user
1794 'dired-clean-up-buffers-too
ce64e046 1795 'dired-omit-mode
cb3fe1f0
RS
1796 'dired-omit-files
1797 'dired-omit-extensions
1798 )
b847eb8c 1799 "List of variables to be appended to reports sent by `dired-x-submit-report'.")
cb3fe1f0
RS
1800
1801(defun dired-x-submit-report ()
6fbad7af 1802 "Submit via `reporter.el' a bug report on program.
5a0c3f56 1803Send report on `dired-x-file' version `dired-x-version', to
b847eb8c
DL
1804`dired-x-maintainer' at address `dired-x-help-address' listing
1805variables `dired-x-variable-list' in the message."
cb3fe1f0
RS
1806 (interactive)
1807
b847eb8c
DL
1808 (reporter-submit-bug-report
1809 dired-x-help-address ; address
1810 "dired-x" ; pkgname
1811 dired-x-variable-list ; varlist
1812 nil nil ; pre-/post-hooks
1813 ""))
cb3fe1f0
RS
1814
1815\f
1816;; As Barry Warsaw would say: "This might be useful..."
1817(provide 'dired-x)
1818
276f1d00
GM
1819;; Local Variables:
1820;; byte-compile-dynamic: t
1821;; generated-autoload-file: "dired.el"
1822;; End:
1823
2d29381c 1824;; arch-tag: 71a43ba2-7a00-4793-a028-0613dd7765ae
cb3fe1f0 1825;;; dired-x.el ends here