I'm trying to tweak the dired-find-file
function in emacs on Windows XP so that when I open (say) a pdf file from dired it fires up a copy of Acrobat Reader and opens that file with it, instead of opening it within emacs. But I can't work out what variant on shell-command/call-process
to use. Here's what I have so far:
(defadvice dired-find-file (around dired-find-file-external (filename &optional wildcards))
"Open non-text files with an appropriate external program."
(if (string= ".pdf" (substring filename (- (length filename) 4))) ; obviously I'll replace this with something more general/robust
(shell-command filename) ;; what should go here?
(ad-do-it)))
(ad-activate 'dired-find-file)
I know I could hard-code it to start Acrobat Reader by giving it the location of the .exe file. But I'd rather have something which requires less searching from me and which won't break when default applications move/change. What should I use?
To extend on the 'org-open-file' proposal:
(defun my-dired-find-file (&optional prefix)
(interactive "P")
(if prefix
(org-open-file (dired-get-file-for-visit) 'system)
(dired-find-file)))
(define-key dired-mode-map "\r" 'my-dired-find-file)
Will let you open a file externally with `C-u RET'.
found at http://lists.gnu.org/archive/html/bug-gnu-emacs/2012-11/msg01069.html
I found this terrific web page via google, which let me to a technique using RunDll that works. I'm putting it up here in case anyone else is curious.
Here is the key piece of code, which opens filename
using the appropriate application:
(shell-command (concat "rundll32 shell32,ShellExec_RunDLL " (shell-quote-argument filename)))
And here is my full solution. (Note that dired-find-file
is just a wrapper round find-file
which doesn't know the filename, so that you have to advise find-file
rather than dired-find-file
as in the question. If you don't want the behaviour for find-file
you will probably need to rewrite dired-find-file
or write more complicated advice.)
(defun open-externally (filename)
(shell-command (concat "rundll32 shell32,ShellExec_RunDLL " (shell-quote-argument filename))))
(defun is-file-type? (filename type)
(string= type (substring filename (- (length filename) (length type)))))
(defun should-open-externally? (filename)
(let ((file-types '(".pdf" ".doc" ".xls")))
(member t (mapcar #'(lambda (type) (is-file-type? filename type)) file-types))))
(defadvice find-file (around find-file-external-file-advice (filename &optional wildcards))
"Open non-emacs files with an appropriate external program"
(if (should-open-externally? filename)
(open-externally filename)
ad-do-it))
(ad-activate 'find-file)
I have this in my .emacs:
(setq dired-guess-shell-alist-user
(list
(list "\\.*$" "cmd /k")
))
This will open the file using cmd.exe which will use whatever program is associated with the file extension. Tested to work on Windows 8 and GNU Emacs 24.2.1.
I'd use (w32-shell-execute "open" file-name)
.
In fact, in my init file I have:
(defun open-externally (file-name)
(interactive "fOpen externally: ")
(let ((process-connection-type nil))
(start-process "open-externally" nil
"xdg-open" file-name)))
(when (eq window-system 'w32)
(defun open-externally (file-name)
(interactive "fOpen externally: ")
(w32-shell-execute "open" file-name)))
Which defines a command that (may be used interactively and) opens a file with the default application according to xdg-open
and then, if I'm actually on Windows, redefines that command appropriately.
Tom Smith's answer is nice, but you can also just run the program "start" with the filename as an argument.
(shell-command (concat "start " (shell-quote-argument filename)))
org-open-file
is a system independent external opener. See org-file-apps
for how to customize it further.