master 5e28bcb2d8f: Improve vc-dir-next-* commands (bug#81248)

Stephen Berman via Mailing list for Emacs changes <[email protected]>
Newsgroups gmane.emacs.diffs
Message-ID <[email protected]>
branch: master
commit 5e28bcb2d8fc7f7ae3d66868ddfe6d05e15b4bfe
Author: Stephen Berman <[email protected]>
Commit: Stephen Berman <[email protected]>

    Improve vc-dir-next-* commands (bug#81248)
    
    * lisp/vc/vc-dir.el (vc-dir--before-dotname-p): New function.
    (vc-dir-next-line, vc-dir-next-directory): Use it to enable using
    these commands to move point to the VC Dir root directory entry "./".
    
    * test/lisp/vc/vc-tests/vc-test-misc.el
    (vc-test-vc-dir-next/previous): New test.
---
 lisp/vc/vc-dir.el                     | 21 ++++++++++--
 test/lisp/vc/vc-tests/vc-test-misc.el | 60 +++++++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+), 2 deletions(-)

diff --git a/lisp/vc/vc-dir.el b/lisp/vc/vc-dir.el
index 57a7488825e..596c2fe7362 100644
--- a/lisp/vc/vc-dir.el
+++ b/lisp/vc/vc-dir.el
@@ -710,12 +710,27 @@ information."
       t)
     t))
 
+;; By design the vc-dir-next-* commands move point from the current
+;; entry to the next one of the same type.  But for technical reasons
+;; any buffer position before the "./" entry is part of that entry, so
+;; there is no previous entry from which to move via vc-dir-next-* to
+;; this entry.  But from the UX perspective such movement is natural, so
+;; we enable it by making these commands move point directly to the "./"
+;; entry (instead of the "next" one) whenever point is before this
+;; entry, as determined by the following function.  See bug#81248 for
+;; further details.
+(defun vc-dir--before-dotname-p ()
+  "Return non-nil if point is before the \"./\" entry."
+  (< (point) (ewoc-location (ewoc-nth vc-ewoc 0))))
+
 (defun vc-dir-next-line (arg)
   "Go to the next line.
 With prefix argument ARG, move that many lines."
   (interactive "p")
   (with-no-warnings
-    (ewoc-goto-next vc-ewoc arg)
+    (if (vc-dir--before-dotname-p)
+        (ewoc-goto-node vc-ewoc (ewoc-nth vc-ewoc 0))
+      (ewoc-goto-next vc-ewoc arg))
     (vc-dir-move-to-goal-column)))
 
 (defun vc-dir-previous-line (arg)
@@ -732,7 +747,9 @@ With prefix argument ARG, move that many lines."
     (if
 	(catch 'foundit
 	  (while t
-	    (let* ((next (ewoc-next vc-ewoc (ewoc-locate vc-ewoc))))
+	    (let* ((next (if (vc-dir--before-dotname-p)
+                             (ewoc-nth vc-ewoc 0)
+                           (ewoc-next vc-ewoc (ewoc-locate vc-ewoc)))))
 	      (cond ((not next)
 		     (throw 'foundit t))
 		    (t
diff --git a/test/lisp/vc/vc-tests/vc-test-misc.el b/test/lisp/vc/vc-tests/vc-test-misc.el
index 066c49df324..83a69867220 100644
--- a/test/lisp/vc/vc-tests/vc-test-misc.el
+++ b/test/lisp/vc/vc-tests/vc-test-misc.el
@@ -298,5 +298,65 @@ See bug#80803 and bug#80967."
                 (should (equal (vc-dir-fileinfo->state data)
                                'edited))))))))))
 
+(ert-deftest vc-test-vc-dir-next/previous ()
+  "Test navigating with `vc-dir-{next,previous}-{line,directory}'."
+  (skip-unless (executable-find vc-git-program))
+  (vc-test--with-author-identity 'Git
+    (let ((vc-handled-backends '(Git)))
+      (ert-with-temp-directory tempdir
+        (let ((default-directory tempdir)
+              (n 0)
+              vc-dir-buf)
+          (vc-test--create-repo-function 'Git)
+          (dolist (file '("file01" "dir1/file11"))
+            (make-empty-file file t))
+          (vc-dir default-directory 'Git)
+          (while (vc-dir-busy) (sit-for 0.05))
+          (setq vc-dir-buf (current-buffer))
+          (should (bobp))
+          (while (vc-dir--before-dotname-p)
+            (vc-dir-next-line 1)
+            (should (and (looking-at "\\./$") (looking-back "^ +")))
+            (incf n 1)
+            (goto-char (point-min))
+            (forward-line n))
+          (vc-dir-next-line 1)
+          (should (looking-at "file01$"))
+          (vc-dir-next-line 1)
+          (should (looking-at "dir1/$"))
+          (vc-dir-next-line 1)
+          (should (looking-at "dir1/file11$"))
+          (vc-dir-next-line 1)
+          (should (looking-at "^$"))
+          (let ((end (point)))
+            (vc-dir-next-line 1)
+            (should (equal (point) end)))
+          (goto-char (point-min))
+          (vc-dir-next-directory)
+          (should (and (looking-at "\\./$") (looking-back "^ +")))
+          (vc-dir-next-directory)
+          (should (and (looking-at "dir1/$") (looking-back "^ +")))
+          (vc-dir-next-directory)
+          (should (and (looking-at "dir1/$") (looking-back "^ +")))
+          (goto-char (point-max))
+          (vc-dir-previous-line 1)
+          (should (looking-at "dir1/file11$"))
+          (vc-dir-previous-line 1)
+          (should (and (looking-at "dir1/$") (looking-back "^ +")))
+          (vc-dir-previous-line 1)
+          (should (looking-at "file01$"))
+          (vc-dir-previous-line 1)
+          (should (and (looking-at "\\./$") (looking-back "^ +")))
+          (vc-dir-previous-line 1)
+          (should (and (looking-at "\\./$") (looking-back "^ +")))
+          (goto-char (point-max))
+          (vc-dir-previous-directory)
+          (should (and (looking-at "dir1/$") (looking-back "^ +")))
+          (vc-dir-previous-directory)
+          (should (and (looking-at "\\./$") (looking-back "^ +")))
+          (vc-dir-previous-directory)
+          (should (and (looking-at "\\./$") (looking-back "^ +")))
+          (kill-buffer vc-dir-buf))))))
+
 (provide 'vc-test-misc)
 ;;; vc-test-misc.el ends here
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.