Skip to content

Commit

Permalink
util (ble/util/is-stdin-ready): check "$_ble_util_fd_tui_stdin" by de…
Browse files Browse the repository at this point in the history
…fault
  • Loading branch information
akinomyoga committed Aug 22, 2024
1 parent 0e8c388 commit 29c00fd
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 27 deletions.
2 changes: 1 addition & 1 deletion contrib
1 change: 1 addition & 0 deletions docs/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@
- util (`ble/util/buffer.flush`): write to the TUI stderr `#D2218` b5c88947
- util (`ble/util/buffer.flush`): use <kbd>DECSET(2026)</kbd> in terminals with the support `#D2226` c3df08be
- main: refactor initialization sequence `#D2231` cc9d7f39
- util (`ble/util/is-stdin-ready`): check `$_ble_util_fd_tui_stdin` by default `#D2254` xxxxxxxx

<!---------------------------------------------------------------------------->
# ble-0.4.0-devel3
Expand Down
14 changes: 7 additions & 7 deletions lib/core-complete.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1690,7 +1690,7 @@ function ble/complete/action/quote-insert.batch/proc {
local fname_cands=$_ble_local_tmpfile
ble/util/conditional-sync \
'ble/complete/action/quote-insert.batch/awk < "$fname_cands"' \
'! ble/complete/check-cancel <&"$_ble_util_fd_tui_stdin"' '' progressive-weight
'! ble/complete/check-cancel' '' progressive-weight
local ext=$?

ble/util/assign/rmtmp
Expand Down Expand Up @@ -2818,7 +2818,7 @@ function ble/complete/util/eval-pathname-expansion {

local def
ble/util/assign def 'ble/util/conditional-sync "$sync_command" "" "" "$sync_opts"' &>/dev/null; local ext=$?
if ((ext==148)) || ble/complete/check-cancel <&"$_ble_util_fd_tui_stdin"; then
if ((ext==148)) || ble/complete/check-cancel; then
ble/util/invoke-hook dtor
return 148
fi
Expand Down Expand Up @@ -3597,7 +3597,7 @@ function ble/complete/progcomp/compopt {
function ble/complete/progcomp/.check-limits {
# user-input check
((cand_iloop++%bleopt_complete_polling_cycle==0)) &&
[[ ! -t 0 ]] && ble/complete/check-cancel <&"$_ble_util_fd_tui_stdin" &&
[[ ! -t 0 ]] && ble/complete/check-cancel &&
return 148
ble/complete/source/test-limit "$((progcomp_read_count++))"
return "$?"
Expand All @@ -3619,7 +3619,7 @@ function ble/complete/progcomp/.compgen-helper-func {
if [[ " ${FUNCNAME[*]} " == *" ble/complete/progcomp/.compgen "* ]]; then
local -a args; args=("$@")
ble/util/conditional-sync "exec ssh \"\${args[@]}\"" \
"! ble/complete/check-cancel <&$_ble_util_fd_tui_stdin" 128 progressive-weight:killall
'\''! ble/complete/check-cancel'\'' 128 progressive-weight:killall
else
ble/function#push/call-top "$@"
fi'
Expand Down Expand Up @@ -4091,7 +4091,7 @@ function ble/complete/progcomp/patch:bash-completion/_comp_cmd_make.advice {
local -a make_args; make_args=("${ADVICE_WORDS[1]}" "$@")
ble/util/conditional-sync \
'\''command "${make_args[@]}"'\'' \
"! ble/complete/check-cancel <&$_ble_util_fd_tui_stdin" 128 progressive-weight:killall'
'\''! ble/complete/check-cancel'\'' 128 progressive-weight:killall'
ble/function#advice/do
ble/function#pop "${ADVICE_WORDS[1]}"
else
Expand Down Expand Up @@ -4148,7 +4148,7 @@ function ble/complete/progcomp/patch:cobraV2/get_completion_results.invoke {
local -a invoke_args; invoke_args=("$@")
ble/util/conditional-sync \
"${orig_words[0]} \"\${invoke_args[@]}\"" \
"! ble/complete/check-cancel <&$_ble_util_fd_tui_stdin" 128 progressive-weight:killall
'! ble/complete/check-cancel' 128 progressive-weight:killall
}
## @fn ble/complete/progcomp/call-by-conditional-sync funcname
## This modifies the function to process its task in a subshell using
Expand All @@ -4164,7 +4164,7 @@ function ble/complete/progcomp/call-by-conditional-sync {
ble/function#advice around "$1" '
ble/util/conditional-sync \
ble/function#advice/do \
"! ble/complete/check-cancel <&$_ble_util_fd_tui_stdin" 128 progressive-weight:killall'
'\''! ble/complete/check-cancel'\'' 128 progressive-weight:killall'
}

## @fn ble/complete/progcomp/.compgen opts
Expand Down
12 changes: 6 additions & 6 deletions lib/test-util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1495,16 +1495,16 @@ function is-global { (builtin readonly "$1"; ! local "$1" 2>/dev/null); }
# ble/util/is-stdin-ready
if ((_ble_bash>=40000)); then
(
ble/test 'echo 1 | { sleep 0.01; ble/util/is-stdin-ready; }'
ble/test 'echo 1 | { sleep 0.01; ble/util/is-stdin-ready 0; }'
[[ ${CI-} == true && ${GITHUB_ACTION-} && $OSTYPE == msys* ]] ||
ble/test 'sleep 0.01 | ble/util/is-stdin-ready' exit=1
ble/test 'ble/util/is-stdin-ready <<< a'
ble/test 'ble/util/is-stdin-ready <<< ""'
ble/test 'sleep 0.01 | ble/util/is-stdin-ready 0' exit=1
ble/test 'ble/util/is-stdin-ready 0 <<< a'
ble/test 'ble/util/is-stdin-ready 0 <<< ""'

# EOF は成功してしまう? これは意図しない振る舞いである。
# しかし bash 自体が終了するので関係ないのかもしれない。
ble/test ': | { sleep 0.01; ble/util/is-stdin-ready; }'
ble/test 'ble/util/is-stdin-ready < /dev/null'
ble/test ': | { sleep 0.01; ble/util/is-stdin-ready 0; }'
ble/test 'ble/util/is-stdin-ready 0 < /dev/null'
)
fi

Expand Down
166 changes: 166 additions & 0 deletions note.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7394,6 +7394,172 @@ bash_tips

2024-08-22

* ble/util/is-stdin-ready で直接 _ble_util_fd_tui_stdin から読み取る? [#D2254]

うーん。或いは is-stdin-ready で常に tui から読み出す様に変更するべきだ
ろうか。

? "-u fd vs <&fd": redirection はコストが明らかにある。一方で引数解析に対し
てもコストはある気がするが、syscall よりは流石に軽いだろうと思いたい (或
いは malloc で syscall 迄行くという可能性もあるが)。うーん。これは後で
benchmark すれば良い。

うーん。計測してみた所普通に redirection した方が速い。では -u は何の為に
あるのだろうか。よく分からないが <&fd の形式を使う事にする。

? ble/util/is-stdin-ready を別の目的で使っている箇所はあるだろうか。つまり、
"現在の stdin" に入力があるかどうかを確認するのに使っている箇所。tes全ての現れる箇所について確認する。

* lib/test-* については気にしなくて良いだろう。と思ったが、テストの為に
stdin が置き換えられるという事を仮定している。うーん。これは
_ble_util_fd_tui_stdin を上書きする事で対処する事にした

% → やはり引数に fd を受け取る様に修正する事にした。何も指定しない時は
% _ble_util_fd_tui_stdin を使う。と思ったが、ble/util/is-stdin-ready の
% 第一引数は既に poll できない場合の既定の exit status として使われてい
% るのだった。

既存の ble/util/is-stdin-ready の引数は一箇所でしか使っていない。やはり、
引数の意味を変える事にする。

* ./lib/keymap.vi.sh:1195: if ((depth>=bleopt_keymap_vi_macro_depth)) || ble/util/is-stdin-ready; then
これは ble/widget/vi_nmap/play-register.hook の中で停止条件を定める物。

* ./src/decode.sh: 以下の関数の実装で ble/util/is-stdin-ready を使っている

ble/decode/wait-input

./src/decode.sh:1320: ble/decode/wait-input 5 char || ent=${ent%_}
./src/decode.sh:2146: ble/decode/wait-input "$timeout" || node_type=1

これらは ble-decode-char の処理で使っている。ユーザー入力の処理なので
基本的にやはり tui stdin で良い。

ble/decode/has-input-for-char
ble/decode/has-input
ble/decode/has-input-char

./lib/core-syntax.sh:1429: ble/decode/has-input && return 148

これは simple-word/eval によるチェックである。まあ、tui stdin を見
に行く動作で妥当だろう。

./src/decode.sh:866: ble/decode/has-input || ble-decode-key/batch/flush
./src/decode.sh:1191: if [[ ! $ble_decode_char_sync ]] && ble/decode/has-input-for-char; then
./src/decode.sh:2144: if (($#==0)) && ! ble/decode/has-input; then
./src/decode.sh:2194: if ! ble/decode/has-input || ((${#_ble_decode_key_batch[@]}>=50)); then
./src/decode.sh:2264: if ble/decode/has-input && builtin eval "[[ \${${dicthead}[_ble_decode_KCODE_BATCH_CHAR]-} ]]"; then

これは全てユーザー入力の処理関連なのでok

./src/edit.sh:7995: [[ $_ble_edit_str ]] && ble/decode/has-input &&

これは accept_line_threshold の為のチェック @
ble-edit/is-single-complete-line。これも tui stdin で良い。

./src/edit.sh:11310: if ble/decode/has-input && ! ble-edit/exec/has-pending-commands; then

これは ble-decode/EPILOGUE で描画をスキップする為の物。これもユーザー
入力の関係なので tui stdin で良い。

./src/history.sh:2219: if ((has_stop_check&&isearch_time%isearch_block==0)) && ble/decode/has-input; then
./src/history.sh:2270: ble/decode/has-input && return 148

これは履歴検索関係。これもまあ tui stdin で良いだろう。現在の所
ble.sh tui 以外から使う事がある様には思われない。

./src/util.sh:4450: local __ble_continue=${2:-'! ble/decode/has-input'}

これは ble/util/conditional-sync の既定の条件である。うーん。まあ、そ
の時の stdin を使いたい場合は ble/util/is-stdin-ready を使う筈で、
ble/decode/has-input を用いて decode 経由でアクセスしている時点で tui
stdin を介した確認になっている筈なので、これも tui stdin で良いだろう。
そういう意味で考えると ble/decode/has-input の呼び出し元をチェックす
る意味は余りなかったかもしれない。

./lib/core-complete.sh:94: ble/decode/has-input
./lib/core-complete.sh:1233: [[ :$comp_type: != *:sync:* ]] && ble/decode/has-input

これらは以下の関数の呼び出しである。

ble/complete/menu#check-cancel

/lib/core-complete.sh:206: ble/complete/menu#check-cancel && return 148
/lib/core-complete.sh:271: ble/complete/menu#check-cancel && return 148
/lib/core-complete.sh:338: ble/complete/menu#check-cancel && return 148
/lib/core-complete.sh:403: ble/complete/menu#check-cancel && return 148
/lib/core-complete.sh:492: ble/complete/menu#check-cancel && return 148
/lib/core-complete.sh:510: ble/complete/menu#check-cancel && return 148

ble/complete/menu-style:XXX/construct の処理の中断条件で使われてい
る。微妙だけれどやはり ble/decode 経由の時点で tui stdin で良いだろ
う。

ble/complete/check-cancel

これの呼び出し元はたくさんあるが、やはりこれも tui stdin でOK。補完
は特に ble.sh tui でしか発生しない (read を使った時にどうなるかは分
からないが)。

./lib/core-complete.sh:1720: '! ble/complete/check-cancel <&"$_ble_util_fd_tui_stdin"' '' progressive-weight
./lib/core-complete.sh:2848: if ((ext==148)) || ble/complete/check-cancel <&"$_ble_util_fd_tui_stdin"; then
./lib/core-complete.sh:3627: [[ ! -t 0 ]] && ble/complete/check-cancel <&"$_ble_util_fd_tui_stdin" &&
./lib/core-complete.sh:3649: "! ble/complete/check-cancel <&$_ble_util_fd_tui_stdin" 128 progressive-weight:killall
./lib/core-complete.sh:4121: "! ble/complete/check-cancel <&$_ble_util_fd_tui_stdin" 128 progressive-weight:killall'
./lib/core-complete.sh:4178: "! ble/complete/check-cancel <&$_ble_util_fd_tui_stdin" 128 progressive-weight:killall
./lib/core-complete.sh:4194: "! ble/complete/check-cancel <&$_ble_util_fd_tui_stdin" 128 progressive-weight:killall'

取り敢えずこれらは最早置換すれば良い。これらを置換したら <& は
core-complete.sh からなくなった。なので、他に
$_ble_util_fd_tui_stdin を ble/complete/check-cancel の為に余分に
redirect している箇所はないだろう。

./lib/core-complete.sh:2604: '! ble/complete/check-cancel' 128 progressive-weight

これは redirection がなかったが恐らく変更忘れか必要なかったか。何れ
にしても別の stdin をチェックする様な文脈ではないはずなのでこのまま
で良い。

以下で検索しても _ble_util_fd_tui_stdin の切り替え自体の処理以外はも
うない。全て置換できた様な気がする。

$ grc '<&"?\$_ble_util_fd_tui_stdin


何れにしても decode 関係は大概ユーザーからの入力を意識していて、何処か
勝手に用意した所からの入力を待つという事はないと思われる。

? fixed: ble/decode/cmap/decode-chars で処理している時に
ble/util/is-stdin-ready を見に行って大丈夫なのか? これの制御は
ble_decode_char_sync=1 というローカル変数で行われている様だが部分的に
しか制御されていない気がする。現状では寧ろ一般には stdin を見に行って
動作を決定している様な気がする。そもそも decode-chars は現在のユーザー
の入力と関係なく処理する物のはずだから、ble/util/is-stdin-ready は恰
も必ず失敗する様に振る舞わなければならない (或いは has-input でチェッ
クしない)。ble_decode_char_sync が設定されてる時は
ble/util/is-stdin-ready のチェックは失敗する様に書き換える事にした。

* ./src/edit.sh:10525: ble/util/is-stdin-ready && continue
これは read の実装に使っている。微妙だが、これは 0 を使う様に修正した。

* ./src/util.sh:5771: function ble/util/idle/IS_IDLE { ! ble/util/is-stdin-ready; }
ble/util/idle/IS_IDLE

./src/util.sh:5896: ble/util/idle/IS_IDLE || return 1
./src/util.sh:5914: ble/util/idle/IS_IDLE || break 2
./src/util.sh:6034: ble/util/idle/IS_IDLE || return 148
./src/util.sh:6071: ble/util/idle/IS_IDLE || return 148

ble/util/idle.do ループの中での利用なのでこれで良いはず。

./src/history.sh:373: [[ $opt_async ]] && ! ble/util/idle/IS_IDLE && return 148
./src/history.sh:439: [[ $opt_async ]] && ! ble/util/idle/IS_IDLE && return 148
./src/history.sh:810: [[ $opt_async ]] && ! ble/util/idle/IS_IDLE && return 148
./src/history.sh:824: [[ $opt_async ]] && ! ble/util/idle/IS_IDLE && return 148

これらは履歴読み込み及び mlfix の中断に用いている。基本的に idle/util
と同じ取扱で良いだろう。

* progcomp: compgen -V による結果取得 (motivated by RBT22, and many) [#D2253]
https://github.com/akinomyoga/ble.sh/issues/356

Expand Down
20 changes: 11 additions & 9 deletions src/decode.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1145,7 +1145,7 @@ function ble-decode-char/csi/consume {
_ble_decode_char_buffer=()
function ble/decode/has-input-for-char {
((_ble_decode_input_count)) ||
ble/util/is-stdin-ready ||
{ [[ ! $ble_decode_char_sync ]] && ble/util/is-stdin-ready; } ||
ble/encoding:"$bleopt_input_encoding"/is-intermediate
}

Expand Down Expand Up @@ -2494,7 +2494,7 @@ function ble/decode/widget/keymap-dispatch {
##
function ble/decode/has-input {
((_ble_decode_input_count||ble_decode_char_rest)) ||
ble/util/is-stdin-ready ||
{ [[ ! $ble_decode_char_sync ]] && ble/util/is-stdin-ready; } ||
ble/encoding:"$bleopt_input_encoding"/is-intermediate ||
ble-decode-char/is-intermediate

Expand All @@ -2511,7 +2511,7 @@ function ble/decode/has-input {
## cseq (char -> key) にとって次の文字が来ているかどうか
function ble/decode/has-input-char {
((_ble_decode_input_count||ble_decode_char_rest)) ||
ble/util/is-stdin-ready ||
{ [[ ! $ble_decode_char_sync ]] && ble/util/is-stdin-ready; } ||
ble/encoding:"$bleopt_input_encoding"/is-intermediate
}

Expand All @@ -2524,12 +2524,14 @@ function ble/decode/wait-input {
ble/decode/has-input && return 0
fi

while ((timeout>0)); do
local w=$((timeout<20?timeout:20))
ble/util/msleep "$w"
((timeout-=w))
ble/util/is-stdin-ready 0 && return 0
done
if [[ ! $ble_decode_char_sync ]]; then
while ((timeout>0)); do
local w=$((timeout<20?timeout:20))
ble/util/msleep "$w"
((timeout-=w))
ble/util/is-stdin-ready '' 0 && return 0
done
fi
return 1
}

Expand Down
2 changes: 1 addition & 1 deletion src/edit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10503,7 +10503,7 @@ function ble/builtin/read/.loop {
[[ $_ble_edit_read_accept ]] && break

# render
ble/util/is-stdin-ready && continue
ble/util/is-stdin-ready 0 && continue
ble-edit/content/check-limit
ble-decode/.hook/erase-progress
ble/application/render
Expand Down
14 changes: 11 additions & 3 deletions src/util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2793,21 +2793,29 @@ function ble/util/load-standard-builtin {
fi
}

## @fn ble/util/is-stdin-ready [exit]
## @fn ble/util/is-stdin-ready [fd] [exit]
## Returns if there is already any user inputs pending in stdin.
## @param[in,opt] fd
## This specifies the file descriptor to check. If omitted, it uses the
## file descriptor saved in $_ble_util_fd_tui_stdin.
## @param[in,opt] exit
## This specifies the exit status when we cannot test it. The default
## value is 1.
## @remarks When stdin (0) is connected to /dev/null, this function succeeds
## unconditionally, even though a read from /dev/null will fail.
if ((_ble_bash>=40000)); then
# #D1341 対策 変数代入形式だと組み込みコマンドにロケールが適用されない。
function ble/util/is-stdin-ready {
local IFS= LC_ALL= LC_CTYPE=C
builtin read -t 0
# Note: We use the explicit redirection "<&fd" instead of "-u fd" because
# it turned out that "builtin read -t 0 -u fd" is slower than "builtin read
# -t 0 <&fd".
builtin read -t 0 <&"${1:-${_ble_util_fd_tui_stdin:-0}}"
}
# suppress locale error #D1440
ble/function#suppress-stderr ble/util/is-stdin-ready
else
function ble/util/is-stdin-ready { return "${1:-1}"; }
function ble/util/is-stdin-ready { return "${2:-1}"; }
fi

# Note: BASHPID は Bash-4.0 以上
Expand Down

0 comments on commit 29c00fd

Please sign in to comment.