在 AppleScript 中获取活动浏览器 window 详细信息

Getting active browser window details in AppleScript

目标:在 macOS 中识别最新的浏览器 window,并获取 URL 及其活动选项卡的标题作为 Markdown link。

它注定要用于从其他应用程序触发的 Alfred 工作流,但现在我只是在脚本编辑器中调试它的核心。我同时打开了 Safari 和 Chrome,以及许多其他应用程序。通过调试,我看到它正确地列出了所有打开的 windows,但它从不匹配任何一个 if 条件。作为进一步的证据,如果我仅单独使用 tell application 行,则会返回正确的结果。我敢肯定这很简单。

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

正如评论中所讨论的那样,您的脚本假设 AppleScript 将 return 由最近获得焦点的应用程序排序的进程列表,但事实并非如此。

但是,您可以使用 shell 命令 lsappinfo metainfo 按此顺序检索应用程序名称列表。通过一些额外的命令将其传输以隔离感兴趣的信息并清理文本:

lsappinfo metainfo \
    | grep bringForwardOrder \
    | grep -E -o '"[^"]+"' \
    | tr -d "\""

生成一个漂亮的、可读的、有序的应用程序列表,其中最后一个项目的最后活动时间比它下面的项目最近:

Google Chrome
Script Editor
Atom
Messages
WhatsApp
Finder
Safari
Script Debugger
WebTorrent

测试这个,当我切换到 脚本编辑器 ,然后再次 运行 shell 命令时,列表 returned 是:

Script Editor
Google Chrome
Atom
Messages
WhatsApp
Finder
Safari
Script Debugger
WebTorrent

因为您只对辨别两个特定应用程序之间的顺序感兴趣,即 SafariGoogle Chrome,shell 命令可以简化为:

lsappinfo metainfo | grep -E -o 'Safari|Google Chrome' | head -1

这将 return 一个名称,即当前处于活动状态或最近获得焦点的浏览器;或者一个空字符串,如果两个浏览器都不是 运行ning.

将其合并到您的 AppleScript 中,并稍微清理脚本:

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 & ")"

但是,我建议实际将脚本编写为 shell 脚本。我相信 shell 脚本会比 AppleScript 更快,因为 AppleScript 将花费更多时间来生成 shell 进程和 运行 shell 脚本而不是 shell 将需要编译和 运行 一个 AppleScript(在这种情况下,尽管通常 osascript 通常比本机 AppleScript 进程慢)。另一个好处是,通过使用 shell 变量替换,我们可以使生成的脚本更加紧凑​​,将两个浏览器 AppleScript 代码块压缩成一个单一的双用途文本脚本 osascript 将在变量替换完成后进行编译(从而避免了我在评论中提到的 runtime/compile-time 错误)。

shell (bash) 脚本如下所示:

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 ""