【问题标题】:have an AppleScript Automator service to process all text if no text is selected如果未选择任何文本,则使用 AppleScript Automator 服务来处理所有文本
【发布时间】:2012-05-07 21:16:12
【问题描述】:

我正在使用nslater's wonderful script 计算选定文本块中的单词和字符,但我需要两个增强功能:

  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

【问题讨论】:

  • 服务不是这样工作的。操作系统安排服务接收所需的输入。如果服务接受输入,那么它仅在有选择时可用。如果服务不接受输入,那么服务就没有可靠的方法来获取选定的文本(或所有文本)。
  • 感谢@KenThomases。因此,如果我理解正确,我需要做的是使用 Keyboard Maestro 或其他东西设置一个宏来启动文本选择逻辑,然后调用服务。
  • 也许吧。我不熟悉键盘大师,但也许它允许直接调用脚本,这根本不涉及服务。
  • @KenThomases:实际上,如果您将服务用作哑启动器(“无输入”)并使用 Accessibility API 检索文本选择的状态,则可以这样做。请参阅my answer 了解如何做到这一点。在 Applescript 中尽可能接近文本系统,我认为……

标签: text osx-lion applescript


【解决方案1】:

以下 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),如果 Adob​​e CS 应用程序也没有,我不会感到惊讶。 Java 和 AIR 应用程序也可能会出现问题。

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

【讨论】:

  • 脚本在 TextEdit 中运行良好。它是否适用于其他应用程序?我添加了---告诉应用程序“Safari”将文档1的设置URL设置为“stackoverflow.com/questions/10489265/…”延迟3结束告诉---在脚本的开头并没有得到任何结果
  • 脚本将在当前最前面的应用程序上运行,并检索当前焦点字段的文本内容。如果您像您一样以编程方式激活 Safari,则不会聚焦任何文本字段 - 因此没有结果。另请注意,Safari 的 UI 层次结构非常庞大,因为 WebKit 将整个 DOM 映射到 UI 元素(在可访问性方面值得称赞,在缓慢的旧 AppleScript 上不太容易)。如果您在 Safari 中选择一个文本字段(例如 URL 栏)并在其上运行服务,它最终返回计数。请耐心等待:)。
  • @adayzdone:请注意,像 TextEdit 这样的文本处理应用程序默认会关注其文档内容,因此激活和创建新文档就足以获得结果;但是,许多其他应用程序,例如 Safari,本身不会专注于任何文本字段。如果没有焦点文本字段,脚本就无法猜测您的目标文本内容是什么(在 Safari 的情况下:URL 栏?搜索字段?文档选项卡内容[不需要是文本的]?)。
  • 我只是添加了延迟 5,然后激活了不同的字段/程序。 Safari URL 栏有效,Word 和 Excel 无效。我假设 OP 会想要包含在 Select All 中的 word doc 正文?对于 Safari,您可以 -- 将 xxx 设置为文档 1 的文本 -- 但随后您会陷入应用程序的细节。
  • @adayzdone:MS Office 应用程序对其文档区域使用非标准视图,这些视图不提供 AXSelected... 属性。我已经警告说需要对 Accessibility API 的支持,但我会对该警告进行一些扩展。
猜你喜欢
  • 2016-01-11
  • 1970-01-01
  • 2016-09-06
  • 1970-01-01
  • 1970-01-01
  • 2018-12-05
  • 2015-08-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多