branch: elpa/evil
commit e31bff8cb64d773bbfd9a8e326db8645eaee43fd
Author: Tom Dalziel <tom...@hotmail.com>
Commit: Tom Dalziel <33435574+tomd...@users.noreply.github.com>

    Visual eol anchoring, so g$ is sticky
    
    Also fixes #1876
---
 evil-commands.el | 26 ++++++++++++++++++++++++--
 evil-common.el   |  5 ++++-
 evil-tests.el    | 23 +++++++++++++++++++++++
 3 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/evil-commands.el b/evil-commands.el
index e3af076f52..a44cc25dc1 100644
--- a/evil-commands.el
+++ b/evil-commands.el
@@ -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)
@@ -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
@@ -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)
diff --git a/evil-common.el b/evil-common.el
index c305c2568e..2b228c236f 100644
--- a/evil-common.el
+++ b/evil-common.el
@@ -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.
diff --git a/evil-tests.el b/evil-tests.el
index f22a6694a6..88a8aa5a07 100644
--- a/evil-tests.el
+++ b/evil-tests.el
@@ -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)

Reply via email to