diff --git a/extensions/vi-mode/binds.lisp b/extensions/vi-mode/binds.lisp index 2ba20e022..6b70c3353 100644 --- a/extensions/vi-mode/binds.lisp +++ b/extensions/vi-mode/binds.lisp @@ -58,6 +58,7 @@ (define-key *motion-keymap* "n" 'vi-search-next) (define-key *motion-keymap* "N" 'vi-search-previous) (define-key *motion-keymap* "*" 'vi-search-forward-symbol-at-point) +(define-key *motion-keymap* "#" 'vi-search-backward-symbol-at-point) (define-key *motion-keymap* "g g" 'vi-goto-first-line) (define-key *motion-keymap* "g e" 'vi-backward-word-end) (define-key *motion-keymap* "g E" 'vi-backward-word-end-broad) diff --git a/extensions/vi-mode/commands.lisp b/extensions/vi-mode/commands.lisp index 1ea84a3b4..f8c5409b1 100644 --- a/extensions/vi-mode/commands.lisp +++ b/extensions/vi-mode/commands.lisp @@ -96,6 +96,7 @@ :vi-search-next :vi-search-previous :vi-search-forward-symbol-at-point + :vi-search-backward-symbol-at-point :vi-goto-first-line :vi-goto-line :vi-goto-column @@ -761,11 +762,33 @@ Move the cursor to the first non-blank character of the line." (:forward (vi-search-repeat-backward n)) (:backward (vi-search-repeat-forward n)))) -(define-command vi-search-forward-symbol-at-point () () +(define-command vi-search-forward-symbol-at-point (&optional (n 1)) ("p") (with-jumplist (lem/isearch:isearch-forward-symbol-at-point) (lem/isearch:isearch-finish) - (lem/isearch:isearch-next))) + (let ((wrapped nil)) + (loop :repeat n + :unless (lem/isearch:isearch-next) + :do (move-point (current-point) (buffer-start-point (current-buffer))) + (lem/isearch:isearch-next) + (setq wrapped t)) + (skip-chars-backward (current-point) #'syntax-symbol-char-p) + (when wrapped + (message "Search wrapped around from bottom to top"))))) + +(define-command vi-search-backward-symbol-at-point (&optional (n 1)) ("p") + (with-jumplist + (lem/isearch:isearch-forward-symbol-at-point) + (lem/isearch:isearch-finish) + (lem/isearch:isearch-prev) + (let ((wrapped nil)) + (loop :repeat n + :unless (lem/isearch:isearch-prev) + :do (move-point (current-point) (buffer-end-point (current-buffer))) + (lem/isearch:isearch-prev) + (setq wrapped t)) + (when wrapped + (message "Search wrapped around from top to bottom"))))) (define-motion vi-goto-first-line (&optional (n 1)) ("p") (:type :line diff --git a/extensions/vi-mode/tests/commands.lisp b/extensions/vi-mode/tests/commands.lisp index 828a21224..43bc04556 100644 --- a/extensions/vi-mode/tests/commands.lisp +++ b/extensions/vi-mode/tests/commands.lisp @@ -85,3 +85,27 @@ (ok (buf= #?"abcd\nef[b]cgh\n fg\nijk\n")) (cmd "u$2hP") (ok (buf= #?"abcd\ne[b]cfgh\n fg\nijk\n")))))) + +(deftest vi-search-forward-symbol-at-point + (with-fake-interface () + (with-vi-buffer (#?"f[o]o\nbar\nfoo\nbar\nfoo") + (cmd "*") + (ok (buf= #?"foo\nbar\n[f]oo\nbar\nfoo"))) + (with-vi-buffer (#?"f[o]o\nbar\nfoo\nbar\nfoo") + (cmd "1*") + (ok (buf= #?"foo\nbar\n[f]oo\nbar\nfoo"))) + (with-vi-buffer (#?"f[o]o\nbar\nfoo\nbar\nfoo") + (cmd "2*") + (ok (buf= #?"foo\nbar\nfoo\nbar\n[f]oo"))))) + +(deftest vi-search-backward-symbol-at-point + (with-fake-interface () + (with-vi-buffer (#?"foo\nbar\nfoo\nbar\nf[o]o") + (cmd "#") + (ok (buf= #?"foo\nbar\n[f]oo\nbar\nfoo"))) + (with-vi-buffer (#?"foo\nbar\nfoo\nbar\nf[o]o") + (cmd "1#") + (ok (buf= #?"foo\nbar\n[f]oo\nbar\nfoo"))) + (with-vi-buffer (#?"foo\nbar\nfoo\nbar\nf[o]o") + (cmd "2#") + (ok (buf= #?"[f]oo\nbar\nfoo\nbar\nfoo")))))