aboutsummaryrefslogtreecommitdiff
path: root/evil-commands.el
diff options
context:
space:
mode:
authorTom Dalziel <tom_dl@hotmail.com>2024-03-30 23:17:58 +0100
committerTom Dalziel <33435574+tomdl89@users.noreply.github.com>2024-03-31 00:39:27 +0100
commit643e01d1a07fc472b5a9ff6fa3ec001ddc8681ba (patch)
tree8d857063a99ca272a9d5952c0941177fa08c2fa4 /evil-commands.el
parent700d574843e2ae3545c983dcf6ad6db604d38c43 (diff)
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
Diffstat (limited to 'evil-commands.el')
-rw-r--r--evil-commands.el68
1 files changed, 38 insertions, 30 deletions
diff --git a/evil-commands.el b/evil-commands.el
index 62a6597..2ae01d5 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)))