KLE本家は拒否するが、VIAとRemapは読む。Remapで扱える基板を取り込めない 状態にしないため、位置を問わず受け入れる。本家のコードから行頭チェックを 外した挙動をそのまま採る。出力は従来どおり行頭にのみ置く。 Journal: journal/2026-09-21-kle-lenient-row.md Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SSKcJLPAaPLchG4LXxk6cY
3.7 KiB
行の先頭以外の r, rx, ry を受け入れるか
結論
受け入れる。位置を問わず、そのキー以降に適用する。rx, ry は座標を (rx, ry) に戻してから x, y を加える (KLE本家のコードから行頭チェックだけを外したときの挙動と同じ)。
決め手は Remap が読めること。ユーザーの判断: 「Remapで扱えるものを拒否したくない」。
| 案 | 取り込める基板 | 既存の解釈への影響 | 出力への影響 |
|---|---|---|---|
| 本家に合わせて拒否 | 1505件中1504件 | なし | なし |
| r だけ受け入れ | 1505件 | なし | なし |
| r, rx, ry とも受け入れ(採用) | 1505件 | なし | なし |
3案とも出力は変わらない。本家の serialize はクラスターが変わると必ず行を割るので、 r, rx, ry は常に行頭にしか出ない。寛容化しても非互換なJSONを生む側には回らない。
実データ
コーパス1505件(KLE本家プリセット12 + samples 9 + the-via/keyboards 1484)で、
行の先頭以外の r, rx, ry を持つのは owlab/spring/spring.json の1件だけ。内訳は r が15回、rx/ry は0回。
spring は Alice系。物理行ごとに配列を1つ書き、行の途中で r を 0 → 12 → -12 → 0 と切り替えている。 行頭チェックを外して読むと素直に開く(67キー、左右±12度のスプレイ + 回転なしの外側2列)。
0,3 x=3.25 r=0 0,4 x=4.44 r=12 0,8 x=8.72 r=-12 0,12 x=12.85 r=0
1,2 x=2.50 r=0 1,3 x=3.70 r=12 1,7 x=8.48 r=-12 1,11 x=12.60 r=0
寛容化が既存の解釈を変えないこと
本家 serial.js の該当箇所は throw だけで、意味づけは残りの行が決めている。
if(key.r != null) { if(k!=0) {deserializeError(...)} current.rotation_angle = key.r; }
if(key.rx != null) { if(k!=0) {deserializeError(...)} current.rotation_x = cluster.x = key.rx; extend(current, cluster); }
throw を3つ消したパーサーと本家で全1505件を読み比べ、本家が読めた1504件はキー配列が完全一致。 変わるのは今エラーになる1件だけ。
他のツールの受け入れ
| ツール | 行の途中の r/rx/ry | 根拠 |
|---|---|---|
KLE本家 serial.js |
拒否 | 'r' can only be used on the first key in a row |
| kle-serial (ijprest, TS移植) | 拒否 | 同じチェックを移植 |
Vial kle_serial.py |
拒否 | k != 0 and ("r" in item or ...) |
| kicad-kbplacer | 拒否 | 同じチェックあり |
VIA @the-via/reader |
許容 | reduceで位置チェックなし |
Remap KeyboardModel.ts |
許容 | Current.setOp() に位置チェックなし |
QMK kle2xy.py |
無関係 | r/rx/ry を読まない(回転を捨てる) |
Remap の Current を位置計算だけ移植して、throw を外した本家と突き合わせた。行の途中の r、
行の途中の rx/ry、途中で r=0 に戻す、spring 全体、いずれも一致する。VIA reader はコードを読んだだけで、
cursor.y = ry としか書いていないため rx/ry の扱いは本家と違う可能性がある(spring は rx=ry=0 なので影響なし)。
同じ突き合わせをコーパス全件でやると19件が不一致になるが、いずれも行頭側の ry の解釈やラベルなしキーの扱いで、 今回の話とは別件。簡易移植での比較なので Remap 本体で再現したわけでもない。追っていない。
取り込んで書き戻す
spring を寛容パーサーで読み、PHY経由で本家の serialize に通すと、5行 → 26行のJSONになる。 本家の deserialize が読め、配置も元と一致した。寛容化は本家で開けないファイルの修復経路になる。