-
Notifications
You must be signed in to change notification settings - Fork 1
/
dired-x.el
1795 lines (1542 loc) · 66.4 KB
/
dired-x.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;;; dired-x.el --- extra Dired functionality -*-byte-compile-dynamic: t;-*-
;; Copyright (C) 1993, 1994, 1997, 2001, 2002, 2003, 2004, 2005, 2006,
;; 2007, 2008, 2009 Free Software Foundation, Inc.
;; Author: Sebastian Kremer <[email protected]>
;; Lawrence R. Dodd <[email protected]>
;; Maintainer: Romain Francoise <[email protected]>
;; Keywords: dired extensions files
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; This is Sebastian Kremer's excellent dired-x.el (Dired Extra), version
;; 1.191, hacked up for GNU Emacs. Redundant or conflicting material has
;; been removed or renamed in order to work properly with dired of GNU
;; Emacs. All suggestions or comments are most welcomed.
;;
;; Please, PLEASE, *PLEASE* see the info pages.
;;
;; BUGS: Type M-x dired-x-submit-report and a report will be generated.
;; INSTALLATION: In your ~/.emacs,
;;
;; (add-hook 'dired-load-hook
;; (function (lambda ()
;; (load "dired-x")
;; ;; Set global variables here. For example:
;; ;; (setq dired-guess-shell-gnutar "gtar")
;; )))
;; (add-hook 'dired-mode-hook
;; (function (lambda ()
;; ;; Set buffer-local variables here. For example:
;; ;; (dired-omit-mode 1)
;; )))
;;
;; At load time dired-x.el will install itself, redefine some functions, and
;; bind some dired keys. *Please* see the info pages for more details.
;; *Please* see the info pages for more details.
;; User defined variables:
;;
;; dired-bind-vm
;; dired-vm-read-only-folders
;; dired-bind-jump
;; dired-bind-info
;; dired-bind-man
;; dired-x-hands-off-my-keys
;; dired-find-subdir
;; dired-enable-local-variables
;; dired-local-variables-file
;; dired-guess-shell-gnutar
;; dired-guess-shell-gzip-quiet
;; dired-guess-shell-znew-switches
;; dired-guess-shell-alist-user
;; dired-clean-up-buffers-too
;; dired-omit-mode
;; dired-omit-files
;; dired-omit-extensions
;; dired-omit-size-limit
;;
;; To find out more about these variables, load this file, put your cursor at
;; the end of any of the variable names, and hit C-h v [RET]. *Please* see
;; the info pages for more details.
;; When loaded this code redefines the following functions of GNU Emacs
;;
;; Function Found in this file of GNU Emacs
;; -------- -------------------------------
;; dired-clean-up-after-deletion ../lisp/dired.el
;; dired-find-buffer-nocreate ../lisp/dired.el
;; dired-initial-position ../lisp/dired.el
;;
;; dired-add-entry ../lisp/dired-aux.el
;; dired-read-shell-command ../lisp/dired-aux.el
;;; Code:
;; LOAD.
;; This is a no-op if dired-x is being loaded via `dired-load-hook'. It is
;; here in case the user has autoloaded dired-x via the dired-jump key binding
;; (instead of autoloading to dired as is suggested in the info-pages).
(require 'dired)
;; We will redefine some functions and also need some macros so we need to
;; load dired stuff of GNU Emacs.
(require 'dired-aux)
(defvar vm-folder-directory)
(eval-when-compile (require 'man))
;;; User-defined variables.
(defgroup dired-x nil
"Extended directory editing (dired-x)."
:group 'dired)
(defgroup dired-keys nil
"Dired keys customizations."
:prefix "dired-"
:group 'dired-x)
(defcustom dired-bind-vm nil
"Non-nil means \"V\" runs `dired-vm', otherwise \"V\" runs `dired-rmail'.
RMAIL files in the old Babyl format (used before before Emacs 23.1)
contain \"-*- rmail -*-\" at the top, so `dired-find-file'
will run `rmail' on these files. New RMAIL files use the standard
mbox format, and so cannot be distinguished in this way."
:type 'boolean
:group 'dired-keys)
(defcustom dired-bind-jump t
"Non-nil means bind `dired-jump' to C-x C-j, otherwise do not."
:type 'boolean
:group 'dired-keys)
(defcustom dired-bind-man t
"Non-nil means bind `dired-man' to \"N\" in dired-mode, otherwise do not."
:type 'boolean
:group 'dired-keys)
(defcustom dired-bind-info t
"Non-nil means bind `dired-info' to \"I\" in dired-mode, otherwise do not."
:type 'boolean
:group 'dired-keys)
(defcustom dired-vm-read-only-folders nil
"If non-nil, \\[dired-vm] will visit all folders read-only.
If neither nil nor t, e.g. the symbol `if-file-read-only', only
files not writable by you are visited read-only.
Read-only folders only work in VM 5, not in VM 4."
:type '(choice (const :tag "off" nil)
(const :tag "on" t)
(other :tag "non-writable only" if-file-read-only))
:group 'dired-x)
(define-minor-mode dired-omit-mode
"Toggle Dired-Omit mode.
With numeric ARG, enable Dired-Omit mode if ARG is positive, disable
otherwise. Enabling and disabling is buffer-local.
If enabled, \"uninteresting\" files are not listed.
Uninteresting files are those whose filenames match regexp `dired-omit-files',
plus those ending with extensions in `dired-omit-extensions'."
:group 'dired-x
(if dired-omit-mode
;; This will mention how many lines were omitted:
(let ((dired-omit-size-limit nil)) (dired-omit-expunge))
(revert-buffer)))
;; For backward compatibility
(define-obsolete-variable-alias 'dired-omit-files-p 'dired-omit-mode "22.1")
(defcustom dired-omit-files "^\\.?#\\|^\\.$\\|^\\.\\.$"
"Filenames matching this regexp will not be displayed.
This only has effect when `dired-omit-mode' is t. See interactive function
`dired-omit-mode' \(\\[dired-omit-mode]\) and variable
`dired-omit-extensions'. The default is to omit `.', `..', auto-save
files and lock files."
:type 'regexp
:group 'dired-x)
(defcustom dired-find-subdir nil ; t is pretty near to DWIM...
"If non-nil, Dired always finds a directory in a buffer of its own.
If nil, Dired finds the directory as a subdirectory in some other buffer
if it is present as one.
If there are several dired buffers for a directory, the most recently
used is chosen.
Dired avoids switching to the current buffer, so that if you have
a normal and a wildcard buffer for the same directory, \\[dired] will
toggle between those two."
:type 'boolean
:group 'dired-x)
(defcustom dired-omit-size-limit 30000
"Maximum size for the \"omitting\" feature.
If nil, there is no maximum size."
:type '(choice (const :tag "no maximum" nil) integer)
:group 'dired-x)
(defcustom dired-enable-local-variables t
"Control use of local-variables lists in Dired.
The value can be t, nil or something else.
A value of t means local-variables lists are obeyed;
nil means they are ignored; anything else means query.
This temporarily overrides the value of `enable-local-variables' when listing
a directory. See also `dired-local-variables-file'."
:type 'boolean
:group 'dired-x)
(defcustom dired-guess-shell-gnutar (when (or (eq system-type 'gnu)
(eq system-type 'gnu/linux))
"tar")
"If non-nil, name of GNU tar executable.
\(E.g., \"tar\" or \"gtar\"). The `z' switch will be used with it for
compressed or gzip'ed tar files. If you don't have GNU tar, set this
to nil: a pipe using `zcat' or `gunzip -c' will be used."
:type '(choice (const :tag "Not GNU tar" nil)
(string :tag "Command name"))
:group 'dired-x)
(defcustom dired-guess-shell-gzip-quiet t
"Non-nil says pass -q to gzip overriding verbose GZIP environment."
:type 'boolean
:group 'dired-x)
(defcustom dired-guess-shell-znew-switches nil
"If non-nil, then string of switches passed to `znew', example: \"-K\"."
:type '(choice (const :tag "None" nil)
(string :tag "Switches"))
:group 'dired-x)
(defcustom dired-clean-up-buffers-too t
"Non-nil means offer to kill buffers visiting files and dirs deleted in Dired."
:type 'boolean
:group 'dired-x)
;;; KEY BINDINGS.
(define-key dired-mode-map "\M-o" 'dired-omit-mode)
(define-key dired-mode-map "*O" 'dired-mark-omitted)
(define-key dired-mode-map "\M-(" 'dired-mark-sexp)
(define-key dired-mode-map "*(" 'dired-mark-sexp)
(define-key dired-mode-map "*." 'dired-mark-extension)
(define-key dired-mode-map "\M-!" 'dired-smart-shell-command)
(define-key dired-mode-map "w" 'dired-copy-filename-as-kill)
(define-key dired-mode-map "\M-G" 'dired-goto-subdir)
(define-key dired-mode-map "F" 'dired-do-find-marked-files)
(define-key dired-mode-map "Y" 'dired-do-relsymlink)
(define-key dired-mode-map "%Y" 'dired-do-relsymlink-regexp)
(define-key dired-mode-map "V" 'dired-do-run-mail)
(if dired-bind-man
(define-key dired-mode-map "N" 'dired-man))
(if dired-bind-info
(define-key dired-mode-map "I" 'dired-info))
;;; MENU BINDINGS
(let ((menu-bar (lookup-key dired-mode-map [menu-bar])))
(let ((menu (lookup-key menu-bar [operate])))
(define-key-after
menu
[find-files]
'(menu-item
"Find files"
dired-do-find-marked-files
:help "Find current or marked files")
'delete)
(define-key-after
menu
[relsymlink]
'(menu-item
"Relative symlink to..."
dired-do-relsymlink
:visible (fboundp 'make-symbolic-link)
:help "Make relative symbolic links for current or marked files")
'symlink))
(let ((menu (lookup-key menu-bar [mark])))
(define-key-after
menu
[flag-extension]
'(menu-item
"Flag extension..."
dired-flag-extension
:help "Flag files with a certain extension for deletion")
'garbage-files)
(define-key-after
menu
[mark-extension]
'(menu-item
"Mark extension..."
dired-mark-extension
:help "Mark files with a certain extension")
'symlinks)
(define-key-after
menu
[mark-omitted]
'(menu-item
"Mark omitted"
dired-mark-omitted
:help "Mark files matching `dired-omit-files' and `dired-omit-extensions'")
'mark-extension))
(let ((menu (lookup-key menu-bar [regexp])))
(define-key-after
menu
[relsymlink-regexp]
'(menu-item
"Relative symlink..."
dired-do-relsymlink-regexp
:visible (fboundp 'make-symbolic-link)
:help "Make relative symbolic links for files matching regexp")
'symlink))
(let ((menu (lookup-key menu-bar [immediate])))
(define-key-after
menu
[omit-mode]
'(menu-item
"Omit mode" dired-omit-mode
:button (:toggle . dired-omit-mode)
:help "Enable or disable omitting \"uninteresting\" files")
'dashes)))
;;; GLOBAL BINDING.
(if dired-bind-jump
(progn
(define-key global-map "\C-x\C-j" 'dired-jump)
(define-key global-map "\C-x4\C-j" 'dired-jump-other-window)))
;; Install into appropriate hooks.
(add-hook 'dired-mode-hook 'dired-extra-startup)
(add-hook 'dired-after-readin-hook 'dired-omit-expunge)
(defun dired-extra-startup ()
"Automatically put on `dired-mode-hook' to get extra Dired features:
\\<dired-mode-map>
\\[dired-do-run-mail]\t-- run mail on folder (see `dired-bind-vm')
\\[dired-info]\t-- run info on file
\\[dired-man]\t-- run man on file
\\[dired-do-find-marked-files]\t-- visit all marked files simultaneously
\\[dired-omit-mode]\t-- toggle omitting of files
\\[dired-mark-sexp]\t-- mark by Lisp expression
\\[dired-copy-filename-as-kill]\t-- copy the file or subdir names into the kill ring;
\t you can feed it to other commands using \\[yank]
For more features, see variables
`dired-bind-vm'
`dired-bind-jump'
`dired-bind-info'
`dired-bind-man'
`dired-vm-read-only-folders'
`dired-omit-mode'
`dired-omit-files'
`dired-omit-extensions'
`dired-omit-size-limit'
`dired-find-subdir'
`dired-enable-local-variables'
`dired-local-variables-file'
`dired-guess-shell-gnutar'
`dired-guess-shell-gzip-quiet'
`dired-guess-shell-znew-switches'
`dired-guess-shell-alist-user'
`dired-clean-up-buffers-too'
See also functions
`dired-flag-extension'
`dired-virtual'
`dired-jump'
`dired-man'
`dired-vm'
`dired-rmail'
`dired-info'
`dired-do-find-marked-files'"
(interactive)
;; These must be done in each new dired buffer.
(dired-hack-local-variables)
(dired-omit-startup))
;;; BUFFER CLEANING.
;; REDEFINE.
(defun dired-clean-up-after-deletion (fn)
"Clean up after a deleted file or directory FN.
Remove expanded subdir of deleted dir, if any."
(save-excursion (and (cdr dired-subdir-alist)
(dired-goto-subdir fn)
(dired-kill-subdir)))
;; Offer to kill buffer of deleted file FN.
(if dired-clean-up-buffers-too
(progn
(let ((buf (get-file-buffer fn)))
(and buf
(funcall (function y-or-n-p)
(format "Kill buffer of %s, too? "
(file-name-nondirectory fn)))
(save-excursion ; you never know where kill-buffer leaves you
(kill-buffer buf))))
(let ((buf-list (dired-buffers-for-dir (expand-file-name fn)))
(buf nil))
(and buf-list
(y-or-n-p (format "Kill dired buffer%s of %s, too? "
(dired-plural-s (length buf-list))
(file-name-nondirectory fn)))
(while buf-list
(save-excursion (kill-buffer (car buf-list)))
(setq buf-list (cdr buf-list)))))))
;; Anything else?
)
;;; EXTENSION MARKING FUNCTIONS.
;; Mark files with some extension.
(defun dired-mark-extension (extension &optional marker-char)
"Mark all files with a certain EXTENSION for use in later commands.
A `.' is *not* automatically prepended to the string entered."
;; EXTENSION may also be a list of extensions instead of a single one.
;; Optional MARKER-CHAR is marker to use.
(interactive "sMarking extension: \nP")
(or (listp extension)
(setq extension (list extension)))
(dired-mark-files-regexp
(concat ".";; don't match names with nothing but an extension
"\\("
(mapconcat 'regexp-quote extension "\\|")
"\\)$")
marker-char))
(defun dired-flag-extension (extension)
"In dired, flag all files with a certain EXTENSION for deletion.
A `.' is *not* automatically prepended to the string entered."
(interactive "sFlagging extension: ")
(dired-mark-extension extension dired-del-marker))
;; Define some unpopular file extensions. Used for cleaning and omitting.
(defvar dired-patch-unclean-extensions
'(".rej" ".orig")
"List of extensions of dispensable files created by the `patch' program.")
(defvar dired-tex-unclean-extensions
'(".toc" ".log" ".aux");; these are already in completion-ignored-extensions
"List of extensions of dispensable files created by TeX.")
(defvar dired-latex-unclean-extensions
'(".idx" ".lof" ".lot" ".glo")
"List of extensions of dispensable files created by LaTeX.")
(defvar dired-bibtex-unclean-extensions
'(".blg" ".bbl")
"List of extensions of dispensable files created by BibTeX.")
(defvar dired-texinfo-unclean-extensions
'(".cp" ".cps" ".fn" ".fns" ".ky" ".kys" ".pg" ".pgs"
".tp" ".tps" ".vr" ".vrs")
"List of extensions of dispensable files created by texinfo.")
(defun dired-clean-patch ()
"Flag dispensable files created by patch for deletion.
See variable `dired-patch-unclean-extensions'."
(interactive)
(dired-flag-extension dired-patch-unclean-extensions))
(defun dired-clean-tex ()
"Flag dispensable files created by [La]TeX etc. for deletion.
See variables `dired-tex-unclean-extensions',
`dired-latex-unclean-extensions', `dired-bibtex-unclean-extensions' and
`dired-texinfo-unclean-extensions'."
(interactive)
(dired-flag-extension (append dired-texinfo-unclean-extensions
dired-latex-unclean-extensions
dired-bibtex-unclean-extensions
dired-tex-unclean-extensions)))
(defun dired-very-clean-tex ()
"Flag dispensable files created by [La]TeX *and* \".dvi\" for deletion.
See variables `dired-texinfo-unclean-extensions',
`dired-latex-unclean-extensions', `dired-bibtex-unclean-extensions' and
`dired-texinfo-unclean-extensions'."
(interactive)
(dired-flag-extension (append dired-texinfo-unclean-extensions
dired-latex-unclean-extensions
dired-bibtex-unclean-extensions
dired-tex-unclean-extensions
(list ".dvi"))))
;;; JUMP.
;;;###autoload
(defun dired-jump (&optional other-window)
"Jump to dired buffer corresponding to current buffer.
If in a file, dired the current directory and move to file's line.
If in Dired already, pop up a level and goto old directory's line.
In case the proper dired file line cannot be found, refresh the dired
buffer and try again."
(interactive "P")
(let* ((file buffer-file-name)
(dir (if file (file-name-directory file) default-directory)))
(if (eq major-mode 'dired-mode)
(progn
(setq dir (dired-current-directory))
(dired-up-directory other-window)
(or (dired-goto-file dir)
;; refresh and try again
(progn
(dired-insert-subdir (file-name-directory dir))
(dired-goto-file dir))))
(if other-window
(dired-other-window dir)
(dired dir))
(if file
(or (dired-goto-file file)
;; refresh and try again
(progn
(dired-insert-subdir (file-name-directory file))
(dired-goto-file file))
;; Toggle omitting, if it is on, and try again.
(if dired-omit-mode
(progn
(dired-omit-mode)
(dired-goto-file file))))))))
(defun dired-jump-other-window ()
"Like \\[dired-jump] (`dired-jump') but in other window."
(interactive)
(dired-jump t))
;;; OMITTING.
;; Enhanced omitting of lines from directory listings.
;; Marked files are never omitted.
;; should probably get rid of this and always use 'no-dir.
;; sk 28-Aug-1991 09:37
(defvar dired-omit-localp 'no-dir
"The LOCALP argument `dired-omit-expunge' passes to `dired-get-filename'.
If it is `no-dir', omitting is much faster, but you can only match
against the non-directory part of the file name. Set it to nil if you
need to match the entire file name.")
;; \017=^O for Omit - other packages can chose other control characters.
(defvar dired-omit-marker-char ?\017
"Temporary marker used by dired-omit.
Should never be used as marker by the user or other packages.")
(defun dired-omit-startup ()
(or (assq 'dired-omit-mode minor-mode-alist)
(setq minor-mode-alist
(append '((dired-omit-mode
(:eval (if (eq major-mode 'dired-mode)
" Omit" ""))))
minor-mode-alist))))
(defun dired-mark-omitted ()
"Mark files matching `dired-omit-files' and `dired-omit-extensions'."
(interactive)
(let ((dired-omit-mode nil)) (revert-buffer)) ;; Show omitted files
(dired-mark-unmarked-files (dired-omit-regexp) nil nil dired-omit-localp))
(defvar dired-omit-extensions
(append completion-ignored-extensions
dired-latex-unclean-extensions
dired-bibtex-unclean-extensions
dired-texinfo-unclean-extensions)
"If non-nil, a list of extensions \(strings\) to omit from Dired listings.
Defaults to elements of `completion-ignored-extensions',
`dired-latex-unclean-extensions', `dired-bibtex-unclean-extensions', and
`dired-texinfo-unclean-extensions'.
See interactive function `dired-omit-mode' \(\\[dired-omit-mode]\) and
variables `dired-omit-mode' and `dired-omit-files'.")
(defun dired-omit-expunge (&optional regexp)
"Erases all unmarked files matching REGEXP.
Does nothing if global variable `dired-omit-mode' is nil, or if called
non-interactively and buffer is bigger than `dired-omit-size-limit'.
If REGEXP is nil or not specified, uses `dired-omit-files', and also omits
filenames ending in `dired-omit-extensions'.
If REGEXP is the empty string, this function is a no-op.
This functions works by temporarily binding `dired-marker-char' to
`dired-omit-marker-char' and calling `dired-do-kill-lines'."
(interactive "sOmit files (regexp): ")
(if (and dired-omit-mode
(or (interactive-p)
(not dired-omit-size-limit)
(< (buffer-size) dired-omit-size-limit)
(progn
(message "Not omitting: directory larger than %d characters."
dired-omit-size-limit)
(setq dired-omit-mode nil)
nil)))
(let ((omit-re (or regexp (dired-omit-regexp)))
(old-modified-p (buffer-modified-p))
count)
(or (string= omit-re "")
(let ((dired-marker-char dired-omit-marker-char))
(message "Omitting...")
(if (dired-mark-unmarked-files omit-re nil nil dired-omit-localp)
(progn
(setq count (dired-do-kill-lines nil "Omitted %d line%s."))
(force-mode-line-update))
(message "(Nothing to omit)"))))
;; Try to preserve modified state of buffer. So `%*' doesn't appear
;; in mode-line of omitted buffers.
(set-buffer-modified-p (and old-modified-p
(save-excursion
(goto-char (point-min))
(re-search-forward dired-re-mark nil t))))
count)))
(defun dired-omit-regexp ()
(concat (if dired-omit-files (concat "\\(" dired-omit-files "\\)") "")
(if (and dired-omit-files dired-omit-extensions) "\\|" "")
(if dired-omit-extensions
(concat ".";; a non-extension part should exist
"\\("
(mapconcat 'regexp-quote dired-omit-extensions "\\|")
"\\)$")
"")))
;; Returns t if any work was done, nil otherwise.
(defun dired-mark-unmarked-files (regexp msg &optional unflag-p localp)
"Mark unmarked files matching REGEXP, displaying MSG.
REGEXP is matched against the entire file name.
Does not re-mark files which already have a mark.
With prefix argument, unflag all those files.
Optional fourth argument LOCALP is as in `dired-get-filename'."
(interactive "P")
(let ((dired-marker-char (if unflag-p ?\s dired-marker-char)))
(dired-mark-if
(and
;; not already marked
(looking-at " ")
;; uninteresting
(let ((fn (dired-get-filename localp t)))
(and fn (string-match regexp fn))))
msg)))
;; Compiler does not get fset.
(declare-function dired-omit-old-add-entry "dired-x")
;; REDEFINE.
;; Redefine dired-aux.el's version of `dired-add-entry'
;; Save old defun if not already done:
(or (fboundp 'dired-omit-old-add-entry)
(fset 'dired-omit-old-add-entry (symbol-function 'dired-add-entry)))
;; REDEFINE.
(defun dired-omit-new-add-entry (filename &optional marker-char relative)
;; This redefines dired-aux.el's dired-add-entry to avoid calling ls for
;; files that are going to be omitted anyway.
(if dired-omit-mode
;; perhaps return t without calling ls
(let ((omit-re (dired-omit-regexp)))
(if (or (string= omit-re "")
(not
(string-match omit-re
(cond
((eq 'no-dir dired-omit-localp)
filename)
((eq t dired-omit-localp)
(dired-make-relative filename))
(t
(dired-make-absolute
filename
(file-name-directory filename)))))))
;; if it didn't match, go ahead and add the entry
(dired-omit-old-add-entry filename marker-char relative)
;; dired-add-entry returns t for success, perhaps we should
;; return file-exists-p
t))
;; omitting is not turned on at all
(dired-omit-old-add-entry filename marker-char relative)))
;; Redefine it.
(fset 'dired-add-entry 'dired-omit-new-add-entry)
;;; VIRTUAL DIRED MODE.
;; For browsing `ls -lR' listings in a dired-like fashion.
(defalias 'virtual-dired 'dired-virtual)
(defun dired-virtual (dirname &optional switches)
"Put this buffer into Virtual Dired mode.
In Virtual Dired mode, all commands that do not actually consult the
filesystem will work.
This is useful if you want to peruse and move around in an ls -lR
output file, for example one you got from an ftp server. With
ange-ftp, you can even dired a directory containing an ls-lR file,
visit that file and turn on virtual dired mode. But don't try to save
this file, as dired-virtual indents the listing and thus changes the
buffer.
If you have save a Dired buffer in a file you can use \\[dired-virtual] to
resume it in a later session.
Type \\<dired-mode-map>\\[revert-buffer] \
in the Virtual Dired buffer and answer `y' to convert
the virtual to a real dired buffer again. You don't have to do this, though:
you can relist single subdirs using \\[dired-do-redisplay]."
;; DIRNAME is the top level directory of the buffer. It will become
;; its `default-directory'. If nil, the old value of
;; default-directory is used.
;; Optional SWITCHES are the ls switches to use.
;; Shell wildcards will be used if there already is a `wildcard'
;; line in the buffer (thus it is a saved Dired buffer), but there
;; is no other way to get wildcards. Insert a `wildcard' line by
;; hand if you want them.
(interactive
(list (read-string "Virtual Dired directory: " (dired-virtual-guess-dir))))
(goto-char (point-min))
(or (looking-at " ")
;; if not already indented, do it now:
(indent-region (point-min) (point-max) 2))
(or dirname (setq dirname default-directory))
(setq dirname (expand-file-name (file-name-as-directory dirname)))
(setq default-directory dirname) ; contains no wildcards
(let ((wildcard (save-excursion
(goto-char (point-min))
(forward-line 1)
(and (looking-at "^ wildcard ")
(buffer-substring (match-end 0)
(progn (end-of-line) (point)))))))
(if wildcard
(setq dirname (expand-file-name wildcard default-directory))))
;; If raw ls listing (not a saved old dired buffer), give it a
;; decent subdir headerline:
(goto-char (point-min))
(or (looking-at dired-subdir-regexp)
(insert " "
(directory-file-name (file-name-directory default-directory))
":\n"))
(dired-mode dirname (or switches dired-listing-switches))
(setq mode-name "Virtual Dired"
revert-buffer-function 'dired-virtual-revert)
(set (make-local-variable 'dired-subdir-alist) nil)
(dired-build-subdir-alist)
(goto-char (point-min))
(dired-initial-position dirname))
(defun dired-virtual-guess-dir ()
"Guess and return appropriate working directory of this buffer.
The buffer is assumed to be in Dired or ls -lR format. The guess is
based upon buffer contents. If nothing could be guessed, returns
nil."
(let ((regexp "^\\( \\)?\\([^ \n\r]*\\)\\(:\\)[\n\r]")
(subexpr 2))
(goto-char (point-min))
(cond ((looking-at regexp)
;; If a saved dired buffer, look to which dir and
;; perhaps wildcard it belongs:
(let ((dir (buffer-substring (match-beginning subexpr)
(match-end subexpr))))
(file-name-as-directory dir)))
;; Else no match for headerline found. It's a raw ls listing.
;; In raw ls listings the directory does not have a headerline
;; try parent of first subdir, if any
((re-search-forward regexp nil t)
(file-name-directory
(directory-file-name
(file-name-as-directory
(buffer-substring (match-beginning subexpr)
(match-end subexpr))))))
(t ; if all else fails
nil))))
(defun dired-virtual-revert (&optional arg noconfirm)
(if (not
(y-or-n-p "Cannot revert a Virtual Dired buffer - switch to Real Dired mode? "))
(error "Cannot revert a Virtual Dired buffer")
(setq mode-name "Dired"
revert-buffer-function 'dired-revert)
(revert-buffer)))
;; A zero-arg version of dired-virtual.
(defun dired-virtual-mode ()
"Put current buffer into Virtual Dired mode (see `dired-virtual').
Useful on `magic-mode-alist' with the regexp
\"^ \\\\(/[^ /]+\\\\)+/?:$\"
to put saved dired buffers automatically into Virtual Dired mode.
Also useful for `auto-mode-alist' like this:
(add-to-list 'auto-mode-alist
'(\"[^/]\\\\.dired\\\\'\" . dired-virtual-mode))"
(interactive)
(dired-virtual (dired-virtual-guess-dir)))
;;; SMART SHELL.
;; An Emacs buffer can have but one working directory, stored in the
;; buffer-local variable `default-directory'. A Dired buffer may have
;; several subdirectories inserted, but still has but one working directory:
;; that of the top level Dired directory in that buffer. For some commands
;; it is appropriate that they use the current Dired directory instead of
;; `default-directory', e.g., `find-file' and `compile'. This is a general
;; mechanism is provided for special handling of the working directory in
;; special major modes.
;; It's easier to add to this alist than redefine function
;; default-directory while keeping the old information.
(defconst default-directory-alist
'((dired-mode . (if (fboundp 'dired-current-directory)
(dired-current-directory)
default-directory)))
"Alist of major modes and their opinion on `default-directory'.
This is given as a Lisp expression to evaluate. A resulting value of
nil is ignored in favor of `default-directory'.")
(defun dired-default-directory ()
"Usage like variable `default-directory'.
Knows about the special cases in variable `default-directory-alist'."
(or (eval (cdr (assq major-mode default-directory-alist)))
default-directory))
(defun dired-smart-shell-command (command &optional output-buffer error-buffer)
"Like function `shell-command', but in the current Virtual Dired directory."
(interactive
(list
(read-shell-command "Shell command: " nil nil
(cond
(buffer-file-name (file-relative-name buffer-file-name))
((eq major-mode 'dired-mode) (dired-get-filename t t))))
current-prefix-arg
shell-command-default-error-buffer))
(let ((default-directory (dired-default-directory)))
(shell-command command output-buffer error-buffer)))
;;; LOCAL VARIABLES FOR DIRED BUFFERS.
;; Brief Description:
;;;
;; * `dired-extra-startup' is part of the `dired-mode-hook'.
;;;
;; * `dired-extra-startup' calls `dired-hack-local-variables'
;;;
;; * `dired-hack-local-variables' checks the value of
;;; `dired-local-variables-file'
;;;
;; * Check if `dired-local-variables-file' is a non-nil string and is a
;;; filename found in the directory of the Dired Buffer being created.
;;;
;; * If `dired-local-variables-file' satisfies the above, then temporarily
;;; include it in the Dired Buffer at the bottom.
;;;
;; * Set `enable-local-variables' temporarily to the user variable
;;; `dired-enable-local-variables' and run `hack-local-variables' on the
;;; Dired Buffer.
(defvar dired-local-variables-file (convert-standard-filename ".dired")
"Filename, as string, containing local dired buffer variables to be hacked.
If this file found in current directory, then it will be inserted into dired
buffer and `hack-local-variables' will be run. See Info node
`(emacs)File Variables' for more information on local variables.
See also `dired-enable-local-variables'.")
(defun dired-hack-local-variables ()
"Evaluate local variables in `dired-local-variables-file' for dired buffer."
(if (and dired-local-variables-file
(stringp dired-local-variables-file)
(file-exists-p dired-local-variables-file))
(let ((opoint (point-max))
buffer-read-only
;; In case user has `enable-local-variables' set to nil we
;; override it locally with dired's variable.
(enable-local-variables dired-enable-local-variables))
;; Insert 'em.
(save-excursion
(goto-char opoint)
(insert "\^L\n")
(insert-file-contents dired-local-variables-file))
;; Hack 'em.
(let ((buffer-file-name dired-local-variables-file))
(hack-local-variables))
;; Make sure that the modeline shows the proper information.
(dired-sort-set-modeline)
;; Delete this stuff: `eobp' is used to find last subdir by dired.el.
(delete-region opoint (point-max)))))
(defun dired-omit-here-always ()
"Create `dired-local-variables-file' for omitting and reverts directory.
Sets `dired-omit-mode' to t in a local variables file that is readable by
dired."
(interactive)
(if (file-exists-p dired-local-variables-file)
(message "File `./%s' already exists." dired-local-variables-file)
;; Create `dired-local-variables-file'.
(with-current-buffer (get-buffer-create " *dot-dired*")
(erase-buffer)
(insert "Local Variables:\ndired-omit-mode: t\nEnd:\n")
(write-file dired-local-variables-file)
(kill-buffer (current-buffer)))
;; Run extra-hooks and revert directory.
(dired-extra-startup)
(dired-revert)))
;;; GUESS SHELL COMMAND.
;; Brief Description:
;;;
;; `dired-do-shell-command' is bound to `!' by dired.el.
;;;
;; * Redefine `dired-read-shell-command' so it calls
;;; `dired-guess-shell-command'.
;;;
;; * `dired-guess-shell-command' calls `dired-guess-default' with list of
;;; marked files.
;;;
;; * Parse `dired-guess-shell-alist-user' and
;;; `dired-guess-shell-alist-default' (in that order) for the first REGEXP
;;; that matches the first file in the file list.
;;;
;; * If the REGEXP matches all the entries of the file list then evaluate
;;; COMMAND, which is either a string or a Lisp expression returning a
;;; string. COMMAND may be a list of commands.
;;;
;; * Return this command to `dired-guess-shell-command' which prompts user
;;; with it. The list of commands is put into the list of default values.
;;; If a command is used successfully then it is stored permanently in
;;; `dired-shell-command-history'.
;; Guess what shell command to apply to a file.
(defvar dired-shell-command-history nil
"History list for commands that read dired-shell commands.")
;; Default list of shell commands.
;; NOTE: Use `gunzip -c' instead of `zcat' on `.gz' files. Some do not
;; install GNU zip's version of zcat.
(defvar dired-guess-shell-alist-default
(list
(list "\\.tar$"
'(if dired-guess-shell-gnutar
(concat dired-guess-shell-gnutar " xvf")
"tar xvf")
;; Extract files into a separate subdirectory
'(if dired-guess-shell-gnutar
(concat "mkdir " (file-name-sans-extension file)
"; " dired-guess-shell-gnutar " -C "
(file-name-sans-extension file) " -xvf")
(concat "mkdir " (file-name-sans-extension file)
"; tar -C " (file-name-sans-extension file) " -xvf"))
;; List archive contents.
'(if dired-guess-shell-gnutar
(concat dired-guess-shell-gnutar " tvf")
"tar tvf"))
;; REGEXPS for compressed archives must come before the .Z rule to
;; be recognized:
(list "\\.tar\\.Z$"
;; Untar it.
'(if dired-guess-shell-gnutar
(concat dired-guess-shell-gnutar " zxvf")
(concat "zcat * | tar xvf -"))
;; Optional conversion to gzip format.
'(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
" " dired-guess-shell-znew-switches))
;; gzip'ed archives
(list "\\.t\\(ar\\.\\)?gz$"
'(if dired-guess-shell-gnutar
(concat dired-guess-shell-gnutar " zxvf")
(concat "gunzip -qc * | tar xvf -"))
;; Extract files into a separate subdirectory
'(if dired-guess-shell-gnutar
(concat "mkdir " (file-name-sans-extension file)
"; " dired-guess-shell-gnutar " -C "
(file-name-sans-extension file) " -zxvf")
(concat "mkdir " (file-name-sans-extension file)