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?
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))))
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.
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.
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
! 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
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
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
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.
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))
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
defined here. I found this link very helpful as a starting
(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
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.