;;; dired.el --- directory-browsing commands
-;; Copyright (C) 1985, 1986, 1992, 1993, 1994 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 86, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
;; Maintainer: FSF
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; along with GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
;;; Commentary:
;;;###autoload
(defvar dired-chown-program
- (if (memq system-type '(hpux dgux usg-unix-v irix linux))
- "chown" "/etc/chown")
+ (if (memq system-type '(hpux dgux usg-unix-v irix linux gnu/linux))
+ "chown"
+ (if (file-exists-p "/usr/sbin/chown")
+ "/usr/sbin/chown"
+ "/etc/chown"))
"Name of chown command (usually `chown' or `/etc/chown').")
+(defvar dired-chmod-program
+ (if (eq system-type 'windows-nt)
+ "chmode" "chmod")
+ "Name of chmod command (usually `chmod' or `chmode').")
+
;;;###autoload
(defvar dired-ls-F-marks-symlinks nil
"*Informs dired about how `ls -lF' marks symbolic links.
-Set this to t if `insert-directory-program' with `-lF' marks the symbolic link
+Set this to t if `ls' (or whatever program is specified by
+`insert-directory-program') with `-lF' marks the symbolic link
itself with a trailing @ (usually the case under Ultrix).
Example: if `ln -s foo bar; ls -F bar' gives `bar -> foo', set it to
"-[-r][-w].[-r][-w][xs][-r][-w]."
"-[-r][-w].[-r][-w].[-r][-w][xst]")
"\\|"))
-(defvar dired-re-perms "-[-r][-w].[-r][-w].[-r][-w].")
+(defvar dired-re-perms "[-bcdlps][-r][-w].[-r][-w].[-r][-w].")
(defvar dired-re-dot "^.* \\.\\.?$")
+;; The subdirectory names in this list are expanded.
(defvar dired-subdir-alist nil
"Association list of subdirectories and their buffer positions.
Each subdirectory has an element: (DIRNAME . STARTMARKER).
of the line (\\n or \\r).
Subexpression 2 must end right before the \\n or \\r.")
+(defvar dired-font-lock-keywords
+ (list
+ ;;
+ ;; Directory headers.
+ (list dired-subdir-regexp '(1 font-lock-type-face))
+ ;;
+ ;; We make heavy use of MATCH-ANCHORED, since the regexps don't identify the
+ ;; file name itself. We search for Dired defined regexps, and then use the
+ ;; Dired defined function `dired-move-to-filename' before searching for the
+ ;; simple regexp ".+". It is that regexp which matches the file name.
+ ;;
+ ;; Dired marks.
+ (list dired-re-mark
+ '(0 font-lock-reference-face)
+ '(".+" (dired-move-to-filename) nil (0 font-lock-warning-face)))
+ ;;
+ ;; Files that are group or world writable.
+ (list (concat dired-re-maybe-mark dired-re-inode-size
+ "\\([-d]\\(....w....\\|.......w.\\)\\)")
+ '(1 font-lock-comment-face)
+ '(".+" (dired-move-to-filename) nil (0 font-lock-comment-face)))
+ ;;
+ ;; Subdirectories.
+ (list dired-re-dir
+ '(".+" (dired-move-to-filename) nil (0 font-lock-function-name-face)))
+ ;;
+ ;; Symbolic links.
+ (list dired-re-sym
+ '(".+" (dired-move-to-filename) nil (0 font-lock-keyword-face)))
+ ;;
+ ;; Files suffixed with `completion-ignored-extensions'.
+ '(eval .
+ (let ((extensions (mapcar 'regexp-quote completion-ignored-extensions)))
+ ;; It is quicker to first find just an extension, then go back to the
+ ;; start of that file name. So we do this complex MATCH-ANCHORED form.
+ (list (concat "\\(" (mapconcat 'identity extensions "\\|") "\\|#\\)$")
+ '(".+" (dired-move-to-filename) nil (0 font-lock-string-face))))))
+ "Additional expressions to highlight in Dired mode.")
\f
;;; Macros must be defined before they are used, for the byte compiler.
\(Interactively, use a prefix argument to be able to specify SWITCHES.)
Dired displays a list of files in DIRNAME (which may also have
shell wildcards appended to select certain files). If DIRNAME is a cons,
-its first element is taken as the directory name and the resr as an explicit
+its first element is taken as the directory name and the rest as an explicit
list of files to make directory entries for.
\\<dired-mode-map>\
You can move around in it with the usual commands.
(if (consp dir-or-list)
(setq dirname (car dir-or-list))
(setq dirname dir-or-list))
- (setq dirname (expand-file-name (directory-file-name dirname)))
+ (setq dirname (abbreviate-file-name
+ (expand-file-name (directory-file-name dirname))))
+ (if find-file-visit-truename
+ (setq dirname (file-truename dirname)))
(if (file-directory-p dirname)
(setq dirname (file-name-as-directory dirname)))
(if (consp dir-or-list)
(dired-internal-noselect dir-or-list switches)))
;; Separate function from dired-noselect for the sake of dired-vms.el.
-(defun dired-internal-noselect (dir-or-list &optional switches)
+(defun dired-internal-noselect (dir-or-list &optional switches mode)
;; If there is an existing dired buffer for DIRNAME, just leave
;; buffer as it is (don't even call dired-revert).
;; This saves time especially for deep trees or with ange-ftp.
;; revert the buffer.
;; A pity we can't possibly do "Directory has changed - refresh? "
;; like find-file does.
+ ;; Optional argument MODE is passed to dired-find-buffer-nocreate,
+ ;; see there.
(let* ((dirname (if (consp dir-or-list) (car dir-or-list) dir-or-list))
- (buffer (dired-find-buffer-nocreate dir-or-list))
+ ;; The following line used to use dir-or-list.
+ ;; That never found an existing buffer, in the case
+ ;; where it is a list.
+ (buffer (dired-find-buffer-nocreate dirname mode))
;; note that buffer already is in dired-mode, if found
(new-buffer-p (not buffer))
(old-buf (current-buffer)))
;; kill-all-local-variables any longer.
(setq buffer (create-file-buffer (directory-file-name dirname)))))
(set-buffer buffer)
- (if (not new-buffer-p) ; existing buffer ...
- (if switches ; ... but new switches
- (dired-sort-other switches)) ; this calls dired-revert
+ (if (not new-buffer-p) ; existing buffer ...
+ (cond (switches ; ... but new switches
+ ;; file list may have changed
+ (if (consp dir-or-list)
+ (setq dired-directory dir-or-list))
+ ;; this calls dired-revert
+ (dired-sort-other switches))
+ ;; If directory has changed on disk, offer to revert.
+ ((if (let ((attributes (file-attributes dirname))
+ (modtime (visited-file-modtime)))
+ (or (eq modtime 0)
+ (not (eq (car attributes) t))
+ (and (= (car (nth 5 attributes)) (car modtime))
+ (= (nth 1 (nth 5 attributes)) (cdr modtime)))))
+ nil
+ (message "%s"
+ (substitute-command-keys
+ "Directory has changed on disk; type \\[revert-buffer] to update Dired")))))
;; Else a new buffer
(setq default-directory
- (abbreviate-file-name
- (if (file-directory-p dirname)
- dirname
- (file-name-directory dirname))))
+ (if (file-directory-p dirname)
+ dirname
+ (file-name-directory dirname)))
(or switches (setq switches dired-listing-switches))
(dired-mode dirname switches)
+ (if mode (funcall mode))
;; default-directory and dired-actual-switches are set now
;; (buffer-local), so we can call dired-readin:
(let ((failed t))
(set-buffer old-buf)
buffer))
-;; This differs from dired-buffers-for-dir in that it does not consider
-;; subdirs of default-directory and searches for the first match only
-(defun dired-find-buffer-nocreate (dirname)
- (let (found (blist (buffer-list)))
+(defun dired-find-buffer-nocreate (dirname &optional mode)
+ ;; This differs from dired-buffers-for-dir in that it does not consider
+ ;; subdirs of default-directory and searches for the first match only.
+ ;; Also, the major mode must be MODE.
+ (let (found (blist dired-buffers)) ; was (buffer-list)
+ (or mode (setq mode 'dired-mode))
(while blist
- (save-excursion
- (set-buffer (car blist))
- (if (and (eq major-mode 'dired-mode)
- (equal dired-directory dirname))
- (setq found (car blist)
- blist nil)
- (setq blist (cdr blist)))))
+ (if (null (buffer-name (cdr (car blist))))
+ (setq blist (cdr blist))
+ (save-excursion
+ (set-buffer (cdr (car blist)))
+ (if (and (eq major-mode mode)
+ (if (consp dired-directory)
+ (equal (car dired-directory) dirname)
+ (equal dired-directory dirname)))
+ (setq found (cdr (car blist))
+ blist nil)
+ (setq blist (cdr blist))))))
found))
\f
;; dired-build-subdir-alist will call dired-clear-alist first
(set (make-local-variable 'dired-subdir-alist) nil)
(dired-build-subdir-alist)
+ (let ((attributes (file-attributes dirname)))
+ (if (eq (car attributes) t)
+ (set-visited-file-modtime (nth 5 attributes))))
(set-buffer-modified-p nil))))
;; Subroutines of dired-readin
;; Do the right thing whether dir-or-list is atomic or not. If it is,
;; inset all files listed in the cdr (the car is the passed-in directory
;; list).
- (let ((opoint (point)))
+ (let ((opoint (point))
+ (process-environment (copy-sequence process-environment))
+ end)
+ ;; This makes sure that month names come out in English
+ ;; so we can find the start of the file name.
+ ;; But if the user has customized the way of finding the file name,
+ ;; this is not necessary.
+ (if (and (equal dired-move-to-filename-regexp
+ dired-standard-move-to-filename-regexp)
+ ;; It also isn't necessary if we'd use the C locale anyway.
+ (not (equal (or (getenv "LC_ALL") (getenv "LC_TIME")
+ (getenv "LANGUAGE") (getenv "LANG") "C")
+ "C")))
+ (setq process-environment (cons "LC_ALL=C" process-environment)))
(if (consp dir-or-list)
- (progn
- (mapcar
- (function (lambda (x) (insert-directory x switches wildcard full-p)))
- (cdr dir-or-list)))
- (insert-directory dir-or-list switches wildcard full-p))
+ ;; In this case, use the file names in the cdr
+ ;; exactly as originally given to dired-noselect.
+ (mapcar
+ (function (lambda (x) (insert-directory x switches wildcard full-p)))
+ (cdr dir-or-list))
+ ;; Expand the file name here because it may have been abbreviated
+ ;; in dired-noselect.
+ (insert-directory (expand-file-name dir-or-list) switches wildcard full-p))
+ ;; Quote certain characters, unless ls quoted them for us.
+ (if (not (string-match "b" dired-actual-switches))
+ (save-excursion
+ (setq end (point-marker))
+ (goto-char opoint)
+ (while (search-forward "\\" end t)
+ (replace-match "\\\\" nil t))
+ (goto-char opoint)
+ (while (search-forward "\^m" end t)
+ (replace-match "\\015" nil t))
+ (set-marker end nil)))
(dired-insert-set-properties opoint (point)))
(setq dired-directory dir-or-list))
+;; Make the file names highlight when the mouse is on them.
(defun dired-insert-set-properties (beg end)
(save-excursion
(goto-char beg)
(while (< (point) end)
- (if (dired-move-to-filename)
- (put-text-property (point)
- (save-excursion
- (dired-move-to-end-of-filename)
- (point))
- 'mouse-face 'highlight))
+ (condition-case nil
+ (if (dired-move-to-filename)
+ (put-text-property (point)
+ (save-excursion
+ (dired-move-to-end-of-filename)
+ (point))
+ 'mouse-face 'highlight))
+ (error nil))
(forward-line 1))))
(defun dired-insert-headerline (dir);; also used by dired-insert-subdir
;; This looks ugly when substitute-command-keys uses C-d instead d:
;; (define-key dired-mode-map "\C-d" 'dired-flag-file-deletion)
- (setq dired-mode-map (make-keymap))
- (suppress-keymap dired-mode-map)
- (define-key dired-mode-map [mouse-2] 'dired-mouse-find-file-other-window)
- ;; Commands to mark or flag certain categories of files
- (define-key dired-mode-map "#" 'dired-flag-auto-save-files)
- (define-key dired-mode-map "*" 'dired-mark-executables)
- (define-key dired-mode-map "." 'dired-clean-directory)
- (define-key dired-mode-map "/" 'dired-mark-directories)
- (define-key dired-mode-map "@" 'dired-mark-symlinks)
- (define-key dired-mode-map "~" 'dired-flag-backup-files)
- ;; Upper case keys (except !) for operating on the marked files
- (define-key dired-mode-map "C" 'dired-do-copy)
- (define-key dired-mode-map "B" 'dired-do-byte-compile)
- (define-key dired-mode-map "D" 'dired-do-delete)
- (define-key dired-mode-map "G" 'dired-do-chgrp)
- (define-key dired-mode-map "H" 'dired-do-hardlink)
- (define-key dired-mode-map "L" 'dired-do-load)
- (define-key dired-mode-map "M" 'dired-do-chmod)
- (define-key dired-mode-map "O" 'dired-do-chown)
- (define-key dired-mode-map "P" 'dired-do-print)
- (define-key dired-mode-map "R" 'dired-do-rename)
- (define-key dired-mode-map "S" 'dired-do-symlink)
- (define-key dired-mode-map "X" 'dired-do-shell-command)
- (define-key dired-mode-map "Z" 'dired-do-compress)
- (define-key dired-mode-map "!" 'dired-do-shell-command)
- ;; Comparison commands
- (define-key dired-mode-map "=" 'dired-diff)
- (define-key dired-mode-map "\M-=" 'dired-backup-diff)
- ;; Tree Dired commands
- (define-key dired-mode-map "\M-\C-?" 'dired-unmark-all-files)
- (define-key dired-mode-map "\M-\C-d" 'dired-tree-down)
- (define-key dired-mode-map "\M-\C-u" 'dired-tree-up)
- (define-key dired-mode-map "\M-\C-n" 'dired-next-subdir)
- (define-key dired-mode-map "\M-\C-p" 'dired-prev-subdir)
- ;; move to marked files
- (define-key dired-mode-map "\M-{" 'dired-prev-marked-file)
- (define-key dired-mode-map "\M-}" 'dired-next-marked-file)
- ;; Make all regexp commands share a `%' prefix:
- ;; We used to get to the submap via a symbol dired-regexp-prefix,
- ;; but that seems to serve little purpose, and copy-keymap
- ;; does a better job without it.
- (define-key dired-mode-map "%" nil)
- (define-key dired-mode-map "%u" 'dired-upcase)
- (define-key dired-mode-map "%l" 'dired-downcase)
- (define-key dired-mode-map "%d" 'dired-flag-files-regexp)
- (define-key dired-mode-map "%m" 'dired-mark-files-regexp)
- (define-key dired-mode-map "%r" 'dired-do-rename-regexp)
- (define-key dired-mode-map "%C" 'dired-do-copy-regexp)
- (define-key dired-mode-map "%H" 'dired-do-hardlink-regexp)
- (define-key dired-mode-map "%R" 'dired-do-rename-regexp)
- (define-key dired-mode-map "%S" 'dired-do-symlink-regexp)
- ;; Lower keys for commands not operating on all the marked files
- (define-key dired-mode-map "c" 'dired-change-marks)
- (define-key dired-mode-map "d" 'dired-flag-file-deletion)
- (define-key dired-mode-map "e" 'dired-find-file)
- (define-key dired-mode-map "f" 'dired-advertised-find-file)
- (define-key dired-mode-map "g" 'revert-buffer)
- (define-key dired-mode-map "h" 'describe-mode)
- (define-key dired-mode-map "i" 'dired-maybe-insert-subdir)
- (define-key dired-mode-map "k" 'dired-do-kill-lines)
- (define-key dired-mode-map "l" 'dired-do-redisplay)
- (define-key dired-mode-map "m" 'dired-mark)
- (define-key dired-mode-map "n" 'dired-next-line)
- (define-key dired-mode-map "o" 'dired-find-file-other-window)
- (define-key dired-mode-map "\C-o" 'dired-display-file)
- (define-key dired-mode-map "p" 'dired-previous-line)
- (define-key dired-mode-map "q" 'dired-quit)
- (define-key dired-mode-map "s" 'dired-sort-toggle-or-edit)
- (define-key dired-mode-map "u" 'dired-unmark)
- (define-key dired-mode-map "v" 'dired-view-file)
- (define-key dired-mode-map "x" 'dired-do-flagged-delete)
- (define-key dired-mode-map "+" 'dired-create-directory)
- ;; moving
- (define-key dired-mode-map "<" 'dired-prev-dirline)
- (define-key dired-mode-map ">" 'dired-next-dirline)
- (define-key dired-mode-map "^" 'dired-up-directory)
- (define-key dired-mode-map " " 'dired-next-line)
- (define-key dired-mode-map "\C-n" 'dired-next-line)
- (define-key dired-mode-map "\C-p" 'dired-previous-line)
- ;; hiding
- (define-key dired-mode-map "$" 'dired-hide-subdir)
- (define-key dired-mode-map "\M-$" 'dired-hide-all)
- ;; misc
- (define-key dired-mode-map "?" 'dired-summary)
- (define-key dired-mode-map "\177" 'dired-unmark-backward)
- (define-key dired-mode-map "\C-_" 'dired-undo)
- (define-key dired-mode-map "\C-xu" 'dired-undo)
- )
-\f
-;; Make menu bar items.
-
-;; Get rid of the Edit menu bar item to save space.
-(define-key dired-mode-map [menu-bar edit] 'undefined)
-
-(define-key dired-mode-map [menu-bar subdir]
- (cons "Subdir" (make-sparse-keymap "Subdir")))
-
-(define-key dired-mode-map [menu-bar subdir hide-all]
- '("Hide All" . dired-hide-all))
-(define-key dired-mode-map [menu-bar subdir hide-subdir]
- '("Hide Subdir" . dired-hide-subdir))
-(define-key dired-mode-map [menu-bar subdir tree-down]
- '("Tree Down" . dired-tree-down))
-(define-key dired-mode-map [menu-bar subdir tree-up]
- '("Tree Up" . dired-tree-up))
-(define-key dired-mode-map [menu-bar subdir up]
- '("Up Directory" . dired-up-directory))
-(define-key dired-mode-map [menu-bar subdir prev-subdir]
- '("Prev Subdir" . dired-prev-subdir))
-(define-key dired-mode-map [menu-bar subdir next-subdir]
- '("Next Subdir" . dired-next-subdir))
-(define-key dired-mode-map [menu-bar subdir prev-dirline]
- '("Prev Dirline" . dired-prev-dirline))
-(define-key dired-mode-map [menu-bar subdir next-dirline]
- '("Next Dirline" . dired-next-dirline))
-(define-key dired-mode-map [menu-bar subdir insert]
- '("Insert This Subdir" . dired-maybe-insert-subdir))
-
-(define-key dired-mode-map [menu-bar immediate]
- (cons "Immediate" (make-sparse-keymap "Immediate")))
-
-(define-key dired-mode-map [menu-bar immediate backup-diff]
- '("Compare with Backup" . dired-backup-diff))
-(define-key dired-mode-map [menu-bar immediate diff]
- '("Diff" . dired-diff))
-(define-key dired-mode-map [menu-bar immediate view]
- '("View This File" . dired-view-file))
-(define-key dired-mode-map [menu-bar immediate display]
- '("Display in Other Window" . dired-display-file))
-(define-key dired-mode-map [menu-bar immediate find-file-other-window]
- '("Find in Other Window" . dired-find-file-other-window))
-(define-key dired-mode-map [menu-bar immediate find-file]
- '("Find This File" . dired-find-file))
-(define-key dired-mode-map [menu-bar immediate create-directory]
- '("Create Directory..." . dired-create-directory))
-
-(define-key dired-mode-map [menu-bar regexp]
- (cons "Regexp" (make-sparse-keymap "Regexp")))
-
-(define-key dired-mode-map [menu-bar regexp downcase]
- '("Downcase" . dired-downcase))
-(define-key dired-mode-map [menu-bar regexp upcase]
- '("Upcase" . dired-upcase))
-(define-key dired-mode-map [menu-bar regexp hardlink]
- '("Hardlink..." . dired-do-hardlink-regexp))
-(define-key dired-mode-map [menu-bar regexp symlink]
- '("Symlink..." . dired-do-symlink-regexp))
-(define-key dired-mode-map [menu-bar regexp rename]
- '("Rename..." . dired-do-rename-regexp))
-(define-key dired-mode-map [menu-bar regexp copy]
- '("Copy..." . dired-do-copy-regexp))
-(define-key dired-mode-map [menu-bar regexp flag]
- '("Flag..." . dired-flag-files-regexp))
-(define-key dired-mode-map [menu-bar regexp mark]
- '("Mark..." . dired-mark-files-regexp))
-
-(define-key dired-mode-map [menu-bar mark]
- (cons "Mark" (make-sparse-keymap "Mark")))
-
-(define-key dired-mode-map [menu-bar mark prev]
- '("Previous Marked" . dired-prev-marked-file))
-(define-key dired-mode-map [menu-bar mark next]
- '("Next Marked" . dired-next-marked-file))
-(define-key dired-mode-map [menu-bar mark marks]
- '("Change Marks..." . dired-change-marks))
-(define-key dired-mode-map [menu-bar mark unmark-all]
- '("Unmark All" . dired-unmark-all-files-no-query))
-(define-key dired-mode-map [menu-bar mark symlinks]
- '("Mark Symlinks" . dired-mark-symlinks))
-(define-key dired-mode-map [menu-bar mark directories]
- '("Mark Directories" . dired-mark-directories))
-(define-key dired-mode-map [menu-bar mark directory]
- '("Mark Old Backups" . dired-clean-directory))
-(define-key dired-mode-map [menu-bar mark executables]
- '("Mark Executables" . dired-mark-executables))
-(define-key dired-mode-map [menu-bar mark backup-files]
- '("Flag Backup Files" . dired-flag-backup-files))
-(define-key dired-mode-map [menu-bar mark auto-save-files]
- '("Flag Auto-save Files" . dired-flag-auto-save-files))
-(define-key dired-mode-map [menu-bar mark deletion]
- '("Flag" . dired-flag-file-deletion))
-(define-key dired-mode-map [menu-bar mark unmark]
- '("Unmark" . dired-unmark))
-(define-key dired-mode-map [menu-bar mark mark]
- '("Mark" . dired-mark))
-
-(define-key dired-mode-map [menu-bar operate]
- (cons "Operate" (make-sparse-keymap "Operate")))
-
-(define-key dired-mode-map [menu-bar operate chown]
- '("Change Owner..." . dired-do-chown))
-(define-key dired-mode-map [menu-bar operate chgrp]
- '("Change Group..." . dired-do-chgrp))
-(define-key dired-mode-map [menu-bar operate chmod]
- '("Change Mode..." . dired-do-chmod))
-(define-key dired-mode-map [menu-bar operate load]
- '("Load" . dired-do-load))
-(define-key dired-mode-map [menu-bar operate compile]
- '("Byte-compile" . dired-do-byte-compile))
-(define-key dired-mode-map [menu-bar operate compress]
- '("Compress" . dired-do-compress))
-(define-key dired-mode-map [menu-bar operate print]
- '("Print" . dired-do-print))
-(define-key dired-mode-map [menu-bar operate hardlink]
- '("Hardlink to..." . dired-do-hardlink))
-(define-key dired-mode-map [menu-bar operate symlink]
- '("Symlink to..." . dired-do-symlink))
-(define-key dired-mode-map [menu-bar operate command]
- '("Shell Command..." . dired-do-shell-command))
-(define-key dired-mode-map [menu-bar operate delete]
- '("Delete" . dired-do-delete))
-(define-key dired-mode-map [menu-bar operate rename]
- '("Rename to..." . dired-do-rename))
-(define-key dired-mode-map [menu-bar operate copy]
- '("Copy to..." . dired-do-copy))
+ (let ((map (make-keymap)))
+ (suppress-keymap map)
+ (define-key map [mouse-2] 'dired-mouse-find-file-other-window)
+ ;; Commands to mark or flag certain categories of files
+ (define-key map "#" 'dired-flag-auto-save-files)
+ (define-key map "." 'dired-clean-directory)
+ (define-key map "~" 'dired-flag-backup-files)
+ ;; Upper case keys (except !) for operating on the marked files
+ (define-key map "A" 'dired-do-search)
+ (define-key map "C" 'dired-do-copy)
+ (define-key map "B" 'dired-do-byte-compile)
+ (define-key map "D" 'dired-do-delete)
+ (define-key map "G" 'dired-do-chgrp)
+ (define-key map "H" 'dired-do-hardlink)
+ (define-key map "L" 'dired-do-load)
+ (define-key map "M" 'dired-do-chmod)
+ (define-key map "O" 'dired-do-chown)
+ (define-key map "P" 'dired-do-print)
+ (define-key map "Q" 'dired-do-query-replace)
+ (define-key map "R" 'dired-do-rename)
+ (define-key map "S" 'dired-do-symlink)
+ (define-key map "X" 'dired-do-shell-command)
+ (define-key map "Z" 'dired-do-compress)
+ (define-key map "!" 'dired-do-shell-command)
+ ;; Comparison commands
+ (define-key map "=" 'dired-diff)
+ (define-key map "\M-=" 'dired-backup-diff)
+ ;; Tree Dired commands
+ (define-key map "\M-\C-?" 'dired-unmark-all-files)
+ (define-key map "\M-\C-d" 'dired-tree-down)
+ (define-key map "\M-\C-u" 'dired-tree-up)
+ (define-key map "\M-\C-n" 'dired-next-subdir)
+ (define-key map "\M-\C-p" 'dired-prev-subdir)
+ ;; move to marked files
+ (define-key map "\M-{" 'dired-prev-marked-file)
+ (define-key map "\M-}" 'dired-next-marked-file)
+ ;; Make all regexp commands share a `%' prefix:
+ ;; We used to get to the submap via a symbol dired-regexp-prefix,
+ ;; but that seems to serve little purpose, and copy-keymap
+ ;; does a better job without it.
+ (define-key map "%" nil)
+ (define-key map "%u" 'dired-upcase)
+ (define-key map "%l" 'dired-downcase)
+ (define-key map "%d" 'dired-flag-files-regexp)
+ (define-key map "%m" 'dired-mark-files-regexp)
+ (define-key map "%r" 'dired-do-rename-regexp)
+ (define-key map "%C" 'dired-do-copy-regexp)
+ (define-key map "%H" 'dired-do-hardlink-regexp)
+ (define-key map "%R" 'dired-do-rename-regexp)
+ (define-key map "%S" 'dired-do-symlink-regexp)
+ ;; Commands for marking and unmarking.
+ (define-key map "*" nil)
+ (define-key map "**" 'dired-mark-executables)
+ (define-key map "*/" 'dired-mark-directories)
+ (define-key map "*@" 'dired-mark-symlinks)
+ (define-key map "*%" 'dired-mark-files-regexp)
+ (define-key map "*c" 'dired-change-marks)
+ (define-key map "*s" 'dired-mark-subdir-files)
+ (define-key map "*m" 'dired-mark)
+ (define-key map "*u" 'dired-unmark)
+ (define-key map "*?" 'dired-unmark-all-files)
+ (define-key map "*!" 'dired-unmark-all-files-no-query)
+ (define-key map "*\177" 'dired-unmark-backward)
+ (define-key map "*\C-n" 'dired-next-marked-file)
+ (define-key map "*\C-p" 'dired-prev-marked-file)
+ ;; Lower keys for commands not operating on all the marked files
+ (define-key map "d" 'dired-flag-file-deletion)
+ (define-key map "e" 'dired-find-file)
+ (define-key map "f" 'dired-find-file)
+ (define-key map "\C-m" 'dired-advertised-find-file)
+ (define-key map "g" 'revert-buffer)
+ (define-key map "h" 'describe-mode)
+ (define-key map "i" 'dired-maybe-insert-subdir)
+ (define-key map "k" 'dired-do-kill-lines)
+ (define-key map "l" 'dired-do-redisplay)
+ (define-key map "m" 'dired-mark)
+ (define-key map "n" 'dired-next-line)
+ (define-key map "o" 'dired-find-file-other-window)
+ (define-key map "\C-o" 'dired-display-file)
+ (define-key map "p" 'dired-previous-line)
+ (define-key map "q" 'dired-quit)
+ (define-key map "s" 'dired-sort-toggle-or-edit)
+ (define-key map "u" 'dired-unmark)
+ (define-key map "v" 'dired-view-file)
+ (define-key map "x" 'dired-do-flagged-delete)
+ (define-key map "+" 'dired-create-directory)
+ ;; moving
+ (define-key map "<" 'dired-prev-dirline)
+ (define-key map ">" 'dired-next-dirline)
+ (define-key map "^" 'dired-up-directory)
+ (define-key map " " 'dired-next-line)
+ (define-key map "\C-n" 'dired-next-line)
+ (define-key map "\C-p" 'dired-previous-line)
+ (define-key map [down] 'dired-next-line)
+ (define-key map [up] 'dired-previous-line)
+ ;; hiding
+ (define-key map "$" 'dired-hide-subdir)
+ (define-key map "\M-$" 'dired-hide-all)
+ ;; misc
+ (define-key map "?" 'dired-summary)
+ (define-key map "\177" 'dired-unmark-backward)
+ (define-key map "\C-_" 'dired-undo)
+ (define-key map "\C-xu" 'dired-undo)
+
+ ;; Make menu bar items.
+
+ ;; Get rid of the Edit menu bar item to save space.
+ (define-key map [menu-bar edit] 'undefined)
+
+ (define-key map [menu-bar subdir]
+ (cons "Subdir" (make-sparse-keymap "Subdir")))
+
+ (define-key map [menu-bar subdir hide-all]
+ '("Hide All" . dired-hide-all))
+ (define-key map [menu-bar subdir hide-subdir]
+ '("Hide Subdir" . dired-hide-subdir))
+ (define-key map [menu-bar subdir tree-down]
+ '("Tree Down" . dired-tree-down))
+ (define-key map [menu-bar subdir tree-up]
+ '("Tree Up" . dired-tree-up))
+ (define-key map [menu-bar subdir up]
+ '("Up Directory" . dired-up-directory))
+ (define-key map [menu-bar subdir prev-subdir]
+ '("Prev Subdir" . dired-prev-subdir))
+ (define-key map [menu-bar subdir next-subdir]
+ '("Next Subdir" . dired-next-subdir))
+ (define-key map [menu-bar subdir prev-dirline]
+ '("Prev Dirline" . dired-prev-dirline))
+ (define-key map [menu-bar subdir next-dirline]
+ '("Next Dirline" . dired-next-dirline))
+ (define-key map [menu-bar subdir insert]
+ '("Insert This Subdir" . dired-maybe-insert-subdir))
+
+ (define-key map [menu-bar immediate]
+ (cons "Immediate" (make-sparse-keymap "Immediate")))
+
+ (define-key map [menu-bar immediate revert-buffer]
+ '("Update Buffer" . revert-buffer))
+
+ (define-key map [menu-bar immediate dashes]
+ '("--"))
+
+ (define-key map [menu-bar immediate backup-diff]
+ '("Compare with Backup" . dired-backup-diff))
+ (define-key map [menu-bar immediate diff]
+ '("Diff" . dired-diff))
+ (define-key map [menu-bar immediate view]
+ '("View This File" . dired-view-file))
+ (define-key map [menu-bar immediate display]
+ '("Display in Other Window" . dired-display-file))
+ (define-key map [menu-bar immediate find-file-other-window]
+ '("Find in Other Window" . dired-find-file-other-window))
+ (define-key map [menu-bar immediate find-file]
+ '("Find This File" . dired-find-file))
+ (define-key map [menu-bar immediate create-directory]
+ '("Create Directory..." . dired-create-directory))
+
+ (define-key map [menu-bar regexp]
+ (cons "Regexp" (make-sparse-keymap "Regexp")))
+
+ (define-key map [menu-bar regexp downcase]
+ '("Downcase" . dired-downcase))
+ (define-key map [menu-bar regexp upcase]
+ '("Upcase" . dired-upcase))
+ (define-key map [menu-bar regexp hardlink]
+ '("Hardlink..." . dired-do-hardlink-regexp))
+ (define-key map [menu-bar regexp symlink]
+ '("Symlink..." . dired-do-symlink-regexp))
+ (define-key map [menu-bar regexp rename]
+ '("Rename..." . dired-do-rename-regexp))
+ (define-key map [menu-bar regexp copy]
+ '("Copy..." . dired-do-copy-regexp))
+ (define-key map [menu-bar regexp flag]
+ '("Flag..." . dired-flag-files-regexp))
+ (define-key map [menu-bar regexp mark]
+ '("Mark..." . dired-mark-files-regexp))
+
+ (define-key map [menu-bar mark]
+ (cons "Mark" (make-sparse-keymap "Mark")))
+
+ (define-key map [menu-bar mark prev]
+ '("Previous Marked" . dired-prev-marked-file))
+ (define-key map [menu-bar mark next]
+ '("Next Marked" . dired-next-marked-file))
+ (define-key map [menu-bar mark marks]
+ '("Change Marks..." . dired-change-marks))
+ (define-key map [menu-bar mark unmark-all]
+ '("Unmark All" . dired-unmark-all-files-no-query))
+ (define-key map [menu-bar mark symlinks]
+ '("Mark Symlinks" . dired-mark-symlinks))
+ (define-key map [menu-bar mark directories]
+ '("Mark Directories" . dired-mark-directories))
+ (define-key map [menu-bar mark directory]
+ '("Mark Old Backups" . dired-clean-directory))
+ (define-key map [menu-bar mark executables]
+ '("Mark Executables" . dired-mark-executables))
+ (define-key map [menu-bar mark backup-files]
+ '("Flag Backup Files" . dired-flag-backup-files))
+ (define-key map [menu-bar mark auto-save-files]
+ '("Flag Auto-save Files" . dired-flag-auto-save-files))
+ (define-key map [menu-bar mark deletion]
+ '("Flag" . dired-flag-file-deletion))
+ (define-key map [menu-bar mark unmark]
+ '("Unmark" . dired-unmark))
+ (define-key map [menu-bar mark mark]
+ '("Mark" . dired-mark))
+
+ (define-key map [menu-bar operate]
+ (cons "Operate" (make-sparse-keymap "Operate")))
+
+ (define-key map [menu-bar operate query-replace]
+ '("Query Replace in Files..." . dired-do-query-replace))
+ (define-key map [menu-bar operate search]
+ '("Search Files..." . dired-do-search))
+ (define-key map [menu-bar operate chown]
+ '("Change Owner..." . dired-do-chown))
+ (define-key map [menu-bar operate chgrp]
+ '("Change Group..." . dired-do-chgrp))
+ (define-key map [menu-bar operate chmod]
+ '("Change Mode..." . dired-do-chmod))
+ (define-key map [menu-bar operate load]
+ '("Load" . dired-do-load))
+ (define-key map [menu-bar operate compile]
+ '("Byte-compile" . dired-do-byte-compile))
+ (define-key map [menu-bar operate compress]
+ '("Compress" . dired-do-compress))
+ (define-key map [menu-bar operate print]
+ '("Print" . dired-do-print))
+ (define-key map [menu-bar operate hardlink]
+ '("Hardlink to..." . dired-do-hardlink))
+ (define-key map [menu-bar operate symlink]
+ '("Symlink to..." . dired-do-symlink))
+ (define-key map [menu-bar operate command]
+ '("Shell Command..." . dired-do-shell-command))
+ (define-key map [menu-bar operate delete]
+ '("Delete" . dired-do-delete))
+ (define-key map [menu-bar operate rename]
+ '("Rename to..." . dired-do-rename))
+ (define-key map [menu-bar operate copy]
+ '("Copy to..." . dired-do-copy))
+
+ (setq dired-mode-map map)))
\f
;; Dired mode is suitable only for specially formatted data.
(put 'dired-mode 'mode-class 'special)
(or dirname default-directory))
;; list-buffers uses this to display the dir being edited in this buffer.
(set (make-local-variable 'list-buffers-directory)
- dired-directory)
+ (expand-file-name dired-directory))
(set (make-local-variable 'dired-actual-switches)
(or switches dired-listing-switches))
+ (set (make-local-variable 'font-lock-defaults) '(dired-font-lock-keywords t))
(dired-sort-other dired-actual-switches t)
(run-hooks 'dired-mode-hook))
\f
(interactive "p")
(dired-next-dirline (- arg)))
-(defun dired-up-directory ()
+(defun dired-up-directory (&optional other-window)
"Run dired on parent directory of current directory.
Find the parent directory either in this buffer or another buffer.
Creates a buffer if necessary."
- (interactive)
+ (interactive "P")
(let* ((dir (dired-current-directory))
(up (file-name-directory (directory-file-name dir))))
(or (dired-goto-file (directory-file-name dir))
(and (cdr dired-subdir-alist)
(dired-goto-subdir up))
(progn
- (dired
-up)
+ (if other-window
+ (dired-other-window up)
+ (dired up))
(dired-goto-file dir)))))
;; Force `f' rather than `e' in the mode doc:
(defun dired-find-file ()
"In dired, visit the file or directory named on this line."
(interactive)
- (find-file (file-name-sans-versions (dired-get-filename) t)))
+ (let ((file-name (file-name-sans-versions (dired-get-filename) t)))
+ (if (file-exists-p file-name)
+ (find-file file-name)
+ (error "File no longer exists; type `g' to update Dired buffer"))))
(defun dired-mouse-find-file-other-window (event)
"In dired, visit the file or directory name you click on."
(if (setq p1 (dired-move-to-filename (not no-error-if-not-filep)))
(setq p2 (dired-move-to-end-of-filename no-error-if-not-filep))))
;; nil if no file on this line, but no-error-if-not-filep is t:
- (if (setq file (and p1 p2 (format "%s" (buffer-substring p1 p2))))
- ;; Check if ls quoted the names, and unquote them.
- ;; Using read to unquote is much faster than substituting
- ;; \007 (4 chars) -> ^G (1 char) etc. in a lisp loop.
- (cond ((string-match "b" dired-actual-switches) ; System V ls
- ;; This case is about 20% slower than without -b.
- (setq file
- (read
- (concat "\""
- ;; some ls -b don't escape quotes, argh!
- ;; This is not needed for GNU ls, though.
- (or (dired-string-replace-match
- "\\([^\\]\\)\"" file "\\1\\\\\"")
- file)
- "\""))))
- ;; If you do this, update dired-insert-subdir-validate too
- ;; ((string-match "Q" dired-actual-switches) ; GNU ls
- ;; (setq file (read file)))
- ))
+ (if (setq file (and p1 p2 (buffer-substring p1 p2)))
+ (progn
+ ;; Get rid of the mouse-face property that file names have.
+ (set-text-properties 0 (length file) nil file)
+ ;; Unquote names quoted by ls or by dired-insert-directory.
+ ;; Using read to unquote is much faster than substituting
+ ;; \007 (4 chars) -> ^G (1 char) etc. in a lisp loop.
+ (setq file
+ (read
+ (concat "\""
+ ;; some ls -b don't escape quotes, argh!
+ ;; This is not needed for GNU ls, though.
+ (or (dired-string-replace-match
+ "\\([^\\]\\|\\`\\)\"" file "\\1\\\\\"" nil t)
+ file)
+ "\"")))))
(if (eq localp 'no-dir)
file
(and file (concat (dired-current-directory localp) file)))))
+(defun dired-string-replace-match (regexp string newtext
+ &optional literal global)
+ "Replace first match of REGEXP in STRING with NEWTEXT.
+If it does not match, nil is returned instead of the new string.
+Optional arg LITERAL means to take NEWTEXT literally.
+Optional arg GLOBAL means to replace all matches."
+ (if global
+ (let ((start 0))
+ (while (string-match regexp string start)
+ (let ((from-end (- (length string) (match-end 0))))
+ (setq string (replace-match newtext t literal string))
+ (setq start (- (length string) from-end))))
+ string)
+ (if (not (string-match regexp string 0))
+ nil
+ (replace-match newtext t literal string))))
+
(defun dired-make-absolute (file &optional dir)
;;"Convert FILE (a pathname relative to DIR) to an absolute pathname."
;; We can't always use expand-file-name as this would get rid of `.'
;;; Functions for finding the file name in a dired buffer line.
(defvar dired-move-to-filename-regexp
+ " [A-Za-z\xa0-\xff][A-Za-z\xa0-\xff][A-Za-z\xa0-\xff] [0-3 ][0-9]\
+ [ 0-9][0-9][:0-9][0-9][ 0-9] "
+ "Regular expression to match a month abbreviation followed date/time.")
+
+(defconst dired-standard-move-to-filename-regexp
"\\(Jan\\|Feb\\|Mar\\|Apr\\|May\\|Jun\\|Jul\\|Aug\\|Sep\\|Oct\\|Nov\\|Dec\\)[ ]+[0-9]+ [ 0-9][0-9][:0-9][0-9][ 0-9] "
"Regular expression to match a month abbreviation followed by a number.")
;; Enlarged by dired-advertise
;; Queried by function dired-buffers-for-dir. When this detects a
;; killed buffer, it is removed from this list.
- "Alist of directories and their associated dired buffers.")
+ "Alist of expanded directories and their associated dired buffers.")
(defun dired-buffers-for-dir (dir)
;; Return a list of buffers that dired DIR (top level or in-situ subdir).
;; As a side effect, killed dired buffers for DIR are removed from
;; dired-buffers.
(setq dir (file-name-as-directory dir))
- (let ((alist dired-buffers) result elt)
+ (let ((alist dired-buffers) result elt buf)
(while alist
- (setq elt (car alist))
- (if (dired-in-this-tree dir (car elt))
- (let ((buf (cdr elt)))
- (if (buffer-name buf)
- (if (assoc dir (save-excursion
- (set-buffer buf)
- dired-subdir-alist))
- (setq result (cons buf result)))
- ;; else buffer is killed - clean up:
- (setq dired-buffers (delq elt dired-buffers)))))
+ (setq elt (car alist)
+ buf (cdr elt))
+ (if (buffer-name buf)
+ (if (dired-in-this-tree dir (car elt))
+ (if (assoc dir (save-excursion
+ (set-buffer buf)
+ dired-subdir-alist))
+ (setq result (cons buf result))))
+ ;; else buffer is killed - clean up:
+ (setq dired-buffers (delq elt dired-buffers)))
(setq alist (cdr alist)))
result))
(defun dired-advertise ()
;;"Advertise in variable `dired-buffers' that we dired `default-directory'."
;; With wildcards we actually advertise too much.
- (if (memq (current-buffer) (dired-buffers-for-dir default-directory))
- t ; we have already advertised ourselves
- (setq dired-buffers
- (cons (cons default-directory (current-buffer))
- dired-buffers))))
+ (let ((expanded-default (expand-file-name default-directory)))
+ (if (memq (current-buffer) (dired-buffers-for-dir expanded-default))
+ t ; we have already advertised ourselves
+ (setq dired-buffers
+ (cons (cons expanded-default (current-buffer))
+ dired-buffers)))))
(defun dired-unadvertise (dir)
;; Remove DIR from the buffer alist in variable dired-buffers.
;; It does not affect buffers in which DIR is a subdir.
;; Removing is also done as a side-effect in dired-buffer-for-dir.
(setq dired-buffers
- (delq (assoc dir dired-buffers) dired-buffers)))
+ (delq (assoc (expand-file-name dir) dired-buffers) dired-buffers)))
\f
;; Tree Dired
(defun dired-in-this-tree (file dir)
;;"Is FILE part of the directory tree starting at DIR?"
(let (case-fold-search)
- (string-match (concat "^" (regexp-quote (expand-file-name dir))) file)))
+ (string-match (concat "^" (regexp-quote dir)) file)))
(defun dired-normalize-subdir (dir)
;; Prepend default-directory to DIR if relative path name.
(goto-char (match-beginning 0))
(beginning-of-line)
(forward-char 2)
- (looking-at dired-re-perms))))
+ (save-match-data (looking-at dired-re-perms)))))
(save-excursion
(goto-char (match-beginning 1))
(setq new-dir-name
\f
;; Deleting files
-(defun dired-do-flagged-delete ()
- "In dired, delete the files flagged for deletion."
+(defun dired-do-flagged-delete (&optional nomessage)
+ "In dired, delete the files flagged for deletion.
+If NOMESSAGE is non-nil, we don't display any message
+if there are no flagged files."
(interactive)
(let* ((dired-marker-char dired-del-marker)
(regexp (dired-marker-regexp))
(dired-map-over-marks (cons (dired-get-filename) (point))
nil)
nil)
- (message "(No deletions requested)"))))
+ (or nomessage
+ (message "(No deletions requested)")))))
(defun dired-do-delete (&optional arg)
"Delete all marked (or next ARG) files."
;; Should be equivalent to (save-excursion (not (dired-move-to-filename)))
;; but is about 1.5..2.0 times as fast. (Actually that's not worth it)
(or (looking-at "^$\\|^. *$\\|^. total\\|^. wildcard")
- (looking-at dired-subdir-regexp)))
+ (and (looking-at dired-subdir-regexp)
+ (save-excursion (not (dired-move-to-filename))))))
(defun dired-next-marked-file (arg &optional wrap opoint)
"Move to the next marked file, wrapping around the end of the buffer."
and \\[dired-unmark] on a subdir to remove the marks in
this subdir."
(interactive "P")
- (if (and (cdr dired-subdir-alist) (dired-get-subdir))
+ (if (dired-get-subdir)
(save-excursion (dired-mark-subdir-files))
(let (buffer-read-only)
(dired-repeat-over-lines
"Flag all backup files (names ending with `~') for deletion.
With prefix argument, unflag these files."
(interactive "P")
- (let ((dired-marker-char (if unflag-p ?\040 dired-del-marker)))
+ (let ((dired-marker-char (if unflag-p ?\ dired-del-marker)))
(dired-mark-if
- ;; It is less than general to check for ~ here,
+ ;; Don't call backup-file-name-p unless the last character looks like
+ ;; it might be the end of a backup file name. This isn't very general,
;; but it's the only way this runs fast enough.
(and (save-excursion (end-of-line)
- (or
- (eq (preceding-char) ?~)
- ;; Handle executables in case of -F option.
- ;; We need not worry about the other kinds
- ;; of markings that -F makes, since they won't
- ;; appear on real backup files.
- (if (eq (preceding-char) ?*)
- (progn
- (forward-char -1)
- (eq (preceding-char) ?~)))))
+ ;; Handle executables in case of -F option.
+ ;; We need not worry about the other kinds
+ ;; of markings that -F makes, since they won't
+ ;; appear on real backup files.
+ (if (eq (preceding-char) ?*)
+ (forward-char -1))
+ (eq (preceding-char) ?~))
(not (looking-at dired-re-dir))
(let ((fn (dired-get-filename t t)))
(if fn (backup-file-name-p fn))))
(save-excursion
(goto-char (point-min))
(while (search-forward string nil t)
- (subst-char-in-region (match-beginning 0)
- (match-end 0) old new))))))
+ (if (if (= old ?\ )
+ (save-match-data
+ (dired-get-filename 'no-dir t))
+ t)
+ (subst-char-in-region (match-beginning 0)
+ (match-end 0) old new)))))))
(defun dired-unmark-all-files-no-query ()
"Remove all marks from all files in the Dired buffer."
"Dired by date")
(t
(concat "Dired " dired-actual-switches)))))
- ;; update mode line:
- (set-buffer-modified-p (buffer-modified-p)))
+ (force-mode-line-update))
(defun dired-sort-toggle-or-edit (&optional arg)
"Toggle between sort by date/name and refresh the dired buffer.
;; minor mode accordingly, others appear literally in the mode line.
;; With optional second arg NO-REVERT, don't refresh the listing afterwards.
(setq dired-actual-switches switches)
- (dired-sort-set-modeline)
+ (if (eq major-mode 'dired-mode) (dired-sort-set-modeline))
(or no-revert (revert-buffer)))
\f
;; To make this file smaller, the less common commands