]> code.delx.au - gnu-emacs/blobdiff - lisp/dired.el
Require CL when compiling.
[gnu-emacs] / lisp / dired.el
index 872eef3eacd7063d8674dd320cca74859e0ad349..5308cdb7e1a4588437362f7c0b186fdfa0622e88 100644 (file)
@@ -33,8 +33,6 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'dired-aux))
-
 ;;; Customizable variables
 
 (defgroup dired nil
@@ -336,66 +334,65 @@ Subexpression 2 must end right before the \\n or \\r.")
        (and (> count 0) count))))
 
 (defmacro dired-map-over-marks (body arg &optional show-progress)
-;;  "Macro: Perform BODY with point somewhere on each marked line
-;;and return a list of BODY's results.
-;;If no marked file could be found, execute BODY on the current line.
-;;  If ARG is an integer, use the next ARG (or previous -ARG, if ARG<0)
-;;  files instead of the marked files.
-;;  In that case point is dragged along.  This is so that commands on
-;;  the next ARG (instead of the marked) files can be chained easily.
-;;  If ARG is otherwise non-nil, use current file instead.
-;;If optional third arg SHOW-PROGRESS evaluates to non-nil,
-;;   redisplay the dired buffer after each file is processed.
-;;No guarantee is made about the position on the marked line.
-;;  BODY must ensure this itself if it depends on this.
-;;Search starts at the beginning of the buffer, thus the car of the list
-;;  corresponds to the line nearest to the buffer's bottom.  This
-;;  is also true for (positive and negative) integer values of ARG.
-;;BODY should not be too long as it is expanded four times."
-;;
-;;Warning: BODY must not add new lines before point - this may cause an
-;;endless loop.
-;;This warning should not apply any longer, sk  2-Sep-1991 14:10.
-  (` (prog1
-        (let (buffer-read-only case-fold-search found results)
-          (if (, arg)
-              (if (integerp (, arg))
-                  (progn;; no save-excursion, want to move point.
-                    (dired-repeat-over-lines
-                     (, arg)
-                     (function (lambda ()
-                                 (if (, show-progress) (sit-for 0))
-                                 (setq results (cons (, body) results)))))
-                    (if (< (, arg) 0)
-                        (nreverse results)
-                      results))
-                ;; non-nil, non-integer ARG means use current file:
-                (list (, body)))
-            (let ((regexp (dired-marker-regexp)) next-position)
-              (save-excursion
-                (goto-char (point-min))
-                ;; remember position of next marked file before BODY
-                ;; can insert lines before the just found file,
-                ;; confusing us by finding the same marked file again
-                ;; and again and...
+  "Eval BODY with point on each marked line.  Return a list of BODY's results.
+If no marked file could be found, execute BODY on the current line.
+  If ARG is an integer, use the next ARG (or previous -ARG, if ARG<0)
+  files instead of the marked files.
+  In that case point is dragged along.  This is so that commands on
+  the next ARG (instead of the marked) files can be chained easily.
+  If ARG is otherwise non-nil, use current file instead.
+If optional third arg SHOW-PROGRESS evaluates to non-nil,
+  redisplay the dired buffer after each file is processed.
+No guarantee is made about the position on the marked line.
+  BODY must ensure this itself if it depends on this.
+Search starts at the beginning of the buffer, thus the car of the list
+  corresponds to the line nearest to the buffer's bottom.  This
+  is also true for (positive and negative) integer values of ARG.
+BODY should not be too long as it is expanded four times."
+  ;;
+  ;;Warning: BODY must not add new lines before point - this may cause an
+  ;;endless loop.
+  ;;This warning should not apply any longer, sk  2-Sep-1991 14:10.
+  `(prog1
+       (let (buffer-read-only case-fold-search found results)
+        (if ,arg
+            (if (integerp ,arg)
+                (progn ;; no save-excursion, want to move point.
+                  (dired-repeat-over-lines
+                   ,arg
+                   (function (lambda ()
+                               (if ,show-progress (sit-for 0))
+                               (setq results (cons ,body results)))))
+                  (if (< ,arg 0)
+                      (nreverse results)
+                    results))
+              ;; non-nil, non-integer ARG means use current file:
+              (list ,body))
+          (let ((regexp (dired-marker-regexp)) next-position)
+            (save-excursion
+              (goto-char (point-min))
+              ;; remember position of next marked file before BODY
+              ;; can insert lines before the just found file,
+              ;; confusing us by finding the same marked file again
+              ;; and again and...
+              (setq next-position (and (re-search-forward regexp nil t)
+                                       (point-marker))
+                    found (not (null next-position)))
+              (while next-position
+                (goto-char next-position)
+                (if ,show-progress (sit-for 0))
+                (setq results (cons ,body results))
+                ;; move after last match
+                (goto-char next-position)
+                (forward-line 1)
+                (set-marker next-position nil)
                 (setq next-position (and (re-search-forward regexp nil t)
-                                         (point-marker))
-                      found (not (null next-position)))
-                (while next-position
-                  (goto-char next-position)
-                  (if (, show-progress) (sit-for 0))
-                  (setq results (cons (, body) results))
-                  ;; move after last match
-                  (goto-char next-position)
-                  (forward-line 1)
-                  (set-marker next-position nil)
-                  (setq next-position (and (re-search-forward regexp nil t)
-                                           (point-marker)))))
-              (if found
-                  results
-                (list (, body))))))
-       ;; save-excursion loses, again
-       (dired-move-to-filename))))
+                                         (point-marker)))))
+            (if found
+                results
+              (list ,body)))))
+     ;; save-excursion loses, again
+     (dired-move-to-filename)))
 
 (defun dired-get-marked-files (&optional localp arg)
   "Return the marked files' names as list of strings.
@@ -603,7 +600,8 @@ If DIRNAME is already in a dired buffer, that buffer is used without refresh."
   ;; Also, we can run this hook which may want to modify the switches
   ;; based on default-directory, e.g. with ange-ftp to a SysV host
   ;; where ls won't understand -Al switches.
-  (let (dirname)
+  (let (dirname
+       (indent-tabs-mode nil))
     (if (consp dir-or-list)
        (setq dirname (car dir-or-list))
       (setq dirname dir-or-list))
@@ -1766,7 +1764,13 @@ Returns the new value of the alist."
   (save-excursion
     (let ((count 0)
          (buffer-read-only nil)
-         new-dir-name)
+         new-dir-name
+         (R-ftp-base-dir-regex
+          ;; Used to expand subdirectory names correctly in recursive
+          ;; ange-ftp listings.
+          (and (string-match "R" dired-actual-switches)
+               (string-match "\\`/.*:\\(/.*\\)" default-directory)
+               (concat "\\`" (match-string 1 default-directory)))))
       (goto-char (point-min))
       (setq dired-subdir-alist nil)
       (while (and (re-search-forward dired-subdir-regexp nil t)
@@ -1780,7 +1784,15 @@ Returns the new value of the alist."
        (save-excursion
          (goto-char (match-beginning 1))
          (setq new-dir-name
-               (expand-file-name (buffer-substring (point) (match-end 1))))
+               (buffer-substring-no-properties (point) (match-end 1))
+               new-dir-name
+               (save-match-data
+                 (if (and R-ftp-base-dir-regex
+                          (not (string= new-dir-name default-directory))
+                          (string-match R-ftp-base-dir-regex new-dir-name))
+                     (concat default-directory
+                             (substring new-dir-name (match-end 0)))
+                   (expand-file-name new-dir-name))))
          (delete-region (point) (match-end 1))
          (insert new-dir-name))
        (setq count (1+ count))
@@ -2108,22 +2120,21 @@ Command symbols are `byte-compile', `chgrp', `chmod', `chown', `compress',
 `uncompress'.")
 
 (defun dired-mark-pop-up (bufname op-symbol files function &rest args)
-  ;;"Args BUFNAME OP-SYMBOL FILES FUNCTION &rest ARGS.
-  ;;Return FUNCTION's result on ARGS after popping up a window (in a buffer
-  ;;named BUFNAME, nil gives \" *Marked Files*\") showing the marked
-  ;;files.  Uses function `dired-pop-to-buffer' to do that.
 ;; FUNCTION should not manipulate files.
 ;; It should only read input (an argument or confirmation).
-  ;;The window is not shown if there is just one file or
 ;; OP-SYMBOL is a member of the list in `dired-no-confirm'.
-  ;;FILES is the list of marked files."
+  "Args BUFNAME OP-SYMBOL FILES FUNCTION &rest ARGS.
+Return FUNCTION's result on ARGS after popping up a window (in a buffer
+named BUFNAME, nil gives \" *Marked Files*\") showing the marked
+files.  Uses function `dired-pop-to-buffer' to do that.
+ FUNCTION should not manipulate files.
+ It should only read input (an argument or confirmation).
+The window is not shown if there is just one file or
+ OP-SYMBOL is a member of the list in `dired-no-confirm'.
+FILES is the list of marked files."
   (or bufname (setq bufname  " *Marked Files*"))
   (if (or (eq dired-no-confirm t)
          (memq op-symbol dired-no-confirm)
          (= (length files) 1))
       (apply function args)
-    (save-excursion
-      (set-buffer (get-buffer-create bufname))
+    (with-current-buffer (get-buffer-create bufname)
       (erase-buffer)
       (dired-format-columns-of-files files)
       (remove-text-properties (point-min) (point-max) '(mouse-face)))
@@ -2634,9 +2645,45 @@ With a prefix argument you can edit the current listing switches instead."
   ;; `dired-sort-by-date-regexp' or `dired-sort-by-name-regexp' set the
   ;; minor mode accordingly, others appear literally in the mode line.
   ;; With optional second arg NO-REVERT, don't refresh the listing afterwards.
+  (dired-sort-R-check switches)
   (setq dired-actual-switches switches)
   (if (eq major-mode 'dired-mode) (dired-sort-set-modeline))
   (or no-revert (revert-buffer)))
+
+(make-variable-buffer-local
+ (defvar dired-subdir-alist-pre-R nil
+   "Value of `dired-subdir-alist' before -R switch added."))
+
+(defun dired-sort-R-check (switches)
+  "Additional processing of -R in ls option string SWITCHES.
+Saves `dired-subdir-alist' when R is set and restores saved value
+minus any directories explicitly deleted when R is cleared.
+To be called first in body of `dired-sort-other', etc."
+  (cond
+   ((and (string-match "R" switches)
+        (not (string-match "R" dired-actual-switches)))
+    ;; Adding -R to ls switches -- save `dired-subdir-alist':
+    (setq dired-subdir-alist-pre-R dired-subdir-alist))
+   ((and (string-match "R" dired-actual-switches)
+        (not (string-match "R" switches)))
+    ;; Deleting -R from ls switches -- revert to pre-R subdirs
+    ;; that are still present:
+    (setq dired-subdir-alist
+         (if dired-subdir-alist-pre-R
+             (let (subdirs)
+               (while dired-subdir-alist-pre-R
+                 (if (assoc (caar dired-subdir-alist-pre-R)
+                            dired-subdir-alist)
+                     ;; subdir still present...
+                     (setq subdirs
+                           (cons (car dired-subdir-alist-pre-R)
+                                 subdirs)))
+                 (setq dired-subdir-alist-pre-R
+                       (cdr dired-subdir-alist-pre-R)))
+               (reverse subdirs))
+           ;; No pre-R subdir alist, so revert to main directory
+           ;; listing:
+           (list (car (reverse dired-subdir-alist))))))))
 \f
 ;; To make this file smaller, the less common commands
 ;; go in a separate file.  But autoload them here