]> git.eshelyaron.com Git - emacs.git/commitdiff
Be more precise about navigating forward/backward through Eshell prompts
authorJim Porter <jporterbugs@gmail.com>
Sat, 2 Sep 2023 21:44:33 +0000 (14:44 -0700)
committerJim Porter <jporterbugs@gmail.com>
Sat, 2 Sep 2023 22:06:22 +0000 (15:06 -0700)
* lisp/eshell/em-prompt.el (eshell-next-prompt): Make N optional.
When navigating, first move to the end of the prompt.  This makes the
subsequent navigation more predictable.
(eshell-previous-prompt): Mane N optional.

* test/lisp/eshell/em-prompt-tests.el
(em-prompt-test--with-multiline): Move to "Code" section.
(em-prompt-test/next-previous-prompt-with): Rename to...
(em-prompt-test/next-previous-prompt-1): ... this, and add additional
test cases.  Update callers.
(em-prompt-test/forward-backward-matching-input-with): Rename to...
(em-prompt-test/forward-backward-matching-input-1): ... this, and
improve existing test cases.

lisp/eshell/em-prompt.el
test/lisp/eshell/em-prompt-tests.el

index 42f8f273b52d14cb5e949406b3c7404ff5eefe9a..e334d3956e24b3ab529adffb9aad1d16b1fc8fc0 100644 (file)
@@ -172,16 +172,27 @@ negative, find the Nth next match."
   (interactive (eshell-regexp-arg "Backward input matching (regexp): "))
   (eshell-forward-matching-input regexp (- arg)))
 
-(defun eshell-next-prompt (n)
+(defun eshell-next-prompt (&optional n)
   "Move to end of Nth next prompt in the buffer."
   (interactive "p")
+  (unless n (setq n 1))
+  ;; First, move point to our starting position: the end of the
+  ;; current prompt (aka the beginning of the input), if any.  (The
+  ;; welcome message and output from commands don't count as having a
+  ;; current prompt.)
+  (pcase (get-text-property (point) 'field)
+    ('command-output)
+    ('prompt (goto-char (field-end)))
+    (_ (when-let ((match (text-property-search-backward 'field 'prompt t)))
+         (goto-char (prop-match-end match)))))
+  ;; Now, move forward/backward to our destination prompt.
   (if (natnump n)
       (while (and (> n 0)
                   (text-property-search-forward 'field 'prompt t))
         (setq n (1- n)))
     (let (match this-match)
-      ;; Don't count the current prompt.
-      (text-property-search-backward 'field 'prompt t)
+      ;; Go to the beginning of the current prompt.
+      (goto-char (field-beginning (point) t))
       (while (and (< n 0)
                   (setq this-match (text-property-search-backward
                                     'field 'prompt t)))
@@ -190,10 +201,10 @@ negative, find the Nth next match."
       (when match
         (goto-char (prop-match-end match))))))
 
-(defun eshell-previous-prompt (n)
+(defun eshell-previous-prompt (&optional n)
   "Move to end of Nth previous prompt in the buffer."
   (interactive "p")
-  (eshell-next-prompt (- n)))
+  (eshell-next-prompt (- (or n 1))))
 
 (defun eshell-skip-prompt ()
   "Skip past the text matching regexp `eshell-prompt-regexp'.
index 93bf9d84ab3ae385d6b369d26f4e2d8dd1fffe90..f6a63ac0db5af6f69750f6d48a0fd56c01a05860 100644 (file)
                            (file-name-directory (or load-file-name
                                                     default-directory))))
 
+(defmacro em-prompt-test--with-multiline (&rest body)
+  "Execute BODY with a multiline Eshell prompt."
+  `(let ((eshell-prompt-function (lambda () "multiline prompt\n$ ")))
+     ,@body))
+
 ;;; Tests:
 
 (ert-deftest em-prompt-test/field-properties ()
@@ -80,39 +85,56 @@ This tests the case when `eshell-highlight-prompt' is nil."
                 (apply #'propertize "hello\n"
                        eshell-command-output-properties)))))))
 
-(defmacro em-prompt-test--with-multiline (&rest body)
-  "Execute BODY with a multiline Eshell prompt."
-  `(let ((eshell-prompt-function (lambda () "multiline prompt\n$ ")))
-     ,@body))
-
-(defun em-prompt-test/next-previous-prompt-with ()
+(defun em-prompt-test/next-previous-prompt-1 ()
   "Helper for checking forward/backward navigation of old prompts."
   (with-temp-eshell
    (eshell-insert-command "echo one")
    (eshell-insert-command "echo two")
    (eshell-insert-command "echo three")
    (insert "echo fou")                  ; A partially-entered command.
-   ;; Go back one prompt.
-   (eshell-previous-prompt 1)
-   (should (equal (eshell-get-old-input) "echo three"))
-   ;; Go back two prompts, starting from the end of this line.
-   (end-of-line)
-   (eshell-previous-prompt 2)
-   (should (equal (eshell-get-old-input) "echo one"))
-   ;; Go forward three prompts.
-   (eshell-next-prompt 3)
-   (should (equal (eshell-get-old-input) "echo fou"))))
+   (ert-info ("Go back one prompt")
+     (eshell-previous-prompt)
+     (should (equal (point) (field-beginning)))
+     (should (equal (field-string) "echo three\n")))
+   (ert-info ("Go back two prompts, starting from the end of the input")
+     (end-of-line)
+     (eshell-previous-prompt 2)
+     (should (equal (point) (field-beginning)))
+     (should (equal (field-string) "echo one\n")))
+   (ert-info ("Go to the current prompt, starting from the end of the input")
+     (end-of-line)
+     (eshell-previous-prompt 0)
+     (should (equal (point) (field-beginning)))
+     (should (equal (field-string) "echo one\n")))
+   (ert-info ("Go forward one prompt")
+     (eshell-next-prompt)
+     (should (equal (point) (field-beginning)))
+     (should (equal (field-string) "echo two\n")))
+   (ert-info ("Go forward two prompts")
+     (eshell-next-prompt 2)
+     (should (equal (point) (field-beginning)))
+     (should (equal (field-string) "echo fou")))
+   (ert-info ("Go back one prompt, starting from the beginning of the line")
+     (forward-line 0)
+     (eshell-previous-prompt 1)
+     (should (equal (point) (field-beginning)))
+     (should (equal (field-string) "echo three\n")))
+   (ert-info ("Go back one prompt, starting from the previous prompt's output")
+     (forward-line -1)
+     (eshell-previous-prompt 1)
+     (should (equal (point) (field-beginning)))
+     (should (equal (field-string) "echo two\n")))))
 
 (ert-deftest em-prompt-test/next-previous-prompt ()
   "Check that navigating forward/backward through old prompts works correctly."
-  (em-prompt-test/next-previous-prompt-with))
+  (em-prompt-test/next-previous-prompt-1))
 
 (ert-deftest em-prompt-test/next-previous-prompt-multiline ()
   "Check old prompt forward/backward navigation for multiline prompts."
   (em-prompt-test--with-multiline
-   (em-prompt-test/next-previous-prompt-with)))
+   (em-prompt-test/next-previous-prompt-1)))
 
-(defun em-prompt-test/forward-backward-matching-input-with ()
+(defun em-prompt-test/forward-backward-matching-input-1 ()
   "Helper for checking forward/backward navigation via regexps."
   (with-temp-eshell
    (eshell-insert-command "echo one")
@@ -120,24 +142,27 @@ This tests the case when `eshell-highlight-prompt' is nil."
    (eshell-insert-command "echo two")
    (eshell-insert-command "echo three")
    (insert "echo fou")                  ; A partially-entered command.
-   ;; Go back one prompt.
-   (eshell-backward-matching-input "echo" 1)
-   (should (equal (eshell-get-old-input) "echo three"))
-   ;; Go back two prompts, starting from the end of this line.
-   (end-of-line)
-   (eshell-backward-matching-input "echo" 2)
-   (should (equal (eshell-get-old-input) "echo one"))
-   ;; Go forward three prompts.
-   (eshell-forward-matching-input "echo" 3)
-   (should (equal (eshell-get-old-input) "echo fou"))))
+   (ert-info ("Go back one prompt")
+     (eshell-backward-matching-input "echo" 1)
+     (should (equal (point) (field-beginning)))
+     (should (equal (field-string) "echo three\n")))
+   (ert-info ("Go back two prompts, starting from the end of this line")
+     (end-of-line)
+     (eshell-backward-matching-input "echo" 2)
+     (should (equal (point) (field-beginning)))
+     (should (equal (field-string) "echo one\n")))
+   (ert-info ("Go forward three prompts")
+     (eshell-forward-matching-input "echo" 3)
+     (should (equal (point) (field-beginning)))
+     (should (equal (field-string) "echo fou")))))
 
 (ert-deftest em-prompt-test/forward-backward-matching-input ()
   "Check that navigating forward/backward via regexps works correctly."
-  (em-prompt-test/forward-backward-matching-input-with))
+  (em-prompt-test/forward-backward-matching-input-1))
 
 (ert-deftest em-prompt-test/forward-backward-matching-input-multiline ()
   "Check forward/backward regexp navigation for multiline prompts."
   (em-prompt-test--with-multiline
-   (em-prompt-test/forward-backward-matching-input-with)))
+   (em-prompt-test/forward-backward-matching-input-1)))
 
 ;;; em-prompt-tests.el ends here