3

On

GNU Emacs 25.1.50.2 (x86_64-pc-linux-gnu, GTK+ Version 3.10.8) of 2016-04-25
Org-mode version 8.2.10 (release_8.2.10 @ /usr/share/emacs/25.1.50/lisp/org/)

opening a pdf file link (f.ex. [[./9.pdf]]) via C-c C-o automatically opens that file in docview-mode.

How can this be disabled? (Or is this a bug? Where to submit?)

  • 2
    I am on emacs-25 branch and using the master branch of org. For me, pdf files open in my system default application: acroread. What do you see on doing C-h v org-file-apps? I see ((auto-mode . emacs) ("\\.mm\\'" . default) ("\\.x?html?\\'" . default) ("\\.pdf\\'" . "acroread %s")) – Kaushal Modi Jun 3 '16 at 16:04
  • Here is a link to the same question, with no accepted answer: emacs.stackexchange.com/q/2856/2287 The question in this current thread is unclear without reading the recent comment underneath @zck answer. – lawlist Jun 3 '16 at 16:34
  • I had an opportunity to try this today with Emacs -Q without any user-configuration on OSX 10.11.5 (El Capitan) and org-mode version 8.2.10. The example works as advertised by opening up the pdf file in my default system-defined application of Skim.app. Please try with Emacs -Q and see if it works correctly. If it works with Emacs -Q, then something in your user configuration has caused the conflict. Recursively bisect your user configuration by commenting stuff out until you find the culprit. – lawlist Jun 3 '16 at 21:25
  • @KaushalModi: org-file-apps’s value is ((auto-mode . emacs) ("\\.mm\\'" . default) ("\\.x?html?\\'" . default) ("\\.pdf\\'" . default)) – serv-inc Jun 4 '16 at 14:43
  • @lawlist: same behavior for emacs -Q this is the snapshot version. The other question asked about configuration. This is about restoring the default. How would you clarify? (feel free to edit, if you wish) – serv-inc Jun 4 '16 at 14:45
3

It happens because doc-view was added to mailcap-mime-data; I am using

(defun ensc/mailcap-mime-data-filter (filter)
  ""
  (mapcar (lambda(major)
        (append (list (car major))
            (remove nil
                (mapcar (lambda(minor)
                      (when (funcall filter (car major) (car minor) (cdr minor))
                    minor))
                    (cdr major)))))
      mailcap-mime-data))

(defun ensc/no-pdf-doc-view-filter (major minor spec)
  (if (and (string= major "application")
       (string= minor "pdf")
       (member '(viewer . doc-view-mode) spec))
      nil
    t))

(eval-after-load 'mailcap
  '(progn
     (setq mailcap-mime-data
       (ensc/mailcap-mime-data-filter 'ensc/no-pdf-doc-view-filter))))

to remove corresponding entry.

This does not solve only the org-mode problem but allows e.g. to display PDFs in gnus using an external viewer.

  • Thanks. Evaluating this indeed solves the problem for me. However, this seems to be a bit "crazy" to me, why does the mailcap-mime-data variable contain this setting in the beginning? – Christian Herenz Mar 5 '17 at 19:55
3

I wanted it to use the previous behavior: the system's pdf viewer.

Then restore the original value of the variable org-file-apps to contain:

((auto-mode . emacs)
 ("\\.pdf\\'" . default))

So whatever is the default viewer on your linux system will be used. To go back to doc-view, put this in your init file:

(add-to-list 'auto-mode-alist '("\\.pdf\\'" . doc-view-mode-maybe))

In any case, as others have pointed out, you'll have to bisect your init file to see what or where your defaults are being changed.

  • As far as I can see, this does not work (on Linux) since default wires to system, which calls mailcap and therein, doc-view-mode is hard coded in the starting value of mailcap-mime-data. – Michaël Oct 16 '18 at 12:50
1

Assume you are using a Linux distro.

There are several ways to achieve the effects you want and each of them comes with advantages and disadvantages.

The simplistic way to achieve this is to set org-file-apps to:

((auto-mode . emacs)
 ("\\.mm\\'" . default)
 ("\\.x?html?\\'" . default)
 ("\\.pdf\\'" . "evince $s"))

The advantage of this approach is that it works and is just a change of variables, which is straightforward. The disadvantage is that you must specify which command to use for the types of file concerned. Another disadvantage is that the evince process is actually a child process of the running Emacs itself and this means the PDF reader has also to be closed when you exit Emacs.

After reading the documentation for org-file-apps, I am tempted to set it to:

((auto-mode . emacs)
 (t . "xdg-open %s")  ;; This does NOT work.
 ("\\.mm\\'" . default)
 ("\\.x?html?\\'" . default)
 ("\\.pdf\\'" . default))

The command xdg-open is used on most Linux distros for opening file with default app. See xdg-open.

The reason why it doesn't work can be answered by this line of code from org-open-file.

    (start-process-shell-command cmd nil cmd)

The function start-process-shell-command actually executes cmd and then communicates with it using pty instead of pipe. See the doc for process-connection-type.

To walk around this, we can, however, use a function instead of a command string for default action.

(defun xdg-open (file link)
  (let ((process-connection-type))      ; using pipe instead pty
    (start-process
     "xdg-open" nil "xdg-open" file)))

And set org-file-apps to:

((auto-mode . emacs)
 (t . xdg-open)
 ("\\.mm\\'" . default)
 ("\\.x?html?\\'" . default)
 ("\\.pdf\\'" . default))

This way, whatever reader launched by xdg-open will not be a child process of running Emacs. They are independent of each other.

In fact, xdg-open is a very useful function by its own. You probably want to use M-x xdg-open or bind it to whatever key you like. To do that, you have to update it to:

(defun xdg-open (file &optional link)   ; link is unused
  (interactive "fFilename: ")
  (let ((process-connection-type))      ; using pipe instead pty
    (start-process
     "xdg-open" nil "xdg-open"
     (expand-file-name file))))         ; maybe unexpanded

Note that we have to expand the filename if we want to use xdg-open outside of org-open-file. The reason why previous version don't need to expand is that org-open-file expands the filename for us.

So far so good. And finally here comes my favorite approach using advising function.

By reading the source code of org-open-file carefully, we can find that it actually uses find-file-other-window to open the file as a fallback option. See L8579 of org.el and L235 of ol.el.

We can advise the function find-file-other-window with xdg-find-file (defined below) and leave the variable org-file-apps untouched.

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

(advice-add 'find-file-other-window :around 'xdg-find-file)

In fact, we can also advise find-file around xdg-find-file so that it becomes Emacs-wide default action for opening PDF and Word file with system default application.

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

The advantage of this approach is that this is an Emacs-wide solution. Not only org-mode calls find-file and find-file-other-window, but also many other Emacs packages relies on these two functions. Now I can even open a PDF with system default app by C-x C-f. In addition, I can control what kind of files to open with system default app.

To know more about advising function, see (elisp) Advising Functions.

0

The thing that determines what mode a file opens in is auto-mode-alist. So we just need to add something to that list that will tell Emacs to use a different mode.

What mode do you want .pdf files to open as? For this answer, I'll assume you want to use fundamental-mode. This won't render the pdf well, but you will be able to view the contents of the pdf. Add this code to your init file, and eval it or restart Emacs:

(add-to-list 'auto-mode-alist '("\\.pdf\\'" . fundamental-mode))

As mentioned, you'll want to replace fundamental-mode with the mode you want pdfs to open in.

  • I wanted it to use the previous behavior: the system's pdf viewer. Forgive me if it was unclear. – serv-inc Jun 3 '16 at 15:45

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.