Foltia with AppleScript

Foltia animelockerのトラブルシューティング

コードは短ければ短いほどよい Try編:アップルスクリプト

Try構文って何?

他のスクリプト言語にそれほど詳しいというわけではないのですが、エラー処理に該当するtry/ on error構文ってアップルスクリプト以外ではあんまり見たことないです。 クラリスファイルメーカースクリプトなどにはエラー処理ってステップがありますので、もしかしたらアップルの独特のコンセプトなのかもしれませんね。

例えば

set str to "This is sample text for script\nEnd of June\nWhat a hell"

 

return do shell script "echo " & quoted form of str & "|tr \\\\r \\\\n|grep 'heaven'"

このコードだと、str変数内をgrepでheavenというテキストを探すことになるんですが、heavenがstrに入ってません。 Terminalで実行すると

echo "This is sample text for script\nEnd of June\nWhat a hell"|grep 'heaven'

これはレスポンスは""が戻ってきます。正確には""の他にはShell script上では見つかったという意味でエラーコード0が一緒に戻ってくるようです。

上の例をスクリプトエディターで実行すると、

こんなエラーが戻ってきてハングします

error "0以外の状況でコマンドが終了しました。" number 1

とエラーメッセージダイアローグがでてハンドラは入力待ちでハングします。これはShellで見つからないというエラーコード1が一緒に戻ってくるので正常動作終了しなかったため、ハングするわけです。

今回のfoltia監視用のM-loop_pubのようにidle()を使ったループアプリだと、このような手動入力を要するエラーは極力避ける必要があります。

ではここでtry構文を使ってみましょう。

set str to "This is sample text for script\nEnd of June\nWhat a hell"

try

    return do shell script "echo " & quoted form of str & "|tr \\\\r \\\\n|grep 'heaven'"

on error

    return "Not found"

end try

こうするとエラーは出ずに、on errorの中に書かれたコマンドを実行してくれます。 つまり "Not found" です。

このtry構文はとても便利ではあるのですが、やっかいな点は長いことです。 if文の様に1行で書くことができません。 on errorの記載もすると少なくとも5行は必要となります。
Try構文はコードを実行する前に予想出来なかったエラーを、実行しながら修正して行く事が出来る点が優れています。 

例えば、前回紹介したLog_ForConsole_pub.scptを 変数 Lにロードして

set str to "This is sample text for script\nEnd of June\nWhat a hell"

try

    return do shell script "echo " & quoted form of str & "|tr \\\\r \\\\n|grep 'heaven'"

on error

    return {erro:true, status:LogOnConsoleR({cmt:"20行目でエラー発生", open_:false}) of L}

end try

と実行するとエラーが起こると20行目にエラーといった感じでログが残ってくれて、その場所を後で修正することができます。

ただある程度なれてきたら、やはりこの5行は長すぎますし、インデントが発生して視認性が悪くなるので

set str to "This is sample text for script\nEnd of June\nWhat a hell"

return do shell script "echo " & quoted form of str & "|tr \\\\r \\\\n|grep 'heaven'||true"

こうやって||trueをつけてやると、grepで行が検出されたらその行が戻り、見つからなければtrueを返しながら""が戻ってきます。 こうやって記載した方が短い行でハングさせずにコードを実行できます。

Record変数を強制的にテキストに変更してログで確認

余談になりますが、Try構文はちょっとトリッキーな使い方があります。 例えばレコード変数は実行した場合、Returnするとアップルスクリプトエディター上でレコードの内容を見ることができます。 しかしそれをStringに変換してテキストに書き出してログで確認したりすることはできません。 List変数はできるんですけどね。 *1

これをTry構文を使って実行できます。

set ls to {URLList:"http://www.ntv.co.jp/", GooChannelList:"0004", VHForUHF:"VHF_1", Chlist:"4", StationName:"日本テレビ", TVking:"101040", IgorList:"CH04", StationNameR:"日本テレビ"}

try

    set a to ls as string

on error aMessage --ここは好きな変数名を定義

    set a to aMessage

end try

return a

 

-->"{URLList:\"http://www.ntv.co.jp/\", GooChannelList:\"0004\", VHForUHF:\"VHF_1\", Chlist:\"4\", StationName:\"日本テレビ\", TVking:\"101040\", IgorList:\"CH04\", StationNameR:\"日本テレビ\"}のタイプをstringに変換できません。"

 

こんな感じですね。後ろに"stringに変換できません"と記載されてますが、まあ内容は読めますよね。 バグをとるにはそれで十分な訳ですね。 つまり引数であるGp(global query)の値をループ実行中にログに吐き出させて確認することが出来るわけですね。

 

*1:ちなみに、テキストに書き出すためにはJSON helperをつかってJSON形式にするという方法もあります