I want to open PDF files with Zathura on Mac. Problem is - Zathura does not have a proper App Bundle. So you cannot go in Finder to a pdf file, navigate to ‘Get Info’ and set pdf files to be opened with Zathura.
Luckily, you can create a custom App Bundle that wraps up a script that does that
But that is not as straightforward as you think it is, you can’t just execute a shell script. What if the file already opened with one of the instances of zathura process? Since Zathura is not a native OSX app, it will create a new process instance every time you open it.
The following script opens a file in Zathura, and if it was already opened, it would only activate the right window.
- Open Automator
- Create new Application
- Copy & paste this script
- Save as ‘zathura-client.app’ (or whatever you like)
- Associate .pdf files with that App - In Finder:
Get Info -> Open with -> Change All
-- it's not even funny, I couldn't figure out the proper way of unqotting a
-- string in applescript with quoted form of POSIX path, so I did this instead
on replace_chars(this_text, search_string, replacement_string)
set AppleScript's text item delimiters to the search_string
set the item_list to every text item of this_text
set AppleScript's text item delimiters to the replacement_string
set this_text to the item_list as string
set AppleScript's text item delimiters to ""
return this_text
end replace_chars
on activate_open_instance(win_title, is_first_time)
tell application "System Events"
set zathuraProcList to a reference to (every process whose name is "zathura")
repeat with proc in zathuraProcList
set PID to proc's unix id
-- I needed to figure out if this is the instance of Zathura with the
-- file on hand. And if it is, then focus on that window. Guess what?
-- Apparently you cannot grab list of all windows for a process (through
-- "System Events") if that process has fullscreen windows. It just not
-- possible. You have to do something like:
-- `tell application "zathura"`
-- alas, Zathura is not a "Cocoa Application"
-- so I had to run lsof for the process PID and strip down the output to contain only filenames
set myFiles to paragraphs of (do shell script "lsof -F -p " & PID & " | grep ^n/ | cut -c2-")
set fName to my replace_chars(win_title,"'", "") -- have to unquote or comparison won't work
if myFiles contains fName then
tell proc
set frontmost to true
if is_first_time then
set value of attribute "AXFullScreen" of window 1 to true -- set it to fullscreen the first time file opens
end if
end tell
return true
end if
end repeat
end tell
return false
end activate_open_instance
on run {input, parameters}
set filePath to quoted form of POSIX path of input
-- first we try to find it (in case it's already opened)
if not my activate_open_instance(filePath, false) then
set zathura to "/usr/local/bin/zathura "
do shell script zathura & filePath & " > /dev/null 2>&1 &"
delay 0.3 -- delay is required so it can set the window to fullscreen, but until the window is created, you can't set its properties
my activate_open_instance(filePath, true)
end if
return input
end run
Got this error
Cannot get POSIX path