]> code.delx.au - gnu-emacs/blobdiff - lisp/dired.el
*** empty log message ***
[gnu-emacs] / lisp / dired.el
index a9afa3e11e37f8adef239eac62c9b18fc21f8a6b..895c95fc78e5f4076ee530bed4999831abc0fea8 100644 (file)
@@ -152,6 +152,21 @@ The target is used in the prompt for file copy, rename etc."
   :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
@@ -217,8 +232,10 @@ directory name and the cdr is the actual files to list.")
 ;; "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)
@@ -656,7 +673,25 @@ If DIRNAME is already in a dired buffer, that buffer is used without refresh."
         (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
@@ -989,7 +1024,7 @@ If DIRNAME is already in a dired buffer, that buffer is used without refresh."
       '("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]
@@ -1315,12 +1350,12 @@ 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))
+      (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))))
@@ -1356,7 +1391,9 @@ DIR must be a directory name, not a file name."
   (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]")
@@ -1364,15 +1401,22 @@ DIR must be a directory name, not a file name."
         (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.")
@@ -1775,6 +1819,50 @@ Optional argument means return a file name relative to `default-directory'."
 \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
@@ -1830,12 +1918,7 @@ if there are no flagged files."
              (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)
@@ -2165,19 +2248,21 @@ A prefix argument means to unmark them instead.
      (and (not (looking-at dired-re-dot))
          (not (eolp))                  ; empty line
          (let ((fn (dired-get-filename nil t)))
-           (and 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))
-                             (re-search-forward regexp nil t)))
-                       (with-temp-buffer
-                         (insert-buffer-contents fn)
-                         (goto-char (point-min))
-                         (re-search-forward regexp nil t))))
+           (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))
+                       (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")))
 
@@ -2596,17 +2681,17 @@ With a zero prefix arg, renaming by regexp affects the complete
 
 (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"