Reputation: 602
Aim: identify most recent browser window in macOS, and get the URL and title of its active tab as a Markdown link.
It's destined for an Alfred workflow triggered from other apps, but for now I'm just debugging the core of it in the Script Editor. I have both Safari and Chrome open, along with a number of other apps. From debugging I see it correctly lists all the open windows, but it never matches either of the if
conditions. As further evidence, if I just use the tell application
lines in isolation, the right results are returned. I'm sure this is dead simple.
set output to ""
tell application "System Events"
set appNames to name of every application process whose visible is true
repeat with appName in appNames
if (appName = "Google Chrome") then
using terms from application "Google Chrome"
tell application appName to set currentTabTitle to title of active tab of front window
tell application appName to set currentTabUrl to URL of active tab of front window
end using terms from
set output to "[" & currentTabTitle & "](" & currentTabUrl & ")"
exit repeat
else if (appName = "Safari") then
using terms from application "Safari"
tell application appName to set currentTabTitle to name of front document
tell application appName to set currentTabUrl to URL of front document
end using terms from
set output to "[" & currentTabTitle & "](" & currentTabUrl & ")"
exit repeat
end if
end repeat
end tell
return output
Upvotes: 0
Views: 1632
Reputation: 6102
As discussed in the comments, the assumption your script makes is that AppleScript will return a list of processes ordered by the application which most recently had focus, but this isn't the case.
However, you can retrieve a list of application names in this order using a shell command lsappinfo metainfo
. Piping this through a few additional commands to isolate the information of interest and clean up the text:
lsappinfo metainfo \
| grep bringForwardOrder \
| grep -E -o '"[^"]+"' \
| tr -d "\""
produces a nice, readable, ordered list of applications, where each item in the last was last active more recently than the one below it:
Google Chrome
Script Editor
Atom
Messages
WhatsApp
Finder
Safari
Script Debugger
WebTorrent
Testing this, when I switch to Script Editor, and then run the shell command again, the list returned is:
Script Editor
Google Chrome
Atom
Messages
WhatsApp
Finder
Safari
Script Debugger
WebTorrent
Since you're only interested in discerning this order between two specific applications, namely Safari and Google Chrome, the shell command can be simplified somewhat to:
lsappinfo metainfo | grep -E -o 'Safari|Google Chrome' | head -1
which will return a single name, that being the browser that is either currently active or most recently had focus; or an empty string if, say, neither browser is running.
Incorporating this into your AppleScript, and cleaning the script up somewhat:
property nil : ""
set [currentTabTitle, currentTabUrl] to [nil, nil]
set cmd to "lsappinfo metainfo | grep -E -o 'Safari|Google Chrome' | head -1"
set frontmostBrowser to do shell script cmd
if the frontmostBrowser = "" then return nil
if the frontmostBrowser = "Google Chrome" then
tell application "Google Chrome" to tell ¬
(a reference to the front window) to tell ¬
(a reference to its active tab)
if not (it exists) then return nil
set currentTabTitle to its title
set currentTabUrl to its URL
end tell
else if the frontmostBrowser = "Safari" then
tell application "Safari" to tell ¬
(a reference to the front document)
if not (it exists) then return nil
set currentTabTitle to its name
set currentTabUrl to its URL
end tell
end if
return "[" & currentTabTitle & "](" & currentTabUrl & ")"
However, I would suggest actually composing the script as a shell script. I believe a shell script will be faster than an AppleScript, because the AppleScript will take more time to spawn a shell process and run a shell script than the shell would take to compile and run an AppleScript (in this instance—although, generally, osascript
is typically slower than a native AppleScript process). The other benefit is that, with the use of shell variable substitutions, we can make the resulting script a lot more compact, condensing the two browser AppleScript code blocks into a single, dual-purpose text script that osascript
will compile once the variable substitutions have been made (thus avoiding the runtime/compile-time malarky I mentioned in the comments).
The shell (bash) script looks like this:
browser=$(lsappinfo metainfo | grep -E -o 'Safari|Google Chrome' | head -1)
[[ "$browser" = "Safari" ]] && syntax="current" || syntax="active"
script="tell app \"$browser\" to tell ¬
(a reference to the front window) to tell ¬
(a reference to its $syntax tab)
if not (it exists) then return \"\"
\"[\" & its name & \"](\" & its URL & \")\"
end tell"
[[ -n "$browser" ]] && osascript <<< "$script" || echo ""
Upvotes: 6