I use pdf-tools in Emacs to view PDF documents. I would like to be able to select words (mark their region and then copy them to the kill-ring) in the PDF by double-clicking on them. Is there a function in pdf-tools or elsewhere I could use to obtain this functionality?

More specifically, I want to write a function (unless it already exists in some form)

(defun select-word-on-doubleclick (ev)
    "Set region to the word under the mouse pointer and copy it to the kill-ring"
    (interactive "@e")
    ...  ;; Set region to the word under the pointer
    (pdf-view-kill-ring-save)  ;; Save region to kill-ring

and bind it to <double-mouse-1>. I need help filling out the dots above.

In the pdf-tools package there is a function called

(pdf-info-gettext PAGE EDGES &optional SELECTION-STYLE FILE-OR-BUFFER)

which could be useful for this purpose. Based on the event ev, the position of the mouse pointer (when double-clicked) can be obtained. If somehow the edges of the word under the pointer could be determined from this position, the function above would do the trick. I greatly appreciate any hints on how to make this computation.

  • In what way is this emacs-related?
    – NickD
    Sep 2 '19 at 1:44
  • @NIckD pdf-tools is an Emacs package.
    – Tobias
    Sep 2 '19 at 7:38
  • @NickD: As pointed out by Tobias, my question concerns the pdf-tools Emacs package. I added some clarification to the question.
    – StarBug
    Sep 2 '19 at 8:07
  • Thanks! I was confused indeed: there's a pdf-tools package on Fedora that has nothing to do with the emacs package of the same name (at least, at first sight).
    – NickD
    Sep 2 '19 at 17:02

At first, note that pdf-sync binds mouse-double-1 in the minor mode pdf-sync-minor-mode to pdf-sync-backward-search-mouse. So one should probably only bind it in a minor mode that can be deactivated again.

The following code defines a minor mode pdf-sel-mode that binds mouse-double-1 to a new command pdf-sel-mouse. pdf-sel-mouse selects the word below the mouse pointer and copies it to the kill-ring.

(defvar pdf-sel-mode-map nil
  "Keymap for `pdf-sel-mode'.")

(setq pdf-sel-mode-map
      (let ((map (make-sparse-keymap)))
    (define-key map [double-mouse-1] 'pdf-sel-mouse)

(define-minor-mode pdf-sel-mode
  "\\<pdf-sel-mode-map>Just binding \\[pdf-sel-mouse] to `pdf-sel-mouse'.
`pdf-sel-mouse' selects the text at point and copies it to `kill-ring'."
  :keymap pdf-sel-mode-map)

(defvar pdf-view-active-region) ;; defined in "pdf-view.el"

(defun pdf-sel-mouse (ev)
  "Select word at mouse event EV and copy it to `kill-ring'."
  (interactive "@e")
  (let* ((posn (event-start ev))
     (xy (posn-object-x-y posn))
     (size (pdf-view-image-size))
     (page (pdf-view-current-page))
     (x (/ (car xy) (float (car size))))
         (y (/ (cdr xy) (float (cdr size)))))
    (setq pdf-view-active-region (pdf-info-getselection page (list x y x y) 'word))
    (pdf-view-display-region pdf-view-active-region)
    (kill-new (pdf-info-gettext page (list x y x y) 'word))))

Note, that this function sometimes selects more than a word. But that is what epdfinfo interprets as a word.

  • Works like a charm! Thank you so much.
    – StarBug
    Sep 2 '19 at 16:49
  • "We" would be very happy if you could submit a PR for this to the new pdf-tools repo. In case of no reply, I guess you do not mind that one of us will submit a PR with your code (let us know in case you prefer anyway that we create the PR). Jun 15 '21 at 14:12
  • @dalanicolai All stuff on the SE network is CC. So feel free to use the code in accordance to CC. (I think you only need to mention the license and the original author somewhere in the code). But see for yourself.
    – Tobias
    Jun 17 '21 at 11:44
  • @tobias Ah okay, thanks for that info and for the code! Jun 17 '21 at 13:05
  • @tobias I assume that we can leave out the link to the license (it is only a small snippet, and it is used, and can only be used, in an Emacs package). We will mention your name and a link to this post. B.t.w. do you (or anybody reading this) happen to know how to bind this to a triple click (just replacing double with triple in the vector does not seem to work). Jun 17 '21 at 13:14

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.