0

Is there a way to access the second last value of the clipboard in Emacs?

I assume it's possible to make this work within Emacs.

  • Intercept the copy function.
  • Read the clipboard and add it to a list.
  • Set the clipboard as expected.

Note, the reason I'm asking this is I'd like to make a shortcut to paste the second last item in the clipboard, so I can copy things while keeping access to what was already in the clipboard.

1
  • The "clipboard" means different things to different systems, so you probably want to specify the system more precisely. If you are using the X Window System, are you running the xclipboard program?
    – NickD
    Aug 10 '20 at 16:55
2

You're in luck; this is already built in. C-y yanks the last thing that you've killed or copied, and M-y replaces it with the next item from the kill-ring, which contains everything you've killed or copied in your current Emacs session.

2
  • ... but that's the kill ring, not the clipboard.
    – NickD
    Aug 10 '20 at 16:52
  • 2
    True, I suppose it's possible that ideasman42 could be asking about the system clipboard or the primary selection.
    – db48x
    Aug 10 '20 at 17:07
1

This can be done by advising the function that sets the clipboard.

;; Clipboard history.
(defvar my-clipboard-history-limit 10)
(defvar my-clipboard-history--list nil)

(defun my-clipboard-history-paste (&optional index)
  (insert (nth (or index 0) my-clipboard-history--list)))

(defun my-clipboard-history-paste-penultimate ()
  (interactive)
  (my-clipboard-history-paste))

(defun my-clipboard-history--gui-set-selection (orig-fn type data)
  (when (eq type 'CLIPBOARD)
    (let ((old-data (gui-get-selection type)))
      (when old-data
        (let ((trim-number (- (length my-clipboard-history--list)
                              my-clipboard-history-limit)))
          (when (> 0 trim-number)
            (nbutlast my-clipboard-history--list trim-number)))
        (push old-data my-clipboard-history--list))))
  (funcall orig-fn type data))

;;;###autoload
(define-minor-mode my-clipboard-history-mode
  "Highlight block under the cursor."
  :global t
  :lighter
  ""
  (cond
   (my-clipboard-history-mode
    (advice-add
     'gui-set-selection :around
     #'my-clipboard-history--gui-set-selection))
   (t
    (advice-remove
     'gui-set-selection
     #'my-clipboard-history--gui-set-selection))))

(provide 'my-clipboard-history-mode)

You can bind this to Alt-P in evil mode, for example:

(define-key evil-normal-state-map (kbd "M-p")
  'my-clipboard-history-paste-penultimate)
(define-key evil-insert-state-map (kbd "M-p")
  'my-clipboard-history-paste-penultimate)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.