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
@agzam, I figure out the "proper way of unqotting a string in applescript with quoted form of POSIX path". It turned out you actually did not need to do it, just get it from the input. My script below now can stop opening multiple instances if the filename contains special characters, such as
'
. It can also open multiple files at the same time.