:type 'boolean
:group 'dired)
+(defcustom dired-free-space-program "df"
+ "*Program to get the amount of free space on a file system.
+We assume the output has the format of `df'.
+The value of this variable must be just a command name or file name;
+if you want to specify options, use `dired-free-space-args'.
+
+A value of nil disables this feature."
+ :type '(choice (string :tag "Program") (const :tag "None" nil))
+ :group 'dired)
+
+(defcustom dired-free-space-args "-Pk"
+ "*Options to use when running `dired-free-space-program'."
+ :type 'string
+ :group 'dired)
+
;;; Hook variables
(defvar dired-load-hook nil
;; "Regexp matching a marked line.
;; Important: the match ends just after the marker."
(defvar dired-re-maybe-mark "^. ")
-(defvar dired-re-dir (concat dired-re-maybe-mark dired-re-inode-size "d"))
-(defvar dired-re-sym (concat dired-re-maybe-mark dired-re-inode-size "l"))
+;; The [^:] part after "d" and "l" is to avoid confusion with the
+;; DOS/Windows-style drive letters in directory names, like in "d:/foo".
+(defvar dired-re-dir (concat dired-re-maybe-mark dired-re-inode-size "d[^:]"))
+(defvar dired-re-sym (concat dired-re-maybe-mark dired-re-inode-size "l[^:]"))
(defvar dired-re-exe;; match ls permission string of an executable file
(mapconcat (function
(lambda (x)
;; We need this to make the root dir have a header line as all
;; other subdirs have:
(goto-char (point-min))
- (dired-insert-headerline default-directory)
+ (if (not (looking-at "^ /.*:$"))
+ (dired-insert-headerline default-directory))
;; can't run dired-after-readin-hook here, it may depend on the subdir
;; alist to be OK.
)
(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))
+ (insert-directory (expand-file-name dir-or-list) switches wildcard full-p)
+ (when (and full-p dired-free-space-program)
+ (save-excursion
+ (goto-char (point-min))
+ (when (re-search-forward "total [0-9]+$" nil t)
+ (insert " free ")
+ (let ((beg (point)))
+ (call-process dired-free-space-program nil t nil
+ dired-free-space-args
+ (expand-file-name dir-or-list))
+ (goto-char beg)
+ (forward-line 1)
+ (skip-chars-forward "^ \t")
+ (forward-word 2)
+ (skip-chars-forward " \t")
+ (delete-region beg (point))
+ (forward-word 1)
+ (delete-region (point)
+ (progn (forward-line 1) (point))))))))
;; Quote certain characters, unless ls quoted them for us.
(if (not (string-match "b" dired-actual-switches))
(save-excursion
'("Flag..." . dired-flag-files-regexp))
(define-key map [menu-bar regexp mark]
'("Mark..." . dired-mark-files-regexp))
- (define-key map [menu-bar regexp mark]
+ (define-key map [menu-bar regexp mark-cont]
'("Mark Containing..." . dired-mark-files-containing-regexp))
(define-key map [menu-bar mark]
Optional arg LITERAL means to take NEWTEXT literally.
Optional arg GLOBAL means to replace all matches."
(if global
- (let ((start 0))
+ (let ((start 0) ret)
(while (string-match regexp string start)
(let ((from-end (- (length string) (match-end 0))))
- (setq string (replace-match newtext t literal string))
+ (setq ret (setq string (replace-match newtext t literal string)))
(setq start (- (length string) from-end))))
- string)
+ ret)
(if (not (string-match regexp string 0))
nil
(replace-match newtext t literal string))))
(let* ((l "\\([A-Za-z]\\|[^\0-\177]\\)")
;; In some locales, month abbreviations are as short as 2 letters,
;; and they can be padded on the right with spaces.
- (month (concat l l "+ *"))
+ ;; weiand: changed: month ends potentially with . or , or .,
+;;old (month (concat l l "+ *"))
+ (month (concat l l "+[.]?,? *"))
;; Recognize any non-ASCII character.
;; The purpose is to match a Kanji character.
(k "[^\0-\177]")
(s " ")
(yyyy "[0-9][0-9][0-9][0-9]")
(mm "[ 0-1][0-9]")
- (dd "[ 0-3][0-9]")
+;;old (dd "[ 0-3][0-9]")
+ (dd "[ 0-3][0-9][.]?")
(HH:MM "[ 0-2][0-9]:[0-5][0-9]")
(western (concat "\\(" month s dd "\\|" dd s month "\\)"
- s "\\(" HH:MM "\\|" s yyyy "\\|" yyyy s "\\)"))
+ ;; weiand: changed: year potentially unaligned
+;;old s "\\(" HH:MM "\\|" s yyyy "\\|" yyyy s "\\)"))
+ s "\\(" HH:MM "\\|" s "?" yyyy "\\|" yyyy s
+"\\)"))
(japanese (concat mm k s dd k s "\\(" s HH:MM "\\|" yyyy k "\\)")))
- ;; Require the previous column to end in a digit.
+ ;; The "[0-9]" below requires the previous column to end in a digit.
;; This avoids recognizing `1 may 1997' as a date in the line:
;; -r--r--r-- 1 may 1997 1168 Oct 19 16:49 README
- (concat "[0-9]" s "\\(" western "\\|" japanese "\\)" s))
+ ;; The ".*" below finds the last match if there are multiple matches.
+ ;; This avoids recognizing `jservice 10 1024' as a date in the line:
+ ;; drwxr-xr-x 3 jservice 10 1024 Jul 2 1997 esg-host
+ (concat ".*[0-9]" s "\\(" western "\\|" japanese "\\)" s))
"Regular expression to match up to the file name in a directory listing.
The default value is designed to recognize dates and times
regardless of the language.")
\f
;; Deleting files
+(defcustom dired-recursive-deletes nil ; Default only delete empty directories.
+ "*Decide whether recursive deletes are allowed.
+Nil means no recursive deletes.
+`always' means delete recursively without asking. This is DANGEROUS!
+`top' means ask for each directory at top level, but delete its subdirectories
+without asking.
+Anything else means ask for each directory."
+ :type '(choice :tag "Delete not empty directory"
+ (const :tag "No. Only empty directories" nil)
+ (const :tag "Ask for each directory" t)
+ (const :tag "Ask for each top directory only" top))
+ :group 'dired)
+
+;; Match anything but `.' and `..'.
+(defvar dired-re-no-dot "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")
+
+;; Delete file, possibly delete a directory and all its files.
+;; This function is usefull outside of dired. One could change it's name
+;; to e.g. recursive-delete-file and put it somewhere else.
+(defun dired-delete-file (file &optional recursive) "\
+Delete FILE or directory (possibly recursively if optional RECURSIVE is true.)
+RECURSIVE determines what to do with a non-empty directory. If RECURSIVE is:
+Nil, do not delete.
+`always', delete recursively without asking.
+`top', ask for each directory at top level.
+Anything else, ask for each sub-directory."
+ (let (files)
+ ;; This test is equivalent to
+ ;; (and (file-directory-p fn) (not (file-symlink-p fn)))
+ ;; but more efficient
+ (if (not (eq t (car (file-attributes file))))
+ (delete-file file)
+ (when (and recursive
+ (setq files
+ (directory-files file t dired-re-no-dot)) ; Not empty.
+ (or (eq recursive 'always)
+ (yes-or-no-p (format "Recursive delete of %s "
+ (dired-make-relative file)))))
+ (if (eq recursive 'top) (setq recursive 'always)) ; Don't ask again.
+ (while files ; Recursively delete (possibly asking).
+ (dired-delete-file (car files) recursive)
+ (setq files (cdr files))))
+ (delete-directory file))))
+
(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
(let (buffer-read-only)
(condition-case err
(let ((fn (car (car l))))
- ;; This test is equivalent to
- ;; (and (file-directory-p fn) (not (file-symlink-p fn)))
- ;; but more efficient
- (if (eq t (car (file-attributes fn)))
- (delete-directory fn)
- (delete-file fn))
+ (dired-delete-file fn dired-recursive-deletes)
;; if we get here, removing worked
(setq succ (1+ succ))
(message "%s of %s deletions" succ count)
(and (not (looking-at dired-re-dot))
(not (eolp)) ; empty line
(let ((fn (dired-get-filename nil t)))
- (and fn (save-excursion
- ;; For now we do it inside emacs
- ;; Grep might be better if there are a lot of files
- (message "Checking %s" fn)
- (let* ((prebuf (get-file-buffer fn)))
- (find-file fn)
+ (when (and fn (file-readable-p fn)
+ (not (file-directory-p fn)))
+ (let ((prebuf (get-file-buffer fn)))
+ (message "Checking %s" fn)
+ ;; For now we do it inside emacs
+ ;; Grep might be better if there are a lot of files
+ (if prebuf
+ (with-current-buffer prebuf
+ (save-excursion
(goto-char (point-min))
- (prog1
- (re-search-forward regexp nil t)
- (if (not prebuf) (kill-buffer nil))))
- ))))
+ (re-search-forward regexp nil t)))
+ (with-temp-buffer
+ (insert-file-contents fn)
+ (goto-char (point-min))
+ (re-search-forward regexp nil t))))
+ )))
"matching file")))
(defun dired-flag-files-regexp (regexp)
"auto save file")))
(defvar dired-garbage-files-regexp
- "\\.log$\\|\\.toc$\\|.dvi$|\\.bak$\\|\\.orig$\\|\\.rej$"
+ "\\.log$\\|\\.toc$\\|\\.dvi$\\|\\.bak$\\|\\.orig$\\|\\.rej$"
"*Regular expression to match \"garbage\" files for `dired-flag-garbage-files'.")
(defun dired-flag-garbage-files ()
(autoload 'dired-do-copy-regexp "dired-aux"
"Copy all marked files containing REGEXP to NEWNAME.
-See function `dired-rename-regexp' for more info."
+See function `dired-do-rename-regexp' for more info."
t)
(autoload 'dired-do-hardlink-regexp "dired-aux"
"Hardlink all marked files containing REGEXP to NEWNAME.
-See function `dired-rename-regexp' for more info."
+See function `dired-do-rename-regexp' for more info."
t)
(autoload 'dired-do-symlink-regexp "dired-aux"
"Symlink all marked files containing REGEXP to NEWNAME.
-See function `dired-rename-regexp' for more info."
+See function `dired-do-rename-regexp' for more info."
t)
(autoload 'dired-upcase "dired-aux"