[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)