はじめに
AppleScript最速基礎文法マスターはPiyomaruさんのページ(http://piyocast.com/as/master/)もあるのですが、若干目次が見にくい…。あと自分用としてもまとめたいと思いPiyomaruさんのものをベースに書いてみた。
ちゃんとAppleScriptを学ぶならオフィシャルのドキュメント(https://developer.apple.com/library/mac/documentation/AppleScript/Conceptual/AppleScriptLangGuide/introduction/ASLR_intro.html)を読むのが一番。英語だけど。英語で躊躇してしまう人はseraphyさんの「AppleScriptを使ってみるよ!(言語編1/2) 」「AppleScriptを使ってみるよ!(言語編2/2)」がおすすめ。
AppleScriptを書く準備
OSXに最初からAppleScript エディタという専用のエディタがインストールされています。コード補完や実行結果の表示など優れた機能を有していますのでこちらを使用することをおすすめ。アプリケーションフォルダのユーティリティの中にあります。
hello world
display dialog "hello world"
ツールバーの実行ボタン(Command + R)でコンパイル&実行が行われます。正しい文法で記述されているかはコンパイルボタン(Command + K)で確認できます。
基本的な考え方
AppleScriptは「オブジェクトに対してメッセージを送る」という考えでコードを書くのが基本。いわゆるオブジェクト指向言語というものです。アプリケーションはオブジェクトの一つと言えます。特徴的なのは比較的自然言語に近い形でコードが書けるところです。
tell referenceToObject to statement
例:iTunesにプレイリスト名"トップ 25"の再生を指示。アプリケーションが起動していない場合は起動して実行します。
tell application "iTunes" to play the playlist named "トップ 25"
例:現在のアプリケーションにて"hello world"ダイアログを表示
tell current application to display dialog "hello world" --tell current application toは省略可能 display dialog "hello world"
特に何もせずダイアログを表示させたとします。
display dialog "hello world"
これはAppleScriptエディタにダイアログ表示させるという指示です。これをiTunesにさせてみます。方法は二つ。まず先に上げた例のようにtellでiTunesを指定します。
tell application "iTunes" to display dialog "hello world"
するとiTunesがアクティブになりダイアログが表示されます。これはAppleScriptエディタではなくiTunesがダイアログを表示したという事です。本当にiTunesのダイアログなのかを確認するにはドックのiTunesアイコンからメニューを開きiTunesを隠してみてください。ダイアログも一緒に隠されます。iTunesを表示すると再びダイアログも表示されます。
もう一つの方法はコードではなくAppleScriptエディタで操作対象とするオブジェクトを指定する方法。図のようにiTunesを選択しダイアログを表示するコードでtell ~ toの部分を削除します。
display dialog "hello world"
同じようにiTunesでダイアログが表示されたのを確認できたと思います。同様に他のオブジェクトを選択して試してみてください。各アプリケーションでダイアログが表示されるのを確認できます。
このようにAppleScriptはオブジェクトに対して何らかの操作を指示することが簡単に出来る仕組みです。
このドキュメントはオブジェクトの操作を覚える前にまずAppleScriptの文法をごく簡単に学ぶことを目的として書かれていますので、以下は対象とするオブジェクトはAppleScriptエディタとします。
表示
単に結果を知るためだけならわざわざ表示させる必要はありません。エディタの下にある結果エリアに表示されます。編集エリアにて1 + 1と入力し実行してみてください。計算結果が表示されます。
何かを明示的に表示する場合はdisplay dialogコマンドを使います。
display dialog "hello (again)"
デバッグの為に値を表示したい場合はlogコマンドを使います。こちらは返された値かイベントのエリアで表示。
log "hello (again)"
ちなみにsayコマンドを使い指定した内容を読み上げさせることもできます。
say "think different."
コメント
一行コメント
-- this is comment.
ブロックコメント
(* これはブロックコメントです。 複数行のコメントはこちらを使用します。 *)
変数
変数は前もって宣言する必要はありません。値を代入する記述を行えばすぐ使用できます。宣言の明示も可能です。型は特に指定する必要はありませんが明示することも可能です。
setコマンドを使用して代入。通常はこちら。
-- 変数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コマンドを使用して代入。
copy 1 to one
a reference toコマンドは左辺の値を求めるのではなく右辺の参照として処理します。
set one to 1 set ichi to a reference to one get ichi -- get oneと同義 --> 1
getコマンドで変数から値を取得します。getを省略し単に変数名だけでも値を取得できます。
set foo to "foo" get foo --> "foo"
missing valueを代入することが出来ます。missing valueは初期化されていない値を意味します。
set foo to missing value get foo --> missing value
localコマンドでスコープ内に有効な変数の宣言、globalコマンドで全てのスコープに対して有効な変数の宣言ができます。
local foo -- defines one variable local bar,baz -- defines 2 variables global hoge global fuga, hogera
数値
数値を表すnumber、整数のinteger、実数のrealの3つが型として使用できます。
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
四則演算
-- 加算 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と書きます。
set str to "this is test." set str to " this is test. " set str to "\tthis is \ntest.\r"
注意: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で配列はリストと呼びます。
-- リスト {"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を用いて代入する必要があります。
-- 要素への代入 copy "hoge" to item 1 of {"foo", "bar", "baz"} --> {"hoge", "bar", "baz"} -- リストの最初に要素を追加 copy "hoge" to the beginning of {"foo", "bar", "baz"} --> {"hoge", "foo", "bar", "baz"} -- リストの最後に要素を追加 copy "hoge" to the end of {"foo", "bar", "baz"} --> {"foo", "bar", "baz", "hoge"} -- 後ろの要素を削除する例 set aList to {"foo", "bar", "baz"} set aList to reverse of rest of reverse of aList get aList --> {"foo", "bar"}
レコード
AppleScriptの連想配列はレコードと呼ばれます。
-- レコード {name:"Steve", height:74.5, weight:170} -- キーがnameの要素 name of {name:"Steve", height:74.5, weight:170} --> "Steve" -- 連結 {name:"Steve", height:74.5, weight:170} & {lastName:"Jobs"} --> {name:"Steve", height:74.5, weight:170, lastName:"Jobs"} -- 要素数 count {name:"Steve", height:74.5, weight:170} --> 3 -- 要素数 値が文字列のみ count text in {name:"Steve", height:74.5, weight:170} --> 1 -- ランダムな要素 some item of {name:"Steve", height:74.5, weight:170}
レコードの操作は直接影響を及ぼしません。実際に内容を変更したい場合はsetやcopyを用いて代入する必要があります。
-- 要素への代入 copy 210 to weight of {name:"Steve", height:74.5, weight:170} --> {name:"Steve", height:74.5, weight:210} -- 要素の追加 set aRecord to {name:"Steve", height:74.5, weight:170} copy aRecord & {lastName:"Woz"} to aRecord --> {name:"Steve", height:74.5, weight:170, lastName:"Woz"}
レコードから任意の要素を削除するコマンドはありません。新たにレコードを構築し直して代入する必要があります。
制御文
制御文は他の言語に比べて貧弱かもしれません。条件分岐でswitchに相当するものはなくif文のみ。繰り返しもrepeatだけです。
if文
if 条件式 then else if 条件式 then else end if
repeat文
-- 指定した回数の処理を行う 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は自然言語に近い記述ができるよう表現方法が豊富です。しかし最初からそれを全て覚えて書くのは大変。ここでは自分がよく使うものだけをピックアップしました。詳しくはオフィシャルドキュメントを参照してください。
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ではサブルーチンをハンドラと言います。
-- 基本 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プロパティを使い簡単に行えます。
-- 基本形 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."
スコープ
スコープの区切りはスクリプトオブジェクトとハンドラになります。最上位のスコープをトップレベルと呼びます。暗黙でスクリプト自身はトップレベルのスクリプトオブジェクトです。トップレベル直下のハンドラはスクリプト自身のメンバという位置づけです。
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
ライフサイクル
トップレベルの変数とプロパティは操作対象のアプリケーションが終了するまで値を保持します。なのでアプリケーションが起動している間にスクリプトを再び実行すると前回の値が残った状態で実行することになります。
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
ファイル入出力
-- ファイルの書き込み set filePath to "Macintosh HD:Users:hoge:NewFile" 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 filePath to "Macintosh HD:Users:hoge:NewFile" set fp to open for access file filePath set myText to read fp close access fp display dialog myText
open for access file でファイルを開きます。with write permissionで書き込み用として開きます。オープンに失敗するとスクリプトは停止します。書き込み時に発生するエラーの対応として開いたファイルを必ず閉じる必要があるのでエラーハンドリングしてファイルを閉じます。
0 件のコメント:
コメントを投稿