コマンドラインで caps lock キーを潰す.control キーに. -- macOS Sierra (v10.12)

macOS の環境設定は,GUI ではなく defaults コマンドなりを並べた shellscript を走らせて行っておりまして,今回はそこでのお話.

そのうちのひとつ,Caps Lock キーを control キーにする設定を施しているのですが,これができていない様子.

思った通り,Sierra (v10.12)になってやはり上手く設定ができなくなっているアイテムはあるけれど,選りによって面倒くさいところで引っかかってくれた.

正直ダルい.

覗いてみると,どうやら制御に必要なキーボードの情報,いわゆる "keyboard ID"*1,が上手く取れていないようで,これが原因っぽい.

ちなみに使用しているマシンは powerbook pro 13".Mid 2012.レガシーw
us キーボード.

結果こうしました.;

# キーボードID
keyboardid="keyboardid=$(ioreg -c AppleEmbeddedKeyboard -r | grep -Eiw "VendorID|ProductID" | awk '{ print $4 }' | paste -s -d'-\n' -)'-0'"
# Capls Lock キーを control キーにする.
defaults -currentHost write -g com.apple.keyboard.modifiermapping.${keyboardid} /
    -array-add /
    '<dict>
      <key>HIDKeyboardModifierMappingDst</key>
      <integer>2</integer>
      <key>HIDKeyboardModifierMappingSrc</key>
      <integer>0</integer>
    </dict>'
# [システム環境設定 > キーボード > 修飾キー > Caps Lock キー] => [^ Control]

defaults の箇所は実際 1 行で書いてます.
ここでは見易さを考え,ちょっと整形することにしました.

問題は IOHIDKeyboard がなくなった,ってこと?

で,良いのですか?...というか,っぽいのですが.

いやいや,こう言うことってあるの?と,素人目には正直ちょいと信じがたいレベルだったりするのですが...

話を進めるのに,以前のコードを置いて始めた方が早いかな,と.

これまで

こんな感じでした.;

keyboardid=$(ioreg -n IOHIDKeyboard -r | grep -E 'VendorID"|ProductID' | awk '{ print $4 }' | paste -s -d'-\n' -)'-0'
defaults -currentHost delete -g com.apple.keyboard.modifiermapping.${keyboardid}

Sierra (v10.12) になって

キーボードの情報,上のコードですと ${keyboardid} という変数に期待している値が入って来てない様子.

覗いてみると結果はブランク.

以後,Apple オフィシャルではありませんが "伝わりやすいかな" という感覚でこちらに倣って,便宜的に,"keyboard id" と呼ぶことにしようかと思います.

f:id:wooweezoowee:20161003184134p:plain



キーボードのベンダーと製品の情報が必要

上述のコード見て頂ければおわかりの通り設定にはドメインcom.apple.keyboard.~ の部分,を構成するキーボードの情報 keyboard id が必要となります.

さらにこの keyboard id 言うのは,キーボードの "ベンダー" の情報と "製品" の情報で構成されてまして,これらの情報が必要となります.

上のコードですと VendorIDVendorID にあたる箇所ですね.

その情報を獲るには,ioreg

キーボードの情報を取得する道具は ioreg コマンド.

ioreg とは.;

The command ioreg located in /usr/sbin/ioreg is used to display the I/O Kit registory. Man Page.

ちなみに I/O Kit って何なのさ,って話なのですが,ハードウェア寄りのシステム情報が集約されたもので,各ハードウェアへアクセスはこの I/O Kit を介して行われるんだそう.

で,後で知ったのですが,同様のことが GUI で出来るアプリケーションがあるようです.

ioreg | Prints the contents of the I/O Registry (a command-line version of the I/O Registry Explorer application).

via. [What Is the I/O Kit?][46]

I/O Registry Explorer と言うらしい*2

ん?*3

そんなこんなで

ioreg -n IOHIDKeyboard -r の部分がイケテナイ,と.

細かい,と言うか本当の技術的な背景分からないのですが,とりあえずは結果より IOHIDKeyboard と言うのが無くなっているみたい,で良いのでしょうか?

キーボードの情報を探す

IOHIDKeyboard という名前では引っ掛かってこなくとも,まさかキーボードの情報自体が無くなった,なんてないでしょう,と言うことで探してみることに.

このあたりの手法を参考に試行錯誤しながら探りを入れて見る.

どういう手続きで特定していったか

ioreg の出力をまず "keyboard" で grep

% ioreg | grep -i "keyboard"
    | | | |       |     |   +-o Apple Internal Keyboard / Trackpad@1d183000  <class IOUSBHostDevice, id 0x1000002ec, registered, matched, active, busy 0 (583 ms), retain 32>
    | | | |       |     |     +-o Apple Internal Keyboard@0  <class IOUSBHostInterface, id 0x1000002f5, registered, matched, active, busy 0 (43 ms), retain 10>
    | | | |       |     |     | +-o AppleUSBTCKeyboard@1d183000,0  <class AppleUSBTCKeyboard, id 0x1000002fd, registered, matched, active, busy 0 (33 ms), retain 11>
    | | | |       |     |     |   | +-o AppleEmbeddedKeyboard  <class AppleEmbeddedKeyboard, id 0x100000301, registered, matched, active, busy 0 (0 ms), retain 8>
      | | | +-o Apple Internal Keyboard / Trackpad@1d183000  <class AppleUSBDevice, id 0x1000002ee, registered, matched, active, busy 0 (6 ms), retain 15>
      | | | | +-o Apple Internal Keyboard@0  <class AppleUSBInterface, id 0x1000002f8, registered, matched, active, busy 0 (1 ms), retain 5>

中から "っぽい" のを目視で探し,アタリをつけたのが AppleEmbeddedKeyboard というクラス.

この出力結果から,有りそうな情報が絞り込まれるよう試行錯誤をし,結果.

% ioreg -c AppleEmbeddedKeyboard -r | grep -Eiw "VendorID|ProductID"
  |   "VendorID" = 1452
  |   "ProductID" = 594

ちなみに,"IOHID..." ではじまるオブジェクトは沢山あれど,どうも IOHDKeyboard は見当たりませんでした.勿論,探し方が悪かった可能性も拭えませんが...

実は,keyboard id,予め分かっていて,の作業だったりします

事前にどの VendorID とどの ProductID を捕まえれば良いか,を知っていた,と.

ioreg の結果から最終的に「AppleEmbeddedKeyboard だ」と判断した根拠と言うのは,VendorID と ProductID の値を知っていたからのことでして,「この両方が揃っているから AppleEmbeddedKeyboard だ」としたのが本当のところ.

ちょっとしたズルがあったと :-P

ではその keyboards id をどうやって知ったか.

設定の対象とする plist ファイルを見れば良い.

defaults コマンドの部分を見て頂ければわかるよう,-currentHost なので ˜/Library/Preferences/ByHost/ の中にある,というのが分かります.

同様に -g で global domain だと分かるので,˜/Library/Preferences/ByHost/ の中の .GlobalPreferences~ というファイル名の plist ファイルであると分かる.

ファイルは見てのとおり,ドットファイルなので,defaults write com.apple.finder AppleShowAllFiles true && killall Finder で可視化するといー.

あとはこの中を覗いて,com.apple.keyboard.modifiermapping.~ というキーを探せば終了.

はい,そういうことでして.

keyboard id,「引っ張って来るようなことしないで直接書き込んでしまえばいいのに」というのもありますが,何となく嫌なんですよね.

あとちょっと気になっているのは,同じようなことができるらしい?という感じで,system_profiler というコマンドの存在.

おしまい.

*1:Apple やらのオフィシャルの用語ではないようです.

*2:ちなみにこのアプリケーションは,Hardware IO Tools for Xcode という開発者向けのパッケージのうちのひとつらしいのですが,Xcode 8 では未だ無いようです.7.3 まではあるみたい.

*3:ioreg に同じだ,な事が書いてるけど,相手にしているのが "I/O Kit" ではなく "I/O Registry"?何か違ったりするの?...とゆーのは,今んとこは伏せとく :-P