Copy/paste with emacs in terminal
Posted: March 8, 2009 Filed under: Uncategorized 32 CommentsI often run emacs in a terminal window. The following is a way to get copy-paste “working” to and from other applications. Note that it requires xsel, “a command-line program for getting and setting the contents of the X selection”. See also http://shreevatsa.wordpress.com/2006/10/22/emacs-copypaste-and-x/
;; https://hugoheden.wordpress.com/2009/03/08/copypaste-with-emacs-in-terminal/ ;; I prefer using the "clipboard" selection (the one the ;; typically is used by c-c/c-v) before the primary selection ;; (that uses mouse-select/middle-button-click) (setq x-select-enable-clipboard t) ;; If emacs is run in a terminal, the clipboard- functions have no ;; effect. Instead, we use of xsel, see ;; http://www.vergenet.net/~conrad/software/xsel/ -- "a command-line ;; program for getting and setting the contents of the X selection" (unless window-system (when (getenv "DISPLAY") ;; Callback for when user cuts (defun xsel-cut-function (text &optional push) ;; Insert text to temp-buffer, and "send" content to xsel stdin (with-temp-buffer (insert text) ;; I prefer using the "clipboard" selection (the one the ;; typically is used by c-c/c-v) before the primary selection ;; (that uses mouse-select/middle-button-click) (call-process-region (point-min) (point-max) "xsel" nil 0 nil "--clipboard" "--input"))) ;; Call back for when user pastes (defun xsel-paste-function() ;; Find out what is current selection by xsel. If it is different ;; from the top of the kill-ring (car kill-ring), then return ;; it. Else, nil is returned, so whatever is in the top of the ;; kill-ring will be used. (let ((xsel-output (shell-command-to-string "xsel --clipboard --output"))) (unless (string= (car kill-ring) xsel-output) xsel-output ))) ;; Attach callbacks to hooks (setq interprogram-cut-function 'xsel-cut-function) (setq interprogram-paste-function 'xsel-paste-function) ;; Idea from ;; http://shreevatsa.wordpress.com/2006/10/22/emacs-copypaste-and-x/ ;; http://www.mail-archive.com/help-gnu-emacs@gnu.org/msg03577.html ))
Thanks to Nikolaj Schumacher and Miles Bader on the help-gnu-emacs mailing list for helping out.
This is a great hack and it works perfectly. I’ve been looking for similar solution for months. Thank you so much for sharing it. You made my day. 🙂
Cheers,
rbz
[…] clipboard into Emacs. In some of the comments below, Richard Lewis had the idea of using xsel, and Hugo Heden completed it further. Possibly related posts: (automatically generated)Using EmacsclientEditing TEXTAREAs in an external […]
Thanks, I’ve been looking for this for a long time, very nice. I suppose the correct way of loading the functions is by putting a line in my `.emacs’ file, this worked for me:
(load "~/copypaste/copypaste.el")
Yes, thanks for mentioning that, that looks reasonable. (You could also just paste the whole piece of code into .emacs, but your version seems cleaner.) More about loading files: http://www.gnu.org/software/emacs/emacs-lisp-intro/html_node/Loading-Files.html
Excellent Post! Outstanding 🙂 The best in this month 🙂 Have been searching for this for a while.
With this post, copy-paste works in my emacs/putty/cygwin. I had to replace the xsel with putclip and getclip commands (for cygwin). And voila, it worked!
Thanks, glad to help 🙂 Thanks for the putty/cygwin info, that’s useful!
Hi, can you share your edition of this for cygwin?
Thanks a lot!
Thanks that worked great!
I am using emacs-nox in a xfce4-terminal in xubuntu. I had to remove –output from the definition of xsel-output
Otherwise I would get “/bin/bash: –output command not found” at the end of the string copied.
Ok, so instead of
(let ((xsel-output (shell-command-to-string "xsel --clipboard --output")))
you are using just
(let ((xsel-output (shell-command-to-string "xsel --clipboard")))
– is that correct? Not sure how that can work, but it’s useful info for others that may find their way here, thanks!
Correct.
It works fine when I am using emacs on the desktop locally. It breaks down when I am using emacs remotely over ssh. The first yank produces “xsel: can’t open display (null): Invalid argument” M-y then pastes the copied text.
Cheers
giulio
Aah.. I hadn’t thought about that. I guess you’ve found a limitation in the code above.
If you log in on a remote machine using ssh you’ll have to use ssh -X for this whole thing to work, so that the remote shell you’re using (specifically the xsel program) has “access” to the X-server on your local machine.
Putting it another way: this trick requires a graphical environment — an X-server (or a Windows equivalent — see the comment from Mohamad Alrawashdeh) — whose “clipboard” we use to copy to and from, with the help from the xsel program (or putclip/getclip).
Without ssh -X (using just plain ssh) the code above is pointless.. It’s like logging in to a completely non-graphical environment — it’s just a terminal — there’s no “global clipboard” that can be used to copy and paste from.
You should be able to verify this on the command line on the remote machine: xsel should not work at all without -X:
$ xsel --clipboard
xsel: Can't open display: (null)
So the “script” above should probably detect if there’s no display, and in that case revert to regular emacs behaviour. Contributions welcome 🙂
Another issue with this code, I believe, is handling new
emacs --daemon
mode; Nowadays, the same “emacs process” (the daemon) can run in a GUI-window and in a terminal, often simultaneously. This code does not handle that — I guess it performs the check for whether emacs is run in terminal or GUI-window at emacs start-up.. Hmm.Thank you so much for this! It is so unusual to find a solution that just works perfectly like this!
Glad to hear it, thanks!
I may be late in posting this but I have been looking for a long time for something like this. I am a student and new to emacs and programming. My professor is unwilling or unable to provide me any guidance in this matter and I just need to know how to actually accomplish the procedure.
My assignments consist of editing large C++ files in order to complete a program. The instructor provides the basic source code in a text file which we are supposed to edit in emacs and then compile. I access emacs remotely through VNC and cannot figure out how to copy the text files into the emacs editor window. The source code is too large to just type into the editor although that is what I have been doing.
Where and how would I enter the following code:
(setq x-select-enable-clipboard t)
Thank you kindly.
Sorry, can’t help you.. How about starting with just transferring the instructor’s source-file to the remote computer (on which emacs runs) and then just open the file with emacs?
Also, in some configurations and cases, middle-clicking works as paste.
This. Is. Sicknasty. Exactly what I was looking for. Well ‘effing done.
Hehe, thanks
Thank you for this, it’s been bothering me for quite some time. I guess to ought to add Emacs Lisp to the ever-growing list of things to learn.
Fix to not add hooks if DISPLAY is unset:
http://pastebin.com/NSZgWLLQ
Thanks Daniel. That’s useful. I’ve added your additions to the code above: The two lines the check the $DISPLAY variable early in the script (currently colored in green), and the two extra parantheses right at the end.
I am guessing it is better/faster to use (getenv “DISPLAY”) instead spinning a new process and relying on “echo” being there with (shell-command-to-string “echo $DISPLAY”)
And so it now becomes:
(when (getenv "DISPLAY")
(defun xsel-cut-function
...))
Thanks Ilya, that seems reasonable. I’ve updated the code as per your suggestions.
Thnx Hugo a ton. This makes the work flow so less painful!
[…] 参考:https://hugoheden.wordpress.com/2009/03/08/copypaste-with-emacs-in-terminal/ 此条目由 vancel1 发表在 2012-03 分类目录,并贴了 emacs 标签。将固定链接加入收藏夹。 […]
Thank you! Emacs’ complete takeover of my computing life is one step closer.
[…] https://hugoheden.wordpress.com/2009/03/08/copypaste-with-emacs-in-terminal/ […]
非常感谢,我找了很长时间,很多网上说的pbpaste和pbcopy都是在mac上的,linux上根本用不了,太感谢了!
[…] 终端下的 Emacs 访问系统剪切板,方便不同程序间的复制粘贴,fromhttps://hugoheden.wordpress.com/2009/03/08/copypaste-with-emacs-in-terminal/ […]
[…] 终端下的 Emacs 访问系统剪切板,方便不同程序间的复制粘贴,fromhttps://hugoheden.wordpress.com/2009/03/08/copypaste-with-emacs-in-terminal/ […]
[…] 终端下的 Emacs 访问系统剪切板,方便不同程序间的复制粘贴,fromhttps://hugoheden.wordpress.com/2009/03/08/copypaste-with-emacs-in-terminal/ […]
добродушный ресурс http://4xcasino.ru
This is really great! Thank you very much for this script.