Skip to content

Commit

Permalink
Fix pasting in visual block mode (#1786)
Browse files Browse the repository at this point in the history
Co-authored-by: Tom Dalziel <[email protected]>
  • Loading branch information
axelf4 and tomdl89 committed May 29, 2023
1 parent b7bc385 commit 2a80de3
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 27 deletions.
38 changes: 19 additions & 19 deletions evil-commands.el
Original file line number Diff line number Diff line change
Expand Up @@ -2273,45 +2273,45 @@ leave the cursor just after the new text."
(yank-handler (car-safe (get-text-property
0 'yank-handler text)))
(dir (evil-visual-direction))
beg end paste-eob)
beg end type)
(evil-with-undo
(let ((kill-ring-yank-pointer (when kill-ring (list (current-kill 0)))))
(when (evil-visual-state-p)
(setq beg evil-visual-beginning
end evil-visual-end)
end evil-visual-end
type (evil-visual-type))
(evil-visual-rotate 'upper-left)
;; if we replace the last buffer line that does not end in a
;; newline, we use `evil-paste-after' because `evil-delete'
;; will move point to the line above
(when (and (= evil-visual-end (point-max))
(/= (char-before (point-max)) ?\n))
(setq paste-eob t))
(evil-delete beg end (evil-visual-type) (unless evil-kill-on-visual-paste ?_))
(evil-delete beg end type (unless evil-kill-on-visual-paste ?_))
(when (and (eq yank-handler #'evil-yank-line-handler)
(not (memq (evil-visual-type) '(line block)))
(not (= evil-visual-end (point-max))))
(not (memq type '(line block)))
(/= end (point-max)))
(insert "\n"))
(evil-normal-state)
(when kill-ring (current-kill 1)))
;; Effectively memoize `evil-get-register' because it can be
;; side-effecting (e.g. for the `=' register)...
(cl-letf (((symbol-function 'evil-get-register)
(cl-letf (((symbol-function #'evil-get-register)
(lambda (&rest _) text)))
(cond
((eq 'block (evil-visual-type))
(when (eq yank-handler #'evil-yank-line-handler)
(setq text (concat "\n" text)))
(evil-set-marker ?\[ beg)
;; When replacing the last buffer line and it does not end
;; in a newline, use `evil-paste-after' because
;; `evil-delete' will have moved point to the line above.
((cond ((eq type 'line) (= end (point-max)))
((eq type 'block) (eq yank-handler #'evil-yank-line-handler)))
(goto-char end)
(evil-paste-after count register))
((and (eq type 'block)
(not (eq yank-handler #'evil-yank-block-handler))
(not (string-match-p "\n" text)))
(evil-apply-on-block #'evil-insert-for-yank-at-col beg end t text count))
(paste-eob (evil-paste-after count register))
(t (evil-paste-before count register)))))
(when evil-kill-on-visual-paste
(current-kill -1))
;; Ensure that gv can restore visually pasted area...
(setq evil-visual-previous-mark evil-visual-mark
evil-visual-mark (evil-get-marker (if (<= 0 dir) ?\[ ?\]) t)
evil-visual-mark (evil-get-marker (if (< 0 dir) ?\[ ?\]) t)
evil-visual-previous-point evil-visual-point
evil-visual-point (evil-get-marker (if (<= 0 dir) ?\] ?\[) t))
evil-visual-point (evil-get-marker (if (< 0 dir) ?\] ?\[) t))
;; mark the last paste as visual-paste
(setq evil-last-paste
(list (nth 0 evil-last-paste)
Expand Down
7 changes: 3 additions & 4 deletions evil-states.el
Original file line number Diff line number Diff line change
Expand Up @@ -759,10 +759,9 @@ the direction of the last selection."
(defun evil-visual-type (&optional selection)
"Return the type of the Visual selection.
If SELECTION is specified, return the type of that instead."
(if (and (null selection) (evil-visual-state-p))
(or evil-this-type (evil-visual-type evil-visual-selection))
(setq selection (or selection evil-visual-selection))
(symbol-value (cdr-safe (assq selection evil-visual-alist)))))
(or (and (null selection) (evil-visual-state-p) evil-this-type)
(symbol-value (cdr (assq (or selection evil-visual-selection)
evil-visual-alist)))))

(defun evil-visual-goto-end ()
"Go to the last line of the Visual selection.
Expand Down
11 changes: 7 additions & 4 deletions evil-tests.el
Original file line number Diff line number Diff line change
Expand Up @@ -3039,10 +3039,13 @@ word3[]"))
("gv") ;; Test point & mark are stored correctly
"abc\n1<abcabc3\n1abcabc3\n1abcab[c]>3"))
(ert-info ("Blockwise visual paste of linewise text")
(evil-test-buffer
"[a]bc\n123\n123\n123"
("yy" "jl" "\C-vG" "p")
"abc\n1\nabc\n3\n1\nabc\n3\n1\nabc\n3")))
(evil-test-buffer "[a]bc\n123\n123"
("yy" "jl" "\C-vj" "p")
"abc\n13\n13\nabc"))
(ert-info ("Blockwise visual paste of blockwise text")
(evil-test-buffer "xy\n[z]\n123\n123"
("\C-vkly2jl\C-vjp")
"xy\nz\n1xy3\n1z 3")))

(ert-deftest evil-test-visual-paste-pop ()
"Test `evil-paste-pop' after visual paste."
Expand Down

0 comments on commit 2a80de3

Please sign in to comment.