【问题标题】:Add selected hyperlink to Safari reading list using AppleScript使用 AppleScript 将选定的超链接添加到 Safari 阅读列表
【发布时间】:2014-02-02 23:30:11
【问题描述】:

我正在尝试编写 AppleScript 服务以将选定的超链接添加到 Safari 阅读列表。对于裸 URL,这很容易。例如,下面是接收选定 URL 的我的服务(输入是“仅 URL”):

on run {theUrl}

    using terms from application "Safari"
        tell application "Safari"
            add reading list item theUrl as string
        end tell
    end using terms from

    return theUrl
end run

但是,如果所选文本是超链接的(但不是纯 URL),例如 StackOverflow,这显然不起作用。有没有办法使该服务也适用于超链接文本?谢谢。

【问题讨论】:

    标签: applescript


    【解决方案1】:

    遗憾的是,没有好的解决方案,但您可以尝试以下方法(粗略):

    • 让您的服务接受text 作为输入 - 即使选择了超链接,它也会启用它(尽管它会有效地启用任何文本)
    • 不处理传入的文本,而是将复制到剪贴板命令发送到活动应用程序(通过发送击键或最好通过 GUI 脚本)。 (请注意,即使是接受rich text 的服务也只会将纯文本 文本传递给服务处理程序。
    • 使用下面的技巧从剪贴板中以源文本的形式获取数据 - 遗憾的是,AS 不允许您原生处理 RTF 或 HTML。
    • 从源文本中提取 URL 并将其添加到阅读列表中。

    要从剪贴板获取 RTF 或 HTML 数据,需要进行一些黑客攻击(感谢 https://stackoverflow.com/a/2548429/45375):

    set html to do shell script "osascript -e '«class HTML» of (the clipboard as record)' | perl -ne 'print chr foreach unpack(\"C*\",pack(\"H*\",substr($_,11,-3)))'"
    set rtf to do shell script "osascript -e '«class RTF » of (the clipboard as record)' | perl -ne 'print chr foreach unpack(\"C*\",pack(\"H*\",substr($_,11,-3)))'"
    

    您可以使用正则表达式解析结果以提取 URL。

    请注意,有些应用只在剪贴板 (Safari) 上放置 RTF,而其他应用则同时放置 HTML 和 RTF (Chrome)。

    如果您愿意解决此问题,请告诉我您是否需要有关具体步骤的帮助。祝你好运。

    更新:根据要求,调用最前面应用程序的复制到剪贴板命令的代码

    • 简单,但不是最强大的:发送⌘-C(问题是如果在发送击键时用户碰巧按住另一个键,它可能会干扰):
    tell application "System Events" to keystroke "c" using command down
    
    • 可靠的替代方案:使用 GUI 脚本调用菜单命令

    唯一需要注意的是,必须通过System Preferences 启用辅助设备访问,最高为 10.8,其中这是一个全局开关,可以从脚本启动(使用管理员需要密码才能允许它;不幸的是,从 10.9 开始,每个使用 GUI 脚本的个人应用程序都必须经过授权,这需要最终用户进行相当多的手动干预——不过,这是一次性的痛苦) .

    my copyToClipboard()
    
    (* 
     # Copies the frontmost application's current selection to the clipboard
     # using GUI scripting rather than keyboard shortcuts so as to avoid conflicts 
     # (with keys held down by the user while the script is sending keystrokes).
    
     # CAVEAT: While this subroutine IS portable across *languages*, it does make an 
     # assumption that will hopefully hold for all applications: that the "Edit" menu is
     # the *4th* menu from the left (Apple menu, app menu, File, Edit).
    
    *)
    on copyToClipboard()
         tell application "System Events"
              tell menu 1 of menu bar item 4 of menu bar 1 of (first process whose frontmost is true)
                   -- Find the menu item whose keyboard shortcut is Cmd-C
                   set miCopy to first menu item whose value of attribute "AXMenuItemCmdChar" is "C" and value of attribute "AXMenuItemCmdModifiers" is 0
                   click miCopy
              end tell
         end tell
    end copyToClipboard
    

    最后,这是一个确保启用辅助设备访问的子程序;适用于 10.9 及之前的版本:

    • 在 10.8 及更早版本中,它只会触发管理员授权提示,如果获得授权,则继续运行。
    • 在 10.9 上,它可以做的最好的事情是弹出一个带有说明的对话框并打开相关的System preferences 窗格 - 其余的取决于用户。但是,即使用户设法授权该应用,也必须重新启动它才能开始工作。
        # Example use.
        try
            my ensureAssistiveAccess()
        on error
           # Exit quietly, relying on the prompt to have provided
           # sufficient information.
           return
        end try
    
    
        # Tries to ensure that access for assistive devices is turned on so as to enable GUI scripting.
        # - Up to 10.8.x, access can be turned on programmatically, on demand - via an admin authorization prompt.
        # - From 10.9, the best we can do is display a GUI prompt, then open System Preferences to the relevant pane, then exit, telling the user to try again after interactively enabling access.
        # Returns:
        #   Only returns if access is already enabled; throws an error otherwise.
        # Example:
        #   try 
        #       my ensureAssistiveAccess()
        #   on error
        #       # Enabling failed (10.8-: user didn't provide admin password; 10.9: user may or may not have authorized
        #       # this script's app as instructed by the prompt, but either way the script must be restarted.
        #       # Exit quietly, relying on the prompt to have provided sufficient information.
        #       return
        #   end try
        on ensureAssistiveAccess()
            local ok, isPreMavericks, verOs, verMajor, verMinor, appName, errMsg
            # Determine if access is currently enabled.
            tell application "System Events" to set ok to UI elements enabled
            if not ok then
                # See if we're running 10.8 or below
                set {orgTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {"."}}
                set verOs to system version of (system info)
                set verMajor to first text item of verOs as number
                set verMinor to second text item of verOs as number
                set AppleScript's text item delimiters to orgTIDs
                set isPreMavericks to verMajor ≤ 10 and verMinor < 9
                if isPreMavericks then # 10.8-: we can try to turn it on ourselves, which will prompt for authorization
                    try
                        # Try to turn it on - will prompt for authorization via admin credentials.
                        tell application "System Events"
                            set UI elements enabled to true
                            set ok to UI elements enabled # Check if the user actually provided the authorization.
                        end tell
                    end try
                else # 10.9+: we cannot turn it on ourselves, it has to be enabled *interactively*, *per application*.
                    # Try a dummy GUI scripting operation - which we know will fail - in the hope that this will
                    # get the app at hand registered in System Preferences > Security & Privacy > Privacy > Accessibility.
                    # ?? Does this work?
                    try
                        tell application "System Events" to windows of process "SystemUIServer"
                    end try
                    set appName to name of current application
                    if appName = "osascript" then set appName to "Terminal" # ?? how can we deal with other apps that invoke `osascript`, such as Alfred?
                    set errMsg to "You must turn on ACCESS FOR ASSISTIVE DEVICES for application '" & appName & "' (System Preferences > Security & Privacy > Privacy > Accessibility) first, then retry."
                    try
                        display dialog errMsg & linefeed & linefeed & "Press OK to open System Preferences now; unlock, if necessary, then locate the application in the list and check it." with icon caution
                        # We only get here if the user didn't cancel.
                        # Open System Preferences and show the appropriate pane. (This is the best we can do in guiding the user - further guidance would require the very kind of assistive access we're trying to turn on.)
                        tell application "System Preferences"
                            activate
                            tell pane id "com.apple.preference.security"
                                reveal anchor "Privacy_Assistive"
                            end tell
                        end tell
                    end try
                end if
            end if
            if not ok then
                if isPreMavericks then # This indicates that the authorization prompt was aborted; for 10.9+, errMsg was set above.         
                    set errMsg to "You must turn on ACCESS FOR ASSISTIVE DEVICES first, via System Preferences > Accessibility > Enable access for assistive devices"
                end if
                error errMsg
            end if
        end ensureAssistiveAccess
    

    【讨论】:

    • 非常感谢,剪贴板解析技巧非常聪明。 This linked script 是我迄今为止所做的——它非常适用于超链接和未链接的裸 URL。但是,我无法弄清楚“将复制到剪贴板命令发送到活动应用程序”步骤。 (抱歉,我根本不熟悉 AppleScript。)虽然这不是问题——选择文本后手动 Cmd+C 没什么大不了的,你能告诉我如何实际实现发送到剪贴板的事情吗?再次感谢。
    • @KevinSayHi 我很高兴 - 为了在应得的地方给予赞扬,我已经更新了我的答案,并参考了我最初得到 get-RTF/HTML-as-source-text 的 SO 答案诡计来自。我还更新了我的答案,向您展示了如何调用复制到剪贴板命令的两种方法。顺便说一句,我不确定您是否需要 using terms from ... - 仅仅是 tell application "Safari" 还不够吗?
    • 感谢您的全面回答:)
    【解决方案2】:

    令人讨厌的是,这是不可能的,但是您是否尝试过(或者您没有使用的原因)Safari 中的右键单击(控制单击)上下文菜单项“添加到阅读列表的链接” ?我猜你想将服务添加到任何应用程序中,在这种情况下,AFAIK,你不走运。

    【讨论】:

    • 是的,我想将电子邮件或 Chrome 中的链接保存到 Safari — 事实上,我仅将 Safari 用于阅读列表和阅读器功能。
    猜你喜欢
    • 1970-01-01
    • 2013-04-23
    • 2012-12-13
    • 1970-01-01
    • 1970-01-01
    • 2021-04-24
    • 2019-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多