35

In Org-mode when I try to open a link to a PDF file nothing happens. Also, when I do C-c C-e d to export as LaTeX and process to PDF and open the PDF is generated but not opened. How do I make Org-mode open PDF files in Evince?

I am using Org-mode 7.6 in GNU Emacs 23.3.1 and Evince 3.2.1 in Ubuntu 11.10.

N.N.
  • 8,336
  • 12
  • 54
  • 94

3 Answers3

23
M-x customize-variable [RET] org-file-apps [RET]

If org uses your system defaults, you have to edit your ./mailcap file.

Try adding this line:

application/pdf; /usr/bin/evince %s
certainly
  • 547
  • 3
  • 5
  • Is there a line I can add to my .emacs rather than having to use `M-x customize-variable [RET] org-file-apps [RET]`? – N.N. Jan 12 '12 at 12:09
  • `org-file-apps` includes `("\\.pdf\\'" . default)` according to `find-variable`. – N.N. Jan 12 '12 at 12:13
  • You could probably add something to your .emacs along the lines of `(setq org-file-apps...)`, but I don't see why you wouldn't set the variable according to your needs. If you try `F1 v org-file-apps`, the first example that comes up is this `Example: ("pdf" . "evince %s") to open PDFs with evince.` So have a look at the help file and try setting it to evince. – certainly Jan 12 '12 at 13:23
  • 1
    Your solution with `customize-variable` and adding `evince %s` for pdf works. However I think that `customize-variable` obfuscates the .emacs so I came up with a solution without `customize-variable`, see my answer http://stackoverflow.com/a/8836108/789593. – N.N. Jan 12 '12 at 13:49
12

Another possible construct that could work for this would be to use eval-after-load rather than add-hook. It will only set the values once on startup, you won't have to worry about entries being added or not (unless you regularly reload org).

Combine that with setcdr and you can avoid having to delete from the list and then re-add, add if and you'll ensure that you either add or change the value. The if is only needed for values that aren't in the list by default, just to make sure you don't end up with conflicts somewhere down the line.

(eval-after-load "org"
  '(progn
     ;; .txt files aren't in the list initially, but in case that changes
     ;; in a future version of org, use if to avoid errors
     (if (assoc "\\.txt\\'" org-file-apps)
         (setcdr (assoc "\\.txt\\'" org-file-apps) "notepad.exe %s")
       (add-to-list 'org-file-apps '("\\.txt\\'" . "notepad.exe %s") t))
     ;; Change .pdf association directly within the alist
     (setcdr (assoc "\\.pdf\\'" org-file-apps) "evince %s")))

Edit for clarification

eval-after-load only evaluates the block when (require 'org) is called. If org is already loaded it will evaluate immediately (I mistakenly thought it ran each time a library was loaded, but it seems to be only the first time). The difference between add-hook and eval-after-load is explained here.

Since org-file-apps is a defcustom it won't change the values if you set them before org is loaded, if you build the list from scratch (including default values as in your second (uglier) solution) you could simply setq in your init.el and everything would work. It also means it won't overwrite your changes.

Adding (if (assoc to the PDF entry won't hurt anything, it will simply ensure that if PDFs are ever removed from the default org-file-apps that it will still be added. The only solution that would not fail if PDFs were removed is your second one. The others all assume the entry exists in one form or another.

Community
  • 1
  • 1
Jonathan Leech-Pepin
  • 7,684
  • 2
  • 29
  • 45
  • I sometimes load org-mode for buffers several times in a session. Does that affect this solution? Or is it just if I use `org-reload`? Also, could I add a `(if (assoc` structure for pdfs to make it future proof? – N.N. Feb 02 '12 at 16:39
  • @N.N added some details in an edit that should answer that question. – Jonathan Leech-Pepin Feb 02 '12 at 21:48
  • Thanks for your elaboration. This solution is the most elegant so far. – N.N. Feb 03 '12 at 18:31
11

You can use a construct similar to https://stackoverflow.com/a/3985552/789593 but adapt it to PDF files and Evince. What you want to do is to alter the list org-file-apps. This can be done by adding the following to your .emacs:

;; PDFs visited in Org-mode are opened in Evince (and not in the default choice) https://stackoverflow.com/a/8836108/789593
(add-hook 'org-mode-hook
      '(lambda ()
         (delete '("\\.pdf\\'" . default) org-file-apps)
         (add-to-list 'org-file-apps '("\\.pdf\\'" . "evince %s"))))

This will delete the default setting for PDF files and instead open them in Evince (and retain everything else included in org-file-apps). I am new to elisp so I do not know if this solution is robust, but it works for me and seems to be more elegant than the one below.

Another option, which seems uglier, is to instead look up the default values and set them all that but change the value for PDF files:

;; PDFs visited in Org-mode are opened in Evince (and other file extensions are handled according to the defaults)
(add-hook 'org-mode-hook
      '(lambda ()
         (setq org-file-apps
           '((auto-mode . emacs)
             ("\\.mm\\'" . default)
             ("\\.x?html?\\'" . default)
             ("\\.pdf\\'" . "evince %s")))))
Community
  • 1
  • 1
N.N.
  • 8,336
  • 12
  • 54
  • 94
  • @certainly I have edited the solution because `append` added the entry everytime org-mode was invoked which flooded the variable. Maybe I can do something more elegant with `add-to-list`. – N.N. Jan 12 '12 at 16:22
  • @certainly I have added something that might be more elegant. – N.N. Jan 12 '12 at 16:49
  • your solution looks like it should do the job! I have no knowledge of elisp so I am glad to have the Customize system in Emacs but it is not without flaws. I hope that there will someday be a more advanced tool to organize and keep track of preferences in emacs with a more intuitive interface. There are some projects that point in this direction but AFAIK nothing that is really convenient. – certainly Jan 12 '12 at 17:32