Copy/Paste in Emacs

  |   Source

CREATED: <2012-01-30 Mon>

UPDATED: <2018-06-04 Mon>

Prepare

At Linux, xsel is required.

At Cygwin, please install package cygutils-extra.

At macOS, no external tool is required.

At Windows 10 Linux Subsystem, no external tool is required.

Solution

This solution works reliably in any environment.

Insert below code into ~/.emacs. Run M-x paste-from-xclipboard to paste.

(defun my-gclip ()
  "Get clipboard content."
  (cond
   ((eq system-type 'darwin)
    (with-output-to-string
      (with-current-buffer standard-output
        (call-process "/usr/bin/pbpaste" nil t nil "-Prefer" "txt"))))
   ((eq system-type 'cygwin)
    (with-output-to-string
      (with-current-buffer standard-output
        (call-process "getclip" nil t nil))))
   ((memq system-type '(gnu gnu/linux gnu/kfreebsd))
    (let* ((powershell-program (executable-find "powershell.exe")))
           (cond
            (powershell-program
             ;; PowerLine adds extra white space character at the end of text
             (string-trim-right
              (with-output-to-string
                (with-current-buffer standard-output
                  (call-process powershell-program nil t nil "-command" "Get-Clipboard")))))
            (t
             (with-output-to-string
               (with-current-buffer standard-output
                 (call-process "xsel" nil t nil "--clipboard" "--output")))))))))

(defun my-pclip (str-val)
  "Copy STR-VAL into clipboard."
  (cond
   ((eq system-type 'darwin)
    (with-temp-buffer
      (insert str-val)
      (call-process-region (point-min) (point-max) "/usr/bin/pbcopy")))
   ((eq system-type 'cygwin)
    (with-temp-buffer
      (insert str-val)
      (call-process-region (point-min) (point-max) "putclip")))
   ((memq system-type '(gnu gnu/linux gnu/kfreebsd))
    (let* ((win64-clip-program (executable-find "clip.exe")))
      (with-temp-buffer
        (insert str-val)
        (cond
         ;; Linux Subsystem on Windows 10
         (win64-clip-program
          (call-process-region (point-min) (point-max) win64-clip-program))
         (t
          (call-process-region (point-min) (point-max) "xsel" nil nil nil "--clipboard" "--input"))))))))

(defun paste-from-x-clipboard(&optional n)
  "Paste string clipboard."
  (interactive "P")
  ;; paste after the cursor in evil normal state
  (when (and (functionp 'evil-normal-state-p)
             (functionp 'evil-move-cursor-back)
             (evil-normal-state-p)
             (not (eolp))
             (not (eobp)))
    (forward-char))
  (insert (my-gclip)))

(add-hook 'minibuffer-setup-hook
          (lambda ()
            (local-set-key (kbd "M-y") 'paste-from-xclipboard)))

My actual setup is more robust. See https://github.com/redguardtoo/emacs.d/blob/master/lisp/init-clipboard.el for details.

Tips

Clipboard manager

I suggest Parcellite on Linux, Ditto on Windows, Flycut on macOS.

My parcellite setup ($HOME/.config/parcellite/parcelliterc):

[rc]
use_copy=true
use_primary=true
synchronize=true
save_history=true
history_limit=64
hyperlinks_only=false
confirm_clear=false
single_line=true
reverse_history=false
item_length=50
ellipsize=2
history_key=<Super>Y
actions_key=
menu_key=
history_pos=false
history_x=1
history_y=1
case_search=false
type_search=false
data_size=0
ignore_whiteonly=false
trim_wspace_begend=false
trim_newline=false

Clipboard in ssh

Use ssh -X -C username@some-server.whatever.domain.

Comments powered by Disqus