如果没有选择文本,则使用AppleScript Automator服务处理所有文本

时间:2012-05-07 21:16:13

标签: text osx-lion applescript

我正在使用nslater's wonderful script来计算所选文本块中的单词和字符,但我需要两次加注:

  1. 即使没有选择文本也可以使用该脚本。目前,当我在没有选择的情况下提取可用服务列表时,服务不存在(当然,这是合乎逻辑的)但是增强#2会改变一些事情。)

  2. 向脚本添加条件行为:如果未选择任何文本,则处理所有文本,但如果有选择,则仅处理所选文本。

  3. 这是 nslater的脚本,我将其粘贴到Automator中(我按照注释说明中的步骤创建了服务):

    # Word and Character Count service for Mac OS X
    #
    # Adds a Word and Character Count option to the text selection context menu in all apps
    #
    # Use Automator.app to create a new service, and then select the Run AppleScript action.
    # Paste this code in to the text box, and save as Word and Character Count. Now switch to
    # a new app, select some text, and open the context menu to find the new option.
    
    on run {input, parameters}
        tell application "System Events"
            set _appname to name of first process whose frontmost is true
        end tell
        set word_count to count words of (input as string)
        set character_count to count characters of (input as string)
        tell application _appname
            display alert "" & word_count & " words, " & character_count & " characters"
        end tell
        return input
    end run
    

1 个答案:

答案 0 :(得分:0)

以下AppleScript代码将完成您的工作:

tell application "System Events" to set frontApplication to (first application process whose frontmost is true)
set theText to my getCurrentTextContents(frontApplication)
if theText is not "" then
    set wordCount to count words of theText
    set charCount to count characters of theText
    tell application (name of frontApplication) to display alert "" & wordCount & " words, " & charCount & " characters"
end

on getCurrentTextContents(ofApplication)
    tell application "System Events"
        try -- time-out as some UI elements block, notably system sheets
            with timeout of 5 seconds
                set allElements to entire contents of window 1 of ofApplication
            end timeout
        on error
            return ""
        end try

        repeat with UIelement in allElements
            try –– very large element collections can change before looped through
                if focused of UIelement is true then
                    if attribute "AXSelectedTextRange" of UIelement exists then
                        set {x, y} to value of attribute "AXSelectedTextRange" of UIelement
                        if y ≥ x then
                            return value of attribute "AXSelectedText" of UIelement
                        else
                            return value of UIelement
                        end if
                    else
                        return ""
                    end if
                end if
            on error errorMessage
                log errorMessage
                return ""
            end try
        end repeat
        return ""
    end tell
end getCurrentTextContents

如果要在服务中使用它,则必须将该服务设置为“无输入” - 正如Ken Thomases正确声明in his comment,服务仅在有选择时处理输入。对于“无输入”服务,您实际上是在创建脚本的全局(或特定于应用程序,如果限制应用程序的服务)启动点。任何其他不会从其定位的应用程序中窃取焦点的脚本启动程序也将起作用(并且可能更快 - 首次启动时Automator服务往往是 veeerrrrryyyyy sssllllooooowwww 。)

还要注意整个事情通过Accessibility API(GUI脚本的基础)工作,需要访问用户启用的API - 通过选中“辅助功能中的启用辅助设备访问” “系统偏好设置的窗格,或者通过

tell application "System Events" to if not UI elements enabled then
    activate
    set UI elements enabled to true
end if

它还要求目标应用程序在Apple定义的文本视图中支持Accessibility API(请参阅链接到above的文档),并正确执行。 MS Office应用程序,不是,一个(他们使用没有选择属性的非标准视图 - thanks @adayzdone),如果Adobe CS应用程序也没有,我也不会感到惊讶。 Java和AIR应用程序也可能存在问题。

最后,当我在 caveat empteor 阶段时,我将添加脚本的速度直接取决于目标应用程序的UI层次结构的复杂性。这在普通应用程序的情况下不是问题,但它肯定是在WebKit生成的Web视图的情况下 - 也就是 Safari 和co。 - 因为这些将整个DOM映射到UI元素。虽然在可访问性方面非常值得称赞,但这会导致一个庞大的UI层次结构,需要花费很长时间才能遍历。