aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Dalziel <tom_dl@hotmail.com>2024-06-04 09:38:55 +0200
committerTom Dalziel <33435574+tomdl89@users.noreply.github.com>2024-06-14 18:21:16 +0200
commitf29ad3c91e06ca1910f326b3b0a41ae59ba2c8b6 (patch)
tree5117d95ad9f59d3461a7f303aee59e61228eb9f7
parenta32f016536fadf5080be39f239288b76146216ee (diff)
Track (and restore) previous visual selection, point, mark for gv
-rw-r--r--evil-commands.el34
-rw-r--r--evil-states.el8
-rw-r--r--evil-tests.el29
-rw-r--r--evil-vars.el10
4 files changed, 64 insertions, 17 deletions
diff --git a/evil-commands.el b/evil-commands.el
index 1278c61..43030c2 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 6b86d9d..26eb844 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 8ed12b7..4699108 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 aea7eee..7adbb60 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