Choose Your Application: embark-open-with for Emacs

2 minutes (336 Words)
(This post was updated )

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.


  1. 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. ↩︎

  2. karthink has a most excellent post about various embark tricks at https://karthinks.com/software/fifteen-ways-to-use-embark/ ↩︎

  3. 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. ↩︎