]> code.delx.au - gnu-emacs/blobdiff - lisp/vc-dir.el
Update author email.
[gnu-emacs] / lisp / vc-dir.el
index dcb5f00c155fc19ae21bc7c4ec55f6acfc289975..d7ae86e079ec4c04f9f7b90b4f97b0f83a78f72b 100644 (file)
@@ -88,7 +88,7 @@ See `run-hooks'."
 
 (defun vc-dir-prepare-status-buffer (bname dir backend &optional create-new)
   "Find a buffer named BNAME showing DIR, or create a new one."
-  (setq dir (expand-file-name dir))
+  (setq dir (file-name-as-directory (expand-file-name dir)))
   (let*
         ;; Look for another buffer name BNAME visiting the same directory.
         ((buf (save-excursion
@@ -157,8 +157,17 @@ See `run-hooks'."
 
     (define-key map [sepopn] '("--"))
     (define-key map [qr]
-      '(menu-item "Query Replace in Files" vc-dir-query-replace-regexp
+      '(menu-item "Query Replace in Files..." vc-dir-query-replace-regexp
                  :help "Replace a string in the marked files"))
+    (define-key map [se]
+      '(menu-item "Search Files..." vc-dir-search
+                 :help "Search a regexp in the marked files"))
+    (define-key map [ires]
+      '(menu-item "Isearch Regexp Files..." vc-dir-isearch-regexp
+                 :help "Incremental search a regexp in the marked files"))
+    (define-key map [ise]
+      '(menu-item "Isearch Files..." vc-dir-isearch
+                 :help "Incremental search a string in the marked files"))
     (define-key map [open-other]
       '(menu-item "Open in other window" vc-dir-find-file-other-window
                  :help "Find the file on the current line, in another window"))
@@ -197,7 +206,7 @@ See `run-hooks'."
       '(menu-item "Register" vc-register
                  :help "Register file set into the version control system"))
     map)
-  "Menu for dispatcher status")
+  "Menu for VC dir")
 
 ;; VC backends can use this to add mode-specific menu items to
 ;; vc-dir-menu-map.
@@ -222,8 +231,9 @@ See `run-hooks'."
     (define-key map "+" 'vc-update)       ;; C-x v +
     (define-key map "l" 'vc-print-log)    ;; C-x v l
     ;; More confusing than helpful, probably
-    ;;(define-key map "R" 'vc-revert) ;; u is taken by dispatcher unmark.
-    ;;(define-key map "A" 'vc-annotate) ;; g is taken by dispatcher refresh
+    ;;(define-key map "R" 'vc-revert) ;; u is taken by vc-dir-unmark.
+    ;;(define-key map "A" 'vc-annotate) ;; g is taken by revert-buffer
+    ;;                                     bound by `special-mode'.
     ;; Marking.
     (define-key map "m" 'vc-dir-mark)
     (define-key map "M" 'vc-dir-mark-all-files)
@@ -250,7 +260,10 @@ See `run-hooks'."
     (define-key map [down-mouse-3] 'vc-dir-menu)
     (define-key map [mouse-2] 'vc-dir-toggle-mark)
     (define-key map "x" 'vc-dir-hide-up-to-date)
+    (define-key map "S" 'vc-dir-search) ;; FIXME: Maybe use A like dired?
     (define-key map "Q" 'vc-dir-query-replace-regexp)
+    (define-key map (kbd "M-s a C-s")   'vc-dir-isearch)
+    (define-key map (kbd "M-s a M-C-s") 'vc-dir-isearch-regexp)
 
     ;; Hook up the menu.
     (define-key map [menu-bar vc-dir-mode]
@@ -273,7 +286,7 @@ If `body' uses `event', it should be a variable,
          ,@body))))
 
 (defun vc-dir-menu (e)
-  "Popup the dispatcher status menu."
+  "Popup the VC dir menu."
   (interactive "e")
   (vc-at-event e (popup-menu vc-dir-menu-map e)))
 
@@ -679,8 +692,29 @@ that share the same state."
   (interactive)
   (find-file-other-window (vc-dir-current-file)))
 
+(defun vc-dir-isearch ()
+  "Search for a string through all marked buffers using Isearch."
+  (interactive)
+  (multi-isearch-files
+   (mapcar 'car (vc-dir-marked-only-files-and-states))))
+
+(defun vc-dir-isearch-regexp ()
+  "Search for a regexp through all marked buffers using Isearch."
+  (interactive)
+  (multi-isearch-files-regexp
+   (mapcar 'car (vc-dir-marked-only-files-and-states))))
+
+(defun vc-dir-search (regexp)
+  "Search through all marked files for a match for REGEXP.
+For marked directories, use the files displayed from those directories.
+Stops when a match is found.
+To continue searching for next match, use command \\[tags-loop-continue]."
+  (interactive "sSearch marked files (regexp): ")
+  (tags-search regexp '(mapcar 'car (vc-dir-marked-only-files-and-states))))
+
 (defun vc-dir-query-replace-regexp (from to &optional delimited)
   "Do `query-replace-regexp' of FROM with TO, on all marked files.
+For marked directories, use the files displayed from those directories.
 If a directory is marked, then use the files displayed for that directory.
 Third arg DELIMITED (prefix arg) means replace only word-delimited matches.
 If you exit (\\[keyboard-quit], RET or q), you can resume the query replace
@@ -743,7 +777,7 @@ child files."
                    result)
              (setq crt (ewoc-next vc-ewoc crt)))
          (setq crt (ewoc-next vc-ewoc crt)))))
-    result))
+    (nreverse result)))
 
 (defun vc-dir-child-files-and-states ()
   "Return the list of conses (FILE . STATE) for child files of the current entry if it's a directory.
@@ -768,10 +802,15 @@ If it is a file, return the corresponding cons for the file itself."
       (push
        (cons (expand-file-name (vc-dir-fileinfo->name crt-data))
             (vc-dir-fileinfo->state crt-data)) result))
-    result))
+    (nreverse result)))
 
 (defun vc-dir-recompute-file-state (fname def-dir)
   (let* ((file-short (file-relative-name fname def-dir))
+        (remove-me-when-CVS-works
+         (when (eq vc-dir-backend 'CVS)
+           ;; FIXME: Warning: UGLY HACK.  The CVS backend caches the state
+           ;; info, this forces the backend to update it.
+           (vc-call-backend vc-dir-backend 'registered fname)))
         (state (vc-call-backend vc-dir-backend 'state fname))
         (extra (vc-call-backend vc-dir-backend
                                 'status-fileinfo-extra fname)))
@@ -833,7 +872,7 @@ If it is a file, return the corresponding cons for the file itself."
 (defvar use-vc-backend)  ;; dynamically bound
 
 (define-derived-mode vc-dir-mode special-mode "VC dir"
-  "Major mode for dispatcher directory buffers.
+  "Major mode for VC directory buffers.
 Marking/Unmarking key bindings and actions:
 m - marks a file/directory or if the region is active, mark all the files
      in region.
@@ -851,6 +890,19 @@ U - if the cursor is on a file: unmark all the files with the same state
   - if the cursor is on a directory: unmark all child files
   - with a prefix argument: unmark all files
 
+VC commands
+VC commands in the `C-x v' can be used, they act on the marked
+entries, or on the current entry if nothing is marked.
+
+Search & Replace
+S - searches the marked files
+Q - does a query replace on the marked files
+M-s a C-s - does an isearch on the marked files
+M-s a C-M-s - does a regexp isearch on the marked files
+If nothing is marked, these commands act on the current entry.
+When a directory is current or marked, the Search & Replace
+commands act on the files in those directories displayed in the
+*vc-dir* buffer.
 
 \\{vc-dir-mode-map}"
   (set (make-local-variable 'vc-dir-backend) use-vc-backend)
@@ -860,9 +912,7 @@ U - if the cursor is on a file: unmark all the files with the same state
   (let ((buffer-read-only nil))
     (erase-buffer)
     (set (make-local-variable 'vc-dir-process-buffer) nil)
-    (set (make-local-variable 'vc-ewoc)
-        (ewoc-create #'vc-dir-status-printer
-                     (vc-dir-headers vc-dir-backend default-directory)))
+    (set (make-local-variable 'vc-ewoc) (ewoc-create #'vc-dir-status-printer))
     (set (make-local-variable 'revert-buffer-function)
         'vc-dir-revert-buffer-function)
     (set (make-local-variable 'list-buffers-directory)
@@ -955,8 +1005,10 @@ Throw an error if another update process is in progress."
       (unless (buffer-live-p vc-dir-process-buffer)
         (setq vc-dir-process-buffer
               (generate-new-buffer (format " *VC-%s* tmp status" backend))))
-      ;; set the needs-update flag on all entries
-      (ewoc-map (lambda (info) (setf (vc-dir-fileinfo->needs-update info) t) nil)
+      ;; set the needs-update flag on all non-directory entries
+      (ewoc-map (lambda (info)
+                 (unless (vc-dir-fileinfo->directory info)
+                   (setf (vc-dir-fileinfo->needs-update info) t) nil))
                 vc-ewoc)
       (lexical-let ((buffer (current-buffer)))
         (with-current-buffer vc-dir-process-buffer
@@ -978,7 +1030,8 @@ Throw an error if another update process is in progress."
                        (vc-dir-refresh-files
                         (mapcar 'vc-dir-fileinfo->name remaining)
                         'up-to-date)
-                     (setq mode-line-process nil))))))))))))
+                     (setq mode-line-process nil)))))))))
+      (ewoc-set-hf vc-ewoc (vc-dir-headers backend def-dir) ""))))
 
 (defun vc-dir-show-fileentry (file)
   "Insert an entry for a specific file into the current *VC-dir* listing.
@@ -1053,9 +1106,14 @@ Optional second argument BACKEND specifies the VC backend to use.
 Interactively, a prefix argument means to ask for the backend."
   (interactive
    (list
-    (read-file-name "VC status for directory: "
-                   default-directory default-directory t
-                   nil #'file-directory-p)
+    ;; When you hit C-x v d in a visited VC file,
+    ;; the *vc-dir* buffer visits the directory under its truename;
+    ;; therefore it makes sense to always do that.
+    ;; Otherwise if you do C-x v d -> C-x C-f -> C-c v d
+    ;; you may get a new *vc-dir* buffer, different from the original
+    (file-truename (read-file-name "VC status for directory: "
+                                   default-directory default-directory t
+                                   nil #'file-directory-p))
     (if current-prefix-arg
        (intern
         (completing-read