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

Reply via email to