キー配列を最適化してプログラミングの生産性を倍にしよう! OSX限定

現代のキーボードの配列は
アルファベットを中心にしたQWERTYが主流です
これは1882年に完成されたそうです*1
もちろんコンピュータが生まれる以前です


一方プログラミングでは
アルファベット以外の記号を頻繁に打鍵します
例えばRubyでは _ = - + : [ { ( . ? ' "
などの記号の使用頻度はとても高いです
ところがUSキーボードを使っている場合
上記のうち : [ { . ? ' " は良いですが
_ = - + ( が最上段に位置していて
タッチタイピングしづらいです


US Keyboard


これはプログラムの生産性に大きく影響しそうです
なぜならこれらのキー入力が出現するたびに
目視でその位置を確認するか当て推量で外すかして
それによって入力のリズムが崩れてしまうからです


つまりこれらのキーの配列を
ホームポジションで所掌できる範囲内に収めることができれば
プログラムの生産性は飛躍的に向上すると思われます*2


きっと...


そんなわけで
ここでは自分が取っているキー配列とその実現方法を書きます
環境はMac OS X Tiger + Apple keyboard(US)です
なおMacVimとTextMateとTerminalでこれらのキーバインド
使えるようになることが前提となっています


まだTigerかよ!というツッコミは無視して..

USキーボードを使う

USキーボードはJISに比べて美しく使いやすいです
しかしCtrlキーが最下段で使いづらいという点と
IMEの切換えが不便という欠点があります
以下によりこれを解決・緩和します

  • Caps LockキーにCtrlキーを割り当てる

これは
[システム環境設定->キーボードとマウス->キーボード->修飾キー]
と辿って設定変更できます

  • IMEのon/offをCtrl+Jに割り当てる

これは同じく
[キーボードとマウス->キーボードショートカット]と辿って
入力メニューにおける[前の入力ソースを選択する]のショートカットを
Ctrl+Jにすることで変更できます

_と;を入れ替える

Rubyではアンダースコアを頻繁に打つ一方で
セミコロンはほとんど使わないのでこれらを入れ替えます


HOMEディレクトリ下にある
DefaultKeybindig.dictに以下を追記します
ファイルがなければ作成します
~/Library/KeyBindings/DefaultKeybinding.dict

{
	/* customize single stroke key */
    ";"  =	("insertText:", "_");     
    "_"  =	("insertText:", ";");     
}

これで右小指をそのまま打つだけで
アンダースコアが打てるようになるので
Rubyでコードを書く場合は非常に便利です

KeyRemap4MacBookを使う

Macにおけるキー配列の変更になくてはならないツールです


KeyRemap4MacBook

  • シフトキーをスペースキーに割り当てる

[Remap Space Key]の[Space to Shift_L (+ When you type Space only, send Space)]にチェックを入れます


これによって
スペースキーがシフトキーのModifierとしての役割をします
つまりスペースを押しながら
アルファベットを押せば大文字になります
一方でスペースキーを単独で押したときは
元通りにスペースを入力します
これに慣れるとアルファベットの位置に応じて
左シフトを押したり右シフトを押したりしていた煩わしさが
何だったのかと感じるようになります

  • =(equal) -(minus) +(plus) ( (round bracket)の移動

これらのキーの設定は以下の通りです

  1. Ctrl+;で=
  2. Ctrl+'で-
  3. Ctrl+Shift+'で+
  4. Ctrl+Shift+iで(
  5. Ctrl+Shift+oで)


KeyRemap4MacBookではちょっと手数を要しますが
未定義のキーバインドを定義することができます*3
上記のキーについてはこれを利用します
なおこれらの設定は上記のDefaultKeybinding.dictでもできますが
MacVimではそれが反映されなかったためこちらを利用します


詳細は本家に譲りますが概略をここに書いておきます
基本はソースを取得し定義ファイルを書き換えて再ビルドします
なおSnow Leopard向けヴァージョンでは
ソースのビルドをすることなく
設定の変更ができるようになっているようです


まずソースを取得して
その中のfiles/prefpane/checkbox.xmlの最後に
以下の項目を追加します*4

 <item>
   <name>My Custom Keys</name>
   <list>
     <item>
       <name>Remap Ctrl+Semicolon to Equal</name>
       <sysctl>remap.ctrlsemicolon2equal</sysctl>
       <autogen>--KeyToKey-- KeyCode::SEMICOLON, VK_CONTROL, KeyCode::EQUAL</autogen>
     </item>
     <item>
       <name>Remap Ctrl+Shift+Quote to Plus</name>
       <sysctl>remap.ctrlshiftquote2plus</sysctl>
       <autogen>--KeyToKey-- KeyCode::QUOTE, VK_CONTROL | ModifierFlag::SHIFT_L, KeyCode::KEYPAD_PLUS</autogen>
     </item>
     <item>
       <name>Remap Ctrl+Quote to Minus</name>
       <sysctl>remap.ctrlquote2minus</sysctl>
       <autogen>--KeyToKey-- KeyCode::QUOTE, VK_CONTROL, KeyCode::MINUS</autogen>
     </item>
     <item>
       <name>Remap Ctrl+Shift+i_and_o to RoundBracket</name>
       <sysctl>remap.ctrlshiftsquarebracket2roundbracket</sysctl>
       <autogen>--KeyToKey-- KeyCode::I, VK_CONTROL | ModifierFlag::SHIFT_L, KeyCode::KEY_9, ModifierFlag::SHIFT_L</autogen>
       <autogen>--KeyToKey-- KeyCode::O, VK_CONTROL | ModifierFlag::SHIFT_L, KeyCode::KEY_0, ModifierFlag::SHIFT_L</autogen>
     </item>
   </list>
 </item>
  1. My Custom Keysはグルーピングの名前です
  2. 各itemにはname, sysctl, autogenの項目があってautogenでキーの割り当てを定義します
  3. 修飾キーがある場合はKeyCodeの後にカンマで区切って書きます
  4. 修飾キーが複数ある場合は | で繋ぎます
  5. KeyCodeの定義名は src/core/kext/keycode.hppで定義されています
  6. 1つのitemに複数のautogenを定義できます
  7. itemのname項目はパネルにおける各表題名になります
  8. itemのsysctlはよくわかりませんが内部関数名か何かになると思います
  9. VK_CONTROLとModifierFlag::CONTROL_Lの使い分けはよくわかりません


本家の[設定の追加方法]の手順に従ってビルド・パッケージ化して
アプリケーションを再インストールします


自分は定義ファイルを何度も書き換えてビルドを繰り返していたので
以下のようなRubyスクリプトを用意してバッチ処理していました

keyremap_pkg.rb

#!/opt/local/bin/ruby1.9
#-*-encoding: utf-8-*-
# Build KeyRemap4MacBook pkg
def keyremap_pkg
  root = Dir.pwd

  Dir.chdir(root+"/src/core/kext")
  if system("make") && system("make reload")
    Dir.chdir(root+ "/files/prefpane")
    if system("make install")
      Dir.chdir(root)
      system("make")
      system("open #{Dir["KeyRemap4MacBook*.pkg"][0]}")
    end
  end
end
keyremap_pkg

このファイルをダウンロードしたソースのルートに配置し
以下を実行すればパッケージのインストール手前まで完了します

sudo ruby keyremap_pkg.rb

パッケージのインストール後に再起動が必要になります


以上により次のようなキー配列が得られます

  1. ;で_
  2. CapsLock+;で=
  3. CapsLock+'で-
  4. CapsLock+Space+'で+
  5. CapsLock+Space+iで(
  6. CapsLock+Space+oで)


その結果
Rubyで良く使う _ = - + : [ { ( . ? ' "
のキーはタッチタイプできるエリア内に収まりました


これで明日からは生産性が倍になりますね!
きっと...


なお実はアンダースコアとセミコロンの入れ替えも
KeyRemap4MacBookで実現したかったのですが
2つのキーを入れ替えるという方法がわからなかったので
DefaultKeybinding.dictのほうでこれを実現しました
分かる方がいましたら教えてください


(追記:2010-11-28)iTermではCapsLock+Space+'が動きません。一方でどこで設定されているのか、iTermに限らずCapsLock+Space+;で+が入力できるようになっています。そのため自分の環境ではRemap Ctrl+Shift+Quote to Plusの設定は不要かも知れません。
(追記:2010-11-29)Ctrl+Shift+[はTextMate上のkeybindとconflictしていたため、round bracketの設定先をCtrl+Shift+iおよびoに変えました。

[関連記事]
hp12c Macのキーバインドをいじる
hp12c オートペアリングをキーバインドしようよ
hp12c グリフをキーバインドしようよ

*1:http://ja.wikipedia.org/wiki/QWERTY配列

*2:それ以前の問題がいろいろとありますが..

*3:このことはTwitterで@splhackさんに教えて頂きました

*4:正確にはの直前です