Skip to content

Commit

Permalink
Track (and restore) previous visual selection, point, mark for gv
Browse files Browse the repository at this point in the history
  • Loading branch information
tomdl89 committed Jun 14, 2024
1 parent a32f016 commit f29ad3c
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 17 deletions.
34 changes: 20 additions & 14 deletions evil-commands.el
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
8 changes: 6 additions & 2 deletions evil-states.el
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
29 changes: 28 additions & 1 deletion evil-tests.el
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
10 changes: 10 additions & 0 deletions evil-vars.el
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit f29ad3c

Please sign in to comment.