AppleScriptを書く準備 --- OSXに最初から**AppleScriptエディタ**という専用のエディタがインストールされています。コード補完や実行結果の表示など優れた機能を有していますのでこちらを使用することをおすすめ。アプリケーションフォルダのユーティリティの中にあります。 hello world --- ```applescript display dialog "hello world" ``` AppleScriptエディタのツールバーの実行ボタン(Command + R)でコンパイル&実行が行われます。正しい文法で記述されているかはコンパイルボタン(Command + K)で確認できます。 あとAppleScriptらしいhello worldはこんな感じで。 ```applescript say "hello world" ``` 基本的な考え方 --- AppleScriptは「オブジェクトに対してメッセージを送る」という考えでコードを書くのが基本。いわゆるオブジェクト指向言語というものです。アプリケーションはオブジェクトの一つと言えます。特徴的なのは比較的自然言語に近い形でコードが書けるところです。 ```applescript tell referenceToObject to statement ``` 例:iTunesにプレイリスト名"トップ 25"の再生を指示。 ```applescript tell application "iTunes" to play the playlist named "トップ 25" ``` 例:現在のアプリケーションに"hello world"ダイアログ表示を指示。 ```applescript tell current application to display dialog "hello world" ``` *tell current application to* は省略可能。よく目にするコードはこの形。 ```applescript display dialog "hello world" ``` これはAppleScriptエディタにダイアログ表示させるという指示です。これをiTunesにさせてみます。 ```applescript tell application "iTunes" to display dialog "hello world" ``` するとiTunesがアクティブになりダイアログが表示されます。これはAppleScriptエディタではなくiTunesがダイアログを表示したという事です。本当にiTunesのダイアログなのかを確認するにはドックのiTunesアイコンからメニューを開きiTunesを隠してみてください。ダイアログも一緒に隠されます。iTunesを表示すると再びダイアログも表示されます。 このようにAppleScriptはオブジェクトに対して何らかの操作を指示することが簡単に出来る仕組みです。 このドキュメントはオブジェクトの操作を覚える前にまずAppleScriptの文法をごく簡単に学ぶことを目的として書いていますので、以下の対象とするオブジェクトはAppleScriptエディタとします。 表示 --- 単に結果を知るためだけならわざわざ表示させる必要はありません。エディタの下にある結果エリアに表示されます。編集エリアにて1 + 1と入力し実行してみてください。計算結果が表示されます。 何かを明示的に表示する場合は**display dialog**コマンドを使います。 ```applescript display dialog "hello (again)" ``` デバッグの為に値を表示したい場合は**log**コマンドを使います。こちらは**返された値**か**イベント**のエリアで表示されます。 ```applescript log "hello (again)" ``` hello worldでも挙げましたが、**say**コマンドを使い指定した内容を読み上げさせることもできます。 ```applescript say "think different." ``` コメント --- 一行コメント ```applescript -- this is comment. ``` ブロックコメント ```applescript (* これはブロックコメントです。 複数行のコメントはこちらを使用します。 *) ``` 変数 --- 変数は前もって宣言する必要はありません。値を代入する記述を行えばすぐに変数を使用できます。型は特に指定する必要はありませんが明示することも可能です。 値を変数に代入するには**set**コマンドを使用します。 ```applescript -- 変数oneに数値の1を代入 set one to 1 -- 変数fooに文字列"foo"を代入 set foo to "foo" -- 変数barに真を代入 set bar to true -- 変数bazに文字列"baz"を文字列であることを明示して代入。 set baz to "baz" as text ``` **copy**コマンドで変数に値を代入するも出来ます。 ```applescript copy 1 to one ``` **get**コマンドで変数から値を取得します。getを省略し単に変数名だけでも値を取得できます。 ```applescript set foo to "foo" get foo --> "foo" ``` **a reference to**コマンドは左辺の値を求めるのではなく右辺の参照として処理します。 ```applescript set one to 1 set ichi to a reference to one get ichi -- get oneと同義 ichi + ichi --> 2 ``` **missing value**を代入することが出来ます。missing valueは初期化されていない値を意味します。 ```applescript set foo to missing value get foo --> missing value ``` **local**コマンドでスコープ内に有効な変数の宣言、**global**コマンドで全てのスコープに対して有効な変数の宣言ができます。 ```applescript local foo -- defines one variable local bar,baz -- defines 2 variables global hoge global fuga, hogera ``` 数値 --- 数値を表す**number**、整数の**integer**、実数の**real**の3つが型として使用できます。 ```applescript set a to 1 set b to 1.234 set b to b as integer --> 1 set a to a as real --> 1.0 set a to "100" set b to a as number --> 100 ``` 四則演算 --- ```applescript -- 加算 1 + 1 --> 2 -- 減算 1 - 1 --> 0 -- 乗算 1 * 1 --> 1 -- 除算 10 / 3 --> 3.333333333333 -- 商 10 div 3 --> 3 -- 余り 10 mod 3 --> 1 ``` インクリメント、デクリメントはありません。 文字列 --- 文字列はダブルクォートで囲みます。enterキーで文字列を改行させることができます。タブやリターン、改行などの特殊記号は\t、\r、\nと書きます。 ```applescript set str to "this is test." set str to " this is test. " set str to "\tthis is \ntest.\r" ``` 注意:AppleScriptエディタの環境設定で特殊文字を展開する場合があります。 文字列操作 --- ```applescript -- 結合 "aaa" & "bbb" --> "aaabbb" -- 分割 set AppleScript's text item delimiters to {","} text items of "aaa,bbb,ccc" –-> {”aaa”, ”bbb”, “ccc”} -- 長さ length of "あいうえお" –-> 5 count "あいうえお" --> 5 -- 切り出し –- 1~3文字目 text 1 thru 3 of "ABCDEFG" –-> “ABC” –- 4~末尾 text 4 thru -1 of "ABCDEFG" –-> “DEFG” –- 4~末尾の1つ前 text 4 thru -2 of "ABCDEFG" –-> “DEF” -- delimitersの使用例 set tempDelimiters to AppleScript's text item delimiters set filePath to "Macintosh HD:Users:hoge:Desktop:example.applescript" set AppleScript's text item delimiters to {":"} get text items of filePath --> {"Macintosh HD","Users","hoge","Desktop","example.applescript"} get first text item of filePath --> "Macintosh HD" get last text item of filePath --> "example.applescript" get text item 3 of filePath --> "hoge" repeat with anItem in text items of filePath log anItem end repeat (* --> "Macintosh HD" "Users" "hoge" "Desktop" "example.applescript" *) copy tempDelimiters to AppleScript's text item delimiters ``` AppleScriptには標準の検索・置換機能はありません。delimitersを使用して独自に検索機能を書く必要があります。操作対象のアプリケーションによっては検索・置換コマンドが用意されているのでそちらを使うのが簡単です。 リスト --- AppleScriptで配列はリストと呼びます。 ```applescript -- リスト {"foo", "bar", "baz"} -- リストの入れ子 {{1, 2, 3}, {2, 3, 4}, {3, 4, 5}} -- リストの連結 {"foo"} & {"bar", "baz"} --> {"foo", "bar", "baz"} -- 要素数 count {"foo", "bar", "baz"} --> 3 -- 要素数 整数のみ count integers in {"foo", "bar", "baz", 1, 2, 3} -- 3番目の要素 item 3 of {"foo", "bar", "baz"} --> "baz" -- ランダムな要素 some item of {"foo", "bar", "baz"} -- 4〜6の要素 items 4 thru 6 of {"foo", "bar", "baz", 1, 2, 3} --> {1, 2, 3} -- 要素の並びを反転 reverse of {"foo", "bar", "baz"} --> {"baz", "bar", "foo"} -- 先頭を除いた残りの要素 rest of {"foo", "bar", "baz"} --> {"bar", "baz"} ``` リストの操作は直接影響を及ぼしません。実際に内容を変更したい場合はsetやcopyを用いて代入する必要があります。 レコード --- AppleScriptの連想配列はレコードと呼ばれます。 ```applescript -- レコード {name:"Steve", height:74.5, weight:170} -- キーがnameの要素 name of {name:"Steve", height:74.5, weight:170} -- 連結 {name:"Steve", height:74.5, weight:170} & {lastName:"Jobs"} -- 要素数 count {name:"Steve", height:74.5, weight:170} -- 要素数 値が文字列のみ count text in {name:"Steve", height:74.5, weight:170} -- ランダムな要素 some item of {name:"Steve", height:74.5, weight:170} ``` レコードの操作は直接影響を及ぼしません。実際に内容を変更したい場合はsetやcopyを用いて代入する必要があります。 ```applescript -- 要素への代入 copy 210 to weight of {name:"Steve", height:74.5, weight:170} -- 要素の追加 set aRecord to {name:"Steve", height:74.5, weight:170} copy aRecord & {lastName:"Woz"} to aRecord ``` レコードから任意の要素を削除するコマンドはありません。新たにレコードを構築し直して代入する必要があります。 制御文 --- 制御文は他の言語に比べて貧弱かもしれません。条件分岐でswitchに相当するものはなくif文のみ。繰り返しもrepeatだけです。 ### if文 ```applescript if 条件式 then else if 条件式 then else end if ``` ### repeat文 ```applescript -- 指定した回数の処理を行う repeat 繰り返す回数 times end repeat -- 指定範囲内で処理を繰り返す repeat with 変数 from 開始 to 終了 end repeat -- リストを順に繰り返し repeat with 変数 in リスト end repeat -- 条件一致まで繰り返す repeat while 条件式 end repeat -- 無限ループ repeat end repeat -- ループから抜ける repeat if 条件式 then exit repeat end repeat ``` 演算子 --- 演算子の一覧です。AppleScriptは自然言語に近い記述ができるよう表現方法が豊富です。しかし最初からそれを全て覚えて書くのは大変。ここでは自分がよく使うものだけをピックアップしました。詳しくはオフィシャルドキュメントを参照してください。 [AppleScript Language Guide - Operators Reference](https://developer.apple.com/library/mac/#documentation/applescript/conceptual/applescriptlangguide/reference/ASLR_operators.html) AppleScript operator | 説明 --- | --- =, is | 等しい is not | 等しくない and | かつ or | または \> | より大きい \< | より小さい \>= | 以上 \<= | 以下 例外処理 --- ```applescript -- 基本形 try on error end try -- エラーハンドリングの例 try error number -10004 -- エラー番号-10004のエラーを発生 on error message number n if n = -128 then (*ユーザによってキャンセルされました。*) -- do something else if n = -10004 then (*アクセス権の違反が起きました。*) -- do something else -- 想定外のエラーは再度エラーとする log message error number n end if end try ``` サブルーチン --- AppleScriptではサブルーチンをハンドラと言います。 ```applescript -- 基本 on helloWorld() display dialog "Hello World" end helloWorld() -- 位置パラメーター形式のハンドラ on greeting(message) display dialog message end greeting("hello, again") -- ラベル付きパラメーター形式のハンドラ to findNumbers of numberList above minLimit given rounding:roundBoolean set resultList to {} repeat with i from 1 to (count items of numberList) set x to item i of numberList if roundBoolean then -- round the number -- Use copy so original list isn’t modified. copy (round x) to x end if if x > minLimit then set end of resultList to x end if end repeat return resultList end findNumbers set myList to {2, 5, 19.75, 99, 1} findNumbers of myList above 19 given rounding:true --> {20, 99} -- 定義済みラベル付きパラメーター形式のハンドラ on rock around the clock display dialog (clock as text) end rock rock around the current date -- 現在日時を表示 ``` ハンドラのパラメーターにはいくつかの種類がありますが、これはハンドラを使用する際の記述の可読性を高める目的で使い分けます。すべてを位置パラメーター形式で定義してもかまいません。また**on**の代わりに**to**を用いて定義することも可能です。やはりこちらも可読性を高めるのが目的でどちらを使用しても機能的な差異はありません。 スクリプトオブジェクト --- AppleScriptはプロトタイプベースのオブジェクト指向言語です。オブジェクトの定義がそのままインスタンスとなり即利用できます。AppleScriptで定義できるオブジェクトは**スクリプトオブジェクト**といいます。スクリプトオブジェクトにはプロパティとハンドラを定義できますが、その他にコマンドやハンドラの呼び出しを列挙できます。継承はparentプロパティを使い簡単に行えます。 ```applescript -- 基本形 script John property HowManyTimes : 0 to sayHello to someone set HowManyTimes to HowManyTimes + 1 return "Hello " & someone end sayHello end script tell John to sayHello to "Herb" --result: "Hello Herb" tell John sayHello to "Rose" sayHello to "Grace" end tell -- ハンドラによるスクリプトオブジェクトの初期化と生成 on makePoint(x, y) script thePoint property xCoordinate:x property yCoordinate:y end script return thePoint end makePoint set aPoint to makePoint(0,0) get xCoordinate of aPoint --result: 0 get yCoordinate of aPoint --result: 0 set myPoint to makePoint(10,20) get xCoordinate of myPoint --result: 10 get yCoordinate of myPoint --result: 20 get xCoordinate of aPoint --result: 0 get yCoordinate of aPoint --result: 0 tell myPoint set xCoordinate to 20 set yCoordinate to 40 get xCoordinate --result: 20 get yCoordinate --result: 40 end tell -- 継承 script Alex on sayHello() return "Hello, " & getName() end sayHello on getName() return "Alex" end getName end script script AlexJunior property parent : Alex on getName() return "Alex Jr" end getName end script -- Sample calls to handlers in the script objects: tell Alex to sayHello() --result: "Hello, Alex" tell AlexJunior to sayHello() --result: "Hello, Alex Jr." tell Alex to getName() --result: "Alex" tell AlexJunior to getName() --result: "Alex Jr" script John property vegetable : "Spinach" end script script JohnSon property parent : John end script set vegetable of John to "Swiss chard" vegetable of JohnSon --result: "Swiss chard" -- オーバーライドしたハンドラから親ハンドラを呼ぶcontinueの例 script Elizabeth property HowManyTimes : 0 to sayHello to someone set HowManyTimes to HowManyTimes + 1 return "Hello " & someone end sayHello end script script ChildOfElizabeth property parent : Elizabeth on sayHello to someone if my HowManyTimes > 3 then return "No, I'm tired of saying hello." else continue sayHello to someone end if end sayHello end script tell Elizabeth to sayHello to "Matt" --result: "Hello Matt", no matter how often the tell is executed tell ChildOfElizabeth to sayHello to "Bob" --result: "Hello Bob", the first four times the tell is executed; -- after the fourth time: "No, I’m tired of saying hello." ``` スコープ --- スコープの区切りはスクリプトオブジェクトとハンドラになります。最上位のスコープをトップレベルと呼びます。暗黙でスクリプト自身はトップレベルのスクリプトオブジェクトです。トップレベル直下のハンドラはスクリプト自身のメンバという位置づけです。 ```applescript set a to 0 if true then set a to 1 end if get a --> 1 on foo() set a to 2 get a --> 2 end foo foo() get a --> 1 script bar set a to 3 get a --> 3 end script run bar get a --> 1 ``` ライフサイクル --- トップレベルの変数とプロパティは操作対象のアプリケーションが終了するまで値を保持します。なのでアプリケーションが起動している間にスクリプトを再び実行すると前回の値が残った状態で実行することになります。トップレベルでないスクリプトオブジェクトと変数のライフサイクルはハンドラの終了で寿命を終えます。 ```applescript try log a on error set a to 0 log "error " & a end try set a to a + 1 on foo() try log a on error set a to 0 log "foo ():error " & a end try set a to a + 1 end foo foo() script bar try log a on error set a to 0 log "bar:error " & a end try set a to a + 1 end script run bar ``` ファイル入出力 --- ```applescript -- ファイルの書き込み set filePath to "Macintosh HD:Users:hoge:TheFile" set fp to open for access file filePath with write permission try write "Some text. And some more text." to fp on error msg number n close access fp error msg number n end try close access fp -- ファイルの読み込み set aFile to "Macintosh HD:Users:hoge:TheFile" as alias set fp to open for access aFile try set myText to read fp on error msg number n close access fp error msg number n end try close access fp -- ファイルの読み込み その2 set myText to read ("Macintosh HD:Users:hoge:TheFile" as alias) ``` **open for access file**でファイルを開きます。**with write permission**で書き込み用として開きます。オープンに失敗するとスクリプトは停止します。書き込み時に発生するエラーの対応として開いたファイルを必ず閉じる必要があるのでエラーハンドリングしてファイルを閉じます。 ファイル入出力に関しての説明がコマンドの使い方の説明になっているので書き直す必要あり。また文字コードの扱いに難が有る為、実質的に使えない。 関連リンク --- - AppleScript Language Guide - AppleScriptを使ってみるよ!(言語編1/2) - AppleScriptを使ってみるよ!(言語編2/2)