0

nslater のすばらしいスクリプトを使用して、選択したテキスト ブロック内の単語と文字をカウントしていますが、次の 2 つの強化が必要です。

  1. テキストを選択しなくてもスクリプトを使用できるようにします。現在、選択せずに利用可能なサービスのリストをプルアップすると、サービスはそこにありません (もちろん、これは論理的ですが、拡張 #2 によって状況が変わります)。

  2. スクリプトに条件付き動作を追加します。テキストが選択されていない場合はすべてのテキストを処理しますが、選択されている場合は選択されたテキストのみを処理します。

これは、私が Automator に貼り付けたnslater のスクリプトです(コメントされた指示の手順に従ってサービスを作成しました)。

# 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になる傾向があります)。

また、すべてがアクセシビリティ API (GUI スクリプトの基盤) を介して機能し、ユーザーが API へのアクセスを有効にする必要があることに注意してください。またはすることによって

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

また、ターゲット アプリケーションは、Apple によって定義されたテキスト ビューでアクセシビリティ API をサポートする必要があり (上記のリンク先のドキュメントを参照)、正しくサポートする必要があります。たとえば、MS Office アプリケーションはそうではありません (選択属性のない非標準ビューを使用します - @adayzdone に感謝します)。Adobe CS アプリケーションがそうでなかったとしても、私は驚かないでしょう。Java および AIR アプリケーションもおそらく問題になるでしょう。

最後に、私はまだ警告を出している段階ですが、スクリプトの速度は対象となるアプリケーションの UI 階層の複雑さに直接依存することを付け加えておきます。これは、通常のアプリの場合は問題ありませんが、WebKit で生成された Web ビュー (別名Safariなど) の場合は問題ありません。– これらは DOM 全体を UI 要素にマップするためです。アクセシビリティの点では非常に称賛に値しますが、これにより膨大な UI 階層が作成され、移動にかなりの時間がかかります。

于 2012-05-08T15:32:35.190 に答える