diff --git a/docs/ChangeLog.md b/docs/ChangeLog.md index 2366e2d5..723e903b 100644 --- a/docs/ChangeLog.md +++ b/docs/ChangeLog.md @@ -60,6 +60,7 @@ - syntax: save stat after command name for consistent completion-context `#D2126` 50d6f1bb - term: fix control sequences for hiding cursor (reported by n87) `#D2130` f9b9aea8 - highlight: fix inconsistent tab width in plain layer (reported by dgudim) `#D2132` xxxxxxxx +- decode: consume incomplete keyseq in macros `#D2137` xxxxxxxx ## Compatibility diff --git a/memo/D2137.bashrc b/memo/D2137.bashrc new file mode 100644 index 00000000..eda70cf2 --- /dev/null +++ b/memo/D2137.bashrc @@ -0,0 +1,15 @@ +# 2024-02-04 + +source out/ble.sh --norc +ble/function#advice \ + after ble/decode/cmap/decode-chars \ + '[[ ${keyseq-} ]] && ble/debug/print-variables keyseq chars keys' +bind '"\e[A": "\C-x\xC0\x96\C-x\xC0\x8F\C-x\xC0\x8D"' +bind '"\C-x\xC0\x96": ""' +bind '"\C-x\xC0\x8F": ""' +bind '"\C-x\xC0\x8D": ""' +bind '"\e": ""' +bind '"\e\e": ""' +bind '"\e[123": ""' +ble/function#advice \ + clear ble/decode/cmap/decode-chars diff --git a/note.txt b/note.txt index 0ca0f13a..1d791183 100644 --- a/note.txt +++ b/note.txt @@ -7094,6 +7094,118 @@ bash_tips 2024-02-04 + * decode: bind '"keyseq": ""' で keyseq が正しく解析されていない [#D2137] + + atuin の macro chain の実験中に ble.sh が変な挙動をする + + 結構無理な事をしているから仕方がないとは言え何故この様な振る舞いをするのか + については確認しておきたい。keylog を見ると C-x が重複して受信されて それか + ら SS3 が重複した形になっている何故だろうか。 + + .MACRO は ble-decode-char に対してデータを送っている様だ。ble-decode-char + が受け取っているシーケンスを見る限りは何も問題ない気がする。但し、macro + chain の為に中で新しい keyseq を解析しているのでその解析が途中で入っている。 + + ? reject: 或いはその途中の解析が状態を破壊している可能性? + + ble-decode-key が受け取っているシーケンスも問題ない気がする、と思ったがよ + く見ると 143 (\M-\C-o) を重複して受け取っている。これは内部で解析を行った + 直後である。そう言えば最近 ble-decode-key の解析を修正して新しい状態変数 + を導入したのだった。ちゃんとその状態変数は localize できているのか? blame + で確認するとその変数は _ble_decode_char2_modseq である。bind の為の呼び出 + しは以下の経路で行われている。 + + 'ble-decode-char' + 'ble/decode/cmap/decode-chars' + 'ble/builtin/bind/.initialize-keys-and-value' + 'ble/builtin/bind/option:-' + 'ble/builtin/bind/.process' + 'ble/builtin/bind' + 'bind' + + 然し _ble_decode_char2_modseq を localize しても問題は直らない。他にも途 + 中状態が破壊されている箇所があるという事の気がする。decode-chars の呼び出 + し元で確認する必要がある気がする → 呼び出し元で declare で全変数を dump + して前後比較してみたが _ と keys しか変わっていない。前者は元々変わる物で + 後者は今回目的の変更対象なので期待している通りである。他の状態は何も変更 + されていない。 + + 或いは全く bind を実行しなくても問題が発生するのだろうか? 試してみる → + 再現した。つまり ble/decode/cmap/decode-chars は関係ない。 + + 実は以下の設定だけで問題が再現した。不思議なのは何故最後から二番目だけ問題 + が発生しているのかという事。うーん。keyseq の一致に失敗しているという事だと + 思われるが? + + bind '"\e[A": "\C-x\xC0\x96\C-x\xC0\x8F\C-x\xC0\x8D"' + bind '"\C-x\xC0\x96": ""' + bind '"\C-x\xC0\x8F": ""' + bind '"\C-x\xC0\x8D": ""' + + うーん。keyseq の一致を確認してみると、そもそも \C-x\xC0 の時点で + keybinding が見つかっている。そして \C-x\xC0\x8F に対応する keybinding が存 + 在しない事になっている。何故? つまり、bind を実行した時点での問題の気がする。 + + 改めて .initialize-keys-and-value の結果を確認する。 + + keyseq='"\C-x\xC0\x96"' chars=('24' '192' '150') keys=('67108984' '192' '150') + keyseq='"\C-x\xC0\x8F"' chars=('24' '192' '143') keys=('67108984' '192') + keyseq='"\C-x\xC0\x8D"' chars=('24' '192' '141') keys=('67108984' '192' '141') + + 分かった。つまり、最後の C-o が処理されずに中途半端な状態になっているので、 + keys の中に反映されていないという事。decode-chars では中途半端に pending に + なっている物を flush する機能が必要なのではないか? + + うーん。読んだがよく分からない。ent を取得する部分で何の sequence にも属さ + ない文字を無理やり入れたらいい感じに残留している物がなくなるまで吐き出され + る様な気がする。丁度 __ignore__ というのがあるのでそれを入れて、その上で + __ignore__ を削除すれば良いのでは? と思って試してみたら動く。しかも + __ignore__ は結果に混入していない。 + + ? ok: 然し __ignore__ が消えるのは今回は好ましい振る舞いだが何故だろう? 通 + 常文字として挿入されたりしないのか? と思ったが元より __ignore__ は + csistat の処理の途中で無視するべき (or 処理済み) のキーが発生した時にそれ + にお着替えているのだから、今回の場合も M-__ignore__ みたいな物が生成され + ない限りは __ignore__ も生成されないのである。 + + ? fixed: だとすると、"\e" を正しく処理する事はできるのだろうか? meta + modifier は未だ flush されずに残留する様な気がする。 + + keyseq='"\e"' chars=('27') keys=() + + やっぱり駄目だ。ちゃんと処理できていない。修正が必要である。 + + % コードを読む限りは未だ処理されていない modifier の key 列は + % _ble_decode_char2_modseq に記録されている。特に失敗した時には全てこれを + % 直接 ble-decode-key に流し込んでいるので、_ble_decode_char2_modseq の中 + % 身をそのまま keys に追加すれば問題ない気がする。 + % + % keyseq='"\e"' chars=('27') keys=('27') + % + % 動いている。と、思ったが C-[ に変換しなくて良いのだろうか? うーん。然し + % 最終的に同じ key 列を出力している限りは特に問題はないのでは? 問題は + % __ignore__ が発生しない状況で本当に同じキー列が生成されるのかという事。 + % うーん。そもそも 27 に関しては失敗する事がないから、中途半端な 27 があ + % る keybinding はそもそも意味がない? 改めてコードを見る。 + + うーん。別に _ble_decode_char2_modseq を直接 ble-decode-key に渡している + 訳では無い様だ。寧ろ _ble_decode_char2_modkcode の方を渡していて、その時 + にその key を生成するのに使った char の列として _ble_decode_char2_modseq + が使われているのに過ぎない。 + + keyseq='"\e"' chars=('27') keys=('67108955') + + 改めてそれに倣って見た所、元よりちゃんと C-[ への変換は実施されていた様だ。 + OK。取り敢えずこれでOK \e\e の時の振る舞いもチェックしておく。 + + keyseq='"\e\e"' chars=('27' '27') keys=('201326683') + + 問題なさそうだ。 + + ? ok: 閉じていない CSI シーケンスはちゃんと分解されてから処理される? + + keyseq='"\e[123"' chars=('27' '91' '49' '50' '51') keys=('134217819' '49' '50' '51') + * contrib: execmark が colorglass に対応していない [#D2136] 確認してみた所、これは元々 trace を使って一気に error と elapsed を処理して diff --git a/src/decode.sh b/src/decode.sh index 5a1a145d..9d776c17 100644 --- a/src/decode.sh +++ b/src/decode.sh @@ -2873,6 +2873,7 @@ function ble/decode/cmap/decode-chars { local _ble_decode_char2_reach_seq= local _ble_decode_char2_modifier= local _ble_decode_char2_modkcode= + local -a _ble_decode_char2_modseq=() # suppress unrelated triggers local _ble_decode_char__hook= @@ -2893,9 +2894,12 @@ function ble/decode/cmap/decode-chars { local -a ble_decode_bind_keys=() local _ble_decode_key__hook=ble/decode/cmap/decode-chars.hook local ble_decode_char_sync=1 # ユーザ入力があっても中断しない - ble-decode-char "$@" + ble-decode-char "$@" "$_ble_decode_KCODE_IGNORE" keys=("${ble_decode_bind_keys[@]}") + if [[ $_ble_decode_char2_modkcode ]]; then + ble/array#push keys "$_ble_decode_char2_modkcode" + fi } #------------------------------------------------------------------------------