4

I am running Emacs in Gnome-terminal on Ubuntu.

The way I know to copy and paste between emacs and other applications is by Ctrl+C and Ctrl+V, which I think is by the terminal emulator.

A problem with that is it will copy the line continuation symbol \ in Emacs.

How can I do that flawlessly? Can you explain why your way works? Thanks.

Btw, I asked a similar question with output of less, which I heard uses vi. If possible, could you also take a look at it?

Tim
  • 4,987
  • 7
  • 31
  • 60

2 Answers2

7

You can use the external utilities xsel or xclip (they have mostly the same features, I'll use xsel in this answer) to copy data from or to the X clipboard. To copy to the clipboard, pass the desired content on standard input. When pasting from the clipboard, the content is written to standard output.

To copy the selection to the X clipboard, use M-| xsel -bi RET (shell-command-on-region). If you want to copy to the X selection (which can be pasted with the middle mouse button), use xsel -i. To paste from the X selection, you can use the middle mouse button or M-1 M-! xsel -o RET (shell-command with a prefix argument to insert the output into the current buffer); make that xsel -bo to insert the clipboard content.

If you want to copy and paste automatically to the X selection or clipboard (when available) when running in a terminal under X, like what happens when running in an X window, you can set the variables interprogram-cut-function and interprogram-paste-function to functions that call xsel. Here's some minimally-tested code to automatically copy to the X clipboard when running in a text terminal under X.

(defmacro with-x-environment (&rest body)
  `(let ((process-environment
            (cons (concat "DISPLAY=" (getenv "DISPLAY" (selected-frame)))
                  process-environment)))
     (if (getenv "XAUTHORITY" (selected-frame))
          (setq process-environment
                       (cons (concat "XAUTHORITY=" (getenv "XAUTHORITY" (selected-frame)))
                                  process-environment)))
     ,@body))
(defun x-terminal-copy (text)
  (with-temp-buffer
    (insert text)
    (with-x-environment
     (call-process-region (point-min) (point-max) "xsel" nil nil nil "-bi"))))
(defadvice x-select-text
  (before x-select-text-in-tty activate)
  "Use xsel to copy to the X clipboard when running in a terminal under X."
  (when (and (eq (framep (selected-frame)) t)
                  (getenv "DISPLAY" (selected-frame)))
    (x-terminal-copy text)))

If you want automatic pasting as well, the following code should do it, but in a possibly annoying way: it always considers the X clipboard to be newer than Emacs's internal buffers, so it will always paste from X. You may find it more convenient to bind X pasting to a different key instead.

(defun x-terminal-paste ()
  (with-temp-buffer
    (with-x-environment
     (call-process "xsel" nil t nil "-bo"))))
(defadvice x-cut-buffer-or-selection-value
  (before x-cut-buffer-or-selection-value-in-tty activate)
  "Use xsel to paste from the X clipboard when running in a terminal under X."
  (when (and (eq (framep (selected-frame)) t)
                  (getenv "DISPLAY" (selected-frame)))
    (x-terminal-paste text)))
Chris
  • 143
  • 5
  • Thanks. Gilles. [Here](http://www.gnu.org/software/emacs/manual/html_mono/eshell.html) it says "Use Eshell when you want to move text between Emacs and external processes". Can Eshell also accomplish the same thing as what we discussed here? – Tim Oct 23 '14 at 19:08
  • @Tim I don't understand the connection between this question and eshell. In eshell, the input and output of processes is normal Emacs buffer text. It has nothing to do with copy-paste between Emacs and other **X** applications. – Gilles 'SO- stop being evil' Oct 23 '14 at 19:58
2

Gilles's solution actually exists as a package, called xclip available from GNU ELPA. I.e. install it from M-x list-packages and then enable it with M-x xclip-mode RET.

See also Clipboard manager will not work in terminal Emacs which is basically the same question.

Stefan
  • 26,154
  • 3
  • 46
  • 84