Two Improvements to Open macOS Finder Window in Emacs Dired + Automator Quick Action Downloads
In my previous post, I shared a function to fetch macOS Finder’s frontmost window path using AppleScript. The result was then opened in dired
so you can import your Finder session into Emacs, so to speak.
Here are two improvements I discovered today when reading Sacha Chua’s Emacs News. (Downloads are at the very bottom.)
Redditor /u/cyanj shared that there’s a ns-do-applescript
function we can use instead of calling out to the shell, spawning a new process. And it definitely feels faster!
If you want that, too, replace ct/finder-path
with this:
(defun ct/finder-path ()
"Return path of the frontmost Finder window, or the empty string.
Asks Finder for the path using AppleScript via `osascript', so
this can take a second or two to execute."
(let ($applescript $result)
;; Script via: https://brettterpstra.com/2013/02/09/quick-tip-jumping-to-the-finder-location-in-terminal/
(setq $applescript "tell application \"Finder\" to if (count of Finder windows) > 0 then get POSIX path of (target of front Finder window as text)")
(setq $result (ns-do-applescript $applescript))
(if $result
(string-trim $result)
"")))
ns-do-applescript
returns the script’s string result, if possible, which I also find more straight-forward than creating a temporary background buffer and capturing contents there. It works in my emacs-head@28 via homebrew. If you build Emacs from source, check if the ns-do-applescript
function is available at all.
If you have this in your init.el
, wrap everything in (when (memq window-system '(mac ns)) ...)
as usual so you don’t accidentally try to execute the ns-
prefixed function on e.g. Linux.
The post on Reddit there originally pointed to Álvaro Ramírez’s “macOS: Show in Finder / Show in Emacs” article, which introduces another enhancement to my set-up.
Up until that point, I got this Finder interop:
- Reveal current file/directory that I see in Emacs in Finder
- Open Finder’s frontmost window in Emacs
dired
Both require Emacs being focused. So I’m telling Emacs to do everything: remote-control Finder, or fetch its window’s path.
Álvaro now introduces a macOS Service so that you can start in Finder and then tell Emacs to open this location. So you don’t have to switch to Emacs and fetch the Finder window. Tell, don’t ask, if you will!
His AppleScripts, copied here for preservation, are:
-
Reveal file or folder in Emacs dired
#!/bin/bash current_dir=$(dirname "$1") osascript -e 'tell application "Emacs" to activate' path/to/emacsclient --eval "(progn (dired \"$current_dir\") (dired-goto-file \"$1\"))"
-
Visit (aka open) file in Emacs directly
#!/bin/bash osascript -e 'tell application "Emacs" to activate' path/to/emacsclient --eval "(find-file \"$1\")"
Both bash scripts need to be wrapped into Automator Quick Actions (used to be called “Services”) that take files or folders
from Finder
as input. The shell script action takes the input as arguments
, not the default as stdin
. Check out Álvaro’s post for screenshots.
I tweaked the lookup a bit and added common (?) paths to look for emacsclient
so you don’t have to hard-code the current value into the Automator action. Plus I added error handling if emacsclient
can still not be found:
...
# You may have to add the location of your emacsclient to PATH for lookup to work
PATH=~/bin:/usr/local/bin:/usr/bin:$PATH
if [[ ! -f `which emacsclient` ]]; then
>&2 echo "emacsclient not found"
>&2 echo ""
>&2 echo "Script needs tweaking. Looked in PATH: ${PATH}"
exit 1
fi
...
Since I have an Apple Developer ID, I figured I might as well bundle these actions up for you and also sign them so macOS doesn’t complain about the downloaded script. In about 6 months or so, we’ll probably be transforming these Automator actions to Shortcuts.app workflows, which I actually am looking forward to.