Skip to content

Commit

Permalink
Visual eol anchoring, so g$ is sticky
Browse files Browse the repository at this point in the history
Also fixes emacs-evil#1876
  • Loading branch information
tomdl89 committed Apr 14, 2024
1 parent 27c9dce commit e31bff8
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 3 deletions.
26 changes: 24 additions & 2 deletions evil-commands.el
Original file line number Diff line number Diff line change
Expand Up @@ -108,29 +108,49 @@ of the line or the buffer; just return nil."
(unless (or (evil-visual-state-p) (evil-operator-state-p))
(evil-adjust-cursor))))))

(defvar evil--visual-eol-anchored nil
"Non nil if the cursor should be anchored at the end of the visual line.
Only reliably usable via `evil-visual-eol-anchored-p'.")

(defun evil-visual-eol-anchored-p ()
"Return non nil if the cursor should be anchored at the end of the visual line."
(if (memq last-command '(next-line previous-line evil-end-of-visual-line))
evil--visual-eol-anchored
(setq evil--visual-eol-anchored nil)))

(evil-define-motion evil-next-line (count)
"Move the cursor COUNT lines down."
:type line
(let (line-move-visual)
(unless (memq last-command '(next-line previous-line evil-end-of-visual-line))
(setq evil--visual-eol-anchored nil))
(evil-line-move (or count 1))))

(evil-define-motion evil-previous-line (count)
"Move the cursor COUNT lines up."
:type line
(let (line-move-visual)
(unless (memq last-command '(next-line previous-line evil-end-of-visual-line))
(setq evil--visual-eol-anchored nil))
(evil-line-move (- (or count 1)))))

(evil-define-motion evil-next-visual-line (count)
"Move the cursor COUNT screen lines down."
:type exclusive
(let ((line-move-visual t))
(evil-line-move (or count 1))))
(when (eq most-positive-fixnum temporary-goal-column)
(setq temporary-goal-column (current-column))) ; Fix #1876
(evil-line-move (or count 1))
(when (evil-visual-eol-anchored-p) (evil-end-of-visual-line))))

(evil-define-motion evil-previous-visual-line (count)
"Move the cursor COUNT screen lines up."
:type exclusive
(let ((line-move-visual t))
(evil-line-move (- (or count 1)))))
(when (eq most-positive-fixnum temporary-goal-column)
(setq temporary-goal-column (current-column))) ; Fix #1876
(evil-line-move (- (or count 1)))
(when (evil-visual-eol-anchored-p) (evil-end-of-visual-line))))

;; used for repeated commands like "dd"
(evil-define-motion evil-line (count)
Expand Down Expand Up @@ -168,6 +188,7 @@ If COUNT is given, move COUNT - 1 lines downward first."
(move-end-of-line count)
(when evil-track-eol
(setq temporary-goal-column most-positive-fixnum
evil--visual-eol-anchored t
this-command 'next-line))
(if (evil-visual-state-p)
(when evil-v$-excludes-newline
Expand All @@ -187,6 +208,7 @@ If COUNT is given, move COUNT - 1 lines downward first."
"Move the cursor to the last character of the current screen line.
If COUNT is given, move COUNT - 1 screen lines downward first."
:type inclusive
(setq evil--visual-eol-anchored t)
(end-of-visual-line count))

(evil-define-motion evil-end-of-line-or-visual-line (count)
Expand Down
5 changes: 4 additions & 1 deletion evil-common.el
Original file line number Diff line number Diff line change
Expand Up @@ -1254,7 +1254,10 @@ Signals an error at buffer boundaries unless NOERROR is non-nil."
(car-safe temporary-goal-column)
temporary-goal-column)))
(line-move-finish col opoint (< count 0)))
(or noerror (/= (point) opoint) (signal (car err) (cdr err)))))))
(or noerror (/= (point) opoint) (signal (car err) (cdr err))))
(args-out-of-range
(unless (eq most-positive-fixnum temporary-goal-column)
(signal (car err) (cdr err)))))))

(defun evil-forward-syntax (syntax &optional count)
"Move point to the end or beginning of a sequence of characters in SYNTAX.
Expand Down
23 changes: 23 additions & 0 deletions evil-tests.el
Original file line number Diff line number Diff line change
Expand Up @@ -3529,6 +3529,29 @@ Below some empty line"
("Gkgk")
(should (not (bolp)))))

(ert-deftest evil-test-end-of-visual-line ()
"Test `evil-end-of-visual-line'."
:tags '(evil motion)
(skip-unless (and (not noninteractive) (> (window-width) 2)))
(evil-test-buffer
"alpha bravo charlie\nd[e]lta echo\nfoxtrot golf hotel india"
("g$" "gj")
"alpha bravo charlie\ndelta echo\nfoxtrot golf hotel indi[a]"
("gkgk")
"alpha bravo charli[e]\ndelta echo\nfoxtrot golf hotel india"
("ro" "2gj")
"alpha bravo charlio\ndelta echo\nfoxtrot golf hotel[ ]india"))

(ert-deftest evil-test-eol-anchoring-with-visual-line-movement ()
"Test gj and gk once the cursor is anchored at eol with $."
:tags '(evil motion)
(skip-unless (and (not noninteractive) (> (window-width) 2)))
(evil-test-buffer
"Short [l]ine\nA longer line\nThird line"
(visual-line-mode 1)
("$gj")
"Short line\nA longer lin[e]\nThird line"))

(ert-deftest evil-test-other-commands-preserve-column ()
"Test other comamnds preserve the column, when appropriate."
:tags '(evil motion)
Expand Down

0 comments on commit e31bff8

Please sign in to comment.