Rindrics Mumbles

keyball44 を買ったので Dvorak/NICOLA で入力できるようにした

Keyball44 を入手して組み立ててあったのだが、QMK 用のキーマップ定義の書き方を覚えるのが億劫に思えてそのまま放置してしまっていた。

4 ヶ月ほど前(2023 年 10 月)からほそぼそ取り組み始めて、大きく回り道をしながらもなんとか実用レベルにまで設定がまとまった。 動作させるのに必要なポイントがいくつかあったので記事にしておく。

背景

Keyball44 導入前の環境:

  • OS: macOSX
  • キーボード: PFU HHKB
  • 入力方式
    • 英語入力: Dvorak-Qwerty ⌘1(OS ビルトインの入力方式を利用)
    • 日本語入力: NICOLA2(macOSX 向けアプリ Lacaille を利用)

上記の環境を 2016 年ごろから 7 年程度利用しており大変気に入っていたが、同時に下記のような課題も感じていた:

  • 愛用の入力方式を OS のアップデートを経ながらいつまで維持できるかについて、漠然とした不安があった
  • Linux マシンを新たにセットアップするたび、慣れない OS を慣れないキーバインドで使わわねばならないという地獄の苦しみを毎回味わっていた

Keyball44 の良い評判はもちろん知っていたが、長らく品薄状態が続いていたこともあり、自分には手の届かない代物と半ば諦めていた。 そんな中、遊舎工房さんの実店舗に赴いた同僚3がなんとキットの代理購入をしてくれたことによって、やっと積年の課題に向き合う決心がついたのだった。

レイヤー構成とキーマップ(ざっくり)

  • レイヤー 0: 英語と日本語を入力するためのデフォルトレイヤー
    • 英語入力時: Dvorak-Qwerty ⌘
    • 日本語入力時: NICOLA
  • レイヤー 1: 主に数字の入力に利用
  • レイヤー 2: 主に記号の入力に利用
執筆時点のキーマップ

執筆時点のキーマップ

肝心の親指シフトや combo は前掲のレイアウトに表れていないが、動作自体はソースをビルドすれば再現できるので説明しない。 そこそこ複雑な入力方式である NICOLA が英語入力と同じレイヤーで実現されているところが特徴かと思う。 (…とは言ったものの、親指シフトがレイアウトに表れていないのはやっぱり落ち度だなぁ)

下した意思決定

Keyball をバグなく動かすのに必要だった意思決定から順に書いていく。 早く使えるようにすることを重視したので、各意思決定には少なからず妥協も含まれている。

動作させるのに必要だったもの

親指シフトキーにはプレーンなキーを使う

親指の位置にあるキーには、 LT() とか MOD_TAP() を使いたくなりがちだが、親指シフトキーだけは「プレーンなキー」つまり KC_SPC などの通常のキーを使うことにした。 実は、少なくとも MOD_TAP() 系は使い方に注意すれば親指シフトキーとして使えそうだったのだが4、個人的なこだわりとして、認知負荷の軽減のためにNICOLA モードの有効化を親指シフトキーと一緒にしたく、しかしそうして入力切り替え機能を持つキーを親指シフトキーとして使った場合には想定通りに動かなかった。 日英の入力モードの切り替えをどのように扱うかと併せて見直せば解決できたのかもしれないが、ひとまず早く動かしたかったのでこの問題は早々に諦めた。

結果的に、親指シフトキーとして、左は KC_LCTL 、右は KC_SPC を選んだ。 Emacs ユーザーなので、親指 Ctrl はとても嬉しい。

NICOLA の各 shifted キーは combo で定義する

(これは親指シフトユーザーなら直感的にわかるだろうからたぶんわざわざ書くまでもないが…)

レイヤーを使った実装も一応可能ではあるものの、 その場合には親指シフトキー(mod キー)が必ず先に押されていないといけないので、ミスタイプが増えるか、少なくとも日本語入力状態での modified アルファベットの入力はかなり厳しくなりそう。

Dvorak/NICOLA の出し分けをレイヤーではなくイベントハンドリングでプログラムした

(とはいえ、eswai 氏は薙刀式をレイヤーを分けて実装されているので、私の実装はうまくないんだろう)

QMK を触り始めた当初、カスタムキーとして定義した NICOLA 用キー( NICOLA_U とか)を NICOLA 用のレイヤーに配置して実現しようとしていたこともあったのだが(たぶんこのへん)、カスタムキーを作ったところで結局中身はイベントハンドリングになるし、カスタムキー数とレイヤー数の増加によってファームウェアサイズ的なデメリットが大きかったのでやめた5

NICOLA の入力に使う全てのキーについてイベントハンドリングを定義する必要があるので、この部分は下記のようなマクロで実装した: https://github.com/Rindrics/keyball/blob/a1f5fe27b909c53bb831eaba74ff056ca44026bf/qmk_firmware/keyboards/keyball/keyball44/keymaps/rin/keymap.c#L258-L282

このマクロを HANDLE_DVORAK_NICOLA(O, S, "si"); と呼び出せば、Dvorak モードで普通に打鍵した場合には O 、NICOLA モードでは 、GUI-modified な状態では入力モードに関わらず S (つまり多くのアプリにおける “保存” ショートカット)を早出するキーを定義できる。

使い勝手を見ながら設定したもの

入力モード切り替えについて

日英の入力切り替えは下記のように設定した:

  • Dvorak-Qwerty ⌘ オン: LALT(KC_SPC)
  • NICOLA オン: KC_LCTLKC_SPC のコンボ

これらは必須な設定ではないし、なによりかなり地味だが、入力方式の切り替えを自分好みにカスタマイズすることは、私にとって念願の設定の一つだったのでとても嬉しい。

この決定に至った要件をそれぞれ記しておく。

「ステートレス」かつ「複数キー」方式とする

理由は下記:

  • 入力を始めるとき、入力モードが意図したものになっていることを保証したいので、入力切り替えはトグル式ではなく、明示的に指定する方法をとりたかった
  • ミスタイプによって入力方式が意図せず切り替わることを避けたかった
NICOLA オンに利用するキーを親指シフトキーと合わせる

理由: NICOLA オン時に利用するキーをいろいろ試したのだが、親指シフトキーを利用する方法が他の方法に比べて明らかに優れていたため(当社比)

単純に親指の無駄な移動が少なくなること以外にも、認知負荷が軽くなっている実感がある。

NICOLA モードは combo でオンにする

理由: 素朴に LCTL(KC_SPC) としてしまうと、Emacs で範囲選択などに使うコマンド( M-x set-mark-command )と衝突したため

この決定は当初やむなく設定したものだったが、combo は NICOLA モードで多用する入力方式なので、今ではあながち悪くないかもと思っている。

key overrides で Emacs バインドをいつでも使えるようにする

macOS はもともと Emacs キーバインドをサポートしているが、アプリやウェブサイトのモーダルの中には、キーバインドを無言で奪ってくるものがある。

そこでkey overrides を使っていつでも Emacs バインドを使えるようにした。 例えば、LCTL(KC_H) を押すと KC_BSPC が送出される。

少し使ってみて学んだことは、key overrides を使っていても、override 先の単独キーは撤去しない方がいいということ。 撤去したキーが複数キーを組み合わせるショートカットに使われていた場合に詰んでしまう(Ctrl キーを必要とするショートカットを入力できなくなったり、指使いがアクロバティックになったりする)ためだ。

KC_GUI より KC_LALT を押しやすいところに配置する

これは macOS に限定された話ではあるが、GUI キー(⌘)は誤入力したときの影響が大きい。 ⌘-Q (Quit)、 ⌘-M (Minimize)、 ⌘-W (Close)などは、長文入力時に誤発動してしまうと破壊的な悪影響がある。

そこで KC_LGUI を親指のホームポジションから離れ小島(何ていうんだここ)に移動した。 そういえば、Emacs ユーザーなら KC_LGUI より KC_LALT のほうが使用頻度が圧倒的に高いので、その意味でもこうなっているほうがありがたい。

KC_ENT 自体は押しにくいところに配置する

チャット形式のインターフェースを使うときには、入力内容を確認してから送信したい。 Enter キーが押しやすい位置にあると、誤入力によって意図しないタイミングで送信されてしまう可能性があるので、ミスタッチの確率を減らすために右手小指の一番遠い位置に置いた。 こうしても、 KC_ENTLCTL(KC_M) で入力できるよう override しているので、頻繁に使う「確定」操作は無理なく使えている。

親指シフトキーの選定

Keyball は親指キーが複数あるので、親指にも自分なりの「ホームポジション」を設定したくなる。 すると、NICOLA モードで多用する親指シフトキーは、この「ホームポジション」としたキーにするのが合理的だ。 私は Ctrl と SPC をよく使うので、これらを親指シフトキーにした。

一応、市販の親指シフトキーボードのように、親指シフト機能だけを持ったカスタムキーを定義することもできるが、キーをなるべく節約したかったのでやめた。 親指シフトキーは必ず同時押しで使われるため、combo として定義すればキーを二つぶん節約できることになる。

数字を必ず半角で入力できるようにする

これは恐らく全人類が同意してくれるネタだと思うが、全角数字を入力したくなるシーンは絶対に存在しない。

そこで下記のような処理で、NICOLA モード時に数字キーが押されたときには、一時的に Dvorak-Qwerty ⌘ モードに切り替えることで半角数字が送出されるようにした。 https://github.com/Rindrics/keyball/blob/a1f5fe27b909c53bb831eaba74ff056ca44026bf/qmk_firmware/keyboards/keyball/keyball44/keymaps/rin/keymap.c#L305-L310

対応する括弧類は隣り合う指にする

開き括弧に対する閉じ括弧をどのように入力するかの話。 コーディング時には補完が効くことが多いが、補完がない状態でもストレスなく入力できるようにしておきたい。 今のところ、左手の小指と薬指、中指と人差し指がそれぞれ開き–閉じのセットになるようにマッピングする方法に落ち着いた。 これまで、開き括弧を入力するキーを mod 版を閉じ括弧にしたり、開き括弧を入力した指に対して、反対側の同じ指を閉じ括弧にしたりを試してみたが、どちらも直感的に使えなかったので却下した。

改善点

使用頻度の高いショートカットの追加

キーマップにまだまだ余裕があるのでぽちぽち追加していきたい

OLED の有効化

かっこいいから。

もしかすると…Qwerty ⌘ でない、ただの Dvorak でいいかもしれない

この記事を書いていて気づいたのだが、Keyball のようなプログラマブルキーボードを使っているならば、Dvorak-Qwerty ⌘ にする意味があまりないかもしれない。 QMK を触り始めたころ、マッピングにそこそこ苦労したところだけど。

思い返せば、英語入力に Dvorak-Qwerty ⌘ を選定した当時、私はソフトウェアエンジニアではなかった。 当時は WYSIWIG ソフトウェアを使う頻度がそれなりにあり、したがってコピー(⌘C)、ペースト(⌘V)、保存(⌘S)、undo(⌘Z)などの GUI ショートカットの使用頻度も高かった。 これらのショートカットは、Qweryt 配列ならば一箇所にまとまっており片手でも入力できるのだが、Dvorak 配列だと各キーはかなり分散してしまう。 当時はこれをデメリットと捉えて Dvorak-Qwerty ⌘ を選定し、そしてそのまま現在までの 7 年間、惰性だけで使い続けてきたことになる。

しかしソフトウェアエンジニアとして働く現在、GUI ショートカットの出番はかなり少なくなったし、もし GUI ショートカットが必要な場面においても、Dvorak でも Qwerty でもない、よりよいキーマップで入力できるはずだ。 …うーん、卒業するか。

まとめ

  • GrabShell がほしい()
  • お気に入りの配列をどのマシンでも(新しい Linux でも!)使えるようになったのがとても嬉しい
    • プログラマブルキーボードなしに特殊な配列に手を出すのはリスクが大きい行為だったと思う

  1. Dvorak-Qwerty ⌘ と書いてしまうと macOS にしか通用しなくなってしまうが、要は Dvorak 配列を基本としつつも、GUI キーを押している間だけ Qwerty 配列になる配列のこと。多くのアプリに共通する GUI ショートカットを崩さずに利用できるのが利点 ↩︎

  2. Nihongo Input COnsortium LAyout の略でいわゆる「親指シフト」の規格の一つ。本家による解説は http://nicola.sunicom.co.jp/spec/kikaku.htm。 ↩︎

  3. wonwon-eater さんです。ありがとうございます。 ↩︎

  4. 例えば LSFT_T(KC_SPC) を親指シフトキーとして使う場合、combo 定義時には LSFT_T(KC_SPC) を指定する必要があった(combo 時の打鍵がタップ的だからといって、タップ時に創出される KC_SPC を指定しても期待通りには動かない) ↩︎

  5. 実際にサイズオーバーでコンパイルが失敗するようになったので、こちらの記事を参考にオプションを調整した。OLED も泣く泣く諦めた。いいんだ、どうせ見ないから、、、 ↩︎


comments powered by Disqus