diff --git a/README-ja_JP.md b/README-ja_JP.md index 04a6518c..de389967 100644 --- a/README-ja_JP.md +++ b/README-ja_JP.md @@ -230,6 +230,10 @@ Vimモードの実装は2017年9月に始まり2018年3月に一先ず完成と つまり、同名の異なるローカル変数さえ定義することができません。 この問題は `ble.sh` 固有の制限ではなく、あらゆる Bash の枠組みがグローバルの読み込み専用変数に影響を受けます。 一般的にグローバルスコープに読み込み変数を設定することはセキュリティ的な理由がない限りは非推奨と考えられています (参照 [[1]](https://lists.gnu.org/archive/html/bug-bash/2019-03/threads.html#00150), [[2]](https://lists.gnu.org/archive/html/bug-bash/2020-04/threads.html#00200), [[3]](https://mywiki.wooledge.org/BashProgramming?highlight=%28%22readonly%22%20flag,%20or%20an%20%22integer%22%20flag,%20but%20these%20are%20mostly%20useless,%20and%20serious%20scripts%20shouldn%27t%20be%20using%20them%29#Variables))。 + また、`ble.sh` はビルトインコマンド `readonly` をシェル関数で置き換え、グローバル変数を読み込み専用にするのをブロックします。 + 例外として、全て大文字の変数 (`ble.sh` が内部使用するものを除く) および `_*` の形の変数 (`_ble_*` および `__ble_*` を除く) を読み込み専用にすることは可能です。 +- `ble.sh` は Bash のビルトインコマンド (`trap`, `readonly`, `bind`, `history`, `read`, `exit`) をシェル関数で上書きし、`ble.sh` と干渉しないようにその振る舞いを調整します。 + ユーザーまたは他の枠組みが元のビルトインを直接呼び出した場合、または `ble.sh` の定義したシェル関数を別のシェル関数で上書きした場合、正しい動作を保証できません。 # 1 使い方 diff --git a/README.md b/README.md index 074f0502..db45c135 100644 --- a/README.md +++ b/README.md @@ -245,6 +245,10 @@ For example, This is not the problem specific to `ble.sh`, but any Bash framework may suffer from the global readonly variables. It is generally not recommended to define global readonly variables in Bash except for the security reasoning (Refs. [[1]](https://lists.gnu.org/archive/html/bug-bash/2019-03/threads.html#00150), [[2]](https://lists.gnu.org/archive/html/bug-bash/2020-04/threads.html#00200), [[3]](https://mywiki.wooledge.org/BashProgramming?highlight=%28%22readonly%22%20flag,%20or%20an%20%22integer%22%20flag,%20but%20these%20are%20mostly%20useless,%20and%20serious%20scripts%20shouldn%27t%20be%20using%20them%29#Variables)). + Also, `ble.sh` overrides the builtin `readonly` with a shell function to prevent it from making global variables readonly. + It allows only uppercase global variables and `_*` to become readonly except `_ble_*`, `__ble_*`, and some special uppercase variables. +- `ble.sh` overrides Bash's built-in commands (`trap`, `readonly`, `bind`, `history`, `read`, and `exit`) with shell functions to adjust the behavior of each built-in command and prevent them from interfering with `ble.sh`. + If the user or another framework directly calls the original builtins through `builtin BUILTIN`, or if the user or another framework replaces the shell functions, the behavior is undefined. # 1 Usage diff --git a/archive/getopt-test.sh b/archive/getopt-test.sh index 25dc4b58..e0c13ba7 100755 --- a/archive/getopt-test.sh +++ b/archive/getopt-test.sh @@ -2,11 +2,11 @@ # # usage # -# declare "${ble_getopt_locals[@]}" +# declare "${_ble_getopt_locals[@]}" # ble/getopt.init "$0" "$@" # # while ble/getopt.next; do -# case "$OPTION" in +# case "$option" in # (-a|--hoge) # echo hoge ;; # esac @@ -20,49 +20,49 @@ source getopt.sh function command1 { - builtin eval -- "$ble_getopt_prologue" + builtin eval -- "$_ble_getopt_prologue" ble/getopt.init "$0" "$@" while ble/getopt.next; do - case "$OPTION" in + case "$option" in (-b|--bytes) ble/util/print bytes ;; (-s|--spaces) ble/util/print spaces ;; (-w|--width) if ! ble/getopt.get-optarg; then - ble/getopt.print-argument-message "missing an option argument for $OPTION" - _opterror=1 + ble/getopt.print-argument-message "missing an option argument for $option" + getopt_error=1 continue fi - ble/util/print "width=$OPTARG" ;; + ble/util/print "width=$optarg" ;; (--char-width|--tab-width|--indent-type) if ! ble/getopt.get-optarg; then - ble/getopt.print-argument-message "missing an option argument for $OPTION" - _opterror=1 + ble/getopt.print-argument-message "missing an option argument for $option" + getopt_error=1 continue fi - ble/util/print "${OPTION#--} = $OPTARG" ;; + ble/util/print "${option#--} = $optarg" ;; (--continue) if ble/getopt.has-optarg; then ble/getopt.get-optarg - ble/util/print "continue = $OPTARG" + ble/util/print "continue = $optarg" else ble/util/print "continue" fi ;; (-i|--indent) if ble/getopt.has-optarg; then ble/getopt.get-optarg - ble/util/print "indent = $OPTARG" + ble/util/print "indent = $optarg" else ble/util/print "indent" fi ;; (--text-justify|--no-text-justify) - ble/util/print "${OPTION#--}" ;; + ble/util/print "${option#--}" ;; (-[^-]*|--?*) ble/getopt.print-argument-message "unknown option." - _opterror=1 ;; + getopt_error=1 ;; (*) ble/getopt.print-argument-message "unknown argument." - _opterror=1 ;; + getopt_error=1 ;; esac done diff --git a/archive/getopt.sh b/archive/getopt.sh index 32c42d5c..60e07c43 100644 --- a/archive/getopt.sh +++ b/archive/getopt.sh @@ -5,10 +5,10 @@ ## function myfunc { ## local flagVersion= flagHelp= flagEnd= ## -## builtin eval -- "$ble_getopt_prologue" +## builtin eval -- "$_ble_getopt_prologue" ## ble/getopt.init myfunc "$@" ## while ble/getopt.next; do -## case "$OPTION" in +## case "$option" in ## ## # ## # --version, --help (引数を取らないオプション) @@ -22,11 +22,11 @@ ## (-w|--width) ## if ble/getopt.get-optarg; then ## # 引数が見付かった場合 -## process "$OPTARG" +## process "$optarg" ## else ## # 引数が見付からなかった場合 -## ble/getopt.print-argument-message "missing an option argument for $OPTION" -## _opterror=1 +## ble/getopt.print-argument-message "missing an option argument for $option" +## getopt_error=1 ## fi ## ## # @@ -37,7 +37,7 @@ ## if ble/getopt.has-optarg; then ## # 形式 --continue=... (直接引数あり) の場合 ## ble/getopt.get-optarg -## process "$OPTARG" +## process "$optarg" ## else ## # 形式 --continue (直接引数なし) の場合 ## fi @@ -47,14 +47,14 @@ ## # ## (--) ## # 残りの引数を処理 -## process "${@:OPTIND}" +## process "${@:optind}" ## break ;; ## ## (-*) ## ble/getopt.print-argument-message "unknown option." -## _opterror=1 ;; +## getopt_error=1 ;; ## (*) -## process "$OPTION" ;; +## process "$option" ;; ## esac ## done ## @@ -73,37 +73,39 @@ ## fi ## } -ble_getopt_locals=(_optargs _optchars _optarg _opterror OPTIND OPTION OPTARG) -ble_getopt_prologue='declare "${ble_getopt_locals[@]}"' +_ble_getopt_locals=(getopt_args getopt_chars getopt_arg getopt_error optind option optarg) +_ble_getopt_prologue='declare "${_ble_getopt_locals[@]}"' function ble/getopt.init { - _optargs=("$@") - _optchars= _optarg= _opterror= - OPTIND=1 OPTION= OPTARG= + getopt_args=("$@") + getopt_chars= + getopt_arg= + getopt_error= + optind=1 option= optarg= } function ble/getopt.print-argument-message { local IFS=$_ble_term_IFS - local index=$((OPTIND-1)) - ble/util/print "${_optargs[0]##*/} (argument#$index \`${_optargs[index]}'): $*" >&2 + local index=$((optind-1)) + ble/util/print "${getopt_args[0]##*/} (argument#$index \`${getopt_args[index]}'): $*" >&2 } function ble/getopt.print-message { local IFS=$_ble_term_IFS - local index=$((OPTIND-1)) - ble/util/print "${_optargs[0]##*/} (arguments): $*" >&2 + local index=$((optind-1)) + ble/util/print "${getopt_args[0]##*/} (arguments): $*" >&2 } function ble/getopt.next { ble/getopt/.check-optarg-cleared - if ((${#_optchars})); then - OPTION=-${_optchars::1} - _optchars=${_optchars:1} - elif ((OPTIND<${#_optargs[@]})); then - OPTION=${_optargs[OPTIND++]} - if [[ $OPTION == -[^-]* ]]; then - _optchars=${OPTION:2} - OPTION=${OPTION::2} - elif [[ $OPTION == --*=* ]]; then - _optarg==${OPTION#--*=} - OPTION=${OPTION%%=*} + if ((${#getopt_chars})); then + option=-${getopt_chars::1} + getopt_chars=${getopt_chars:1} + elif ((optind<${#getopt_args[@]})); then + option=${getopt_args[optind++]} + if [[ $option == -[^-]* ]]; then + getopt_chars=${option:2} + option=${option::2} + elif [[ $option == --*=* ]]; then + getopt_arg==${option#--*=} + option=${option%%=*} fi else return 1 @@ -112,28 +114,28 @@ function ble/getopt.next { # optarg function ble/getopt.get-optarg { - if [[ $_optarg ]]; then - OPTARG=${_optarg:1} - _optarg= - elif ((OPTIND<${#_optargs[@]})); then - OPTARG=${_optargs[OPTIND++]} + if [[ $getopt_arg ]]; then + optarg=${getopt_arg:1} + getopt_arg= + elif ((optind<${#getopt_args[@]})); then + optarg=${getopt_args[optind++]} else return 1 fi } function ble/getopt.has-optarg { - [[ $_optarg ]] + [[ $getopt_arg ]] } function ble/getopt/.check-optarg-cleared { - if [[ $_optarg ]]; then - ble/getopt.print-argument-message "the option argument \`${_optarg:1}' is not processed ">&2 - _opterror=1 _optarg= + if [[ $getopt_arg ]]; then + ble/getopt.print-argument-message "the option argument \`${getopt_arg:1}' is not processed ">&2 + getopt_error=1 getopt_arg= fi } function ble/getopt.finalize { ble/getopt/.check-optarg-cleared - [[ ! $_opterror ]] + [[ ! $getopt_error ]] } diff --git a/archive/getopt1.sh b/archive/getopt1.sh index b79988e9..59cf7b19 100755 --- a/archive/getopt1.sh +++ b/archive/getopt1.sh @@ -3,7 +3,7 @@ # Usage # -# local "${ble_getopt_vars[@]/%/=}" # WA #D1570 checked +# local "${_ble_getopt_vars[@]/%/=}" # WA #D1570 checked # ble-getopt-begin "progname" "m:n c:n,n k:n,n" "$@" # ble-getopt # @@ -12,35 +12,35 @@ # * next-argument: appropriate error message # * next-argument: negative tests # * next-argument: function calls -# * _getopt_index を OPTIND に名前を変える? +# * getopt_index を OPTIND に名前を変える? -ble_getopt_vars=( - OPTARGS # 読み取られたオプション +_ble_getopt_vars=( + optargs # 読み取られたオプション - _getopt_cmd # 呼出元コマンド名 - _getopt_odefs # オプション定義 - _getopt_args # コマンド引数 - _getopt_len # コマンド引数の数 - _getopt_index # 現在のコマンド引数の位置 OPTIND + getopt_cmd # 呼出元コマンド名 + getopt_odefs # オプション定義 + getopt_args # コマンド引数 + getopt_len # コマンド引数の数 + getopt_index # 現在のコマンド引数の位置 OPTIND - _getopt_opt # 解析中オプション - _getopt_oarg # オプション引数 - _getopt_olen # オプション引数の数 - _getopt_oind # オプション引数の現在位置 + getopt_opt # 解析中オプション + getopt_oarg # オプション引数 + getopt_olen # オプション引数の数 + getopt_oind # オプション引数の現在位置 ) function .ble-getopt.next-argument { local type=$1 oarg - if ((_getopt_oind<_getopt_olen)); then - oarg=${_getopt_oarg[_getopt_oind++]} - elif ((_getopt_index<_getopt_len)); then - oarg=${_getopt_args[_getopt_index++]} + if ((getopt_oind&2 + ble/util/print "$getopt_cmd: missing an argument of the option \`${optargs[0]}'." 1>&2 return 1 fi fi @@ -49,24 +49,24 @@ function .ble-getopt.next-argument { case "$type" in [nefdhcbpugkrwxsv]) if [ ! -$type "$oarg" ]; then - ble/util/print "$_getopt_cmd: the argument of the option \`${OPTARGS[0]}' is empty string (oarg=$oarg)." 1>&2 + ble/util/print "$getopt_cmd: the argument of the option \`${optargs[0]}' is empty string (oarg=$oarg)." 1>&2 return 1 fi ;; esac - OPTARGS[${#OPTARGS[@]}]=$oarg + optargs[${#optargs[@]}]=$oarg } function .ble-getopt.process-option { local name=$1 - OPTARGS=("$name") + optargs=("$name") # search the option definition local i f_found adef - for ((i=0;i<${#_getopt_odefs[@]};i++)); do - if [[ $name == "${_getopt_odefs[$i]%%:*}" ]]; then + for ((i=0;i<${#getopt_odefs[@]};i++)); do + if [[ $name == "${getopt_odefs[$i]%%:*}" ]]; then f_found=1 - ble/string#split adef : "${_getopt_odefs[i]}" + ble/string#split adef : "${getopt_odefs[i]}" break fi done @@ -87,35 +87,35 @@ function .ble-getopt.process-option { } function ble-getopt-begin { - ble/string#split-words _getopt_cmd "$1" - ble/string#split-words _getopt_odefs "$2" + ble/string#split-words getopt_cmd "$1" + ble/string#split-words getopt_odefs "$2" shift 2 - _getopt_args=("$@") - _getopt_len=${#_getopt_args[@]} - _getopt_index=0 + getopt_args=("$@") + getopt_len=${#getopt_args[@]} + getopt_index=0 - _getopt_opt= - _getopt_olen=0 - _getopt_oind=0 + getopt_opt= + getopt_olen=0 + getopt_oind=0 - OPTARGS=() + optargs=() } function .ble-getopt.check-oarg-processed { - if ((_getopt_oind<_getopt_olen)); then - ble/util/print "$_getopt_cmd: an option argument not processed (oarg=${_getopt_oarg[$_getopt_oind]})." 1>&2 - _getopt_oind=0 - _getopt_olen=0 - builtin unset -v '_getopt_oarg[@]' + if ((getopt_oind&2 + getopt_oind=0 + getopt_olen=0 + builtin unset -v 'getopt_oarg[@]' return 1 fi } function ble-getopt { # 読み掛けのオプション列 - if [[ $_getopt_opt ]]; then - local o=${_getopt_opt::1} - _getopt_opt=${_getopt_opt:1} + if [[ $getopt_opt ]]; then + local o=${getopt_opt::1} + getopt_opt=${getopt_opt:1} .ble-getopt.process-option "$o" return "$?" fi @@ -124,26 +124,26 @@ function ble-getopt { .ble-getopt.check-oarg-processed || return 1 # 完了 - if ((_getopt_index>=_getopt_len)); then - builtin unset -v 'OPTARGS[@]' + if ((getopt_index>=getopt_len)); then + builtin unset -v 'optargs[@]' return 2 fi - local arg=${_getopt_args[_getopt_index++]} + local arg=${getopt_args[getopt_index++]} if [[ $arg == -?* ]]; then if [[ $arg == --?* ]]; then # longname option local f_longname=1 - _getopt_opt=${arg:2} + getopt_opt=${arg:2} - local o=${_getopt_opt%%=*} - if [[ $o != "$_getopt_opt" ]]; then - _getopt_oarg=("${_getopt_opt#*=}") - _getopt_oind=0 - _getopt_olen=1 + local o=${getopt_opt%%=*} + if [[ $o != "$getopt_opt" ]]; then + getopt_oarg=("${getopt_opt#*=}") + getopt_oind=0 + getopt_olen=1 fi - _getopt_opt= + getopt_opt= .ble-getopt.process-option "$o" .ble-getopt.check-oarg-processed || return 1 @@ -151,17 +151,17 @@ function ble-getopt { else # short options local f_longname= - _getopt_opt=${arg:1} + getopt_opt=${arg:1} - ble/string#split _getopt_oarg : "$_getopt_opt" - _getopt_olen=${#_getopt_oarg[@]} - _getopt_oind=1 + ble/string#split getopt_oarg : "$getopt_opt" + getopt_olen=${#getopt_oarg[@]} + getopt_oind=1 ble-getopt return "$?" fi else # 通常の引数 - OPTARGS=('' "$arg") + optargs=('' "$arg") fi } diff --git a/archive/layer/adapter.sh b/archive/layer/adapter.sh index 108d7294..98691605 100755 --- a/archive/layer/adapter.sh +++ b/archive/layer/adapter.sh @@ -219,14 +219,14 @@ function ble/syntax-highlight+default { elif rex='^([^'"$IFS"'|&;()<>'\''"\]|\\.)+' && [[ $tail =~ $rex ]]; then # ■ time'hello' 等の場合に time だけが切り出されてしまう - local _0=${BASH_REMATCH[0]} - builtin eval "local cmd=${_0}" + local word=${BASH_REMATCH[0]} + builtin eval "local cmd=${word}" # この部分の判定で fork を沢山する \if 等に対しては 4fork+2exec になる。 # ■キャッシュ(accept-line 時に clear)するなどした方が良いかもしれない。 local type; ble/util/type type "$cmd" ble/syntax-highlight+default/type "$type" "$cmd" # -> type - if [[ $type = alias && $cmd != "$_0" ]]; then + if [[ $type = alias && $cmd != "$word" ]]; then # alias を \ で無効化している場合 # → unalias して再度 check (2fork) type=$( @@ -234,7 +234,7 @@ function ble/syntax-highlight+default { ble/util/type type "$cmd" ble/syntax-highlight+default/type "$type" "$cmd" # -> type ble/util/put "$type") - elif [[ "$type" = keyword && "$cmd" != "$_0" ]]; then + elif [[ "$type" = keyword && "$cmd" != "$word" ]]; then # keyword (time do if function else elif fi の類) を \ で無効化している場合 # →file, function, builtin, jobs のどれかになる。以下 3fork+2exec ble/util/joblist.check @@ -256,21 +256,21 @@ function ble/syntax-highlight+default { case "$type" in (file) - ble/syntax-highlight/append "$i $((i+${#_0})) fg=green" ;; + ble/syntax-highlight/append "$i $((i+${#word})) fg=green" ;; (alias) - ble/syntax-highlight/append "$i $((i+${#_0})) fg=teal" ;; + ble/syntax-highlight/append "$i $((i+${#word})) fg=teal" ;; (function) - ble/syntax-highlight/append "$i $((i+${#_0})) fg=navy" ;; + ble/syntax-highlight/append "$i $((i+${#word})) fg=navy" ;; (builtin) - ble/syntax-highlight/append "$i $((i+${#_0})) fg=red" ;; + ble/syntax-highlight/append "$i $((i+${#word})) fg=red" ;; (builtin_bold) - ble/syntax-highlight/append "$i $((i+${#_0})) fg=red,bold" ;; + ble/syntax-highlight/append "$i $((i+${#word})) fg=red,bold" ;; (keyword) - ble/syntax-highlight/append "$i $((i+${#_0})) fg=blue" ;; + ble/syntax-highlight/append "$i $((i+${#word})) fg=blue" ;; (jobs) ble/syntax-highlight/append "$i $((i+1)) fg=red" ;; (error|*) - ble/syntax-highlight/append "$i $((i+${#_0})) bg=224" ;; + ble/syntax-highlight/append "$i $((i+${#word})) bg=224" ;; esac ((i+=${#BASH_REMATCH})) diff --git a/ble.pp b/ble.pp index c701a32a..8fb84169 100644 --- a/ble.pp +++ b/ble.pp @@ -302,7 +302,7 @@ function ble/base/adjust-builtin-wrappers-1 { # ので builtin は unset -f builtin してしまう。 unset -f builtin builtin local POSIXLY_CORRECT=y builtins1 keywords1 - builtins1=(builtin unset enable unalias return break continue declare local typeset readonly eval exec set) + builtins1=(builtin unset enable unalias return break continue declare local typeset eval exec set) keywords1=(if then elif else case esac while until for select do done '{' '}' '[[' function) if [[ ! $_ble_bash_builtins_adjusted ]]; then _ble_bash_builtins_adjusted=1 @@ -375,9 +375,13 @@ function ble/variable#copy-state { # From src/util.sh (ble/fd#is-open and ble/fd#alloc/.nextfd) function ble/base/xtrace/.fdcheck { builtin : >&"$1"; } 2>/dev/null function ble/base/xtrace/.fdnext { - local __init=${_ble_util_openat_nextfd:=${bleopt_openat_base:-30}} - for (($1=__init;$1<__init+1024;$1++)); do ble/base/xtrace/.fdcheck "${!1}" || break; done - (($1<__init+1024)) || { (($1=__init,_ble_util_openat_nextfd++)); builtin eval "exec ${!1}>&-"; } || ((1)) + local _ble_local_init=${_ble_util_openat_nextfd:=${bleopt_openat_base:-30}} + for (($1=_ble_local_init;$1<_ble_local_init+1024;$1++)); do + ble/base/xtrace/.fdcheck "${!1}" || break + done + (($1<_ble_local_init+1024)) || + { (($1=_ble_local_init,_ble_util_openat_nextfd++)); builtin eval "exec ${!1}>&-"; } || + ((1)) } function ble/base/xtrace/.log { local bash=${_ble_bash:-$((BASH_VERSINFO[0]*10000+BASH_VERSINFO[1]*100+BASH_VERSINFO[2]))} @@ -1740,11 +1744,11 @@ function ble-update/.make { shift fi - if ! "$MAKE" -q "$@"; then + if ! "$make" -q "$@"; then if [[ $sudo ]]; then - sudo "$MAKE" "$@" + sudo "$make" "$@" else - "$MAKE" "$@" + "$make" "$@" fi else # インストール先に更新がなくても現在の session でロードされている ble.sh が @@ -1882,11 +1886,11 @@ function ble-update { fi # check make - local MAKE= + local make= if ble/bin#has gmake; then - MAKE=gmake + make=gmake elif ble/bin#has make && make --version 2>&1 | ble/bin/grep -qiF 'GNU Make'; then - MAKE=make + make=make else ble/util/print "ble-update: GNU Make is not available." >&2 return 1 @@ -1942,8 +1946,8 @@ function ble-update { local branch=${_ble_base_branch:-master} ( ble/bin/mkdir -p "$_ble_base/src" && builtin cd "$_ble_base/src" && git clone --recursive --depth 1 "$_ble_base_repository_url" "$_ble_base/src/ble.sh" -b "$branch" && - builtin cd ble.sh && "$MAKE" all && - "$MAKE" INSDIR="$_ble_base" INSDIR_DOC="$insdir_doc" install ) && + builtin cd ble.sh && "$make" all && + "$make" INSDIR="$_ble_base" INSDIR_DOC="$insdir_doc" install ) && ble-update/.reload return "$?" fi diff --git a/contrib b/contrib index cd9dcae3..93c2bdf8 160000 --- a/contrib +++ b/contrib @@ -1 +1 @@ -Subproject commit cd9dcae3c2502f581b9a0d6e4f2f7657c3a257d5 +Subproject commit 93c2bdf8bf8df817dfa8a9b287f7614732cdb135 diff --git a/docs/ChangeLog.md b/docs/ChangeLog.md index d660ffbc..cd5db4c3 100644 --- a/docs/ChangeLog.md +++ b/docs/ChangeLog.md @@ -546,6 +546,7 @@ - util, decode, vi: fix leak variables `#D1933` 8d5cab8 - util: support `bleopt debug_idle` `#D1945` fa10184 - global: work around bash-4.4 no-argument return in trap `#D1970` eb4ffce +- util: replace builtin `readonly` with a shell function (requested by mozirilla213) `#D1985` xxxxxxx ## Contrib diff --git a/keymap/vi.sh b/keymap/vi.sh index 9f932138..6ddc9c58 100644 --- a/keymap/vi.sh +++ b/keymap/vi.sh @@ -4861,7 +4861,7 @@ function ble/keymap:vi/text-object/tag.impl { ## @fn ble/keymap:vi/text-object:sentence/.beg ## @var[out] beg ## @var[out] is_interval -## @var[in] LF, HT +## @var[in] lf, ht function ble/keymap:vi/text-object:sentence/.beg { beg= is_interval= local pivot=$_ble_edit_ind rex= @@ -4877,7 +4877,7 @@ function ble/keymap:vi/text-object:sentence/.beg { fi fi if [[ ! $beg ]]; then - rex="^.*((^$LF?|$LF$LF)([ $HT]*)|[.!?][])'\"]*([ $HT$LF]+))" + rex="^.*((^$lf?|$lf$lf)([ $ht]*)|[.!?][])'\"]*([ $ht$lf]+))" if [[ ${_ble_edit_str::pivot+1} =~ $rex ]]; then beg=${#BASH_REMATCH} if ((pivot=0)); then - _prev="@$((axis-_prev-1))>" + local sprev=${word[nofs+3]} schild=${word[nofs+2]} + if ((sprev>=0)); then + sprev="@$((axis-sprev-1))>" else - _prev= + sprev= fi - if ((_child>=0)); then - _child=">@$((axis-_child-1))" + if ((schild>=0)); then + schild=">@$((axis-schild-1))" else - _child= + schild= fi - local wattr=${word[nofs+4]} _wattr= + local wattr=${word[nofs+4]} if [[ $wattr != - ]]; then wattr="/(wattr=$wattr)" else wattr= fi - out=" word=$wtype:$_prev$b-$e$_child$wattr$out" + out=" word=$wtype:$sprev$b-$e$schild$wattr$out" for ((;b=i2)) && [[ ${_tail_syntax_stat[i-i2]} == "$_stat" ]]; then + ble/syntax/parse/serialize-stat + if ((i>=i2)) && [[ ${tail_syntax_stat[i-i2]} == "$sstat" ]]; then if ble/syntax/parse/nest-equals "$inest"; then # 前回の解析と同じ状態になった時 → 残りは前回の結果と同じ - _ble_syntax_stat=("${_ble_syntax_stat[@]::i}" "${_tail_syntax_stat[@]:i-i2}") - _ble_syntax_tree=("${_ble_syntax_tree[@]::i}" "${_tail_syntax_tree[@]:i-i2}") - _ble_syntax_nest=("${_ble_syntax_nest[@]::i}" "${_tail_syntax_nest[@]:i-i2}") - _ble_syntax_attr=("${_ble_syntax_attr[@]::i}" "${_tail_syntax_attr[@]:i-i2}") + _ble_syntax_stat=("${_ble_syntax_stat[@]::i}" "${tail_syntax_stat[@]:i-i2}") + _ble_syntax_tree=("${_ble_syntax_tree[@]::i}" "${tail_syntax_tree[@]:i-i2}") + _ble_syntax_nest=("${_ble_syntax_nest[@]::i}" "${tail_syntax_nest[@]:i-i2}") + _ble_syntax_attr=("${_ble_syntax_attr[@]::i}" "${tail_syntax_attr[@]:i-i2}") break fi fi - _ble_syntax_stat[i]=$_stat + _ble_syntax_stat[i]=$sstat tail=${text:i} #%if !release debug_p1=$i #%end # 処理 - "${_BLE_SYNTAX_FCTX[ctx]}" || ((_ble_syntax_attr[i]=ATTR_ERR,i++)) + "${_ble_syntax_context_proc[ctx]}" || ((_ble_syntax_attr[i]=ATTR_ERR,i++)) # nest-pop で CMDI/ARGI になる事もあるし、 # また単語終端な文字でも FCTX が失敗する事もある (unrecognized な場合) ので、 @@ -5183,7 +5183,7 @@ function ble/syntax/parse { builtin unset -v debug_p1 #%end - ble/syntax/vanishing-word/register _tail_syntax_tree "$((-i2))" "$((i2+1))" "$i" 0 "$i" + ble/syntax/vanishing-word/register tail_syntax_tree "$((-i2))" "$((i2+1))" "$i" 0 "$i" ble/syntax/urange#update _ble_syntax_attr_ "$i1" "$i" @@ -5195,8 +5195,8 @@ function ble/syntax/parse { # 終端の状態の記録 if ((i>=iN)); then ((i=iN)) - ble/syntax/parse/generate-stat - _ble_syntax_stat[i]=$_stat + ble/syntax/parse/serialize-stat + _ble_syntax_stat[i]=$sstat # ネスト開始点のエラー表示は +syntax 内で。 # ここで設定すると部分更新の際に取り消しできないから。 @@ -6359,11 +6359,11 @@ function ble/syntax/highlight/cmdtype/.is-job-name { return 1 } function ble/syntax/highlight/cmdtype/.impl { - local cmd=$1 _0=$2 + local cmd=$1 word=$2 local cmd_type; ble/util/type cmd_type "$cmd" ble/syntax/highlight/cmdtype1 "$cmd_type" "$cmd" - if [[ $type == "$ATTR_CMD_ALIAS" && $cmd != "$_0" ]]; then + if [[ $type == "$ATTR_CMD_ALIAS" && $cmd != "$word" ]]; then # alias を \ で無効化している場合は # unalias して再度 check (2fork) type=$( @@ -6371,7 +6371,7 @@ function ble/syntax/highlight/cmdtype/.impl { ble/util/type cmd_type "$cmd" ble/syntax/highlight/cmdtype1 "$cmd_type" "$cmd" printf %s "$type") - elif ble/syntax/highlight/cmdtype/.is-job-name "$cmd" "$_0"; then + elif ble/syntax/highlight/cmdtype/.is-job-name "$cmd" "$word"; then # %() { :; } として 関数を定義できるが jobs の方が優先される。 # (% という名の関数を呼び出す方法はない?) # でも % で始まる物が keyword になる事はそもそも無いような。 @@ -6395,7 +6395,7 @@ function ble/syntax/highlight/cmdtype/.impl { # Note: 連想配列 _ble_syntax_highlight_filetype は core-syntax-def.sh で先に定義される。 _ble_syntax_highlight_filetype_version=-1 function ble/syntax/highlight/cmdtype { - local cmd=$1 _0=$2 + local cmd=$1 word=$2 # check cache if ((_ble_syntax_highlight_filetype_version!=_ble_edit_LINENO)); then @@ -6403,13 +6403,13 @@ function ble/syntax/highlight/cmdtype { ((_ble_syntax_highlight_filetype_version=_ble_edit_LINENO)) fi - if local ret; ble/gdict#get _ble_syntax_highlight_filetype "$_0"; then + if local ret; ble/gdict#get _ble_syntax_highlight_filetype "$word"; then type=$ret return 0 fi - ble/syntax/highlight/cmdtype/.impl "$cmd" "$_0" - ble/gdict#set _ble_syntax_highlight_filetype "$_0" "$type" + ble/syntax/highlight/cmdtype/.impl "$cmd" "$word" + ble/gdict#set _ble_syntax_highlight_filetype "$word" "$type" } #------------------------------------------------------------------------------ @@ -7182,10 +7182,12 @@ function ble/highlight/layer:syntax/touch-range { ble/syntax/urange#update '' "$@" } function ble/highlight/layer:syntax/fill { - local _i _arr=$1 _i1=$2 _i2=$3 _v=$4 - for ((_i=_i1;_i<_i2;_i++)); do - builtin eval "$_arr[_i]=\"\$_v\"" - done + local _ble_local_script=' + local iARR=0 i1ARR=$2 i2ARR=$3 + for ((iARR=i1ARR;iARR&1'; exit=$? + ble/util/assign stdout "$_ble_test_code" 2>&1'; exit=$? local -a item_result=() item_result[0]=$stdout item_result[1]=$stderr @@ -205,18 +209,18 @@ function ble/test { item_result[3]=$ret local i flag_error= - for i in "${!item_expect[@]}"; do - [[ ${item_result[i]} == "${item_expect[i]}" ]] && continue + for i in "${!_ble_test_item_expect[@]}"; do + [[ ${item_result[i]} == "${_ble_test_item_expect[i]}" ]] && continue if [[ ! $flag_error ]]; then flag_error=1 - ble/test/log $'\e[1m'"$title"$'\e[m: \e[91m'"${display_code:-$code}"$'\e[m' + ble/test/log $'\e[1m'"$_ble_test_title"$'\e[m: \e[91m'"${_ble_test_display_code:-$_ble_test_code}"$'\e[m' fi - ble/test/diff "${item_name[i]}" "${item_expect[i]}" "${item_result[i]}" + ble/test/diff "${_ble_test_item_name[i]}" "${_ble_test_item_expect[i]}" "${item_result[i]}" done if [[ $flag_error ]]; then - if [[ ! ${item_expect[1]+set} && $stderr ]]; then + if [[ ! ${_ble_test_item_expect[1]+set} && $stderr ]]; then ble/test/log "" ble/test/log "$stderr" ble/test/log "" @@ -225,6 +229,6 @@ function ble/test { fi [[ ! $flag_error ]] - ble/test/section#report "$title" + ble/test/section#report "$_ble_test_title" return 0 } diff --git a/lib/test-syntax.sh b/lib/test-syntax.sh index 767d963e..c51bbe11 100644 --- a/lib/test-syntax.sh +++ b/lib/test-syntax.sh @@ -6,40 +6,40 @@ ble-import lib/core-test ble/test/start-section 'ble/syntax' 22 ( - _func=ble/syntax:bash/simple-word/evaluate-last-brace-expansion - _collect='ret=$simple_ibrace/$ret' - ble/test "$_func 'a{b,c}x' ; $_collect" ret='6:2/acx' - ble/test "$_func 'a{b,{c,d}x' ; $_collect" ret='9:2/adx' - ble/test "$_func 'a{b,{c,d}}x'; $_collect" ret='10:2/adx' - ble/test "$_func 'a{{c,dx' ; $_collect" ret='5:1/adx' - ble/test "$_func 'a{b{c,dx' ; $_collect" ret='6:2/abdx' - ble/test "$_func 'a{b,c}{d}x' ; $_collect" ret='7:2/acd}x' + func=ble/syntax:bash/simple-word/evaluate-last-brace-expansion + collect='ret=$simple_ibrace/$ret' + ble/test "$func 'a{b,c}x' ; $collect" ret='6:2/acx' + ble/test "$func 'a{b,{c,d}x' ; $collect" ret='9:2/adx' + ble/test "$func 'a{b,{c,d}}x'; $collect" ret='10:2/adx' + ble/test "$func 'a{{c,dx' ; $collect" ret='5:1/adx' + ble/test "$func 'a{b{c,dx' ; $collect" ret='6:2/abdx' + ble/test "$func 'a{b,c}{d}x' ; $collect" ret='7:2/acd}x' ) ( - _func=ble/syntax:bash/simple-word/reconstruct-incomplete-word - _collect='ret=$?:$simple_flags:[$simple_ibrace]:$ret' - ble/test "$_func 'hello-word' ; $_collect" ret='0::[0:0]:hello-word' - ble/test "$_func 'hello word' ; $_collect" ret='1::[0:0]:hello' - ble/test "$_func 'hello-word\"a' ; $_collect" ret='0:D:[0:0]:hello-word"a"' - ble/test "$_func 'a{b,c}x' ; $_collect" ret='0::[6:2]:acx' - ble/test "$_func 'a{b,{c,d}x' ; $_collect" ret='0::[9:2]:adx' - ble/test "$_func 'a{b,{c,d}}x' ; $_collect" ret='0::[10:2]:adx' - ble/test "$_func 'a{{c,dx' ; $_collect" ret='0::[5:1]:adx' - ble/test "$_func 'a{b{c,dx' ; $_collect" ret='0::[6:2]:abdx' - ble/test "$_func 'a{b,c}{d}x' ; $_collect" ret='0::[7:2]:acd}x' - ble/test "$_func 'a{b,c}x\"hello, world'; $_collect" ret='0:D:[6:2]:acx"hello, world"' - ble/test "$_func 'a{b,{c,d}x'\''a' ; $_collect" ret='0:S:[9:2]:adx'\''a'\' - ble/test "$_func 'a{b,{c,d}}x\$'\''\e[m'; $_collect" ret='0:E:[10:2]:adx$'\''\e[m'\' - ble/test "$_func 'a{{c,dx\$\"aa' ; $_collect" ret='0:I:[5:1]:adx$"aa"' + func=ble/syntax:bash/simple-word/reconstruct-incomplete-word + collect='ret=$?:$simple_flags:[$simple_ibrace]:$ret' + ble/test "$func 'hello-word' ; $collect" ret='0::[0:0]:hello-word' + ble/test "$func 'hello word' ; $collect" ret='1::[0:0]:hello' + ble/test "$func 'hello-word\"a' ; $collect" ret='0:D:[0:0]:hello-word"a"' + ble/test "$func 'a{b,c}x' ; $collect" ret='0::[6:2]:acx' + ble/test "$func 'a{b,{c,d}x' ; $collect" ret='0::[9:2]:adx' + ble/test "$func 'a{b,{c,d}}x' ; $collect" ret='0::[10:2]:adx' + ble/test "$func 'a{{c,dx' ; $collect" ret='0::[5:1]:adx' + ble/test "$func 'a{b{c,dx' ; $collect" ret='0::[6:2]:abdx' + ble/test "$func 'a{b,c}{d}x' ; $collect" ret='0::[7:2]:acd}x' + ble/test "$func 'a{b,c}x\"hello, world'; $collect" ret='0:D:[6:2]:acx"hello, world"' + ble/test "$func 'a{b,{c,d}x'\''a' ; $collect" ret='0:S:[9:2]:adx'\''a'\' + ble/test "$func 'a{b,{c,d}}x\$'\''\e[m'; $collect" ret='0:E:[10:2]:adx$'\''\e[m'\' + ble/test "$func 'a{{c,dx\$\"aa' ; $collect" ret='0:I:[5:1]:adx$"aa"' ) ( - _func=ble/syntax:bash/simple-word/evaluate-path-spec - _collect='ret="${spec[*]} >>> ${path[*]}"' - ble/test "$_func '~/a/b/c' ; $_collect" ret="~ ~/a ~/a/b ~/a/b/c >>> $HOME $HOME/a $HOME/a/b $HOME/a/b/c" - ble/test "$_func '~/a/b/c' / after-sep; $_collect" ret="~/ ~/a/ ~/a/b/ ~/a/b/c >>> $HOME/ $HOME/a/ $HOME/a/b/ $HOME/a/b/c" - ble/test "$_func '/x/y/z' / after-sep ; $_collect" ret="/ /x/ /x/y/ /x/y/z >>> / /x/ /x/y/ /x/y/z" + func=ble/syntax:bash/simple-word/evaluate-path-spec + collect='ret="${spec[*]} >>> ${path[*]}"' + ble/test "$func '~/a/b/c' ; $collect" ret="~ ~/a ~/a/b ~/a/b/c >>> $HOME $HOME/a $HOME/a/b $HOME/a/b/c" + ble/test "$func '~/a/b/c' / after-sep; $collect" ret="~/ ~/a/ ~/a/b/ ~/a/b/c >>> $HOME/ $HOME/a/ $HOME/a/b/ $HOME/a/b/c" + ble/test "$func '/x/y/z' / after-sep ; $collect" ret="/ /x/ /x/y/ /x/y/z >>> / /x/ /x/y/ /x/y/z" ) ble/test/end-section diff --git a/lib/test-util.sh b/lib/test-util.sh index 81eec588..06690f33 100644 --- a/lib/test-util.sh +++ b/lib/test-util.sh @@ -138,27 +138,27 @@ ble/test ble/util/setexit 255 exit=255 # ble/util/save-vars, restore-vars ( - VARNAMES=(name x y count data) + varnames=(name x y count data) function print-status { echo "name=$name x=$x y=$y count=$count data=(${data[*]})" } function f1 { - local "${VARNAMES[@]/%/=}" # WA #D1570 checked + local "${varnames[@]/%/=}" # WA #D1570 checked name=1 x=2 y=3 count=4 data=(aa bb cc dd) print-status - ble/util/save-vars save1_ "${VARNAMES[@]}" + ble/util/save-vars save1_ "${varnames[@]}" name=one x= y=A count=1 data=(Q) print-status - ble/util/save-vars save2_ "${VARNAMES[@]}" + ble/util/save-vars save2_ "${varnames[@]}" - ble/util/restore-vars save1_ "${VARNAMES[@]}" + ble/util/restore-vars save1_ "${varnames[@]}" print-status - ble/util/restore-vars save2_ "${VARNAMES[@]}" + ble/util/restore-vars save2_ "${varnames[@]}" print-status } ble/test f1 \ @@ -174,7 +174,7 @@ ble/test ble/util/setexit 255 exit=255 declare v=1 declare -i i=1 export x=2 - readonly r=3 + builtin readonly r=3 declare -a a=() if ((_ble_bash>=40000)); then declare -A A=() @@ -236,7 +236,7 @@ ble/test ble/util/setexit 255 exit=255 ) # ble/variable#is-global -function is-global() (readonly "$1"; ! local "$1" 2>/dev/null) +function is-global() (builtin readonly "$1"; ! local "$1" 2>/dev/null) ( v1=1 v2=2 ((_ble_bash>=40200)) && diff --git a/lib/vim-surround.sh b/lib/vim-surround.sh index 86addb20..06d17c67 100644 --- a/lib/vim-surround.sh +++ b/lib/vim-surround.sh @@ -148,7 +148,7 @@ function ble/lib/vim-surround.sh/load-template { # read user settings - if [[ ${ins//[0-9]} && ! ${ins//[_0-9a-zA-Z]} ]]; then + if [[ ${ins//[0-9]} && ! ${ins//[_a-zA-Z0-9]} ]]; then local optname=bleopt_vim_surround_$ins template=${!optname} [[ $template ]] && return 0 diff --git a/make_command.sh b/make_command.sh index dbad1ffc..68863665 100755 --- a/make_command.sh +++ b/make_command.sh @@ -1402,6 +1402,15 @@ function sub:scan { \Z# EXIT trapZd g' + sub:scan/builtin 'readonly' | + sed -E 'h;s/'"$_make_rex_escseq"'//g;s/^[^:]*:[0-9]+:[[:space:]]*// + \Z^[[:space:]]*#Zd + \ZWA readonlyZd + \Zble/cmdspec/opts Zd + \Z\('\''declare'\''(\|'\''[a-z]+'\'')+\)Zd + \Z readonly was blocked\.Zd + g' + sub:scan/a.txt sub:scan/check-todo-mark sub:scan/bash300bug diff --git a/note.txt b/note.txt index 0610877c..c00c8b31 100644 --- a/note.txt +++ b/note.txt @@ -6661,6 +6661,61 @@ bash_tips 2023-03-01 + * util: readonly を上書きする? (reqeusted by mozirilla213) [#D1985] + https://github.com/akinomyoga/ble.sh/issues/289 + + 其処まで積極的にユーザー環境を上書きして良いのか不明である。 + + - alias doesn't affect existing functions. + + - command line can be easily detected, but this is still incomplete + detection because even if the user does not directly write declare -r, + the functions called by the user could contain declare -gr, etc. + + The scope that the readonly is called and the scope of the variable + specified to readonly are unrelated to each other. One needs to test each + variable name whether it is in the global scope or not. + + * propagating tempenv にも気をつけなければならない。 + + $ f1() { ble/variable#is-global fdsafdsa; } + $ fdsafdsa=a f1 + + このテストだと global ではないと判定されてそれは is-global の判定としては + 期待する動作である。然しこれに対して export/readonly を実行すると外側に + propagate してしまう。global に propagate しないという事までちゃんと判定 + する方法はあるのだろうか。そもそも tempenv をそうと判定する方法があるのか + という事も疑問である。 + + まあこの場合は仕方がないと思って諦めるべきだろうか。 + + これの判定は完全ではない。 + + * done: global readonly に対しても whitelist は作っても良いのかもしれない。 + 全て [A-Z0-9_] であり 2 文字以上で Bash の特殊変数に一致していなくて + ble.sh が使っていない変数名? + + ble.sh 内部で使っている大文字変数も実は改名するべきの気もする。特に vi.sh + の中で使っている変数が気になる…がこれは禁止リストに入れてしまっても良い + 気がする。 + + 小文字でも _ble で始まらない _[a-zA-Z]* の様な変数名も許容して良いのでは + ないか。然し、ble.sh の内部で使っている変数もあるのでそれらは ble.sh の側 + で改名する等して避ける事にする。 + + * done: is-global の実装で readonly が使われている。 + + * done: adjust builtins: readonly はユーザーによる上書きを許容する。 + + * done: エラーメッセージは一回しか実行しない→もう何回か表示して良い気がす + る。10回迄表示する事にした。 + + * ユーザーが既に readonly を上書きしている場合にはどうするのか。 + function#push,pop で処理する事にすれば良いだろうか。と思ったがその様にす + るのであれば他の builtin も同様にする必要があるのではないかという事になっ + てくる。もしこれについて考えるのであれば全ての builtin について同時に適用 + するべき。 + * exec: BLE_PIPESTATUS 公開する (motivated by mozirilla213) [#D1984] https://github.com/akinomyoga/ble.sh/issues/290 diff --git a/src/benchmark.sh b/src/benchmark.sh index bc68d039..bbdbc66e 100644 --- a/src/benchmark.sh +++ b/src/benchmark.sh @@ -13,8 +13,8 @@ fi function ble-measure/.loop { # Note: ksh requires to quote ; builtin eval "function _target { ${2:+"$2; "}return 0; }" - local _i _n=$1 - for ((_i=0;_i<_n;_i++)); do + local __ble_i __ble_n=$1 + for ((__ble_i=0;__ble_i<__ble_n;__ble_i++)); do _target done } @@ -226,7 +226,7 @@ function ble-measure/.read-arguments { measure_threshold=$optarg ;; (B) ble-measure/.read-arguments.get-optarg && - __base=$optarg ;; + __ble_base=$optarg ;; (*) ble/util/print "ble-measure: unrecognized option '-$c'." flags=E$flags ;; @@ -257,8 +257,8 @@ function ble-measure/.read-arguments { ## @var[out] nsec ## 実行時間を nsec 単位で返します。 function ble-measure { - local __level=${#FUNCNAME[@]} __base= - [[ ${ZSH_VERSION-} ]] && __level=${#funcstack[@]} + local __ble_level=${#FUNCNAME[@]} __ble_base= + [[ ${ZSH_VERSION-} ]] && __ble_level=${#funcstack[@]} local flags= command= count=$_ble_measure_count local measure_threshold=$_ble_measure_threshold ble-measure/.read-arguments "$@" || return "$?" @@ -285,14 +285,14 @@ function ble-measure { return 2 fi - if [[ ! $__base ]]; then + if [[ ! $__ble_base ]]; then if [[ $_ble_measure_base ]]; then # ble-measure/calibrate 実行済みの時 - __base=$((_ble_measure_base+_ble_measure_base_nestcost*__level/10)) + __ble_base=$((_ble_measure_base+_ble_measure_base_nestcost*__ble_level/10)) else - # それ以外の時は __level 毎に計測 - if [[ ! $ble_measure_calibrate && ! ${_ble_measure_base_guess[__level]} ]]; then - if [[ ! ${_ble_measure_base_real[__level+1]} ]]; then + # それ以外の時は __ble_level 毎に計測 + if [[ ! $ble_measure_calibrate && ! ${_ble_measure_base_guess[__ble_level]} ]]; then + if [[ ! ${_ble_measure_base_real[__ble_level+1]} ]]; then if [[ ${_ble_measure_target-} == ksh ]]; then # Note: In ksh, we cannot do recursive call with dynamic scoping, # so we directly call the measuring function @@ -303,23 +303,23 @@ function ble-measure { ble-measure -qc3 -B 0 '' ble/util/unlocal ble_measure_calibrate fi - _ble_measure_base_real[__level+1]=$nsec - _ble_measure_base_guess[__level+1]=$nsec + _ble_measure_base_real[__ble_level+1]=$nsec + _ble_measure_base_guess[__ble_level+1]=$nsec fi - # 上の実測値は一つ上のレベル (__level+1) での結果になるので現在のレベル - # (__level) の値に補正する。レベル毎の時間が chatoyancy での線形フィッ + # 上の実測値は一つ上のレベル (__ble_level+1) での結果になるので現在のレベル + # (__ble_level) の値に補正する。レベル毎の時間が chatoyancy での線形フィッ # トの結果に比例する仮定して補正を行う。 # # linear-fit result with $f(x) = A x + B$ in chatoyancy # A = 65.9818 pm 2.945 (4.463%) # B = 4356.75 pm 19.97 (0.4585%) - local __A=6598 __B=435675 - nsec=${_ble_measure_base_real[__level+1]} - _ble_measure_base_guess[__level]=$((nsec*(__B+__A*(__level-1))/(__B+__A*__level))) - ble/util/unlocal __A __B + local cA=6598 cB=435675 + nsec=${_ble_measure_base_real[__ble_level+1]} + _ble_measure_base_guess[__ble_level]=$((nsec*(cB+cA*(__ble_level-1))/(cB+cA*__ble_level))) + ble/util/unlocal cA cB fi - __base=${_ble_measure_base_guess[__level]:-0} + __ble_base=${_ble_measure_base_guess[__ble_level]:-0} fi fi @@ -358,18 +358,18 @@ function ble-measure { # upate base if the result is shorter than base if ((min_utot<0x7FFFFFFFFFFFFFFF/1000)); then - local __real=$((min_utot*1000/n)) - [[ ${_ble_measure_base_real[__level]} ]] && - ((__real<_ble_measure_base_real[__level])) && - _ble_measure_base_real[__level]=$__real - [[ ${_ble_measure_base_guess[__level]} ]] && - ((__real<_ble_measure_base_guess[__level])) && - _ble_measure_base_guess[__level]=$__real - ((__real<__base)) && - __base=$__real + local __ble_real=$((min_utot*1000/n)) + [[ ${_ble_measure_base_real[__ble_level]} ]] && + ((__ble_real<_ble_measure_base_real[__ble_level])) && + _ble_measure_base_real[__ble_level]=$__ble_real + [[ ${_ble_measure_base_guess[__ble_level]} ]] && + ((__ble_real<_ble_measure_base_guess[__ble_level])) && + _ble_measure_base_guess[__ble_level]=$__ble_real + ((__ble_real<__ble_base)) && + __ble_base=$__ble_real fi - local nsec0=$__base + local nsec0=$__ble_base if [[ $flags != *q* ]]; then local reso=$_ble_measure_resolution local awk=ble/bin/awk diff --git a/src/canvas.sh b/src/canvas.sh index dc6611fe..bfe24dc3 100644 --- a/src/canvas.sh +++ b/src/canvas.sh @@ -1133,9 +1133,9 @@ function ble/canvas/flush.draw { ## 出力先の変数名を指定します。 ## @var[out] !var function ble/canvas/sflush.draw { - local _var=ret - [[ $1 == -v ]] && _var=$2 - IFS= builtin eval "$_var=\"\${DRAW_BUFF[*]}\"" + local _ble_local_var=ret + [[ $1 == -v ]] && _ble_local_var=$2 + IFS= builtin eval "$_ble_local_var=\"\${DRAW_BUFF[*]}\"" DRAW_BUFF=() } function ble/canvas/bflush.draw { @@ -1787,21 +1787,21 @@ function ble/canvas/trace/.process-csi-sequence { fi elif [[ $char == I ]]; then # CHT "CSI I" - local _x - ((_x=(x/it+arg)*it, - _x>=cols&&(_x=cols-1))) - if ((_x>x)); then - [[ $flag_clip ]] || ble/canvas/put-cuf.draw "$((_x-x))" - ((x=_x)) + local tx + ((tx=(x/it+arg)*it, + tx>=cols&&(tx=cols-1))) + if ((tx>x)); then + [[ $flag_clip ]] || ble/canvas/put-cuf.draw "$((tx-x))" + ((x=tx)) fi elif [[ $char == Z ]]; then # CHB "CSI Z" - local _x - ((_x=((x+it-1)/it-arg)*it, - _x<0&&(_x=0))) - if ((_x=cols&&(_x=cols-1))) - if ((x<_x)); then + local tx + ((tx=(x+it)/it*it, + tx>=cols&&(tx=cols-1))) + if ((x_ble_textmap_endy)); then - (($_var=_ble_textmap_length)) - elif ((_y<_ble_textmap_begy)); then - (($_var=0)) + local __ble_x=$1 __ble_y=$2 + if ((__ble_y>_ble_textmap_endy)); then + (($__ble_var=_ble_textmap_length)) + elif ((__ble_y<_ble_textmap_begy)); then + (($__ble_var=0)) else # 2分法 - local _l=0 _u=$((_ble_textmap_length+1)) _m - local _mx _my - while ((_l+1<_u)); do - ble/textmap#getxy.cur --prefix=_m "$((_m=(_l+_u)/2))" - (((_y<_my||_y==_my&&_x<_mx)?(_u=_m):(_l=_m))) + local __ble_l=0 __ble_u=$((_ble_textmap_length+1)) + local m mx my + while ((__ble_l+1<__ble_u)); do + ble/textmap#getxy.cur --prefix=m "$((m=(__ble_l+__ble_u)/2))" + (((__ble_y=0x1000000)); then - if ((__color==0x1000000)); then + elif ((_ble_local_color>=0x1000000)); then + if ((_ble_local_color==0x1000000)); then ble/color/g#setfg-index "$1" 16 else - (($1=$1&~(_ble_color_gflags_FgIndexed|_ble_color_gflags_FgMask)|(__color&0xFFFFFF)<<8)) # true color + (($1=$1&~(_ble_color_gflags_FgIndexed|_ble_color_gflags_FgMask)|(_ble_local_color&0xFFFFFF)<<8)) # true color fi else - ble/color/g#setfg-index "$1" "$__color" + ble/color/g#setfg-index "$1" "$_ble_local_color" fi } function ble/color/g#setbg { - local __color=$2 - if ((__color<0)); then + local _ble_local_color=$2 + if ((_ble_local_color<0)); then ble/color/g#setbg-clear "$1" - elif ((__color>=0x1000000)); then - if ((__color==0x1000000)); then + elif ((_ble_local_color>=0x1000000)); then + if ((_ble_local_color==0x1000000)); then ble/color/g#setbg-index "$1" 16 else - (($1=$1&~(_ble_color_gflags_BgIndexed|_ble_color_gflags_BgMask)|(__color&0xFFFFFF)<<32)) # true color + (($1=$1&~(_ble_color_gflags_BgIndexed|_ble_color_gflags_BgMask)|(_ble_local_color&0xFFFFFF)<<32)) # true color fi else - ble/color/g#setbg-index "$1" "$__color" + ble/color/g#setbg-index "$1" "$_ble_local_color" fi } ## @fn ble/color/g#append g g2 @@ -318,18 +328,18 @@ function ble/color/g#setbg { ## @param[in,out] g ## @param[in] g2 function ble/color/g#append { - local __g2=$2 - ((__g2&(_ble_color_gflags_FgMask|_ble_color_gflags_FgIndexed))) && + local _ble_local_g2=$2 + ((_ble_local_g2&(_ble_color_gflags_FgMask|_ble_color_gflags_FgIndexed))) && (($1&=~(_ble_color_gflags_FgMask|_ble_color_gflags_FgIndexed))) - ((__g2&(_ble_color_gflags_BgMask|_ble_color_gflags_BgIndexed))) && + ((_ble_local_g2&(_ble_color_gflags_BgMask|_ble_color_gflags_BgIndexed))) && (($1&=~(_ble_color_gflags_BgMask|_ble_color_gflags_BgIndexed))) - (($1|=__g2)) + (($1|=_ble_local_g2)) } function ble/color/g#compose { (($1=($2))) - local __g2 - for __g2 in "${@:3}"; do - ble/color/g#append "$1" "$__g2" + local _ble_local_g2 + for _ble_local_g2 in "${@:3}"; do + ble/color/g#append "$1" "$_ble_local_g2" done } function ble/color/g.setfg { ble/color/g#setfg g "$@"; } @@ -827,20 +837,20 @@ function ble/color/.color2sgrbg { ## @var[in,out] j ## @var[ out] arg function ble/color/read-sgrspec/.arg-next { - local _var=arg _ret + local _ble_local_var=arg _ble_local_ret if [[ $1 == -v ]]; then - _var=$2 + _ble_local_var=$2 shift 2 fi if ((j<${#fields[*]})); then - ((_ret=10#0${fields[j++]})) + ((_ble_local_ret=10#0${fields[j++]})) else ((i++)) - ((_ret=10#0${specs[i]%%:*})) + ((_ble_local_ret=10#0${specs[i]%%:*})) fi - (($_var=_ret)) + (($_ble_local_var=_ble_local_ret)) } ## @fn ble-color/read-sgrspec sgrspec opts @@ -1479,17 +1489,18 @@ function ble/highlight/layer/update/add-urange { (PREV_UMAX<0||PREV_UMAX=0)); then ble/array#reserve-prototype "$((DMAX-DMIN))" builtin eval " - $__dstArray=( - \"\${$__srcArray[@]::DMIN}\" + $_ble_local_dstarr=( + \"\${$_ble_local_srcarr[@]::DMIN}\" \"\${_ble_array_prototype[@]::DMAX-DMIN}\" - \"\${$__srcArray[@]:DMAX0}\")" + \"\${$_ble_local_srcarr[@]:DMAX0}\")" else - [[ $__dstArray != "$__srcArray" ]] && builtin eval "$__dstArray=(\"\${$__srcArray[@]}\")" + [[ $_ble_local_dstarr != "$_ble_local_srcarr" ]] && + builtin eval -- "$_ble_local_dstarr=(\"\${$_ble_local_srcarr[@]}\")" fi } diff --git a/src/decode.sh b/src/decode.sh index 345c5831..c8d44013 100644 --- a/src/decode.sh +++ b/src/decode.sh @@ -155,7 +155,7 @@ function ble-decode-kbd/generate-keycode { local keyname=$1 if ((${#keyname}==1)); then ble/util/s2c "$1" - elif [[ $keyname && ! ${keyname//[a-zA-Z_0-9]} ]]; then + elif [[ $keyname && ! ${keyname//[_a-zA-Z0-9]} ]]; then ble-decode-kbd/.get-keycode "$keyname" if [[ ! $ret ]]; then ((ret=_ble_decode_FunctionKeyBase+_ble_decode_kbd__n++)) @@ -365,7 +365,7 @@ function ble-decode-kbd { if [[ $kspec == ? ]]; then ble/util/s2c "$kspec" ((code|=ret)) - elif [[ $kspec && ! ${kspec//[@_0-9a-zA-Z]} ]]; then + elif [[ $kspec && ! ${kspec//[@_a-zA-Z0-9]} ]]; then ble-decode-kbd/.get-keycode "$kspec" [[ $ret ]] || ble-decode-kbd/generate-keycode "$kspec" ((code|=ret)) diff --git a/src/edit.sh b/src/edit.sh index 6bd2b042..ea23f09d 100644 --- a/src/edit.sh +++ b/src/edit.sh @@ -560,20 +560,22 @@ ble/function#suppress-stderr ble/prompt/.escape-control-characters # LC_COLLATE ## コロン区切りのオプションリストです。escape が指定されている時、 ## 展開結果に含まれる制御文字をエスケープします。 function ble/prompt/.initialize-constant { - local __ps=$1 __defeval=$2 __opts=$3 + local _ble_local_ps=$1 + local _ble_local_defeval=$2 + local _ble_local_opts=$3 if ((_ble_bash>=40400)); then - ret=${__ps@P} + ret=${_ble_local_ps@P} else - builtin eval -- "$__defeval" + builtin eval -- "$_ble_local_defeval" fi - if [[ $__opts == *:escape:* ]]; then + if [[ $_ble_local_opts == *:escape:* ]]; then if ((_ble_bash>=50200)); then # bash-5.2 以上では bash が escape を行うが、反転などの処理が実 # 装されていないので、制御文字が含まれている場合には ble.sh の側 # で処理を行う。 if [[ $ret == *\^['A'-'Z[\]^_?']* ]]; then - builtin eval -- "$__defeval" + builtin eval -- "$_ble_local_defeval" ble/prompt/.escape-control-characters "$ret" elif [[ $ret == *$'\t'* ]]; then ble/prompt/.escape-control-characters "$ret" @@ -1676,11 +1678,11 @@ function _ble_prompt_update__eval_prompt_command_1 { ble/function#trace _ble_prompt_update__eval_prompt_command_1 function ble/prompt/update/.eval-prompt_command { ((${#PROMPT_COMMAND[@]})) || return 0 - local _command _ble_edit_exec_TRAPDEBUG_adjusted=1 + local _ble_local_command _ble_edit_exec_TRAPDEBUG_adjusted=1 ble-edit/exec:gexec/.TRAPDEBUG/restore filter - for _command in "${PROMPT_COMMAND[@]}"; do - [[ $_command ]] || continue - _ble_prompt_update__eval_prompt_command_1 "$_command" + for _ble_local_command in "${PROMPT_COMMAND[@]}"; do + [[ $_ble_local_command ]] || continue + _ble_prompt_update__eval_prompt_command_1 "$_ble_local_command" done _ble_edit_exec_gexec__TRAPDEBUG_adjust } @@ -3006,12 +3008,12 @@ function ble/textarea#render/.determine-scroll { if ((height=6&&_nline>_height+2?2:1)) + local rheight=$((height-begy)) rnline=$((nline-begy)) rcy=$((cy-begy)) + local margin=$((rheight>=6&&rnline>rheight+2?2:1)) local smin smax - ((smin=_cy-_height+margin, + ((smin=rcy-rheight+margin, smin>nline-height&&(smin=nline-height), - smax=_cy-margin, + smax=rcy-margin, smax<0&&(smax=0))) if ((scroll>smax)); then scroll=$smax @@ -5569,21 +5571,21 @@ function ble/widget/backward-line { ## @fn ble/edit/word:uword/setup ## @fn ble/edit/word:sword/setup ## @fn ble/edit/word:fword/setup -## @var[out] WSET WSEP +## @var[out] word_set word_sep function ble/edit/word:eword/setup { - WSET='a-zA-Z0-9'; WSEP="^$WSET" + word_set='a-zA-Z0-9'; word_sep="^$word_set" } function ble/edit/word:cword/setup { - WSET='_a-zA-Z0-9'; WSEP="^$WSET" + word_set='_a-zA-Z0-9'; word_sep="^$word_set" } function ble/edit/word:uword/setup { - WSEP="$_ble_term_IFS"; WSET="^$WSEP" + word_sep="$_ble_term_IFS"; word_set="^$word_sep" } function ble/edit/word:sword/setup { - WSEP=$'|&;()<> \t\n'; WSET="^$WSEP" + word_sep=$'|&;()<> \t\n'; word_set="^$word_sep" } function ble/edit/word:fword/setup { - WSEP="/$_ble_term_IFS"; WSET="^$WSEP" + word_sep="/$_ble_term_IFS"; word_set="^$word_sep" } ## @fn ble/edit/word/skip-backward set @@ -5603,7 +5605,7 @@ function ble/edit/word/skip-forward { ## @fn ble/edit/word/locate-backward x arg ## 左側の単語の範囲を特定します。 ## @param[in] x arg -## @var[in] WSET WSEP +## @var[in] word_set word_sep ## @var[out] a b c ## ## |---|www|---| @@ -5612,15 +5614,15 @@ function ble/edit/word/skip-forward { function ble/edit/word/locate-backward { local x=${1:-$_ble_edit_ind} arg=${2:-1} while ((arg--)); do - ble/edit/word/skip-backward "$WSET"; c=$x - ble/edit/word/skip-backward "$WSEP"; b=$x + ble/edit/word/skip-backward "$word_set"; c=$x + ble/edit/word/skip-backward "$word_sep"; b=$x done - ble/edit/word/skip-backward "$WSET"; a=$x + ble/edit/word/skip-backward "$word_set"; a=$x } ## @fn ble/edit/word/locate-forward x arg ## 右側の単語の範囲を特定します。 ## @param[in] x arg -## @var[in] WSET WSEP +## @var[in] word_set word_sep ## @var[out] s t u ## ## |---|www|---| @@ -5629,10 +5631,10 @@ function ble/edit/word/locate-backward { function ble/edit/word/locate-forward { local x=${1:-$_ble_edit_ind} arg=${2:-1} while ((arg--)); do - ble/edit/word/skip-forward "$WSET"; s=$x - ble/edit/word/skip-forward "$WSEP"; t=$x + ble/edit/word/skip-forward "$word_set"; s=$x + ble/edit/word/skip-forward "$word_sep"; t=$x done - ble/edit/word/skip-forward "$WSET"; u=$x + ble/edit/word/skip-forward "$word_set"; u=$x } ## @fn ble/edit/word/forward-range arg @@ -5674,7 +5676,7 @@ function ble/widget/word.impl { local operator=$1 direction=$2 wtype=$3 local arg; ble-edit/content/get-arg 1 - local WSET WSEP; ble/edit/word:"$wtype"/setup + local word_set word_sep; ble/edit/word:"$wtype"/setup local x=$_ble_edit_ind y=$_ble_edit_ind ble/function#try ble/edit/word/"$direction"-range "$arg" @@ -5705,32 +5707,32 @@ function ble/widget/word.impl { function ble/widget/transpose-words.impl1 { local wtype=$1 arg=$2 - local WSET WSEP; ble/edit/word:"$wtype"/setup + local word_set word_sep; ble/edit/word:"$wtype"/setup if ((arg==0)); then local x=$_ble_edit_ind - ble/edit/word/skip-forward "$WSET" - ble/edit/word/skip-forward "$WSEP"; local e1=$x - ble/edit/word/skip-backward "$WSEP"; local b1=$x + ble/edit/word/skip-forward "$word_set" + ble/edit/word/skip-forward "$word_sep"; local e1=$x + ble/edit/word/skip-backward "$word_sep"; local b1=$x local x=$_ble_edit_mark - ble/edit/word/skip-forward "$WSET" - ble/edit/word/skip-forward "$WSEP"; local e2=$x - ble/edit/word/skip-backward "$WSEP"; local b2=$x + ble/edit/word/skip-forward "$word_set" + ble/edit/word/skip-forward "$word_sep"; local e2=$x + ble/edit/word/skip-backward "$word_sep"; local b2=$x else local x=$_ble_edit_ind - ble/edit/word/skip-backward "$WSET" - ble/edit/word/skip-backward "$WSEP"; local b1=$x - ble/edit/word/skip-forward "$WSEP"; local e1=$x + ble/edit/word/skip-backward "$word_set" + ble/edit/word/skip-backward "$word_sep"; local b1=$x + ble/edit/word/skip-forward "$word_sep"; local e1=$x if ((arg>0)); then x=$e1 - ble/edit/word/skip-forward "$WSET"; local b2=$x - while ble/edit/word/skip-forward "$WSEP" || return 1; ((--arg>0)); do - ble/edit/word/skip-forward "$WSET" + ble/edit/word/skip-forward "$word_set"; local b2=$x + while ble/edit/word/skip-forward "$word_sep" || return 1; ((--arg>0)); do + ble/edit/word/skip-forward "$word_set" done; local e2=$x else x=$b1 - ble/edit/word/skip-backward "$WSET"; local e2=$x - while ble/edit/word/skip-backward "$WSEP" || return 1; ((++arg<0)); do - ble/edit/word/skip-backward "$WSET" + ble/edit/word/skip-backward "$word_set"; local e2=$x + while ble/edit/word/skip-backward "$word_sep" || return 1; ((++arg<0)); do + ble/edit/word/skip-backward "$word_set" done; local b2=$x fi fi @@ -5767,7 +5769,7 @@ function ble/widget/filter-word.impl { local arg; ble-edit/content/get-arg 1 fi - local WSET WSEP; ble/edit/word:"$xword"/setup + local word_set word_sep; ble/edit/word:"$xword"/setup local x=$_ble_edit_ind s t u ble/edit/word/locate-forward "$x" "$arg" if ((x==t)); then diff --git a/src/history.sh b/src/history.sh index a43479a4..15e7144a 100644 --- a/src/history.sh +++ b/src/history.sh @@ -551,7 +551,7 @@ if ((_ble_bash>=30100)); then ## 各行は '#%s' または 'コマンド' の形式をしている。 ## ble.sh では先頭行が '#%s' の時の複数行モードには対応しない。 ## - ## @var[in] TMPBASE + ## @var[in] tmpfile_base function ble/history:bash/resolve-multiline/.awk { if ((_ble_bash>=50000)); then local -x epoch=$EPOCHSECONDS @@ -569,7 +569,7 @@ if ((_ble_bash>=30100)); then reason = ENVIRON["reason"]; is_resolve = reason == "resolve"; - TMPBASE = ENVIRON["TMPBASE"]; + TMPBASE = ENVIRON["tmpfile_base"]; filename_source = TMPBASE ".part"; if (is_resolve) print "builtin history -c" > filename_source @@ -713,26 +713,26 @@ if ((_ble_bash>=30100)); then ' } ## @fn ble/history:bash/resolve-multiline/.cleanup - ## @var[in] TMPBASE + ## @var[in] tmpfile_base function ble/history:bash/resolve-multiline/.cleanup { local file - for file in "$TMPBASE".*; do : >| "$file"; done + for file in "$tmpfile_base".*; do : >| "$file"; done } function ble/history:bash/resolve-multiline/.worker { local HISTTIMEFORMAT=__ble_time_%s__ - local -x TMPBASE=$_ble_base_run/$$.history.mlfix + local -x tmpfile_base=$_ble_base_run/$$.history.mlfix local multiline_count=0 modification_count=0 builtin eval -- "$(ble/builtin/history/.dump | ble/history:bash/resolve-multiline/.awk resolve 2>/dev/null)" if ((modification_count)); then - ble/bin/mv -f "$TMPBASE.part" "$TMPBASE.sh" + ble/bin/mv -f "$tmpfile_base.part" "$tmpfile_base.sh" else - ble/util/print : >| "$TMPBASE.sh" + ble/util/print : >| "$tmpfile_base.sh" fi } function ble/history:bash/resolve-multiline/.load { - local TMPBASE=$_ble_base_run/$$.history.mlfix + local tmpfile_base=$_ble_base_run/$$.history.mlfix local HISTCONTROL= HISTSIZE= HISTIGNORE= - source "$TMPBASE.sh" + source "$tmpfile_base.sh" ble/history:bash/resolve-multiline/.cleanup } @@ -832,9 +832,9 @@ if ((_ble_bash>=30100)); then function ble/history:bash/resolve-multiline/readfile { local filename=$1 - local -x TMPBASE=$_ble_base_run/$$.history.read + local -x tmpfile_base=$_ble_base_run/$$.history.read ble/history:bash/resolve-multiline/.awk read < "$filename" &>/dev/null - source "$TMPBASE.part" + source "$tmpfile_base.part" ble/history:bash/resolve-multiline/.cleanup } else @@ -1929,37 +1929,37 @@ function ble/history/initialize { ble/history:bash/initialize } function ble/history/get-count { - local _var=count _ret - [[ $1 == -v ]] && { _var=$2; shift 2; } + local _ble_local_var=count + [[ $1 == -v ]] && { _ble_local_var=$2; shift 2; } ble/history/.update-position - (($_var=_ble_history_COUNT)) + (($_ble_local_var=_ble_history_COUNT)) } function ble/history/get-index { - local _var=index - [[ $1 == -v ]] && { _var=$2; shift 2; } + local _ble_local_var=index + [[ $1 == -v ]] && { _ble_local_var=$2; shift 2; } ble/history/.update-position - (($_var=_ble_history_INDEX)) + (($_ble_local_var=_ble_history_INDEX)) } function ble/history/set-index { _ble_history_INDEX=$1 ((${_ble_history_prefix:-_ble}_history_index=_ble_history_INDEX)) } function ble/history/get-entry { - local __var=entry - [[ $1 == -v ]] && { __var=$2; shift 2; } + local _ble_local_var=entry + [[ $1 == -v ]] && { _ble_local_var=$2; shift 2; } if [[ $_ble_history_prefix$_ble_history_load_done ]]; then - builtin eval -- "$__var=\${${_ble_history_prefix:-_ble}_history[\$1]}" + builtin eval -- "$_ble_local_var=\${${_ble_history_prefix:-_ble}_history[\$1]}" else - builtin eval -- "$__var=" + builtin eval -- "$_ble_local_var=" fi } function ble/history/get-edited-entry { - local __var=entry - [[ $1 == -v ]] && { __var=$2; shift 2; } + local _ble_local_var=entry + [[ $1 == -v ]] && { _ble_local_var=$2; shift 2; } if [[ $_ble_history_prefix$_ble_history_load_done ]]; then - builtin eval -- "$__var=\${${_ble_history_prefix:-_ble}_history_edit[\$1]}" + builtin eval -- "$_ble_local_var=\${${_ble_history_prefix:-_ble}_history_edit[\$1]}" else - builtin eval -- "$__var=\$_ble_edit_str" + builtin eval -- "$_ble_local_var=\$_ble_edit_str" fi } ## @fn ble/history/set-edited-entry index str @@ -2136,8 +2136,8 @@ function ble/history/isearch-backward-blockwise { builtin eval "_ble_history_edit=(\"\${${_ble_history_prefix}_history_edit[@]}\")" fi - local NSTPCHK=1000 # 十分高速なのでこれぐらい大きくてOK - local NPROGRESS=$((NSTPCHK*2)) # 倍数である必要有り + local isearch_block=1000 # 十分高速なのでこれぐらい大きくてOK + local isearch_quantum=$((isearch_block*2)) # 倍数である必要有り local irest block j i=$index index= @@ -2156,7 +2156,7 @@ function ble/history/isearch-backward-blockwise { ((block=range_max-i, block<5&&(block=5), block>i+1-range_min&&(block=i+1-range_min), - irest=NSTPCHK-isearch_time%NSTPCHK, + irest=isearch_block-isearch_time%isearch_block, block>irest&&(block=irest))) [[ $flag_icase ]] && shopt -s nocasematch @@ -2194,10 +2194,10 @@ function ble/history/isearch-backward-blockwise { [[ $index ]] && return 0 ((i-=block)) - if ((has_stop_check&&isearch_time%NSTPCHK==0)) && ble/decode/has-input; then + if ((has_stop_check&&isearch_time%isearch_block==0)) && ble/decode/has-input; then index=$i return 148 - elif ((has_progress&&isearch_time%NPROGRESS==0)); then + elif ((has_progress&&isearch_time%isearch_quantum==0)); then "$isearch_progress_callback" "$i" fi done diff --git a/src/util.sh b/src/util.sh index fa0b9ffc..fb66bef9 100644 --- a/src/util.sh +++ b/src/util.sh @@ -404,22 +404,22 @@ else fi function ble/util/save-vars { - local __name __prefix=$1; shift - for __name; do - if ble/is-array "$__name"; then - builtin eval "$__prefix$__name=(\"\${$__name[@]}\")" + local __ble_name __ble_prefix=$1; shift + for __ble_name; do + if ble/is-array "$__ble_name"; then + builtin eval "$__ble_prefix$__ble_name=(\"\${$__ble_name[@]}\")" else - builtin eval "$__prefix$__name=\"\$$__name\"" + builtin eval "$__ble_prefix$__ble_name=\"\$$__ble_name\"" fi done } function ble/util/restore-vars { - local __name __prefix=$1; shift - for __name; do - if ble/is-array "$__prefix$__name"; then - builtin eval "$__name=(\"\${$__prefix$__name[@]}\")" + local __ble_name __ble_prefix=$1; shift + for __ble_name; do + if ble/is-array "$__ble_prefix$__ble_name"; then + builtin eval "$__ble_name=(\"\${$__ble_prefix$__ble_name[@]}\")" else - builtin eval "$__name=\"\$$__prefix$__name\"" + builtin eval "$__ble_name=\"\$$__ble_prefix$__ble_name\"" fi done } @@ -466,7 +466,7 @@ function ble/is-transformed { ble/variable#has-attr "$1" luc; } function ble/variable#is-declared { [[ ${!1+set} ]] || declare -p "$1" &>/dev/null; } function ble/variable#is-global/.test { ! local "$1"; } function ble/variable#is-global { - (readonly "$1"; ble/variable#is-global/.test "$1") 2>/dev/null + (builtin readonly "$1"; ble/variable#is-global/.test "$1") 2>/dev/null } function ble/variable#copy-state { local src=$1 dst=$2 @@ -3049,7 +3049,7 @@ function ble/util/for-global-variables { # we can test if the visible variable is global or not by using # `(readonly var; ! local var)' because `local var' succeeds if the # visible variable is local readonly. - if readonly "$__ble_name"; ble/variable#is-global/.test "$__ble_name"; then + if builtin readonly "$__ble_name"; ble/variable#is-global/.test "$__ble_name"; then __ble_found=1 [[ $__ble_hidden_only && $__ble_i == 0 ]] || "$__ble_proc" "$__ble_name" @@ -3593,18 +3593,18 @@ function ble/util/conditional-sync/.collect-descendant-pids { } ## @fn ble/util/conditional-sync/.kill -## @var __pid -## @var __opts +## @var __ble_pid +## @var __ble_opts function ble/util/conditional-sync/.kill { local kill_pids - if [[ :$__opts: == *:killall:* ]]; then - ble/util/conditional-sync/.collect-descendant-pids "$__pid" + if [[ :$__ble_opts: == *:killall:* ]]; then + ble/util/conditional-sync/.collect-descendant-pids "$__ble_pid" kill_pids=("${ret[@]}") else - kill_pids=("$__pid") + kill_pids=("$__ble_pid") fi - if [[ :$__opts: == *:SIGKILL:* ]]; then + if [[ :$__ble_opts: == *:SIGKILL:* ]]; then builtin kill -9 "${kill_pids[@]}" &>/dev/null else builtin kill "${kill_pids[@]}" &>/dev/null @@ -3646,45 +3646,45 @@ function ble/util/conditional-sync/.kill { ## processes are killed by SIGTERM. ## function ble/util/conditional-sync { - local __command=$1 - local __continue=${2:-'! ble/decode/has-input'} - local __weight=$3; ((__weight<=0&&(__weight=100))) - local __opts=$4 + local __ble_command=$1 + local __ble_continue=${2:-'! ble/decode/has-input'} + local __ble_weight=$3; ((__ble_weight<=0&&(__ble_weight=100))) + local __ble_opts=$4 - local __timeout= __rex=':timeout=([^:]+):' - [[ :$__opts: =~ $__rex ]] && ((__timeout=BASH_REMATCH[1])) + local __ble_timeout= __ble_rex=':timeout=([^:]+):' + [[ :$__ble_opts: =~ $__ble_rex ]] && ((__ble_timeout=BASH_REMATCH[1])) - [[ :$__opts: == *:progressive-weight:* ]] && - local __weight_max=$__weight __weight=1 + [[ :$__ble_opts: == *:progressive-weight:* ]] && + local __ble_weight_max=$__ble_weight __ble_weight=1 local sync_elapsed=0 - [[ $__timeout ]] && ((__timeout<=0)) && return 142 - builtin eval -- "$__continue" || return 148 + [[ $__ble_timeout ]] && ((__ble_timeout<=0)) && return 142 + builtin eval -- "$__ble_continue" || return 148 ( - builtin eval -- "$__command" & local __pid=$! + builtin eval -- "$__ble_command" & local __ble_pid=$! while # check timeout - if [[ $__timeout ]]; then - if ((__timeout<=0)); then + if [[ $__ble_timeout ]]; then + if ((__ble_timeout<=0)); then ble/util/conditional-sync/.kill return 142 fi - ((__weight>__timeout)) && __weight=$__timeout - ((__timeout-=__weight)) + ((__ble_weight>__ble_timeout)) && __ble_weight=$__ble_timeout + ((__ble_timeout-=__ble_weight)) fi - ble/util/msleep "$__weight" - ((sync_elapsed+=__weight)) - [[ :$__opts: == *:progressive-weight:* ]] && - ((__weight<<=1,__weight>__weight_max&&(__weight=__weight_max))) - builtin kill -0 "$__pid" &>/dev/null + ble/util/msleep "$__ble_weight" + ((sync_elapsed+=__ble_weight)) + [[ :$__ble_opts: == *:progressive-weight:* ]] && + ((__ble_weight<<=1,__ble_weight>__ble_weight_max&&(__ble_weight=__ble_weight_max))) + builtin kill -0 "$__ble_pid" &>/dev/null do - if ! builtin eval -- "$__continue"; then + if ! builtin eval -- "$__ble_continue"; then ble/util/conditional-sync/.kill return 148 fi done - wait "$__pid" + wait "$__ble_pid" ) } @@ -3870,25 +3870,25 @@ function ble/util/buffer.clear { # class dirty-range, urange function ble/dirty-range#load { - local _prefix= + local prefix= if [[ $1 == --prefix=* ]]; then - _prefix=${1#--prefix=} - ((beg=${_prefix}beg, - end=${_prefix}end, - end0=${_prefix}end0)) + prefix=${1#--prefix=} + ((beg=${prefix}beg, + end=${prefix}end, + end0=${prefix}end0)) fi } function ble/dirty-range#clear { - local _prefix= + local prefix= if [[ $1 == --prefix=* ]]; then - _prefix=${1#--prefix=} + prefix=${1#--prefix=} shift fi - ((${_prefix}beg=-1, - ${_prefix}end=-1, - ${_prefix}end0=-1)) + ((${prefix}beg=-1, + ${prefix}end=-1, + ${prefix}end0=-1)) } ## @fn ble/dirty-range#update [--prefix=PREFIX] beg end end0 @@ -3897,18 +3897,18 @@ function ble/dirty-range#clear { ## @param[in] end 変更終了点。end<0 は変更が末端までである事を表す ## @param[in] end0 変更前の end に対応する位置。 function ble/dirty-range#update { - local _prefix= + local prefix= if [[ $1 == --prefix=* ]]; then - _prefix=${1#--prefix=} + prefix=${1#--prefix=} shift - [[ $_prefix ]] && local beg end end0 + [[ $prefix ]] && local beg end end0 fi local begB=$1 endB=$2 endB0=$3 ((begB<0)) && return 1 local begA endA endA0 - ((begA=${_prefix}beg,endA=${_prefix}end,endA0=${_prefix}end0)) + ((begA=${prefix}beg,endA=${prefix}end,endA0=${prefix}end0)) local delta if ((begA<0)); then @@ -3925,10 +3925,10 @@ function ble/dirty-range#update { fi fi - if [[ $_prefix ]]; then - ((${_prefix}beg=beg, - ${_prefix}end=end, - ${_prefix}end0=end0)) + if [[ $prefix ]]; then + ((${prefix}beg=beg, + ${prefix}end=end, + ${prefix}end0=end0)) fi } @@ -4770,7 +4770,7 @@ function ble/util/clock/.initialize { local now=$EPOCHREALTIME [[ $now == *.???* && $now != $EPOCHREALTIME ]]; }; then # implementation with EPOCHREALTIME - readonly EPOCHREALTIME + builtin readonly EPOCHREALTIME _ble_util_clock_base=$((10#0${now%.*})) _ble_util_clock_reso=1 _ble_util_clock_type=EPOCHREALTIME @@ -4808,7 +4808,7 @@ function ble/util/clock/.initialize { ((ret=(now-_ble_util_clock_base)*1000)) } elif [[ $SECONDS && ! ${SECONDS//[0-9]} ]]; then - readonly SECONDS + builtin readonly SECONDS _ble_util_clock_base=$SECONDS _ble_util_clock_reso=1000 _ble_util_clock_type=SECONDS @@ -4965,117 +4965,117 @@ if ((_ble_bash>=40000)); then ble/util/idle.clock/.initialize ble/util/idle.clock/.restart ble/util/idle.clock - local _idle_clock_start=$ret - local _idle_sclock_start=$_ble_util_idle_sclock - local _idle_is_first=1 - local _idle_processed= - local _idle_info_shown= - local _idle_after_task=0 + local _ble_idle_clock_start=$ret + local _ble_idle_sclock_start=$_ble_util_idle_sclock + local _ble_idle_is_first=1 + local _ble_idle_processed= + local _ble_idle_info_shown= + local _ble_idle_after_task=0 while :; do - local _idle_key - local _idle_next_time= _idle_next_itime= _idle_running= _idle_waiting= - for _idle_key in "${!_ble_util_idle_task[@]}"; do + local _ble_idle_key + local _ble_idle_next_time= _ble_idle_next_itime= _ble_idle_running= _ble_idle_waiting= + for _ble_idle_key in "${!_ble_util_idle_task[@]}"; do ble/util/idle/IS_IDLE || break 2 - local _idle_to_process= - local _idle_status=${_ble_util_idle_task[_idle_key]%%"$_ble_util_idle_SEP"*} - case ${_idle_status::1} in - (R) _idle_to_process=1 ;; - (I) [[ $_idle_is_first ]] && _idle_to_process=1 ;; - (S) ble/util/idle/.check-clock "$_idle_status" && _idle_to_process=1 ;; - (W) ble/util/idle/.check-clock "$_idle_status" && _idle_to_process=1 ;; - (F) [[ -s ${_idle_status:1} ]] && _idle_to_process=1 ;; - (E) [[ -e ${_idle_status:1} ]] && _idle_to_process=1 ;; - (P) ! builtin kill -0 ${_idle_status:1} &>/dev/null && _idle_to_process=1 ;; - (C) builtin eval -- "${_idle_status:1}" && _idle_to_process=1 ;; + local _ble_idle_to_process= + local _ble_idle_status=${_ble_util_idle_task[_ble_idle_key]%%"$_ble_util_idle_SEP"*} + case ${_ble_idle_status::1} in + (R) _ble_idle_to_process=1 ;; + (I) [[ $_ble_idle_is_first ]] && _ble_idle_to_process=1 ;; + (S) ble/util/idle/.check-clock "$_ble_idle_status" && _ble_idle_to_process=1 ;; + (W) ble/util/idle/.check-clock "$_ble_idle_status" && _ble_idle_to_process=1 ;; + (F) [[ -s ${_ble_idle_status:1} ]] && _ble_idle_to_process=1 ;; + (E) [[ -e ${_ble_idle_status:1} ]] && _ble_idle_to_process=1 ;; + (P) ! builtin kill -0 ${_ble_idle_status:1} &>/dev/null && _ble_idle_to_process=1 ;; + (C) builtin eval -- "${_ble_idle_status:1}" && _ble_idle_to_process=1 ;; (Z) ;; - (*) builtin unset -v '_ble_util_idle_task[_idle_key]' + (*) builtin unset -v '_ble_util_idle_task[_ble_idle_key]' esac - if [[ $_idle_to_process ]]; then - local _idle_command=${_ble_util_idle_task[_idle_key]#*"$_ble_util_idle_SEP"} - _idle_processed=1 - ble/util/idle.do/.call-task "$_idle_command" + if [[ $_ble_idle_to_process ]]; then + local _ble_idle_command=${_ble_util_idle_task[_ble_idle_key]#*"$_ble_util_idle_SEP"} + _ble_idle_processed=1 + ble/util/idle.do/.call-task "$_ble_idle_command" - # Note: #D1450 _idle_command が 148 を返したとしても idle.do は中断し - # ない事にした。IS_IDLE と条件が同じとは限らないので。 - #((ext==148)) && return 0 + # Note: #D1450 _ble_idle_command が 148 を返したとしても idle.do は中 + # 断しない事にした。IS_IDLE と条件が同じとは限らないので。 + # ((ext==148)) && return 0 - ((_idle_after_task++)) - elif [[ $_idle_status == [FEPC]* ]]; then - _idle_waiting=1 + ((_ble_idle_after_task++)) + elif [[ $_ble_idle_status == [FEPC]* ]]; then + _ble_idle_waiting=1 fi done - _idle_is_first= + _ble_idle_is_first= ble/util/idle.do/.sleep-until-next; local ext=$? ((ext==148)) && break - [[ $_idle_next_itime$_idle_next_time$_idle_running$_idle_waiting ]] || break + [[ $_ble_idle_next_itime$_ble_idle_next_time$_ble_idle_running$_ble_idle_waiting ]] || break done - [[ $_idle_info_shown ]] && + [[ $_ble_idle_info_shown ]] && ble/edit/info/immediate-default ble/util/idle.do/.do-after-task - [[ $_idle_processed ]] + [[ $_ble_idle_processed ]] } ## @fn ble/util/idle.do/.do-after-task - ## @var[ref] _idle_after_task + ## @var[ref] _ble_idle_after_task function ble/util/idle.do/.do-after-task { - if ((_idle_after_task)); then + if ((_ble_idle_after_task)); then # 50ms 以上の待機時間があれば再描画などの処理を試行する。 blehook/invoke idle_after_task - _idle_after_task=0 + _ble_idle_after_task=0 fi } ## @fn ble/util/idle.do/.call-task command - ## @var[in,out] _idle_next_time - ## @var[in,out] _idle_next_itime - ## @var[in,out] _idle_running - ## @var[in,out] _idle_waiting + ## @var[in,out] _ble_idle_next_time + ## @var[in,out] _ble_idle_next_itime + ## @var[in,out] _ble_idle_running + ## @var[in,out] _ble_idle_waiting function ble/util/idle.do/.call-task { - local _command=$1 + local _ble_local_command=$1 local ble_util_idle_status= - local ble_util_idle_elapsed=$((_ble_util_idle_sclock-_idle_sclock_start)) - if [[ $bleopt_debug_idle && ( $_ble_edit_info_scene == default || $_idle_info_shown ) ]]; then - _idle_info_shown=1 - ble/edit/info/immediate-show text "${EPOCHREALTIME:+[$EPOCHREALTIME] }idle: $_command" + local ble_util_idle_elapsed=$((_ble_util_idle_sclock-_ble_idle_sclock_start)) + if [[ $bleopt_debug_idle && ( $_ble_edit_info_scene == default || $_ble_idle_info_shown ) ]]; then + _ble_idle_info_shown=1 + ble/edit/info/immediate-show text "${EPOCHREALTIME:+[$EPOCHREALTIME] }idle: $_ble_local_command" fi - builtin eval -- "$_command"; local ext=$? + builtin eval -- "$_ble_local_command"; local ext=$? if ((ext==148)); then - _ble_util_idle_task[_idle_key]=R$_ble_util_idle_SEP$_command + _ble_util_idle_task[_ble_idle_key]=R$_ble_util_idle_SEP$_ble_local_command elif [[ $ble_util_idle_status ]]; then - _ble_util_idle_task[_idle_key]=$ble_util_idle_status$_ble_util_idle_SEP$_command + _ble_util_idle_task[_ble_idle_key]=$ble_util_idle_status$_ble_util_idle_SEP$_ble_local_command if [[ $ble_util_idle_status == [WS]* ]]; then local scheduled_time=${ble_util_idle_status:1} if [[ $ble_util_idle_status == W* ]]; then - local next=_idle_next_itime + local next=_ble_idle_next_itime else - local next=_idle_next_time + local next=_ble_idle_next_time fi if [[ ! ${!next} ]] || ((scheduled_time=40000)); then return 1 } ## @fn ble/util/idle.do/.sleep-until-next - ## @var[in] _idle_next_time - ## @var[in] _idle_next_itime - ## @var[in] _idle_running - ## @var[in] _idle_waiting + ## @var[in] _ble_idle_next_time + ## @var[in] _ble_idle_next_itime + ## @var[in] _ble_idle_running + ## @var[in] _ble_idle_waiting function ble/util/idle.do/.sleep-until-next { ble/util/idle/IS_IDLE || return 148 - [[ $_idle_running ]] && return 0 + [[ $_ble_idle_running ]] && return 0 local isfirst=1 while # ファイル等他の条件を待っている時は一回だけで外に戻り確認する状態確認 - [[ $_idle_waiting && ! $isfirst ]] && break + [[ $_ble_idle_waiting && ! $isfirst ]] && break local sleep_amount= - if [[ $_idle_next_itime ]]; then + if [[ $_ble_idle_next_itime ]]; then local clock=$_ble_util_idle_sclock - local sleep1=$((_idle_next_itime-clock)) + local sleep1=$((_ble_idle_next_itime-clock)) if [[ ! $sleep_amount ]] || ((sleep1=40000)); then do # Note: 変数 ble_util_idle_elapsed は # $((bleopt_idle_interval)) の評価時に参照される。 - local ble_util_idle_elapsed=$((_ble_util_idle_sclock-_idle_sclock_start)) + local ble_util_idle_elapsed=$((_ble_util_idle_sclock-_ble_idle_sclock_start)) # sleep_amount が十分に長い場合に idle_after_task が必要あれば実行する ((sleep_amount>50)) && ble/util/idle.do/.do-after-task @@ -5862,13 +5862,13 @@ _ble_term_TERM_done= ## @var[out] _ble_term_TERM function ble/term/DA2/initialize-term { local depth=$1 - local DA2R=${_ble_term_DA2R[depth]} - local rex='^[0-9]*(;[0-9]*)*$'; [[ $DA2R =~ $rex ]] || return 1 - local da2r - ble/string#split da2r ';' "$DA2R" - da2r=("${da2r[@]/#/10#0}") # 0で始まっていても10進数で解釈; WA #D1570 checked (is-array) + local da2r=${_ble_term_DA2R[depth]} + local rex='^[0-9]*(;[0-9]*)*$'; [[ $da2r =~ $rex ]] || return 1 + local da2r_vec + ble/string#split da2r_vec ';' "$da2r" + da2r_vec=("${da2r_vec[@]/#/10#0}") # 0で始まっていても10進数で解釈; WA #D1570 checked (is-array) - case $DA2R in + case $da2r in # Note #D1946: Terminology は xterm と区別が付かないが決め打ちの様なので、丁 # 度 xterm の該当 version を使っている可能性は低いと見て、取り敢えず # terminology と判断する事にする。 @@ -5887,19 +5887,19 @@ function ble/term/DA2/initialize-term { # https://github.com/microsoft/terminal/blob/bcc38d04/src/terminal/adapter/adaptDispatch.cpp#L779-L782 _ble_term_TERM[depth]=wt:0 ;; ('0;'*';1') - if ((da2r[1]>=1001)); then + if ((da2r_vec[1]>=1001)); then # Alacritty # https://github.com/alacritty/alacritty/blob/4734b2b8/alacritty_terminal/src/term/mod.rs#L1315 # https://github.com/alacritty/alacritty/blob/4734b2b8/alacritty_terminal/src/term/mod.rs#L3104 - _ble_term_TERM[depth]=alacritty:$((da2r[1])) + _ble_term_TERM[depth]=alacritty:$((da2r_vec[1])) fi ;; ('1;0'?????';0') - _ble_term_TERM[depth]=foot:${DA2R:3:5} ;; + _ble_term_TERM[depth]=foot:${da2r:3:5} ;; ('1;'*) - if ((4000<=da2r[1]&&da2r[1]<=4009&&3<=da2r[2])); then - _ble_term_TERM[depth]=kitty:$((da2r[1]-4000)) - elif ((2000<=da2r[1]&&da2r[1]<5400&&da2r[2]==0)); then - local version=$((da2r[1])) + if ((4000<=da2r_vec[1]&&da2r_vec[1]<=4009&&3<=da2r_vec[2])); then + _ble_term_TERM[depth]=kitty:$((da2r_vec[1]-4000)) + elif ((2000<=da2r_vec[1]&&da2r_vec[1]<5400&&da2r_vec[2]==0)); then + local version=$((da2r_vec[1])) _ble_term_TERM[depth]=vte:$version if ((version<4000)); then # Note #D1785: vte 0.40.0 未満では DECSCUSR に対応していない。更に未知のシーケ @@ -5910,39 +5910,39 @@ function ble/term/DA2/initialize-term { fi fi ;; ('65;'*) - if ((5300<=da2r[1]&&da2r[2]==1)); then - _ble_term_TERM[depth]=vte:$((da2r[1])) - elif ((da2r[1]>=100)); then - _ble_term_TERM[depth]=RLogin:$((da2r[1])) + if ((5300<=da2r_vec[1]&&da2r_vec[2]==1)); then + _ble_term_TERM[depth]=vte:$((da2r_vec[1])) + elif ((da2r_vec[1]>=100)); then + _ble_term_TERM[depth]=RLogin:$((da2r_vec[1])) fi ;; ('67;'*) local rex='^67;[0-9]{3,};0$' - if [[ $TERM == cygwin && $DA2R =~ $rex ]]; then - _ble_term_TERM[depth]=cygwin:$((da2r[1])) + if [[ $TERM == cygwin && $da2r =~ $rex ]]; then + _ble_term_TERM[depth]=cygwin:$((da2r_vec[1])) fi ;; ('77;'*';0') - _ble_term_TERM[depth]=mintty:$((da2r[1])) ;; + _ble_term_TERM[depth]=mintty:$((da2r_vec[1])) ;; ('83;'*) local rex='^83;[0-9]+;0$' - [[ $DA2R =~ $rex ]] && _ble_term_TERM[depth]=screen:$((da2r[1])) ;; + [[ $da2r =~ $rex ]] && _ble_term_TERM[depth]=screen:$((da2r_vec[1])) ;; ('84;0;0') _ble_term_TERM[depth]=tmux:0 ;; ('99;'*) - _ble_term_TERM[depth]=contra:$((da2r[1])) ;; + _ble_term_TERM[depth]=contra:$((da2r_vec[1])) ;; esac [[ ${_ble_term_TERM[depth]} ]] && return 0 # xterm if rex='^xterm(-|$)'; [[ $TERM =~ $rex ]]; then - local version=$((da2r[1])) - if rex='^1;[0-9]+;0$'; [[ $DA2R =~ $rex ]]; then + local version=$((da2r_vec[1])) + if rex='^1;[0-9]+;0$'; [[ $da2r =~ $rex ]]; then # Note: vte (2000以上), kitty (4000以上) は処理済み true - elif rex='^0;[0-9]+;0$'; [[ $DA2R =~ $rex ]]; then + elif rex='^0;[0-9]+;0$'; [[ $da2r =~ $rex ]]; then ((95<=version)) - elif rex='^(2|24|1[89]|41|6[145]);[0-9]+;0$'; [[ $DA2R =~ $rex ]]; then + elif rex='^(2|24|1[89]|41|6[145]);[0-9]+;0$'; [[ $da2r =~ $rex ]]; then ((280<=version)) - elif rex='^32;[0-9]+;0$'; [[ $DA2R =~ $rex ]]; then + elif rex='^32;[0-9]+;0$'; [[ $da2r =~ $rex ]]; then ((354<=version&&version<2000)) else false @@ -6120,9 +6120,9 @@ function ble/term/modifyOtherKeys/.update { case $_ble_term_TERM in (RLogin:*) method=RLogin_modifyStringKeys ;; (kitty:*) - local da2r - ble/string#split da2r ';' "$_ble_term_DA2R" - if ((da2r[2]>=23)); then + local da2r_vec + ble/string#split da2r_vec ';' "$_ble_term_DA2R" + if ((da2r_vec[2]>=23)); then method=kitty_keyboard_protocol else method=kitty_modifyOtherKeys @@ -6135,9 +6135,9 @@ function ble/term/modifyOtherKeys/.update { # send keyboard-protocol sequences to the outermost kitty. local index=$((${#_ble_term_TERM[*]}-1)) if [[ ${_ble_term_TERM[index]} == kitty:* ]]; then - local da2r - ble/string#split da2r ';' "${_ble_term_DA2R[index]}" - ((da2r[2]>=23)) && method=kitty_keyboard_protocol + local da2r_vec + ble/string#split da2r_vec ';' "${_ble_term_DA2R[index]}" + ((da2r_vec[2]>=23)) && method=kitty_keyboard_protocol fi fi ;; (*) @@ -6787,3 +6787,118 @@ function ble/encoding:C/c2b { local code=$1 bytes=("$((code&0xFF))") } + +#------------------------------------------------------------------------------ +# builtin readonly + +_ble_builtin_readonly_message= +builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_builtin_readonly_blacklist}" + +function ble/builtin/readonly/.initialize-blacklist { + function ble/builtin/readonly/.initialize-blacklist { return 0; } + + local -a list=() + + # Bash variables ble.sh uses + ble/array#push list FUNCNEST IFS IGNOREEOF POSIXLY_CORRECT TMOUT # adjust + ble/array#push list PWD OLDPWD CDPATH # readlink + ble/array#push list BASHPID GLOBIGNORE MAPFILE REPLY # util + ble/array#push list INPUTRC # decode + ble/array#push list LINES COLUMNS # canvas + ble/array#push list HIST{CONTROL,IGNORE,SIZE,TIMEFORMAT} # history + ble/array#push list PROMPT_COMMAND PS1 # prompt + ble/array#push list BASH_COMMAND BASH_REMATCH HISTCMD LINENO PIPESTATUS TIMEFORMAT # exec + ble/array#push list BASH_XTRACEFD PS4 # debug + + # Other common variables that ble.sh uses + ble/array#push list CC LESS MANOPT MANPAGER PAGER PATH MANPATH + + # Other uppercase variables that ble.sh internally uses in each module + ble/array#push list BUFF # util + ble/array#push list KEYS KEYMAP WIDGET LASTWIDGET # decode + ble/array#push list DRAW_BUFF # canvas + ble/array#push list D{MIN,MAX,MAX0} {HIGHLIGHT,PREV}_{BUFF,UMAX,UMIN} LEVEL LAYER_{UMAX,UMIN} # color + ble/array#push list HISTINDEX_NEXT FILE LINE INDEX INDEX_FILE # history + ble/array#push list ARG FLAG REG # vi + ble/array#push list COMP{1,2,S,V} ACTION CAND DATA INSERT PREFIX_LEN # core-complete + + local v + for v in "${list[@]}"; do ble/gdict#set _ble_builtin_readonly_blacklist "$v" 1; done +} +function ble/builtin/readonly/.check-variable-name { + # Local variables are always allowed to make readonly. Note: this + # implementation does not block propagating tempenv variables being + # propagated to the global context. There is no way to reliably detect the + # tempenv variables. + ble/variable#is-global "$1" || return 0 + + # If the variable starts with "_" but does not start with "_ble", it could be + # a global variable used by another framework. We allow such namespaced + # variables being readonly. + if [[ $1 == _* && $1 != _ble* && $1 != __ble* ]]; then + return 0 + fi + + # These special variables should not be made readonly. + case $1 in + (?) return 1;; # single character variables + (BLE_*|ADVICE_*) return 1;; # ble.sh variables + (COMP_*|COMPREPLY) return 1;; # completion variables + (READLINE_*) return 1;; # readline variables + (LC_*|LANG) return 1;; # locale variables + esac + + # If the variable name is in the black list, the variable cannot be readonly. + ble/builtin/readonly/.initialize-blacklist + if ble/gdict#get _ble_builtin_readonly_blacklist; then + return 1 + fi + + # Otherwise, the variables that do not contain lowercase characters are + # allowed to become readonly. + if [[ $1 != *[a-z]* ]] && ! ; then + return 0 + fi + + return 1 +} +function ble/builtin/readonly { + local _ble_local_flags= + local -a _ble_local_options=() + while (($#)); do + if ble/string#match "$1" '^([_a-zA-Z][_a-zA-Z0-9]*)($|=)'; then + _ble_local_flags=v$_ble_local_flags + local _ble_local_var=${BASH_REMATCH[1]} + if [[ ${BASH_REMATCH[2]} == = ]]; then + ble/util/sprintf "$_ble_local_var" "${1#*=}" + fi + + if ble/builtin/readonly/.check-variable-name "$_ble_local_var"; then + _ble_local_flags=r$_ble_local_flags + ble/array#push _ble_local_options "$_ble_local_var" + else + # We show messages only up to ten times + if ((_ble_builtin_readonly_message<10)) && [[ -t 2 ]]; then + ((++_ble_builtin_readonly_message)) + _ble_local_flags=w$_ble_local_flags + ble/util/print "ble.sh: An attempt to make variable \`$1' readonly was blocked." >&2 + fi + fi + else + ble/array#push _ble_local_options "$1" + fi + shift + done + + if [[ $_ble_local_flags == *w* ]]; then + ble/util/print 'ble.sh: The global variables with unprefixed lowercase names or special names should not be made readonly. It can break arbitrary Bash configurations.' >&2 + fi + if [[ $_ble_local_flags != *v* || $_ble_local_flags == *r* ]]; then + # We call `builtin readonly' only when no variables are specified + # (e.g. readonly, readonly --help), or at least one variable are allowed to + # become readonly. + builtin readonly "${_ble_local_options[@]}" + fi +} + +function readonly { ble/builtin/readonly "$@"; }