4

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.

4
  • 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
5

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)
    map))

(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.

5
  • 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). – dalanicolai Jun 15 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 at 11:44
  • @tobias Ah okay, thanks for that info and for the code! – dalanicolai Jun 17 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). – dalanicolai Jun 17 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.