diff --git a/ble.pp b/ble.pp index c5e39615..4f5c484f 100644 --- a/ble.pp +++ b/ble.pp @@ -2278,9 +2278,10 @@ function ble/base/unload-for-reload { [[ $_ble_edit_detach_flag ]] || _ble_edit_detach_flag=reload fi - ble/base/unload + ble/base/unload reload return 0 } +## @fn ble/base/unload [opts] function ble/base/unload { ble/util/is-running-in-subshell && return 1 local IFS=$_ble_term_IFS @@ -2291,7 +2292,7 @@ function ble/base/unload { blehook/invoke unload ble/decode/keymap#unload ble-edit/bind/clear-keymap-definition-loader - ble/builtin/trap/finalize + ble/builtin/trap/finalize "$1" ble/util/import/finalize ble/fd#finalize ble/base/clean-up-runtime-directory finalize diff --git a/contrib b/contrib index bfc1670e..306c165d 160000 --- a/contrib +++ b/contrib @@ -1 +1 @@ -Subproject commit bfc1670e9ca473af6db1eb7b5ccabda44dd896e5 +Subproject commit 306c165dd93fb36dd6ebbf7af2ffd5990dd16dcf diff --git a/docs/ChangeLog.md b/docs/ChangeLog.md index 012e148d..35df4329 100644 --- a/docs/ChangeLog.md +++ b/docs/ChangeLog.md @@ -577,13 +577,15 @@ - global: avoid directly using `/dev/tty` `#D1986` a835b83 - util: add `ble/util/message` `#D2001` 2a524f34 - global: normalize bracket expressions to `_a-zA-Z` / `_a-zA-Z0-9` `#D2006` 41faa494 -- global: fix leak variables `#D2018` xxxxxxxx +- global: fix leak variables `#D2018` 6f5604de +- edit: handle nested WINCH properly `#D2020` xxxxxxxx ## Contrib - prompt-git: detect staged changes `#D1718` 2b48e31 - prompt-git: fix a bug that information is not updated on reload `#D1732` 361e9c5 - config/execmark: show exit status in a separate line `#D1828` 4d24f84 + - config/execmark: add names of exit statuses `#D2019` xxxxxxxx - prompt-git: ignore untracked files in submodules `#D1829` 4d24f84 - integration/fzf - fzf-completion: fix integration (reported by ferdinandyb) `#D1837` 12c022b diff --git a/make_command.sh b/make_command.sh index 041d03b8..207c1a83 100755 --- a/make_command.sh +++ b/make_command.sh @@ -1297,7 +1297,10 @@ function sub:scan/eval-literal { function sub:scan/WA-localvar_inherit { echo "--- $FUNCNAME ---" - grc 'local [^;&|()]*"\$\{[_a-zA-Z0-9]+\[@*\]\}"' + grc 'local [^;&|()]*"\$\{[_a-zA-Z0-9]+\[@*\]\}"' | + sed -E 'h;s/'"$_make_rex_escseq"'//g;s/^[^:]*:[0-9]+:[[:space:]]*// + \Ztest_command='\''ble/bin/stty -echo -nl -icrnl -icanon "\$\{_ble_term_stty_flags_enter\[@]}" size'\''Zd + g' } function sub:scan/mistake-_ble_bash { @@ -1461,6 +1464,7 @@ function sub:scan { \Z_ble_trap_handler="trap -- '\''\$\{_ble_trap_handler//\$q/\$Q}'\'' \$nZd \Zline = "bind"Zd \Ztrap_command=["'\'']trap -- Zd + \Z_ble_builtin_trap_handlers_reload\[sig\]="trap -- Zd \Zlocal trap$Zd \Z"trap -- '\''"Zd \Z\('\'' trap '\''\*Zd diff --git a/note.txt b/note.txt index 7b8554b6..519db2c5 100644 --- a/note.txt +++ b/note.txt @@ -2982,9 +2982,6 @@ bash_tips 2021-10-26 - * ble/builtin/read: WINCH を受信できていない気がする。 - もしかすると subshell の中では受信できないという事なのかもしれない。 - * winch: Window サイズを変化した時に menu の座標計算がずれる (menu_style=dense)そもそも resize した時点で menu の再配置を実行しなければ ならない筈である。 @@ -6730,9 +6727,169 @@ bash_tips Done (実装ログ) ------------------------------------------------------------------------------- +2023-03-14 + + * 2021-10-26 ble/builtin/read: WINCH を受信できていない気がする [#D2022] + もしかすると subshell の中では受信できないという事なのかもしれない。 + + 2023-03-14 winsize を更新する関数を作ったのでこれにも対応する事にする。 + + % と思ったが WINCH を受信できていない? 問題は WINCH を受信しても LINES + % COLUMNS が更新されない事と思ったが、そもそも WINCH を受信できていないという + % 事なのだった。 + % →即時 WINCH を受信できる訳では無いがユーザーが文字を入力した時にちゃんと + % 受信できている。 + + subshell の中で実行するとちゃんと内部で設定した trap が発火している様に見える。 + + * fixed: ble/builtin/read/TRAPWINCH でも update-winsize を呼ぶ事にした。と + 思ったが 個別に色々処理するよりも単にここで ble/application/onwinch を呼 + び出してしまうのが自然である→その様に修正した。 + + x fixed: "bash: ble/term/visible-bell:/clear: そのようなファイルやディレク + トリはありません" というエラーが発生する。/clear は + ble/term/visible-bell/.erase-previous-visible-bell から呼び出されるが、こ + の関数は $_ble_base_run/$$.visible-bell.* に属している物を全て削除しよう + とする。なので subshell で設定された物も削除しようとする。 + + この時親 shell で一度も visible-bell を使っていないと visible-bell が初期 + 化されていない状態になっていて問題が生じる。 + + 或いは subshell で発生した visible-bell は subshell だけで管理する事にし + て subshell を抜ける時に始末する事にする? subshell というか read を抜ける + 時に処理すれば良い → read を終了する時に visible-bell/erase を呼び出して + 消去する事にした。C-c を押した時には結局中断して駄目なのでは? と思って試 + してみたが C-c の時にもちゃんとその場で visible-bell/erase が呼び出されて + いる様なので、C-c もちゃんと ble.sh の上で処理されているという事なのだろ + う。 + + 実際に read -ep でも WINCH もちゃんと発火している様に見える。LINES, COLUMNS + も更新されている。それなのに textmap が更新されていない様な気がする → と思っ + たが textmap を更新した後に出力して確認していたので更新されていない様に見え + ただけだった。ちゃんと更新されていて新しい端末幅を反映した値になっている。 + ずれて見えたのは単に端末の折り返しによって行が増えている事による物だった。 + + ? reject: redraw-here がちゃんと働いていない様な気がする? と思ったがそもそ + も幅が縮まった時には、縦に内容がはみ出てしまってその分まで遡ろうとはしな + いので、現在見えている振る舞いが元々意図した物である気がする。なので気に + しない。 + + * fixed: サイズの変更があった後に read を中断すると親のプロンプトが表示され + てから [EOF] 等のマーカーが表示される。何故? + + うーん。read -ep ; read -ep をコマンドから実行すると一つ目の read と二つ + 目の read の間で既にプロンプトを表示しようとしている。SIGWINCH が走ってそ + れで再描画が起こっている? + + ble-edit/attach/TRAPWINCH ではちゃんと _ble_term_state を確認しているのに + 何故かそれをすりぬけて表示が実行されている。_ble_term_state が一時的に + internal になっている様に見える。 + + と思ったら分かった気がする。ble/builtin/read/.impl の中で一旦 + ble/term/enter してその後で ble/term/leave している。この ble/term/leave + するよりも前に WINCH が走って其処で internal 状態にあると勘違いしてプロン + プトが表示されてしまうということの気がする。何故 subshell の中で実行しな + いのかというと C-c やその他の事故で subshell が予期せず終了した時に状態の + 復元に失敗しない為だろうという気がする。 + + →これは ble/application/onwinch を呼び出す時の条件を増やして対処する事に + した。 + +2023-03-13 + + * trap: winch の様々な問題 [#D2021] + + * fixed: bash-4.3..5.0 で ble-reload 後に WINCH が効かない + + 一方で Cygwin の bash-4.4 で ble-reload した後に WINCH が正しく処理されな + くなっている。chatoyancy 上では bash-5.2 も 4.4 もちゃんと動いている。 + + builtin trap WINCH 自体が発火していない様だ。一方でウィンドウサイズを変更 + した後は謎の PS1 への代入ジョブ (終了ステータス 127) が表示される。而も、 + その PS1 に代入される値は現在の値とは関係ない。 + + うーん。chatoyancy でも 4.4 で再現した。histdb を無効にした状態で reload + すると動かなくなる。bash-5.2 では問題になっていない。5.1 でも OK。5.0, + 4.3 は駄目。bash-4.2 はちゃんと動いている。つまり 4.3,4.4,5.0 の問題。何 + 故 reload だと駄目なのだろうか。 + + 詳しく調べてみると ble-detach してから ble-attach すると再び動く様になる。 + これは要するに rl winch hook のインストールが関係しているという事ではない + か? 確認してみると実際に winch が再設定されている。既存の trap を確認し + てみると、空になっている。つまり unload の時にクリアされているという事。 + + unload-for-reload から呼び出している時には WINCH を削除しない事にした。動 + く様になった。因みに INT についても同様の処理はしなくて良いのか? と思った + が取り敢えずは問題は起こっていない気がするので気にしないことにする。現在 + は WINCH だけ特別扱いする。 + + x この実装だと元々存在していた user WINCH trap が消えてしまうのではないか。 + →実際に確かめてみたら消滅する。別の変数に記録しておく事にした。別の変 + 数に記録しておいた物を拾う処理をする為に、今まで内部 trap を install 済 + みの時に単に return 0 していたのを trap_string, trap_command を空にして + 処理を続ける事にした。取り敢えず動いている。 + + ? ok: bashrc で ble-attach しても WINCH はちゃんと有効なのか? bash-4.3 以外 + は大丈夫。 + + * ok: bash-4.3 で WINCH が即時発火しない問題 + + 逆に bash-4.3 は最初から ble-attach しても prompt attach しても WINCH が + 全然発火していない。というか 4.3 は --norc で起動して WINCH に trap した + としても WINCH が発火しない。次にユーザーが入力を試みた時に初めて発火して + いる。逆に言えば 4.3 では入力を開始すれば何れにしても正しい幅で描画される。 + + これは取り敢えず入力を開始さえすれば直るので取り敢えずは気にしない。 + + * fixed: bash-5.2 でコマンド実行中にサイズ変更が発生した時に反映されない問題 + + うーん。全てのコマンドを実行する度にサイズ再取得を実行する必要があるか? + 或いは idle で処理する必要があるかもしれない。 + + できるだけ高速に判定する方法が欲しい。複数のコマンドで速度を比較する? + + stty size, resize, tput lines cols, bash -c + + 試してみた所、tput が最も速く、その次が stty、更に resize が来て bash -c + による方法が最も遅かった。一方で、stty size は ble/term/stty/enter で呼び + 出している stty とくっつけることができる。取り敢えず優先順位として stty, + tput, resize, bash の順に試し、stty による実装が使える場合には + ble/term/stty/enter の stty 呼び出しを修正する方法も考慮に入れる事にした。 + + 取り敢えず実装した。動いている。 + + * edit: WINCH で拡大した時のサイズの変わり方が変だ [#D2020] + + 調べてみると onwinch が入れ子で呼び出されている。SINGWINCH の処理が入れ子に + なっている。bash 自体は入れ子にはしていないが、read-timeout が WINCH 発火を + 遅延していて、read-timeout の中から主導で呼び出した WINCH の中で、更に trap + WINCH が発火している様だ。 + + 一方で、ble/application/onwinch の実装を見ると入れ子で呼び出した時の対策は + ちゃんとしてある様に見える。 + + うーん。ble/application/onwinch の中では何れにしても一切の更新処理は実行し + たくない。ble/application/onwinch を抜ける時に改めて処理を行いたい。 + + ? 今の実装だと _ble_decode_hook_Processing=body|prologue の時に winch を受 + け取ると後の ble/application/render の際に無駄に二回描画される気がする。 + どうせ onwinch の中で ble/application/render が発生するのだから、直接 + ble/application/render を呼び出せば良いのではないか。 + + 取り敢えず onwinch 全体を WINCH の抑制対象として onwinch の末尾でも WINCH + の発火が途中であった時に onwinch を呼び出す様にした。ble/application/render + の前に onwinch があった時には ble/application/render をせずに最初から + onwinch をする様にした。実装した。動いている。前よりも素早い動作になった。 + + * execmark: wrong usage (2), command_not_found (127) 等の文字列 [#D2019] + https://qiita.com/Linda_pp/items/1104d2d9a263b60e104b に面白い記述がある + + /usr/include/sysexits.h に幾らか値が定義されている様だ。EX_USAGE..EX_CONFIG + が 64..78 に定義されている。 + 2023-03-12 - * ret が leak する様になっている [#D2018] + * global: ret が leak する様になっている [#D2018] だいぶ遡ってもずっと leak している。何故だろうか。取り敢えず最新版で修正した。 diff --git a/src/edit.sh b/src/edit.sh index e1936f11..cb80521a 100644 --- a/src/edit.sh +++ b/src/edit.sh @@ -258,7 +258,6 @@ bleopt/declare -v line_limit_type none _ble_app_render_mode=panel _ble_app_winsize=() -_ble_app_render_Processing= function ble/application/.set-up-render-mode { [[ $1 == "$_ble_app_render_mode" ]] && return 0 case $1 in @@ -285,7 +284,20 @@ function ble/application/pop-render-mode { ble/array#shift _ble_app_render_mode } function ble/application/render { - local _ble_app_render_Processing=1 + # 既に未処理の winch がある場合には初めから ble/application/onwinch + # 経由で再描画を行う。何れにせよ ble/application/onwinch から改めて + # ble/application/render が呼び出されるので onwinch 後は直ぐに抜けて + # 良い。 + # + # Note: この文脈でも更に ble/application/onwinch が遅延される場合は、 + # 更に外側の何処かで最終的に ble/application/onwinch が呼び出される + # 手筈になっているので問題ない。 + if [[ $_ble_app_onwinch_Deferred ]]; then + ble/application/onwinch + return "$?" + fi + + local _ble_app_onwinch_Suppress=1 { local render=$_ble_app_render_mode case $render in @@ -299,9 +311,9 @@ function ble/application/render { _ble_app_winsize=("$COLUMNS" "$LINES") ble/util/buffer.flush >&2 } - ble/util/unlocal _ble_app_render_Processing - if [[ $_ble_application_render_winch ]]; then - _ble_application_render_winch= + ble/util/unlocal _ble_app_onwinch_Suppress + + if [[ $_ble_app_onwinch_Deferred ]]; then ble/application/onwinch fi } @@ -356,35 +368,38 @@ function ble/application/onwinch/panel.process-redraw-here { return 0 } +_ble_app_onwinch_Suppress= +_ble_app_onwinch_Deferred= function ble/application/onwinch { - if [[ $_ble_app_render_Processing || $_ble_decode_hook_Processing == body || $_ble_decode_hook_Processing == prologue ]]; then - # Note #D1762: 別の処理が走っている途中に描画更新すると中途半端な - # データに対して処理が実行されてデータが破壊されるので後で処理する。 + if [[ $_ble_app_onwinch_Suppress || $_ble_decode_hook_Processing == body || $_ble_decode_hook_Processing == prologue ]]; then + # Note #D1762: 別の処理が走っている途中に描画更新すると中途半端なデータに対 + # して処理が実行されてデータが破壊されるので後で処理する。 # - # ble_decode_hook_body=1 の時は EPILOGUE が後で必ず呼び出されるの - # でその時に ble/application/render が呼び出される。その中で - # _ble_application_render_winch がチェックされて改めてこの関数が呼 - # び出される。_ble_app_render_Processing=1 の時には、 - # ble/application/render の末尾でやはりチェックが走ると期待する。 - _ble_application_render_winch=1 + # ble_decode_hook_body=1 の時は EPILOGUE が後で必ず呼び出されるのでその時に + # ble/application/render が呼び出される。その中で_ble_app_onwinch_Deferred + # がチェックされて改めてこの関数が呼び出される。_ble_app_onwinch_Suppress=1 + # の時には、ble/application/render の末尾でやはりチェックが走ると期待する。 + _ble_app_onwinch_Deferred=1 return 0 fi - _ble_textmap_pos=() - # 処理中に届いた WINCH は失われる様だ。連続的サイズ変化を通知す - # る端末の場合、途中のサイズの WINCH の処理中に最終的なサイズの - # WINCH を逃して表示が乱れたままになる。対策として描画終了時に処 - # 理中にサイズ変化が起こっていないか確認する。 + local _ble_app_onwinch_Suppress=1 + _ble_app_onwinch_Deferred= + + _ble_textmap_cols= + # 処理中に届いた WINCH は失われる様だ。連続的サイズ変化を通知する端末の場合、 + # 途中のサイズの WINCH の処理中に最終的なサイズのWINCH を逃して表示が乱れたま + # まになる。対策として描画終了時に処理中にサイズ変化が起こっていないか確認す + # る。 local old_size= i for ((i=0;i<20;i++)); do - if ((50200<=_ble_bash&&_ble_bash<50300)); then - # Note: bash-5.2 では trap string / bind -x 内部で COLUMNS/LINES が更新さ - # れないので "$BASH" を起動して端末サイズを取得する。 - builtin eval -- "$(ble/util/msleep 50; exec "$BASH" -O checkwinsize -c '(:); [[ $COLUMNS && $LINES ]] && printf %s "COLUMNS=$COLUMNS LINES=$LINES"' 2>&"$_ble_util_fd_stderr")" - else - # 次の WINCH を待つと共にサブシェルで checkwinsize を誘発 - (ble/util/msleep 50) + # 次の WINCH を待つと共にサブシェルで checkwinsize を誘発。 + (ble/util/msleep 50) + # Bash 5.2 では trap string / bind -x 内部で COLUMNS/LINES が更新されないの + # で明示的に ble/term/update-winsize を呼び出す。 + if ble/util/is-running-in-subshell || ((50200<=_ble_bash&&_ble_bash<50300)); then + ble/term/update-winsize fi # trap 中だと bash のバグでジョブが溜まるので逐次捌く @@ -393,36 +408,37 @@ function ble/application/onwinch { [[ $size == "$old_size" ]] && break old_size=$size - local _ble_app_render_Processing=1 - { - local render=$_ble_app_render_mode - case $render in - (panel) - case $bleopt_canvas_winch_action in - (clear) - # 全消去して一番上から再描画 - _ble_prompt_trim_opwd= - ble/util/buffer "$_ble_term_clear" ;; - (redraw-here) - ble/application/onwinch/panel.process-redraw-here ;; - (redraw-prev) - # 前回の開始相対位置が変化していないと仮定して戻って再描画 - local -a DRAW_BUFF=() - ble/canvas/panel#goto.draw 0 0 0 - ble/canvas/bflush.draw ;; - (redraw-safe) ;; - esac - # 高さの再確保も含めて。 - ble/canvas/panel/invalidate height ;; - - (forms:*) - ble/forms/invalidate "${render#*:}" ;; # NYI + local render=$_ble_app_render_mode + case $render in + (panel) + case $bleopt_canvas_winch_action in + (clear) + # 全消去して一番上から再描画 + _ble_prompt_trim_opwd= + ble/util/buffer "$_ble_term_clear" ;; + (redraw-here) + ble/application/onwinch/panel.process-redraw-here ;; + (redraw-prev) + # 前回の開始相対位置が変化していないと仮定して戻って再描画 + local -a DRAW_BUFF=() + ble/canvas/panel#goto.draw 0 0 0 + ble/canvas/bflush.draw ;; + (redraw-safe) ;; esac - } - ble/util/unlocal _ble_app_render_Processing + # 高さの再確保も含めて。 + ble/canvas/panel/invalidate height ;; + + (forms:*) + ble/forms/invalidate "${render#*:}" ;; # NYI + esac ble/application/render done + ble/util/unlocal _ble_app_onwinch_Suppress + + if [[ $_ble_app_onwinch_Deferred ]]; then + ble/application/onwinch + fi } # canvas.sh 設定 @@ -2631,7 +2647,9 @@ bleopt/declare -n canvas_winch_action redraw-here function ble-edit/attach/TRAPWINCH { # 現在前面に出ていなければ関係ない - ((_ble_edit_attached)) && [[ $_ble_term_state == internal ]] || return 0 + ((_ble_edit_attached)) && [[ $_ble_term_state == internal ]] && + ! ble/edit/is-command-layout && ! ble/util/is-running-in-subshell || + return 0 ble/application/onwinch 2>&"$_ble_util_fd_stderr" } @@ -9560,9 +9578,7 @@ function ble/builtin/read/.set-up-textarea { } function ble/builtin/read/TRAPWINCH { local IFS=$_ble_term_IFS - _ble_textmap_pos=() - ble/util/buffer "$_ble_term_ed" - ble/textarea#redraw + ble/application/onwinch } function ble/builtin/read/.loop { # この関数はサブシェルの中で実行される事を前提としている。 @@ -9671,6 +9687,8 @@ function ble/builtin/read/.loop { fi ble/util/buffer.flush >&2 + ble/term/visible-bell/erase + if ((_ble_edit_read_accept==1)); then local q=\' Q="'\''" printf %s "__ble_input='${_ble_edit_read_result//$q/$Q}'" diff --git a/src/util.hook.sh b/src/util.hook.sh index c9f4b53e..a8f6e097 100644 --- a/src/util.hook.sh +++ b/src/util.hook.sh @@ -581,11 +581,28 @@ function ble/builtin/trap/user-handler/is-internal { } function ble/builtin/trap/finalize { - local sig + _ble_builtin_trap_handlers_reload=() + + local sig unload_opts=$1 for sig in "${!_ble_builtin_trap_sig_opts[@]}"; do local name=${_ble_builtin_trap_sig_name[sig]} local opts=${_ble_builtin_trap_sig_opts[sig]} [[ $name && :$opts: == *:override-builtin-signal:* ]] || continue + + # Note (#D2021): reload の為に一旦設定を復元する時は readline によ + # る WINCH trap を破壊しない様に WINCH だけはそのままにして置く。 + # 元々のユーザートラップは _ble_builtin_trap_handlers_reload に記 + # 録し、後の ble/builtin/trap/install-hook で読み取る。 + if [[ :$opts: == *:readline:* && :$unload_opts: == *:reload:* ]]; then + if local _ble_trap_handler; ble/builtin/trap/user-handler#load "$sig"; then + local q=\' Q="'\''" + _ble_builtin_trap_handlers_reload[sig]="trap -- '${_ble_trap_handler//$q/$Q}' $name" + else + _ble_builtin_trap_handlers_reload[sig]= + fi + continue + fi + if local _ble_trap_handler; ble/builtin/trap/user-handler#load "$sig"; then builtin trap -- "$_ble_trap_handler" "$name" else @@ -1040,10 +1057,13 @@ function ble/builtin/trap/install-hook { # - INT は bind -x 内だと改めて設定しないと有効にならない(?)様なの # で既に登録されていても、builtin trap は省略できない。 # - [[ $trap_command == "$trap_string" ]] && return 0 + [[ $trap_command == "$trap_string" ]] && trap_command= trap_string= + + # Note (#D2021): reload 時に元の trap が保存されていればそれを読み取る。 + [[ $trap_string ]] || trap_string=${_ble_builtin_trap_handlers_reload[sig]-} fi - [[ :$opts: == *:inactive:* && ! $trap_string ]] || + [[ ! $trap_command || :$opts: == *:inactive:* && ! $trap_string ]] || builtin eval "builtin $trap_command"; local ext=$? local q=\' diff --git a/src/util.sh b/src/util.sh index 3392e2b5..8bd7d094 100644 --- a/src/util.sh +++ b/src/util.sh @@ -5759,6 +5759,132 @@ function ble/term/stty/TRAPEXIT { "${_ble_term_stty_flags_leave[@]}" } +function ble/term/update-winsize { + # (0) checkwinsize による実装 (2167.054 usec/eval) + if ((_ble_bash<50200||50300<=_ble_bash)); then + function ble/term/update-winsize { + if shopt -q checkwinsize; then + (:) + else + shopt -s checkwinsize + (:) + shopt -u checkwinsize + fi 2>&"$_ble_util_fd_stderr" + } + ble/term/update-winsize + return 0 + fi + + local ret + + # (a) "tput lines cols" または "tput li co" による実装 (2909.052 usec/eval) + if ble/bin/.freeze-utility-path tput; then + if ble/util/assign-words ret 'ble/bin/tput lines cols' 2>/dev/null && + [[ ${#ret[@]} -eq 2 && ${ret[0]} =~ ^[0-9]+$ && ${ret[1]} =~ ^[0-9]+$ ]] + then + LINES=${ret[0]} COLUMNS=${ret[1]} + function ble/term/update-winsize { + local -x ret LINES= COLUMNS= + ble/util/assign-words ret 'ble/bin/tput lines cols' 2>/dev/null + ble/util/unlocal LINES COLUMNS + [[ ${ret[0]} ]] && LINES=${ret[0]} + [[ ${ret[1]} ]] && COLUMNS=${ret[1]} + } + return 0 + elif ble/util/assign-words ret 'ble/bin/tput li co' 2>/dev/null && + [[ ${#ret[@]} -eq 2 && ${ret[0]} =~ ^[0-9]+$ && ${ret[1]} =~ ^[0-9]+$ ]] + then + LINES=${ret[0]} COLUMNS=${ret[1]} + function ble/term/update-winsize { + local -x ret LINES= COLUMNS= + ble/util/assign-words ret 'ble/bin/tput li co' 2>/dev/null + ble/util/unlocal LINES COLUMNS + [[ ${ret[0]} ]] && LINES=${ret[0]} + [[ ${ret[1]} ]] && COLUMNS=${ret[1]} + } + return 0 + fi + fi + + # (b) "stty size" による実装 (2976.172 usec/eval) + if ble/util/assign-words ret 'ble/bin/stty size' 2>/dev/null && + [[ ${#ret[@]} -eq 2 && ${ret[0]} =~ ^[0-9]+$ && ${ret[1]} =~ ^[0-9]+$ ]] + then + LINES=${ret[0]} COLUMNS=${ret[1]} + function ble/term/update-winsize { + local ret + ble/util/assign-words ret 'ble/bin/stty size' 2>/dev/null + [[ ${ret[0]} ]] && LINES=${ret[0]} + [[ ${ret[1]} ]] && COLUMNS=${ret[1]} + } + return 0 + fi + + # (c) "resize" による実装 (3108.696 usec/eval) + if ble/bin/.freeze-utility-path resize && + ble/util/assign ret 'ble/bin/resize' && + ble/string#match "$ret" 'COLUMNS=([0-9]+).*LINES=([0-9]+)' + then + LINES=${BASH_REMATCH[2]} COLUMNS=${BASH_REMATCH[1]} + function ble/term/update-winsize { + local ret + ble/util/assign ret 'ble/bin/resize' 2>/dev/null + ble/string#match ret 'COLUMNS=([0-9]+).*LINES=([0-9]+)' + [[ ${BASH_REMATCH[2]} ]] && LINES=${BASH_REMATCH[2]} + [[ ${BASH_REMATCH[1]} ]] && COLUMNS=${BASH_REMATCH[1]} + } + return 0 + fi + + # (d) "bash -O checkwinsize -c ..." による実装 (bash-4.3 以上) (9094.595 usec/eval) + function ble/term/update-winsize { + local ret script='LINES= COLUMNS=; (:); [[ $COLUMNS && $LINES ]] && builtin echo "$LINES $COLUMNS"' + ble/util/assign-words ret '"$BASH" -O checkwinsize -c "$script"' 2>&"$_ble_util_fd_stderr" + [[ ${ret[0]} ]] && LINES=${ret[0]} + [[ ${ret[1]} ]] && COLUMNS=${ret[1]} + } + ble/term/update-winsize + return 0 +} + +# bash-5.2 では "bind -x" 内部で checkwinsize が動作しないので +# ble/term/stty/enter に於いて自前で端末サイズを取得して LINES COLUMNS を更新す +# る。 +if ((50200<=_ble_bash&&_ble_bash<50300)); then + ## @fn ble/term/update-winsize/.stty-enter.advice + ## ble/term/stty/enter の実装を "stty size" を用いて調節します。 + ## + ## 最初の ble/term/stty/enter の呼び出し時に'stty "${enter_options[@]}" + ## size' が動くか検査し、使えそうならば今後はstty に size を追加して呼び出 + ## してそれを元にして LINES, COLUMNS を再設定する様にする。 + ## + ## テスト自体が stty の設定を変更するので、初回の ble/term/stty/enter の呼 + ## び出しの時にテストも含めて調整を実行することにしている。 + function ble/term/update-winsize/.stty-enter.advice { + local ret stderr test_command='ble/bin/stty -echo -nl -icrnl -icanon "${_ble_term_stty_flags_enter[@]}" size' + if ble/util/assign stderr 'ble/util/assign-words ret "$test_command" 2>&1' && + [[ ! $stderr ]] && + ((${#ret[@]}==2)) && + [[ ${ret[0]} =~ ^[0-9]+$ && ${ret[1]} =~ ^[0-9]+$ ]] + then + LINES=${ret[0]} COLUMNS=${ret[1]} + function ble/term/stty/enter { + [[ $_ble_term_stty_state ]] && return 0 + local ret + ble/util/assign-words ret 'ble/bin/stty -echo -nl -icrnl -icanon "${_ble_term_stty_flags_enter[@]}" size' + [[ ${ret[0]} =~ ^[0-9]+$ ]] && LINES=${ret[0]} + [[ ${ret[1]} =~ ^[0-9]+$ ]] && COLUMNS=${ret[1]} + _ble_term_stty_state=1 + } + else + ble/term/update-winsize + ble/function#advice before ble/term/stty/enter ble/term/update-winsize + fi + builtin unset -f "$FUNCNAME" + } + ble/function#advice before ble/term/stty/enter ble/term/update-winsize/.stty-enter.advice +fi + #---- cursor state ------------------------------------------------------------