AppleScript 最速基本文法マスター

はじめに


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で書き込み用として開きます。オープンに失敗するとスクリプトは停止します。書き込み時に発生するエラーの対応として開いたファイルを必ず閉じる必要があるのでエラーハンドリングしてファイルを閉じます。

AppleScriptについていくつかのこと









コメント

このブログの人気の投稿

オレブラウザを作る 01

オレブラウザを作る 14