From b0e39732b5baa1727174fe18c439aa5e663427cd Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Thu, 26 Sep 2024 13:39:58 +0900 Subject: [PATCH] global: use "ble/util/assign" in more places --- ble.pp | 68 +++++++++++++++++++++++------------------------ contrib | 2 +- docs/ChangeLog.md | 9 ++++--- lib/core-test.sh | 19 +++++++------ make_command.sh | 1 + note.txt | 11 ++++++++ src/decode.sh | 2 +- src/edit.sh | 7 ++--- src/history.sh | 13 +++++---- src/util.sh | 17 +++++++++--- 10 files changed, 85 insertions(+), 64 deletions(-) diff --git a/ble.pp b/ble.pp index e11acc94..eeded808 100644 --- a/ble.pp +++ b/ble.pp @@ -399,24 +399,17 @@ function ble/base/evaldef { return "$ext" } +# will be overwritten by src/util.sh +if ((_ble_bash>=50300)); then + function ble/util/assign { builtin eval -- "$1=\${ builtin eval -- \"\$2\"; }"; } +else + function ble/util/assign { builtin eval -- "$1=\$(builtin eval -- \"\$2\")"; } +fi + { _ble_bash_builtins_adjusted= _ble_bash_builtins_save= } 2>/dev/null # set -x 対策 -## @fn ble/base/adjust-builtin-wrappers/.assign -## @remarks This function may be called with POSIXLY_CORRECT=y -function ble/base/adjust-builtin-wrappers/.assign { - if [[ ${_ble_util_assign_base-} ]]; then - local _ble_local_tmpfile; ble/util/assign/mktmp - builtin eval -- "$1" >| "$_ble_local_tmpfile" - local IFS= - ble/bash/read -d '' defs < "$_ble_local_tmpfile" - IFS=$_ble_term_IFS - ble/util/assign/rmtmp - else - defs=$(builtin eval -- "$1") - fi || ((1)) -} function ble/base/adjust-builtin-wrappers/.impl1 { # Note: 何故か local POSIXLY_CORRECT の効果が # builtin unset -v POSIXLY_CORRECT しても残存するので関数に入れる。 @@ -431,7 +424,7 @@ function ble/base/adjust-builtin-wrappers/.impl1 { _ble_bash_builtins_adjusted=1 builtin local defs - ble/base/adjust-builtin-wrappers/.assign ' + ble/util/assign defs ' \builtin declare -f "${builtins1[@]}" || ((1)) \builtin alias "${builtins1[@]}" "${keywords1[@]}" || ((1))' # set -e 対策 _ble_bash_builtins_save=$defs @@ -452,7 +445,7 @@ function ble/base/adjust-builtin-wrappers/.impl2 { # function :, alias : の保存 local defs - ble/base/adjust-builtin-wrappers/.assign 'LC_ALL= LC_MESSAGES=C builtin type :; alias :' || ((1)) # set -e 対策 + ble/util/assign defs 'LC_ALL= LC_MESSAGES=C builtin type :; alias :' || ((1)) # set -e 対策 defs=${defs#$': is a shell builtin\n'} _ble_bash_builtins_save=$_ble_bash_builtins_save$'\n'$defs @@ -534,7 +527,9 @@ function ble/base/xtrace/.log { if ((_ble_bash>=40200)); then builtin printf '%s [%(%F %T %Z)T] %s %s\n' "$open" -1 "$1" "$close" else - builtin printf '%s [%s] %s %s\n' "$open" "$(date 2>/dev/null)" "$1" "$close" + local date + ble/util/assign date 'date 2>/dev/null' + builtin printf '%s [%s] %s %s\n' "$open" "$date" "$1" "$close" fi >&"${BASH_XTRACEFD:-2}" } function ble/base/xtrace/adjust { @@ -751,13 +746,20 @@ function ble/variable#load-user-state/variable:LANG { { ble/base/adjust-bash-options; } &>/dev/null # set -x 対策 #D0930 -builtin bind &>/dev/null # force to load .inputrc +function ble/init/force-load-inputrc { + builtin unset -f "$FUNCNAME" -# WA #D1534 workaround for msys2 .inputrc -if [[ $OSTYPE == msys* ]]; then - [[ $(builtin bind -m emacs -p 2>/dev/null | grep '"\\C-?"') == '"\C-?": backward-kill-line' ]] && - builtin bind -m emacs '"\C-?": backward-delete-char' 2>/dev/null -fi + builtin bind &>/dev/null # force to load .inputrc + + # WA #D1534 workaround for msys2 .inputrc + if [[ $OSTYPE == msys* ]]; then + local bind_emacs + ble/util/assign bind_emacs 'builtin bind -m emacs -p 2>/dev/null' + [[ $'\n'$bind_emacs$'\n' == *$'\n"\\C-?": backward-kill-line\n' ]] && + builtin bind -m emacs '"\C-?": backward-delete-char' 2>/dev/null + fi +} +ble/init/force-load-inputrc if [[ ! -o emacs && ! -o vi && ! $_ble_init_command ]]; then builtin echo "ble.sh: ble.sh is not intended to be used with the line-editing mode disabled (--noediting)." >&2 @@ -1177,13 +1179,6 @@ function ble/bash/read-timeout { builtin read -t "$@"; } #------------------------------------------------------------------------------ # check environment -# will be overwritten by src/util.sh -if ((_ble_bash>=50300)); then - function ble/util/assign { builtin eval "$1=\${ builtin eval -- \"\$2\"; }"; } -else - function ble/util/assign { builtin eval "$1=\$(builtin eval -- \"\$2\")"; } -fi - # ble/bin if ((_ble_bash>=40000)); then @@ -1250,7 +1245,8 @@ function ble/init/check-environment { ble/util/print "ble.sh: insane environment: The command(s), ${commandMissing}not found. Check your environment variable PATH." >&2 # try to fix PATH - local default_path=$(command -p getconf PATH 2>/dev/null) + local default_path + ble/util/assign default_path 'command -p getconf PATH 2>/dev/null' [[ $default_path ]] || return 1 local original_path=$PATH @@ -1266,7 +1262,7 @@ function ble/init/check-environment { if [[ ! ${USER-} ]]; then ble/util/print "ble.sh: insane environment: \$USER is empty." >&2 - if USER=$(id -un 2>/dev/null) && [[ $USER ]]; then + if ble/util/assign USER 'id -un 2>/dev/null' && [[ $USER ]]; then export USER ble/util/print "ble.sh: modified USER=$USER" >&2 fi @@ -1275,7 +1271,7 @@ function ble/init/check-environment { if [[ ! ${HOSTNAME-} ]]; then ble/util/print "ble.sh: suspicious environment: \$HOSTNAME is empty." - if HOSTNAME=$(uname -n 2>/dev/null) && [[ $HOSTNAME ]]; then + if ble/util/assign HOSTNAME 'uname -n 2>/dev/null' && [[ $HOSTNAME ]]; then export HOSTNAME ble/util/print "ble.sh: fixed HOSTNAME=$HOSTNAME" >&2 fi @@ -1285,7 +1281,7 @@ function ble/init/check-environment { if [[ ! ${HOME-} ]]; then ble/util/print "ble.sh: insane environment: \$HOME is empty." >&2 local home - if home=$(getent passwd 2>/dev/null | awk -F : -v UID="$UID" '$3 == UID {print $6}') && [[ $home && -d $home ]] || + if ble/util/assign home 'getent passwd 2>/dev/null | awk -F : -v UID="$UID" '\''$3 == UID {print $6}'\''' && [[ $home && -d $home ]] || { [[ $USER && -d /home/$USER && -O /home/$USER ]] && home=/home/$USER; } || { [[ $USER && -d /Users/$USER && -O /Users/$USER ]] && home=/Users/$USER; } || { [[ $home && ! ( -e $home && -h $home ) ]] && ble/bin/mkdir -p "$home" 2>/dev/null; } @@ -3031,7 +3027,9 @@ function ble/base/sub:test { if (($#==0)); then set -- bash main util canvas decode edit syntax complete keymap.vi - logfile=$_ble_base_cache/test.$(date +'%Y%m%d.%H%M%S').log + local timestamp + ble/util/strftime -v timestamp '%Y%m%d.%H%M%S' + logfile=$_ble_base_cache/test.$timestamp.log >| "$logfile" ble/test/log#open "$logfile" fi diff --git a/contrib b/contrib index c2163775..1b9051ff 160000 --- a/contrib +++ b/contrib @@ -1 +1 @@ -Subproject commit c21637750e99caf265bbc61bd3d8102dd14b15ad +Subproject commit 1b9051ff4ea95e82a08cc31d06578407f3a139bf diff --git a/docs/ChangeLog.md b/docs/ChangeLog.md index 57fb9e98..255565e5 100644 --- a/docs/ChangeLog.md +++ b/docs/ChangeLog.md @@ -17,7 +17,7 @@ - main: suppress "--bash-debug-version" in "ble-reload" `#D2275` ec422115 - decode(read-user-settings): read the colonless form of `bind -x` of Bash 5.3 `#D2233` 62b23b69 - progcomp: use Bash 5.3 `compgen -V` for completions with newlines (motivated by RBT22) `#D2253` 0e8c388a - - progcomp: fix a bug that `x` at the end of the last completion is trimmed `#D2308` xxxxxxxx + - progcomp: fix a bug that `x` at the end of the last completion is trimmed `#D2308` d9faeb37 - main: fix attach failure with `--attach=prompt` in Bash 5.3 POSIX mode `#D2267` 49845707 - syntax: fix a problem that `$_` is not preserved `#D2269` e053690d - keymap/vi: support bash-5.3 readline bindable function `bash-vi-complete` in `vi_nmap` `#D2305` 55e0ee71 @@ -157,8 +157,8 @@ - edit: fix fd broken by ble-attach of new session in user space (reported by JohEngstrom) `#D2271` 49f97618 670c7ea0 - util (`ble-import`): do not specify arguments to `-C callback` `#D2277` 4f0e94a2 - main: fix issues with `ble/bin/awk` (reported by devidw) `#D2292` b0a7adcb -- util (`ble/path#remove-glob`): fix a bug that `*` matches and removes multiple paths `#D2310` xxxxxxxx -- decode (`bind`): print the filename and line in error messages (motivated by excited-bore) `#D2311` xxxxxxxx +- util (`ble/path#remove-glob`): fix a bug that `*` matches and removes multiple paths `#D2310` fd518d24 +- decode (`bind`): print the filename and line in error messages (motivated by excited-bore) `#D2311` 89c69077 ## Compatibility @@ -302,7 +302,8 @@ - global: normalize quoting of function names of the form `prefix:$name` `#D2296` 3d7c98bb - global: use `[:blank:]` instead of `[:space:]` `#D2299` e2fd8f0f - global: rename `ret` not used as `REPLY` `#D2300` 86cbf78e -- global: avoid raw word splitting `#D2309` xxxxxxxx +- global: avoid raw word splitting `#D2309` b55c4003 +- global: use `ble/util/assign` in more places `#D2312` xxxxxxxx # ble-0.4.0-devel3 diff --git a/lib/core-test.sh b/lib/core-test.sh index e69093b6..e15506a9 100644 --- a/lib/core-test.sh +++ b/lib/core-test.sh @@ -40,12 +40,12 @@ function ble/test/log#open { local h10=---------- [[ -s $file ]] && ble/util/print "$h10$h10$h10$h10$h10$h10$h10" >&"$_ble_test_logfile_fd" - ble/util/print "[$(date +'%F %T %Z')] test: start logging" >&"$_ble_test_logfile_fd" + ble/util/strftime "[%F %T %Z] test: start logging" >&"$_ble_test_logfile_fd" fi } function ble/test/log#close { if [[ $_ble_test_logfile_fd ]]; then - ble/util/print "[$(date +'%F %T %Z')] test: end logging" >&"$_ble_test_logfile_fd" + ble/util/strftime "[%F %T %Z] test: end logging" >&"$_ble_test_logfile_fd" ble/fd#close _ble_test_logfile_fd _ble_test_logfile_fd= fi @@ -102,14 +102,13 @@ function ble/test/end-section { local ntest npass count=$_ble_test_section_count local ntest nfail npass - builtin eval -- $( - ble/bin/awk ' - BEGIN{test=0;fail=0;pass=0;} - /^test /{test++} - /^fail /{fail++} - /^pass /{pass++} - END{print "ntest="test" nfail="fail" npass="pass;} - ' "$_ble_test_section_file") + local awk_script=' + BEGIN{test=0;fail=0;pass=0;} + /^test /{test++} + /^fail /{fail++} + /^pass /{pass++} + END{print "ntest="test" nfail="fail" npass="pass;}' + ble/util/eval-stdout 'ble/bin/awk "$awk_script" "$_ble_test_section_file"' local sgr=$'\e[32m' sgr0=$'\e[m' ((npass==ntest)) || sgr=$'\e[31m' diff --git a/make_command.sh b/make_command.sh index 9ce4f483..7cbfcff2 100755 --- a/make_command.sh +++ b/make_command.sh @@ -508,6 +508,7 @@ function sub:scan/check-readonly-unsafe { # Exceptions in each file /^\.\/ble.pp:[0-9]*:BLEOPT=$/d + /^\.\/ble.pp:[0-9]*:\/assign (USER|HOSTNAME)/d /^\.\/lib\/core-complete.sh:[0-9]+:KEY=$/d /^\.\/lib\/core-syntax.sh:[0-9]+:VAR=$/d /^\.\/lib\/init-(cmap|term).sh:[0-9]+:TERM=$/d diff --git a/note.txt b/note.txt index 726bde06..c48e147a 100644 --- a/note.txt +++ b/note.txt @@ -7728,6 +7728,17 @@ bash_tips Done (実装ログ) ------------------------------------------------------------------------------- +2024-12-31 + + * global: ble/util/assign をもっと広く使う [#D2312] + + 初期化の段階で $() を使っていた箇所があるが、もっと早く ble/util/assign の + 一時実装を用意して良い筈である。特に bash-5.3 では ${ ...; } を単純に使えば + 良いので最初に定義するのが効率的である。 + + そもそも builtin eval -- "$(...)" だって今後は builtin eval -- "${ ...; }" + に置き換えることができる筈。 + 2024-12-30 * decode (bind): print the filename and line in error messages (motivated by excited-bore) [#D2311] diff --git a/src/decode.sh b/src/decode.sh index 8d5c3feb..d31dff6f 100644 --- a/src/decode.sh +++ b/src/decode.sh @@ -4575,7 +4575,7 @@ function ble/decode/attach { ble/util/reset-keymap-of-editing-mode # 元のキー割り当ての保存・unbind - builtin eval -- "$(ble/decode/readline/.generate-source-to-unbind-default)" # 21ms + ble/util/eval-stdout 'ble/decode/readline/.generate-source-to-unbind-default' # 21ms # ble.sh bind の設置 ble/decode/readline/bind # 20ms diff --git a/src/edit.sh b/src/edit.sh index 1659b413..2bfe9cf5 100644 --- a/src/edit.sh +++ b/src/edit.sh @@ -11419,13 +11419,13 @@ function ble/widget/command-help.core { if ble/is-function ble/bin/man; then MANOPT= ble/bin/man "${command##*/}" 2>/dev/null && return 0 # Note: $(man "${command##*/}") だと (特に日本語で) 正しい結果が得られない。 - # if local content=$(MANOPT= ble/bin/man "${command##*/}" 2>&1) && [[ $content ]]; then + # if local content; ble/util/assign content 'MANOPT= ble/bin/man "${command##*/}" 2>&1' && [[ $content ]]; then # ble/util/print "$content" | ble/util/pager # return 0 # fi fi - if local content; content=$("$command" --help 2>&1) && [[ $content ]]; then + if local content; ble/util/assign content '"$command" --help 2>&1' && [[ $content ]]; then ble/util/print "$content" | ble/util/pager return 0 fi @@ -11496,7 +11496,8 @@ function ble/widget/command-help/.type { # alias の時はサブシェルで解決 if [[ $type == alias ]]; then - builtin eval -- "$(ble/widget/command-help/.type/.resolve-alias "$literal" "$command")" + # Note: This has a side effect so is done in a subshell + builtin eval -- "$(ble/widget/command-help/.type/.resolve-alias "$literal" "$command")" # subshell fi if [[ $type == keyword && $command != "$literal" ]]; then diff --git a/src/history.sh b/src/history.sh index e3740b4c..810a66e6 100644 --- a/src/history.sh +++ b/src/history.sh @@ -127,7 +127,7 @@ if ((_ble_bash>=50200)); then # following command produces SIGPIPE because "head -1" or "sed 1q" # terminates prematurely. To prevent Bash from changing the TTY state on # exit, we intentionally run the following command in a subshell. - ble/string#split-words min "$(builtin history | ble/bin/sed -n '1{p;q;}')" + ble/string#split-words min "$(builtin history | ble/bin/sed -n '1{p;q;}')" # subshell else ble/util/assign-words min 'builtin history | ble/bin/sed -n "1{p;q;}"' fi @@ -504,7 +504,7 @@ else # * プロセス置換にしてもファイルに書き出しても大した違いはない。 # 270ms for 16437 entries (generate-source の時間は除く) # * プロセス置換×source は bash-3 で動かない。eval に変更する。 - local result=$(ble/history:bash/load/.generate-source) + local result=$(ble/history:bash/load/.generate-source) # subshell local IFS=$_ble_term_IFS if [[ $opt_append ]]; then if ((_ble_bash>=30100)); then @@ -968,7 +968,7 @@ function ble/builtin/history/.initialize { fi local histfile=${HISTFILE-} rskip=0 - [[ -e $histfile ]] && rskip=$(ble/bin/wc -l "$histfile" 2>/dev/null) + [[ -e $histfile ]] && ble/util/assign rskip 'ble/bin/wc -l "$histfile" 2>/dev/null' ble/string#split-words rskip "$rskip" local min; ble/builtin/history/.get-min local max; ble/builtin/history/.get-max @@ -1044,16 +1044,15 @@ function ble/builtin/history/.read { local file=$1 skip=${2:-0} fetch=$3 local -x histnew=$_ble_base_run/$$.history.new if [[ -s $file ]]; then - local script=$(ble/bin/awk -v skip="$skip" ' + local awk_script=' BEGIN { histnew = ENVIRON["histnew"]; count = 0; } NR <= skip { next; } { print $0 >> histnew; count++; } END { print "ble/builtin/history/.set-rskip \"$file\" " NR; print "((_ble_builtin_history_histnew_count+=" count "))"; - } - ' "$file") - builtin eval -- "$script" + }' + ble/util/eval-stdout 'ble/bin/awk -v skip="$skip" "$awk_script" "$file"' else ble/builtin/history/.set-rskip "$file" 0 fi diff --git a/src/util.sh b/src/util.sh index dfdaf7a7..b68729a7 100644 --- a/src/util.sh +++ b/src/util.sh @@ -2249,6 +2249,10 @@ function ble/util/readarray { ## files. In the function substitutions, the update of the job list is ## suppressed, so the notified dead jobs are not flushed on just running ## ble/util/assign jobs jobs. +## +## @remarks This function is intended to work under POSIXLY_CORRECT=y when it +## is called by ble/base/adjust-builtin-wrappers/.impl1. +## _ble_util_assign_base=$_ble_base_run/$$.util.assign.tmp _ble_util_assign_level=0 if ((_ble_bash>=40000)); then @@ -2276,7 +2280,7 @@ function ble/util/assign/rmtmp { } if ((_ble_bash>=50300)); then function ble/util/assign { - builtin eval "$1=\${ builtin eval -- \"\$2\"; }" + builtin eval -- "$1=\${ builtin eval -- \"\$2\"; }" } elif ((_ble_bash>=40000)); then # mapfile の方が read より高速 @@ -2286,7 +2290,8 @@ elif ((_ble_bash>=40000)); then local _ble_local_ret=$? _ble_local_arr= mapfile -t _ble_local_arr < "$_ble_local_tmpfile" ble/util/assign/rmtmp - IFS=$'\n' builtin eval "$1=\"\${_ble_local_arr[*]}\"" + local IFS=$'\n' # avoid tmpenv to make it POSIXLY_CORRECT-safe + builtin eval -- "$1=\"\${_ble_local_arr[*]}\"" return "$_ble_local_ret" } else @@ -2296,7 +2301,7 @@ else local _ble_local_ret=$? IFS= ble/bash/read -d '' "$1" < "$_ble_local_tmpfile" ble/util/assign/rmtmp - builtin eval "$1=\${$1%\$_ble_term_nl}" + builtin eval -- "$1=\${$1%\$_ble_term_nl}" return "$_ble_local_ret" } fi @@ -2370,6 +2375,12 @@ function ble/util/assign-words { ble/string#split-words "$1" "${!1}" } +function ble/util/eval-stdout { + local _ble_local_script + ble/util/assign _ble_local_script "$1" + builtin eval -- "$_ble_local_script" +} + if ((_ble_bash>=50300)); then function ble/util/compgen { builtin compgen -V "$@"; } else