diff --git a/memo/ChangeLog.md b/memo/ChangeLog.md index 02a5bb5f..7685a89c 100644 --- a/memo/ChangeLog.md +++ b/memo/ChangeLog.md @@ -14,6 +14,7 @@ - canvas: update emoji database and support `bleopt emoji_version` (motivated by endorfina) `#D1454` d1f8c27 - canvas, edit: support `bleopt info_display` (suggested by 0neGuyDev) `#D1458` 69228fa - canvas (panel): always call `panel::render` to update height `#D1472` 51d2c05 + - util (visible-bell): work around coordinate mismatches in subshells `#D1495` 0000000 - prompt: support `bleopt prompt_status_{line,align}` and `face prompt_status_line` `#D1462` cca1cbc - prompt: fix missing height allocation for status line `#D1487` b424fa5 - syntax: properly support case patterns `#D1474` `#D1475` `#D1476` 64b55b7 diff --git a/note.txt b/note.txt index 3fa40fa1..852f3101 100644 --- a/note.txt +++ b/note.txt @@ -1204,19 +1204,34 @@ bash_tips ToDo ------------------------------------------------------------------------------- -2021-02-22 +2021-02-23 - * global: IFS 対策 + * util: カーソルが bottom-dock にいる時の vbell の座標計算 + Ref #D1495 ... 取り敢えずの対策 - 多くの関数は IFS が普通の値になっているという事を前提にして書かれている。 - ble.sh の中では一時的に IFS を設定して動作する様になっているが、 - ユーザーから使用された時に IFS に変な値が設定されている可能性は排除でいない。 + 現在の実装は vbell が sc..rc を自由に使える前提になっている。しかしカーソル + が bottom-dock に停泊している時に vbell が来るとvbell によって floating + panels の位置が分からなくなってしまい、表示がずれてしまう事になる。 - * 引数を $* で渡された時の対策は取り敢えず grc -F で ${* もしくは $* に一致させて確認した。 - * 配列に対する単語分割 =($...) に関してもチェックは行った。 + 同じプロセス (親シェル) の中で vbell を処理している場合には、一旦 floating + panel の位置に戻ってから sc..rc をしてそれから再び bottom-dock に戻るという + 手順を踏む事によって問題を回避できる。然し、サブシェルの中にいる場合には現 + 在の最新の配置情報にアクセスできないのでこの方法は取れない。 + + 現在は取り敢えずカーソルが bottom-dock に停泊している事はないとの想定で + sc..rc を実行しているが、例えば info_display=bottom にして vi_cmap を使って + いる時などにこの前提が破れてしまう。 + + [解決方法] - 他に配列を結合する処理に関しても注意が必要になる可能性がある。 - つまり、aa="${arr[*]}" の形の処理である。 + ちゃんと実装する為には、親シェルで全ての描画を行う様にする必要がある。その + 時に問題になるのがどうやって visible-bell の消去のタイミングを親側で決める + かという事。idle を使う方法は bash-4 以降でしか使えない。シグナルを使う方法 + には余り頼りたくないが、現実的にはそうするしかないのだろうか。bash-3 と + bash-4 で実装を切り替えても良い。何れにしてもサブシェルと通信を行う枠組みを + 整える必要がある気がする。 + +2021-02-22 * cavnas: 描画の最中で status が高さを取得する時に textarea の内容を削り取る可能性がある @@ -3756,6 +3771,110 @@ bash_tips Done (実装ログ) ------------------------------------------------------------------------------- +2021-02-23 + + * util: vbell で座標計算がずれる [#D1495] + + [状況] + + | 座標計算がずれる様になっている。ble.sh のディレクトリで空コマンドラインで + | TAB 補完を実行しようとすると、complete_limit に達すると同時に sabbrev 候補 + | の \ が一次挿入される。この時に座標が一つ左にずれる。 + | + | 8856a04 では問題は起こっていない。3cadd54 では問題が発生している。37363be + | でも発生している。3cadd54 は ecb8888 に対応する。 + | 取り敢えず問題の commit は 69228fa にあると分かった。 + | + | * bleopt edit_vbell= にすると問題は発生しなくなる。 + | * visible-bell の先頭で return して実際の処理を行わない様にすると発生しなく + | なる。 + | + | 問題の commit では vbell に対する修正も色々入っている。やはりこの辺りが怪し + | い。 + | + | これは sc/rc による問題だろうか。然し、_ble_term_sc= _ble_term_rc= としても + | 問題は再現している。fork の直前で return 0 すれば問題は生じない。つまり + | .show 自体の問題というよりは出力が混ざる事による問題の様な気がする。 + | 然し buffer.flush を fork 直前に挿入しても何も効果はない。 + | + | うーん。タイミングが丁度悪いという事なのだろう。 + + あー。分かった。save-position/restore-position しているが、この時に + _ble_canvas_{x,y} を参照している。然し、これらの値は subshell の中では更新 + されない。これが理由で座標計算がずれてしまうのである。 + + [解決法] + + どの様に対策すれば良か。何が問題かと言うと…bottom-dock に対応する為に + SC/RC を使っていて、それが visible-bell の使っている SC/RC と衝突していると + いう事。コマンドライン上に居る時には visible-bell の為に SC/RC しても良いが、 + bottom-dock にいる時には visible-bell が SC/RC すると本来のコマンドライン上 + の位置が失われてしまって問題になる。これを防ぐ為に visible-bell では一旦コ + マンドライン上に復帰してから visible-bell を表示する事にしている。 + + どの様に解決するべきか。 + + a IPCか何かを使って vbell の状態変化を親シェルに伝達して描画は親シェルで行 + う様にする? 然しどの様に伝達するのが良いだろうか。 + + - シグナルは bind -x の内部ではチェックされない (もしくは bash の内部的に + はチェックされているのかもしれないが対応する trap handler の呼び出しが + 遅延される)。然し、或いはそれでも良いのかもしれない。例えば現在 + bash-3.0 における C-d の読み取りは外部プロセスに行わせていて、C-d を検 + 出したらファイルに書き込んでシグナルを送信する仕組みになっている。 + + - tty に文字を挿入する事ができれば decode の枠組みに自然にイベントを組み + 入れる事ができるが、実際の所 tty に文字を外部から挿入する事はできない。 + シグナルを + + - FIFO か何かを使って通信するというのはよくある方法だが、現在の実装では + visible-bell を実行する度に新しくプロセスを立ち上げているので、pipe を + 沢山管理しなければならないので非効率的である。 + + - ファイルを使って処理をするという手が考えられる。bash-3.0 C-d でやってい + る様にファイルに書き込んでからシグナルで通知する。然し、複数のプロセス + が走っている場合には出力が混ざりあった時に問題が発生する。mkdir 等を使っ + て同期するという手も考えられなくはないが益々処理が重くなってしまう。 + + プロセスごとにファイルを作って処理するという手も考えられる。そして、読 + み取り用のプロセスは一つに絞る事にする。というか実は親プロセスで読み取 + りを実行すれば良いだけの気もする。ファイル書き込み中の同期に関しては、 + 現在既に visible-bell でやっている様に複数の状態通知様ファイルを作って + ファイルが空かどうかで判定する様にすれば良い。 + + b そもそも別のプロセスを作る必要があるだろうか。全て親シェルで実行すれば良 + いのではないだろうか。折に触れて状態をチェックしつつ sleep して時間が来た + ら親シェルが書き換え・消去を行う。 + + 然し、この方法の問題点は Bash 3.0 である。read -t 0 がないので、ユーザー + 入力が来た事の判定ができない。ユーザー入力があると想定してすぐ抜ける様に + していると、実際にユーザー入力がなかった時に bind -x による制御が戻ってこ + ないので、次にユーザー入力があるまで vbell の処理をする事ができなくなって + しまう。ユーザー入力がないと想定して処理を続けると、vbell が表示されてい + る間ユーザー入力が処理できなくなって固まった様になってしまう。 + + そうするとやはり別プロセスに任せてそれをシグナルで処理するという事になる + のだろうか。実際の所、シグナルハンドラーの中での処理は色々と怪しい事が起 + こるのでやりたくない。 + + 複数のサブシェルとメッセージをやり取りする様な一般的な枠組みを整えるのも + 手なのかもしれないと思う。 + + c 取り敢えず今まで通り sc..rc が自由に使える前提で処理する + + 今まで問題が起こっていなかったのは SC したまま放置される様な状況がなかっ + たからである。その為いつでも SC...RC を気兼ねなく用いる事ができて親シェル + の _ble_canvas_{x,y} の状態に依存せずに実装する事ができていた。本当の所、 + タイミングが悪ければ SC...RC が overlap して描画が乱れる可能性は 0 ではな + いが確率的にはとても小さい筈。というのもシーケンスの書き出しは buffer に + 貯めてできるだけ atomic に行っているので。 + + 実は現在の所は SC/RC によって bottom-dock を実現しているとは言え、カーソ + ルを bottom-dock に放置する様な事はしていない。なので、visible-bell の書 + き換えを行う時には常に SC..RC は閉じていると想定して良いのではないか。 + + 取り敢えず現在は c の方針で回避する事にする。 + 2021-02-22 * prompt: status line が最初の起動時に表示されていない [#D1492] diff --git a/src/util.sh b/src/util.sh index 1d8a20fc..5866a6f3 100644 --- a/src/util.sh +++ b/src/util.sh @@ -4234,18 +4234,18 @@ function ble/term/visible-bell:canvas/show { local y=${_ble_term_visible_bell_prev[5]} local -a DRAW_BUFF=() - [[ $_ble_attached ]] && + [[ :$opts: != *:update:* && $_ble_attached ]] && # WA #D1495 [[ $_ble_term_ri || :$opts: != *:erased:* && :$opts: != *:update:* ]] && ble/canvas/panel/ensure-tmargin.draw if [[ $_ble_term_rc ]]; then local ret= - [[ $_ble_attached ]] && ble/canvas/panel/save-position goto-top-dock + [[ :$opts: != *:update:* && $_ble_attached ]] && ble/canvas/panel/save-position goto-top-dock # WA #D1495 ble/canvas/put.draw "$_ble_term_ri_or_cuu1$_ble_term_sc$_ble_term_sgr0" ble/canvas/put-cup.draw $((y0+1)) $((x0+1)) ble/canvas/put.draw "$sgr$message$_ble_term_sgr0" ble/canvas/put.draw "$_ble_term_rc" ble/canvas/put-cud.draw 1 - [[ $_ble_attached ]] && ble/canvas/panel/load-position.draw "$ret" + [[ :$opts: != *:update:* && $_ble_attached ]] && ble/canvas/panel/load-position.draw "$ret" # WA #D1495 else ble/canvas/put.draw "$_ble_term_ri_or_cuu1$_ble_term_sgr0" ble/canvas/put-hpa.draw $((1+x0)) @@ -4269,7 +4269,7 @@ function ble/term/visible-bell:canvas/clear { local -a DRAW_BUFF=() if [[ $_ble_term_rc ]]; then local ret= - [[ $_ble_attached ]] && ble/canvas/panel/save-position goto-top-dock + #[[ $_ble_attached ]] && ble/canvas/panel/save-position goto-top-dock # WA #D1495 ble/canvas/put.draw "$_ble_term_sc$_ble_term_sgr0" ble/canvas/put-cup.draw $((y0+1)) $((x0+1)) ble/canvas/put.draw "$sgr" @@ -4277,7 +4277,7 @@ function ble/term/visible-bell:canvas/clear { #ble/canvas/put-ech.draw "$x" #ble/canvas/put.draw "$_ble_term_el" ble/canvas/put.draw "$_ble_term_sgr0$_ble_term_rc" - [[ $_ble_attached ]] && ble/canvas/panel/load-position.draw "$ret" + #[[ $_ble_attached ]] && ble/canvas/panel/load-position.draw "$ret" # WA #D1495 else : # 親プロセスの _ble_canvas_x が分からないので座標がずれる # ble/util/buffer.flush >&2