tags:

views:

566

answers:

5

This is scenario that I ran into a few times:

I copy some text from other program. Go to Emacs and did some editing before I paste/yank the text in. C-y to yank and voila ... not the text I intended to paste in. Then I realize that while I am moving things around, I used commands like kill-line and backward-kill-word, and those killed lines and words now occupied the kill-ring. But typing M-y does not bring the original copied text back, so I need to go back to my original program to copy the text again. And even worst if the original program is closed, then I lost the copied text completely.

Kill-line, etc. are such basic commands (like hitting the delete key, almost), and while I don't mind that the kill-ring gets a bit cluttered by using those command, I expect that my original text stays somewhere in the kill-ring so that I can eventually find it by typing M-y a few times. How can I make Emacs to automatically preserve the current clipboard content into the kill-ring before overriding the clipboard content?

+2  A: 

I think the problem is that when you yank from the clipboard outside emacs, you're not saving to the kill ring.

What you'd need is to use the function clipboard-yank to insert the region, then somehow select it and save it to the kill ring, like the function kill-ring-save does.

Or even better write a function clipboard-save-to-kill-ring-and-yank which saves the clipboad to the kill ring and then yanks it.

edit: Tracking through the code a bit, this does what you want; you could hook it up to a key. It saves the windows clipboard contents to the kill ring.

(defun clipboard-to-kill-ring()
  "save the external clipboard contents to the kill ring"
  (interactive)
    (let ((clip (funcall interprogram-paste-function)))
      (when clip
        (kill-new clip)))

(defadvice yank (before maybe-copy-windows-clipboard (arg))
    (clipboard-to-kill-ring))

(ad-activate 'yank)
justinhj
This is nice, but I need something automatic (in case I forget!) so that whenever I kill something, whatever on the clipboard is preserved to the kill-ring if it is not already there.
polyglot
I think my edit works. The before advice makes the yank command automatically save the windows clipboard to the kill ring.
justinhj
I think your code fails to work in the scenario: select text in a non-emacs window (say "XYZ") now kill some text in emacs (say "ABC") C-y M-y M-y ... the XYZ is not to be found b/c the selection is lost on the first kill, before the first yank can add it to the kill ring.
Trey Jackson
yes, you're right, yours works better
justinhj
A: 

I'd guess you could hack the various kill commands to not put text into the clipboard, and then have clipboard-yank bound to a different key, dunno if that would work.

shapr
A: 

I sort of work around this by just yanking the text then re-killing it, when I pop into emacs after having done a copy or cut in another windows app.

A better approach would be to hack emacs so that when you kill something, it compares the existing clipboard to the topmost entry in the kill ring, and if different, it pushes the clipboard contents to the kill ring, before doing the kill you explicitly requested.

Cheeso
You don't need to check whats on the kill ring with my solution because when you grab clipboard it clears it, so subsequent calls just get nil and they don't add that to the kill ring.
justinhj
+8  A: 

This code should automatically put the selection (from outside Emacs) onto the kill-ring any time you do a kill in Emacs. It's been tested on Linux, but shouldn't be restricted to Linux.

(defadvice kill-new (before kill-new-push-xselection-on-kill-ring activate)
  "Before putting new kill onto the kill-ring, add the clipboard/external selection to the kill ring"
  (let ((have-paste (and interprogram-paste-function
                         (funcall interprogram-paste-function))))
    (when have-paste (push have-paste kill-ring))))

If you find yourself doing this a lot, it may be useful to take a look at the package browse-kill-ring, which gives you a nice view of the kill ring (as opposed to repeatedly typing M-y).

Trey Jackson
simple, easy, perfect. I used this today. Had copied some text from a browser, and then went into emacs to paste it into a new file. Without realizing, I had used some kill commands on the file pathname as I was opening the new file. Without this script the clipboard content would be gone. But this time it worked as expected!
Cheeso
A: 

Note that latest Emacs CVS version have the variable save-interprogram-paste-before-kill which does exactly this cf: from the etc/NEWS file :

** When save-interprogram-paste-before-kill' is non-nil, emacs will not clobber the the interprogram paste when something is killed in it by saving the former in the kill-ring' before the latter.

Chmouel Boudjnah
Oh sweet! (15 chars)
polyglot