]> code.delx.au - gnu-emacs/blobdiff - lisp/vc-dir.el
* vc-dir.el (vc-dir-update): Remove debug helper.
[gnu-emacs] / lisp / vc-dir.el
index 249ceec75f9a43f5bc180d7bc7a903342e736349..c87366b8294d0feb3b4341a320a82636d7728e75 100644 (file)
@@ -326,8 +326,9 @@ If BODY uses EVENT, it should be a variable,
     (or (vc-dir-fileinfo->directory data)
        ;; Otherwise compute it from the file name.
        (file-name-directory
-        (expand-file-name
-         (vc-dir-fileinfo->name data))))))
+        (directory-file-name
+         (expand-file-name
+          (vc-dir-fileinfo->name data)))))))
 
 (defun vc-dir-update (entries buffer &optional noinsert)
   "Update BUFFER's ewoc from the list of ENTRIES.
@@ -343,26 +344,29 @@ If NOINSERT, ignore elements on ENTRIES which are not in the ewoc."
          ;; names too many times
          (sort entries
                (lambda (entry1 entry2)
-                 (let ((dir1 (file-name-directory (expand-file-name (car entry1))))
-                       (dir2 (file-name-directory (expand-file-name (car entry2)))))
+                 (let ((dir1 (file-name-directory
+                               (directory-file-name (expand-file-name (car entry1)))))
+                       (dir2 (file-name-directory
+                              (directory-file-name (expand-file-name (car entry2))))))
                    (cond
                     ((string< dir1 dir2) t)
                     ((not (string= dir1 dir2)) nil)
                     ((string< (car entry1) (car entry2))))))))
     ;; Insert directory entries in the right places.
     (let ((entry (car entries))
-         (node (ewoc-nth vc-ewoc 0)))
+         (node (ewoc-nth vc-ewoc 0))
+         (dotname (file-relative-name default-directory)))
       ;; Insert . if it is not present.
       (unless node
-       (let ((rd (file-relative-name default-directory)))
-         (ewoc-enter-last
-          vc-ewoc (vc-dir-create-fileinfo
-                   rd nil nil nil (expand-file-name default-directory))))
+       (ewoc-enter-last
+        vc-ewoc (vc-dir-create-fileinfo
+                 dotname nil nil nil (expand-file-name default-directory)))
        (setq node (ewoc-nth vc-ewoc 0)))
 
       (while (and entry node)
        (let* ((entryfile (car entry))
-              (entrydir (file-name-directory (expand-file-name entryfile)))
+              (entrydir (file-name-directory (directory-file-name
+                                              (expand-file-name entryfile))))
               (nodedir (vc-dir-node-directory node)))
          (cond
           ;; First try to find the directory.
@@ -372,6 +376,8 @@ If NOINSERT, ignore elements on ENTRIES which are not in the ewoc."
            ;; Found the directory, find the place for the file name.
            (let ((nodefile (vc-dir-fileinfo->name (ewoc-data node))))
              (cond
+              ((string= nodefile dotname)
+               (setq node (ewoc-next vc-ewoc node)))
               ((string-lessp nodefile entryfile)
                (setq node (ewoc-next vc-ewoc node)))
               ((string-equal nodefile entryfile)
@@ -404,7 +410,8 @@ If NOINSERT, ignore elements on ENTRIES which are not in the ewoc."
       (unless (or node noinsert)
        (let ((lastdir (vc-dir-node-directory (ewoc-nth vc-ewoc -1))))
          (dolist (entry entries)
-           (let ((entrydir (file-name-directory (expand-file-name (car entry)))))
+           (let ((entrydir (file-name-directory
+                            (directory-file-name (expand-file-name (car entry))))))
              ;; Insert a directory node if needed.
              (unless (string-equal lastdir entrydir)
                (setq lastdir entrydir)
@@ -689,9 +696,10 @@ that share the same state."
   (interactive)
   (find-file (vc-dir-current-file)))
 
-(defun vc-dir-find-file-other-window ()
+(defun vc-dir-find-file-other-window (&optional event)
   "Find the file on the current line, in another window."
-  (interactive)
+  (interactive (list last-nonmenu-event))
+  (if event (posn-set-point (event-end event)))
   (find-file-other-window (vc-dir-current-file)))
 
 (defun vc-dir-isearch ()
@@ -863,9 +871,10 @@ If it is a file, return the corresponding cons for the file itself."
            (when (vc-string-prefix-p ddir file)
              (if (file-directory-p file)
                  (vc-dir-resync-directory-files file)
-               (vc-dir-update
-                (list (vc-dir-recompute-file-state file ddir))
-                status-buf)))))))
+               (let ((state (vc-dir-recompute-file-state file ddir)))
+                 (vc-dir-update
+                  (list state)
+                  status-buf (eq (cadr state) 'up-to-date)))))))))
     ;; We didn't find any vc-dir buffers, remove the hook, it is
     ;; not needed.
     (unless found-vc-dir-buf
@@ -876,13 +885,13 @@ If it is a file, return the corresponding cons for the file itself."
 (define-derived-mode vc-dir-mode special-mode "VC dir"
   "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.
+m - mark a file/directory
+  - if the region is active, mark all the files in region.
     Restrictions: - a file cannot be marked if any parent directory is marked
                   - a directory cannot be marked if any child file or
                     directory is marked
-u - marks a file/directory or if the region is active, unmark all the files
-     in region.
+u - unmark a file/directory
+  - if the region is active, unmark all the files in region.
 M - if the cursor is on a file: mark all the files with the same state as
       the current file
   - if the cursor is on a directory: mark all child files
@@ -891,10 +900,12 @@ U - if the cursor is on a file: unmark all the files with the same state
       as the current file
   - if the cursor is on a directory: unmark all child files
   - with a prefix argument: unmark all files
+mouse-2  - toggles the mark state
 
 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.
+VC commands in the `C-x v' prefix can be used.
+VC commands act on the marked entries.  If nothing is marked, VC
+commands act on the current entry.
 
 Search & Replace
 S - searches the marked files
@@ -903,8 +914,8 @@ 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.
+commands act on the child files of that directory that are displayed in
+the *vc-dir* buffer.
 
 \\{vc-dir-mode-map}"
   (set (make-local-variable 'vc-dir-backend) use-vc-backend)
@@ -1096,7 +1107,7 @@ outside of VC) and one wants to do some operation on it."
       ;; state to decide which operation to perform.
       (dolist (crt (cdr only-files-list))
        (unless (vc-compatible-state (cdr crt) state)
-         (error "%s:%s clashes with %s:%s"
+         (error "When applying VC operations to multiple files, the files are required\nto  be in similar VC states.\n%s in state %s clashes with %s in state %s"
                 (car crt) (cdr crt) (caar only-files-list) state)))
       (setq only-files-list (mapcar 'car only-files-list))
       (when (and state (not (eq state 'unregistered)))
@@ -1105,9 +1116,22 @@ outside of VC) and one wants to do some operation on it."
 
 ;;;###autoload
 (defun vc-dir (dir &optional backend)
-  "Show the VC status for DIR.
+  "Show the VC status for \"interesting\" files in and below DIR.
+This allows you to mark files and perform VC operations on them.
+The list omits files which are up to date, with no changes in your copy
+or the repository, if there is nothing in particular to say about them.
+
+Preparing the list of file status takes time; when the buffer
+first appears, it has only the first few lines of summary information.
+The file lines appear later.
+
 Optional second argument BACKEND specifies the VC backend to use.
-Interactively, a prefix argument means to ask for the backend."
+Interactively, a prefix argument means to ask for the backend.
+
+These are the commands available for use in the file status buffer:
+
+\\<vc-dir-mode-map>"
+
   (interactive
    (list
     ;; When you hit C-x v d in a visited VC file,
@@ -1143,9 +1167,18 @@ Interactively, a prefix argument means to ask for the backend."
    (propertize "Please add backend specific headers here.  It's easy!"
               'face 'font-lock-warning-face)))
 
+(defvar vc-dir-filename-mouse-map
+   (let ((map (make-sparse-keymap)))
+     (define-key map [mouse-2] 'vc-dir-find-file-other-window)
+    map)
+  "Local keymap for visiting a file.")
+
 (defun vc-default-dir-printer (backend fileentry)
   "Pretty print FILEENTRY."
   ;; If you change the layout here, change vc-dir-move-to-goal-column.
+  ;; VC backends can implement backend specific versions of this
+  ;; function.  Changes here might need to be reflected in the
+  ;; vc-BACKEND-dir-printer functions.
   (let* ((isdir (vc-dir-fileinfo->directory fileentry))
        (state (if isdir "" (vc-dir-fileinfo->state fileentry)))
        (filename (vc-dir-fileinfo->name fileentry)))
@@ -1169,7 +1202,8 @@ Interactively, a prefix argument means to ask for the backend."
       (if isdir
          "Directory\nVC operations can be applied to it\nmouse-3: Pop-up menu"
        "File\nmouse-3: Pop-up menu")
-      'mouse-face 'highlight))))
+      'mouse-face 'highlight
+      'keymap vc-dir-filename-mouse-map))))
 
 (defun vc-default-extra-status-menu (backend)
   nil)