Scripting Bridge

Scripting Bridge 面白い。普通(?)の AppleScript に飽きた人はぜひ。以下、覚え書き(環境は Mac OS X Leopard。当然だけど...)。なんで Python なのかは秘密です。

Terminal.app を起動して、

$ python

と、打ち込む。インタープリタが起動するので、まず、以下の呪文を唱える。

>>> from ScriptingBridge import *

これで、Scripting Bridge に関するモジュールが取り込まれるので、次に操作したいアプリケーションオブジェクトを作成する。

>>> finder = SBApplication.applicationWithBundleIdentifier_("com.apple.finder")

Python: unknown type name "ICN#"... と、ずらずら出てくるけど、気にしない。Finder の home にあるフォルダを取得してみる。

>>> homeFolders = finder.home().folders()
>>> for thisFolder in homeFolders:
...     thisFolder.name()
... 
u'Applications'
u'backup'
u'Desktop'
u'Documents'
u'Downloads'
u'Library'
u'Movies'
u'Music'
u'Pictures'
u'Public'
u'Sites'

おほぅ(おほぅって...)。でました。って、ここまでくるのに結構時間がかかっていたり。ちょっと、違和感がある。name() なんて書かれてると、属性を取得しているように見えない。なぜか分からないし、調べてもいないのだけど、Python では属性の取得でも () が必要みたい。

フォルダでも作ってみる。まず、Foundation を取り込む。

>>> from Foundation import *

まず、フォルダの属性を辞書で作る。

prop = {'name' : 'testing'}

この属性からオブジェクトを作る。

>>> folder = finder.classForScriptingClass_("folder").alloc().initWithProperties_(prop)

これは、Objective-C ですね。init で作っているけど、メモリとかどうなるのか知らない。ガベージコレクションがあるからいいか。そして、作る。

>>> finder.desktop().folders().addObject_(folder)

ここではデスクトップに作ってみました。Finder には make 命令があるのに、なぜ make 命令を使わないか?

実は、Scripting Bridge では操作するアプリケーションのオブジェクトを作れないのです。folder を作ったではないか、と思うかもしれませんが、Finder のオブジェクトではないのです。

>>> type(folder)
<objective-c class SBProxyByClass at 0x19e15e0>

SBProxyByClass というものなんですね(SB という接頭辞は Scripting Bridge のこと)。で、結局、Finder のデスクトップにあるフォルダのリスト(配列。SBElementArray)を、まず、取得するのです。そして、このリストに追加するのです。すると、Finder でフォルダが作成されるのです。なぜか。

Objective-C マジックですな。

しかし、insertObject:atIndex: が使えないんですね。iTunes のサンプルでは使えるようですが。だから、ここでは addObject:。

先の name() ではないですが、Objective-C のメソッドを使うのに Python では、アンダースコアを使う必要があるみたい。

insertObject_atIndex_(folder, 0)
addObject_(folder)

といった感じ。コロンをアンダースコアに置き換えるのかな(ちゃんとドキュメント読みなさいって)?

Finder で一番使うものって selection でしょう(勝手に決めつけていますが)。この selection は悩みました。だって、リストが返ってくると思うじゃないですか。

>>> curSelection = finder.selection()
>>> type(curSelection)
<objective-c class SBObject at 0x19e1560>

なんで、SBObject なの?

selection を取得して繰り返しで処理...みたいなことをどうやって書くのか悩んだね。全く。結局、以下のようにすればいいのでした。

>>> for thisItem in curSelection.get():
...     print thisItem.name(),
... 
music top testing

SBObject の get メソッドを使ってオブジェクトの参照を取得するとタプルで選択項目が返ってくるので、これを使って処理をすればいいということみたい。

繰り返して処理するためには set 命令が使えないといけない。が、set 命令はそもそも使えない。どうやるのかといえば、以下のようにする。

>>> curSelection = finder.selection()
>>> for thisFolder in curSelection.get():
...     thisFolder.setLocked_(1)
... 
>>>

オブジェクトが持っている属性(locked)に set をくっつけて続く属性の先頭文字を大文字にする。setLocked_(value) となる。name 属性なら setName(value)、label index 属性なら setLabelIndex(value) となる。value はそれぞれ、真偽値や整数値などの属性が受け取る事ができる値になります。

とりあえず、オブジェクトの作成と属性の取得、変更ができました。最低限はいちおう分かったのですが、ScriptingBridge で使えることができるアプリケーションの命令やオブジェクトなどはどうやって調べるといいのか?

Script Editor で表示される用語辞書だと楽でいいのですが、利用できるものに違いがあるのでそうもいきません。スクリプタブルアプリケーションがもっている用語辞書を Objective-C のヘッダファイルに変換することで Scripting Bridge で利用できるオブジェクトや属性を調べる事ができます。

Terminal.app を起動し(先ほどの Python インタープリタのままなら Control - D でインタープリタを終了させます)。おもむろに、以下のようにタイプ。

$ sdef /System/Library/CoreServices/Finder.app | sdp -fh --basename Finder --bundleid com.apple.Finder

これでカレントディレクトリに Finder の Objective-C ヘッダファイルが作成されます。このファイルを開くとクラスやメソッドが確認できます(他のスクリプタブルアプリケーションの場合は...って上記を見ればだいたい分かる...かな?)。

以上、Python での Scripting Bridge でした。コードをいろいろ見てみましたが、Objective-C でも Ruby でもそんなに大差はないような感じですね。しかし、上記のような Python のサンプルの少ないこと、少ないこと。PyObjCappscript はたくさんあるのに...。

参考

0 件のコメント :

コメントを投稿