[AutoHotKey]一時的にhjklでカーソル移動する

矢印キーはあんまり押したくないが、常時VimオペレーションにこだわるほどVimmerでもないという場合に。

- [リマップ \- AutoHotkey Wiki](http://ahkwiki.net/Remap)

> [リマップはホットキーに比べて以下の点で優れる。
> - CtrlやShiftなど修飾キーが同時に押されているときに、置換元キーを押すと「修飾キ> ー\+置換先キー」を発行するようになる。
>     \(例\) 「a::b」としたとき Ctrl\+A を押すと Ctrl\+B が発行される\)]

普段常駐するスクリプトとは別に、以下のようなリマップスクリプトを用意して、使いたいときだけ走らせるという手はある。

```hjkl.ahk
h::Left
j::Down
k::Up
l::Right
j & k::ExitApp
```

常駐させるスクリプトで、ホットキーなりホットストリングでhjkl.ahkを起動させればいい。

あるいは、これ自体を独立したスクリプトとして常駐させて、`Suspend`してもよい。

```hjkl.ahk
Suspend, On ; 起動時にホットキーを無効にする
Return

h::Left
j::Down
k::Up
l::Right
~j & k::Suspend, Toggle ; ホットキーの有効/無効を切り替え
```

他にメインで常駐させるホットキースクリプトがある場合、そちらに`#Include`するとhjkl以外のホットキーも無効になってしまうので注意。
`Run, hjkl.ahk`なら問題ない。

## 常駐スクリプトに組み込めないの？
いや、なにがなんでも`#Include`で処理したい、と言い始めるとだいぶ話がややこしくなる。言い出した。俺が。

その場合、リマップを個別に無効化する必要がある。

- [リマップ \- AutoHotkey Wiki](http://ahkwiki.net/Remap)

> 上述のように、リマップはホットキーになるので、Suspendコマンドによってリマップも> 通常のホットキーと同様に無効になる。
> 従って、以下のようにすればリマップを個別に無効化することもできる。
>
> ```
> Hotkey, *a, off
> Hotkey, *a up, off
> ```

つまり、Auto-executeセクションで無効化しておいて、別のホットキーなりホットストリングで有効化すればよいということになる。

のだが、それはそれで問題があって、ホットキーを無効化すると、通常の動作に戻るのではなくなんの動作もしなくなる。
つまり、**リマップを無効化すると、そのキーは完全に死ぬ。**

というわけで、その対策が必要になる。

### コンビネーションキー
別途、コンビネーションキーの修飾キー側として、チルダ付きで登録しておけば、修飾キー付き入力、ホールド（キーリピート）含め無効化されなくなる。

- [ホットキー \- AutoHotkey Wiki](http://ahkwiki.net/Hotkeys#.E3.82.B3.E3.83.B3.E3.83.93.E3.83.8D.E3.83.BC.E3.82.B7.E3.83.A7.E3.83.B3.E3.82.AD.E3.83.BC)

> `&`を使うことで、2つの任意のキー（ジョイスティック以外）の組み合わせをホットキ> ーに指定することが可能。
>
> 一つ目に指定したキーが修飾キーとなり、一つ目のキーを押しながら二つ目のキーを押> すと発動する。
>
> 一つ目のキーにチルダ（ `~` ）をつければ、そのキーは無効化されず、普通に入力される。

ちなみに、コンビネーションキーではない単独ホットキー（`~h::Return`とか）を登録した場合、修飾キー付き入力は無効化される。いまいち理屈が飲み込めないが。

というわけで、サンプルコード。

```auto-execute.ahk
Hotkey, *h, Off
Hotkey, *j, Off
Hotkey, *k, Off
Hotkey, *l, Off
Hotkey, ~j & k, Off
```

```hotkey.ahk
h::Left
j::Down
k::Up
l::Right
~h & F12::Return
~j & F12::Return ; 必要ないが一応
~k & F12::Return ; 必要ないが一応
~l & F12::Return
~k & j::
    ToolTip, hjklモード
    Send, {BackSpace} ; 入ってしまうkを削除
    Hotkey, *h, On
    Hotkey, *j, On
    Hotkey, *k, On
    Hotkey, *l, On
    Hotkey, ~j & k, On
    Hotkey, ~k & j, Off
    Return
~j & k::
    ToolTip
    Send, {Up} ; 入ってしまうjによる下入力をキャンセル
    Hotkey, *h, Off
    Hotkey, *j, Off
    Hotkey, *k, Off
    Hotkey, *l, Off
    Hotkey, ~j & k, Off
    Hotkey, ~k & j, On
    Return
```

`#Include`する場合、[Auto-executeセクションに関する問題](https://qiita.com/catfist/items/7186d2b7fd56225b57b9)があるため、Auto-executeセクションと、それ以降のホットキーラベル部分を別々のファイルにしてある。

### 動的割当
しかし、そこまでやるくらいなら最初から全部動的割当にしてしまえばよいのだ。

そうすれば、通常動作を確保するためにわざわざダミーを設定する必要もなくなるし、hjklモードで使用するキーに、通常時は他の動作を割り当てることもできる。

```auto-execute.ahk
; #Persistent ; ホットキーラベルが存在しないため、他にホットキーラベル等が存在しない場合は必要
Hotkey, ~k & j, kandj, On
Hotkey, ~j & k, jandk_normal, On
; Return ; 同じくホットキーラベルが存在しないため、他にホットキーラベルやReturn/Exit等が存在しない場合は必要
```

```hotkey.ahk
h_arrow:
    Send, {Blind}{left}
    Return
j_arrow:
    Send, {Blind}{Down}
    Return
k_arrow:
    Send, {Blind}{Up}
    Return
l_arrow:
    Send, {Blind}{Right}
    Return
kandj:
    ToolTip, hjklモード`nj&kで終了
    Send, {BackSpace} ; 入ってしまうkを削除
    Hotkey, *h, h_arrow, On
    Hotkey, *j, j_arrow, On
    Hotkey, *k, k_arrow, On
    Hotkey, *l, l_arrow, On
    Hotkey, ~j & k, jandk_hjkl, On
    Hotkey, ~k & j, kandj, Off
    Return
jandk_hjkl:
    Send, {Up} ; 入ってしまうjによる下入力をキャンセル
    ToolTip ; ツールチップを削除
    Hotkey, *h, h_arrow, Off
    Hotkey, *j, j_arrow, Off
    Hotkey, *k, k_arrow, Off
    Hotkey, *l, l_arrow, Off
    Hotkey, ~j & k, jandk_hjkl, Off
    Hotkey, ~j & k, jandk_normal, On
    Hotkey, ~k & j, kandj, On
    Return
jandk_normal:
	send, {BackSpace}{esc} ; j&kをEsc
	Return
```

動的割当するサブルーチンラベルはホットキーラベルではないため、常駐条件やAuto-executeセクションの終了条件を満たさない可能性があることに注意。