I sometimes want to open a file in Emacs with something other than the system default - maybe okular instead of zathura for a PDF1, or a different image viewer for screenshots. This is a perfect case for embark2.
embark is this nifty package for emacs that is a bit like a contextual right click system. If you haven’t tried it, I highly recommend it. It took me a while to really integrate it into my workflow - honestly because of the overwhelming number of actions you are presented with. So since embark has around a billion actions included, I was a bit surprised to find I could only open files in the default application (embark-open-externally
).
Naturally, this being Emacs and more important things needed to be done, I ignored all of that and made this3:
(defun bergheim/embark-open-with (file)
"Open the current file in 'dired-mode' with an application of your choosing."
(interactive "sOpen externally: ")
(unless (string-match-p "\\`[a-z]+://" file)
(setq file (expand-file-name file)))
(when-let ((command (completing-read "Open current file with: "
(bergheim//executables-in-path))))
(start-process command nil command file)))
(defun bergheim//executables-in-path ()
"Retrieve a list of all executable files in `exec-path'."
(let (files-in-path)
(dolist (dir exec-path files-in-path)
(when-let ((files (and dir (file-exists-p dir)
(directory-files dir t))))
(dolist (file files)
(when (and (file-executable-p file)
(not (file-directory-p file)))
(push (file-name-nondirectory file) files-in-path)))))))
The function prompts you to select from all executable in your PATH and launches the chosen application with the file. Wire it up with:
(define-key embark-file-map "X" #'bergheim/embark-open-with)
Now when you’re in dired or anywhere embark can act on a file, call embark-act
, hit X
to get an interactive application picker.
-
This blog post has now been a draft for a year; I have since then found org-noter and once again Emacs turns out to be superior. ↩︎
-
karthink has a most excellent post about various embark tricks at https://karthinks.com/software/fifteen-ways-to-use-embark/ ↩︎
-
This is old code. I was experimenting with using // as a way to signify an internal/private function. Not sure how I feel about that when I published this. ↩︎