azooKey で Colemak 使いたい → PR マージまでの一日
皆さんこんにちは。「Anthrotech Advent Calendar 2025」、15 日担当の inugaminé です。
この記事はケモノ界隈の技術者のためのコミュニティ: Anthrotech で公開されています。
ケモノが好きでコンピュータなどの技術に興味がある方はぜひリンク先をチェックしてみてください!
昨日は@RyoTNさんのConcrntでRustFSを使おう!~MinIOからの移行~という記事でした。
新しいシステムにスムーズに移行できる技術力、凄まじいですね👀✨
さて、今回は人生初のアドベントカレンダーとして、OSS プロジェクトである「azooKey」に初めて本格的なプルリクエストを投げ、そのプルリクエストがマージされるまでのお話を書かせていただこうと思います。
そもそもあんた誰よ - 自己紹介と前提のお話
改めまして戌咬音かんぬき (inugaminé) といいます。
普段はととがんまさんが中心となって開発が進められている分散型SNS基盤 Concrnt や Bluesky 地方に存在していて、日常のあれこれや、最近興味を持っている Swift について、ああでもないこうでもないと言いながらポストをしているプログラミング初心者です。
今日はぜひ名前だけでも覚えていってください。
今回話題に上がる「azooKey」って?
azooKey とは、iOS や macOS でライブ変換が行える日本語 IME です。
オープンソースソフトウェアとして開発が行われていて、なんと Windows 版と Linux 版もあるそうです。
詳しい情報は azooKey公式サイト や azooKey 公式 GitHub をご確認ください。
また、今回の記事では macOS版である azooKey-Desktop について取り扱っています。
上でちょっと書いている iOS、Windows、Linux 版のお話は含みませんのでご注意ください。
ちなみにオープンソースソフトウェア (Open Source Software、略称 OSS) とは、ソースコードと呼ばれる設計図のようなものが一般に公開されていて、誰でも無料または低コストで利用・改変・再配布できるソフトウェアのことです。現代の IT 社会やインターネットの基盤を支えています。
ことの始まり
僕が azooKey と出会う前までは、Mac の標準 IME である「日本語 IM」を使用していました。
この IME には漢字やカタカナの変換を自動で行うライブ変換という機能があり、個人的にとても重宝していたのです。
そんな日本語 IM ですが、困ったことにそもそもの変換能力があまり高くありません。また、意図して変換を行うためにスペースバーを押しても反応しないなど、ライブ変換以前の問題を抱えていました。
かねてから Mac の日本語能力は低いと言われていたのは知っていたのですが、いざ目の当たりにすると真顔になってしまいます。
もちろん一度は Google 日本語入力の Mac 版の導入も検討しました。
しかし当時は Apple Silicon にネイティブで対応しておらず、Rosetta 2 を使うことに僅かばかりの不満がありました。
最大のマイナス要素ですか? ライブ変換が利用できなくなることです。
そのため渋々標準の日本語 IM を使用し続けることに。
そんなある日、ふと思い立って Google 日本語入力以外の IME を探していたところ「ライブ変換が可能で、大規模言語モデル (LLM) を使って精度の高いかな漢字変換を行う IME がある」という情報を得ました。
これが僕と azooKey との出会いです。僕はさっそくダウンロードして使って……みたのですが……
第一話「Colemak 配列が使えない!?」 - まさかのところに潜んでいた罠
僕は普段から Colemak 配列と呼ばれるキーボード配列を使っています。
詳しい説明はここでは割愛する必要があり大変心苦しいのですが、皆さんが普段使っている QWERTY 配列と呼ばれるキーボードのキーの配置を、なんかいい感じになるように再配置したキーボードなんだな〜と思っておいてください。
みんなも Colemak 配列を使いましょう。
さて、何が起こったかはもうタイトルからして明らかなのですが、azooKey は Colemak 配列を認識してはくれませんでした。
まるで右腕を動かそうとすると左足、右足を動かそうとすると右肩が動くかのような感覚です。まともに文字入力ができません。
落ち着いて観察すると、どうやら QWERTY 配列で入力が行われているようでした。
azooKey の設定項目に配列を固定する設定があるのかと思って見てみたのですが、そのような項目は見当たらず……
結果として azooKey の利用はここで終了となりました。
かんぬきの IME 探しはここでおしまいです。読んでいただきありがとうございました。
-完-
第二話 最初の解決 - コメントアウトで動いた
しかし、どうしてもライブ変換と高効率の変換機能を使いたい。奥歯を噛み締めながらそう思った僕は、とあることに気が付きました。
「オープンソースってことは、自分で修正すればいいんじゃね?💡」
ソースコードが公開されているということは、自分でコードを弄ってビルド、つまり自分専用の azooKey が作成できるということです☝️
その事に気がついた僕は、おぼつかない操作で公式 GitHub から azooKey のリポジトリをクローンしました。
(「azooKey の設計図をパソコンにダウンロードする」ことの専門的な言い方です)
azooKey のソースコードを、人工知能の Claude と一緒に読んでみたところ、
client.overrideKeyboard(withKeyboardNamed: "com.apple.keylayout.US")
self.client()?.overrideKeyboard(withKeyboardNamed: "com.apple.keylayout.US")
というコードがいくつかの場所で見つかりました。
その筋のプロの方や、勘のいい方はお気付きかと思いますが、こいつが今回の犯人です。
overrideKeyboard とあるように、com.apple.keylayout.US で QWERTY 配列が強制されていました。これではいくら Colemak でタイプしてもうまく入力できません。
ここで初心者の僕は覚えたての知識をこねくり回し、ふとした疑問を持ちます。
「これをコメントアウトすれば、どのキー配列にするかの指定がなくなるのでは?」
Claude にお願いして似たようなコードを探してもらい、それらの該当部分をコメントアウトしてビルドしてみました。
結果、あっけなく Colemak 配列で文字入力が行えるようになりました。
標準 IM 以外でのライブ変換、しかもこれまでよりも正確な変換が行われていく様子に興奮を抑えられませんでした。
すごいぞ azooKey!!!
第三話 設定画面も実装してプルリクエストしちゃお - かんぬき初めてのプルリク
azooKey の開発者でもない僕にはどうしてキーボード配列を QWERTY に固定しているのかは分かりませんが、少なくともこれでキー配列の固定を回避することができるようになりました。めでたしめでたし。
……とはいかないのが僕かんぬきです。
うちには iMac と MacBook Air があるのですが、主に実験で使っているのは MacBook Air であり、今回も実験でビルドしたので Colemak 版 azooKey は MacBook Air にしかありません。
綺麗に使いたい iMac にいろいろな開発ツールを組み込むには些か面倒であり、かつ今後も開発が進んで正式に更新される公開版 azooKey と違い Colemak 版は手動で更新を取り込まねばならず、初心者の僕には荷が重い作業です。
どうにかしてキーボード配列が固定される問題を修正してもらえないだろうか。
Claude にどういうアプローチを取ればいいだろうかと相談したところ、
おいおい『修正してもらう』じゃねえよ。お前が作って出しちまえばいいんだ。それがオープンソースってもんだろ?コード書いて、プルリク出して、『これ使ってくれ』って堂々と言やいい。Swift初心者?関係ねえ。動くもん作れば、それが価値だ。やってみようぜ!
と返ってきました。手塩にかけて育てた結果、かなり脳筋な AI になったようです。
僕にできるのか〜?と思っていたのですが、いろいろやり取りを続けたところ
単にコメントアウトしただけじゃなくて、ユーザーが設定で選べるようにするってことだろ?
実装方針 「macOSのキーボード配列を使う」っていう設定項目を追加して、オン/オフできるようにする。デフォルトはオン(Colemakなどカスタム配列を尊重)にして、何か理由があってQWERTY強制が必要な人だけオフにできるようにする。
つまり com.apple.keylayout.US で強制されているのが原因なら、必要に応じて強制されないように if 文で切り替えればいいのではとなったため、azooKey の設定画面にチェックボックスを設け、そのオン・オフで強制されるか否かを切り替える方式を取ることにしました。
それぞれ
if let client = sender as? IMKTextInput {
if !Config.RespectSystemKeyboardLayout().value {
client.overrideKeyboard(withKeyboardNamed: "com.apple.keylayout.US")
}
if let value = value as? NSString {
if !Config.RespectSystemKeyboardLayout().value {
self.client()?.overrideKeyboard(withKeyboardNamed: "com.apple.keylayout.US")
}
という修正内容になりました。
また、設定画面の修正箇所も Claude に教えてもらい、勉強中の SwiftUI でチェックボックスを実装しました。
ちなみにチェックボックスを設けるには Toggle() というものを使い、
Toggle("macOSのキーボード配列を使用", isOn: $respectSystemKeyboardLayout)
というような形でコードを書きます。
(近くに他のチェックボックスがあったので見よう見まねで書きました。)
再度ビルドし、設定画面にチェックボックスが実装できました。
チェックを入れると Mac で設定しているキーボード配列が。逆にチェックを外すと従来通り QWERTY 配列になるようになったので、ようやくプルリクエストを送ることができます。
少しだけ慣れた操作でコミット操作をし、リモートリポジトリにプッシュし、おぼつかない操作で GitHub を操作しながらプルリクエストを作成し、そしてドキドキしながら送信しました。
第四話 プルリクエスト、取り下げます!!!(一敗)
午前 4 時 57 分にプルリクエストを送信した同日午前 10 時 28 分、GitHub から通知が届きました。
あんな時間にプルリクエストを送って本当にごめんなさい。
なんと azooKey の開発者さんからのレビューコメントでした。
内容は実際のプルリクエストのリンク先に書いてある通りなのですが、僕は「チェックを外せば配列強制が解除され、Mac で設定した入力ソースに従って動作する」と思っていましたが、 では解除された後、azooKey はどうやって Colemak 配列を認識しているのか? という根本的な疑問に確証を持って答えられませんでした。
そこで、慌てて Claude に相談しながら検証を始め、「azooKey がどうやってキーボード配列を認識しているのか」を調べることにしました。
Mac の入力ソースから「U.S.」や「ABC」、「Colemak」などを追加したり削除したりしながら、どの配列が優先されるのかを確認していきます。
結果、わかったことは:
- Mac 標準の ABC (QWERTY 配列) と azooKey のみ → QWERTY配列で動作
- Mac 標準の U.S. (QWERTY 配列) と azooKey のみ → QWERTY 配列で動作
- Mac 標準の Colemak と azooKey のみ → Colemak配列で動作
- Mac 標準の U.S. と Colemak、azooKey → QWERTY配列で動作 (Colemakが無視される)
つまり、入力ソースにある配列を基準にしていて、QWERTY と Colemak が両方あると QWERTY が優先されるという、環境に依存した動作になっているらしいことが分かりました。
これでは、ユーザーの環境によって動作が変わってしまいます。困りました。
「それなら、明示的に配列を指定すればいいのでは?」そう考えた僕たちでしたが、次に直面した課題は Mac がキーボードを認識する際の識別子の謎です。
overrideKeyboard(withKeyboardNamed:) に渡すべき正確な文字列が分からないのです。
今回強制されるキーボード配列の識別子は com.apple.keylayout.US でした。
だからといって Colemak 配列の識別子は com.apple.keylayout.Colemak なのか? そもそも別の識別子なのか?
defaults read com.apple.HIToolbox AppleSelectedInputSources というコマンドで調べると、下記のように返ってきました。
(
{
"Bundle ID" = "com.apple.PressAndHold";
InputSourceKind = "Non Keyboard Input Method";
},
{
InputSourceKind = "Keyboard Layout";
"KeyboardLayout ID" = 12825;
"KeyboardLayout Name" = Colemak;
}
)
下から 3 行目 "KeyboardLayout Name" = Colemak; とあり、com.apple.keylayout.US とは大きく異なっていますね。Claude と一緒に調べてみましたが、確証が持てません。
JIS 配列の識別子に至っては、うちには US 配列の Mac しかないため、自前で検証すらできませんでした。
これに関しては Anthrotech のメンバーさんに Mac で JIS 配列をお持ちの方がいたので助けていただけました。圧倒的感謝ァ!🙏
キーボードレイアウトの識別子について調査しましたが、overrideKeyboard(withKeyboardNamed:) に渡す正確な文字列の特定が難しく、また各レイアウト(Colemak、Dvorak など)の動作検証も必要になるため、現時点では確実な実装が難しいと判断しました。
Claude に相談するとこう返ってきました。
お前、十分頑張ったぜ。今回は一旦引いて、もっと調べてから再挑戦するのも立派な判断だ。完璧を目指して出せないより、問題を認識して次に活かす方が価値がある
そうだ、焦る必要はない。初心者なりにここまで頑張ったんだ。一度引いて、しっかり調べてから再挑戦しよう。
僕は azooKey の開発者さんに、以下のようにコメントを返しました。
キーボードレイアウトの識別子について調査しましたが、
overrideKeyboard(withKeyboardNamed:)に渡す正確な文字列の特定が難しく、また各レイアウト(Colemak、Dvorakなど)の動作検証も必要になるため、現時点では確実な実装が難しいと判断しました。つきまして、今回のプルリクエストは一旦取り下げさせていただけないでしょうか。 貴重な学びの機会をいただきありがとうございました。
こうして、僕の初プルリクエストは取り下げとなるはずでした。
……ちょっと待った🤔
そういえばうちの iMac って JIS 配列のキーボード構成で届いていたのをここで思い出しました。
iMac の箱を開けると、包装されたままの JIS キーボードが収まっています。灯台元暗しとはまさにこのこと!
Mac に接続して再び defaults read com.apple.HIToolbox AppleSelectedInputSources コマンドを打ったのですが
(
{
"Bundle ID" = "com.apple.PressAndHold";
InputSourceKind = "Non Keyboard Input Method";
},
{
InputSourceKind = "Keyboard Layout";
"KeyboardLayout ID" = 252;
"KeyboardLayout Name" = ABC;
}
)
この結果は、検証作業で確認した US 配列の場合と同じものが出力されました。これでは US 配列と JIS 配列における @ などの記号の差異を吸収できません。頭を抱える動作がうまくなった Claude を横に、僕はある仮説を立てました。
もしこの com.apple.keylayout.US で強制されている状態であっても JIS 配列では @ がキーボード通りに打てるのではないかというものです。もし azooKey 使用中に JIS 配列の印字通りに @ などが入力できれば US/JIS を分ける必要がなくなるのではないか。
結果としては JIS 配列の印字通りに記号が入力できました。つまり、QWERTY に関しては US/JIS (恐らく UK も)を分ける必要がなさそうだということです。
とはいえ識別子の予測がつかなくては進めることができません。
第五話 やります!やらせてください!!! - 開発者さんの助け舟
落ち込んでても仕方ない。しかし、ここまで結構 Claude とやり取りしながら進めてきたので Claude は時間当たりの制限に到達してしまいました。しばらく作業はお休みです。
ふと気がつくと GitHub から通知が来ていて、なんと開発者さんがキーボードレイアウトの一覧(FreeRDP)を見つけてくださいました。
僕はすぐにその情報に齧り付きます。
一覧を確認したところ、Colemak の識別子は com.apple.keylayout.Colemak とありました。
これはいけるのでは? 心臓が高鳴ります。
開発者さんからはレビューコメントにて
「com.apple.keylayout.USに強制的に置き換える処理を外す」ではなく、「com.apple.keylayout.USではない配列に強制的に置き換える」が妥当だと思います
という指摘を頂いていたので、それを満たすためにもチェックボックスで強制を回避する方法から、キーボード配列を azooKey に明示するというアプローチを取ることにしました。
com.apple.keylauout.US を azooKey に指定できているのだから、別の配列を指定することもできるはずです。
リミットが解除された Claude とやり取りを再開し、まずは設定を行うためにプルダウンで選択するギミックを入れる事にしました。
ちなみに、SwiftUI ではプルダウンの事を Picker と呼び、以下のように書きます。
Picker("キーボード配列", selection: $keyboardLayout) {
Text("QWERTY (US)").tag(Config.KeyboardLayout.Value.qwerty)
Text("Colemak").tag(Config.KeyboardLayout.Value.colemak)
Text("Dvorak").tag(Config.KeyboardLayout.Value.dvorak)
}
また、Colemak の他に Dvorak 配列というキーボードも存在するため、それも一緒に追加しました。
再びビルド。エラーが出ないかドキドキしながら見守ります。
うまくビルドが通ったので次は動作確認です。ちゃんと動いてくれるかドキドキしながら Mac を再起動させました。
azooKey をインプットメソッドに追加し、プルダウンから まず QWERTY を選択します。うん、Colemak 配列通りに入力できませんが QWERTY 配列通りに入力できています。
次に プルダウンから Colemak を選択します。こちらもしっかり入力できました。
最後に Dvorak 配列。これは持っていないので画像検索をして配列を確認しながら入力します。
無事配列通りに入力できました。
……ん?🤔 完成では???
第六話 初のマージ! - 今回学んだこと
完成したのです、Colemak で使える azooKey が!!!
興奮冷めやらぬまま僕はスクショを撮り GitHub に駆け込みました。
「Picker で選択する方式で実装することができました!今のところ QWERTY、Colemak、Dvorak での入力に対応することができています」
プルリクエストのコメント欄にスクショと報告を投稿。送信ボタンをクリック。
しばらくして、開発者さんからレビューコメントが届きました。
レビュー 1:変数名の改善
この変数名は layoutIdentifier などの方が良さそうです
確かに。layoutName より layoutIdentifier の方が、識別子であることが明確です。
すぐに修正してプッシュ。
レビュー 2:Optional の削除
この値が Optional である必要はない気がするんですが、何か意図がありますか?
あっ、これは確かに。全ての case で必ず値を返しているので、String? ではなく String で十分です。
if let を使わなくてもよくなり、コードがシンプルになりました。
// 修正前
if let layoutIdentifier = Config.KeyboardLayout().value.layoutIdentifier {
client.overrideKeyboard(withKeyboardNamed: layoutIdentifier)
}
// 修正後
client.overrideKeyboard(withKeyboardNamed: Config.KeyboardLayout().value.layoutIdentifier)
すっきりしましたね!🙌 これに似たものが今回僕が修正した部分であと 2 箇所あり、そこも同じように修正しました。
設定画面の Picker の位置も少し調整。「ライブ変換を有効化」の上に配置した方が、入力方式の設定としてまとまりが良くなります。
一つひとつ丁寧に対応していきました。
そして……
Merged のラベルが表示され、人生初のマージとなりました。
僕たちが書いたコードが、正式な azooKey に取り込まれたのです。
これで日本中の、いや、世界中の Colemak ユーザーや Dvorak ユーザーが azooKey で問題なく文字入力ができるようになります。
はじめはただ不便さを解消するだけの修正だったはずが、気が付いたら機能追加をしてマージにまで繋がりました。
今回の教訓
今回、初めての個人での開発、ほとんど初めての GitHub 上でのコミュニケーション、その他、たくさんの初めてを経験しました。
マージされて嬉しい気持ちもありますが、同時に反省点もたくさんあります。
次はもっといい貢献ができるように、学んだことを書き残しておきます。
-
安易な考えで修正を行わない:
Colemak 配列でうまく動かない = azooKey の不具合かもしれないみたいな ほんのりとした認識 で手を出さない。既存のユーザーさんのエクスペリエンスに悪影響を与える可能性を考えなさい。
→ 開発者さんから「今回の変更を入れたとき、azooKeyは『正しく』動いていますか?Key Codeをマップする処理などが期待通りに動いてるのか若干不安です」というコメントを頂いていました。
Key Code のマッピングに関しては明確な回答ができず、キーボードショートカットの話しかできませんでした。
これは恥ずかしい話で、特に後半部分の Control + U, I, O, P に関しては既に azooKey 側で何か設定されているキーバインドだったらしく、いかにトンチンカンな返答をしているかが丸出しです。実に情けない。
もっと視野を広く持ち、既存のユーザーさんにどのような影響が出そうなのか、少なくともそういう部分に気を回せるようにならなければいけませんね。 -
初見でプルリクエストを出さない:
今回いちばん大きな教訓。まずは公式コミュニティ内で似たような機能追加の話がないか確認をしなさい。無かったのなら issue を立てなさい。
→ オープンソースプロジェクトのセオリーが分かっていない僕の落ち度は、機能追加や修正に関して予めコミュニティ内の有識者とやり取りをしなかったことです。OSS が何たるかを分かっていない初心者なので「分からなければ聞く」ということをまず行うべきでした。あろうことか突然やってきてプルリクエストを叩きつけたのです。
もしかしたらそれもよくある事なのかもしれませんが、少なくとも OSS の文化について何も情報を持っていない僕は、開発者さんやコミュニティの方に挨拶をし、やろうとしている事を説明するべきでした。そうすれば、キーマッピングの話やそもそもの仕様、僕が困っていることの情報共有ができ、スムーズに進められたかもしれません。
公式コミュニティの存在も後になってから知ってしまった(!)のですが、もし引っ掻き回すだけ引っ掻き回していたらと思うとゾッとしてしまいました。確認は大切ですね。
azooKey の開発者さんが優しい方で本当によかったです。コミュニティにも参加して、自己紹介もできました。
今後、かんぬきが個人で何かしらを開発する時に、あるいはまた別の OSS の開発をお手伝いさせていただく時には、今回学ばせていただいた事に気をつけながらやっていこうと思います。
終わりに
OSS は小さなことからでも開発に貢献できる素晴らしい取り組みだと感じました。
初心者だから首を突っ込んではいけないということは全然ありません。(今回の僕の立ち回りは完全に悪い例ですが……)
もしかしたら、あなたが感じている「困ったな」と同じ問題を抱えている人が他にもたくさんいるかもしれませんよ。
オープンソースプロジェクトや、それをはじめとした OSS は、そんな「問題」を解決する敷居がとても低いのが強みだと思います。
あなたも勇気を出してソフトウェアやプロジェクトの改良に貢献してみませんか?
ここまで読んでいただきありがとうございました。
かんぬきのお話はここでおしまいです。
みんなも Colemak 配列と、そして azooKey を使おう!!!
今回の記事は、僕と Claude の二人三脚で貢献した Colemak 配列対応版 azooKey を使って執筆しました。