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))
This is what I put in my init file:
(setq dired-guess-shell-alist-user '(("\\.pdf$" "nohup xdg-open * </dev/null >/dev/null 2>&1 &")))
dired-guess-shell-alist-user as suggested in the answer by Drew and
xdg-open as suggested by Lei Zaho. So when I hit
! in dired it will open the pdf with my pdf viewer picked by
xdg-open (my OS is Ubuntu). Furthermore the stdin, stdout and stderr is redirected. This has the effect that no strange
nohup.out will be created. This is according to the thorough answer given by Mark Reed on how to avoid nohup.out.
Lastly to make it work also add
or something comparable to your init.el. The necessity to load
dired-x is mentioned by Sean Allred in responde to a similar question.
The code above only works for dired, so
find-file will not work. Furthermore, it also splits the dired window in half giving a short message, which is a little bit annoying.
I added this answer, because I found the
* notation helpful, which is mentioned in the online documentation. The asterix notation allows one to wrap the command in
& to let it run in background and not terminate when the terminal is closed.
Adding further file extensions besides
(setq dired-guess-shell-alist-user '(("\\.pdf$" "nohup xdg-open * </dev/null >/dev/null 2>&1 &") ("\\.jpg$" "nohup xdg-open * </dev/null >/dev/null 2>&1 &") ("\\.ods$" "nohup xdg-open * </dev/null >/dev/null 2>&1 &")))
Edit 1: Added input and output redirection to nohup
Edit 2: Add hint to (require 'dired-x) (sry for bumping old thread, last edit I promise)
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.