0

我正在使用nslater 的精彩脚本来计算选定文本块中的单词和字符,但我需要两个增强功能:

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

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

这是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
4

1 回答 1

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在他的评论中正确指出的那样,服务仅在有选择时才处理输入。在“无输入”服务的情况下,您实际上是在为脚本创建一个全局(或特定于应用程序,如果您将服务限制为应用程序)启动点。任何其他不会从它的目标应用程序中窃取焦点的脚本启动器也将提供服务(并且可能更快——Automator 服务在首次启动时往往是veeerrrrryyyyy sssllllooooowwww)。

另请注意,整个事情通过Accessibility API(GUI 脚本的基础)工作,并且需要访问 API 才能由用户启用 - 通过在System Preferences的“Accessibility”窗格中选中“Enable Access for Assistive Devices” ,或通过做

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

它还要求目标应用程序在其文本视图中支持 Apple 定义的 Accessibility API(请参阅上面链接的文档),并且这样做是正确的。MS Office 应用程序,其中之一(它们使用没有选择属性的非标准视图 -感谢@adayzdone),如果 Adob​​e CS 应用程序也没有,我不会感到惊讶。Java 和 AIR 应用程序也可能会出现问题。

最后,当我处于警告购买阶段时,我将添加脚本的速度直接取决于目标应用程序的 UI 层次结构的复杂性。这对于普通应用程序来说不是问题,但对于 WebKit 生成的 Web 视图(即Safari等)来说肯定是问题。– 因为它们将整个 DOM 映射到 UI 元素。虽然在可访问性方面非常值得称赞,但这会导致 UI 层次结构庞大,需要相当长的时间才能遍历。

于 2012-05-08T15:32:35.190 回答