簡単に AppleScript のライブラリ機能について書きましたが、今度はちょっとディープな話。
スクリプト内でライブラリスクリプトを手軽に利用できるのはいいのだけど、利用しているライブラリスクリプトはスクリプトオブジェクトとは違うのかといったことを。
まず、ライブラリスクリプトはどこからでも参照できます。そして、読み込んだライブラリスクリプトはスクリプト内でユニークな存在になります。つまり、そのスクリプト上では一つしか存在しないことになります。load script 命令との最大の違いはここではないかな、と。
試してみましょう。
まず、以下のようなスクリプトを Script Libraries に保存します。
property counter : 0
on displayCounter()
tell me
activate
display dialog (counter as text)
end tell
end displayCounter
on countUp()
set counter of me to counter + 1
end countUp
property の値を変更するだけのものです。これを Script Libraries に Counter.scpt という名前で保存します。
次に以下のスクリプトを作成。
on run
-- 別のハンドラから呼び出してみる
anotherCounter()
-- 通常の呼び出し
script "Counter"'s countUp()
script "Counter"'s displayCounter()
script "Counter"'s countUp()
script "Counter"'s countUp()
script "Counter"'s countUp()
script "Counter"'s countUp()
script "Counter"'s displayCounter()
-- set 命令で変数に代入
set newCounter to script "Counter"
newCounter's countUp()
newCounter's displayCounter()
end run
on anotherCounter()
script "Counter"'s countUp()
script "Counter"'s displayCounter()
script "Counter"'s countUp()
script "Counter"'s countUp()
script "Counter"'s countUp()
script "Counter"'s countUp()
script "Counter"'s displayCounter()
end anotherCounter
実行してみると分かるのですが、どの場所から呼び出してもライブラリ側の property の値は増えていきます。set 命令で変数に割り当てても同じライブラリスクリプトを参照しています。この辺りは通常のスクリプトオブジェクトと同じですね。
何回か繰り返し実行すると分かるのですが、property の値は常に初期値から始まります。保存はされません。
では、スクリプトオブジェクトのようにライブラリスクリプトを複数作成することはできるのでしょうか?
結論から言うと、copy 命令で複製できます。
on run
-- copy 命令で複製
copy script "Counter" to copiedCounter
copiedCounter's countUp()
-- ここでの値は 1
copiedCounter's displayCounter()
script "Counter"'s countUp()
script "Counter"'s countUp()
script "Counter"'s countUp()
script "Counter"'s countUp()
-- ここでの値は 4
script "Counter"'s displayCounter()
-- 両方は同じものか?
script "Counter" is copiedCounter
--> false
-- 再び複製
copy script "Counter" to newObject
newObject's countUp()
-- ここでの値は 5
newObject's displayCounter()
-- 複製されたものは同じものか?
copiedCounter is newObject
-- false
end run
このように複製はできますが、その時点での状態(property)も複製します。初期値を持ったままの新しいオブジェクトが必要なら、初期化ハンドラなどを含めておくか、 load script 命令で読み込むなりする必要があります。
また、ライブラリスクリプト内のスクリプトから他のライブラリスクリプトを利用することもできますし、ライブラリスクリプトの proerty、parent 指定も可能です。
前回使った Finder Utilities.scpt を使って試してみます。Finder Utilities.scpt には finderSelection() というハンドラがあります。
on finderSelection()
tell application id "com.apple.finder" to selection
end finderSelection
これですね。これを利用する側でちょっと拡張してみます。
property parent : script "Finder Utilities"
finderSelection()
on finderSelection()
tell application id "com.apple.finder"
set selectedItems to continue finderSelection()
if selectedItems is {} then return {}
return sort selectedItems by creation date
end tell
end finderSelection
このように作成日でソートした結果を返します。continue 文も利用できます。
property や parent としてライブラリスクリプトを利用するときの注意どころとしては、ライブラリスクリプトは構文確認(コンパイル)時のみ読み込まれるということ。property の挙動としては当然なのですが、久しぶりの AppleScript なんですっかり忘れてました。
finderSelection()
on finderSelection()
tell application id "com.apple.finder"
set selectedItems to script "Finder Utilities"'s finderSelection()
if selectedItems is {} then return {}
return sort selectedItems by creation date
end tell
end finderSelection
このように利用するのであれば、常に最新のライブラリスクリプトが利用されます。
ここまでできれば後は工夫次第で、スクリプト同士が依存したライブラリスクリプトの作成も可能ではないのかと...(複雑なケースを検証した訳ではないので突っ込まれると困りますが)。
最後に関係ないのだけど、ちょっとハマったので。次のスクリプトを実行してみると...。
tell application id "com.apple.Finder"
set theList to selection
end tell
tell application "Finder"
sort theList by name
end tell
はい。エラーになります。では、次のスクリプト。
tell application id "com.apple.finder"
set theList to selection
end tell
tell application "Finder"
sort theList by name
end tell
はい。動きます。
何が違うのかというと、application id の文字列。具体的には com.apple.Finder か com.apple.finder かの違い。
Finder か finder か。
正しいのは com.apple.finder。なんだけど、どれも同じように動くのです。しかし、
application id "com.apple.Finder" is application id "com.apple.finder"
--> false
この結果が false のように両者は異なったものなのです。
application "Finder" is application id "com.apple.finder"
--> true
こっちが正しい。id でアプリケーションを指定する場合、正確な id を利用しましょう。
では、再見!!
0 件のコメント :
コメントを投稿