diff options
| author | Tom Dalziel <tom_dl@hotmail.com> | 2024-03-30 23:17:58 +0100 |
|---|---|---|
| committer | Tom Dalziel <33435574+tomdl89@users.noreply.github.com> | 2024-03-31 00:39:27 +0100 |
| commit | 643e01d1a07fc472b5a9ff6fa3ec001ddc8681ba (patch) | |
| tree | 8d857063a99ca272a9d5952c0941177fa08c2fa4 /evil-commands.el | |
| parent | 700d574843e2ae3545c983dcf6ad6db604d38c43 (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.el | 68 |
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))) |
