40

When I M-x find-file a PDF, it is opened in Emacs. While this is nice, Emacs' PDF viewer lacks many features that I need and I would prefer to open PDFs in an external program instead. How can I configure Emacs to use an external program as the default viewer for PDFs?

31

Try openwith. The following code will enable it, and allow you to open PDFs with evince (change to your favorite PDF viewer):

(require 'openwith)
(openwith-mode t)
(setq openwith-associations '(("\\.pdf\\'" "evince" (file))))
  • 1
    I'm surprised that a third-party package is needed for something simple as that. But it works, thank you! – tmalsburg Nov 4 '14 at 23:28
  • It is not needed (see Drew's answer) but it is a nice and clean way to do it. Note that it will possibly conflict with other programs, like a music reader (mpg123) if you use one. – Ehvince Nov 5 '14 at 9:55
  • This solution has problems. It appears that some packages don't like it when you mess with find-file. For instance, sending emails with attached PDFs (via mu4e) causes the attached PDF to be opened in the external editor and sending fails (see here for details). – tmalsburg Nov 13 '14 at 5:34
  • 1
    @tmalsburg: have a look at this SO thread discussing the problem with email attachments and a solution in that particular use case. – Dan Nov 13 '14 at 11:17
  • I just wrote a bit of code to advise the commands that don't work with openwith-mode to turn it off: see this gist. – Omar Dec 3 '14 at 22:21
19

If you want to view PDF with many features (highlighting search, highlighting selection, annotate, content tree), use pdf-tools. As you can see in the demo, I can using Isearch with highlighting. Emacs is now my favourite PDF reader. You can also bookmark specific PDF page by using Bookmark(+).

EDIT: If you use helm and want to use external program, helm already has one in the action menu for opening external file: Open file externally C-c C-x. C-u to choose again. What it does it that it offers a list of all available programs in your system and present you with a nice Helm interface to select from; once you select, Helm remembers it until you run the command with prefix argument C-u to select a new one.

  • 3
    +1 I can't thank you enough for mentioning pdf-tools!! AMAZING package. Love it! Your demo is great as well, even though it only scratches the surface of what's possible... :) – itsjeyd Nov 5 '14 at 8:38
  • pdf-tools doesn't seem available through standard package managers though, and the install procedure doesn't seem to work with emacs 24.4 :/ – Clément Nov 5 '14 at 16:07
  • It works for me. But you have to clone the pdf-tools repo and compile and install the C part anywhere your Emacs can see the binary, before installing and using the Emacs Lisp part. – Tu Do Nov 5 '14 at 16:12
  • Does pdf-tools allow you to highlight (i.e. in yellow) words and phrases or no? – incandescentman Jun 30 '15 at 17:31
11

You asked about find-file. In addition to what others (e.g., Dan) say about that, it is worthwhile to also know about opening files using an application associated with the file type (e.g. extension) in option dired-guess-shell-alist-user. And if you use Emacs on MS Windows, then it is worthwhile knowing how to open a file using Windows file associations.

Option dired-guess-shell-alist-user is available after you load standard library dired-x.el. The default association of a PDF file is defined in variable dired-guess-shell-alist-default, and it is program xpdf (available on UNIX and GNU/Linux). Using option dired-guess-shell-alist-user you can, for instance, associate it instead with Adobe Acrobat Reader by adding this association to the alist: ("\.pdf$" . "AcroRd32.exe").

Then you can open a PDF file in Dired just by using !. That provides default programs as "guesses", which you can access by repeating M-n. So ! followed by M-n will give you the shell command AcroRd32.exe if point is on a PDF file name and if that command/program is associated with regexp \.pdf$.

In addition to Dired, you can make use of the file associations in dired-guess-shell-alist-user as a bookmark file handler, that is, have the PDF file association take effect for any bookmarks to PDF files, if you use library Bookmark+. The current value of dired-guess-shell-alist-user is used as the default value of option bmkp-default-handlers-for-file-types, which controls this.

You can think of options dired-guess-shell-alist-user and bmkp-default-handlers-for-file-types as somewhat analogous to auto-mode-alist. But they map file-name patterns to file actions instead of mapping them to buffer modes. And they take effect only when you use certain commands.

If you use MS Windows then you can instead (or also) take advantage of existing Windows file associations when you open a file in Dired or "jump" to a bookmark. For this you need library w32-browser.el.

For Dired, you also need library Dired+ - see Using Windows File Associations in Dired. For bookmarks, you also need Bookmark+ - see Bookmarking Files You Cannot Visit With Emacs and Opening Bookmarks Using Windows File Associations.

3

I'm using runner. Here is an excerpt of my configuration file

    (defun my:open-file-with-dired (file)
      "Ask dired how it would open FILE.
This code is useful if dired is well configured to open files
with external applications. I recommend using the `runner`
package to do so."
      (use-package dired-aux)
      (dired-do-async-shell-command
       (dired-guess-shell-command (format  "Open %s " file) (list file))
       0
       (list file)))

    (add-to-list 'org-file-apps '(t . (my:open-file-with-dired file)))
    (add-to-list 'org-file-apps '("\\.png\\'" . default))
0

My way to achieve this without any plugins is the following. I run Emacs 25.3 under Ubuntu 16.04 LTS. If your OS is macOS or Windows, you definitely need to change the the first function xdg-open defined here. I found this link very helpful as a starting point.

(defun xdg-open (filename)
  (interactive "fFilename: ")
  (let ((process-connection-type))
    (start-process "" nil "xdg-open" (expand-file-name filename))))

(defun find-file-auto (orig-fun &rest args)
  (let ((filename (car args)))
    (if (cl-find-if
         (lambda (regexp) (string-match regexp filename))
         '("\\.pdf\\'" "\\.docx?\\'"))
        (xdg-open filename)
      (apply orig-fun args))))

(advice-add 'find-file :around 'find-file-auto)

After the above code is loaded, when you press C-x C-f for PDF and word file, it will automatically open the file using system default app.

I really like the advice mechanism provided by Emacs, see (elisp) Advising Functions. By advising existent function in a compatible way, I avoid re-binding common keys like C-x C-f to new function.

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.