ble.pp (88385B)
1 #!/bin/bash 2 #%$> out/ble.sh 3 #%[release = 0] 4 #%[measure_load_time = 0] 5 #%[debug_keylogger = 1] 6 #%[leakvar = ""] 7 #%#---------------------------------------------------------------------------- 8 #%if measure_load_time 9 _ble_debug_measure_fork_count=$(echo $BASHPID) 10 TIMEFORMAT='[Elapsed %Rs; CPU U:%Us S:%Ss (%P%%)]' 11 function ble/debug/measure-set-timeformat { 12 local title=$1 opts=$2 13 local new=$(echo $BASHPID) 14 local fork=$(((new-_ble_debug_measure_fork_count-1)&0xFFFF)) 15 _ble_debug_measure_fork_count=$new 16 TIMEFORMAT="[Elapsed %Rs; CPU U:%Us S:%Ss (%P%%)] $title" 17 [[ :$opts: != *:nofork:* ]] && 18 TIMEFORMAT=$TIMEFORMAT" ($fork forks)" 19 } 20 #%end 21 #%if leakvar 22 #%%expand 23 $"leakvar"=__t1wJltaP9nmow__ 24 #%%end.i 25 function ble/bin/grep { command grep "$@"; } 26 function ble/util/print { printf '%s\n' "$1"; } 27 source "${BASH_SOURCE%/*}/lib/core-debug.sh" 28 #%end 29 #%define inc 30 #%%[guard_name = "@_included".replace("[^_a-zA-Z0-9]", "_")] 31 #%%expand 32 #%%%if $"guard_name" != 1 33 #%%%%[$"guard_name" = 1] 34 ############################################################################### 35 # Included from @.sh 36 37 #%%%%if leakvar 38 ble/debug/leakvar#check $"leakvar" "[before include @.sh]" 39 #%%%%end.i 40 #%%%%if measure_load_time 41 time { 42 #%%%%%include @.sh 43 ble/debug/measure-set-timeformat '@.sh' 44 } 45 #%%%%else 46 #%%%%%include @.sh 47 #%%%%end 48 #%%%%if leakvar 49 ble/debug/leakvar#check $"leakvar" "[after include @.sh]" 50 #%%%%end.i 51 #%%%end 52 #%%end.i 53 #%end 54 #%#---------------------------------------------------------------------------- 55 # ble.sh -- Bash Line Editor (https://github.com/akinomyoga/ble.sh) 56 # 57 # Bash configuration designed to be sourced in interactive bash sessions. 58 # 59 # Copyright: 2013, 2015-2019, Koichi Murase <myoga.murase@gmail.com> 60 # 61 62 #%if measure_load_time 63 echo "ble.sh: $EPOCHREALTIME load start" >&2 64 time { 65 echo "ble.sh: $EPOCHREALTIME parsed" >&2 66 # load_time (2015-12-03) 67 # core 12ms 68 # decode 10ms 69 # color 2ms 70 # edit 9ms 71 # syntax 5ms 72 # ble-initialize 14ms 73 time { 74 #%end 75 #------------------------------------------------------------------------------ 76 # check --help or --version 77 78 { 79 #%[commit_hash = system("git show -s --format=%h")] 80 #%[ble_version = getenv("FULLVER") + "+" + commit_hash] 81 #%expand 82 ##%if commit_hash != "" 83 _ble_init_version=$"ble_version" 84 ##%else 85 ###%error Failed to get the commit id (version = $"ble_version"). 86 ##%end 87 #%end.i 88 _ble_init_exit= 89 _ble_init_command= 90 for _ble_init_arg; do 91 case $_ble_init_arg in 92 --version) 93 _ble_init_exit=0 94 echo "ble.sh (Bash Line Editor), version $_ble_init_version" ;; 95 --help) 96 _ble_init_exit=0 97 printf '%s\n' \ 98 "# ble.sh (Bash Line Editor), version $_ble_init_version" \ 99 'usage: source ble.sh [OPTION...]' \ 100 '' \ 101 'OPTION' \ 102 '' \ 103 ' --help' \ 104 ' Show this help and exit' \ 105 ' --version' \ 106 ' Show version and exit' \ 107 ' --test' \ 108 ' Run test and exit' \ 109 ' --update' \ 110 ' Update ble.sh and exit' \ 111 ' --clear-cache' \ 112 ' Clear ble.sh cache and exit' \ 113 '' \ 114 ' --rcfile=BLERC' \ 115 ' --init-file=BLERC' \ 116 ' Specify the ble init file. The default is ~/.blerc if any, or' \ 117 ' ~/.config/blesh/init.sh.' \ 118 '' \ 119 ' --norc' \ 120 ' Do not load the ble init file.' \ 121 '' \ 122 ' --attach=ATTACH' \ 123 ' --noattach' \ 124 ' The option "--attach" selects the strategy of "ble-attach" from the list:' \ 125 ' ATTACH = "attach" | "prompt" | "none". The default strategy is "prompt".' \ 126 ' When "attach" is specified, ble.sh immediately attaches to the session in' \ 127 ' "source ble.sh". When "prompt" is specified, ble.sh attaches to the' \ 128 ' session before the first prompt using PROMPT_COMMAND. When "none" is' \ 129 ' specified, ble.sh does not attach to the session automatically, so' \ 130 ' ble-attach needs to be called explicitly. The option "--noattach" is a' \ 131 ' synonym for "--attach=none".' \ 132 '' \ 133 ' --inputrc=TYPE' \ 134 ' --noinputrc' \ 135 ' The option "--inputrc" selects the strategy of reconstructing user' \ 136 ' keybindings from the list: "auto" (default), "diff", "all", "user", "none".' \ 137 ' When "diff" is specified, user keybindings are extracted by the diff of the' \ 138 ' outputs of the "bind" builtin between the current session and the plain' \ 139 ' Bash. When "all" is specified, the user keybindings are extracted from' \ 140 ' /etc/inputrc and ${INPUTRC:-~/.inputrc*}. When "user" is specified, the' \ 141 ' user keybindings are extracted from ${INPUTRC:-~/.inputrc*}. When "none"' \ 142 ' is specified, the user keybindings are not reconstructed from the state of' \ 143 ' Readline, and only the bindings by "ble-bind" are applied. The option' \ 144 ' "--noinputrc" is a synonym for "--inputrc=none".' \ 145 '' \ 146 ' --keep-rlvars' \ 147 ' Do not change readline settings for ble.sh' \ 148 '' \ 149 ' -o BLEOPT=VALUE' \ 150 ' Set a value for the specified bleopt option.' \ 151 ' --debug-bash-output' \ 152 ' Internal settings for debugging' \ 153 '' ;; 154 --test | --update | --clear-cache | --lib) _ble_init_command=1 ;; 155 esac 156 done 157 if [ -n "$_ble_init_exit" ]; then 158 unset _ble_init_version 159 unset _ble_init_arg 160 unset _ble_init_exit 161 unset _ble_init_command 162 return 0 2>/dev/null || exit 0 163 fi 164 } 2>/dev/null # set -x 対策 #D0930 165 166 #------------------------------------------------------------------------------ 167 # check shell 168 169 if [ -z "${BASH_VERSION-}" ]; then 170 echo "ble.sh: This shell is not Bash. Please use this script with Bash." >&3 171 return 1 2>/dev/null || exit 1 172 fi 3>&2 >/dev/null 2>&1 # set -x 対策 #D0930 173 174 if [ -z "${BASH_VERSINFO-}" ] || [ "${BASH_VERSINFO-0}" -lt 3 ]; then 175 echo "ble.sh: Bash with a version under 3.0 is not supported." >&3 176 return 1 2>/dev/null || exit 1 177 fi 3>&2 >/dev/null 2>&1 # set -x 対策 #D0930 178 179 if [[ ! $_ble_init_command ]]; then 180 if [[ ${BASH_EXECUTION_STRING+set} ]]; then 181 # builtin echo "ble.sh: ble.sh will not be activated for Bash started with '-c' option." >&3 182 return 1 2>/dev/null || builtin exit 1 183 fi 184 185 if ((BASH_SUBSHELL)); then 186 builtin echo "ble.sh: ble.sh cannot be loaded into a subshell." >&3 187 return 1 2>/dev/null || builtin exit 1 188 elif [[ $- != *i* ]]; then 189 case " ${BASH_SOURCE[*]##*/} " in 190 (*' .bashrc '* | *' .bash_profile '* | *' .profile '* | *' bashrc '* | *' profile '*) ((0)) ;; 191 esac && 192 builtin echo "ble.sh: This is not an interactive session." >&3 || ((1)) 193 return 1 2>/dev/null || builtin exit 1 194 elif ! [[ -t 4 && -t 5 ]] && ! ((1)) >/dev/tty; then 195 builtin echo "ble.sh: cannot find a controlling TTY/PTY in this session." >&3 196 return 1 2>/dev/null || builtin exit 1 197 fi 198 fi 3>&2 4<&0 5>&1 &>/dev/null # set -x 対策 #D0930 199 200 { 201 ## @var _ble_bash_POSIXLY_CORRECT_adjusted 202 ## 現在 POSIXLY_CORRECT 状態を待避した状態かどうかを保持します。 203 ## @var _ble_bash_POSIXLY_CORRECT_set 204 ## 待避した POSIXLY_CORRECT の設定・非設定状態を保持します。 205 ## @var _ble_bash_POSIXLY_CORRECT_set 206 ## 待避した POSIXLY_CORRECT の値を保持します。 207 _ble_bash_POSIXLY_CORRECT_adjusted=1 208 _ble_bash_POSIXLY_CORRECT_set=${POSIXLY_CORRECT+set} 209 _ble_bash_POSIXLY_CORRECT=${POSIXLY_CORRECT-} 210 211 POSIXLY_CORRECT=y 212 213 # 暫定対策 expand_aliases (ble/base/adjust-bash-options を呼び出す迄の暫定) 214 _ble_bash_expand_aliases= 215 \shopt -q expand_aliases && 216 _ble_bash_expand_aliases=1 && 217 \shopt -u expand_aliases || ((1)) 218 219 # 対策 FUNCNEST 220 _ble_bash_FUNCNEST_adjusted= 221 _ble_bash_FUNCNEST= 222 _ble_bash_FUNCNEST_set= 223 _ble_bash_FUNCNEST_adjust=' 224 if [[ ! $_ble_bash_FUNCNEST_adjusted ]]; then 225 _ble_bash_FUNCNEST_adjusted=1 226 _ble_bash_FUNCNEST_set=${FUNCNEST+set} 227 _ble_bash_FUNCNEST=${FUNCNEST-} 228 builtin unset -v FUNCNEST 229 fi 2>/dev/null' 230 _ble_bash_FUNCNEST_restore=' 231 if [[ $_ble_bash_FUNCNEST_adjusted ]]; then 232 _ble_bash_FUNCNEST_adjusted= 233 if [[ $_ble_bash_FUNCNEST_set ]]; then 234 FUNCNEST=$_ble_bash_FUNCNEST 235 else 236 builtin unset -v FUNCNEST 237 fi 238 fi 2>/dev/null' 239 \builtin eval -- "$_ble_bash_FUNCNEST_adjust" 240 241 \builtin unset -v POSIXLY_CORRECT 242 } 2>/dev/null 243 244 function ble/base/workaround-POSIXLY_CORRECT { 245 # This function will be overwritten by ble-decode 246 true 247 } 248 function ble/base/unset-POSIXLY_CORRECT { 249 if [[ ${POSIXLY_CORRECT+set} ]]; then 250 builtin unset -v POSIXLY_CORRECT 251 ble/base/workaround-POSIXLY_CORRECT 252 fi 253 } 254 function ble/base/adjust-POSIXLY_CORRECT { 255 if [[ $_ble_bash_POSIXLY_CORRECT_adjusted ]]; then return 0; fi # Note: set -e 対策 256 _ble_bash_POSIXLY_CORRECT_adjusted=1 257 _ble_bash_POSIXLY_CORRECT_set=${POSIXLY_CORRECT+set} 258 _ble_bash_POSIXLY_CORRECT=${POSIXLY_CORRECT-} 259 if [[ $_ble_bash_POSIXLY_CORRECT_set ]]; then 260 builtin unset -v POSIXLY_CORRECT 261 fi 262 263 # ユーザが触ったかもしれないので何れにしても workaround を呼び出す。 264 ble/base/workaround-POSIXLY_CORRECT 265 } 266 function ble/base/restore-POSIXLY_CORRECT { 267 if [[ ! $_ble_bash_POSIXLY_CORRECT_adjusted ]]; then return 0; fi # Note: set -e の為 || は駄目 268 _ble_bash_POSIXLY_CORRECT_adjusted= 269 if [[ $_ble_bash_POSIXLY_CORRECT_set ]]; then 270 POSIXLY_CORRECT=$_ble_bash_POSIXLY_CORRECT 271 else 272 ble/base/unset-POSIXLY_CORRECT 273 fi 274 } 275 function ble/base/is-POSIXLY_CORRECT { 276 if [[ $_ble_bash_POSIXLY_CORRECT_adjusted ]]; then 277 [[ $_ble_bash_POSIXLY_CORRECT_set ]] 278 else 279 [[ ${POSIXLY_CORRECT+set} ]] 280 fi 281 } 282 283 { 284 _ble_bash_builtins_adjusted= 285 _ble_bash_builtins_save= 286 } 2>/dev/null # set -x 対策 287 ## @fn ble/base/adjust-builtin-wrappers/.assign 288 ## @remarks This function may be called with POSIXLY_CORRECT=y 289 function ble/base/adjust-builtin-wrappers/.assign { 290 if [[ ${_ble_util_assign_base-} ]]; then 291 local _ble_local_tmpfile; ble/util/assign/mktmp 292 builtin eval -- "$1" >| "$_ble_local_tmpfile" 293 local IFS= 294 ble/bash/read -d '' defs < "$_ble_local_tmpfile" 295 IFS=$_ble_term_IFS 296 ble/util/assign/rmtmp 297 else 298 defs=$(builtin eval -- "$1") 299 fi || ((1)) 300 } 301 function ble/base/adjust-builtin-wrappers-1 { 302 # Note: 何故か local POSIXLY_CORRECT の効果が 303 # builtin unset -v POSIXLY_CORRECT しても残存するので関数に入れる。 304 # Note: set -o posix にしても read, type, builtin, local 等は上書き 305 # された儘なので難しい。unset -f builtin さえすれば色々動く様になる 306 # ので builtin は unset -f builtin してしまう。 307 unset -f builtin 308 builtin local POSIXLY_CORRECT=y builtins1 keywords1 309 builtins1=(builtin unset enable unalias return break continue declare local typeset eval exec set) 310 keywords1=(if then elif else case esac while until for select do done '{' '}' '[[' function) 311 if [[ ! $_ble_bash_builtins_adjusted ]]; then 312 _ble_bash_builtins_adjusted=1 313 314 builtin local defs 315 ble/base/adjust-builtin-wrappers/.assign ' 316 \builtin declare -f "${builtins1[@]}" || ((1)) 317 \builtin alias "${builtins1[@]}" "${keywords1[@]}" || ((1))' # set -e 対策 318 _ble_bash_builtins_save=$defs 319 fi 320 builtin unset -f "${builtins1[@]}" 321 builtin unalias "${builtins1[@]}" "${keywords1[@]}" || ((1)) # set -e 対策 322 ble/base/unset-POSIXLY_CORRECT 323 } 2>/dev/null 324 function ble/base/adjust-builtin-wrappers-2 { 325 # Workaround (bash-3.0..4.3) #D0722 326 # 327 # builtin unset -v POSIXLY_CORRECT でないと unset -f : できないが、 328 # bash-3.0 -- 4.3 のバグで、local POSIXLY_CORRECT の時、 329 # builtin unset -v POSIXLY_CORRECT しても POSIXLY_CORRECT が有効であると判断されるので、 330 # "unset -f :" (非POSIX関数名) は別関数で adjust-POSIXLY_CORRECT の後で実行することにする。 331 332 # function :, alias : の保存 333 local defs 334 ble/base/adjust-builtin-wrappers/.assign 'LC_ALL= LC_MESSAGES=C builtin type :; alias :' || ((1)) # set -e 対策 335 defs=${defs#$': is a function\n'} 336 _ble_bash_builtins_save=$_ble_bash_builtins_save$'\n'$defs 337 338 builtin unset -f : 339 builtin unalias : || ((1)) # set -e 対策 340 } 2>/dev/null 341 function ble/base/restore-builtin-wrappers { 342 if [[ $_ble_bash_builtins_adjusted ]]; then 343 _ble_bash_builtins_adjusted= 344 builtin eval -- "$_ble_bash_builtins_save" 345 fi 346 } 347 { 348 ble/base/adjust-builtin-wrappers-1 349 ble/base/adjust-builtin-wrappers-2 350 351 # 対策 expand_aliases (暫定) 終了 352 if [[ $_ble_bash_expand_aliases ]]; then 353 shopt -s expand_aliases 354 fi 355 } 2>/dev/null # set -x 対策 356 357 # From src/util.sh 358 function ble/variable#copy-state { 359 local src=$1 dst=$2 360 if [[ ${!src+set} ]]; then 361 builtin eval -- "$dst=\${$src}" 362 else 363 builtin unset -v "$dst[0]" 2>/dev/null || builtin unset -v "$dst" 364 fi 365 } 366 367 # BASH_XTRACEFD は書き換えると勝手に元々設定されていた fd を閉じてしまうので、 368 # 元々の fd を dup しておくなど特別な配慮が必要。 369 { 370 _ble_bash_xtrace=() 371 _ble_bash_xtrace_debug_enabled= 372 _ble_bash_xtrace_debug_filename= 373 _ble_bash_xtrace_debug_fd= 374 _ble_bash_XTRACEFD= 375 _ble_bash_XTRACEFD_set= 376 _ble_bash_XTRACEFD_dup= 377 _ble_bash_PS4= 378 } 2>/dev/null # set -x 対策 379 # From src/util.sh (ble/fd#is-open and ble/fd#alloc/.nextfd) 380 function ble/base/xtrace/.fdcheck { builtin : >&"$1"; } 2>/dev/null 381 function ble/base/xtrace/.fdnext { 382 local _ble_local_init=${_ble_util_openat_nextfd:=${bleopt_openat_base:-30}} 383 for (($1=_ble_local_init;$1<_ble_local_init+1024;$1++)); do 384 ble/base/xtrace/.fdcheck "${!1}" || break 385 done 386 (($1<_ble_local_init+1024)) || 387 { (($1=_ble_local_init,_ble_util_openat_nextfd++)); builtin eval "exec ${!1}>&-"; } || 388 ((1)) 389 } 390 function ble/base/xtrace/.log { 391 local bash=${_ble_bash:-$((BASH_VERSINFO[0]*10000+BASH_VERSINFO[1]*100+BASH_VERSINFO[2]))} 392 local open=---- close=---- 393 if ((bash>=40200)); then 394 builtin printf '%s [%(%F %T %Z)T] %s %s\n' "$open" -1 "$1" "$close" 395 else 396 builtin printf '%s [%s] %s %s\n' "$open" "$(date 2>/dev/null)" "$1" "$close" 397 fi >&"${BASH_XTRACEFD:-2}" 398 } 399 function ble/base/xtrace/adjust { 400 local level=${#_ble_bash_xtrace[@]} IFS=$' \t\n' 401 if [[ $- == *x* ]]; then 402 _ble_bash_xtrace[level]=1 403 else 404 _ble_bash_xtrace[level]= 405 fi 406 set +x 407 408 ((level==0)) || return 0 409 _ble_bash_xtrace_debug_enabled= 410 if [[ ${bleopt_debug_xtrace:-/dev/null} == /dev/null ]]; then 411 if [[ $_ble_bash_xtrace_debug_fd ]]; then 412 builtin eval "exec $_ble_bash_xtrace_debug_fd>&-" || return 0 413 _ble_bash_xtrace_debug_filename= 414 _ble_bash_xtrace_debug_fd= 415 fi 416 else 417 if [[ $_ble_bash_xtrace_debug_filename != "$bleopt_debug_xtrace" ]]; then 418 _ble_bash_xtrace_debug_filename=$bleopt_debug_xtrace 419 [[ $_ble_bash_xtrace_debug_fd ]] || ble/base/xtrace/.fdnext _ble_bash_xtrace_debug_fd 420 builtin eval "exec $_ble_bash_xtrace_debug_fd>>\"$bleopt_debug_xtrace\"" || return 0 421 fi 422 423 _ble_bash_XTRACEFD=${BASH_XTRACEFD-} 424 _ble_bash_XTRACEFD_set=${BASH_XTRACEFD+set} 425 if [[ ${BASH_XTRACEFD-} =~ ^[0-9]+$ ]] && ble/base/xtrace/.fdcheck "$BASH_XTRACEFD"; then 426 ble/base/xtrace/.fdnext _ble_bash_XTRACEFD_dup 427 builtin eval "exec $_ble_bash_XTRACEFD_dup>&$BASH_XTRACEFD" || return 0 428 builtin eval "exec $BASH_XTRACEFD>&$_ble_bash_xtrace_debug_fd" || return 0 429 else 430 _ble_bash_XTRACEFD_dup= 431 local newfd; ble/base/xtrace/.fdnext newfd 432 builtin eval "exec $newfd>&$_ble_bash_xtrace_debug_fd" || return 0 433 BASH_XTRACEFD=$newfd 434 fi 435 436 ble/variable#copy-state PS4 _ble_base_PS4 437 PS4=${bleopt_debug_xtrace_ps4:-'+ '} 438 439 _ble_bash_xtrace_debug_enabled=1 440 ble/base/xtrace/.log "$FUNCNAME" 441 set -x 442 fi 443 } 444 function ble/base/xtrace/restore { 445 local level=$((${#_ble_bash_xtrace[@]}-1)) IFS=$' \t\n' 446 ((level>=0)) || return 0 447 if [[ ${_ble_bash_xtrace[level]-} ]]; then 448 set -x 449 else 450 set +x 451 fi 452 builtin unset -v '_ble_bash_xtrace[level]' 453 454 ((level==0)) || return 0 455 if [[ $_ble_bash_xtrace_debug_enabled ]]; then 456 ble/base/xtrace/.log "$FUNCNAME" 457 _ble_bash_xtrace_debug_enabled= 458 459 # Note: ユーザーの BASH_XTRACEFD にごみが混入しない様にする為、 460 # BASH_XTRACEFD を書き換える前に先に PS4 を戻す。 461 ble/variable#copy-state _ble_base_PS4 PS4 462 463 if [[ $_ble_bash_XTRACEFD_dup ]]; then 464 # BASH_XTRACEFD の fd を元の出力先に繋ぎ直す 465 builtin eval "exec $BASH_XTRACEFD>&$_ble_bash_XTRACEFD_dup" && 466 builtin eval "exec $_ble_bash_XTRACEFD_dup>&-" || ((1)) 467 else 468 # BASH_XTRACEFD の fd は新しく割り当てた fd なので値上書きで閉じて良い 469 if [[ $_ble_bash_XTRACEFD_set ]]; then 470 BASH_XTRACEFD=$_ble_bash_XTRACEFD 471 else 472 builtin unset -v BASH_XTRACEFD 473 fi 474 fi 475 fi 476 } 477 478 function ble/base/.adjust-bash-options { 479 builtin eval -- "$1=\$-" 480 set +evukT -B 481 ble/base/xtrace/adjust 482 483 [[ $2 == shopt ]] || local shopt 484 if ((_ble_bash>=40100)); then 485 shopt=$BASHOPTS 486 else 487 # Note: nocasematch は bash-3.1 以上 488 shopt= 489 shopt -q extdebug 2>/dev/null && shopt=$shopt:extdebug 490 shopt -q nocasematch 2>/dev/null && shopt=$shopt:nocasematch 491 fi 492 [[ $2 == shopt ]] || builtin eval -- "$2=\$shopt" 493 shopt -u extdebug 494 shopt -u nocasematch 2>/dev/null 495 return 0 496 } 2>/dev/null # set -x 対策 497 ## @fn ble/base/.restore-bash-options var_set var_shopt 498 ## @param[out] var_set var_shopt 499 function ble/base/.restore-bash-options { 500 local set=${!1} shopt=${!2} 501 [[ :$shopt: == *:nocasematch:* ]] && shopt -s nocasematch 502 [[ :$shopt: == *:extdebug:* ]] && shopt -s extdebug 503 ble/base/xtrace/restore 504 [[ $set == *B* ]] || set +B 505 [[ $set == *T* ]] && set -T 506 [[ $set == *k* ]] && set -k 507 [[ $set == *u* ]] && set -u 508 [[ $set == *v* ]] && set -v 509 [[ $set == *e* ]] && set -e # set -e は最後 510 return 0 511 } 2>/dev/null # set -x 対策 512 513 { 514 : "${_ble_bash_options_adjusted=}" 515 _ble_bash_set=$- 516 _ble_bash_shopt=${BASHOPTS-} 517 } 2>/dev/null # set -x 対策 518 function ble/base/adjust-bash-options { 519 [[ $_ble_bash_options_adjusted ]] && return 1 || ((1)) # set -e 対策 520 _ble_bash_options_adjusted=1 521 522 ble/base/.adjust-bash-options _ble_bash_set _ble_bash_shopt 523 524 # Note: expand_aliases はユーザー設定を復元する為に記録する 525 _ble_bash_expand_aliases= 526 shopt -q expand_aliases 2>/dev/null && 527 _ble_bash_expand_aliases=1 528 529 # locale 待避 530 # Note #D1854: ble/widget/display-shell-version で此処で待避した変数を参照す 531 # る事に注意する。此処に新しい変数を追加する時は display-shell-version の方 532 # にも処理スキップを追加する必要がある。 533 ble/variable#copy-state LC_ALL _ble_bash_LC_ALL 534 if [[ ${LC_ALL-} ]]; then 535 ble/variable#copy-state LC_CTYPE _ble_bash_LC_CTYPE 536 ble/variable#copy-state LC_MESSAGES _ble_bash_LC_MESSAGES 537 ble/variable#copy-state LC_NUMERIC _ble_bash_LC_NUMERIC 538 ble/variable#copy-state LC_TIME _ble_bash_LC_TIME 539 ble/variable#copy-state LANG _ble_bash_LANG 540 [[ ${LC_CTYPE-} ]] && LC_CTYPE=$LC_ALL 541 [[ ${LC_MESSAGES-} ]] && LC_MESSAGES=$LC_ALL 542 [[ ${LC_NUMERIC-} ]] && LC_NUMERIC=$LC_ALL 543 [[ ${LC_TIME-} ]] && LC_TIME=$LC_ALL 544 LANG=$LC_ALL 545 LC_ALL= 546 fi 547 ble/variable#copy-state LC_COLLATE _ble_bash_LC_COLLATE 548 LC_COLLATE=C 549 550 # TMOUT 確認 #D1630 WA readonly TMOUT 551 if local TMOUT= 2>/dev/null; then # #D1630 WA 552 _ble_bash_tmout_wa=() 553 else 554 _ble_bash_tmout_wa=(-t 2147483647) 555 fi 556 } 2>/dev/null # set -x 対策 #D0930 / locale 変更 557 function ble/base/restore-bash-options { 558 [[ $_ble_bash_options_adjusted ]] || return 1 559 _ble_bash_options_adjusted= 560 561 # locale 復元 562 ble/variable#copy-state _ble_bash_LC_COLLATE LC_COLLATE 563 if [[ $_ble_bash_LC_ALL ]]; then 564 ble/variable#copy-state _ble_bash_LC_CTYPE LC_CTYPE 565 ble/variable#copy-state _ble_bash_LC_MESSAGES LC_MESSAGES 566 ble/variable#copy-state _ble_bash_LC_NUMERIC LC_NUMERIC 567 ble/variable#copy-state _ble_bash_LC_TIME LC_TIME 568 ble/variable#copy-state _ble_bash_LANG LANG 569 fi 570 ble/variable#copy-state _ble_bash_LC_ALL LC_ALL 571 572 [[ $_ble_bash_nocasematch ]] && shopt -s nocasematch 573 574 ble/base/.restore-bash-options _ble_bash_set _ble_bash_shopt 575 } 2>/dev/null # set -x 対策 #D0930 / locale 変更 576 function ble/base/recover-bash-options { 577 # bind -x が終わる度に設定が復元されてしまうので毎回設定し直す #D1526 #D1574 578 if [[ $_ble_bash_expand_aliases ]]; then 579 shopt -s expand_aliases 580 else 581 shopt -u expand_aliases 582 fi 583 } 584 585 { ble/base/adjust-bash-options; } &>/dev/null # set -x 対策 #D0930 586 587 builtin bind &>/dev/null # force to load .inputrc 588 589 # WA #D1534 workaround for msys2 .inputrc 590 if [[ $OSTYPE == msys* ]]; then 591 [[ $(builtin bind -m emacs -p 2>/dev/null | grep '"\\C-?"') == '"\C-?": backward-kill-line' ]] && 592 builtin bind -m emacs '"\C-?": backward-delete-char' 2>/dev/null 593 fi 594 595 if [[ ! -o emacs && ! -o vi && ! $_ble_init_command ]]; then 596 builtin echo "ble.sh: ble.sh is not intended to be used with the line-editing mode disabled (--noediting)." >&2 597 ble/base/restore-bash-options 598 ble/base/restore-builtin-wrappers 599 ble/base/restore-POSIXLY_CORRECT 600 builtin eval -- "$_ble_bash_FUNCNEST_restore" 601 return 1 2>/dev/null || builtin exit 1 602 fi 603 604 if shopt -q restricted_shell; then 605 builtin echo "ble.sh: ble.sh is not intended to be used in restricted shells (--restricted)." >&2 606 ble/base/restore-bash-options 607 ble/base/restore-builtin-wrappers 608 ble/base/restore-POSIXLY_CORRECT 609 builtin eval -- "$_ble_bash_FUNCNEST_restore" 610 return 1 2>/dev/null || builtin exit 1 611 fi 612 613 #-------------------------------------- 614 # save IFS / BASH_REMATCH 615 616 function ble/init/adjust-IFS { 617 _ble_init_original_IFS_set=${IFS+set} 618 _ble_init_original_IFS=$IFS 619 IFS=$' \t\n' 620 } 621 function ble/init/restore-IFS { 622 if [[ $_ble_init_original_IFS_set ]]; then 623 IFS=$_ble_init_original_IFS 624 else 625 builtin unset -v IFS 626 fi 627 builtin unset -v _ble_init_original_IFS_set 628 builtin unset -v _ble_init_original_IFS 629 } 630 631 if ((_ble_bash>=50100)); then 632 _ble_bash_BASH_REMATCH_level=0 633 _ble_bash_BASH_REMATCH=() 634 function ble/base/adjust-BASH_REMATCH { 635 ((_ble_bash_BASH_REMATCH_level++==0)) || return 0 636 _ble_bash_BASH_REMATCH=("${BASH_REMATCH[@]}") 637 } 638 function ble/base/restore-BASH_REMATCH { 639 ((_ble_bash_BASH_REMATCH_level>0&& 640 --_ble_bash_BASH_REMATCH_level==0)) || return 0 641 BASH_REMATCH=("${_ble_bash_BASH_REMATCH[@]}") 642 } 643 644 else 645 _ble_bash_BASH_REMATCH_level=0 646 _ble_bash_BASH_REMATCH=() 647 _ble_bash_BASH_REMATCH_rex=none 648 649 ## @fn ble/base/adjust-BASH_REMATCH/increase delta 650 ## @param[in] delta 651 ## @var[in,out] i rex 652 function ble/base/adjust-BASH_REMATCH/increase { 653 local delta=$1 654 ((delta)) || return 1 655 ((i+=delta)) 656 if ((delta==1)); then 657 rex=$rex. 658 else 659 rex=$rex.{$delta} 660 fi 661 } 662 function ble/base/adjust-BASH_REMATCH/is-updated { 663 local i n=${#_ble_bash_BASH_REMATCH[@]} 664 ((n!=${#BASH_REMATCH[@]})) && return 0 665 for ((i=0;i<n;i++)); do 666 [[ ${_ble_bash_BASH_REMATCH[i]} != "${BASH_REMATCH[i]}" ]] && return 0 667 done 668 return 1 669 } 670 # This is a simplified version of ble/string#index-of text sub 671 function ble/base/adjust-BASH_REMATCH/.find-substr { 672 local t=${1#*"$2"} 673 ((ret=${#1}-${#t}-${#2},ret<0&&(ret=-1),ret>=0)) 674 } 675 function ble/base/adjust-BASH_REMATCH { 676 ((_ble_bash_BASH_REMATCH_level++==0)) || return 0 677 ble/base/adjust-BASH_REMATCH/is-updated || return 1 678 679 local size=${#BASH_REMATCH[@]} 680 if ((size==0)); then 681 _ble_bash_BASH_REMATCH=() 682 _ble_bash_BASH_REMATCH_rex=none 683 return 0 684 fi 685 686 local rex= i=0 687 local text=$BASH_REMATCH sub ret isub 688 689 local -a rparens=() 690 local isub rex i=0 count=0 691 for ((isub=1;isub<size;isub++)); do 692 local sub=${BASH_REMATCH[isub]} 693 694 # 既存の子一致の孫一致になるか確認 695 while ((count>=1)); do 696 local end=${rparens[count-1]} 697 if ble/base/adjust-BASH_REMATCH/.find-substr "${text:i:end-i}" "$sub"; then 698 ble/base/adjust-BASH_REMATCH/increase "$ret" 699 ((rparens[count++]=i+${#sub})) 700 rex=$rex'(' 701 break 702 else 703 ble/base/adjust-BASH_REMATCH/increase "$((end-i))" 704 rex=$rex')' 705 builtin unset -v 'rparens[--count]' 706 fi 707 done 708 709 ((count>0)) && continue 710 711 # 新しい子一致 712 if ble/base/adjust-BASH_REMATCH/.find-substr "${text:i}" "$sub"; then 713 ble/base/adjust-BASH_REMATCH/increase "$ret" 714 ((rparens[count++]=i+${#sub})) 715 rex=$rex'(' 716 else 717 break # 復元失敗 718 fi 719 done 720 721 while ((count>=1)); do 722 local end=${rparens[count-1]} 723 ble/base/adjust-BASH_REMATCH/increase "$((end-i))" 724 rex=$rex')' 725 builtin unset -v 'rparens[--count]' 726 done 727 728 ble/base/adjust-BASH_REMATCH/increase "$((${#text}-i))" 729 730 _ble_bash_BASH_REMATCH=("${BASH_REMATCH[@]}") 731 _ble_bash_BASH_REMATCH_rex=$rex 732 } 733 function ble/base/restore-BASH_REMATCH { 734 ((_ble_bash_BASH_REMATCH_level>0&& 735 --_ble_bash_BASH_REMATCH_level==0)) || return 0 736 [[ $_ble_bash_BASH_REMATCH =~ $_ble_bash_BASH_REMATCH_rex ]] 737 } 738 fi 739 740 ble/init/adjust-IFS 741 ble/base/adjust-BASH_REMATCH 742 743 ## @fn ble/init/clean-up [opts] 744 function ble/init/clean-up { 745 local ext=$? opts=$1 # preserve exit status 746 747 # 一時グローバル変数消去 748 builtin unset -v _ble_init_version 749 builtin unset -v _ble_init_arg 750 builtin unset -v _ble_init_exit 751 builtin unset -v _ble_init_command 752 builtin unset -v _ble_init_attached 753 754 # 状態復元 755 ble/base/restore-BASH_REMATCH 756 ble/init/restore-IFS 757 if [[ :$opts: != *:check-attach:* || ! $_ble_attached ]]; then 758 ble/base/restore-bash-options 759 ble/base/restore-POSIXLY_CORRECT 760 ble/base/restore-builtin-wrappers 761 builtin eval -- "$_ble_bash_FUNCNEST_restore" 762 fi 763 return "$ext" 764 } 765 766 #------------------------------------------------------------------------------ 767 # read arguments 768 769 function ble/util/put { builtin printf '%s' "$1"; } 770 function ble/util/print { builtin printf '%s\n' "$1"; } 771 function ble/util/print-lines { builtin printf '%s\n' "$@"; } 772 773 _ble_base_arguments_opts= 774 _ble_base_arguments_attach= 775 _ble_base_arguments_rcfile= 776 ## @fn ble/base/read-blesh-arguments args 777 ## @var[out] _ble_base_arguments_opts 778 ## @var[out] _ble_base_arguments_attach 779 ## @var[out] _ble_base_arguments_rcfile 780 function ble/base/read-blesh-arguments { 781 local opts= 782 local opt_attach=prompt 783 local opt_inputrc=auto 784 785 builtin unset -v _ble_init_command # 再解析 786 while (($#)); do 787 local arg=$1; shift 788 case $arg in 789 (--noattach|noattach) 790 opt_attach=none ;; 791 (--attach=*) opt_attach=${arg#*=} ;; 792 (--attach) 793 if (($#)); then 794 opt_attach=$1; shift 795 else 796 opt_attach=attach 797 opts=$opts:E 798 ble/util/print "ble.sh ($arg): an option argument is missing." >&2 799 fi ;; 800 801 (--noinputrc) 802 opt_inputrc=none ;; 803 (--inputrc=*) opt_inputrc=${arg#*=} ;; 804 (--inputrc) 805 if (($#)); then 806 opt_inputrc=$1; shift 807 else 808 opt_inputrc=inputrc 809 opts=$opts:E 810 ble/util/print "ble.sh ($arg): an option argument is missing." >&2 811 fi ;; 812 813 (--rcfile=*|--init-file=*|--rcfile|--init-file) 814 if [[ $arg != *=* ]]; then 815 local rcfile=$1; shift 816 else 817 local rcfile=${arg#*=} 818 fi 819 820 _ble_base_arguments_rcfile=${rcfile:-/dev/null} 821 if [[ ! $rcfile || ! -e $rcfile ]]; then 822 ble/util/print "ble.sh ($arg): '$rcfile' does not exist." >&2 823 opts=$opts:E 824 elif [[ ! -r $rcfile ]]; then 825 ble/util/print "ble.sh ($arg): '$rcfile' is not readable." >&2 826 opts=$opts:E 827 fi ;; 828 (--norc) 829 _ble_base_arguments_rcfile=/dev/null ;; 830 (--keep-rlvars) 831 opts=$opts:keep-rlvars ;; 832 (--debug-bash-output) 833 bleopt_internal_suppress_bash_output= ;; 834 (--test | --update | --clear-cache | --lib) 835 if [[ $_ble_init_command ]]; then 836 ble/util/print "ble.sh ($arg): the option '--$_ble_init_command' has already been specified." >&2 837 opts=$opts:E 838 else 839 _ble_init_command=${arg#--} 840 fi ;; 841 (--*) 842 ble/util/print "ble.sh: unrecognized long option '$arg'" >&2 843 opts=$opts:E ;; 844 (-?*) 845 local i c 846 for ((i=1;i<${#arg};i++)); do 847 c=${arg:i:1} 848 case -$c in 849 (-o) 850 if ((i+1<${#arg})); then 851 local oarg=${arg:i+1} 852 i=${#arg} 853 elif (($#)); then 854 local oarg=$1; shift 855 else 856 opts=$opts:E 857 i=${#arg} 858 continue 859 fi 860 local rex='^[_a-zA-Z][_a-zA-Z0-9]*=' 861 if [[ $oarg =~ $rex ]]; then 862 builtin eval -- "bleopt_${oarg%%=*}=\${oarg#*=}" 863 else 864 ble/util/print "ble.sh: unrecognized option '-o $oarg'" >&2 865 opts=$opts:E 866 fi ;; 867 (-*) 868 ble/util/print "ble.sh: unrecognized option '-$c'" >&2 869 opts=$opts:E ;; 870 esac 871 done 872 ;; 873 (*) 874 if [[ ${_ble_init_command-} ]]; then 875 _ble_init_command[${#_ble_init_command[@]}]=$arg 876 else 877 ble/util/print "ble.sh: unrecognized argument '$arg'" >&2 878 opts=$opts:E 879 fi ;; 880 esac 881 done 882 883 _ble_base_arguments_opts=$opts 884 _ble_base_arguments_attach=$opt_attach 885 _ble_base_arguments_inputrc=$opt_inputrc 886 [[ :$opts: != *:E:* ]] 887 } 888 if ! ble/base/read-blesh-arguments "$@"; then 889 builtin echo "ble.sh: cancel initialization." >&2 890 ble/init/clean-up 2>/dev/null # set -x 対策 #D0930 891 return 2 2>/dev/null || builtin exit 2 892 fi 893 894 if [[ ${_ble_base-} ]]; then 895 [[ $_ble_init_command ]] && _ble_init_attached=$_ble_attached 896 if ! ble/base/unload-for-reload; then 897 builtin echo "ble.sh: an old version of ble.sh seems to be already loaded." >&2 898 ble/init/clean-up 2>/dev/null # set -x 対策 #D0930 899 return 1 2>/dev/null || builtin exit 1 900 fi 901 fi 902 903 #------------------------------------------------------------------------------ 904 # Initialize version information 905 906 # DEBUG version の Bash では遅いという通知 907 case ${BASH_VERSINFO[4]} in 908 (alp*|bet*|dev*|rc*|releng*|maint*) 909 ble/util/print-lines \ 910 "ble.sh may become very slow because this is a debug version of Bash" \ 911 " (version '$BASH_VERSION', release status: '${BASH_VERSINFO[4]}')." \ 912 " We recommend using ble.sh with a release version of Bash." >&2 ;; 913 esac 914 915 _ble_bash=$((BASH_VERSINFO[0]*10000+BASH_VERSINFO[1]*100+BASH_VERSINFO[2])) 916 _ble_bash_loaded_in_function=0 917 local _ble_local_test 2>/dev/null && _ble_bash_loaded_in_function=1 918 919 _ble_version=0 920 BLE_VERSION=$_ble_init_version 921 function ble/base/initialize-version-information { 922 local version=$BLE_VERSION 923 924 local hash= 925 if [[ $version == *+* ]]; then 926 hash=${version#*+} 927 version=${version%%+*} 928 fi 929 930 local status=release 931 if [[ $version == *-* ]]; then 932 status=${version#*-} 933 version=${version%%-*} 934 fi 935 936 local major=${version%%.*}; version=${version#*.} 937 local minor=${version%%.*}; version=${version#*.} 938 local patch=${version%%.*} 939 BLE_VERSINFO=("$major" "$minor" "$patch" "$hash" "$status" noarch) 940 ((_ble_version=major*10000+minor*100+patch)) 941 } 942 ble/base/initialize-version-information 943 944 #------------------------------------------------------------------------------ 945 # workarounds for builtin read 946 947 function ble/bash/read { 948 local TMOUT= 2>/dev/null # #D1630 WA readonly TMOUT 949 builtin read "${_ble_bash_tmout_wa[@]}" -r "$@" 950 } 951 function ble/bash/read-timeout { builtin read -t "$@"; } 952 953 # WA for bash-5.2 nested read by WINCH causes corrupted "running_trap" (#D1982) 954 _ble_bash_read_winch= 955 if ((50200<=_ble_bash&&_ble_bash<50300)); then 956 function ble/bash/read/.process-winch { 957 if [[ $_ble_bash_read_winch != - ]]; then 958 local _ble_local_handler=$_ble_bash_read_winch 959 local _ble_bash_read_winch= 960 builtin eval -- "$_ble_local_handler" 961 fi 962 } 963 function ble/bash/read { 964 local TMOUT= 2>/dev/null # #D1630 WA readonly TMOUT 965 local _ble_bash_read_winch=- 966 builtin read "${_ble_bash_tmout_wa[@]}" -r "$@"; local _ble_local_ext=$? 967 ble/bash/read/.process-winch 968 return "$_ble_local_ext" 969 } 970 function ble/bash/read-timeout { 971 local _ble_bash_read_winch=- 972 builtin read -t "$@"; local _ble_local_ext=$? 973 ble/bash/read/.process-winch 974 return "$_ble_local_ext" 975 } 976 fi 977 978 #------------------------------------------------------------------------------ 979 # check environment 980 981 # will be overwritten by src/util.sh 982 if ((_ble_bash>=50300)); then 983 function ble/util/assign { builtin eval "$1=\${ builtin eval -- \"\$2\"; }"; } 984 else 985 function ble/util/assign { builtin eval "$1=\$(builtin eval -- \"\$2\")"; } 986 fi 987 988 # ble/bin 989 990 ## @fn ble/bin/.default-utility-path commands... 991 ## 取り敢えず ble/bin/* からコマンドを呼び出せる様にします。 992 function ble/bin/.default-utility-path { 993 local cmd 994 for cmd; do 995 builtin eval "function ble/bin/$cmd { command $cmd \"\$@\"; }" 996 done 997 } 998 ## @fn ble/bin#freeze-utility-path [-n] commands... 999 ## PATH が破壊された後でも ble が動作を続けられる様に、 1000 ## 現在の PATH で基本コマンドのパスを固定して ble/bin/* から使える様にする。 1001 ## 1002 ## 実装に ble/util/assign を使用しているので ble-core 初期化後に実行する必要がある。 1003 ## 1004 function ble/bin#freeze-utility-path { 1005 local cmd path q=\' Q="'\''" fail= flags= 1006 for cmd; do 1007 if [[ $cmd == -n ]]; then 1008 flags=n$flags 1009 continue 1010 fi 1011 [[ $flags == *n* ]] && ble/bin#has "ble/bin/$cmd" && continue 1012 ble/bin#has "ble/bin/.frozen:$cmd" && continue 1013 if ble/util/assign path "builtin type -P -- $cmd 2>/dev/null" && [[ $path ]]; then 1014 builtin eval "function ble/bin/$cmd { '${path//$q/$Q}' \"\$@\"; }" 1015 else 1016 fail=1 1017 fi 1018 done 1019 ((!fail)) 1020 } 1021 1022 if ((_ble_bash>=40000)); then 1023 function ble/bin#has { type -t "$@" &>/dev/null; } 1024 else 1025 function ble/bin#has { 1026 local cmd 1027 for cmd; do type -t "$cmd" || return 1; done &>/dev/null 1028 return 0 1029 } 1030 fi 1031 1032 # POSIX utilities 1033 1034 _ble_init_posix_command_list=(sed date rm mkdir mkfifo sleep stty tty sort awk chmod grep cat wc mv sh od cp ps) 1035 function ble/init/check-environment { 1036 if ! ble/bin#has "${_ble_init_posix_command_list[@]}"; then 1037 local cmd commandMissing= 1038 for cmd in "${_ble_init_posix_command_list[@]}"; do 1039 if ! type "$cmd" &>/dev/null; then 1040 commandMissing="$commandMissing\`$cmd', " 1041 fi 1042 done 1043 ble/util/print "ble.sh: insane environment: The command(s), ${commandMissing}not found. Check your environment variable PATH." >&2 1044 1045 # try to fix PATH 1046 local default_path=$(command -p getconf PATH 2>/dev/null) 1047 [[ $default_path ]] || return 1 1048 1049 local original_path=$PATH 1050 export PATH=${default_path}${PATH:+:}${PATH} 1051 [[ :$PATH: == *:/bin:* ]] || PATH=/bin${PATH:+:}$PATH 1052 [[ :$PATH: == *:/usr/bin:* ]] || PATH=/usr/bin${PATH:+:}$PATH 1053 if ! ble/bin#has "${_ble_init_posix_command_list[@]}"; then 1054 PATH=$original_path 1055 return 1 1056 fi 1057 ble/util/print "ble.sh: modified PATH=${PATH::${#PATH}-${#original_path}}\$PATH" >&2 1058 fi 1059 1060 if [[ ! ${USER-} ]]; then 1061 ble/util/print "ble.sh: insane environment: \$USER is empty." >&2 1062 if USER=$(id -un 2>/dev/null) && [[ $USER ]]; then 1063 export USER 1064 ble/util/print "ble.sh: modified USER=$USER" >&2 1065 fi 1066 fi 1067 _ble_base_env_USER=$USER 1068 1069 if [[ ! ${HOSTNAME-} ]]; then 1070 ble/util/print "ble.sh: suspicious environment: \$HOSTNAME is empty." 1071 if HOSTNAME=$(uname -n 2>/dev/null) && [[ $HOSTNAME ]]; then 1072 export HOSTNAME 1073 ble/util/print "ble.sh: fixed HOSTNAME=$HOSTNAME" >&2 1074 fi 1075 fi 1076 _ble_base_env_HOSTNAME=$HOSTNAME 1077 1078 if [[ ! ${LANG-} ]]; then 1079 ble/util/print "ble.sh: suspicious environment: \$LANG is empty." >&2 1080 fi 1081 1082 # Check locale and work around `convert-meta on' in bash >= 5.2 1083 if ((_ble_bash>=50200)); then 1084 # Note #D2069: In bash >= 5.2, when the specified locale does not exist, 1085 # the readline setting `convert-meta' is automatically turned on when 1086 # Readline is first initialized. This interferes with ble.sh's trick to 1087 # distinguish isolated ESCs from meta ESCs, i.e., the combination "ESC [" 1088 # is converted to "<C0> <9B> [" by ble.sh's macro, <C0> is converted to 1089 # "ESC @" by `convert-meta', and "ESC @" is again converted to "<C0> <9B> 1090 # @". This forms an infinite loop. ble.sh tries to adjust `convert-meta', 1091 # but Readline's adjustment takes place at a random timing which is not 1092 # controllable. To work around this, we need to forcibly initialize 1093 # Readline before ble.sh adjusts `convert-meta'. 1094 1095 local error 1096 # Note: We check if the current locale setting produces an error message. 1097 # We try the workaround only when the locale appears to be broken because 1098 # the workaround may have a side effect of consuming user's input. 1099 ble/util/assign error '{ LC_ALL= LC_CTYPE=C ble/util/put; } 2>&1' 1100 if [[ $error ]]; then 1101 ble/util/print "$error" >&2 1102 ble/util/print "ble.sh: please check the locale settings (LANG and LC_*)." >&2 1103 1104 # Note: Somehow, the workaround of using "read -et" only works after 1105 # running `LC_ALL= LC_CTYPE=C cmd'. In bash < 5.3, ble/util/assign at 1106 # this point is executed under a subshell, so we need to run `LC_ALL= 1107 # LC_CTYPE=C ble/util/put' again in the main shell 1108 ((_ble_bash>=50300)) || { LC_ALL= LC_CTYPE=C ble/util/put; } 2>/dev/null 1109 1110 # We here forcibly initialize locales of Readline to make Readline's 1111 # adjustment of convert-meta take place here. 1112 local dummy 1113 builtin read -et 0.000001 dummy </dev/tty 1114 fi 1115 fi 1116 1117 # 暫定的な ble/bin/$cmd 設定 1118 ble/bin/.default-utility-path "${_ble_init_posix_command_list[@]}" 1119 1120 return 0 1121 } 1122 if ! ble/init/check-environment; then 1123 ble/util/print "ble.sh: failed to adjust the environment. canceling the load of ble.sh." 1>&2 1124 builtin unset -v _ble_bash BLE_VERSION BLE_VERSINFO 1125 ble/init/clean-up 2>/dev/null # set -x 対策 #D0930 1126 return 1 1127 fi 1128 1129 # Note: src/util.sh で ble/util/assign を定義した後に呼び出される。 1130 _ble_bin_awk_type= 1131 function ble/bin/awk/.instantiate { 1132 local path q=\' Q="'\''" ext=1 1133 1134 if ble/util/assign path "builtin type -P -- nawk 2>/dev/null" && [[ $path ]]; then 1135 # Note: Some distribution (like Ubuntu) provides gawk as "nawk" by 1136 # default. To avoid wrongly picking gawk as nawk, we need to check the 1137 # version output from the command. 1138 ble/util/assign version '"$path" -W version' 2>/dev/null </dev/null 1139 if [[ $version != *'GNU Awk'* && $version != *mawk* ]]; then 1140 builtin eval "function ble/bin/nawk { '${path//$q/$Q}' -v AWKTYPE=nawk \"\$@\"; }" 1141 if [[ ! $_ble_bin_awk_type ]]; then 1142 _ble_bin_awk_type=nawk 1143 builtin eval "function ble/bin/awk { '${path//$q/$Q}' -v AWKTYPE=nawk \"\$@\"; }" && ext=0 1144 fi 1145 fi 1146 fi 1147 1148 if ble/util/assign path "builtin type -P -- mawk 2>/dev/null" && [[ $path ]]; then 1149 builtin eval "function ble/bin/mawk { '${path//$q/$Q}' -v AWKTYPE=mawk \"\$@\"; }" 1150 if [[ ! $_ble_bin_awk_type ]]; then 1151 _ble_bin_awk_type=mawk 1152 builtin eval "function ble/bin/awk { '${path//$q/$Q}' -v AWKTYPE=mawk \"\$@\"; }" && ext=0 1153 fi 1154 fi 1155 1156 if ble/util/assign path "builtin type -P -- gawk 2>/dev/null" && [[ $path ]]; then 1157 builtin eval "function ble/bin/gawk { '${path//$q/$Q}' -v AWKTYPE=gawk \"\$@\"; }" 1158 if [[ ! $_ble_bin_awk_type ]]; then 1159 _ble_bin_awk_type=gawk 1160 builtin eval "function ble/bin/awk { '${path//$q/$Q}' -v AWKTYPE=gawk \"\$@\"; }" && ext=0 1161 fi 1162 fi 1163 1164 if [[ ! $_ble_bin_awk_type ]]; then 1165 if [[ $OSTYPE == solaris* ]] && type /usr/xpg4/bin/awk >/dev/null; then 1166 # Solaris の既定の awk は全然駄目なので /usr/xpg4 以下の awk を使う。 1167 _ble_bin_awk_type=xpg4 1168 function ble/bin/awk { /usr/xpg4/bin/awk -v AWKTYPE=xpg4 "$@"; } && ext=0 1169 elif ble/util/assign path "builtin type -P -- awk 2>/dev/null" && [[ $path ]]; then 1170 local version 1171 ble/util/assign version '"$path" -W version || "$path" --version' 2>/dev/null </dev/null 1172 if [[ $version == *'GNU Awk'* ]]; then 1173 _ble_bin_awk_type=gawk 1174 elif [[ $version == *mawk* ]]; then 1175 _ble_bin_awk_type=mawk 1176 elif [[ $version == 'awk version '[12][0-9][0-9][0-9][01][0-9][0-3][0-9] ]]; then 1177 _ble_bin_awk_type=nawk 1178 else 1179 _ble_bin_awk_type=unknown 1180 fi 1181 builtin eval "function ble/bin/awk { '${path//$q/$Q}' -v AWKTYPE=$_ble_bin_awk_type \"\$@\"; }" && ext=0 1182 if [[ $OSTYPE == darwin* && $path == /usr/bin/awk && $_ble_bin_awk_type == nawk ]]; then 1183 # Note #D1974: macOS の awk-32 の multibyte character support が怪しい。 1184 # 問題は GitHub Actions の上では再現できていないが特別の入力で失敗す 1185 # るのかもしれない。または、報告者の環境が壊れているだけの可能性もあ 1186 # る。テスト不可能だが、そもそも nawk は UTF-8 に対応していない前提な 1187 # ので、取り敢えず LC_CTYPE=C で実行する。 1188 function ble/bin/awk { 1189 local LC_ALL= LC_CTYPE=C 2>/dev/null 1190 /usr/bin/awk -v AWKTYPE=nawk "$@"; local ext=$? 1191 ble/util/unlocal LC_ALL LC_CTYPE 2>/dev/null 1192 return "$ext" 1193 } 1194 elif [[ $_ble_bin_awk_type == [gmn]awk ]] && ! ble/is-function "ble/bin/$_ble_bin_awk_type" ; then 1195 builtin eval "function ble/bin/$_ble_bin_awk_type { '${path//$q/$Q}' -v AWKTYPE=$_ble_bin_awk_type \"\$@\"; }" 1196 fi 1197 fi 1198 fi 1199 return "$ext" 1200 } 1201 1202 # Note: ble//bin/awk/.instantiate が実行される前に使おうとした時の為の暫定実装 1203 function ble/bin/awk { 1204 if ble/bin/awk/.instantiate; then 1205 ble/bin/awk "$@" 1206 else 1207 awk "$@" 1208 fi 1209 } 1210 1211 # Do not overwrite by .freeze-utility-path 1212 function ble/bin/.frozen:awk { :; } 1213 function ble/bin/.frozen:nawk { :; } 1214 function ble/bin/.frozen:mawk { :; } 1215 function ble/bin/.frozen:gawk { :; } 1216 1217 ## @fn ble/bin/awk0 1218 ## awk implementation that supports NUL record separator 1219 ## @fn ble/bin/awk0.available 1220 ## initialize ble/bin/awk0 and returns whether ble/bin/awk0 is available 1221 function ble/bin/awk0.available/test { 1222 local count=0 cmd_awk=$1 awk_script='BEGIN { RS = "\0"; } { count++; } END { print count; }' 1223 ble/util/assign count 'printf "a\0b\0" | "$cmd_awk" "$awk_script"' 1224 ((count==2)) 1225 } 1226 function ble/bin/awk0.available { 1227 local awk 1228 for awk in mawk gawk; do 1229 if ble/bin#freeze-utility-path -n "$awk" && 1230 ble/bin/awk0.available/test ble/bin/"$awk" && 1231 builtin eval -- "function ble/bin/awk0 { ble/bin/$awk -v AWKTYPE=$awk \"\$@\"; }"; then 1232 function ble/bin/awk0.available { ((1)); } 1233 return 0 1234 fi 1235 done 1236 1237 if ble/bin/awk0.available/test ble/bin/awk && 1238 function ble/bin/awk0 { ble/bin/awk "$@"; }; then 1239 function ble/bin/awk0.available { ((1)); } 1240 return 0 1241 fi 1242 1243 function ble/bin/awk0.available { ((0)); } 1244 return 1 1245 } 1246 1247 function ble/util/mkd { 1248 local dir 1249 for dir; do 1250 [[ -d $dir ]] && continue 1251 [[ -e $dir || -L $dir ]] && ble/bin/rm -f "$dir" 1252 ble/bin/mkdir -p "$dir" 1253 done 1254 } 1255 1256 #------------------------------------------------------------------------------ 1257 # readlink -f (Originally taken from akinomyoga/mshex.git) 1258 1259 ## @fn ble/util/readlink path 1260 ## @var[out] ret 1261 1262 if ((_ble_bash>=40000)); then 1263 _ble_util_readlink_visited_init='local -A visited=()' 1264 function ble/util/readlink/.visited { 1265 [[ ${visited[$1]+set} ]] && return 0 1266 visited[$1]=1 1267 return 1 1268 } 1269 else 1270 _ble_util_readlink_visited_init="local -a visited=()" 1271 function ble/util/readlink/.visited { 1272 local key 1273 for key in "${visited[@]}"; do 1274 [[ $1 == "$key" ]] && return 0 1275 done 1276 visited=("$1" "${visited[@]}") 1277 return 1 1278 } 1279 fi 1280 1281 ## @fn ble/util/readlink/.readlink path 1282 ## @var[out] link 1283 function ble/util/readlink/.readlink { 1284 local path=$1 1285 if ble/bin#has ble/bin/readlink; then 1286 ble/util/assign link 'ble/bin/readlink -- "$path"' 1287 [[ $link ]] 1288 elif ble/bin#has ble/bin/ls; then 1289 ble/util/assign link 'ble/bin/ls -ld -- "$path"' && 1290 [[ $link == *" $path -> "?* ]] && 1291 link=${link#*" $path -> "} 1292 else 1293 false 1294 fi 1295 } 2>/dev/null 1296 ## @fn ble/util/readlink/.resolve-physical-directory 1297 ## @var[in,out] path 1298 function ble/util/readlink/.resolve-physical-directory { 1299 [[ $path == */?* ]] || return 0 1300 local PWD=$PWD OLDPWD=$OLDPWD CDPATH= 1301 if builtin cd -L .; then 1302 local pwd=$PWD 1303 builtin cd -P "${path%/*}/" && 1304 path=${PWD%/}/${path##*/} 1305 1306 # Note #D1849: 現在ディレクトリが他者により改名されている場合や PWD がユー 1307 # ザーに書き換えられている場合にも元のディレクトリに戻る為、cd -L . した 1308 # 後のパスに cd する。但し pwd の結果はこの関数の呼び出し前と変わってしま 1309 # う (が実際にはこの方が良いだろう)。PWD は local にして元の値に戻すので 1310 # 変わらない。 1311 builtin cd "$pwd" 1312 fi 1313 return 0 1314 } 1315 function ble/util/readlink/.resolve-loop { 1316 local path=$ret 1317 while [[ $path == ?*/ ]]; do path=${path%/}; done 1318 builtin eval -- "$_ble_util_readlink_visited_init" 1319 while [[ -h $path ]]; do 1320 local link 1321 ble/util/readlink/.visited "$path" && break 1322 ble/util/readlink/.readlink "$path" || break 1323 if [[ $link == /* || $path != */* ]]; then 1324 path=$link 1325 else 1326 # 相対パス ../ は物理ディレクトリ構造に従って遡る。 1327 ble/util/readlink/.resolve-physical-directory 1328 path=${path%/*}/$link 1329 fi 1330 while [[ $path == ?*/ ]]; do path=${path%/}; done 1331 done 1332 ret=$path 1333 } 1334 function ble/util/readlink/.resolve { 1335 # 初回呼び出し時に実装を選択 1336 _ble_util_readlink_type= 1337 1338 # より効率的な実装が可能な場合は ble/util/readlink/.resolve を独自定義。 1339 case $OSTYPE in 1340 (cygwin | msys | linux-gnu) 1341 # これらのシステムの標準 readlink では readlink -f が使える。 1342 # 1343 # Note: 例えば NixOS では標準の readlink を使おうとすると問題が起こるらしい 1344 # ので、見えている readlink を使う。見えている readlink が非標準の時は -f 1345 # が使えるか分からないので readlink -f による実装は有効化しない。 1346 # 1347 local readlink 1348 ble/util/assign readlink 'type -P readlink' 1349 case $readlink in 1350 (/bin/readlink | /usr/bin/readlink) 1351 _ble_util_readlink_type=readlink-f 1352 builtin eval "function ble/util/readlink/.resolve { ble/util/assign ret '$readlink -f -- \"\$ret\"'; }" ;; 1353 esac ;; 1354 esac 1355 1356 if [[ ! $_ble_util_readlink_type ]]; then 1357 _ble_util_readlink_type=loop 1358 ble/bin#freeze-utility-path readlink ls 1359 function ble/util/readlink/.resolve { ble/util/readlink/.resolve-loop; } 1360 fi 1361 1362 ble/util/readlink/.resolve 1363 } 1364 function ble/util/readlink { 1365 ret=$1 1366 if [[ -h $ret ]]; then ble/util/readlink/.resolve; fi 1367 } 1368 1369 #--------------------------------------- 1370 1371 _ble_bash_path= 1372 function ble/bin/.load-builtin { 1373 local name=$1 path=$2 1374 if [[ ! $_ble_bash_path ]]; then 1375 local ret; ble/util/readlink "$BASH" 1376 _ble_bash_path=$ret 1377 fi 1378 1379 if [[ ! $path ]]; then 1380 local bash_prefix=${ret%/*/*} 1381 path=$bash_prefix/lib/bash/$name 1382 [[ -s $path ]] || return 1 1383 fi 1384 1385 if (enable -f "$path" "$name") &>/dev/null; then 1386 enable -f "$path" "$name" 1387 builtin eval -- "function ble/bin/$name { builtin $name \"\$@\"; }" 1388 return 0 1389 else 1390 return 1 1391 fi 1392 } 1393 # ble/bin/.load-builtin mkdir 1394 # ble/bin/.load-builtin mkfifo 1395 # ble/bin/.load-builtin rm 1396 1397 #------------------------------------------------------------------------------ 1398 1399 function ble/base/.create-user-directory { 1400 local var=$1 dir=$2 1401 if [[ ! -d $dir ]]; then 1402 # dangling symlinks are silently removed 1403 [[ ! -e $dir && -h $dir ]] && ble/bin/rm -f "$dir" 1404 if [[ -e $dir || -h $dir ]]; then 1405 ble/util/print "ble.sh: cannot create a directory '$dir' since there is already a file." >&2 1406 return 1 1407 fi 1408 if ! (umask 077; ble/bin/mkdir -p "$dir" && [[ -O $dir ]]); then 1409 ble/util/print "ble.sh: failed to create a directory '$dir'." >&2 1410 return 1 1411 fi 1412 elif ! [[ -r $dir && -w $dir && -x $dir ]]; then 1413 ble/util/print "ble.sh: permission of '$dir' is not correct." >&2 1414 return 1 1415 elif [[ ! -O $dir ]]; then 1416 ble/util/print "ble.sh: owner of '$dir' is not correct." >&2 1417 return 1 1418 fi 1419 builtin eval "$var=\$dir" 1420 } 1421 1422 ## 1423 ## @var _ble_base 1424 ## @var _ble_base_blesh 1425 ## @var _ble_base_blesh_raw 1426 ## 1427 ## ble.sh のインストール先ディレクトリ。 1428 ## 読み込んだ ble.sh の実体があるディレクトリとして解決される。 1429 ## 1430 function ble/base/initialize-base-directory { 1431 local src=$1 1432 local defaultDir=${2-} 1433 1434 # resolve symlink 1435 _ble_base_blesh_raw=$src 1436 if [[ -h $src ]]; then 1437 local ret; ble/util/readlink "$src"; src=$ret 1438 fi 1439 _ble_base_blesh=$src 1440 1441 if [[ -s $src && $src != */* ]]; then 1442 _ble_base=$PWD 1443 elif [[ $src == */* ]]; then 1444 local dir=${src%/*} 1445 if [[ ! $dir ]]; then 1446 _ble_base=/ 1447 elif [[ $dir != /* ]]; then 1448 _ble_base=$PWD/$dir 1449 else 1450 _ble_base=$dir 1451 fi 1452 else 1453 _ble_base=${defaultDir:-$HOME/.local/share/blesh} 1454 fi 1455 1456 [[ -d $_ble_base ]] 1457 } 1458 if ! ble/base/initialize-base-directory "${BASH_SOURCE[0]}"; then 1459 ble/util/print "ble.sh: ble base directory not found!" 1>&2 1460 builtin unset -v _ble_bash BLE_VERSION BLE_VERSINFO 1461 ble/init/clean-up 2>/dev/null # set -x 対策 #D0930 1462 return 1 1463 fi 1464 1465 ## 1466 ## @var _ble_base_run 1467 ## 1468 ## 実行時の一時ファイルを格納するディレクトリ。以下の手順で決定する。 1469 ## 1470 ## 1. ${XDG_RUNTIME_DIR:=/run/user/$UID} が存在すればその下に blesh を作成して使う。 1471 ## 2. /tmp/blesh/$UID を作成可能ならば、それを使う。 1472 ## 3. $_ble_base/tmp/$UID を使う。 1473 ## 1474 function ble/base/initialize-runtime-directory/.xdg { 1475 local runtime_dir= 1476 if [[ $XDG_RUNTIME_DIR ]]; then 1477 if [[ ! -d $XDG_RUNTIME_DIR ]]; then 1478 ble/util/print "ble.sh: XDG_RUNTIME_DIR='$XDG_RUNTIME_DIR' is not a directory." >&2 1479 return 1 1480 elif [[ -O $XDG_RUNTIME_DIR ]]; then 1481 runtime_dir=$XDG_RUNTIME_DIR 1482 else 1483 # When XDG_RUNTIME_DIR is not owned by the current user, maybe "su" is 1484 # used to enter this session keeping the environment variables of the 1485 # original user. We just ignore XDG_RUNTIME_DIR (without issueing 1486 # warnings) for such a case. 1487 false 1488 fi 1489 fi 1490 if [[ ! $runtime_dir ]]; then 1491 runtime_dir=/run/user/$UID 1492 [[ -d $runtime_dir && -O $runtime_dir ]] || return 1 1493 fi 1494 1495 if ! [[ -r $runtime_dir && -w $runtime_dir && -x $runtime_dir ]]; then 1496 [[ $runtime_dir == "$XDG_RUNTIME_DIR" ]] && 1497 ble/util/print "ble.sh: XDG_RUNTIME_DIR='$XDG_RUNTIME_DIR' doesn't have a proper permission." >&2 1498 return 1 1499 fi 1500 1501 ble/base/.create-user-directory _ble_base_run "$runtime_dir/blesh" 1502 } 1503 function ble/base/initialize-runtime-directory/.tmp { 1504 [[ -r /tmp && -w /tmp && -x /tmp ]] || return 1 1505 1506 local tmp_dir=/tmp/blesh 1507 if [[ ! -d $tmp_dir ]]; then 1508 [[ ! -e $tmp_dir && -h $tmp_dir ]] && ble/bin/rm -f "$tmp_dir" 1509 if [[ -e $tmp_dir || -h $tmp_dir ]]; then 1510 ble/util/print "ble.sh: cannot create a directory '$tmp_dir' since there is already a file." >&2 1511 return 1 1512 fi 1513 ble/bin/mkdir -p "$tmp_dir" || return 1 1514 ble/bin/chmod a+rwxt "$tmp_dir" || return 1 1515 elif ! [[ -r $tmp_dir && -w $tmp_dir && -x $tmp_dir ]]; then 1516 ble/util/print "ble.sh: permission of '$tmp_dir' is not correct." >&2 1517 return 1 1518 fi 1519 1520 ble/base/.create-user-directory _ble_base_run "$tmp_dir/$UID" 1521 } 1522 function ble/base/initialize-runtime-directory { 1523 ble/base/initialize-runtime-directory/.xdg && return 0 1524 ble/base/initialize-runtime-directory/.tmp && return 0 1525 1526 # fallback 1527 local tmp_dir=$_ble_base/run 1528 if [[ ! -d $tmp_dir ]]; then 1529 ble/bin/mkdir -p "$tmp_dir" || return 1 1530 ble/bin/chmod a+rwxt "$tmp_dir" || return 1 1531 fi 1532 ble/base/.create-user-directory _ble_base_run "$tmp_dir/${USER:-$UID}@$HOSTNAME" 1533 } 1534 if ! ble/base/initialize-runtime-directory; then 1535 ble/util/print "ble.sh: failed to initialize \$_ble_base_run." 1>&2 1536 builtin unset -v _ble_bash BLE_VERSION BLE_VERSINFO 1537 ble/init/clean-up 2>/dev/null # set -x 対策 #D0930 1538 return 1 1539 fi 1540 1541 # ロード時刻の記録 (ble-update で使う為) 1542 : >| "$_ble_base_run/$$.load" 1543 1544 ## @fn ble/base/clean-up-runtime-directory [opts] 1545 ## 既に存在しないプロセスに属する実行時ファイルを削除します。*.pid のファイル 1546 ## 名を持つ実行時ファイルはについては、子バックグラウンドプロセスのプロセスID 1547 ## を含むと見做し、ファイルの内容を読み取ってそれが整数であればその整数に対し 1548 ## て kill を実行します。 1549 ## 1550 ## @param[in,opt] opts 1551 ## finalize ... 自プロセス $$ に関連するファイルも削除します。現セッション 1552 ## における ble.sh の終了処理時に呼び出される事を想定しています。 1553 ## 1554 function ble/base/clean-up-runtime-directory { 1555 local opts=$1 failglob= noglob= 1556 if [[ $- == *f* ]]; then 1557 noglob=1 1558 set +f 1559 fi 1560 if shopt -q failglob &>/dev/null; then 1561 failglob=1 1562 shopt -u failglob 1563 fi 1564 1565 local -a alive=() removed=() bgpids=() 1566 [[ :$opts: == *:finalize:* ]] && alive[$$]=0 1567 1568 local file pid iremoved=0 ibgpid=0 1569 for file in "$_ble_base_run"/[1-9]*.*; do 1570 [[ -e $file || -h $file ]] || continue 1571 1572 # extract pid (skip if it is not a number) 1573 pid=${file##*/}; pid=${pid%%.*} 1574 [[ $pid && ! ${pid//[0-9]} ]] || continue 1575 1576 if [[ ! ${alive[pid]+set} ]]; then 1577 builtin kill -0 "$pid" &>/dev/null 1578 ((alive[pid]=$?==0)) 1579 fi 1580 ((alive[pid])) && continue 1581 1582 # kill process specified by the pid file 1583 if [[ $file == *.pid && -s $file ]]; then 1584 local run_pid IFS= 1585 ble/bash/read run_pid < "$file" 1586 if [[ $run_pid && ! ${run_pid//[0-9]} ]]; then 1587 if ((pid==$$)); then 1588 # 現セッションの背景プロセスの場合は遅延させる 1589 kill -0 "$run_pid" &>/dev/null && bgpids[ibgpid++]=$run_pid 1590 else 1591 kill "$run_pid" 1592 fi 1593 fi 1594 fi 1595 1596 removed[iremoved++]=$file 1597 done 1598 ((iremoved)) && ble/bin/rm -rf "${removed[@]}" 2>/dev/null 1599 ((ibgpid)) && (ble/util/nohup 'ble/bin/sleep 3; kill "${bgpids[@]}"') 1600 1601 [[ $failglob ]] && shopt -s failglob 1602 [[ $noglob ]] && set -f 1603 return 0 1604 } 1605 1606 # initialization time = 9ms (for 70 files) 1607 ble/base/clean-up-runtime-directory 1608 1609 ## 1610 ## @var _ble_base_cache 1611 ## 1612 ## 環境毎の初期化ファイルを格納するディレクトリ。以下の手順で決定する。 1613 ## 1614 ## 1. ${XDG_CACHE_HOME:=$HOME/.cache} が存在すればその下に blesh を作成して使う。 1615 ## 2. $_ble_base/cache.d/$UID を使う。 1616 ## 1617 function ble/base/initialize-cache-directory/.xdg { 1618 [[ $_ble_base != */out ]] || return 1 1619 1620 local cache_dir=${XDG_CACHE_HOME:-$HOME/.cache} 1621 if [[ ! -d $cache_dir ]]; then 1622 [[ $XDG_CACHE_HOME ]] && 1623 ble/util/print "ble.sh: XDG_CACHE_HOME='$XDG_CACHE_HOME' is not a directory." >&2 1624 return 1 1625 fi 1626 if ! [[ -r $cache_dir && -w $cache_dir && -x $cache_dir ]]; then 1627 [[ $XDG_CACHE_HOME ]] && 1628 ble/util/print "ble.sh: XDG_CACHE_HOME='$XDG_CACHE_HOME' doesn't have a proper permission." >&2 1629 return 1 1630 fi 1631 1632 local ver=${BLE_VERSINFO[0]}.${BLE_VERSINFO[1]} 1633 ble/base/.create-user-directory _ble_base_cache "$cache_dir/blesh/$ver" 1634 } 1635 function ble/base/initialize-cache-directory { 1636 ble/base/initialize-cache-directory/.xdg && return 0 1637 1638 # fallback 1639 local cache_dir=$_ble_base/cache.d 1640 if [[ ! -d $cache_dir ]]; then 1641 ble/bin/mkdir -p "$cache_dir" || return 1 1642 ble/bin/chmod a+rwxt "$cache_dir" || return 1 1643 1644 # relocate an old cache directory if any 1645 local old_cache_dir=$_ble_base/cache 1646 if [[ -d $old_cache_dir && ! -h $old_cache_dir ]]; then 1647 mv "$old_cache_dir" "$cache_dir/$UID" 1648 ln -s "$cache_dir/$UID" "$old_cache_dir" 1649 fi 1650 fi 1651 ble/base/.create-user-directory _ble_base_cache "$cache_dir/$UID" 1652 } 1653 function ble/base/migrate-cache-directory/.move { 1654 local old=$1 new=$2 1655 [[ -e $old ]] || return 0 1656 if [[ -e $new || -L $old ]]; then 1657 ble/bin/rm -rf "$old" 1658 else 1659 ble/bin/mv "$old" "$new" 1660 fi 1661 } 1662 function ble/base/migrate-cache-directory/.check-old-prefix { 1663 local old_prefix=$_ble_base_cache/$1 1664 local new_prefix=$_ble_base_cache/$2 1665 local file 1666 for file in "$old_prefix"*; do 1667 local old=$file 1668 local new=$new_prefix${file#"$old_prefix"} 1669 ble/base/migrate-cache-directory/.move "$old" "$new" 1670 done 1671 } 1672 function ble/base/migrate-cache-directory { 1673 local failglob= 1674 shopt -q failglob && { failglob=1; shopt -u failglob; } 1675 1676 ble/base/migrate-cache-directory/.check-old-prefix cmap+default.binder-source decode.cmap.allseq 1677 ble/base/migrate-cache-directory/.check-old-prefix cmap+default decode.cmap 1678 ble/base/migrate-cache-directory/.check-old-prefix ble-decode-bind decode.bind 1679 1680 local file 1681 for file in "$_ble_base_cache"/*.term; do 1682 local old=$file 1683 local new=$_ble_base_cache/term.${file#"$_ble_base_cache/"}; new=${new%.term} 1684 ble/base/migrate-cache-directory/.move "$old" "$new" 1685 done 1686 1687 ble/base/migrate-cache-directory/.move "$_ble_base_cache/man" "$_ble_base_cache/complete.mandb" 1688 1689 [[ $failglob ]] && shopt -s failglob 1690 } 1691 if ! ble/base/initialize-cache-directory; then 1692 ble/util/print "ble.sh: failed to initialize \$_ble_base_cache." 1>&2 1693 builtin unset -v _ble_bash BLE_VERSION BLE_VERSINFO 1694 ble/init/clean-up 2>/dev/null # set -x 対策 #D0930 1695 return 1 1696 fi 1697 ble/base/migrate-cache-directory 1698 1699 ## 1700 ## @var _ble_base_state 1701 ## 1702 ## 環境毎の初期化ファイルを格納するディレクトリ。以下の手順で決定する。 1703 ## 1704 ## 1. ${XDG_STATE_HOME:=$HOME/.state} (存在しなくても強制的に作成) の下に blesh を作成して使う。 1705 ## 2. (1. に失敗した時) $_ble_base/state.d/$UID を使う。 1706 ## 1707 function ble/base/initialize-state-directory/.xdg { 1708 local state_dir=${XDG_STATE_HOME:-$HOME/.local/state} 1709 if [[ -e $state_dir || -L $state_dir ]]; then 1710 if [[ ! -d $state_dir ]]; then 1711 if [[ $XDG_STATE_HOME ]]; then 1712 ble/util/print "ble.sh: XDG_STATE_HOME='$XDG_STATE_HOME' is not a directory." >&2 1713 else 1714 ble/util/print "ble.sh: '$state_dir' is not a directory." >&2 1715 fi 1716 return 1 1717 fi 1718 if ! [[ -r $state_dir && -w $state_dir && -x $state_dir ]]; then 1719 if [[ $XDG_STATE_HOME ]]; then 1720 ble/util/print "ble.sh: XDG_STATE_HOME='$XDG_STATE_HOME' doesn't have a proper permission." >&2 1721 else 1722 ble/util/print "ble.sh: '$state_dir' doesn't have a proper permission." >&2 1723 fi 1724 return 1 1725 fi 1726 fi 1727 1728 ble/base/.create-user-directory _ble_base_state "$state_dir/blesh" 1729 } 1730 function ble/base/initialize-state-directory { 1731 ble/base/initialize-state-directory/.xdg && return 0 1732 1733 # fallback 1734 local state_dir=$_ble_base/state.d 1735 if [[ ! -d $state_dir ]]; then 1736 ble/bin/mkdir -p "$state_dir" || return 1 1737 ble/bin/chmod a+rwxt "$state_dir" || return 1 1738 1739 # relocate an old state directory if any 1740 local old_state_dir=$_ble_base/state 1741 if [[ -d $old_state_dir && ! -h $old_state_dir ]]; then 1742 mv "$old_state_dir" "$state_dir/$UID" 1743 ln -s "$state_dir/$UID" "$old_state_dir" 1744 fi 1745 fi 1746 ble/util/print "ble.sh: using the non-standard position of the state directory: '$state_dir/$UID'" >&2 1747 ble/base/.create-user-directory _ble_base_state "$state_dir/$UID" 1748 } 1749 if ! ble/base/initialize-state-directory; then 1750 ble/util/print "ble.sh: failed to initialize \$_ble_base_state." 1>&2 1751 builtin unset -v _ble_bash BLE_VERSION BLE_VERSINFO 1752 ble/init/clean-up 2>/dev/null # set -x 対策 #D0930 1753 return 1 1754 fi 1755 1756 1757 function ble/base/print-usage-for-no-argument-command { 1758 local name=${FUNCNAME[1]} desc=$1; shift 1759 ble/util/print-lines \ 1760 "usage: $name" \ 1761 "$desc" >&2 1762 [[ $1 != --help ]] && return 2 1763 return 0 1764 } 1765 function ble-reload { 1766 local -a options=() 1767 [[ ! -e $_ble_base_rcfile ]] || 1768 ble/array#push options --rcfile="${_ble_base_rcfile:-/dev/null}" 1769 [[ $_ble_base_arguments_inputrc == auto ]] || 1770 ble/array#push options --inputrc="$_ble_base_arguments_inputrc" 1771 local name 1772 for name in keep-rlvars; do 1773 if [[ :$_ble_base_arguments_opts: == *:"$name":* ]]; then 1774 ble/array#push options "--$name" 1775 fi 1776 done 1777 source "$_ble_base/ble.sh" "${options[@]}" 1778 } 1779 1780 #%$ pwd=$(pwd) q=\' Q="'\''" bash -c 'echo "_ble_base_repository=$q${pwd//$q/$Q}$q"' 1781 #%$ echo "_ble_base_branch=$(git rev-parse --abbrev-ref HEAD)" 1782 _ble_base_repository_url=https://github.com/akinomyoga/ble.sh 1783 #%$ echo "_ble_base_build_git_version=\"$BUILD_GIT_VERSION\"" 1784 #%$ echo "_ble_base_build_make_version=\"$BUILD_MAKE_VERSION\"" 1785 #%$ echo "_ble_base_build_gawk_version=\"$BUILD_GAWK_VERSION\"" 1786 function ble-update/.check-install-directory-ownership { 1787 if [[ ! -O $_ble_base ]]; then 1788 ble/util/print 'ble-update: install directory is owned by another user:' >&2 1789 ls -ld "$_ble_base" 1790 return 1 1791 elif [[ ! -r $_ble_base || ! -w $_ble_base || ! -x $_ble_base ]]; then 1792 ble/util/print 'ble-update: install directory permission denied:' >&2 1793 ls -ld "$_ble_base" 1794 return 1 1795 fi 1796 } 1797 function ble-update/.make { 1798 local sudo= 1799 if [[ $1 == --sudo ]]; then 1800 sudo=1 1801 shift 1802 fi 1803 1804 if ! "$make" -q "$@"; then 1805 if [[ $sudo ]]; then 1806 sudo "$make" "$@" 1807 else 1808 "$make" "$@" 1809 fi 1810 else 1811 # インストール先に更新がなくても現在の session でロードされている ble.sh が 1812 # 古いかもしれないのでチェックしてリロードする。 1813 return 6 1814 fi 1815 } 1816 function ble-update/.reload { 1817 local ext=$1 1818 if [[ $ext -eq 0 || $ext -eq 6 && $_ble_base/ble.sh -nt $_ble_base_run/$$.load ]]; then 1819 if [[ ! -e $_ble_base/ble.sh ]]; then 1820 ble/util/print "ble-update: new ble.sh not found at '$_ble_base/ble.sh'." >&2 1821 return 1 1822 elif [[ ! -s $_ble_base/ble.sh ]]; then 1823 ble/util/print "ble-update: new ble.sh '$_ble_base/ble.sh' is empty." >&2 1824 return 1 1825 elif [[ $- == *i* && $_ble_attached ]] && ! ble/util/is-running-in-subshell; then 1826 ble-reload 1827 fi 1828 return "$?" 1829 fi 1830 ((ext==6)) && ext=0 1831 return "$ext" 1832 } 1833 function ble-update/.download-nightly-build { 1834 if ! ble/bin#has tar xz; then 1835 local command 1836 for command in tar xz; do 1837 ble/bin#has "$command" || 1838 ble/util/print "ble-update (nightly): '$command' command is not available." >&2 1839 done 1840 return 1 1841 fi 1842 1843 if ((EUID!=0)) && ! ble-update/.check-install-directory-ownership; then 1844 # _ble_base が自分の物でない時は sudo でやり直す 1845 sudo "$BASH" "$_ble_base/ble.sh" --update && 1846 ble-update/.reload 6 1847 return "$?" 1848 fi 1849 1850 local tarname=ble-nightly.tar.xz 1851 local url_tar=$_ble_base_repository_url/releases/download/nightly/$tarname 1852 ( 1853 set +f 1854 shopt -u failglob nullglob 1855 1856 # mkcd "$_ble_base/src" 1857 if ! ble/bin/mkdir -p "$_ble_base/src"; then 1858 ble/util/print "ble-update (nightly): failed to create the directory '$_ble_base/src'" >&2 1859 return 1 1860 fi 1861 if ! builtin cd "$_ble_base/src"; then 1862 ble/util/print "ble-update (nightly): failed to enter the directory '$_ble_base/src'" >&2 1863 return 1 1864 fi 1865 1866 local ret 1867 ble/file#hash "$tarname"; local ohash=$ret 1868 1869 # download "$url_tar" "$tarname" 1870 # Note: アップロードした直後は暫く 404 Not Found になるようなので何回か再試 1871 # 行する。 1872 local retry max_retry=5 1873 for ((retry=0;retry<=max_retry;retry++)); do 1874 if ((retry>0)); then 1875 local wait=$((retry<3?retry*10:30)) 1876 ble/util/print "ble-update (nightly): retry downloading in $wait seconds... ($retry/$max_retry)" >&2 1877 ble/util/sleep "$wait" 1878 fi 1879 1880 if ble/bin#has wget; then 1881 wget -N "$url_tar" && break 1882 elif ble/bin#has curl; then 1883 curl -LRo "$tarname" -z "$tarname" "$url_tar" && break 1884 else 1885 ble/util/print "ble-update (nightly): command 'wget' nor 'curl' is available." >&2 1886 return 1 1887 fi 1888 done 1889 if ((retry>max_retry)); then 1890 ble/util/print "ble-update (nightly): failed to download the archive from '$url_tar'." >&2 1891 return 7 1892 fi 1893 1894 # 前回ダウンロードした物と同じ場合は省略 1895 ble/file#hash "$tarname"; local nhash=$ret 1896 [[ $ohash == "$nhash" ]] && return 6 1897 1898 # tar xJf "$tarname" 1899 ble/bin/rm -rf ble-nightly*/ 1900 if ! tar xJf "$tarname"; then 1901 ble/util/print 'ble-update (nightly): failed to extract the tarball. Removing possibly broken tarball.' >&2 1902 ble/bin/rm -rf "$tarname" 1903 return 1 1904 fi 1905 1906 # cp -T ble-nightly* "$_ble_base" 1907 local extracted_dir=ble-nightly 1908 if [[ ! -d $extracted_dir ]]; then 1909 ble/util/print "ble-update (nightly): the directory 'ble-nightly' not found in the tarball '$PWD/$tarname'." >&2 1910 return 1 1911 fi 1912 ble/bin/cp -Rf "$extracted_dir"/* "$_ble_base/" || return 1 1913 ble/bin/rm -rf "$extracted_dir" 1914 ) && 1915 ble-update/.reload 1916 } 1917 function ble-update { 1918 if (($#)); then 1919 ble/base/print-usage-for-no-argument-command 'Update and reload ble.sh.' "$@" 1920 return "$?" 1921 fi 1922 1923 if [[ ${_ble_base_package_type-} ]] && ble/is-function ble/base/package:"$_ble_base_package_type"/update; then 1924 ble/util/print "ble-update: delegate to '$_ble_base_package_type' package manager..." >&2 1925 ble/base/package:"$_ble_base_package_type"/update; local ext=$? 1926 if ((ext==125)); then 1927 ble/util/print 'ble-update: fallback to the default update process.' >&2 1928 else 1929 ble-update/.reload "$ext" 1930 return "$?" 1931 fi 1932 fi 1933 1934 if [[ ${_ble_base_repository-} == release:nightly-* ]]; then 1935 if ble-update/.download-nightly-build; local ext=$?; ((ext==0||ext==6||ext==7)); then 1936 if ((ext==6)); then 1937 ble/util/print 'ble-update (nightly): Already up to date.' >&2 1938 elif ((ext==7)); then 1939 ble/util/print 'ble-update (nightly): Remote temporarily unavailable. Try it again later.' >&2 1940 fi 1941 return 0 1942 fi 1943 fi 1944 1945 # check make 1946 local make= 1947 if ble/bin#has gmake; then 1948 make=gmake 1949 elif ble/bin#has make && make --version 2>&1 | ble/bin/grep -qiF 'GNU Make'; then 1950 make=make 1951 else 1952 ble/util/print "ble-update: GNU Make is not available." >&2 1953 return 1 1954 fi 1955 1956 # check git, gawk 1957 if ! ble/bin#has git gawk; then 1958 local command 1959 for command in git gawk; do 1960 ble/bin#has "$command" || 1961 ble/util/print "ble-update: '$command' command is not available." >&2 1962 done 1963 return 1 1964 fi 1965 1966 local insdir_doc=$_ble_base/doc 1967 [[ ! -d $insdir_doc && -d ${_ble_base%/*}/doc/blesh ]] && 1968 insdir_doc=${_ble_base%/*}/doc/blesh 1969 1970 if [[ ${_ble_base_repository-} && $_ble_base_repository != release:* ]]; then 1971 if [[ ! -e $_ble_base_repository/.git ]]; then 1972 ble/util/print "ble-update: git repository not found at '$_ble_base_repository'." >&2 1973 elif [[ ! -O $_ble_base_repository ]]; then 1974 ble/util/print "ble-update: git repository is owned by another user:" >&2 1975 ls -ld "$_ble_base_repository" 1976 elif [[ ! -r $_ble_base_repository || ! -w $_ble_base_repository || ! -x $_ble_base_repository ]]; then 1977 ble/util/print 'ble-update: git repository permission denied:' >&2 1978 ls -ld "$_ble_base_repository" 1979 else 1980 ( ble/util/print "cd into $_ble_base_repository..." >&2 && 1981 builtin cd "$_ble_base_repository" && 1982 git pull && git submodule update --recursive --remote && 1983 if [[ $_ble_base == "$_ble_base_repository"/out ]]; then 1984 ble-update/.make all 1985 elif ((EUID!=0)) && ! ble-update/.check-install-directory-ownership; then 1986 ble-update/.make all 1987 ble-update/.make --sudo INSDIR="$_ble_base" INSDIR_DOC="$insdir_doc" install 1988 else 1989 ble-update/.make INSDIR="$_ble_base" INSDIR_DOC="$insdir_doc" install 1990 fi ) 1991 ble-update/.reload "$?" 1992 return "$?" 1993 fi 1994 fi 1995 1996 if ((EUID!=0)) && ! ble-update/.check-install-directory-ownership; then 1997 # _ble_base が自分の物でない時は sudo でやり直す 1998 sudo "$BASH" "$_ble_base/ble.sh" --update && 1999 ble-update/.reload 6 2000 return "$?" 2001 else 2002 # _ble_base/src 内部に clone して make install 2003 local branch=${_ble_base_branch:-master} 2004 ( ble/bin/mkdir -p "$_ble_base/src" && builtin cd "$_ble_base/src" && 2005 git clone --recursive --depth 1 "$_ble_base_repository_url" "$_ble_base/src/ble.sh" -b "$branch" && 2006 builtin cd ble.sh && "$make" all && 2007 "$make" INSDIR="$_ble_base" INSDIR_DOC="$insdir_doc" install ) && 2008 ble-update/.reload 2009 return "$?" 2010 fi 2011 return 1 2012 } 2013 #%if measure_load_time 2014 ble/debug/measure-set-timeformat ble.pp/prologue 2015 } 2016 #%end 2017 2018 2019 #------------------------------------------------------------------------------ 2020 _ble_attached= 2021 BLE_ATTACHED= 2022 2023 #%x inc.r|@|src/def| 2024 #%x inc.r|@|src/util| 2025 2026 bleopt/declare -v debug_xtrace '' 2027 bleopt/declare -v debug_xtrace_ps4 '+ ' 2028 2029 ble/bin#freeze-utility-path "${_ble_init_posix_command_list[@]}" # <- this uses ble/util/assign. 2030 ble/bin#freeze-utility-path man 2031 ble/bin#freeze-utility-path groff nroff mandoc gzip bzcat lzcat xzcat # used by core-complete.sh 2032 2033 ble/function#trace trap ble/builtin/trap ble/builtin/trap/finalize 2034 ble/function#trace ble/builtin/trap/.handler ble/builtin/trap/invoke ble/builtin/trap/invoke.sandbox 2035 ble/builtin/trap/install-hook EXIT 2036 ble/builtin/trap/install-hook INT 2037 ble/builtin/trap/install-hook ERR inactive 2038 ble/builtin/trap/install-hook RETURN inactive 2039 2040 # @var _ble_base_session 2041 # @var BLE_SESSION_ID 2042 function ble/base/initialize-session { 2043 [[ $_ble_base_session == */"$$" ]] && return 0 2044 2045 local start_time= 2046 if ((_ble_bash>=50000)); then 2047 start_time=${EPOCHREALTIME//[!0-9]} 2048 elif ((_ble_bash>=40200)); then 2049 printf -v start_time '%(%s)T' -1 2050 ((start_time*=1000000)) 2051 else 2052 ble/util/assign start_time 'ble/bin/date +%s' 2053 ((start_time*=1000000)) 2054 fi 2055 ((start_time-=SECONDS*1000000)) 2056 2057 _ble_base_session=${start_time::${#start_time}-6}.${start_time:${#start_time}-6}/$$ 2058 BLE_SESSION_ID=$_ble_base_session 2059 } 2060 ble/base/initialize-session 2061 2062 #%x inc.r|@|src/decode| 2063 #%x inc.r|@|src/color| 2064 #%x inc.r|@|src/canvas| 2065 #%x inc.r|@|src/history| 2066 #%x inc.r|@|src/edit| 2067 #%x inc.r|@|lib/core-cmdspec-def| 2068 #%x inc.r|@|lib/core-syntax-def| 2069 #%x inc.r|@|lib/core-complete-def| 2070 #%x inc.r|@|lib/core-debug-def| 2071 #%x inc.r|@|contrib/integration/bash-preexec-def| 2072 2073 bleopt -I 2074 #------------------------------------------------------------------------------ 2075 #%if measure_load_time 2076 time { 2077 #%end 2078 2079 ## @fn ble [SUBCOMMAND] 2080 ## 2081 ## 無引数で呼び出した時、現在 ble.sh の内部空間に居るかどうかを判定します。 2082 ## 2083 # Bluetooth Low Energy のツールが存在するかもしれない 2084 ble/bin#freeze-utility-path ble 2085 function ble/dispatch/.help { 2086 ble/util/print-lines \ 2087 'usage: ble [SUBCOMMAND [ARGS...]]' \ 2088 '' \ 2089 'SUBCOMMAND' \ 2090 ' # Manage ble.sh' \ 2091 ' attach ... alias of ble-attach' \ 2092 ' detach ... alias of ble-detach' \ 2093 ' update ... alias of ble-update' \ 2094 ' reload ... alias of ble-reload' \ 2095 ' help ... Show this help' \ 2096 ' version ... Show version' \ 2097 ' check ... Run unit tests' \ 2098 '' \ 2099 ' # Configuration' \ 2100 ' opt ... alias of bleopt' \ 2101 ' bind ... alias of ble-bind' \ 2102 ' face ... alias of ble-face' \ 2103 ' hook ... alias of blehook' \ 2104 ' sabbrev ... alias of ble-sabbrev' \ 2105 ' palette ... alias of ble-color-show' \ 2106 '' 2107 } 2108 function ble/dispatch { 2109 if (($#==0)); then 2110 [[ $_ble_attached && ! $_ble_edit_exec_inside_userspace ]] 2111 return "$?" 2112 fi 2113 2114 # import autoload measure assert stackdump color-show decode-{byte,char,key} 2115 local cmd=$1; shift 2116 case $cmd in 2117 (attach) ble-attach "$@" ;; 2118 (detach) ble-detach "$@" ;; 2119 (update) ble-update "$@" ;; 2120 (reload) ble-reload "$@" ;; 2121 (face) ble-face "$@" ;; 2122 (bind) ble-bind "$@" ;; 2123 (opt) bleopt "$@" ;; 2124 (hook) blehook "$@" ;; 2125 (sabbrev) ble-sabbrev "$@" ;; 2126 (palette) ble-palette "$@" ;; 2127 (help|--help) ble/dispatch/.help "$@" ;; 2128 (version|--version) ble/util/print "ble.sh, version $BLE_VERSION (noarch)" ;; 2129 (check|--test) ble/base/sub:test "$@" ;; 2130 (*) 2131 if ble/string#match "$cmd" '^[-a-z0-9]+$' && ble/is-function "ble-$cmd"; then 2132 "ble-$cmd" "$@" 2133 elif ble/is-function ble/bin/ble; then 2134 ble/bin/ble "$cmd" "$@" 2135 else 2136 ble/util/print "ble (ble.sh): unrecognized subcommand '$cmd'." >&2 2137 return 2 2138 fi 2139 esac 2140 } 2141 function ble { ble/dispatch "$@"; } 2142 2143 2144 # blerc 2145 _ble_base_rcfile= 2146 _ble_base_rcfile_initialized= 2147 function ble/base/load-rcfile { 2148 [[ $_ble_base_rcfile_initialized ]] && return 0 2149 _ble_base_rcfile_initialized=1 2150 2151 # blerc 2152 if [[ ! $_ble_base_rcfile ]]; then 2153 { _ble_base_rcfile=$HOME/.blerc; [[ -f $_ble_base_rcfile ]]; } || 2154 { _ble_base_rcfile=${XDG_CONFIG_HOME:-$HOME/.config}/blesh/init.sh; [[ -f $_ble_base_rcfile ]]; } || 2155 _ble_base_rcfile=$HOME/.blerc 2156 fi 2157 if [[ -s $_ble_base_rcfile ]]; then 2158 source "$_ble_base_rcfile" 2159 blehook/.compatibility-ble-0.3/check 2160 fi 2161 } 2162 2163 ## @fn ble-attach [opts] 2164 function ble-attach { 2165 #%if leakvar 2166 ble/debug/leakvar#check $"leakvar" A1-begin 2167 #%end.i 2168 if (($# >= 2)); then 2169 ble/util/print-lines \ 2170 'usage: ble-attach [opts]' \ 2171 'Attach to ble.sh.' >&2 2172 [[ $1 != --help ]] && return 2 2173 return 0 2174 fi 2175 2176 #%if leakvar 2177 ble/debug/leakvar#check $"leakvar" A2-arg 2178 #%end.i 2179 # when detach flag is present 2180 if [[ $_ble_edit_detach_flag ]]; then 2181 case $_ble_edit_detach_flag in 2182 (exit) return 0 ;; 2183 (*) _ble_edit_detach_flag= ;; # cancel "detach" 2184 esac 2185 fi 2186 2187 [[ ! $_ble_attached ]] || return 0 2188 _ble_attached=1 2189 BLE_ATTACHED=1 2190 2191 #%if leakvar 2192 ble/debug/leakvar#check $"leakvar" A3-guard 2193 #%end.i 2194 # 特殊シェル設定を待避 2195 builtin eval -- "$_ble_bash_FUNCNEST_adjust" 2196 ble/base/adjust-builtin-wrappers-1 2197 ble/base/adjust-bash-options 2198 ble/base/adjust-POSIXLY_CORRECT 2199 ble/base/adjust-builtin-wrappers-2 2200 ble/base/adjust-BASH_REMATCH 2201 2202 #%if leakvar 2203 ble/debug/leakvar#check $"leakvar" A4-adjust 2204 #%end.i 2205 if [[ ${IN_NIX_SHELL-} ]]; then 2206 # nix-shell rc の中から実行している時は強制的に prompt-attach にする 2207 if [[ "${BASH_SOURCE[*]}" == */rc && $1 != *:force:* ]]; then 2208 ble/base/install-prompt-attach 2209 _ble_attached= 2210 BLE_ATTACHED= 2211 ble/base/restore-BASH_REMATCH 2212 ble/base/restore-bash-options 2213 ble/base/restore-POSIXLY_CORRECT 2214 ble/base/restore-builtin-wrappers 2215 #%if leakvar 2216 ble/debug/leakvar#check $"leakvar" A4b1 2217 #%end.i 2218 builtin eval -- "$_ble_bash_FUNCNEST_restore" 2219 return 0 2220 fi 2221 2222 # nix-shell は BASH を誤った値に書き換えるので上書きする。 2223 local ret 2224 ble/util/readlink "/proc/$$/exe" 2225 [[ -x $ret ]] && BASH=$ret 2226 #%if leakvar 2227 ble/debug/leakvar#check $"leakvar" A4b2 2228 #%end.i 2229 fi 2230 2231 # char_width_mode=auto 2232 ble/canvas/attach 2233 #%if leakvar 2234 ble/debug/leakvar#check $"leakvar" A5-canvas 2235 #%end.i 2236 2237 # 取り敢えずプロンプトを表示する 2238 ble/term/enter # 3ms (起動時のずれ防止の為 stty) 2239 ble-edit/initialize # 3ms 2240 ble-edit/attach # 0ms (_ble_edit_PS1 他の初期化) 2241 ble/canvas/panel/render # 37ms 2242 ble/util/buffer.flush >&2 2243 #%if leakvar 2244 ble/debug/leakvar#check $"leakvar" A6-term/edit 2245 #%end.i 2246 2247 # keymap 初期化 2248 local IFS=$_ble_term_IFS 2249 ble/decode/initialize # 7ms 2250 ble/decode/reset-default-keymap # 264ms (keymap/vi.sh) 2251 #%if leakvar 2252 ble/debug/leakvar#check $"leakvar" A7-decode 2253 #%end.i 2254 if ! ble/decode/attach; then # 53ms 2255 _ble_attached= 2256 BLE_ATTACHED= 2257 ble-edit/detach 2258 ble/term/leave 2259 ble/base/restore-BASH_REMATCH 2260 ble/base/restore-bash-options 2261 ble/base/restore-POSIXLY_CORRECT 2262 ble/base/restore-builtin-wrappers 2263 builtin eval -- "$_ble_bash_FUNCNEST_restore" 2264 #%if leakvar 2265 ble/debug/leakvar#check $"leakvar" A7b1 2266 #%end.i 2267 return 1 2268 fi 2269 2270 ble/history:bash/reset # 27s for bash-3.0 2271 #%if leakvar 2272 ble/debug/leakvar#check $"leakvar" A8-history 2273 #%end.i 2274 2275 blehook/invoke ATTACH 2276 #%if leakvar 2277 ble/debug/leakvar#check $"leakvar" A9-ATTACH 2278 #%end.i 2279 2280 # Note: 再描画 (初期化中のエラーメッセージ・プロンプト変更等の為) 2281 ble/textarea#redraw 2282 #%if leakvar 2283 ble/debug/leakvar#check $"leakvar" A10-redraw 2284 #%end.i 2285 2286 # Note: ble-decode/{initialize,reset-default-keymap} 内で 2287 # info を設定する事があるので表示する。 2288 ble/edit/info/default 2289 #%if leakvar 2290 ble/debug/leakvar#check $"leakvar" A11-info 2291 #%end.i 2292 ble-edit/bind/.tail 2293 #%if leakvar 2294 ble/debug/leakvar#check $"leakvar" A12-tail 2295 #%end.i 2296 } 2297 2298 function ble-detach { 2299 if (($#)); then 2300 ble/base/print-usage-for-no-argument-command 'Detach from ble.sh.' "$@" 2301 return "$?" 2302 fi 2303 2304 [[ $_ble_attached && ! $_ble_edit_detach_flag ]] || return 1 2305 2306 # Note: 実際の detach 処理は ble-edit/bind/.check-detach で実行される 2307 _ble_edit_detach_flag=${1:-detach} # schedule detach 2308 } 2309 function ble-detach/impl { 2310 [[ $_ble_attached ]] || return 1 2311 _ble_attached= 2312 BLE_ATTACHED= 2313 blehook/invoke DETACH 2314 2315 ble-edit/detach 2316 ble/decode/detach 2317 READLINE_LINE='' READLINE_POINT=0 2318 } 2319 function ble-detach/message { 2320 ble/util/buffer.flush >&2 2321 printf '%s\n' "$@" 1>&2 2322 ble/edit/info/clear 2323 ble/textarea#render 2324 ble/util/buffer.flush >&2 2325 } 2326 2327 function ble/base/unload-for-reload { 2328 if [[ $_ble_attached ]]; then 2329 ble-detach/impl 2330 ble/util/print "${_ble_term_setaf[12]}[ble: reload]$_ble_term_sgr0" 1>&2 2331 [[ $_ble_edit_detach_flag ]] || 2332 _ble_edit_detach_flag=reload 2333 fi 2334 ble/base/unload reload 2335 return 0 2336 } 2337 ## @fn ble/base/unload [opts] 2338 function ble/base/unload { 2339 ble/util/is-running-in-subshell && return 1 2340 local IFS=$_ble_term_IFS 2341 ble/term/stty/TRAPEXIT "$1" 2342 ble/term/leave 2343 ble/util/buffer.flush >&2 2344 blehook/invoke unload 2345 ble/decode/keymap#unload 2346 ble-edit/bind/clear-keymap-definition-loader 2347 ble/builtin/trap/finalize "$1" 2348 ble/util/import/finalize 2349 ble/fd#finalize 2350 ble/base/clean-up-runtime-directory finalize 2351 builtin unset -v _ble_bash BLE_VERSION BLE_VERSINFO 2352 return 0 2353 } 2354 2355 ## @var _ble_base_attach_from_prompt 2356 ## 非空文字列の時、PROMPT_COMMAND 経由の ble-attach を現在試みている最中です。 2357 ## 2358 ## @arr _ble_base_attach_PROMPT_COMMAND 2359 ## PROMPT_COMMAND 経由の ble-attach をする時、元々の PROMPT_COMMAND の値を保 2360 ## 持する配列です。複数回 ble.sh をロードした時に、各ロード時に待避した 2361 ## PROMPT_COMMAND の値を配列の各要素に保持します。 2362 ## 2363 ## Note #D1851: 以前の ble.sh ロード時に設定された値を保持したいので、既に要 2364 ## 素がある場合にはクリアしない。 2365 _ble_base_attach_from_prompt= 2366 ((${#_ble_base_attach_PROMPT_COMMAND[@]})) || 2367 _ble_base_attach_PROMPT_COMMAND=() 2368 ## @fn ble/base/install-prompt-attach 2369 function ble/base/install-prompt-attach { 2370 [[ ! $_ble_base_attach_from_prompt ]] || return 0 2371 _ble_base_attach_from_prompt=1 2372 if ((_ble_bash>=50100)); then 2373 ((${#PROMPT_COMMAND[@]})) || PROMPT_COMMAND[0]= 2374 ble/array#push PROMPT_COMMAND ble/base/attach-from-PROMPT_COMMAND 2375 if [[ $_ble_edit_detach_flag == reload ]]; then 2376 _ble_edit_detach_flag=prompt-attach 2377 blehook internal_PRECMD!=ble/base/attach-from-PROMPT_COMMAND 2378 fi 2379 else 2380 local save_index=${#_ble_base_attach_PROMPT_COMMAND[@]} 2381 _ble_base_attach_PROMPT_COMMAND[save_index]=${PROMPT_COMMAND-} 2382 ble/function#lambda PROMPT_COMMAND \ 2383 "ble/base/attach-from-PROMPT_COMMAND $save_index \"\$FUNCNAME\"" 2384 ble/function#trace "$PROMPT_COMMAND" 2385 if [[ $_ble_edit_detach_flag == reload ]]; then 2386 _ble_edit_detach_flag=prompt-attach 2387 blehook internal_PRECMD!="$PROMPT_COMMAND" 2388 fi 2389 fi 2390 } 2391 _ble_base_attach_from_prompt_lastexit= 2392 _ble_base_attach_from_prompt_lastarg= 2393 _ble_base_attach_from_prompt_PIPESTATUS=() 2394 ## @fn ble/base/attach-from-PROMPT_COMMAND prompt_command lambda 2395 function ble/base/attach-from-PROMPT_COMMAND { 2396 # 後続の設定によって PROMPT_COMMAND が置換された場合にはそれを保持する 2397 { 2398 # save $?, $_ and ${PIPE_STATUS[@]} 2399 _ble_base_attach_from_prompt_lastexit=$? \ 2400 _ble_base_attach_from_prompt_lastarg=$_ \ 2401 _ble_base_attach_from_prompt_PIPESTATUS=("${PIPESTATUS[@]}") 2402 #%if measure_load_time 2403 ble/util/print "ble.sh: $EPOCHREALTIME start prompt-attach" >&2 2404 #%end 2405 if ((BASH_LINENO[${#BASH_LINENO[@]}-1]>=1)); then 2406 # 既にコマンドを実行している時にはそのコマンドの結果を記録する 2407 _ble_edit_exec_lastexit=$_ble_base_attach_from_prompt_lastexit 2408 _ble_edit_exec_lastarg=$_ble_base_attach_from_prompt_lastarg 2409 _ble_edit_exec_PIPESTATUS=("${_ble_base_attach_from_prompt_PIPESTATUS[@]}") 2410 # Note: 本当は一つ前のコマンドを知りたいが確実な方法がないのでこの関数の名前を入れておく。 2411 _ble_edit_exec_BASH_COMMAND=$FUNCNAME 2412 fi 2413 2414 local is_last_PROMPT_COMMAND=1 2415 if (($#==0)); then 2416 if local ret; ble/array#index PROMPT_COMMAND ble/base/attach-from-PROMPT_COMMAND; then 2417 local keys; keys=("${!PROMPT_COMMAND[@]}") 2418 ((ret==keys[${#keys[@]}-1])) || is_last_PROMPT_COMMAND= 2419 ble/idict#replace PROMPT_COMMAND ble/base/attach-from-PROMPT_COMMAND 2420 fi 2421 blehook internal_PRECMD-=ble/base/attach-from-PROMPT_COMMAND || ((1)) # set -e 対策 2422 else 2423 local save_index=$1 lambda=$2 2424 2425 # 待避していた内容を復元・実行 2426 local PROMPT_COMMAND=${_ble_base_attach_PROMPT_COMMAND[save_index]} 2427 local ble_base_attach_from_prompt_command=processing 2428 ble/prompt/update/.eval-prompt_command 2>&3 2429 ble/util/unlocal ble_base_attach_from_prompt_command 2430 _ble_base_attach_PROMPT_COMMAND[save_index]=$PROMPT_COMMAND 2431 ble/util/unlocal PROMPT_COMMAND 2432 2433 # 可能なら自身を各 hook から除去 2434 blehook internal_PRECMD-="$lambda" || ((1)) # set -e 対策 2435 if [[ $PROMPT_COMMAND == "$lambda" ]]; then 2436 PROMPT_COMMAND=${_ble_base_attach_PROMPT_COMMAND[save_index]} 2437 else 2438 is_last_PROMPT_COMMAND= 2439 fi 2440 2441 # #D1354: 入れ子の ble/base/attach-from-PROMPT_COMMAND の時は一番 2442 # 外側で ble-attach を実行する様にする。3>&2 2>/dev/null のリダ 2443 # イレクトにより stdout.off の効果が巻き戻されるのを防ぐ為。 2444 [[ ${ble_base_attach_from_prompt_command-} != processing ]] || return 0 2445 fi 2446 2447 # 既に attach 状態の時は処理はスキップ 2448 [[ $_ble_base_attach_from_prompt ]] || return 0 2449 _ble_base_attach_from_prompt= 2450 2451 # Note #D1778: この attach-from-PROMPT_COMMAND が PROMPT_COMMAND 2452 # 処理の最後と見做せる場合、この時点で PROMPT_COMMAND は一通り終 2453 # わったと見做せるので、ble-attach 内部で改めて PROMPT_COMMAND 2454 # を実行する必要はなくなる。それを伝える為に中間状態の 2455 # _ble_prompt_hash の値を設定する。 2456 # Note #D1778: bash-preexec 経由でプロンプトを設定しようとしている 2457 # 場合は、この時点で既に PRECMD に hook が移動している可能性があ 2458 # るので PRECMD も発火しておく (PROMPT_COMMAND と PRECMD の順序 2459 # が逆になるが仕方がない。問題になれば後で考える)。 2460 if [[ $is_last_PROMPT_COMMAND ]]; then 2461 ble-edit/exec:gexec/invoke-hook-with-setexit internal_PRECMD 2462 ble-edit/exec:gexec/invoke-hook-with-setexit PRECMD 2463 _ble_prompt_hash=$COLUMNS:$_ble_edit_lineno:prompt_attach 2464 fi 2465 } 3>&2 2>/dev/null # set -x 対策 #D0930 2466 2467 ble-attach force 2468 2469 # Note: 何故か分からないが PROMPT_COMMAND から ble-attach すると 2470 # ble/bin/stty や ble/bin/mkfifo や tty 2>/dev/null などが 2471 # ジョブとして表示されてしまう。joblist.flush しておくと平気。 2472 # これで取り逃がすジョブもあるかもしれないが仕方ない。 2473 ble/util/joblist.flush &>/dev/null 2474 ble/util/joblist.check 2475 #%if measure_load_time 2476 ble/util/print "ble.sh: $EPOCHREALTIME end prompt-attach" >&2 2477 #%end 2478 } 2479 2480 function ble/base/process-blesh-arguments { 2481 local opts=$_ble_base_arguments_opts 2482 local attach=$_ble_base_arguments_attach 2483 local inputrc=$_ble_base_arguments_inputrc 2484 2485 _ble_base_rcfile=$_ble_base_arguments_rcfile 2486 2487 # reconstruction type of user-bindings 2488 _ble_decode_initialize_inputrc=$inputrc 2489 2490 #%if measure_load_time 2491 time { 2492 #%end 2493 ble/base/load-rcfile # blerc 2494 #%if measure_load_time 2495 ble/debug/measure-set-timeformat "blerc: '$_ble_base_rcfile'"; } 2496 #%end 2497 ble/util/invoke-hook BLE_ONLOAD 2498 2499 # attach 2500 case $attach in 2501 (attach) ble-attach ;; 2502 (prompt) ble/base/install-prompt-attach ;; 2503 (none) ;; 2504 (*) ble/util/print "ble.sh: unrecognized attach method --attach='$attach'." ;; 2505 esac 2506 } 2507 2508 function ble/base/sub:test { 2509 local error= logfile= 2510 2511 [[ ${LANG-} ]] || local LANG=en_US.UTF-8 2512 2513 ble-import lib/core-test 2514 2515 if (($#==0)); then 2516 set -- bash main util canvas decode edit syntax complete 2517 logfile=$_ble_base_cache/test.$(date +'%Y%m%d.%H%M%S').log 2518 : >| "$logfile" 2519 ble/test/log#open "$logfile" 2520 fi 2521 2522 if ((!_ble_make_command_check_count)); then 2523 ble/test/log "MACHTYPE: $MACHTYPE" 2524 ble/test/log "BLE_VERSION: $BLE_VERSION" 2525 fi 2526 ble/test/log "BASH_VERSION: $BASH_VERSION" 2527 local line='locale:' var ret 2528 for var in LANG "${!LC_@}"; do 2529 ble/string#quote-word "${!var}" 2530 line="$line $var=$ret" 2531 done 2532 ble/test/log "$line" 2533 2534 local section 2535 for section; do 2536 local file=$_ble_base/lib/test-$section.sh 2537 if [[ -f $file ]]; then 2538 source "$file" || error=1 2539 else 2540 ble/test/log "ERROR: Test '$section' is not defined." 2541 error=1 2542 fi 2543 done 2544 2545 if [[ $logfile ]]; then 2546 ble/test/log#close 2547 ble/util/print "ble.sh: The test log was saved to '${_ble_term_setaf[4]}$logfile$_ble_term_sgr0'." 2548 fi 2549 [[ ! $error ]] 2550 } 2551 function ble/base/sub:update { ble-update; } 2552 function ble/base/sub:clear-cache { 2553 (shopt -u failglob; ble/bin/rm -rf "$_ble_base_cache"/*) 2554 } 2555 function ble/base/sub:lib { :; } # do nothing 2556 2557 #%if measure_load_time 2558 ble/debug/measure-set-timeformat ble.pp/epilogue; } 2559 #%end 2560 2561 # Note: ble-attach 及びそれを呼び出す可能性がある物には DEBUG trap を 2562 # 継承させる。これはユーザーの設定した user trap を正しく抽出する為 2563 # に必要。現在は ble-attach から呼び出される ble-edit/attach で処理 2564 # している。 2565 ble/function#trace ble-attach 2566 ble/function#trace ble 2567 ble/function#trace ble/dispatch 2568 ble/function#trace ble/base/attach-from-PROMPT_COMMAND 2569 2570 # Note #D1775: 以下は ble/base/unload 時に元の trap または ble.sh 有効時にユー 2571 # ザーが設定した trap を復元する為に用いる物。ble/base/unload は中で 2572 # ble/builtin/trap/finalize を呼び出す。ble/builtin/trap/finalize は別の箇所 2573 # で ble/function#trace されている。 2574 ble/function#trace ble/base/unload 2575 2576 ble-import -f lib/_package 2577 if [[ $_ble_init_command ]]; then 2578 ble/base/sub:"${_ble_init_command[@]}"; _ble_init_exit=$? 2579 [[ $_ble_init_attached ]] && ble-attach 2580 ble/util/setexit "$_ble_init_exit" 2581 else 2582 ble/base/process-blesh-arguments "$@" 2583 fi 2584 2585 #%if measure_load_time 2586 ble/debug/measure-set-timeformat Total nofork; } 2587 _ble_init_exit=$? 2588 echo "ble.sh: $EPOCHREALTIME load end" >&2 2589 ble/util/setexit "$_ble_init_exit" 2590 #%end 2591 2592 ble/init/clean-up check-attach 2>/dev/null # set -x 対策 #D0930 2593 { builtin eval "return $? || exit $?"; } 2>/dev/null # set -x 対策 #D0930 2594 ###############################################################################