emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/evil 643e01d1a0 1/2: Add handler for expanding line for li


From: ELPA Syncer
Subject: [nongnu] elpa/evil 643e01d1a0 1/2: Add handler for expanding line for line-based operators
Date: Sat, 30 Mar 2024 21:59:43 -0400 (EDT)

branch: elpa/evil
commit 643e01d1a07fc472b5a9ff6fa3ec001ddc8681ba
Author: Tom Dalziel <tom_dl@hotmail.com>
Commit: Tom Dalziel <33435574+tomdl89@users.noreply.github.com>

    Add handler for expanding line for line-based operators
    
    Most of the work was done by Maxi Wolff (@smile13241324) over 6yrs ago.
    I've made a few changes, so have assumed authorship.
    
    This fixes #968
---
 evil-commands.el | 68 +++++++++++++++++++++++++++++++-------------------------
 evil-tests.el    | 37 +++++++++++++++++++++++++++++-
 2 files changed, 74 insertions(+), 31 deletions(-)

diff --git a/evil-commands.el b/evil-commands.el
index 62a6597228..2ae01d5c29 100644
--- a/evil-commands.el
+++ b/evil-commands.el
@@ -1436,23 +1436,37 @@ the left edge."
       (evil-yank-characters beg end register yank-handler)
       (goto-char beg)))))
 
-(evil-define-operator evil-yank-line (beg end type register)
-  "Save whole lines into the kill-ring."
-  :motion evil-line-or-visual-line
-  :move-point nil
-  (interactive "<R><x>")
+(defun evil-expand-line-for-line-based-operators (beg end type)
+  "Expand to line when in visual mode possibly changing BEG, END and TYPE.
+Avoids double expansion for line based commands like 'V' or 'D'."
   (when (evil-visual-state-p)
     (unless (memq type '(line block screen-line))
-      (let ((range (evil-expand beg end
-                                (if (and evil-respect-visual-line-mode
-                                         visual-line-mode)
-                                    'screen-line
-                                  'line))))
+      ;; Subtract 1 from end to avoid expanding to the next line
+      ;; when \n is part of the visually selected region.
+      ;; If removed (evil-expand beg end 'line)
+      ;; will expand to the end of the next line instead of the current
+      ;; line which will cause line expanding commands like 'Y' to
+      ;; misbehave when used in visual state.
+      (when (eq ?\n (char-before end))
+        (cl-decf end))
+      (let ((range (evil-expand beg end (if (and evil-respect-visual-line-mode
+                                                 visual-line-mode)
+                                            'screen-line
+                                          'line))))
         (setq beg (evil-range-beginning range)
               end (evil-range-end range)
               type (evil-type range))))
     (evil-exit-visual-state))
-  (evil-yank beg end type register))
+  (list beg end type))
+
+(evil-define-operator evil-yank-line (beg end type register)
+  "Save whole lines into the kill-ring."
+  :motion evil-line-or-visual-line
+  :move-point nil
+  (interactive "<R><x>")
+  (cl-destructuring-bind
+      (beg end type) (evil-expand-line-for-line-based-operators beg end type)
+    (evil-yank beg end type register)))
 
 (evil-define-operator evil-delete (beg end type register yank-handler)
   "Delete text from BEG to END with TYPE.
@@ -1502,24 +1516,17 @@ Save in REGISTER or in the kill-ring with YANK-HANDLER."
   "Delete to end of line."
   :motion evil-end-of-line-or-visual-line
   (interactive "<R><x>")
-  ;; Act linewise in Visual state
-  (when (and (evil-visual-state-p) (eq type 'inclusive))
-    (let ((range (evil-expand
-                  beg end
-                  (if (and evil-respect-visual-line-mode visual-line-mode)
-                      'screen-line 'line))))
-      (setq beg (car range)
-            end (cadr range)
-            type (evil-type range))))
-  (if (eq type 'block)
-      ;; Equivalent to $d, i.e., we use the block-to-eol selection and
-      ;; call `evil-delete'. In this case we fake the call to
-      ;; `evil-end-of-line' by setting `temporary-goal-column' and
-      ;; `last-command' appropriately as `evil-end-of-line' would do.
-      (let ((temporary-goal-column most-positive-fixnum)
-            (last-command 'next-line))
-        (evil-delete beg end 'block register yank-handler))
-    (evil-delete beg end type register yank-handler)))
+  (cl-destructuring-bind
+      (beg end type) (evil-expand-line-for-line-based-operators beg end type)
+    (if (eq type 'block)
+        ;; Equivalent to $d, i.e., we use the block-to-eol selection and
+        ;; call `evil-delete'. In this case we fake the call to
+        ;; `evil-end-of-line' by setting `temporary-goal-column' and
+        ;; `last-command' appropriately as `evil-end-of-line' would do.
+        (let ((temporary-goal-column most-positive-fixnum)
+              (last-command 'next-line))
+          (evil-delete beg end 'block register yank-handler))
+      (evil-delete beg end type register yank-handler))))
 
 (evil-define-operator evil-delete-whole-line
   (beg end type register yank-handler)
@@ -1672,7 +1679,8 @@ of the block."
   :motion evil-end-of-line-or-visual-line
   (interactive "<R><x><y>")
   (if (and (evil-visual-state-p) (eq type 'inclusive))
-      (cl-destructuring-bind (beg end &rest) (evil-line-expand beg end)
+      (cl-destructuring-bind
+          (beg end _type) (evil-expand-line-for-line-based-operators beg end 
type)
         (evil-change-whole-line beg end register yank-handler))
     (evil-change beg end type register yank-handler #'evil-delete-line)))
 
diff --git a/evil-tests.el b/evil-tests.el
index 8004633286..b474770568 100644
--- a/evil-tests.el
+++ b/evil-tests.el
@@ -2013,6 +2013,20 @@ New Tex[t]
       ("my" "G" ":'y,.y")
       "1\n2\n3\n4\n5\n6\n7\n8\n9\n[1]0")))
 
+(ert-deftest evil-test-yank-line ()
+  "Test `evil-yank-line'"
+  :tags '(evil operator)
+  (ert-info ("Yank line with eof being part of visual selection")
+    (evil-test-buffer
+      ";; This is line one
+;; This is lin[e] two
+;; This is line three"
+      ("v$Yjp")
+      ";; This is line one
+;; This is line two
+;; This is line three
+[;]; This is line two")))
+
 (ert-deftest evil-test-delete ()
   "Test `evil-delete'"
   :tags '(evil operator delete)
@@ -2144,7 +2158,15 @@ ine3 line3      line3 l\n"))
     (evil-test-buffer
      "a[a]a\nbbb\nc\n"
      ("2D")
-     "a\nc\n")))
+     "a\nc\n"))
+  (ert-info ("Delete line with eof being part of visual selection")
+    (evil-test-buffer
+      ";; This is line one
+;; This is lin[e] two
+;; This is line three"
+      ("v$D")
+      ";; This is line one
+;; This is line three")))
 
 (ert-deftest evil-test-delete-folded ()
   "Test `evil-delete' on folded lines."
@@ -2342,6 +2364,19 @@ ABCthen enter the text in that file's own buffer.")))
 []
      five")))
 
+(ert-deftest evil-test-change-line ()
+  "Test `evil-change-line'"
+  :tags '(evil operator)
+  (ert-info ("Change line with eof being part of visual selection")
+    (evil-test-buffer
+      "This is line one
+This is lin[e] two
+This is line three"
+      ("v$C")
+      "This is line one
+[]
+This is line three")))
+
 (ert-deftest evil-test-change-word ()
   "Test changing words"
   :tags '(evil operator)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]