A yank-over-region function for Emacs

Mar 10, 2010 23:28

One feature I am surprised hasn't been added to Emacs yet is a yank (paste) operation that replaces the text in the active region.

In order to perform this operation, which is something I do all the time, I need to do a combination of kill-region/yank/yank-pop (or C-w, C-y, M-y). If there is a better way, and I am overlooking something, let me know.

There are three huge disadvantages to doing it this way:

1. It is inefficient.
2. It doesn't work too well with the interprogram clipboard.
3. You can only apply it once. Repeated applications of the operation will need increased presses of M-y to align with the correct item in the kill ring.

So, I decided to write my own function and bind it to C-c C-y.

"yank-over-region" will yank an item from the kill ring, just as if you did a regular yank; however, the yanked text will replace the text in the current region. And immediately after doing a yank-over-region, you can cycle through the kill ring (using M-y) just as if you had done a yank.

The text you are replacing will be added to the kill ring as well; since it calls kill-region to do this, the same behavior for kills can be expected here.

I haven't done a huge amount of testing yet, but so far it seems to work pretty well, and works fine with the clipboard. I'll probably expand it a bit later (such as adding proper documentation and support for arguments, etc.)

To use, just add the following snippet to your .emacs file:

(defun yank-over-region (beg end)
; KES 3/10/2010

(interactive "*r")
(setq yank-window-start (window-start))
(push-mark (point))
(let* ((string (current-kill 0))
(ring-pos kill-ring-yank-pointer)
(before)
(after (cdr ring-pos))
(cur kill-ring))

; prepare the kill ring
(while (and cur (not (eq cur ring-pos)))
(push (car cur) before)
(setq cur (cdr cur)))
(setq kill-ring-yank-pointer
(setq kill-ring (append after (nreverse before))))

(kill-region beg end)
(insert-for-yank string)

; rebuild and normalize kill ring
(setq kill-ring-yank-pointer
(setq kill-ring (cons (car ring-pos) kill-ring))))

(setq this-command 'yank))

; bind
(global-set-key (kbd "C-c y") 'yank-over-region)
(global-set-key (kbd "C-c C-y") 'yank-over-region)
Previous post Next post
Up