branch: elpa/evil commit f29ad3c91e06ca1910f326b3b0a41ae59ba2c8b6 Author: Tom Dalziel <tom...@hotmail.com> Commit: Tom Dalziel <33435574+tomd...@users.noreply.github.com>
Track (and restore) previous visual selection, point, mark for gv --- evil-commands.el | 34 ++++++++++++++++++++-------------- evil-states.el | 8 ++++++-- evil-tests.el | 29 ++++++++++++++++++++++++++++- evil-vars.el | 10 ++++++++++ 4 files changed, 64 insertions(+), 17 deletions(-) diff --git a/evil-commands.el b/evil-commands.el index 1278c612f0..43030c22a2 100644 --- a/evil-commands.el +++ b/evil-commands.el @@ -2579,20 +2579,26 @@ COUNT is infinite." (evil-define-motion evil-visual-restore () "Restore previous selection." - (let* ((point (point)) - (mark (or (mark t) point)) - (type (evil-visual-type))) - ;; TODO handle swapping selection in visual state... - (unless (evil-visual-state-p) - (cond - ;; No previous selection. - ((or (null evil-visual-selection) - (null evil-visual-mark) - (null evil-visual-point))) - (t - (setq mark evil-visual-mark - point evil-visual-point) - (evil-visual-make-selection mark point type t)))))) + (cond + ;; Called from visual state + ((and (evil-visual-state-p) + evil-prev-visual-mark evil-prev-visual-point evil-prev-visual-selection) + (let ((tmp-visual-mark (marker-position evil-visual-mark)) + (tmp-visual-point (marker-position evil-visual-point)) + (tmp-visual-selection evil-visual-selection)) + (evil-visual-make-selection evil-prev-visual-mark + evil-prev-visual-point + evil-prev-visual-selection + t) + (move-marker evil-prev-visual-mark tmp-visual-mark) + (move-marker evil-prev-visual-point tmp-visual-point) + (setq evil-prev-visual-selection tmp-visual-selection))) + ;; Called from other state + ((and evil-visual-selection evil-visual-mark evil-visual-point) + (evil-visual-make-selection evil-visual-mark + evil-visual-point + (evil-visual-type) + t)))) (evil-define-motion evil-visual-exchange-corners () "Rearrange corners in Visual Block mode. diff --git a/evil-states.el b/evil-states.el index 6b86d9deef..26eb844ecf 100644 --- a/evil-states.el +++ b/evil-states.el @@ -421,7 +421,10 @@ If LATER is non-nil, exit after the current command." (setq deactivate-mark t) (when evil-visual-region-expanded (evil-visual-contract-region)) - (setq evil-this-register nil) + (setq evil-this-register nil + evil-prev-visual-selection evil-visual-selection + evil-prev-visual-mark (copy-marker evil-visual-mark) + evil-prev-visual-point (copy-marker evil-visual-point)) (evil-change-to-previous-state))))) (defun evil-visual-tag (&optional selection) @@ -777,7 +780,8 @@ Default to `evil-visual-make-region'." "Return a Visual selection for TYPE." (catch 'done (dolist (selection evil-visual-alist) - (when (eq (symbol-value (cdr selection)) type) + (when (memq (symbol-value (cdr selection)) + (list type (evil-visual-type type))) (throw 'done (car selection)))))) (defun evil-visual-block-corner (&optional corner point mark) diff --git a/evil-tests.el b/evil-tests.el index 8ed12b78a5..4699108af7 100644 --- a/evil-tests.el +++ b/evil-tests.el @@ -7584,7 +7584,34 @@ otel"))) echo foxtrot\ngolf hotel" ("2yy" "++" "Vp" "gv") "alpha bravo\ncharlie delta -<alpha bravo\ncharlie delta\n>golf hotel"))) +<alpha bravo\ncharlie delta\n>golf hotel")) + ;; 4 repetitions appears necessary, from manual testing + (ert-info ("Restore previous linewise selection from linewise selection") + (evil-test-buffer + "alpha bravo\nch[a]rlie delta\necho foxtrot\ngolf hotel" + ("V" [escape] "jV") + "alpha bravo\ncharlie delta\n<ec[h]o foxtrot\n>golf hotel" + ("gv") + "alpha bravo\n<ch[a]rlie delta\n>echo foxtrot\ngolf hotel" + ("gv") + "alpha bravo\ncharlie delta\n<ec[h]o foxtrot\n>golf hotel" + ("gv") + "alpha bravo\n<ch[a]rlie delta\n>echo foxtrot\ngolf hotel" + ("gv") + "alpha bravo\ncharlie delta\n<ec[h]o foxtrot\n>golf hotel")) + (ert-info ("Restore between previous charwise selection and linewise selection") + (evil-test-buffer + "alpha bravo\nch[a]rlie delta\necho foxtrot\ngolf hotel" + ("viw" [escape] "jV") + "alpha bravo\ncharlie delta\n<echo f[o]xtrot\n>golf hotel" + ("gv") + "alpha bravo\n<charli[e]> delta\necho foxtrot\ngolf hotel" + ("gv") + "alpha bravo\ncharlie delta\n<echo f[o]xtrot\n>golf hotel" + ("gv") + "alpha bravo\n<charli[e]> delta\necho foxtrot\ngolf hotel" + ("gv") + "alpha bravo\ncharlie delta\n<echo f[o]xtrot\n>golf hotel"))) (ert-deftest evil-test-visual-redefine () "Test redefining a previous selection" diff --git a/evil-vars.el b/evil-vars.el index aea7eeeaea..7adbb60c8f 100644 --- a/evil-vars.el +++ b/evil-vars.el @@ -1740,6 +1740,16 @@ instead of `buffer-undo-list'.") "The kind of Visual selection. This is a selection as defined by `evil-define-visual-selection'.") +(evil-define-local-var evil-prev-visual-point nil + "The previous position of point in Visual state, a marker.") + +(evil-define-local-var evil-prev-visual-mark nil + "The previous position of mark in Visual state, a marker.") + +(evil-define-local-var evil-prev-visual-selection nil + "The previous kind of Visual selection. +This is a selection as defined by `evil-define-visual-selection'.") + ;; we could infer the direction by comparing `evil-visual-mark' ;; and `evil-visual-point', but destructive operations may ;; displace the markers