aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Dalziel <tom_dl@hotmail.com>2020-10-10 00:23:33 +0100
committerTom Dalziel <tom_dl@hotmail.com>2021-02-14 17:12:31 +0000
commit0febaddaf0e945f878184b58be2ece9293390ab0 (patch)
tree2dd39724f556472e73c3c3ebf37f768ef2cbcfbc
parentcc9d6886b418389752a0591b9fcb270e83234cf9 (diff)
Add next+previous mark navigation and keybindings
-rw-r--r--evil-commands.el63
-rw-r--r--evil-maps.el4
-rw-r--r--evil-tests.el38
3 files changed, 105 insertions, 0 deletions
diff --git a/evil-commands.el b/evil-commands.el
index 073ffc5..f7911da 100644
--- a/evil-commands.el
+++ b/evil-commands.el
@@ -672,6 +672,69 @@ and jump to the corresponding one."
(evil-up-paren ?{ ?} (or count 1))
(backward-char))
+(defun evil--next-mark (forwardp)
+ (let* ((pos (point))
+ (markers (cl-remove-if-not
+ (lambda (x) (or (markerp (cdr x))
+ (<= ?a (car x) ?z)))
+ evil-markers-alist))
+ (sorted-markers (sort markers
+ (lambda (a b) (< (cdr a) (cdr b))))))
+ (cond
+ ((null markers)
+ (user-error "No marks in this buffer"))
+ (forwardp
+ (let ((next-marker (cl-some (lambda (x) (and (< pos (cdr x)) (cdr x)))
+ sorted-markers)))
+ (if next-marker
+ (goto-char (marker-position next-marker))
+ (goto-char (marker-position (cdar sorted-markers))))))
+ (t
+ (let* ((descending-markers (reverse sorted-markers))
+ (prev-marker (cl-some (lambda (x) (and (> pos (cdr x)) (cdr x)))
+ descending-markers)))
+ (if prev-marker
+ (goto-char (marker-position prev-marker))
+ (goto-char (marker-position (cdar descending-markers)))))))))
+
+(evil-define-motion evil-next-mark (count)
+ "Go to [count] next mark."
+ :keep-visual t
+ :repeat nil
+ :type exclusive
+ :jump t
+ (dotimes (_ (or count 1))
+ (evil--next-mark t)))
+
+(evil-define-motion evil-next-mark-line (count)
+ "Go to [count] line of next mark."
+ :keep-visual t
+ :repeat nil
+ :type exclusive
+ :jump t
+ (dotimes (_ (or count 1))
+ (evil--next-mark t)
+ (evil-first-non-blank)))
+
+(evil-define-motion evil-previous-mark (count)
+ "Go to [count] previous mark."
+ :keep-visual t
+ :repeat nil
+ :type exclusive
+ :jump t
+ (dotimes (_ (or count 1))
+ (evil--next-mark nil)))
+
+(evil-define-motion evil-previous-mark-line (count)
+ "Go to [count] line of previous mark."
+ :keep-visual t
+ :repeat nil
+ :type exclusive
+ :jump t
+ (dotimes (_ (or count 1))
+ (evil--next-mark nil)
+ (evil-first-non-blank)))
+
(evil-define-motion evil-find-char (count char)
"Move to the next COUNT'th occurrence of CHAR.
Movement is restricted to the current line unless `evil-cross-lines' is non-nil."
diff --git a/evil-maps.el b/evil-maps.el
index 91ed47e..8820215 100644
--- a/evil-maps.el
+++ b/evil-maps.el
@@ -232,6 +232,10 @@
(define-key evil-motion-state-map "])" 'evil-next-close-paren)
(define-key evil-motion-state-map "[{" 'evil-previous-open-brace)
(define-key evil-motion-state-map "]}" 'evil-next-close-brace)
+(define-key evil-motion-state-map "]'" 'evil-next-mark-line)
+(define-key evil-motion-state-map "]`" 'evil-next-mark)
+(define-key evil-motion-state-map "['" 'evil-previous-mark-line)
+(define-key evil-motion-state-map "[`" 'evil-previous-mark)
(define-key evil-motion-state-map "]s" 'evil-next-flyspell-error)
(define-key evil-motion-state-map "[s" 'evil-prev-flyspell-error)
(define-key evil-motion-state-map "*" 'evil-search-word-forward)
diff --git a/evil-tests.el b/evil-tests.el
index 792dca2..d55941e 100644
--- a/evil-tests.el
+++ b/evil-tests.el
@@ -5202,6 +5202,44 @@ Below some empty line."))
("2])")
"foo ( { ( bar ) baz } [)]")))
+(ert-deftest evil-test-next-mark ()
+ "Test `evil-next-mark', `evil-previous-mark'"
+ :tags '(evil motion)
+ (ert-info ("Can move to next mark and next mark line")
+ (evil-test-buffer
+ "line 1
+lin[e] 2
+line 3"
+ ("majmbgg")
+ "[l]ine 1
+line 2
+line 3"
+ ("]`")
+ "line 1
+lin[e] 2
+line 3"
+ ("]'")
+ "line 1
+line 2
+[l]ine 3"))
+ (ert-info ("Can move to previous mark and previous mark line")
+ (evil-test-buffer
+ "li[n]e 1
+line 2
+line 3"
+ ("mcjmdG")
+ "line 1
+line 2
+[l]ine 3"
+ ("[`")
+ "line 1
+li[n]e 2
+line 3"
+ ("2['")
+ "line 1
+[l]ine 2
+line 3")))
+
(ert-deftest evil-test-flyspell-motions ()
"Test flyspell motions"
:tags '(evil motion)