AppleScript の新機能 (2) - ライブラリの続き

簡単に AppleScript のライブラリ機能について書きましたが、今度はちょっとディープな話。

スクリプト内でライブラリスクリプトを手軽に利用できるのはいいのだけど、利用しているライブラリスクリプトはスクリプトオブジェクトとは違うのかといったことを。

まず、ライブラリスクリプトはどこからでも参照できます。そして、読み込んだライブラリスクリプトはスクリプト内でユニークな存在になります。つまり、そのスクリプト上では一つしか存在しないことになります。load script 命令との最大の違いはここではないかな、と。

試してみましょう。

まず、以下のようなスクリプトを Script Libraries に保存します。

Script Editor で開く

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 という名前で保存します。

次に以下のスクリプトを作成。

Script Editor で開く

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 命令で複製できます。

Script Editor で開く

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() というハンドラがあります。

Script Editor で開く

on finderSelection()
    tell application id "com.apple.finder" to selection
end finderSelection

これですね。これを利用する側でちょっと拡張してみます。

Script Editor で開く

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 なんですっかり忘れてました。

Script Editor で開く

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

このように利用するのであれば、常に最新のライブラリスクリプトが利用されます。

ここまでできれば後は工夫次第で、スクリプト同士が依存したライブラリスクリプトの作成も可能ではないのかと...(複雑なケースを検証した訳ではないので突っ込まれると困りますが)。

最後に関係ないのだけど、ちょっとハマったので。次のスクリプトを実行してみると...。

Script Editor で開く

tell application id "com.apple.Finder"
    set theList to selection
end tell

tell application "Finder"
    sort theList by name
end tell

はい。エラーになります。では、次のスクリプト。

Script Editor で開く

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 件のコメント :

コメントを投稿