「のどか」で"HHKB"をカスタマイズ

# 目的
「[のどか](http://www.appletkan.com/nodoka.htm)」を使ってHappyHackingKeyBoard-JP (HHKB) をカスタマイズする設定ファイルの解説を行います。
HHKBじゃなくても一般的な109キーボードならば使いまわせるはずです。

# キー配置
ホームポジションを離れずにカーソル操作及び、編集ショートカットを操作出来るように下記のようにキー配置を行います。

![image](https://qiita-image-store.s3.amazonaws.com/0/8721/eb19031f-86fe-5401-2c70-85725b7be167.png)


なおこの配列は下記の記事に影響を受けています。
[思考の速度でパソコンを使う技術](http://d.hatena.ne.jp/fromdusktildawn/20070212/1171244226)

# モディファイヤ
このキー配置は常に有効な配置ではなく、図中の"Mod2"キー（HHKB上では無変換キー）と同時押しすることによって有効化されます。
CtrlキーやAltキーのように他のキーとの組み合わせによってキー入力を行うキーをモディファイヤと呼び、のどかではユーザーが自由に組み合わせを指定できるモディファイヤキーをmod0～mod9までの１０種類追加することが出来ます。
ここでMod2を使って定義しているのは筆者の環境の都合で特に他意はありません。

# キー説明
図中のキー名のうち特殊なものだけ説明します。

**「Ctrl+←」「Ctrl+→」**
　単語毎に移動する
**「Top」「Bottom」**
　文頭、文末へ移動する：「Ctrl+Home」「Ctrl+End」
**「New Line」**
　前方に改行を入力する：「Enter, ←」
**「Kill Line」**
　前方行末までを削除する：「Shift+End, Del」
**「BKill Word」「Kill Word」**
　単語毎に削除する：「Shift+Ctrl+←, Del」「Shift+Ctrl+→, Del」
**「Cancel」**
　ShiftLockが有効の場合ShiftLockを無効化する、そうでなければEscキーを入力
**「Shift Lock」**
　Shiftキー押し下げ状態でロックする

# 設定ファイル
「のどか」の文法知識については詳しく解説しません、上記各機能をどのように設定しているかの解説にとどめますので。設定ファイルの文法について詳しく知りたい方は[本家マニュアル](http://www.appletkan.com/nodoka-doc/README-ja.html)をご参照ください。
とりあえず完成品が欲しい方は[こちら](http://qiita.com/rai_suta/items/06b195ecf4468922237f)。

# モディファイヤキーの割り当て
「無変換」キーにmod2と「半角/全角」キーを割り当てた定義が下記になります。

```mayu:list1.mayu
    # Mod2キーを定義
    mod mod2            = !!無変換  # ※１
    key *無変換         = 半角/全角  # ※２
    key R-*無変換       = &Ignore   # ※３
```

※１ 「無変換」キーをmod2のワンショットモディファイヤキーとして設定。
※２ 「無変換」を「半角/全角」として割り当て。
※３ 「無年間」の連続入力を無効化。
上記設定により、「無変換」キーが下記のように動作します。

 - 単体で押した場合は「半角/全角」を入力
 - 他キーと同時押しの場合はモディファイヤキーとして機能
 - 押しっぱなしの場合は入力を無効化

# Mod2修飾キーに対する割り当て
mod2による修飾キーに割り当てる場合は下記のように定義します。

```mayu:list2.mayu
# KeySeq定義 ※１
keyseq	$Edit/kill-word         = S-C-Right Delete      # 前進単語削除
keyseq	$Edit/backward-kill-word    = S-C-Left Delete   # 後退単語削除
keyseq	$Edit/kill-line         = S-End Delete          # １行削除

    # 編集ショートカット
    key M2-*    = *                         # ※２
    key Z       = C-Z                       # UNDO
    key X       = C-X                       # CUT
    key C       = C-C                       # COPY
    key V       = C-V                       # PASTE
    key Y       = C-Y                       # REDO
    key Comma   = $Edit/backward-kill-word  # 後方単語削除
    key FullStop = $Edit/kill-word          # 前方単語削除
    key M       = $Edit/kill-line           # 行末まで削除
    key N       = Return                    # 改行
    key H       = BackSpace                 # BS
    key G       = Delete                    # DEL
    key ~M2-    =
    
    # 移動
    key M2-*    = *
    key K       = ←
    key L       = →
    key S       = ↑
    key D       = ↓
    key J       = C-←                      # 単語
    key Semicolon = C-→
    key A       = PageUp                    # 頁
    key F       = PageDown
    key I       = Home                      # 行頭
    key O       = End
    key W       = C-Home                    # 頁頭
    key E       = C-End
    key ~M2-    =
```

※１ ２段階以上の入力をKeySeqで定義している、この程度の長さならで別ファイル化しないなら直接定義部に書いたほうが良い
※２ デフォルトモディファイヤを設定
デフォルトモディファイヤを設定すると、それ以降の定義には明示しなくてもモディファイヤが指定されていると解釈されます。

# Shiftロック
Shiftロックの動作を状態遷移図で表すと下記のようになります。

![image](https://qiita-image-store.s3.amazonaws.com/0/8721/fccaabfc-9a4b-ef07-bc02-31ab87790162.png)

「通常状態」では通常のカーソル移動操作を行いますが、「Shiftロック状態」では同じキーバインドでカーソル操作した際にShift押し下げ状態でカーソル移動するように実装するのが目標です。

「のどか」にはロックキーと呼ばれる内部変数があるので、それを用いて下記のように設定すると上手く動きそうなんですが、この設定ではShiftロック解除時の動作が意図通りに動作しません。

```mayu:list3.mayu
    # Mod2キーを定義
    mod mod2            = !!無変換

    # 通常モード操作
    key M2-K     = ←
    key M2-L     = →
    key M2-S     = ↑
    key M2-D     = ↓

    # Shiftロック開始
    key M2-D-U      = &Toggle(L0, on)  # ※１

    # Shiftロック操作
    key L0-M2-K     = S-←              # ※２
    key L0-M2-L     = S-→
    key L0-M2-S     = S-↑
    key L0-M2-D     = S-↓

    # Shiftロック解除
    key U-*無変換   = &Toggle(L0, on)   #　※３
```

※１ 「Mod2＋U」を押すとLock0がONする
※２ 修飾キー「L0-M2-」が有効な場合のカーソル移動動作
※３ 「無変換」を単体で「押す－離す」とした場合は動作するが、モディファイヤとして機能させた場合には「離す」の動作を検出できない。

list3.mayu による動作を状態遷移図で表すと下記になります。
![image](https://qiita-image-store.s3.amazonaws.com/0/8721/dfa47719-0f91-1d25-964f-c07e135e65e9.png)

Shiftロックから通常状態へ戻るルートが意図した通りの動きとなりませんでした。

そこで代わりに keymap を使って実装して、うまく動作したのが下記設定になります。

```mayu:list4.mayu
    # Mod2キーを定義
    mod mod2            = !!無変換

    # 通常モード操作
    key M2-K     = ←
    key M2-L     = →
    key M2-S     = ↑
    key M2-D     = ↓

keymap kmp_shiftLock : Global           # ※１
keyseq $Prefix_shiftLock    = &Prefix(kmp_shiftLock, false) &EditNextModifier(M2-)
    mod mod2         -= 無変換          # ※２
    key *無変換       = &Ignore
    key U-*無変換     = &CancelPrefix   # ※３
    
    # Shiftロック操作
    key *K           = S-← $Prefix_shiftLock  # ※４
    key *L           = S-→ $Prefix_shiftLock
    key *S           = S-↑ $Prefix_shiftLock
    key *D           = S-↓ $Prefix_shiftLock
keymap Global

    # Shiftロック開始
    key M2-D-U      = $Prefix_shiftLock  # ※５
```

※１ Shiftロック操作を定義する keymap
※２ 「無変換」を離した際のキー割り当てを動作させるために、kmp_shiftLock内ではモディファイヤ定義から外す
※３ CancelPrefix してShiftロックモードから通常モード操作に戻す
※４ シフトロック操作した後に、再度 kmp_shiftLock へPrefixすることで、キーマップにとどまる
※５ 通常モードからShiftロックモードへ移行する

list4.mayu による動作を状態遷移図で表すと下記になります。
![image](https://qiita-image-store.s3.amazonaws.com/0/8721/82df8946-b856-32e8-a916-1f20894673cf.png)

戻る場合の状態遷移ルートが増えましたが、定義しない操作の場合に通常状態へ戻ってくれるので、コレはコレで上手く動作してくれるので結果オーライです。