のら(NORA)のブログ

主にソフトについて備忘録で(手抜き)書いていますねー。困った人の役とかに立てばいいかなー。とかそういう程度の奴でーす。むぎゅぎゅ~。更新停滞中ですね~。

autohotkey2.0勉強中(翻訳)その4-1~スクリプト編その1~

最終更新日: 2017/12/23

前→(リマップ編)

目次

はじめに

その1ではスクリプトの基礎編として知っておくべき事柄を抜擢して並べてみた
(エスケープシーケンス入ってないけど)
内容としては以下の通りになっている
AHKの最新版(a081)では全ての関数が関数(function)に変更され、第一引数との間のカンマが不要になっているなど変更点あり
また、エスケープシーケンスも異なる仕様になったので注意

  1. スクリプトの書き方
  2. 自動実行セクション
  3. コメントの書き方
  4. エスケープシーケンス
  5. 行を複数行に分割する方法
  6. 継続セクション(分割の一部)
  7. デバッグ

その2では、AHKコマンドライン引数、スクリプト文字コードについて、、スクリプトのEXE化(コンパイル)について扱っている
これらは知らなくても普通に使えるから後回し
その2はこちら

その1のコピペ

翻訳とかあんま得意じゃないんだけど
間違いあったらコメくれれば訂正します。というか自分も間違えて覚えてしまうから(´・ω・`)

一応各説明ごとに例は必ず一つ入れている
手抜きだからかなり見にくいかも
定期的に修正入ると思う

参考:ahkwiki日本版様及び公式ヘルプ

スクリプト編その1

スクリプトの書き方(基礎)

スクリプトは基本的に1行1命令(関数)で書く
スクリプトを起動したら、スクリプトは一行ずつ読み込まれ、最適化、検証されるため、エラーがあったら通知してくれる
また、エラーがあった場合は、そのエラーが修正されるまでプログラムを実行できない

関数の引数に文字列を指定する場合は、「"」で括はないといけない

ex: 一行分のスクリプト どちらもOK

以下のスクリプトの詳しい説明

MsgBox [なんちゃら]で[なんちゃら]を画面に表示する(メッセージを表示する関数)
下記の例はスクリプトの一行分になり、その内容は、MsgBox関数を用いて、引数This is script.をMsgBox関数に渡している
引数が文字列だが、スクリプト内になるため、「"」を使用しなくていいため使用してない

MsgBox "This is script."

スクリプトの起動とAuto-execute(自動実行)セクション(以下自動実行セクション)

スクリプトを起動した際の動作について書かれていて、スクリプトを記述する際、どういう風に動作するのかが書かれてる

スクリプトが読み込まれる(ahk.exeで実行される)と、Return、Exit、ホットキー、ホットストリング、スクリプトの終わりのいずれかに達するまで先頭から自動的に実行される
この部分(スクリプトが自動実行される範囲)のことを、自動実行セクションと呼ぶ

自動実行セクションが終了した際に、ホットキーなど(以下参照)がスクリプト中に記述されている場合はスクリプトが常駐状態にされる
(まあスクリプトが勝手に終わってホットキーとかが動作しないとかなったら大変だしね)
常駐状態にならない場合、スクリプトは終了する

常駐状態の場合は、ホットキー、ホットストリング、GUIイベント、カスタムメニュー項目、タイマーなどのイベントに応答して、待機(アイドル)状態で動作し続ける

自動実行セクションの完了後にこれらの条件が変更された場合や、(たとえば、最後のタイマーが無効になった場合)、最後に実行されたスレッドが完了するか、最後のGUIが終了すると、スクリプト(自動実行セクション)が終了する

自動実行セクションが終了しない例

  • ホットキー
  • ホットストリング
  • 可視GUI(アクティブなGUI)
  • アクティブなメッセージモニタ
  • タイマー
  • OnClipboardChangeコールバック関数
  • カスタムトレイメニュー項目
  • および#Persistent指令(ディレクトリ)
  • Lock系キーの固定

ホットキー、カスタムメニューアイテム、タイマーで起動されるスレッドでは、下記に記載する関数での設定はそれぞれ独立している

これらの初期値は自動実行セクション内で設定できる
設定が行われる前にスレッドが呼び出されると、期待した動作にならないことがあるので、自動実行セクションのできるだけ最初の方で設定しよう
デフォルトでは自動実行セクションが完了すると、下記の設定は再度初期値に更新される
だからホットキー、ホットストリング、タイマー、またはカスタムメニュー項目を含むスクリプトの一番上でデフォルト値を変更するのがいい

自動実行セクションが完了するまでに長い時間がかかる場合(または完了しない場合)、設定のデフォルト値は100ミリ秒後に有効になる

実行時に設定が初期化される該当関数設定一覧

  • DetectHiddenWindows
  • DetectHiddenText
  • SetTitleMatchMode
  • SetBatchLines
  • SetKeyDelay
  • SetMouseDelay
  • SetWinDelay
  • SetControlDelay
  • SetDefaultMouseSpeed
  • Thread attributes
  • CoordMode
  • SetStoreCapslockMode
  • AutoTrim
  • SetFormat
  • StringCaseSense

コメントの書き方

コメントの書き方は以下の3通りある
スクリプトを書いたときにどんなことをするために書いたのか、戻る値がなんなのかなどを書いておくことに使う

  1. 行頭がセミコロン「;」の行はコメント
  2. 関数のあとに半角スペースを空けてセミコロンがあれば、それ以降は行末までコメント(行コメント)
  3. /* …… */で囲まれた範囲もコメントになる(複数行コメント)

ex:

;コメント   
Run "autohotkey.exe" ;これ以降はコメント(1行に限る)  
/*
複数行  
に  
わたる  
コメント  
*/

エスケープシーケンス

AutoHotkeyエスケープ文字は、キーボードの左上にあるアクセント/バッククォート( )です 引用符は引用符で囲まれた文字列の中に含めるためにエスケープすることが出来る たとえば、 """", "" およびChr(34)という式はすべて二重引用符を含む文字列を生成する 特定の特殊文字も、エスケープシーケンスを用いて使用することが出来る
t(タブ),n(改行)、 r(改行)など

長い一行のスクリプトを分割する方法

スクリプトの一行がとてつもなく長いと読みづらいよね
そこで、長いなら分割すればいいじゃないか、ということになったのか何なのか知らないが、複数行に分割することができる
なお、分割しても実行の速度は変わらない←ここ重要
ヘルプの書き方だと主に引数に使用するっぽい

方法その1

やり方

and、 or、||、&&、カンマまたはピリオドで始まる行はそのすぐ上の行と自動的に結合(併合)される
++/--を除く他のすべての式演算子についても同じように一つ上の行と結合される(演算子詳細はまた今度)

これらの行の接続詞のあとにインデントは入れる必要はないが、入れたほうが可読性は上がると思う
また、上の行とつながっていることを示すコメントを入れておくことで、可読性が増す

いずれかの行と行の間または文末に、空白行またはコメントを追加することができる

方法その1の例(長いので折り畳み)

全ての例で[*]で囲んでる部分がスクリプトの結合をしている部分

ex1: 2行目がコンマで始まるため、最初の行に2行目が追加(結合)される

FileAppend "This is the text to append.`n"   ; ここにコメントを書くことが出来る、`nは改行のこと
*,* %A_ProgramFiles%\SomeApplication\LogFile.txt  ; Comment.

ex2:"and"または "or"で始まる例

if (Color = "Red" or Color = "Green" or Color = "Blue" ;コメント
*or* Color = "Black" or Color = "Gray" or Color = "White")   ;コメント
*and* ProductIsAvailableInColor(Product, Color)   ; コメント

ex3: その他の例 この場合は三項演算子

ProductIsAvailable := (Color := "Red")  
*?* false  ; この部分は単純に三項演算子として使われているっぽい  
*:* ProductIsAvailableInColor(Product, Color)

方法その2

「複数の行を結合する」または「結合したい行が"方法その1"に適していない」場合に使用する必要がある
この方法はホットストリングの自動置換に特に便利らしい

この方法を継続セクションというのだが、長いので、簡易的なやり方と、継続セクションについてがっつりで項目を分けた

やり方

結合したい複数の行を「()」で囲むだけでいい
また、初めの「(」は必ず改行してから始めなければならない
()で囲った部分は継続セクション(継続節)と言う
次の章で扱うオプションを用いないとデフォルトの状態だと各行の結合に改行が用いられるので注意

また、途中に)で始まる行を含めたい場合は、`)のようにエスケープする

方法その2の例

ex1: 継続セクションの例
「"」で囲んでいるのは変数「Var」に継続セクションを文字列で代入しているから
式に該当するので、「"」で囲まないといけない

Var := "  
(  ;ここから  
Line 1 of the text.  
Line 2 of the text. By default, a linefeed (`n) is present between lines.  
)"  ;ここまでは継続セクション

結合した結果: Line 1 of the text.
Line 2 of the ~
(改行で結合されるということが言いたい9)  

ex2: 継続セクションのあとにオプションがくる場合の例かな?
下の例の一番下の行には、最初の行のFileAppendの最後の引数が含まれていて、このような書き方もできるらしい
このような場合にはカンマが引数を区切るためのカンマと認識される

FileAppend "  
(  ;ここから  
A line of text.  
By default, the hard carriage return (Enter) between the previous line and this one will be   written to the file as a linefeed (`n).  
By default, the tab to the left of this line will also be written to the file (the same is true for spaces).  
By default, variable references such as %Var% are resolved to the variable's contents.
)", C:\My File.txt  ;ここまで( )まで)は継続セクション

継続セクション

デフォルトでは、継続セクション内の引用符は、エスケープされているかのように動作する
つまり、「"」記号はそのまま「"」として扱われる
さらに、継続セクション内の最初の行のインデントに基づいて、その後の各行の先頭のインデントが省略される
行の始まりがスペースとタブの二つで始まっているとすると、継続セクションの一番先頭の行に用いられているほうが省略される
いずれかの行が最初の行よりもインデントされているか、または間違った文字でインデントされている場合、その行の先行するすべてのインデントは消されず、そのまま残ってしまう

このデフォルトの動作を無効化させたい場合は、セクションの開始括弧の右側に次のオプションの1つ以上を設定すればいい

(LTrim Join|

式(:= 演算子を用いた代入)でも利用が可能だが、引用符の位置に注意が必要。例は↑のex1
継続セクション内にコメントは入れれない、下記に記述するCオプションで指定すれば可能になる
また、[()]から始まる行にはコメントを入れることができる

ex: コメント可能な行には ; 可能と書いてある

FileAppend,   ; コメント可能
; コメント可能
( LTrim Join    ; コメント可能
     ; これはコメントにならないで文字列として扱われる
), C:\File.txt   ; コメント可能

エスケープシーケンスはそのまま使える(`オプションが指定されている場合を除く)

継続セクションのオプション

継続セクションの動作は、セクションの開始括弧の右側に次のオプションの1つ以上を含めることで上書きできる
複数のオプションが存在する場合は、それぞれのオプションをスペースで区切って記述すればいい

ex:複数のオプションを設定する場合(下記のLTrimとJoinはオプション)

(LTrim Join
a
b
c
)

オプション一覧

案の定長いのでたたんでる

オプション 説明
Join [文字] 各行の結合に使用する文字列を改行(\`n)以外に変更する
単にJoinと指定すると、各行がそのまま連結される
[文字] には15文字までの文字列が指定できる
また、[文字]の部分にはエスケープシーケンスが使用できる
セクション内の最後の行もjoinオプションの文字で終了させるには、セクションの閉じ括弧のすぐ上に空白行を入れればいい
ex: 以下の例では、各行をスペースで結合するようにしている
MsgBox, 
(Join `s ;`sは半角スペース
a
b
c
)

結合した結果: a b c
LTrim 各行の行等の半角スペースや、Tab文字を無視する
LTrim0 LTrimの無効
個別では使わないかなというかどういうときに使うの?
RTrim0 行末の末尾の半角スペースやTab文字を無視しないようにする
RTrimはない
C [;]によるコメントを有効にする
あくまで[;]によるコメントのみなので、*/\*....\*/の形式のコメントは使用できない**
各行の最後に書いても、改行して単独で書いても問題ない
Cの代わりにComments、Comment、Commと書いてもいい
` `n、`t などの特殊文字エスケープ文字としてではなく、そのまま出力されるようになる
, カンマ(,)が自動的に[`,]としてエスケープされるのを抑止する
関数の引数の区切りなどとして扱われるようになる
Q(またはQuates) 継続セクションを式で使用する場合で、継続セクション内の引用符で閉じることができるようになる
多分ほとんど使わない
ex: Qオプションがない場合とある場合の例
Var := " ;Qなし
(
テスト
この後の引用符までが文字列として扱われる
)"

Var := " ;Qあり
(Q
テスト
この後の引用符までが文字列として扱われる"
)  ;この括弧の後ろに"をもう一度書くとエラーになる
) 継続節(の先頭)ではなく式として再解釈する
ただしJoinオプションは除く
多分式が長い場合や継続セクションのオプション(Join)が使いたい場合に有用なのかな
説明わかりにくいし例も例でわけわかめ例や説明いいのあったらいいな
ex: [)]の例、この場合括弧をエスケープする必要なく動作するらしく有用みたいよ
どの[)]を示してるのかがわからないんだよね
(x.y)[z]\()  

その他

書いてあったから一応書くけどもあんまりいらないというか別に今読まなくてもとか

  • 一行は最大16383文字までらしい(そんな書かない気がするんだけど)

  • 関数とは別に「#」で始まるプリプロセッサ指令のようなものがある また、このプリプロセッサ指令のようなものは、スクリプトが実行される前の段階で処理されるので、引数に変数を含めることは出来ない

スクリプトデバッグ

基本的なデバッグの方法

方法その1

MsgBoxを利用する

スクリプト要所要所にMsgBox関数を入れて、動作状況や変数の内容を表示させる

例えば、If文の各分岐先にMsgBox関数をいれるなど

ex:要所要所にMsgBox関数を入れたデバッグの方法

変数 "a" の内容によってifで分岐するのだが、ifの中の動作が変数を操作するなど、視覚的でない場合、どっちに分岐したかわからないとか、ifのあとでの変数の値(中身)を見たいとか

if ( a == 1 ) {
    b := 0
} else {
    b := 1
}

方法その2

ListVars,Pauseなどの関数を利用する

ListVarsやPauseなどの関数は、スクリプト中の挿入した所に「ブレークポイント」を作成する

スクリプト上記の2つの関数に遭遇すると、検証のためにすべての変数の現在の内容が表示される
全ての変数が表示されるため、目的の変数のみでいい場合はMsgBox関数を使用するのがよい

再開する準備ができたら、[ファイル]メニューまたは[トレイ]メニューからスクリプトの一時停止を解除する、すると、スクリプトは、次の「ブレークポイント」(存在する場合)に達するまで続く

その他:

これらのデバッグは、アクティブウィンドウが変わってしまうと正常に動作しないようなところでは使用できないので注意が必要である

また、これらのデバックではWinActivate関数の直前など、アクティブなウィンドウがスクリプトに関係しない位置に、これらの「ブレークポイント」を挿入するのが一般的で、こうすれば、スクリプトを再開したときに正常な動作で再開することができる

また、ListLines,KeyHistory,OutputDebug といった関数もデバッグには有用である
誤字や欠落した「グローバル」宣言などの一般的なエラーは、警告を有効にすることで検出できる(デフォルトの状態)

対話型デバッグ

DBGpクライアントを用いた対話型デバッグが可能である
DBGpクライアントを用いてできること

  • ブレイクポイントの設置と撤去(ブレイクポイントに達するとスクリプトの実行は一時停止される)
  • 1行ずつコードをステップ実行することができる(関数やサブルーチン自体、あるいはそれらをまたいでも可)
  • 全て、あるいは特定の変数の検査
  • 実行中のサブルーチンや関数のスタックを表示できる

やり方

対話型デバックをするにはまず対応しているデバッガクライアントを起動し、/ Debugコマンドラインスイッチを使用してスクリプトを起動する

ex: AutoHotkey.exe /Debug[=SERVER:PORT] ...

ex: Server および Port は省略可能で、以下の二つは同じ

  AutoHotkey /Debug "myscript.ahk"  
  AutoHotkey /Debug=localhost:9000 "myscript.ahk"

実行中のスクリプトにデバッガを接続するには、以下のようにメッセージを送信すればいい

ex:実行中のスクリプトをデバッガに接続

ScriptPath := "" ;スクリプトのフルパスを入れる  
DetectHiddenWindows On  
if WinExist("%ScriptPath% ahk_class AutoHotkey")  
    ; オプションの引数:  
    ;   wParam  = the IPv4 address of the debugger client, as a 32-bit integer.  
    ;   lParam  = the port which the debugger client is listening on.  
PostMessage, % DllCall("RegisterWindowMessage", "str", "AHK_ATTACH_DEBUGGER")

その他:
デバッガクライアントが接続されると、"detach" DBGp関数を送信してスクリプトを終了することなく切断されることがある
なおコンパイルしたスクリプトではこの機能は利用できない
コンパイルについては次回のその2で扱っている

スクリプト編その2へ続く