Quoth kch:
それは素晴らしいことですが、スクリプトブリッジがapplescriptとどのように比較されるのか興味があります。私はやるべき読書があると思います。
SBは、AppleScriptにあるいくつかの機能を省略しています。たとえば、次のスクリプトは、すべてのファイルをデスクトップからDocumentsフォルダーに移動します。
tell application "Finder"
move every file of desktop to folder "Documents" of home
end tell
SBでは、SBElementArrayクラスにより、単一のコマンドを複数のオブジェクトに適用する機能が大幅に制限されるため、低レベルAPIを使用するか、個々のファイル参照のリストを取得して一度に1つずつ移動する必要があります。
require 'osx/cocoa'; include OSX
require_framework 'ScriptingBridge'
finder = SBApplication.applicationWithBundleIdentifier('com.apple.finder')
destination = finder.home.folders.objectWithName('Documents')
finder.desktop.files.get.each do |f|
f.moveTo_replacing_positionedAt_routingSuppressed(destination, nil, nil, nil)
end
rb-appscriptでは、AppleScriptと同じアプローチを使用します。
require 'appscript'; include Appscript
app("Finder").desktop.files.move(:to => app.home.folders["Documents"])
..。
SBは、AppleScriptよりもはるかにAppleイベントメカニズムをわかりにくくします。AppleScriptは、奇妙な構文やキーワードの競合の傾向など、頭を悩ませるのに苦労する可能性がありますが、それを超えると、Appleイベントがそのまま表示されます。ASで本当に重要な唯一の魔法は、コマンドのパラメーターとして表示されないリテラル参照を評価するときの「暗黙の取得」動作です。AppleScriptの最大の罪は、そのドキュメントが実際にどのように機能するかをよりよく説明していないことですが、実際に何が起こっているかについて多くの光を当てるWilliamCookによる非常に優れた論文があります。
一方、SBは、Cocoaスタイルの動作を備えた本物のCocoa APIであるかのように見せかけるのが最も難しいため、大量の魔法を重ねます。結果はCocoa開発者にとって表面的に魅力的なものですが、抽象化が漏れ始めるとすぐに(抽象化は常にそうであるように)、何が起こっているのかを理解するという点で完全に海にいます。たとえば、SBElementArrayは配列であると主張します-それはNSMutableArrayをサブクラス化します-しかし、実際にその配列メソッドを使おうとすると、それらの半分は機能し、半分は機能しません。実際、これは実際の配列ではありません。これは、評価されていないAppleイベントオブジェクト指定子のラッパーであり、NSMutableArrayのふりをして偽造されています。したがって、配列のようなものではないことを行う場合、その理由を理解するために大部分が詰め込まれます。そして、#1で述べたように
SBはまず、優れたAppleイベントAPIではなく優れたCocoa APIになろうとしますが、どちらもあまり得意ではありません。
ちなみに、AppscriptはAppleScriptの先導に従い、反対のアプローチを取ります。つまり、Appleイベントを正しく実行してから、ホスト言語に対応することを心配します。そのため、rb-appscriptよりもRubyOSAを好む人もいます。appscriptはより有能なソリューションですが、オブジェクト指向のバックグラウンドから来ている場合は、非常に奇妙に感じるでしょう。これは、AppleイベントがRPC-plus-queryベースのパラダイムを使用しており、OOPに類似しているappscriptは純粋に構文的であるためです。最も近い例えは、XML-RPCを介してXQueriesを送信することであり、慣れるまでに時間がかかります。
..。
SBは、AppleScriptよりもはるかに多くのアプリケーション互換性の問題に悩まされる傾向があります。
これらの問題のいくつかは、SBが実際の動作に加えてAppleイベントIPCがどのように動作するかについて独自のアイデアを課しているためです。たとえば、SBは、ディクショナリで定義されたクラスを表す[pseudo]プロキシクラスのセットを作成します。次に、主に従来のオブジェクト指向の動作ルールに基づいて、これらのオブジェクトと対話する方法にさまざまな制限を課します。
たとえば、次のスクリプトは、Documentsフォルダーのすべてのサブフォルダーの名前を取得します。
tell application "Finder"
get name of every folder of entire contents of folder "Documents" of home
end tell
SBで同じアプローチを試す場合:
finder.home.folders.objectWithName('Documents').entireContents.folders.arrayByApplyingSelector(:name)
Finderのディクショナリの「コンテンツ全体」プロパティのタイプが「参照」として宣言されているため、#foldersメソッドまで取得し、エラーをスローします。ディクショナリに「folder」要素が定義された「reference」クラスがないため、SBではその特定のクエリを作成できません(低レベルAPIにドロップダウンして生のAEコードを使用する場合を除く)。Appleのイベントルールによれば完全に合法ですが、SBによって課されたより狭いOO中心のルールセットには適合しません。
その他のバグは、スクリプト可能なアプリケーションが特定のコマンドやその他の機能をどのように実装するかについてSBが想定していることが原因です。例えば:
tell application "iTunes"
make new playlist with properties {name:"test 1"}
end tell
SBではiTunesが提供するショートカットを利用できません(プレイリストを作成するソースオブジェクトへの参照を省略できます。その場合、メインの「ライブラリ」ソースが使用されます)。より良い比較のためにいっぱい:
tell application "iTunes"
make new playlist at source "Library" with properties {name:"test"}
end tell
SBでは、これを次のように記述します。
itunes = SBApplication.applicationWithBundleIdentifier('com.apple.itunes')
playlists = itunes.sources.objectAtIndex(0).playlists()
newplaylist = itunes.classForScriptingClass(:playlist).alloc().initWithProperties({:name => 'test'})
playlists.addObject(newplaylist)
ただし、実行すると、#addObjectでbarfsします。SBは、単一の「make」コマンドを複数行の演習に変換する試みにおいて、「at」パラメーターが常に「<object>の<elements>の終わり」という形式の参照であると想定します。これがCocoaScriptingの方法です。ベースのアプリケーションがそれを行います。ただし、Carbonアプリケーションには、Appleイベントサポートを実装するための単一の標準フレームワークがないため、要件が少し異なる傾向があります。たとえば、iTunesはコンテナオブジェクト(この場合は「ソース「ライブラリ」」への参照を期待し、SBが「ソース「ライブラリ」のプレイリストの終わり」を渡すときにそれを好みません。これがAppleScriptableアプリケーションの多くですが、SBは「オブジェクト指向」であるとの判断でその現実を無視しています。
アプリケーションディクショナリが100%正確でないか、詳細が網羅されていない場合、さらに多くの問題が発生します。aete形式もsdef形式も、アプリケーションのスクリプトインターフェイスがどのように機能するかを100%詳細に説明することはできません。いくつかのことは、ユーザーが推測するか、補足ドキュメントで説明する必要があります。Finderの「コンテンツ全体」プロパティの性質は一例です。オブジェクトのどのクラスが他のどのクラスのオブジェクトの要素になることができるか、各プロパティのタイプが何であるかなどの他の情報は、AppleScript自体によって実際に使用されることはありません-それはユーザードキュメントとしてのみ存在します。AppleScriptはこの情報に依存していないため、アプリケーションのスクリプトサポートをAppleScriptに対してテストする場合、スクリプトはそれにもかかわらず問題なく機能するため、間違いを見逃すことになります。
ところで、Appscriptも100%「AppleScriptに準拠」しているわけではありませんが、かなり近づいています。初期のバージョンのappscriptも、辞書で定義されたオブジェクトモデルの適用など、AppleイベントにさまざまなOOルールを課そうとしましたが、アプリケーションの非互換性に遭遇した1年後、私はそのすべての「巧妙な」コードをガンガンし、次の数年間はブラックボックスのリバースエンジニアリングを行うAppleScriptの内部の策略を、appscriptに可能な限り厳密にエミュレートさせます。「あなたが彼らを打ち負かすことができないなら(あなたはそれができない)、彼らに加わってください」、言い換えれば。また、appscriptで互換性の問題が発生した場合は、通常、内部の互換性設定を反転したり、アプリケーション用語をモジュールにエクスポートしたり、手動でパッチを適用したり、代わりに使用したりするなどの方法があります。
..。
FWIW、関連するいくつかのAppscriptグッズもプラグインする必要があります。
まず、appscriptサイトのASDictionaryツールとASTranslateツールはあなたの友達です。ASDictionaryは、アプリケーションディクショナリをappscriptスタイルのHTML形式でエクスポートし、rb-appscriptに組み込まれている#helpメソッドも有効にします。irbでのインタラクティブな開発に最適です。ASTranslateはAppleScriptコマンドを受け取り、(バグは喜んで)appscript構文で同等のコマンドを返します。
次に、rb-appscriptのソース配布には、ドキュメントとサンプルスクリプトの両方が含まれています。appscript gemをインストールする場合は、それらのリソースのzipディストリビューションも取得することを忘れないでください。
第三に、MattNeuburgがrb-appscriptに関する本を書いています。rb-appscriptの使用を考えている場合は、読んでください。そして、あなたが最終的に何を決めるかに関係なく、クック博士の論文を読んでください。
..。
とにかく、それが役立つことを願っています。(ああ、長さについてはお詫びしますが、今週は約25000語を書いたばかりなので、これはちょっとしたリラックスです。)
psネッド、あなたの輝くドルはポストにあります。;)