# Copyright 2015 Koichi Murase . All rights reserved. # This script is a part of blesh (https://github.com/akinomyoga/ble.sh) # provided under the BSD-3-Clause license. Do not edit this file because this # is not the original source code: Various pre-processing has been applied. # Also, the code comments and blank lines are stripped off in the installation # process. Please find the corresponding source file(s) in the repository # "akinomyoga/ble.sh". # # Source: /ble.pp # Source: /src/benchmark.sh # Source: /src/canvas.GraphemeClusterBreak.sh # Source: /src/canvas.c2w.musl.sh # Source: /src/canvas.c2w.sh # Source: /src/canvas.emoji.sh # Source: /src/canvas.sh # Source: /src/color.sh # Source: /src/decode.sh # Source: /src/def.sh # Source: /src/edit.sh # Source: /src/history.sh # Source: /src/util.hook.sh # Source: /src/util.sh { _ble_init_version=0.4.0-nightly+75c4a84 _ble_init_exit= _ble_init_command= for _ble_init_arg; do case $_ble_init_arg in --version) _ble_init_exit=0 echo "ble.sh (Bash Line Editor), version $_ble_init_version" ;; --help) _ble_init_exit=0 printf '%s\n' \ "# ble.sh (Bash Line Editor), version $_ble_init_version" \ 'usage: source ble.sh [OPTION...]' \ '' \ 'OPTION' \ '' \ ' --help' \ ' Show this help and exit' \ ' --version' \ ' Show version and exit' \ ' --test' \ ' Run test and exit' \ ' --update' \ ' Update ble.sh and exit' \ ' --clear-cache' \ ' Clear ble.sh cache and exit' \ ' --install PREFIX' \ ' Install ble.sh and exit' \ '' \ ' --rcfile=BLERC' \ ' --init-file=BLERC' \ ' Specify the ble init file. The default is ~/.blerc if any, or' \ ' ~/.config/blesh/init.sh.' \ '' \ ' --norc' \ ' Do not load the ble init file.' \ '' \ ' --attach=ATTACH' \ ' --noattach' \ ' The option "--attach" selects the strategy of "ble-attach" from the list:' \ ' ATTACH = "attach" | "prompt" | "none". The default strategy is "prompt".' \ ' When "attach" is specified, ble.sh immediately attaches to the session in' \ ' "source ble.sh". When "prompt" is specified, ble.sh attaches to the' \ ' session before the first prompt using PROMPT_COMMAND. When "none" is' \ ' specified, ble.sh does not attach to the session automatically, so' \ ' ble-attach needs to be called explicitly. The option "--noattach" is a' \ ' synonym for "--attach=none".' \ '' \ ' --inputrc=TYPE' \ ' --noinputrc' \ ' The option "--inputrc" selects the strategy of reconstructing user' \ ' keybindings from the list: "auto" (default), "diff", "all", "user", "none".' \ ' When "diff" is specified, user keybindings are extracted by the diff of the' \ ' outputs of the "bind" builtin between the current session and the plain' \ ' Bash. When "all" is specified, the user keybindings are extracted from' \ ' /etc/inputrc and ${INPUTRC:-~/.inputrc*}. When "user" is specified, the' \ ' user keybindings are extracted from ${INPUTRC:-~/.inputrc*}. When "none"' \ ' is specified, the user keybindings are not reconstructed from the state of' \ ' Readline, and only the bindings by "ble-bind" are applied. The option' \ ' "--noinputrc" is a synonym for "--inputrc=none".' \ '' \ ' --keep-rlvars' \ ' Do not change readline settings for ble.sh' \ '' \ ' --bash-debug-version=TYPE' \ ' This controls the warning mesage for the debug version of Bash. When' \ ' "full" is specified to TYPE, ble.sh prints the full message to the terminal' \ ' when it is loaded in a debug version of Bash. This is the default. When' \ ' "short" is specified, a short version of the message is printed. When' \ ' "once" is specified, the full message is printed only once for a specific' \ ' version of debug Bash. When "ignore" is specified, the message is not' \ ' printed even when ble.sh is loaded in a debug version of Bash.' \ '' \ ' -o BLEOPT=VALUE' \ ' Set a value for the specified bleopt option.' \ ' --debug-bash-output' \ ' Internal settings for debugging' \ '' ;; --test | --update | --clear-cache | --lib | --install) _ble_init_command=1 ;; esac done unset _ble_init_arg if [ -n "$_ble_init_exit" ]; then unset _ble_init_exit unset _ble_init_command unset _ble_init_version return 0 2>/dev/null || exit 0 fi } 2>/dev/null # set -x 対策 #D0930 if [ -z "${BASH_VERSION-}" ]; then echo "ble.sh: This shell is not Bash. Please use this script with Bash." >&3 unset _ble_init_exit unset _ble_init_command unset _ble_init_version return 1 2>/dev/null || exit 1 fi 3>&2 >/dev/null 2>&1 # set -x 対策 #D0930 if [ -z "${BASH_VERSINFO-}" ] || [ "${BASH_VERSINFO-0}" -lt 3 ]; then echo "ble.sh: Bash with a version under 3.0 is not supported." >&3 unset -v _ble_init_exit _ble_init_command _ble_init_version return 1 2>/dev/null || exit 1 fi 3>&2 >/dev/null 2>&1 # set -x 対策 #D0930 if [[ ! $_ble_init_command ]]; then if [[ ${BASH_EXECUTION_STRING+set} ]]; then _ble_init_exit=1 elif ((BASH_SUBSHELL)); then builtin echo "ble.sh: ble.sh cannot be loaded into a subshell." >&3 _ble_init_exit=1 elif [[ $- != *i* ]]; then case " ${BASH_SOURCE[*]##*/} " in (*' .bashrc '* | *' .bash_profile '* | *' .profile '* | *' bashrc '* | *' profile '*) ((0)) ;; esac && builtin echo "ble.sh: This is not an interactive session." >&3 || ((1)) _ble_init_exit=1 elif ! [[ -t 4 && -t 5 ]] && ! { [[ ${bleopt_connect_tty-} ]] && >/dev/tty; }; then if [[ ${bleopt_connect_tty-} ]]; then builtin echo "ble.sh: cannot find a controlling TTY/PTY in this session." >&3 else builtin echo "ble.sh: stdout/stdin are not connected to TTY/PTY." >&3 fi _ble_init_exit=1 elif [[ ${NRF_CONNECT_VSCODE-} && ! -t 3 ]]; then _ble_init_exit=1 fi if [[ $_ble_init_exit ]]; then builtin unset -v _ble_init_exit _ble_init_command _ble_init_version return 1 2>/dev/null || builtin exit 1 fi fi 3>&2 4<&0 5>&1 &>/dev/null # set -x 対策 #D0930 { _ble_bash=$((BASH_VERSINFO[0]*10000+BASH_VERSINFO[1]*100+BASH_VERSINFO[2])) _ble_bash_POSIXLY_CORRECT_adjusted=1 _ble_bash_POSIXLY_CORRECT_set=${POSIXLY_CORRECT+set} _ble_bash_POSIXLY_CORRECT=${POSIXLY_CORRECT-} POSIXLY_CORRECT=y _ble_bash_expand_aliases= \shopt -q expand_aliases && _ble_bash_expand_aliases=1 && \shopt -u expand_aliases || ((1)) _ble_bash_FUNCNEST_adjusted= _ble_bash_FUNCNEST= _ble_bash_FUNCNEST_set= _ble_bash_FUNCNEST_adjust=' if [[ ! $_ble_bash_FUNCNEST_adjusted ]]; then _ble_bash_FUNCNEST_adjusted=1 _ble_bash_FUNCNEST_set=${FUNCNEST+set} _ble_bash_FUNCNEST=${FUNCNEST-} \builtin unset -v FUNCNEST fi 2>/dev/null' _ble_bash_FUNCNEST_restore=' if [[ $_ble_bash_FUNCNEST_adjusted ]]; then _ble_bash_FUNCNEST_adjusted= if [[ $_ble_bash_FUNCNEST_set ]]; then FUNCNEST=$_ble_bash_FUNCNEST else \builtin unset -v FUNCNEST fi fi 2>/dev/null' \builtin eval -- "$_ble_bash_FUNCNEST_adjust" \builtin unset -v POSIXLY_CORRECT _ble_bash_POSIXLY_CORRECT_adjust=' if [[ ! ${_ble_bash_POSIXLY_CORRECT_adjusted-} ]]; then _ble_bash_POSIXLY_CORRECT_adjusted=1 _ble_bash_POSIXLY_CORRECT_set=${POSIXLY_CORRECT+set} _ble_bash_POSIXLY_CORRECT=${POSIXLY_CORRECT-} if [[ $_ble_bash_POSIXLY_CORRECT_set ]]; then \builtin unset -v POSIXLY_CORRECT fi ble/base/workaround-POSIXLY_CORRECT fi' _ble_bash_POSIXLY_CORRECT_unset=' if [[ ${POSIXLY_CORRECT+set} ]]; then \builtin unset -v POSIXLY_CORRECT ble/base/workaround-POSIXLY_CORRECT fi' _ble_bash_POSIXLY_CORRECT_local_adjust=' \builtin local _ble_local_POSIXLY_CORRECT _ble_local_POSIXLY_CORRECT_set _ble_local_POSIXLY_CORRECT_set=${POSIXLY_CORRECT+set} _ble_local_POSIXLY_CORRECT=${POSIXLY_CORRECT-} '$_ble_bash_POSIXLY_CORRECT_unset _ble_bash_POSIXLY_CORRECT_local_leave=' if [[ $_ble_local_POSIXLY_CORRECT_set ]]; then POSIXLY_CORRECT=$_ble_local_POSIXLY_CORRECT fi' _ble_bash_POSIXLY_CORRECT_local_enter=' _ble_local_POSIXLY_CORRECT_set=${POSIXLY_CORRECT+set} _ble_local_POSIXLY_CORRECT=${POSIXLY_CORRECT-} '$_ble_bash_POSIXLY_CORRECT_unset _ble_bash_POSIXLY_CORRECT_local_return=' \builtin local _ble_local_POSIXLY_CORRECT_ext=$? if [[ $_ble_local_POSIXLY_CORRECT_set ]]; then POSIXLY_CORRECT=$_ble_local_POSIXLY_CORRECT fi \return "$_ble_local_POSIXLY_CORRECT_ext"' } 2>/dev/null function ble/base/workaround-POSIXLY_CORRECT { true } function ble/base/restore-POSIXLY_CORRECT { if [[ ! $_ble_bash_POSIXLY_CORRECT_adjusted ]]; then return 0; fi # Note: set -e の為 || は駄目 _ble_bash_POSIXLY_CORRECT_adjusted= if [[ $_ble_bash_POSIXLY_CORRECT_set ]]; then POSIXLY_CORRECT=$_ble_bash_POSIXLY_CORRECT else builtin eval -- "$_ble_bash_POSIXLY_CORRECT_unset" fi } function ble/base/is-POSIXLY_CORRECT { [[ $_ble_bash_POSIXLY_CORRECT_adjusted && $_ble_bash_POSIXLY_CORRECT_set ]] } if ((_ble_bash>=40100)); then function ble/base/list-shopt { shopt=$BASHOPTS; } else function ble/base/list-shopt { shopt= local name for name; do shopt -q "$name" 2>/dev/null && shopt=$shopt:$name done } fi 2>/dev/null # set -x 対策 function ble/base/evaldef { local shopt ble/base/list-shopt extglob expand_aliases shopt -s extglob shopt -u expand_aliases builtin eval -- "$1"; local ext=$? [[ :$shopt: == *:extglob:* ]] || shopt -u extglob [[ :$shopt: != *:expand_aliases:* ]] || shopt -s expand_aliases return "$ext" } { _ble_bash_builtins_adjusted= _ble_bash_builtins_save= } 2>/dev/null # set -x 対策 function ble/base/adjust-builtin-wrappers/.assign { if [[ ${_ble_util_assign_base-} ]]; then local _ble_local_tmpfile; ble/util/assign/mktmp builtin eval -- "$1" >| "$_ble_local_tmpfile" local IFS= ble/bash/read -d '' defs < "$_ble_local_tmpfile" IFS=$_ble_term_IFS ble/util/assign/rmtmp else defs=$(builtin eval -- "$1") fi || ((1)) } function ble/base/adjust-builtin-wrappers/.impl1 { unset -f builtin builtin local builtins1 keywords1 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 builtin local defs ble/base/adjust-builtin-wrappers/.assign ' \builtin declare -f "${builtins1[@]}" || ((1)) \builtin alias "${builtins1[@]}" "${keywords1[@]}" || ((1))' # set -e 対策 _ble_bash_builtins_save=$defs fi builtin local POSIXLY_CORRECT=y builtin unset -f "${builtins1[@]}" builtin unalias "${builtins1[@]}" "${keywords1[@]}" || ((1)) # set -e 対策 builtin eval -- "$_ble_bash_POSIXLY_CORRECT_unset" } function ble/base/adjust-builtin-wrappers/.impl2 { local defs ble/base/adjust-builtin-wrappers/.assign 'LC_ALL= LC_MESSAGES=C builtin type :; alias :' || ((1)) # set -e 対策 defs=${defs#$': is a shell builtin\n'} _ble_bash_builtins_save=$_ble_bash_builtins_save$'\n'$defs builtin unset -f : builtin unalias : || ((1)) # set -e 対策 } function ble/base/adjust-builtin-wrappers { ble/base/adjust-builtin-wrappers/.impl1 builtin unset -v POSIXLY_CORRECT ble/base/adjust-builtin-wrappers/.impl2 } 2>/dev/null function ble/base/restore-builtin-wrappers { if [[ $_ble_bash_builtins_adjusted ]]; then _ble_bash_builtins_adjusted= ble/base/evaldef "$_ble_bash_builtins_save" return 0 fi } { ble/base/adjust-builtin-wrappers if [[ $_ble_bash_expand_aliases ]]; then shopt -s expand_aliases fi } 2>/dev/null # set -x 対策 function ble/variable#copy-state { local src=$1 dst=$2 if [[ ${!src+set} ]]; then builtin eval -- "$dst=\${$src}" else builtin unset -v "$dst[0]" 2>/dev/null || builtin unset -v "$dst" fi } { _ble_bash_xtrace=() _ble_bash_xtrace_debug_enabled= _ble_bash_xtrace_debug_filename= _ble_bash_xtrace_debug_fd= _ble_bash_XTRACEFD= _ble_bash_XTRACEFD_set= _ble_bash_XTRACEFD_dup= _ble_bash_PS4= } 2>/dev/null # set -x 対策 function ble/base/xtrace/.fdcheck { >&"$1"; } 2>/dev/null function ble/base/xtrace/.fdnext { 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 open=---- close=---- if ((_ble_bash>=40200)); then builtin printf '%s [%(%F %T %Z)T] %s %s\n' "$open" -1 "$1" "$close" else builtin printf '%s [%s] %s %s\n' "$open" "$(date 2>/dev/null)" "$1" "$close" fi >&"${BASH_XTRACEFD:-2}" } function ble/base/xtrace/adjust { local level=${#_ble_bash_xtrace[@]} IFS=$' \t\n' if [[ $- == *x* ]]; then _ble_bash_xtrace[level]=1 else _ble_bash_xtrace[level]= fi set +x ((_ble_bash>=40000&&level==0)) || return 0 _ble_bash_xtrace_debug_enabled= if [[ ${bleopt_debug_xtrace:-/dev/null} == /dev/null ]]; then if [[ $_ble_bash_xtrace_debug_fd ]]; then builtin eval "exec $_ble_bash_xtrace_debug_fd>&-" || return 0 # disable=#D2164 (here bash4+) _ble_bash_xtrace_debug_filename= _ble_bash_xtrace_debug_fd= fi else if [[ $_ble_bash_xtrace_debug_filename != "$bleopt_debug_xtrace" ]]; then _ble_bash_xtrace_debug_filename=$bleopt_debug_xtrace [[ $_ble_bash_xtrace_debug_fd ]] || ble/base/xtrace/.fdnext _ble_bash_xtrace_debug_fd builtin eval "exec $_ble_bash_xtrace_debug_fd>>\"$bleopt_debug_xtrace\"" || return 0 fi _ble_bash_XTRACEFD=${BASH_XTRACEFD-} _ble_bash_XTRACEFD_set=${BASH_XTRACEFD+set} if [[ ${BASH_XTRACEFD-} =~ ^[0-9]+$ ]] && ble/base/xtrace/.fdcheck "$BASH_XTRACEFD"; then ble/base/xtrace/.fdnext _ble_bash_XTRACEFD_dup builtin eval "exec $_ble_bash_XTRACEFD_dup>&$BASH_XTRACEFD" || return 0 builtin eval "exec $BASH_XTRACEFD>&$_ble_bash_xtrace_debug_fd" || return 0 else _ble_bash_XTRACEFD_dup= local newfd; ble/base/xtrace/.fdnext newfd builtin eval "exec $newfd>&$_ble_bash_xtrace_debug_fd" || return 0 BASH_XTRACEFD=$newfd fi ble/variable#copy-state PS4 _ble_base_PS4 PS4=${bleopt_debug_xtrace_ps4:-'+ '} _ble_bash_xtrace_debug_enabled=1 ble/base/xtrace/.log "$FUNCNAME" set -x fi } function ble/base/xtrace/restore { local level=$((${#_ble_bash_xtrace[@]}-1)) IFS=$' \t\n' ((level>=0)) || return 0 if [[ ${_ble_bash_xtrace[level]-} ]]; then set -x else set +x fi builtin unset -v '_ble_bash_xtrace[level]' ((_ble_bash>=40000&&level==0)) || return 0 if [[ $_ble_bash_xtrace_debug_enabled ]]; then ble/base/xtrace/.log "$FUNCNAME" _ble_bash_xtrace_debug_enabled= ble/variable#copy-state _ble_base_PS4 PS4 if [[ $_ble_bash_XTRACEFD_dup ]]; then builtin eval "exec $BASH_XTRACEFD>&$_ble_bash_XTRACEFD_dup" && builtin eval "exec $_ble_bash_XTRACEFD_dup>&-" || ((1)) # disable=#D2164 (here bash4+) else if [[ $_ble_bash_XTRACEFD_set ]]; then BASH_XTRACEFD=$_ble_bash_XTRACEFD else builtin unset -v BASH_XTRACEFD fi fi fi } function ble/base/.adjust-bash-options { builtin eval -- "$1=\$-" set +evukT -B ble/base/xtrace/adjust [[ $2 == shopt ]] || local shopt ble/base/list-shopt extdebug nocasematch [[ $2 == shopt ]] || builtin eval -- "$2=\$shopt" shopt -u extdebug shopt -u nocasematch 2>/dev/null return 0 } 2>/dev/null # set -x 対策 function ble/base/.restore-bash-options { local set=${!1} shopt=${!2} [[ :$shopt: == *:nocasematch:* ]] && shopt -s nocasematch [[ :$shopt: == *:extdebug:* ]] && shopt -s extdebug ble/base/xtrace/restore [[ $set == *B* ]] || set +B [[ $set == *T* ]] && set -T [[ $set == *k* ]] && set -k [[ $set == *u* ]] && set -u [[ $set == *v* ]] && set -v [[ $set == *e* ]] && set -e # set -e は最後 return 0 } 2>/dev/null # set -x 対策 { : "${_ble_bash_options_adjusted=}" _ble_bash_set=$- _ble_bash_shopt=${BASHOPTS-} } 2>/dev/null # set -x 対策 function ble/base/adjust-bash-options { [[ $_ble_bash_options_adjusted ]] && return 1 || ((1)) # set -e 対策 _ble_bash_options_adjusted=1 ble/base/.adjust-bash-options _ble_bash_set _ble_bash_shopt _ble_bash_expand_aliases= shopt -q expand_aliases 2>/dev/null && _ble_bash_expand_aliases=1 ble/variable#copy-state LC_ALL _ble_bash_LC_ALL if [[ ${LC_ALL-} ]]; then ble/variable#copy-state LC_CTYPE _ble_bash_LC_CTYPE ble/variable#copy-state LC_MESSAGES _ble_bash_LC_MESSAGES ble/variable#copy-state LC_NUMERIC _ble_bash_LC_NUMERIC ble/variable#copy-state LC_TIME _ble_bash_LC_TIME ble/variable#copy-state LANG _ble_bash_LANG [[ ${LC_CTYPE-} ]] && LC_CTYPE=$LC_ALL [[ ${LC_MESSAGES-} ]] && LC_MESSAGES=$LC_ALL [[ ${LC_NUMERIC-} ]] && LC_NUMERIC=$LC_ALL [[ ${LC_TIME-} ]] && LC_TIME=$LC_ALL LANG=$LC_ALL LC_ALL= fi ble/variable#copy-state LC_COLLATE _ble_bash_LC_COLLATE LC_COLLATE=C if local TMOUT= 2>/dev/null; then # #D1630 WA _ble_bash_tmout_wa=() else _ble_bash_tmout_wa=(-t 2147483647) fi } 2>/dev/null # set -x 対策 #D0930 / locale 変更 function ble/base/restore-bash-options { [[ $_ble_bash_options_adjusted ]] || return 1 _ble_bash_options_adjusted= ble/variable#copy-state _ble_bash_LC_COLLATE LC_COLLATE if [[ $_ble_bash_LC_ALL ]]; then ble/variable#copy-state _ble_bash_LC_CTYPE LC_CTYPE ble/variable#copy-state _ble_bash_LC_MESSAGES LC_MESSAGES ble/variable#copy-state _ble_bash_LC_NUMERIC LC_NUMERIC ble/variable#copy-state _ble_bash_LC_TIME LC_TIME ble/variable#copy-state _ble_bash_LANG LANG fi ble/variable#copy-state _ble_bash_LC_ALL LC_ALL [[ $_ble_bash_nocasematch ]] && shopt -s nocasematch ble/base/.restore-bash-options _ble_bash_set _ble_bash_shopt } 2>/dev/null # set -x 対策 #D0930 / locale 変更 function ble/base/recover-bash-options { if [[ $_ble_bash_expand_aliases ]]; then shopt -s expand_aliases else shopt -u expand_aliases fi } { ble/base/adjust-bash-options; } &>/dev/null # set -x 対策 #D0930 builtin bind &>/dev/null # force to load .inputrc if [[ $OSTYPE == msys* ]]; then [[ $(builtin bind -m emacs -p 2>/dev/null | grep '"\\C-?"') == '"\C-?": backward-kill-line' ]] && builtin bind -m emacs '"\C-?": backward-delete-char' 2>/dev/null fi if [[ ! -o emacs && ! -o vi && ! $_ble_init_command ]]; then builtin echo "ble.sh: ble.sh is not intended to be used with the line-editing mode disabled (--noediting)." >&2 ble/base/restore-bash-options ble/base/restore-builtin-wrappers ble/base/restore-POSIXLY_CORRECT builtin eval -- "$_ble_bash_FUNCNEST_restore" builtin unset -v _ble_bash return 1 2>/dev/null || builtin exit 1 fi if shopt -q restricted_shell; then builtin echo "ble.sh: ble.sh is not intended to be used in restricted shells (--restricted)." >&2 ble/base/restore-bash-options ble/base/restore-builtin-wrappers ble/base/restore-POSIXLY_CORRECT builtin eval -- "$_ble_bash_FUNCNEST_restore" builtin unset -v _ble_bash return 1 2>/dev/null || builtin exit 1 fi function ble/init/adjust-IFS { _ble_init_original_IFS_set=${IFS+set} _ble_init_original_IFS=$IFS IFS=$' \t\n' } function ble/init/restore-IFS { if [[ $_ble_init_original_IFS_set ]]; then IFS=$_ble_init_original_IFS else builtin unset -v IFS fi builtin unset -v _ble_init_original_IFS_set builtin unset -v _ble_init_original_IFS } if ((_ble_bash>=50100)); then _ble_bash_BASH_REMATCH_level=0 _ble_bash_BASH_REMATCH=() function ble/base/adjust-BASH_REMATCH { ((_ble_bash_BASH_REMATCH_level++==0)) || return 0 _ble_bash_BASH_REMATCH=("${BASH_REMATCH[@]}") } function ble/base/restore-BASH_REMATCH { ((_ble_bash_BASH_REMATCH_level>0&& --_ble_bash_BASH_REMATCH_level==0)) || return 0 BASH_REMATCH=("${_ble_bash_BASH_REMATCH[@]}") } else _ble_bash_BASH_REMATCH_level=0 _ble_bash_BASH_REMATCH=() _ble_bash_BASH_REMATCH_rex=none function ble/base/adjust-BASH_REMATCH/increase { local delta=$1 ((delta)) || return 1 ((i+=delta)) if ((delta==1)); then rex=$rex. else rex=$rex.{$delta} fi } function ble/base/adjust-BASH_REMATCH/is-updated { local i n=${#_ble_bash_BASH_REMATCH[@]} ((n!=${#BASH_REMATCH[@]})) && return 0 for ((i=0;i=0)) } function ble/base/adjust-BASH_REMATCH { ((_ble_bash_BASH_REMATCH_level++==0)) || return 0 ble/base/adjust-BASH_REMATCH/is-updated || return 1 local size=${#BASH_REMATCH[@]} if ((size==0)); then _ble_bash_BASH_REMATCH=() _ble_bash_BASH_REMATCH_rex=none return 0 fi local rex= i=0 local text=$BASH_REMATCH sub ret isub local -a rparens=() local isub rex i=0 count=0 for ((isub=1;isub=1)); do local end=${rparens[count-1]} if ble/base/adjust-BASH_REMATCH/.find-substr "${text:i:end-i}" "$sub"; then ble/base/adjust-BASH_REMATCH/increase "$ret" ((rparens[count++]=i+${#sub})) rex=$rex'(' break else ble/base/adjust-BASH_REMATCH/increase "$((end-i))" rex=$rex')' builtin unset -v 'rparens[--count]' fi done ((count>0)) && continue if ble/base/adjust-BASH_REMATCH/.find-substr "${text:i}" "$sub"; then ble/base/adjust-BASH_REMATCH/increase "$ret" ((rparens[count++]=i+${#sub})) rex=$rex'(' else break # 復元失敗 fi done while ((count>=1)); do local end=${rparens[count-1]} ble/base/adjust-BASH_REMATCH/increase "$((end-i))" rex=$rex')' builtin unset -v 'rparens[--count]' done ble/base/adjust-BASH_REMATCH/increase "$((${#text}-i))" _ble_bash_BASH_REMATCH=("${BASH_REMATCH[@]}") _ble_bash_BASH_REMATCH_rex=$rex } function ble/base/restore-BASH_REMATCH { ((_ble_bash_BASH_REMATCH_level>0&& --_ble_bash_BASH_REMATCH_level==0)) || return 0 [[ ${_ble_bash_BASH_REMATCH-} =~ $_ble_bash_BASH_REMATCH_rex ]] } fi ble/init/adjust-IFS ble/base/adjust-BASH_REMATCH function ble/init/clean-up { local ext=$? opts=$1 # preserve exit status builtin unset -v _ble_init_version builtin unset -v _ble_init_exit builtin unset -v _ble_init_command builtin unset -v _ble_init_attached ble/base/restore-BASH_REMATCH ble/init/restore-IFS if [[ :$opts: != *:check-attach:* || ! $_ble_attached ]]; then ble/base/restore-bash-options ble/base/restore-POSIXLY_CORRECT ble/base/restore-builtin-wrappers builtin eval -- "$_ble_bash_FUNCNEST_restore" fi return "$ext" } function ble/util/put { builtin printf '%s' "$1"; } function ble/util/print { builtin printf '%s\n' "$1"; } function ble/util/print-lines { builtin printf '%s\n' "$@"; } _ble_base_arguments_opts= _ble_base_arguments_attach= _ble_base_arguments_rcfile= function ble/base/read-blesh-arguments { local opts= local opt_attach=prompt local opt_inputrc=auto builtin unset -v _ble_init_command # 再解析 while (($#)); do local arg=$1; shift case $arg in (--noattach|noattach) opt_attach=none ;; (--attach=*) opt_attach=${arg#*=} ;; (--attach) if (($#)); then opt_attach=$1; shift else opt_attach=attach opts=$opts:E ble/util/print "ble.sh ($arg): an option argument is missing." >&2 fi ;; (--noinputrc) opt_inputrc=none ;; (--inputrc=*) opt_inputrc=${arg#*=} ;; (--inputrc) if (($#)); then opt_inputrc=$1; shift else opt_inputrc=inputrc opts=$opts:E ble/util/print "ble.sh ($arg): an option argument is missing." >&2 fi ;; (--rcfile=*|--init-file=*|--rcfile|--init-file) if [[ $arg != *=* ]]; then local rcfile=$1; shift else local rcfile=${arg#*=} fi _ble_base_arguments_rcfile=${rcfile:-/dev/null} if [[ ! $rcfile || ! -e $rcfile ]]; then ble/util/print "ble.sh ($arg): '$rcfile' does not exist." >&2 opts=$opts:E elif [[ ! -r $rcfile ]]; then ble/util/print "ble.sh ($arg): '$rcfile' is not readable." >&2 opts=$opts:E fi ;; (--norc) _ble_base_arguments_rcfile=/dev/null ;; (--keep-rlvars) opts=$opts:keep-rlvars ;; (--bash-debug-version=*|--bash-debug-version) local value= if [[ $arg == *=* ]]; then value=${arg#*=} elif (($#)); then value=$1; shift else opts=$opts:E ble/util/print "ble.sh ($arg): an option argument is missing." >&2 continue fi case $value in (full|short|once|ignore) opts=$opts:bash-debug-version=$value ;; (*) opts=$opts:E ble/util/print "ble.sh ($arg): unrecognized value '$value'." >&2 esac ;; (--debug-bash-output) bleopt_internal_suppress_bash_output= ;; (--test | --update | --clear-cache | --lib | --install) if [[ $_ble_init_command ]]; then ble/util/print "ble.sh ($arg): the option '--$_ble_init_command' has already been specified." >&2 opts=$opts:E else _ble_init_command=${arg#--} fi ;; (--*) ble/util/print "ble.sh: unrecognized long option '$arg'" >&2 opts=$opts:E ;; (-?*) local i c for ((i=1;i<${#arg};i++)); do c=${arg:i:1} case -$c in (-o) if ((i+1<${#arg})); then local oarg=${arg:i+1} i=${#arg} elif (($#)); then local oarg=$1; shift else opts=$opts:E i=${#arg} continue fi local rex='^[_a-zA-Z][_a-zA-Z0-9]*=' if [[ $oarg =~ $rex ]]; then builtin eval -- "bleopt_${oarg%%=*}=\${oarg#*=}" else ble/util/print "ble.sh: unrecognized option '-o $oarg'" >&2 opts=$opts:E fi ;; (-*) ble/util/print "ble.sh: unrecognized option '-$c'" >&2 opts=$opts:E ;; esac done ;; (*) if [[ ${_ble_init_command-} ]]; then _ble_init_command[${#_ble_init_command[@]}]=$arg else ble/util/print "ble.sh: unrecognized argument '$arg'" >&2 opts=$opts:E fi ;; esac done _ble_base_arguments_opts=$opts _ble_base_arguments_attach=$opt_attach _ble_base_arguments_inputrc=$opt_inputrc [[ :$opts: != *:E:* ]] } if ! ble/base/read-blesh-arguments "$@"; then builtin echo "ble.sh: cancel initialization." >&2 ble/init/clean-up 2>/dev/null # set -x 対策 #D0930 builtin unset -v _ble_bash return 2 2>/dev/null || builtin exit 2 fi if [[ ${_ble_base-} ]]; then [[ $_ble_init_command ]] && _ble_init_attached=$_ble_attached if ! ble/base/unload-for-reload; then builtin echo "ble.sh: an old version of ble.sh seems to be already loaded." >&2 ble/init/clean-up 2>/dev/null # set -x 対策 #D0930 builtin unset -v _ble_bash return 1 2>/dev/null || builtin exit 1 fi fi _ble_bash_loaded_in_function=0 local _ble_local_test 2>/dev/null && _ble_bash_loaded_in_function=1 _ble_version=0 BLE_VERSION=$_ble_init_version function ble/base/initialize-version-variables { local version=$BLE_VERSION local hash= if [[ $version == *+* ]]; then hash=${version#*+} version=${version%%+*} fi local status=release if [[ $version == *-* ]]; then status=${version#*-} version=${version%%-*} fi local major=${version%%.*}; version=${version#*.} local minor=${version%%.*}; version=${version#*.} local patch=${version%%.*} ((_ble_version=major*10000+minor*100+patch)) BLE_VERSINFO=("$major" "$minor" "$patch" "$hash" "$status" noarch) BLE_VER=$_ble_version } function ble/base/clear-version-variables { builtin unset -v _ble_bash _ble_version BLE_VERSION BLE_VERSINFO BLE_VER } ble/base/initialize-version-variables function ble/bash/read { local TMOUT= 2>/dev/null # #D1630 WA readonly TMOUT builtin read "${_ble_bash_tmout_wa[@]}" -r "$@" } function ble/bash/read-timeout { builtin read -t "$@"; } _ble_bash_read_winch= if ((50200<=_ble_bash&&_ble_bash<50300)); then function ble/bash/read/.process-winch { if [[ $_ble_bash_read_winch != - ]]; then local _ble_local_handler=$_ble_bash_read_winch local _ble_bash_read_winch= builtin eval -- "$_ble_local_handler" fi } function ble/bash/read { local TMOUT= 2>/dev/null # #D1630 WA readonly TMOUT local _ble_bash_read_winch=- builtin read "${_ble_bash_tmout_wa[@]}" -r "$@"; local _ble_local_ext=$? ble/bash/read/.process-winch return "$_ble_local_ext" } function ble/bash/read-timeout { local _ble_bash_read_winch=- builtin read -t "$@"; local _ble_local_ext=$? ble/bash/read/.process-winch return "$_ble_local_ext" } fi if ((_ble_bash>=50300)); then function ble/util/assign { builtin eval "$1=\${ builtin eval -- \"\$2\"; }"; } else function ble/util/assign { builtin eval "$1=\$(builtin eval -- \"\$2\")"; } fi if ((_ble_bash>=40000)); then function ble/bin#has { builtin type -t -- "$@" &>/dev/null; } else function ble/bin#has { local cmd for cmd; do builtin type -t -- "$cmd" || return 1; done &>/dev/null return 0 } fi function ble/bin#get-path { local cmd=$1 ble/util/assign path 'builtin type -P -- "$cmd" 2>/dev/null' && [[ $path ]] } function ble/bin/.default-utility-path { local cmd for cmd; do builtin eval "function ble/bin/$cmd { command $cmd \"\$@\"; }" done } function ble/bin#freeze-utility-path { local cmd path q=\' Q="'\''" fail= flags= for cmd; do if [[ $cmd == -n ]]; then flags=n$flags continue fi [[ $flags == *n* ]] && ble/bin#has "ble/bin/$cmd" && continue ble/bin#has "ble/bin/.frozen:$cmd" && continue if ble/bin#get-path "$cmd"; then [[ $path == ./* || $path == ../* ]] && path=$PWD/$path builtin eval "function ble/bin/$cmd { '${path//$q/$Q}' \"\$@\"; }" else fail=1 fi done ((!fail)) } _ble_init_posix_command_list=(sed date rm mkdir mkfifo sleep stty tty sort awk chmod grep cat wc mv sh od cp ps) function ble/init/check-environment { if ! ble/bin#has "${_ble_init_posix_command_list[@]}"; then local cmd commandMissing= for cmd in "${_ble_init_posix_command_list[@]}"; do if ! type "$cmd" &>/dev/null; then commandMissing="$commandMissing\`$cmd', " fi done ble/util/print "ble.sh: insane environment: The command(s), ${commandMissing}not found. Check your environment variable PATH." >&2 local default_path=$(command -p getconf PATH 2>/dev/null) [[ $default_path ]] || return 1 local original_path=$PATH export PATH=${default_path}${PATH:+:}${PATH} [[ :$PATH: == *:/bin:* ]] || PATH=/bin${PATH:+:}$PATH [[ :$PATH: == *:/usr/bin:* ]] || PATH=/usr/bin${PATH:+:}$PATH if ! ble/bin#has "${_ble_init_posix_command_list[@]}"; then PATH=$original_path return 1 fi ble/util/print "ble.sh: modified PATH=${PATH::${#PATH}-${#original_path}}\$PATH" >&2 fi if [[ ! ${USER-} ]]; then ble/util/print "ble.sh: insane environment: \$USER is empty." >&2 if USER=$(id -un 2>/dev/null) && [[ $USER ]]; then export USER ble/util/print "ble.sh: modified USER=$USER" >&2 fi fi _ble_base_env_USER=$USER if [[ ! ${HOSTNAME-} ]]; then ble/util/print "ble.sh: suspicious environment: \$HOSTNAME is empty." if HOSTNAME=$(uname -n 2>/dev/null) && [[ $HOSTNAME ]]; then export HOSTNAME ble/util/print "ble.sh: fixed HOSTNAME=$HOSTNAME" >&2 fi fi _ble_base_env_HOSTNAME=$HOSTNAME if [[ ! ${HOME-} ]]; then ble/util/print "ble.sh: insane environment: \$HOME is empty." >&2 local home if home=$(getent passwd 2>/dev/null | awk -F : -v UID="$UID" '$3 == UID {print $6}') && [[ $home && -d $home ]] || { [[ $USER && -d /home/$USER && -O /home/$USER ]] && home=/home/$USER; } || { [[ $USER && -d /Users/$USER && -O /Users/$USER ]] && home=/Users/$USER; } || { [[ $home && ! ( -e $home && -h $home ) ]] && ble/bin/mkdir -p "$home" 2>/dev/null; } then export HOME=$home ble/util/print "ble.sh: modified HOME=$HOME" >&2 fi fi if [[ ! ${LANG-} ]]; then ble/util/print "ble.sh: suspicious environment: \$LANG is empty." >&2 fi if ((_ble_bash>=50200)); then local error ble/util/assign error '{ LC_ALL= LC_CTYPE=C ble/util/put; } 2>&1' if [[ $error ]]; then ble/util/print "$error" >&2 ble/util/print "ble.sh: please check the locale settings (LANG and LC_*)." >&2 ((_ble_bash>=50300)) || { LC_ALL= LC_CTYPE=C ble/util/put; } 2>/dev/null local dummy builtin read -et 0.000001 dummy &2 ble/base/clear-version-variables ble/init/clean-up 2>/dev/null # set -x 対策 #D0930 return 1 fi _ble_bin_awk_type= function ble/bin/awk/.instantiate { local path q=\' Q="'\''" ext=1 if ble/bin#get-path nawk; then [[ $path == ./* || $path == ../* ]] && path=$PWD/$path local version ble/util/assign version '"$path" -W version' 2>/dev/null /dev/null; then _ble_bin_awk_type=xpg4 function ble/bin/awk { /usr/xpg4/bin/awk -v AWKTYPE=xpg4 "$@"; } && ext=0 elif ble/bin#get-path awk; then [[ $path == ./* || $path == ../* ]] && path=$PWD/$path local version ble/util/assign version '"$path" -W version || "$path" --version' 2>/dev/null /dev/null /usr/bin/awk -v AWKTYPE=nawk "$@"; local ext=$? ble/util/unlocal LC_ALL LC_CTYPE 2>/dev/null return "$ext" } elif [[ $_ble_bin_awk_type == [gmn]awk ]] && ! ble/is-function "ble/bin/$_ble_bin_awk_type" ; then builtin eval "function ble/bin/$_ble_bin_awk_type { '${path//$q/$Q}' -v AWKTYPE=$_ble_bin_awk_type \"\$@\"; }" fi fi fi return "$ext" } function ble/bin/awk { if ble/bin/awk/.instantiate; then ble/bin/awk "$@" else awk "$@" fi } function ble/bin/.frozen:awk { return 0; } function ble/bin/.frozen:nawk { return 0; } function ble/bin/.frozen:mawk { return 0; } function ble/bin/.frozen:gawk { return 0; } function ble/bin/awk0.available/test { local count=0 cmd_awk=$1 awk_script='BEGIN { RS = "\0"; } { count++; } END { print count; }' ble/util/assign count 'printf "a\0b\0" | "$cmd_awk" "$awk_script"' ((count==2)) } function ble/bin/awk0.available { local awk for awk in mawk gawk; do if ble/bin#freeze-utility-path -n "$awk" && ble/bin/awk0.available/test ble/bin/"$awk" && builtin eval -- "function ble/bin/awk0 { ble/bin/$awk -v AWKTYPE=$awk \"\$@\"; }"; then function ble/bin/awk0.available { return 0; } return 0 fi done if ble/bin/awk0.available/test ble/bin/awk && function ble/bin/awk0 { ble/bin/awk "$@"; }; then function ble/bin/awk0.available { return 0; } return 0 fi function ble/bin/awk0.available { return 1; } return 1 } function ble/base/is-msys1 { local cr; cr=$'\r' [[ $OSTYPE == msys && ! $cr ]] } function ble/util/mkd { local dir for dir; do [[ -d $dir ]] && continue [[ -e $dir || -L $dir ]] && ble/bin/rm -f "$dir" ble/bin/mkdir -p "$dir" done } if ((_ble_bash>=40000)); then _ble_util_readlink_visited_init='local -A visited=()' function ble/util/readlink/.visited { [[ ${visited[$1]+set} ]] && return 0 visited[$1]=1 return 1 } else _ble_util_readlink_visited_init="local -a visited=()" function ble/util/readlink/.visited { local key for key in "${visited[@]}"; do [[ $1 == "$key" ]] && return 0 done visited=("$1" "${visited[@]}") return 1 } fi function ble/util/readlink/.readlink { local path=$1 if ble/bin#has ble/bin/readlink; then ble/util/assign link 'ble/bin/readlink -- "$path"' [[ $link ]] elif ble/bin#has ble/bin/ls; then ble/util/assign link 'ble/bin/ls -ld -- "$path"' && [[ $link == *" $path -> "?* ]] && link=${link#*" $path -> "} else false fi } 2>/dev/null function ble/util/readlink/.resolve-physical-directory { [[ $path == */?* ]] || return 0 local PWD=$PWD OLDPWD=$OLDPWD CDPATH= if builtin cd -L .; then local pwd=$PWD builtin cd -P "${path%/*}/" && path=${PWD%/}/${path##*/} builtin cd "$pwd" fi return 0 } function ble/util/readlink/.resolve-loop { local path=$ret while [[ $path == ?*/ ]]; do path=${path%/}; done builtin eval -- "$_ble_util_readlink_visited_init" while [[ -h $path ]]; do local link ble/util/readlink/.visited "$path" && break ble/util/readlink/.readlink "$path" || break if [[ $link == /* || $path != */* ]]; then path=$link else ble/util/readlink/.resolve-physical-directory path=${path%/*}/$link fi while [[ $path == ?*/ ]]; do path=${path%/}; done done ret=$path } function ble/util/readlink/.resolve { _ble_util_readlink_type= case $OSTYPE in (cygwin | msys | linux-gnu) local readlink ble/util/assign readlink 'type -P readlink' case $readlink in (/bin/readlink | /usr/bin/readlink) _ble_util_readlink_type=readlink-f builtin eval "function ble/util/readlink/.resolve { ble/util/assign ret '$readlink -f -- \"\$ret\"'; }" ;; esac ;; esac if [[ ! $_ble_util_readlink_type ]]; then _ble_util_readlink_type=loop ble/bin#freeze-utility-path readlink ls function ble/util/readlink/.resolve { ble/util/readlink/.resolve-loop; } fi ble/util/readlink/.resolve } function ble/util/readlink { ret=$1 if [[ -h $ret ]]; then ble/util/readlink/.resolve; fi } _ble_bash_path= function ble/bin/.load-builtin { local name=$1 path=$2 if [[ ! $_ble_bash_path ]]; then local ret; ble/util/readlink "$BASH" _ble_bash_path=$ret fi if [[ ! $path ]]; then local bash_prefix=${ret%/*/*} path=$bash_prefix/lib/bash/$name [[ -s $path ]] || return 1 fi if (enable -f "$path" "$name") &>/dev/null; then enable -f "$path" "$name" builtin eval -- "function ble/bin/$name { builtin $name \"\$@\"; }" return 0 else return 1 fi } function ble/base/.create-user-directory { local var=$1 dir=$2 if [[ ! -d $dir ]]; then [[ ! -e $dir && -h $dir ]] && ble/bin/rm -f "$dir" if [[ -e $dir || -h $dir ]]; then ble/util/print "ble.sh: cannot create a directory '$dir' since there is already a file." >&2 return 1 fi if ! (umask 077; ble/bin/mkdir -p "$dir" && [[ -O $dir ]]); then ble/util/print "ble.sh: failed to create a directory '$dir'." >&2 return 1 fi elif ! [[ -r $dir && -w $dir && -x $dir ]]; then ble/util/print "ble.sh: permission of '$dir' is not correct." >&2 return 1 elif [[ ! -O $dir ]]; then ble/util/print "ble.sh: owner of '$dir' is not correct." >&2 return 1 fi builtin eval "$var=\$dir" } function ble/base/initialize-base-directory { local src=$1 local defaultDir=${2-} _ble_base_blesh_raw=$src if [[ -h $src ]]; then local ret; ble/util/readlink "$src"; src=$ret fi _ble_base_blesh=$src if [[ -s $src && $src != */* ]]; then _ble_base=$PWD elif [[ $src == */* ]]; then local dir=${src%/*} if [[ ! $dir ]]; then _ble_base=/ elif [[ $dir != /* ]]; then _ble_base=$PWD/$dir else _ble_base=$dir fi else _ble_base=${defaultDir:-$HOME/.local/share/blesh} fi [[ -d $_ble_base ]] } if ! ble/base/initialize-base-directory "${BASH_SOURCE[0]}"; then ble/util/print "ble.sh: ble base directory not found!" >&2 ble/base/clear-version-variables ble/init/clean-up 2>/dev/null # set -x 対策 #D0930 return 1 fi _ble_base_is_wsl_status= function ble/base/initialize-runtime-directory/.is-wsl { [[ $_ble_base_is_wsl_status ]] && return "$_ble_base_is_wsl_status" _ble_base_is_wsl_status=1 [[ -d /usr/lib/wsl/lib && -r /proc/version ]] || return 1 local kernel_version ble/bash/read kernel_version < /proc/version || return 1 [[ $kernel_version == *-microsoft-* ]] || return 1 _ble_base_is_wsl_status=0 } function ble/base/initialize-runtime-directory/.xdg { local runtime_dir= if [[ $XDG_RUNTIME_DIR ]]; then if [[ ! -d $XDG_RUNTIME_DIR ]]; then ble/util/print "ble.sh: XDG_RUNTIME_DIR='$XDG_RUNTIME_DIR' is not a directory." >&2 return 1 elif [[ -O $XDG_RUNTIME_DIR ]]; then runtime_dir=$XDG_RUNTIME_DIR else false fi fi if [[ ! $runtime_dir ]]; then runtime_dir=/run/user/$UID [[ -d $runtime_dir && -O $runtime_dir ]] || return 1 fi [[ $runtime_dir == /run/user/* ]] && ble/base/initialize-runtime-directory/.is-wsl && return 1 if ! [[ -r $runtime_dir && -w $runtime_dir && -x $runtime_dir ]]; then [[ $runtime_dir == "$XDG_RUNTIME_DIR" ]] && ble/util/print "ble.sh: XDG_RUNTIME_DIR='$XDG_RUNTIME_DIR' doesn't have a proper permission." >&2 return 1 fi ble/base/.create-user-directory _ble_base_run "$runtime_dir/blesh" } function ble/base/initialize-runtime-directory/.tmp { [[ -r /tmp && -w /tmp && -x /tmp ]] || return 1 ble/base/initialize-runtime-directory/.is-wsl && return 1 local tmp_dir=/tmp/blesh if [[ ! -d $tmp_dir ]]; then [[ ! -e $tmp_dir && -h $tmp_dir ]] && ble/bin/rm -f "$tmp_dir" if [[ -e $tmp_dir || -h $tmp_dir ]]; then ble/util/print "ble.sh: cannot create a directory '$tmp_dir' since there is already a file." >&2 return 1 fi ble/bin/mkdir -p "$tmp_dir" || return 1 ble/bin/chmod a+rwxt "$tmp_dir" || return 1 elif ! [[ -r $tmp_dir && -w $tmp_dir && -x $tmp_dir ]]; then ble/util/print "ble.sh: permission of '$tmp_dir' is not correct." >&2 return 1 fi ble/base/.create-user-directory _ble_base_run "$tmp_dir/$UID" } function ble/base/initialize-runtime-directory/.base { local tmp_dir=$_ble_base/run if [[ ! -d $tmp_dir ]]; then ble/bin/mkdir -p "$tmp_dir" || return 1 ble/bin/chmod a+rwxt "$tmp_dir" || return 1 fi ble/base/.create-user-directory _ble_base_run "$tmp_dir/${USER:-$UID}@$HOSTNAME" } function ble/base/initialize-runtime-directory/.home { local cache_dir=${XDG_CACHE_HOME:-$HOME/.cache} if [[ ! -d $cache_dir ]]; then if [[ $XDG_CACHE_HOME ]]; then ble/util/print "ble.sh: XDG_CACHE_HOME='$XDG_CACHE_HOME' is not a directory." >&2 return 1 else ble/bin/mkdir -p "$cache_dir" || return 1 fi fi if ! [[ -r $cache_dir && -w $cache_dir && -x $cache_dir ]]; then if [[ $XDG_CACHE_HOME ]]; then ble/util/print "ble.sh: XDG_CACHE_HOME='$XDG_CACHE_HOME' doesn't have a proper permission." >&2 else ble/util/print "ble.sh: '$cache_dir' doesn't have a proper permission." >&2 fi return 1 fi ble/base/.create-user-directory _ble_base_run "$cache_dir/blesh/run" } function ble/base/initialize-runtime-directory { ble/base/initialize-runtime-directory/.xdg && return 0 ble/base/initialize-runtime-directory/.tmp && return 0 ble/base/initialize-runtime-directory/.base && return 0 ble/base/initialize-runtime-directory/.home } if ! ble/base/initialize-runtime-directory; then ble/util/print "ble.sh: failed to initialize \$_ble_base_run." >&2 ble/base/clear-version-variables ble/init/clean-up 2>/dev/null # set -x 対策 #D0930 return 1 fi >| "$_ble_base_run/$$.load" function ble/base/clean-up-runtime-directory { local opts=$1 failglob= noglob= if [[ $- == *f* ]]; then noglob=1 set +f fi if shopt -q failglob &>/dev/null; then failglob=1 shopt -u failglob fi local -a alive=() removed=() bgpids=() [[ :$opts: == *:finalize:* ]] && alive[$$]=0 local file pid iremoved=0 ibgpid=0 for file in "$_ble_base_run"/[1-9]*.*; do [[ -e $file || -h $file ]] || continue pid=${file##*/}; pid=${pid%%.*} [[ $pid && ! ${pid//[0-9]} ]] || continue if [[ ! ${alive[pid]+set} ]]; then builtin kill -0 "$pid" &>/dev/null ((alive[pid]=$?==0)) fi ((alive[pid])) && continue if [[ $file == *.pid && -s $file ]]; then local run_pid IFS= ble/bash/read run_pid < "$file" if ble/string#match "$run_pid" '^-?[0-9]+$' && kill -0 "$run_pid" &>/dev/null; then if ((pid==$$)); then bgpids[ibgpid++]=$run_pid else builtin kill -- "$run_pid" &>/dev/null ble/util/msleep 50 builtin kill -0 "$run_pid" &>/dev/null && (ble/util/nohup "ble/util/conditional-sync '' '((1))' 100 progressive-weight:pid=$run_pid:no-wait-pid:timeout=3000:SIGKILL") fi fi fi removed[iremoved++]=$file done ((iremoved)) && ble/bin/rm -rf "${removed[@]}" 2>/dev/null ((ibgpid)) && (ble/util/nohup 'ble/bin/sleep 3; builtin kill -- "${bgpids[@]}" &>/dev/null') [[ $failglob ]] && shopt -s failglob [[ $noglob ]] && set -f return 0 } function ble/base/initialize-cache-directory/.xdg { [[ $_ble_base != */out ]] || return 1 local cache_dir=${XDG_CACHE_HOME:-$HOME/.cache} if [[ ! -d $cache_dir ]]; then [[ $XDG_CACHE_HOME ]] && ble/util/print "ble.sh: XDG_CACHE_HOME='$XDG_CACHE_HOME' is not a directory." >&2 return 1 fi if ! [[ -r $cache_dir && -w $cache_dir && -x $cache_dir ]]; then [[ $XDG_CACHE_HOME ]] && ble/util/print "ble.sh: XDG_CACHE_HOME='$XDG_CACHE_HOME' doesn't have a proper permission." >&2 return 1 fi local ver=${BLE_VERSINFO[0]}.${BLE_VERSINFO[1]} ble/base/.create-user-directory _ble_base_cache "$cache_dir/blesh/$ver" } function ble/base/initialize-cache-directory { ble/base/initialize-cache-directory/.xdg && return 0 local cache_dir=$_ble_base/cache.d if [[ ! -d $cache_dir ]]; then ble/bin/mkdir -p "$cache_dir" || return 1 ble/bin/chmod a+rwxt "$cache_dir" || return 1 local old_cache_dir=$_ble_base/cache if [[ -d $old_cache_dir && ! -h $old_cache_dir ]]; then mv "$old_cache_dir" "$cache_dir/$UID" ln -s "$cache_dir/$UID" "$old_cache_dir" fi fi ble/base/.create-user-directory _ble_base_cache "$cache_dir/$UID" } function ble/base/migrate-cache-directory/.move { local old=$1 new=$2 [[ -e $old ]] || return 0 if [[ -e $new || -L $old ]]; then ble/bin/rm -rf "$old" else ble/bin/mv "$old" "$new" fi } function ble/base/migrate-cache-directory/.check-old-prefix { local old_prefix=$_ble_base_cache/$1 local new_prefix=$_ble_base_cache/$2 local file for file in "$old_prefix"*; do local old=$file local new=$new_prefix${file#"$old_prefix"} ble/base/migrate-cache-directory/.move "$old" "$new" done } function ble/base/migrate-cache-directory { local failglob= shopt -q failglob && { failglob=1; shopt -u failglob; } ble/base/migrate-cache-directory/.check-old-prefix cmap+default.binder-source decode.cmap.allseq ble/base/migrate-cache-directory/.check-old-prefix cmap+default decode.cmap ble/base/migrate-cache-directory/.check-old-prefix ble-decode-bind decode.bind local file for file in "$_ble_base_cache"/*.term; do local old=$file local new=$_ble_base_cache/term.${file#"$_ble_base_cache/"}; new=${new%.term} ble/base/migrate-cache-directory/.move "$old" "$new" done ble/base/migrate-cache-directory/.move "$_ble_base_cache/man" "$_ble_base_cache/complete.mandb" [[ $failglob ]] && shopt -s failglob } if ! ble/base/initialize-cache-directory; then ble/util/print "ble.sh: failed to initialize \$_ble_base_cache." >&2 ble/base/clear-version-variables ble/init/clean-up 2>/dev/null # set -x 対策 #D0930 return 1 fi ble/base/migrate-cache-directory function ble/base/initialize-state-directory/.xdg { local state_dir=${XDG_STATE_HOME:-$HOME/.local/state} if [[ -e $state_dir || -L $state_dir ]]; then if [[ ! -d $state_dir ]]; then if [[ $XDG_STATE_HOME ]]; then ble/util/print "ble.sh: XDG_STATE_HOME='$XDG_STATE_HOME' is not a directory." >&2 else ble/util/print "ble.sh: '$state_dir' is not a directory." >&2 fi return 1 fi if ! [[ -r $state_dir && -w $state_dir && -x $state_dir ]]; then if [[ $XDG_STATE_HOME ]]; then ble/util/print "ble.sh: XDG_STATE_HOME='$XDG_STATE_HOME' doesn't have a proper permission." >&2 else ble/util/print "ble.sh: '$state_dir' doesn't have a proper permission." >&2 fi return 1 fi fi ble/base/.create-user-directory _ble_base_state "$state_dir/blesh" } function ble/base/initialize-state-directory { ble/base/initialize-state-directory/.xdg && return 0 local state_dir=$_ble_base/state.d if [[ ! -d $state_dir ]]; then ble/bin/mkdir -p "$state_dir" || return 1 ble/bin/chmod a+rwxt "$state_dir" || return 1 local old_state_dir=$_ble_base/state if [[ -d $old_state_dir && ! -h $old_state_dir ]]; then mv "$old_state_dir" "$state_dir/$UID" ln -s "$state_dir/$UID" "$old_state_dir" fi fi ble/util/print "ble.sh: using the non-standard position of the state directory: '$state_dir/$UID'" >&2 ble/base/.create-user-directory _ble_base_state "$state_dir/$UID" } if ! ble/base/initialize-state-directory; then ble/util/print "ble.sh: failed to initialize \$_ble_base_state." >&2 ble/base/clear-version-variables ble/init/clean-up 2>/dev/null # set -x 対策 #D0930 return 1 fi function ble/base/print-usage-for-no-argument-command { local name=${FUNCNAME[1]} desc=$1; shift ble/util/print-lines \ "usage: $name" \ "$desc" >&2 [[ $1 != --help ]] && return 2 return 0 } function ble-reload { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" local -a options=() [[ ! -e $_ble_base_rcfile ]] || ble/array#push options --rcfile="${_ble_base_rcfile:-/dev/null}" [[ $_ble_base_arguments_inputrc == auto ]] || ble/array#push options --inputrc="$_ble_base_arguments_inputrc" local name for name in keep-rlvars; do if [[ :$_ble_base_arguments_opts: == *:"$name":* ]]; then ble/array#push options "--$name" fi done builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_leave" source "$_ble_base/ble.sh" "${options[@]}" } _ble_base_repository=release:nightly-20240814+75c4a84 _ble_base_branch=master _ble_base_repository_url=https://github.com/akinomyoga/ble.sh _ble_base_build_git_version="git version 2.46.0" _ble_base_build_make_version="GNU Make 4.3" _ble_base_build_gawk_version="GNU Awk 5.1.0, API: 3.0 (GNU MPFR 4.1.0, GNU MP 6.2.1)" function ble-update/.check-install-directory-ownership { if [[ ! -O $_ble_base ]]; then ble/util/print 'ble-update: install directory is owned by another user:' >&2 ls -ld "$_ble_base" return 1 elif [[ ! -r $_ble_base || ! -w $_ble_base || ! -x $_ble_base ]]; then ble/util/print 'ble-update: install directory permission denied:' >&2 ls -ld "$_ble_base" return 1 fi } function ble-update/.make { local sudo= if [[ $1 == --sudo ]]; then sudo=1 shift fi if ! "$make" -q "$@"; then if [[ $sudo ]]; then sudo "$make" "$@" else "$make" "$@" fi else return 6 fi } function ble-update/.reload { local ext=$1 if [[ $ext -eq 0 || $ext -eq 6 && $_ble_base/ble.sh -nt $_ble_base_run/$$.load ]]; then if [[ ! -e $_ble_base/ble.sh ]]; then ble/util/print "ble-update: new ble.sh not found at '$_ble_base/ble.sh'." >&2 return 1 elif [[ ! -s $_ble_base/ble.sh ]]; then ble/util/print "ble-update: new ble.sh '$_ble_base/ble.sh' is empty." >&2 return 1 elif [[ $- == *i* && $_ble_attached ]] && ! ble/util/is-running-in-subshell; then builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_leave" ble-reload ext=$? builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_enter" return "$ext" fi return 0 fi ((ext==6)) && ext=0 return "$ext" } function ble-update/.download-nightly-build { if ! ble/bin#has tar xz; then local command for command in tar xz; do ble/bin#has "$command" || ble/util/print "ble-update (nightly): '$command' command is not available." >&2 done return 1 fi if ((EUID!=0)) && ! ble-update/.check-install-directory-ownership; then sudo "$BASH" "$_ble_base/ble.sh" --update && ble-update/.reload 6 return "$?" fi local tarname=ble-nightly.tar.xz local url_tar=$_ble_base_repository_url/releases/download/nightly/$tarname ( ble/util/joblist/__suppress__ set +f shopt -u failglob nullglob if ! ble/bin/mkdir -p "$_ble_base/src"; then ble/util/print "ble-update (nightly): failed to create the directory '$_ble_base/src'" >&2 return 1 fi if ! builtin cd "$_ble_base/src"; then ble/util/print "ble-update (nightly): failed to enter the directory '$_ble_base/src'" >&2 return 1 fi local ret ble/file#hash "$tarname"; local ohash=$ret local retry max_retry=5 for ((retry=0;retry<=max_retry;retry++)); do if ((retry>0)); then local wait=$((retry<3?retry*10:30)) ble/util/print "ble-update (nightly): retry downloading in $wait seconds... ($retry/$max_retry)" >&2 ble/util/sleep "$wait" fi if ble/bin#has wget; then wget -N "$url_tar" && break elif ble/bin#has curl; then curl -LRo "$tarname" -z "$tarname" "$url_tar" && break else ble/util/print "ble-update (nightly): command 'wget' nor 'curl' is available." >&2 return 1 fi done if ((retry>max_retry)); then ble/util/print "ble-update (nightly): failed to download the archive from '$url_tar'." >&2 return 7 fi ble/file#hash "$tarname"; local nhash=$ret [[ $ohash == "$nhash" ]] && return 6 ble/bin/rm -rf ble-nightly*/ if ! tar xJf "$tarname"; then ble/util/print 'ble-update (nightly): failed to extract the tarball. Removing possibly broken tarball.' >&2 ble/bin/rm -rf "$tarname" return 1 fi local extracted_dir=ble-nightly if [[ ! -d $extracted_dir ]]; then ble/util/print "ble-update (nightly): the directory 'ble-nightly' not found in the tarball '$PWD/$tarname'." >&2 return 1 fi ble/bin/cp -Rf "$extracted_dir"/* "$_ble_base/" || return 1 ble/bin/rm -rf "$extracted_dir" ) && ble-update/.reload } function ble-update/.check-build-dependencies { make= if ble/bin#has gmake; then make=gmake elif ble/bin#has make && make --version 2>&1 | ble/bin/grep -qiF 'GNU Make'; then make=make else ble/util/print "ble-update: GNU Make is not available." >&2 return 1 fi if ! ble/bin#has git gawk; then local command for command in git gawk; do ble/bin#has "$command" || ble/util/print "ble-update: '$command' command is not available." >&2 done return 1 fi return 0 } function ble-update/.check-repository { if [[ ${_ble_base_repository-} && $_ble_base_repository != release:* ]]; then if [[ ! -e $_ble_base_repository/.git ]]; then ble/util/print "ble-update: git repository not found at '$_ble_base_repository'." >&2 elif [[ ! -O $_ble_base_repository ]]; then ble/util/print "ble-update: git repository is owned by another user:" >&2 ls -ld "$_ble_base_repository" elif [[ ! -r $_ble_base_repository || ! -w $_ble_base_repository || ! -x $_ble_base_repository ]]; then ble/util/print 'ble-update: git repository permission denied:' >&2 ls -ld "$_ble_base_repository" else return 0 fi fi return 1 } function ble-update/.impl { if (($#)); then ble/base/print-usage-for-no-argument-command 'Update and reload ble.sh.' "$@" return "$?" fi if [[ ${_ble_base_package_type-} ]] && ble/is-function ble/base/package:"$_ble_base_package_type"/update; then ble/util/print "ble-update: delegate to '$_ble_base_package_type' package manager..." >&2 ble/base/package:"$_ble_base_package_type"/update; local ext=$? if ((ext==125)); then ble/util/print 'ble-update: fallback to the default update process.' >&2 else ble-update/.reload "$ext" return "$?" fi fi if [[ ${_ble_base_repository-} == release:nightly-* ]]; then if ble-update/.download-nightly-build; local ext=$?; ((ext==0||ext==6||ext==7)); then if ((ext==6)); then ble/util/print 'ble-update (nightly): Already up to date.' >&2 elif ((ext==7)); then ble/util/print 'ble-update (nightly): Remote temporarily unavailable. Try it again later.' >&2 fi return 0 fi fi local make ble-update/.check-build-dependencies || return 1 local insdir_doc=$_ble_base/doc [[ ! -d $insdir_doc && -d ${_ble_base%/*}/doc/blesh ]] && insdir_doc=${_ble_base%/*}/doc/blesh if ble-update/.check-repository; then ( ble/util/print "cd into $_ble_base_repository..." >&2 && builtin cd "$_ble_base_repository" && git pull && git submodule update --recursive --remote && if [[ $_ble_base == "$_ble_base_repository"/out ]]; then ble-update/.make all elif ((EUID!=0)) && ! ble-update/.check-install-directory-ownership; then ble-update/.make all ble-update/.make --sudo INSDIR="$_ble_base" INSDIR_DOC="$insdir_doc" install else ble-update/.make INSDIR="$_ble_base" INSDIR_DOC="$insdir_doc" install fi ) ble-update/.reload "$?" return "$?" fi if ((EUID!=0)) && ! ble-update/.check-install-directory-ownership; then sudo "$BASH" "$_ble_base/ble.sh" --update && ble-update/.reload 6 return "$?" else 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 ) && ble-update/.reload return "$?" fi return 1 } function ble-update { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" ble-update/.impl "$@" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" } _ble_attached= BLE_ATTACHED= _ble_term_nl=$'\n' _ble_term_FS=$'\034' _ble_term_SOH=$'\001' _ble_term_DEL=$'\177' _ble_term_IFS=$' \t\n' _ble_term_CR=$'\r' _ble_term_space=$' \t' # WA #D2055 function blehook/declare { local name=$1 builtin eval "_ble_hook_h_$name=()" builtin eval "_ble_hook_c_$name=0" } blehook/declare EXIT blehook/declare INT blehook/declare internal_EXIT blehook/declare internal_INT blehook/declare internal_ERR blehook/declare internal_RETURN blehook/declare internal_DEBUG blehook/declare unload blehook/declare ATTACH blehook/declare DETACH blehook/declare term_DA1R blehook/declare term_DA2R blehook/declare idle_after_task blehook/declare color_defface_load blehook/declare color_setface_load blehook/declare ADDHISTORY blehook/declare history_reset_background blehook/declare history_leave blehook/declare history_change blehook/declare history_message blehook/declare WINCH blehook/declare internal_WINCH blehook/declare CHPWD blehook/declare PRECMD blehook/declare internal_PRECMD blehook/declare PREEXEC blehook/declare internal_PREEXEC blehook/declare POSTEXEC blehook/declare ERREXEC blehook/declare widget_bell blehook/declare textarea_render_defer blehook/declare info_reveal blehook/declare exec_register blehook/declare exec_end blehook/declare keymap_load blehook/declare keymap_vi_load blehook/declare keymap_emacs_load blehook/declare syntax_load blehook/declare complete_load blehook/declare complete_insert function blehook/.compatibility-ble-0.3 { blehook keymap_load!='ble/util/invoke-hook _ble_keymap_default_load_hook' blehook keymap_emacs_load!='ble/util/invoke-hook _ble_keymap_emacs_load_hook' blehook keymap_vi_load!='ble/util/invoke-hook _ble_keymap_vi_load_hook' blehook complete_load!='ble/util/invoke-hook _ble_complete_load_hook' } function blehook/.compatibility-ble-0.3/check { if ble/is-array _ble_keymap_default_load_hook || ble/is-array _ble_keymap_vi_load_hook || ble/is-array _ble_keymap_emacs_load_hook || ble/is-array _ble_complete_load_hook then ble/bin/cat << EOF # [Change in ble-0.4.0] # # Please update your blerc settings for ble-0.4+. # In ble-0.4+, use the following form: # # blehook/eval-after-load keymap SHELL-COMMAND # blehook/eval-after-load keymap_vi SHELL-COMMAND # blehook/eval-after-load keymap_emacs SHELL-COMMAND # blehook/eval-after-load complete SHELL-COMMAND # # instead of the following older form: # # ble/array#push _ble_keymap_default_load_hook SHELL-COMMAND # ble/array#push _ble_keymap_vi_load_hook SHELL-COMMAND # ble/array#push _ble_keymap_emacs_load_hook SHELL-COMMAND # ble/array#push _ble_complete_load_hook SHELL-COMMAND # # Note: "blehook/eval-after-load" should be called # after you defined SHELL-COMMAND. # EOF fi } function ble-edit/prompt/print { ble/prompt/print "$@"; } function ble-edit/prompt/process-prompt-string { ble/prompt/process-prompt-string "$@"; } function ble/widget/@nomarked { ble/decode/widget/dispatch "$@"; } function ble/complete/action/inherit-from { ble/complete/action#inherit-from "$@" } function bleopt/.read-arguments/process-option { local name=$1 case $name in (help) flags=H$flags ;; (color|color=always) flags=c${flags//[cn]} ;; (color=never) flags=n${flags//[cn]} ;; (color=auto) flags=${flags//[cn]} ;; (color=*) ble/util/print "bleopt: '${name#*=}': unrecognized option argument for '--color'." >&2 flags=E$flags ;; (reset) flags=r$flags ;; (changed) flags=u$flags ;; (initialize) flags=I$flags ;; (*) ble/util/print "bleopt: unrecognized long option '--$name'." >&2 flags=E$flags ;; esac } function bleopt/expand-variable-pattern { ret=() local pattern=$1 if [[ $pattern == *[@*?]* ]]; then builtin eval -- "ret=(\"\${!${pattern%%[@*?]*}@}\")" ble/array#filter-by-glob ret "${pattern//@/*}" elif [[ ${!pattern+set} || :$opts: == :allow-undefined: ]]; then ret=("$pattern") fi ((${#ret[@]})) } function bleopt/.read-arguments { flags= pvars=() specs=() while (($#)); do local arg=$1; shift case $arg in (--) ble/array#push specs "$@" break ;; (-) ble/util/print "bleopt: unrecognized argument '$arg'." >&2 flags=E$flags ;; (--*) bleopt/.read-arguments/process-option "${arg:2}" ;; (-*) local i c for ((i=1;i<${#arg};i++)); do c=${arg:i:1} case $c in (r) bleopt/.read-arguments/process-option reset ;; (u) bleopt/.read-arguments/process-option changed ;; (I) bleopt/.read-arguments/process-option initialize ;; (*) ble/util/print "bleopt: unrecognized option '-$c'." >&2 flags=E$flags ;; esac done ;; (*) if local rex='^([_a-zA-Z0-9@*?]+)(:?=|$)(.*)'; [[ $arg =~ $rex ]]; then local name=${BASH_REMATCH[1]#bleopt_} local var=bleopt_$name local op=${BASH_REMATCH[2]} local value=${BASH_REMATCH[3]} if [[ $op == ':=' ]]; then if [[ $var == *[@*?]* ]]; then ble/util/print "bleopt: \`${var#bleopt_}': wildcard cannot be used in the definition." >&2 flags=E$flags continue fi else local ret; bleopt/expand-variable-pattern "$var" var=() local v i=0 for v in "${ret[@]}"; do ble/is-function "bleopt/obsolete:${v#bleopt_}" && continue var[i++]=$v done [[ ${#var[@]} == 0 ]] && var=("${ret[@]}") if ((${#var[@]}==0)); then ble/util/print "bleopt: option \`$name' not found" >&2 flags=E$flags continue fi fi if [[ $op ]]; then var=("${var[@]}") # #D1570: WA bash-3.0 ${scal[@]/x} bug if ((_ble_bash>=40300)) && ! shopt -q compat42; then ble/array#push specs "${var[@]/%/"=$value"}" # WA #D1570 #D1751 checked else ble/array#push specs "${var[@]/%/=$value}" # WA #D1570 #D1738 checked fi else ble/array#push pvars "${var[@]}" fi else ble/util/print "bleopt: unrecognized argument '$arg'" >&2 flags=E$flags fi ;; esac done } function bleopt/changed.predicate { local cur=$1 def=_ble_opt_def_${1#bleopt_} [[ ! ${!def+set} || ${!cur} != "${!def}" ]] } function bleopt/default { local def=_ble_opt_def_${1#bleopt_} ret=${!def} } function bleopt { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" local flags pvars specs bleopt/.read-arguments "$@" if [[ $flags == *E* ]]; then builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_leave" return 2 elif [[ $flags == *H* ]]; then ble/util/print-lines \ 'usage: bleopt [OPTION] [NAME|NAME=VALUE|NAME:=VALUE]...' \ ' Set ble.sh options. Without arguments, this prints all the settings.' \ '' \ ' Options' \ ' --help Print this help.' \ ' -r, --reset Reset options to the default values' \ ' -I, --initialize Re-initialize settings' \ ' -u, --changed Only select changed options' \ ' --color[=always|never|auto]' \ ' Change color settings.' \ '' \ ' Arguments' \ ' NAME Print the value of the option.' \ ' NAME=VALUE Set the value to the option.' \ ' NAME:=VALUE Set or create the value to the option.' \ '' \ ' NAME can contain "@", "*", and "?" as wildcards.' \ '' builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_leave" return 0 fi if ((${#pvars[@]}==0&&${#specs[@]}==0)); then local var ip=0 for var in "${!bleopt_@}"; do ble/is-function "bleopt/obsolete:${var#bleopt_}" && continue pvars[ip++]=$var done fi [[ $flags == *u* ]] && ble/array#filter pvars bleopt/changed.predicate if [[ $flags == *r* ]]; then local var for var in "${pvars[@]}"; do local name=${var#bleopt_} ble/is-function bleopt/obsolete:"$name" && continue local def=_ble_opt_def_$name [[ ${!def+set} && ${!var-} != "${!def}" ]] && ble/array#push specs "$var=${!def}" done pvars=() elif [[ $flags == *I* ]]; then local var for var in "${pvars[@]}"; do bleopt/reinitialize "${var#bleopt_}" done pvars=() fi if ((${#specs[@]})); then local spec for spec in "${specs[@]}"; do local var=${spec%%=*} value=${spec#*=} [[ ${!var+set} && ${!var} == "$value" ]] && continue if ble/is-function bleopt/check:"${var#bleopt_}"; then local bleopt_source=${BASH_SOURCE[1]} local bleopt_lineno=${BASH_LINENO[0]} if ! bleopt/check:"${var#bleopt_}"; then flags=E$flags continue fi fi builtin eval -- "$var=\"\$value\"" done fi if ((${#pvars[@]})); then local sgr0= sgr1= sgr2= sgr3= if [[ $flags == *c* || $flags != *n* && -t 1 ]]; then local ret ble/color/face2sgr command_function; sgr1=$ret ble/color/face2sgr syntax_varname; sgr2=$ret ble/color/face2sgr syntax_quoted; sgr3=$ret sgr0=$_ble_term_sgr0 fi local var for var in "${pvars[@]}"; do local ret ble/string#quote-word "${!var}" sgrq="$sgr3":sgr0="$sgr0" ble/util/print "${sgr1}bleopt$sgr0 ${sgr2}${var#bleopt_}$sgr0=$ret" done fi [[ $flags != *E* ]] builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" } function bleopt/declare/.check-renamed-option { var=bleopt_$2 local sgr0= sgr1= sgr2= sgr3= if [[ -t 2 ]]; then sgr0=$_ble_term_sgr0 sgr1=${_ble_term_setaf[2]} sgr2=${_ble_term_setaf[1]}$_ble_term_bold sgr3=${_ble_term_setaf[4]}$_ble_term_bold fi local locate=$sgr1${BASH_SOURCE[3]-'(stdin)'}:${BASH_LINENO[2]}$sgr0 ble/util/print "$locate (bleopt): The option '$sgr2$1$sgr0' has been renamed. Please use '$sgr3$2$sgr0' instead." >&2 if ble/is-function bleopt/check:"$2"; then bleopt/check:"$2" return "$?" fi return 0 } function bleopt/declare { local type=$1 name=bleopt_$2 default_value=$3 case $type in (-o) builtin eval -- "$name='[obsolete: renamed to $3]'" builtin eval -- "function bleopt/check:$2 { bleopt/declare/.check-renamed-option $2 $3; }" builtin eval -- "function bleopt/obsolete:$2 { return 0; }" ;; (-n) builtin eval -- "_ble_opt_def_$2=\$3" builtin eval -- ": \"\${$name:=\$default_value}\"" ;; (*) builtin eval -- "_ble_opt_def_$2=\$3" builtin eval -- ": \"\${$name=\$default_value}\"" ;; esac return 0 } function bleopt/reinitialize { local name=$1 local defname=_ble_opt_def_$name local varname=bleopt_$name [[ ${!defname+set} ]] || return 1 [[ ${!varname} == "${!defname}" ]] && return 0 ble/is-function bleopt/obsolete:"$name" && return 0 ble/is-function bleopt/check:"$name" || return 0 local value=${!varname} builtin eval -- "$varname=\$$defname" bleopt/check:"$name" && builtin eval "$varname=\$value" } bleopt/declare -n input_encoding UTF-8 function bleopt/check:input_encoding { if ! ble/is-function "ble/encoding:$value/decode"; then ble/util/print "bleopt: Invalid value input_encoding='$value'." \ "A function 'ble/encoding:$value/decode' is not defined." >&2 return 1 elif ! ble/is-function "ble/encoding:$value/b2c"; then ble/util/print "bleopt: Invalid value input_encoding='$value'." \ "A function 'ble/encoding:$value/b2c' is not defined." >&2 return 1 elif ! ble/is-function "ble/encoding:$value/c2bc"; then ble/util/print "bleopt: Invalid value input_encoding='$value'." \ "A function 'ble/encoding:$value/c2bc' is not defined." >&2 return 1 elif ! ble/is-function "ble/encoding:$value/generate-binder"; then ble/util/print "bleopt: Invalid value input_encoding='$value'." \ "A function 'ble/encoding:$value/generate-binder' is not defined." >&2 return 1 elif ! ble/is-function "ble/encoding:$value/is-intermediate"; then ble/util/print "bleopt: Invalid value input_encoding='$value'." \ "A function 'ble/encoding:$value/is-intermediate' is not defined." >&2 return 1 fi if [[ $bleopt_input_encoding != "$value" ]]; then local bleopt_input_encoding=$value ble/decode/readline/rebind fi return 0 } bleopt/declare -v internal_stackdump_enabled 0 bleopt/declare -n openat_base 30 bleopt/declare -v pager '' bleopt/declare -v editor '' shopt -s checkwinsize function ble/util/setexit { return "$1"; } _ble_util_upvar_setup='local var=ret ret; [[ $1 == -v ]] && var=$2 && shift 2' _ble_util_upvar='local "${var%%\[*\]}" && ble/util/upvar "$var" "$ret"' if ((_ble_bash>=50000)); then function ble/util/unlocal { if shopt -q localvar_unset; then shopt -u localvar_unset builtin unset -v "$@" shopt -s localvar_unset else builtin unset -v "$@" fi } function ble/util/upvar { ble/util/unlocal "${1%%\[*\]}" && builtin eval "$1=\"\$2\""; } function ble/util/uparr { ble/util/unlocal "$1" && builtin eval "$1=(\"\${@:2}\")"; } else function ble/util/unlocal { builtin unset -v "$@"; } function ble/util/upvar { builtin unset -v "${1%%\[*\]}" && builtin eval "$1=\"\$2\""; } function ble/util/uparr { builtin unset -v "$1" && builtin eval "$1=(\"\${@:2}\")"; } fi function ble/util/save-vars { 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 "$__ble_prefix$__ble_name=\"\$$__ble_name\"" fi done } function ble/util/restore-vars { 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[@]+\"\${$__ble_prefix$__ble_name[@]}\"})" else builtin eval "$__ble_name=\"\${$__ble_prefix$__ble_name-}\"" fi done } if ((_ble_bash>=40400)); then function ble/variable#get-attr { if [[ $1 == -v ]]; then builtin eval -- "$2=\${!3@a}" else attr=${!1@a} fi } function ble/variable#has-attr { [[ ${!1@a} == *["$2"]* ]]; } else function ble/variable#get-attr { if [[ $1 == -v ]]; then local __ble_var=$2 __ble_tmp=$3 else local __ble_var=attr __ble_tmp=$1 fi ble/util/assign __ble_tmp 'declare -p "$__ble_tmp" 2>/dev/null' local rex='^declare -([a-zA-Z]*)'; [[ $__ble_tmp =~ $rex ]] builtin eval -- "$__ble_var=\${BASH_REMATCH[1]-}" return 0 } function ble/variable#has-attr { local __ble_tmp=$1 ble/util/assign __ble_tmp 'declare -p "$__ble_tmp" 2>/dev/null' local rex='^declare -([a-zA-Z]*)' [[ $__ble_tmp =~ $rex && ${BASH_REMATCH[1]} == *["$2"]* ]] } fi function ble/is-inttype { ble/variable#has-attr "$1" i; } function ble/is-readonly { ble/variable#has-attr "$1" r; } 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 { (builtin readonly "$1"; ble/variable#is-global/.test "$1") 2>/dev/null } function ble/variable#copy-state { local src=$1 dst=$2 if [[ ${!src+set} ]]; then builtin eval -- "$dst=\${$src}" else builtin unset -v "$dst[0]" 2>/dev/null || builtin unset -v "$dst" fi } _ble_array_prototype=() function ble/array#reserve-prototype { local n=$1 i for ((i=${#_ble_array_prototype[@]};i=40400)); then function ble/is-array { [[ ${!1@a} == *a* ]]; } function ble/is-assoc { [[ ${!1@a} == *A* ]]; } else function ble/is-array { local "decl$1" ble/util/assign "decl$1" "declare -p $1" 2>/dev/null || return 1 local rex='^declare -[b-zAB-Z]*a' builtin eval "[[ \$decl$1 =~ \$rex ]]" } function ble/is-assoc { local "decl$1" ble/util/assign "decl$1" "declare -p $1" 2>/dev/null || return 1 local rex='^declare -[ab-zB-Z]*A' builtin eval "[[ \$decl$1 =~ \$rex ]]" } ((_ble_bash>=40000)) || function ble/is-assoc { false; } fi function ble/array#set { builtin eval "$1=(\"\${@:2}\")"; } if ((_ble_bash>=40000)); then function ble/array#push { builtin eval "$1+=(\"\${@:2}\")" } elif ((_ble_bash>=30100)); then function ble/array#push { IFS=$_ble_term_IFS builtin eval "$1+=(\"\${@:2}\")" } else function ble/array#push { while (($#>=2)); do builtin eval -- "$1[\${#$1[@]}]=\"\$2\"" set -- "$1" "${@:3}" done } fi function ble/array#pop { builtin eval "local i$1=\$((\${#$1[@]}-1))" if ((i$1>=0)); then builtin eval "ret=\${$1[i$1]}" builtin unset -v "$1[i$1]" return 0 else ret= return 1 fi } function ble/array#unshift { builtin eval -- "$1=(\"\${@:2}\" \"\${$1[@]}\")" } function ble/array#shift { builtin eval -- "$1=(\"\${$1[@]:$((${2:-1}))}\")" } function ble/array#reverse { builtin eval " set -- \"\${$1[@]}\"; $1=() local e$1 i$1=\$# for e$1; do $1[--i$1]=\"\$e$1\"; done" } function ble/array#insert-at { builtin eval "$1=(\"\${$1[@]::$2}\" \"\${@:3}\" \"\${$1[@]:$2}\")" } function ble/array#insert-after { local _ble_local_script=' local iNAME=0 eNAME aNAME= for eNAME in "${NAME[@]}"; do ((iNAME++)) [[ $eNAME == "$2" ]] && aNAME=iNAME && break done [[ $aNAME ]] && ble/array#insert-at "$1" "$aNAME" "${@:3}" '; builtin eval -- "${_ble_local_script//NAME/$1}" } function ble/array#insert-before { local _ble_local_script=' local iNAME=0 eNAME aNAME= for eNAME in "${NAME[@]}"; do [[ $eNAME == "$2" ]] && aNAME=iNAME && break ((iNAME++)) done [[ $aNAME ]] && ble/array#insert-at "$1" "$aNAME" "${@:3}" '; builtin eval -- "${_ble_local_script//NAME/$1}" } function ble/array#filter/.eval { builtin eval -- "$_ble_local_predicate_cmd" } function ble/array#filter { local _ble_local_predicate=$2 if [[ $2 == *'$'* ]] || ! ble/is-function "$2"; then _ble_local_predicate=ble/array#filter/.eval _ble_local_predicate_cmd=$2 fi local _ble_local_script=' local -a aNAME=() eNAME for eNAME in "${NAME[@]}"; do "$_ble_local_predicate" "$eNAME" && ble/array#push "aNAME" "$eNAME" done NAME=("${aNAME[@]}") '; builtin eval -- "${_ble_local_script//NAME/$1}" } function ble/array#filter/not.predicate { ! "$_ble_local_pred" "$1"; } function ble/array#remove-if { local _ble_local_pred=$2 ble/array#filter "$1" ble/array#filter/not.predicate } function ble/array#filter/regex.predicate { [[ $1 =~ $_ble_local_rex ]]; } function ble/array#filter-by-regex { local _ble_local_rex=$2 local LC_ALL= LC_COLLATE=C 2>/dev/null ble/array#filter "$1" ble/array#filter/regex.predicate ble/util/unlocal LC_COLLATE LC_ALL 2>/dev/null } function ble/array#remove-by-regex { local _ble_local_rex=$2 local LC_ALL= LC_COLLATE=C 2>/dev/null ble/array#remove-if "$1" ble/array#filter/regex.predicate ble/util/unlocal LC_COLLATE LC_ALL 2>/dev/null } function ble/array#filter/glob.predicate { [[ $1 == $_ble_local_glob ]]; } function ble/array#filter-by-glob { local _ble_local_glob=$2 local LC_ALL= LC_COLLATE=C 2>/dev/null ble/array#filter "$1" ble/array#filter/glob.predicate ble/util/unlocal LC_COLLATE LC_ALL 2>/dev/null } function ble/array#remove-by-glob { local _ble_local_glob=$2 local LC_ALL= LC_COLLATE=C 2>/dev/null ble/array#remove-if "$1" ble/array#filter/glob.predicate ble/util/unlocal LC_COLLATE LC_ALL 2>/dev/null } function ble/array#remove/.predicate { [[ $1 != "$_ble_local_value" ]]; } function ble/array#remove { local _ble_local_value=$2 ble/array#filter "$1" ble/array#remove/.predicate } function ble/array#index { local _ble_local_script=' local eNAME iNAME=0 for eNAME in "${NAME[@]}"; do if [[ $eNAME == "$2" ]]; then ret=$iNAME; return 0; fi ((++iNAME)) done ret=-1; return 1 '; builtin eval -- "${_ble_local_script//NAME/$1}" } function ble/array#last-index { local _ble_local_script=' local eNAME iNAME=${#NAME[@]} while ((iNAME--)); do [[ ${NAME[iNAME]} == "$2" ]] && { ret=$iNAME; return 0; } done ret=-1; return 1 '; builtin eval -- "${_ble_local_script//NAME/$1}" } function ble/array#remove-at { local _ble_local_script=' builtin unset -v "NAME[$2]" NAME=("${NAME[@]}") '; builtin eval -- "${_ble_local_script//NAME/$1}" } function ble/array#fill-range { ble/array#reserve-prototype "$(($3-$2))" local _ble_local_script=' local -a sNAME; sNAME=("${_ble_array_prototype[@]::$3-$2}") NAME=("${NAME[@]::$2}" "${sNAME[@]/#/$4}" "${NAME[@]:$3}")' # WA #D1570 #D1738 checked ((_ble_bash>=40300)) && ! shopt -q compat42 && _ble_local_script=${_ble_local_script//'$4'/'"$4"'} builtin eval -- "${_ble_local_script//NAME/$1}" } function ble/idict#replace { local _ble_local_script=' local iNAME=0 extNAME=1 for iNAME in "${!NAME[@]}"; do [[ ${NAME[iNAME]} == "$2" ]] || continue extNAME=0 if (($#>=3)); then NAME[iNAME]=$3 else builtin unset -v '\''NAME[iNAME]'\'' fi done return "$extNAME" '; builtin eval -- "${_ble_local_script//NAME/$1}" } function ble/idict#copy { local _ble_script=' '$1'=() local i'$1$2' for i'$1$2' in "${!'$2'[@]}"; do '$1'[i'$1$2']=${'$2'[i'$1$2']} done' builtin eval -- "$_ble_script" } _ble_string_prototype=' ' function ble/string#reserve-prototype { local n=$1 c for ((c=${#_ble_string_prototype};c${#b})) && local a=$b b=$a b=${b::${#a}} if [[ $a == "$b" ]]; then ret=$a return 0 fi local l=0 u=${#a} m while ((l+1${#b})) && local a=$b b=$a b=${b:${#b}-${#a}} if [[ $a == "$b" ]]; then ret=$a return 0 fi local l=0 u=${#a} m while ((l+1=40000)); then function ble/string#split-lines { mapfile -t "$1" <<< "$2" } else function ble/string#split-lines { ble/util/mapfile "$1" <<< "$2" } fi function ble/string#count-char { local text=$1 char=$2 text=${text//[!"$char"]} ret=${#text} } function ble/string#count-string { local text=${1//"$2"} ((ret=(${#1}-${#text})/${#2})) } function ble/string#index-of { local haystack=$1 needle=$2 count=${3:-1} ble/string#repeat '*"$needle"' "$count"; local pattern=$ret builtin eval "local transformed=\${haystack#$pattern}" ((ret=${#haystack}-${#transformed}-${#needle}, ret<0&&(ret=-1),ret>=0)) } function ble/string#last-index-of { local haystack=$1 needle=$2 count=${3:-1} ble/string#repeat '"$needle"*' "$count"; local pattern=$ret builtin eval "local transformed=\${haystack%$pattern}" if [[ $transformed == "$haystack" ]]; then ret=-1 else ret=${#transformed} fi ((ret>=0)) } _ble_util_string_lower_list=abcdefghijklmnopqrstuvwxyz _ble_util_string_upper_list=ABCDEFGHIJKLMNOPQRSTUVWXYZ function ble/string#islower { [[ $1 == ["$_ble_util_string_lower_list"] ]]; } function ble/string#isupper { [[ $1 == ["$_ble_util_string_upper_list"] ]]; } function ble/string#toggle-case { local text=$1 ch i local -a buff for ((i=0;i<${#text};i++)); do ch=${text:i:1} if ble/string#isupper "$ch"; then ch=${_ble_util_string_upper_list%%"$ch"*} ch=${_ble_util_string_lower_list:${#ch}:1} elif ble/string#islower "$ch"; then ch=${_ble_util_string_lower_list%%"$ch"*} ch=${_ble_util_string_upper_list:${#ch}:1} fi ble/array#push buff "$ch" done IFS= builtin eval 'ret="${buff[*]-}"' } if ((_ble_bash>=40000)); then function ble/string#tolower { ret=${1,,}; } function ble/string#toupper { ret=${1^^}; } else function ble/string#tolower { local i text=$1 ch local -a buff=() for ((i=0;i<${#text};i++)); do ch=${text:i:1} if ble/string#isupper "$ch"; then ch=${_ble_util_string_upper_list%%"$ch"*} ch=${_ble_util_string_lower_list:${#ch}:1} fi ble/array#push buff "$ch" done IFS= builtin eval 'ret="${buff[*]-}"' } function ble/string#toupper { local i text=$1 ch local -a buff=() for ((i=0;i<${#text};i++)); do ch=${text:i:1} if ble/string#islower "$ch"; then ch=${_ble_util_string_lower_list%%"$ch"*} ch=${_ble_util_string_upper_list:${#ch}:1} fi ble/array#push buff "$ch" done IFS= builtin eval 'ret="${buff[*]-}"' } fi function ble/string#capitalize { local tail=$1 local rex='^[^a-zA-Z0-9]*' [[ $tail =~ $rex ]] local out=$BASH_REMATCH tail=${tail:${#BASH_REMATCH}} rex='^[a-zA-Z0-9]+[^a-zA-Z0-9]*' while [[ $tail =~ $rex ]]; do local rematch=$BASH_REMATCH ble/string#toupper "${rematch::1}"; out=$out$ret ble/string#tolower "${rematch:1}" ; out=$out$ret tail=${tail:${#rematch}} done ret=$out$tail } function ble/string#trim { ret=$1 local rex=$'^[ \t\n]+' [[ $ret =~ $rex ]] && ret=${ret:${#BASH_REMATCH}} local rex=$'[ \t\n]+$' [[ $ret =~ $rex ]] && ret=${ret::${#ret}-${#BASH_REMATCH}} } function ble/string#ltrim { ret=$1 local rex=$'^[ \t\n]+' [[ $ret =~ $rex ]] && ret=${ret:${#BASH_REMATCH}} } function ble/string#rtrim { ret=$1 local rex=$'[ \t\n]+$' [[ $ret =~ $rex ]] && ret=${ret::${#ret}-${#BASH_REMATCH}} } if ((_ble_bash>=50200)); then function ble/string#escape-characters { ret=$1 if [[ $ret == *["$2"]* ]]; then if [[ ! $3 ]]; then local patsub_replacement= shopt -q patsub_replacement && patsub_replacement=1 shopt -s patsub_replacement ret=${ret//["$2"]/\\&} # #D1738 patsub_replacement [[ $patsub_replacement ]] || shopt -u patsub_replacement else local chars1=$2 chars2=${3:-$2} local i n=${#chars1} a b for ((i=0;i()!^' [[ $2 != *G* ]] && chars=$chars'*?[' [[ $2 == *c* ]] && chars=$chars'=:' [[ $2 == *b* ]] && chars=$chars'{,}' ble/string#escape-characters "$1" "$chars" [[ $2 != *[HT]* && $ret == '~'* ]] && ret=\\$ret [[ $2 != *H* && $ret == '#'* ]] && ret=\\$ret if [[ $ret == *[$']\n\t']* ]]; then local a b a=']' b=\\$a ret=${ret//"$a"/"$b"} a=$'\n' b="\$'\n'" ret=${ret//"$a"/"$b"} # WA #D1751 checked a=$'\t' b=$'\\\t' ret=${ret//"$a"/"$b"} fi if [[ $2 == *G* ]] && shopt -q extglob; then local a b a='!\(' b='!(' ret=${ret//"$a"/"$b"} a='@\(' b='@(' ret=${ret//"$a"/"$b"} a='?\(' b='?(' ret=${ret//"$a"/"$b"} a='*\(' b='*(' ret=${ret//"$a"/"$b"} a='+\(' b='+(' ret=${ret//"$a"/"$b"} fi } function ble/string#escape-for-display { local head= tail=$1 opts=$2 local sgr0= sgr1= local rex_csi=$'\e\\[[ -?]*[@-~]' if [[ :$opts: == *:revert:* ]]; then ble/color/g2sgr "$_ble_color_gflags_Revert" sgr1=$ret sgr0=$_ble_term_sgr0 else if local rex=':sgr1=(('$rex_csi'|[^:])*):'; [[ :$opts: =~ $rex ]]; then sgr1=${BASH_REMATCH[1]} sgr0=$_ble_term_sgr0 fi if local rex=':sgr0=(('$rex_csi'|[^:])*):'; [[ :$opts: =~ $rex ]]; then sgr0=${BASH_REMATCH[1]} fi fi while [[ $tail ]]; do if ble/util/isprint+ "$tail"; then head=$head${BASH_REMATCH} tail=${tail:${#BASH_REMATCH}} else ble/util/s2c "${tail::1}" local code=$ret if ((code<32)); then ble/util/c2s "$((code+64))" ret=$sgr1^$ret$sgr0 elif ((code==127)); then ret=$sgr1^?$sgr0 elif ((128<=code&&code<160)); then ble/util/c2s "$((code-64))" ret=${sgr1}M-^$ret$sgr0 else ret=${tail::1} fi head=$head$ret tail=${tail:1} fi done ret=$head } if ((_ble_bash>=40400)); then function ble/string#quote-words { local IFS=$_ble_term_IFS ret="${*@Q}" } function ble/string#quote-command { local IFS=$_ble_term_IFS ret=$1; shift (($#)) && ret="$ret ${*@Q}" } else function ble/string#quote-words { local q=\' Q="'\''" IFS=$_ble_term_IFS ret=("${@//$q/$Q}") ret=("${ret[@]/%/$q}") # WA #D1570 #D1738 checked ret="${ret[*]/#/$q}" # WA #D1570 #D1738 checked } function ble/string#quote-command { if (($#<=1)); then ret=$1 return 0 fi local q=\' Q="'\''" IFS=$_ble_term_IFS ret=("${@:2}") ret=("${ret[@]//$q/$Q}") # WA #D1570 #D1738 checked ret=("${ret[@]/%/$q}") # WA #D1570 #D1738 checked ret="$1 ${ret[*]/#/$q}" # WA #D1570 #D1738 checked } fi function ble/string#quote-word { ret=${1-} local rex_csi=$'\e\\[[ -?]*[@-~]' local opts=${2-} sgrq= sgr0= if [[ $opts ]]; then local rex=':sgrq=(('$rex_csi'|[^:])*):' if [[ :$opts: =~ $rex ]]; then sgrq=${BASH_REMATCH[1]} sgr0=$_ble_term_sgr0 fi rex=':sgr0=(('$rex_csi'|[^:])*):' if [[ :$opts: =~ $rex ]]; then sgr0=${BASH_REMATCH[1]} elif [[ :$opts: == *:ansi:* ]]; then sgr0=$'\e[m' fi fi if [[ ! $ret ]]; then if [[ :$opts: == *:quote-empty:* ]]; then ret=$sgrq\'\'$sgr0 fi return 0 fi local chars=$'\a\b\e\f\n\r\t\v\001-\037\177' if [[ $ret == *[$chars]* ]]; then ble/string#escape-for-bash-escape-string "$ret" ret=$sgrq\$\'$ret\'$sgr0 return 0 fi local chars=$_ble_term_IFS'"`$\<>()|&;*?[]!^=:{,}#~' q=\' if [[ $ret == *["$chars"]* ]]; then local Q="'$sgr0\'$sgrq'" ret=$sgrq$q${ret//$q/$Q}$q$sgr0 ret=${ret#"$sgrq$q$q$sgr0"} ret=${ret%"$sgrq$q$q$sgr0"} elif [[ $ret == *["$q"]* ]]; then local Q="\'" ret=${ret//$q/$Q} fi } function ble/string#match { [[ $1 =~ $2 ]]; } function ble/string#match-safe/.impl { local LC_ALL= LC_COLLATE=C [[ $1 =~ $2 ]] } function ble/string#match-safe { ble/string#match-safe/.impl "$@" 2>/dev/null # suppress locale error #D1440 } function ble/string#create-unicode-progress-bar/.block { local block=$1 if ((block<=0)); then ble/util/c2w "$((0x2588))" ble/string#repeat ' ' "$ret" elif ((block>=8)); then ble/util/c2s "$((0x2588))" ((${#ret}==1)) || ret='*' # LC_CTYPE が非対応の文字の時 else ble/util/c2s "$((0x2590-block))" if ((${#ret}!=1)); then ble/util/c2w "$((0x2588))" ble/string#repeat ' ' "$((ret-1))" ret=$block$ret fi fi } function ble/string#create-unicode-progress-bar { local value=$1 max=$2 width=$3 opts=:$4: local opt_unlimited= if [[ $opts == *:unlimited:* ]]; then opt_unlimited=1 ((value%=max,width--)) fi local progress=$((value*8*width/max)) local progress_fraction=$((progress%8)) progress_integral=$((progress/8)) local out= if ((progress_integral)); then if [[ $opt_unlimited ]]; then ble/string#create-unicode-progress-bar/.block 0 else ble/string#create-unicode-progress-bar/.block 8 fi ble/string#repeat "$ret" "$progress_integral" out=$ret fi if ((progress_fraction)); then if [[ $opt_unlimited ]]; then ble/string#create-unicode-progress-bar/.block "$progress_fraction" out=$out$'\e[7m'$ret$'\e[27m' fi ble/string#create-unicode-progress-bar/.block "$progress_fraction" out=$out$ret ((progress_integral++)) else if [[ $opt_unlimited ]]; then ble/string#create-unicode-progress-bar/.block 8 out=$out$ret fi fi if ((progress_integral/dev/null # suppress locale error #D1440 } function ble/util/substr.impl { local LC_ALL= LC_CTYPE=C ret=${1:$2:$3} } function ble/util/substr { ble/util/substr.impl "$@" 2>/dev/null # suppress locale error #D1440 } function ble/path#append { local _ble_local_script='opts=$opts${opts:+:}$2' _ble_local_script=${_ble_local_script//opts/"$1"} builtin eval -- "$_ble_local_script" } function ble/path#prepend { local _ble_local_script='opts=$2${opts:+:}$opts' _ble_local_script=${_ble_local_script//opts/"$1"} builtin eval -- "$_ble_local_script" } function ble/path#remove { [[ $2 ]] || return 1 local _ble_local_script=' opts=:${opts//:/::}: opts=${opts//:"$2":} opts=${opts//::/:} opts=${opts#:} opts=${opts%:}' _ble_local_script=${_ble_local_script//opts/"$1"} if shopt -q nocasematch 2>/dev/null; then shopt -u nocasematch _ble_local_script=$_ble_local_script';shopt -s nocasematch' fi builtin eval -- "$_ble_local_script" } function ble/path#remove-glob { [[ $2 ]] || return 1 local _ble_local_script=' opts=:${opts//:/::}: opts=${opts//:$2:} opts=${opts//::/:} opts=${opts#:} opts=${opts%:}' _ble_local_script=${_ble_local_script//opts/"$1"} if shopt -q nocasematch 2>/dev/null; then shopt -u nocasematch _ble_local_script=$_ble_local_script';shopt -s nocasematch' fi builtin eval -- "$_ble_local_script" } function ble/path#contains { builtin eval "[[ :\${$1}: == *:\"\$2\":* ]]" } function ble/opts#has { local rex=':'$2'[=:]' [[ :$1: =~ $rex ]] } function ble/opts#remove { ble/path#remove "$@" } function ble/opts#append { ble/util/set "$1" "${!1:+${!1}:}$2" } function ble/opts#append-unique { [[ :${!1}: == *:"$2":* ]] || ble/opts#append "$1" "$2" } function ble/opts#extract-first-optarg { ret= local rex=':'$2'(=[^:]*)?:' [[ :$1: =~ $rex ]] || return 1 if [[ ${BASH_REMATCH[1]} ]]; then ret=${BASH_REMATCH[1]:1} elif [[ ${3+set} ]]; then ret=$3 fi return 0 } function ble/opts#extract-last-optarg { ret= local rex='.*:'$2'(=[^:]*)?:' [[ :$1: =~ $rex ]] || return 1 if [[ ${BASH_REMATCH[1]} ]]; then ret=${BASH_REMATCH[1]:1} elif [[ ${3+set} ]]; then ret=$3 fi return 0 } function ble/opts#extract-all-optargs { ret=() local value=:$1: rex=':'$2'(=[^:]*)?(:.*)$' count=0 while [[ $value =~ $rex ]]; do ((count++)) if [[ ${BASH_REMATCH[1]} ]]; then ble/array#push ret "${BASH_REMATCH[1]:1}" elif [[ ${3+set} ]]; then ble/array#push ret "$3" fi value=${BASH_REMATCH[2]} done ((count)) } if ((_ble_bash>=40000)); then _ble_util_set_declare=(declare -A NAME) function ble/set#add { builtin eval -- "$1[x\$2]=1"; } function ble/set#remove { builtin unset -v "$1[x\$2]"; } function ble/set#contains { builtin eval "[[ \${$1[x\$2]+set} ]]"; } else _ble_util_set_declare=(declare NAME) function ble/set#.escape { _ble_local_value=${_ble_local_value//$_ble_term_FS/"$_ble_term_FS$_ble_term_FS"} _ble_local_value=${_ble_local_value//:/"$_ble_term_FS."} } function ble/set#add { local _ble_local_value=$2; ble/set#.escape ble/path#append "$1" "$_ble_local_value" } function ble/set#remove { local _ble_local_value=$2; ble/set#.escape ble/path#remove "$1" "$_ble_local_value" } function ble/set#contains { local _ble_local_value=$2; ble/set#.escape builtin eval "[[ :\$$1: == *:\"\$_ble_local_value\":* ]]" } fi _ble_util_adict_declare='declare NAME NAME_keylist' function ble/adict#.resolve { _ble_local_key=$2 _ble_local_key=${_ble_local_key//$_ble_term_FS/"$_ble_term_FS,"} _ble_local_key=${_ble_local_key//:/"$_ble_term_FS."} local keylist=${1}_keylist; keylist=:${!keylist} local vec=${keylist%%:"$_ble_local_key":*} if [[ $vec != "$keylist" ]]; then vec=${vec//[!:]} _ble_local_index=${#vec} else _ble_local_index=-1 fi } function ble/adict#set { local _ble_local_key _ble_local_index ble/adict#.resolve "$1" "$2" if ((_ble_local_index>=0)); then builtin eval -- "$1[_ble_local_index]=\$3" else local _ble_local_script=' local _ble_local_vec=${NAME_keylist//[!:]} NAME[${#_ble_local_vec}]=$3 NAME_keylist=$NAME_keylist$_ble_local_key: ' builtin eval -- "${_ble_local_script//NAME/$1}" fi return 0 } function ble/adict#get { local _ble_local_key _ble_local_index ble/adict#.resolve "$1" "$2" if ((_ble_local_index>=0)); then builtin eval -- "ret=\${$1[_ble_local_index]}; [[ \${$1[_ble_local_index]+set} ]]" else builtin eval -- ret= return 1 fi } function ble/adict#unset { local _ble_local_key _ble_local_index ble/adict#.resolve "$1" "$2" ((_ble_local_index>=0)) && builtin eval -- "builtin unset -v '$1[_ble_local_index]'" return 0 } function ble/adict#has { local _ble_local_key _ble_local_index ble/adict#.resolve "$1" "$2" ((_ble_local_index>=0)) && builtin eval -- "[[ \${$1[_ble_local_index]+set} ]]" } function ble/adict#clear { builtin eval -- "${1}_keylist= $1=()" } function ble/adict#keys { local _ble_local_keylist=${1}_keylist _ble_local_keylist=${!_ble_local_keylist%:} ble/string#split ret : "$_ble_local_keylist" if [[ $_ble_local_keylist == *"$_ble_term_FS"* ]]; then ret=("${ret[@]//$_ble_term_FS./:}") # WA #D1570 checked ret=("${ret[@]//$_ble_term_FS,/$_ble_term_FS}") # WA #D1570 #D1738 checked fi local _ble_local_keys _ble_local_i _ble_local_ref=$1[_ble_local_i] _ble_local_keys=("${ret[@]}") ret=() for _ble_local_i in "${!_ble_local_keys[@]}"; do [[ ${_ble_local_ref+set} ]] && ble/array#push ret "${_ble_local_keys[_ble_local_i]}" done } if ((_ble_bash>=40000)); then _ble_util_dict_declare='declare -A NAME' function ble/dict#set { builtin eval -- "$1[x\$2]=\$3"; } function ble/dict#get { builtin eval -- "ret=\${$1[x\$2]-}; [[ \${$1[x\$2]+set} ]]"; } function ble/dict#unset { builtin eval -- "builtin unset -v '$1[x\$2]'"; } function ble/dict#has { builtin eval -- "[[ \${$1[x\$2]+set} ]]"; } function ble/dict#clear { builtin eval -- "$1=()"; } function ble/dict#keys { builtin eval -- 'ret=("${!'"$1"'[@]}"); ret=("${ret[@]#x}")'; } else _ble_util_dict_declare='declare NAME NAME_keylist=' function ble/dict#set { ble/adict#set "$@"; } function ble/dict#get { ble/adict#get "$@"; } function ble/dict#unset { ble/adict#unset "$@"; } function ble/dict#has { ble/adict#has "$@"; } function ble/dict#clear { ble/adict#clear "$@"; } function ble/dict#keys { ble/adict#keys "$@"; } fi if ((_ble_bash>=40200)); then _ble_util_gdict_declare='{ builtin unset -v NAME; declare -gA NAME; NAME=(); }' function ble/gdict#set { ble/dict#set "$@"; } function ble/gdict#get { ble/dict#get "$@"; } function ble/gdict#unset { ble/dict#unset "$@"; } function ble/gdict#has { ble/dict#has "$@"; } function ble/gdict#clear { ble/dict#clear "$@"; } function ble/gdict#keys { ble/dict#keys "$@"; } elif ((_ble_bash>=40000)); then _ble_util_gdict_declare='{ if ! ble/is-assoc NAME; then if local _ble_local_test 2>/dev/null; then NAME_keylist=; else builtin unset -v NAME NAME_keylist; declare -A NAME; fi fi; NAME=(); }' function ble/gdict#.is-adict { local keylist=${1}_keylist [[ ${!keylist+set} ]] } function ble/gdict#set { if ble/gdict#.is-adict "$1"; then ble/adict#set "$@"; else ble/dict#set "$@"; fi; } function ble/gdict#get { if ble/gdict#.is-adict "$1"; then ble/adict#get "$@"; else ble/dict#get "$@"; fi; } function ble/gdict#unset { if ble/gdict#.is-adict "$1"; then ble/adict#unset "$@"; else ble/dict#unset "$@"; fi; } function ble/gdict#has { if ble/gdict#.is-adict "$1"; then ble/adict#has "$@"; else ble/dict#has "$@"; fi; } function ble/gdict#clear { if ble/gdict#.is-adict "$1"; then ble/adict#clear "$@"; else ble/dict#clear "$@"; fi; } function ble/gdict#keys { if ble/gdict#.is-adict "$1"; then ble/adict#keys "$@"; else ble/dict#keys "$@"; fi; } else _ble_util_gdict_declare='{ builtin unset -v NAME NAME_keylist; NAME_keylist= NAME=(); }' function ble/gdict#set { ble/adict#set "$@"; } function ble/gdict#get { ble/adict#get "$@"; } function ble/gdict#unset { ble/adict#unset "$@"; } function ble/gdict#has { ble/adict#has "$@"; } function ble/gdict#clear { ble/adict#clear "$@"; } function ble/gdict#keys { ble/adict#keys "$@"; } fi function ble/dict/.print { declare -p "$2" &>/dev/null || return 1 local ret _ble_local_key _ble_local_value ble/util/print "builtin eval -- \"\${_ble_util_${1}_declare//NAME/$2}\"" ble/"$1"#keys "$2" for _ble_local_key in "${ret[@]}"; do ble/"$1"#get "$2" "$_ble_local_key" ble/string#quote-word "$ret" quote-empty _ble_local_value=$ret ble/string#quote-word "$_ble_local_key" quote-empty _ble_local_key=$ret ble/util/print "ble/$1#set $2 $_ble_local_key $_ble_local_value" done } function ble/dict#print { ble/dict/.print dict "$1"; } function ble/adict#print { ble/dict/.print adict "$1"; } function ble/gdict#print { ble/dict/.print gdict "$1"; } function ble/dict/.copy { local ret ble/"$1"#keys "$2" ble/"$1"#clear "$3" local _ble_local_key for _ble_local_key in "${ret[@]}"; do ble/"$1"#get "$2" "$_ble_local_key" ble/"$1"#set "$3" "$_ble_local_key" "$ret" done } function ble/dict#cp { ble/dict/.copy dict "$1" "$2"; } function ble/adict#cp { ble/dict/.copy adict "$1" "$2"; } function ble/gdict#cp { ble/dict/.copy gdict "$1" "$2"; } if ((_ble_bash>=40000)); then function ble/util/readfile { # 155ms for man bash local -a _ble_local_buffer=() mapfile _ble_local_buffer < "$2"; local _ble_local_ext=$? IFS= builtin eval "$1=\"\${_ble_local_buffer[*]-}\"" return "$_ble_local_ext" } function ble/util/mapfile { mapfile -t "$1" } else function ble/util/readfile { # 465ms for man bash [[ -r $2 && ! -d $2 ]] || return 1 local IFS= ble/bash/read -d '' "$1" < "$2" return 0 } function ble/util/mapfile { local IFS= local _ble_local_i=0 _ble_local_val _ble_local_arr; _ble_local_arr=() while ble/bash/read _ble_local_val || [[ $_ble_local_val ]]; do _ble_local_arr[_ble_local_i++]=$_ble_local_val done builtin eval "$1=(\"\${_ble_local_arr[@]}\")" } fi function ble/util/copyfile { local src=$1 dst=$2 content ble/util/readfile content "$1" || return "$?" ble/util/put "$content" >| "$dst" } function ble/util/writearray/.read-arguments { _ble_local_array= _ble_local_nlfix= _ble_local_delim=$'\n' local flags= while (($#)); do local arg=$1; shift if [[ $flags != *-* && $arg == -* ]]; then case $arg in (--nlfix) _ble_local_nlfix=1 ;; (-d) if (($#)); then _ble_local_delim=$1; shift else ble/util/print "${FUNCNAME[1]}: '$arg': missing option argument." >&2 flags=E$flags fi ;; (--) flags=-$flags ;; (*) ble/util/print "${FUNCNAME[1]}: '$arg': unrecognized option." >&2 flags=E$flags ;; esac else if local rex='^[_a-zA-Z][_a-zA-Z0-9]*$'; ! [[ $arg =~ $rex ]]; then ble/util/print "${FUNCNAME[1]}: '$arg': invalid array name." >&2 flags=E$flags elif [[ $flags == *A* ]]; then ble/util/print "${FUNCNAME[1]}: '$arg': an array name has been already specified." >&2 flags=E$flags else _ble_local_array=$arg flags=A$flags fi fi done [[ $_ble_local_nlfix ]] && _ble_local_delim=$'\n' [[ $flags != *E* ]] } _ble_bin_awk_libES=' function s2i_initialize(_, i) { for (i = 0; i < 16; i++) xdigit2int[sprintf("%x", i)] = i; for (i = 10; i < 16; i++) xdigit2int[sprintf("%X", i)] = i; } function s2i(s, base, _, i, n, r) { if (!base) base = 10; r = 0; n = length(s); for (i = 1; i <= n; i++) r = r * base + xdigit2int[substr(s, i, 1)]; return r; } function c2s_initialize(_, i, n, buff) { if (sprintf("%c", 945) == "α") { C2S_UNICODE_PRINTF_C = 1; n = split(ENVIRON["__ble_rawbytes"], buff); for (i = 1; i <= n; i++) c2s_byte2raw[127 + i] = buff[i]; } else { C2S_UNICODE_PRINTF_C = 0; for (i = 1; i <= 255; i++) c2s_byte2char[i] = sprintf("%c", i); } } function c2s(code, _, leadbyte_mark, leadbyte_sup, tail) { if (C2S_UNICODE_PRINTF_C) return sprintf("%c", code); leadbyte_sup = 128; # 0x80 leadbyte_mark = 0; tail = ""; while (leadbyte_sup && code >= leadbyte_sup) { leadbyte_sup /= 2; leadbyte_mark = leadbyte_mark ? leadbyte_mark / 2 : 65472; # 0xFFC0 tail = c2s_byte2char[128 + int(code % 64)] tail; code = int(code / 64); } return c2s_byte2char[(leadbyte_mark + code) % 256] tail; } function c2s_raw(code, _, ret) { if (code >= 128 && C2S_UNICODE_PRINTF_C) { ret = c2s_byte2raw[code]; if (ret != "") return ret; } return sprintf("%c", code); } function es_initialize(_, c) { s2i_initialize(); c2s_initialize(); es_control_chars["a"] = "\a"; es_control_chars["b"] = "\b"; es_control_chars["t"] = "\t"; es_control_chars["n"] = "\n"; es_control_chars["v"] = "\v"; es_control_chars["f"] = "\f"; es_control_chars["r"] = "\r"; es_control_chars["e"] = "\033"; es_control_chars["E"] = "\033"; es_control_chars["?"] = "?"; es_control_chars["'\''"] = "'\''"; es_control_chars["\""] = "\""; es_control_chars["\\"] = "\\"; for (c = 32; c < 127; c++) es_s2c[sprintf("%c", c)] = c; } function es_unescape(s, _, head, c) { head = ""; while (match(s, /^[^\\]*\\/)) { head = head substr(s, 1, RLENGTH - 1); s = substr(s, RLENGTH + 1); if ((c = es_control_chars[substr(s, 1, 1)])) { head = head c; s = substr(s, 2); } else if (match(s, /^[0-9]([0-9][0-9]?)?/)) { head = head c2s_raw(s2i(substr(s, 1, RLENGTH), 8) % 256); s = substr(s, RLENGTH + 1); } else if (match(s, /^x[0-9a-fA-F][0-9a-fA-F]?/)) { head = head c2s_raw(s2i(substr(s, 2, RLENGTH - 1), 16)); s = substr(s, RLENGTH + 1); } else if (match(s, /^U[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]([0-9a-fA-F]([0-9a-fA-F][0-9a-fA-F]?)?)?/)) { head = head c2s(s2i(substr(s, 2, RLENGTH - 1), 16)); s = substr(s, RLENGTH + 1); } else if (match(s, /^[uU][0-9a-fA-F]([0-9a-fA-F]([0-9a-fA-F][0-9a-fA-F]?)?)?/)) { head = head c2s(s2i(substr(s, 2, RLENGTH - 1), 16)); s = substr(s, RLENGTH + 1); } else if (match(s, /^c[ -~]/)) { c = es_s2c[substr(s, 2, 1)]; head = head c2s(_ble_bash >= 40400 && c == 63 ? 127 : c % 32); s = substr(s, 3); } else { head = head "\\"; } } return head s; } ' _ble_bin_awk_libNLFIX=' function nlfix_begin(_, tmp) { nlfix_rep_slash = "\\"; if (AWKTYPE == "xpg4") nlfix_rep_slash = "\\\\"; nlfix_rep_double_slash = "\\\\"; sub(/.*/, nlfix_rep_double_slash, tmp); if (tmp == "\\") nlfix_rep_double_slash = "\\\\\\\\"; nlfix_indices = ""; nlfix_index = 0; } function nlfix_push(elem, file) { if (elem ~ /\n/) { gsub(/\\/, nlfix_rep_double_slash, elem); gsub(/'\''/, nlfix_rep_slash "'\''", elem); gsub(/\007/, nlfix_rep_slash "a", elem); gsub(/\010/, nlfix_rep_slash "b", elem); gsub(/\011/, nlfix_rep_slash "t", elem); gsub(/\012/, nlfix_rep_slash "n", elem); gsub(/\013/, nlfix_rep_slash "v", elem); gsub(/\014/, nlfix_rep_slash "f", elem); gsub(/\015/, nlfix_rep_slash "r", elem); if (file) printf("$'\''%s'\''\n", elem) > file; else printf("$'\''%s'\''\n", elem); nlfix_indices = nlfix_indices != "" ? nlfix_indices " " nlfix_index : nlfix_index; } else { if (file) printf("%s\n", elem) > file; else printf("%s\n", elem); } nlfix_index++; } function nlfix_end(file) { if (file) printf("%s\n", nlfix_indices) > file; else printf("%s\n", nlfix_indices); } ' _ble_util_writearray_rawbytes= function ble/util/writearray { local _ble_local_array local -x _ble_local_nlfix _ble_local_delim ble/util/writearray/.read-arguments "$@" || return 2 local __ble_awk=ble/bin/awk __ble_awktype=$_ble_bin_awk_type if ble/is-function ble/bin/mawk; then __ble_awk=ble/bin/mawk __ble_awktype=mawk elif ble/is-function ble/bin/nawk; then __ble_awk=ble/bin/nawk __ble_awktype=nawk fi if ((!_ble_local_nlfix)) && ! [[ _ble_bash -ge 50200 && $__ble_awktype == [mn]awk ]]; then if [[ $_ble_local_delim ]]; then if [[ $_ble_local_delim == *["%\'"]* ]]; then local __ble_q=\' __ble_Q="'\''" _ble_local_delim=${_ble_local_delim//'%'/'%%'} _ble_local_delim=${_ble_local_delim//'\'/'\\'} _ble_local_delim=${_ble_local_delim//$__ble_q/$__ble_Q} fi builtin eval "printf '%s$_ble_local_delim' \"\${$_ble_local_array[@]}\"" else builtin eval "printf '%s\0' \"\${$_ble_local_array[@]}\"" fi return "$?" fi local __ble_function_gensub_dummy= [[ $__ble_awktype == gawk ]] || __ble_function_gensub_dummy='function gensub(rex, rep, n, str) { exit 3; }' if [[ ! $_ble_util_writearray_rawbytes ]]; then local IFS=$_ble_term_IFS __ble_tmp; __ble_tmp=('\'{2,3}{0..7}{0..7}) builtin eval "local _ble_util_writearray_rawbytes=\$'${__ble_tmp[*]}'" fi local -x __ble_rawbytes=$_ble_util_writearray_rawbytes local __ble_rex_dq='^"([^\\"]|\\.)*"' local __ble_rex_es='^\$'\''([^\\'\'']|\\.)*'\''' local __ble_rex_sq='^'\''([^'\'']|'\'\\\\\'\'')*'\''' local __ble_rex_normal=$'^[^'$_ble_term_space'$`"'\''()|&;<>\\]' # Note: []{}?*#!~^, @(), +() は quote されていなくても OK とする declare -p "$_ble_local_array" | "$__ble_awk" -v _ble_bash="$_ble_bash" ' '"$__ble_function_gensub_dummy"' BEGIN { DELIM = ENVIRON["_ble_local_delim"]; FLAG_NLFIX = ENVIRON["_ble_local_nlfix"]; if (FLAG_NLFIX) DELIM = "\n"; IS_GAWK = AWKTYPE == "gawk"; IS_XPG4 = AWKTYPE == "xpg4"; REP_SL = "\\"; if (IS_XPG4) REP_SL = "\\\\"; es_initialize(); decl = ""; } '"$_ble_bin_awk_libES"' '"$_ble_bin_awk_libNLFIX"' function str2rep(str) { if (IS_XPG4) sub(/\\/, "\\\\\\\\", str); return str; } function unquote_dq(s, _, head) { if (IS_GAWK) { return gensub(/\\([$`"\\])/, "\\1", "g", s); } else { if (s ~ /\\[$`"\\]/) { gsub(/\\\$/, "$" , s); gsub(/\\`/ , "`" , s); gsub(/\\"/ , "\"", s); gsub(/\\\\/, "\\", s); } return s; } } function unquote_sq(s) { gsub(/'\'\\\\\'\''/, "'\''", s); return s; } function unquote_dqes(s) { if (s ~ /^"/) return unquote_dq(substr(s, 2, length(s) - 2)); else return es_unescape(substr(s, 3, length(s) - 3)); } function unquote(s) { if (s ~ /^"/) return unquote_dq(substr(s, 2, length(s) - 2)); else if (s ~ /^\$/) return es_unescape(substr(s, 3, length(s) - 3)); else if (s ~ /^'\''/) return unquote_sq(substr(s, 2, length(s) - 2)); else if (s ~ /^\\/) return substr(s, 2, 1); else return s; } function analyze_elements_dq(decl, _, arr, i, n) { if (decl ~ /^\[[0-9]+\]="([^'$'\1\2''"\n\\]|\\.)*"( \[[0-9]+\]="([^\1\2"\\]|\\.)*")*$/) { if (IS_GAWK) { decl = gensub(/\[[0-9]+\]="(([^"\\]|\\.)*)" ?/, "\\1\001", "g", decl); sub(/\001$/, "", decl); decl = gensub(/\\([\\$"`])/, "\\1", decl); } else { gsub(/\[[0-9]+\]="([^"\\]|\\.)*" /, "&\001", decl); gsub(/" \001\[[0-9]+\]="/, "\001", decl); sub(/^\[[0-9]+\]="/, "", decl); sub(/"$/, "", decl); gsub(/\\\\/, "\002", decl); gsub(/\\\$/, "$", decl); gsub(/\\"/, "\"", decl); gsub(/\\`/, "`", decl); gsub(/\002/, REP_SL, decl); } if (DELIM != "") { gsub(/\001/, str2rep(DELIM), decl); printf("%s", decl DELIM); } else { n = split(decl, arr, /\001/); for (i = 1; i <= n; i++) printf("%s%c", arr[i], 0); } if (FLAG_NLFIX) printf("\n"); return 1; } return 0; } function _process_elem(elem) { if (FLAG_NLFIX) { nlfix_push(elem); } else if (DELIM != "") { printf("%s", elem DELIM); } else { printf("%s%c", elem, 0); } } function analyze_elements_general(decl, _, arr, i, n, str, elem, m) { if (FLAG_NLFIX) nlfix_begin(); n = split(decl, arr, /\]=/); str = " " arr[1]; elem = ""; first = 1; for (i = 2; i <= n; i++) { str = str "]=" arr[i]; if (sub(/^ \[[0-9]+\]=/, "", str)) { if (first) first = 0; else _process_elem(elem); elem = ""; } if (match(str, /('"$__ble_rex_dq"'|'"$__ble_rex_es"') /)) { mlen = RLENGTH; elem = elem unquote_dqes(substr(str, 1, mlen - 1)); str = substr(str, mlen); continue; } else if (i == n || str !~ /^[\$"]/) { while (match(str, /'"$__ble_rex_dq"'|'"$__ble_rex_es"'|'"$__ble_rex_sq"'|'"$__ble_rex_normal"'|^\\./)) { mlen = RLENGTH; elem = elem unquote(substr(str, 1, mlen)); str = substr(str, mlen + 1); } } } _process_elem(elem); if (FLAG_NLFIX) nlfix_end(); return 1; } function process_declaration(decl) { sub(/^declare +(-[-aAilucnrtxfFgGI]+ +)?(-- +)?/, "", decl); if (decl ~ /^([_a-zA-Z][_a-zA-Z0-9]*)='\''\(.*\)'\''$/) { sub(/(=)'\''\(/, "=(", decl); sub(/\)'\''$/, ")", decl); gsub(/'\'\\\\\'\''/, "'\''", decl); } if (_ble_bash < 30100) gsub(/\\\n/, "\n", decl); if (_ble_bash < 40400) { gsub(/\001\001/, "\001", decl); gsub(/\001\177/, "\177", decl); } sub(/^([_a-zA-Z][_a-zA-Z0-9]*)=\(['"$_ble_term_space"']*/, "", decl); sub(/['"$_ble_term_space"']*\)['"$_ble_term_space"']*$/, "", decl); if (decl == "") return 1; if (AWKTYPE != "mawk" && analyze_elements_dq(decl)) return 1; return analyze_elements_general(decl); } { decl = decl ? decl "\n" $0: $0; } END { process_declaration(decl); } ' } function ble/util/readarray { local _ble_local_array local -x _ble_local_nlfix _ble_local_delim ble/util/writearray/.read-arguments "$@" || return 2 if ((_ble_bash>=40400)); then local _ble_local_script=' mapfile -t -d "$_ble_local_delim" NAME' elif ((_ble_bash>=40000)) && [[ $_ble_local_delim == $'\n' ]]; then local _ble_local_script=' mapfile -t NAME' else local _ble_local_script=' local IFS= NAMEI=0; NAME=() while ble/bash/read -d "$_ble_local_delim" "NAME[NAMEI++]"; do :; done' fi if [[ $_ble_local_nlfix ]]; then _ble_local_script=$_ble_local_script' local NAMEN=${#NAME[@]} NAMEF NAMEI if ((NAMEN--)); then ble/string#split-words NAMEF "${NAME[NAMEN]}" builtin unset -v "NAME[NAMEN]" for NAMEI in "${NAMEF[@]}"; do builtin eval -- "NAME[NAMEI]=${NAME[NAMEI]}" done fi' fi builtin eval -- "${_ble_local_script//NAME/$_ble_local_array}" } _ble_util_assign_base=$_ble_base_run/$$.util.assign.tmp _ble_util_assign_level=0 if ((_ble_bash>=40000)); then function ble/util/assign/mktmp { _ble_local_tmpfile=$_ble_util_assign_base.$((_ble_util_assign_level++)) ((BASH_SUBSHELL)) && _ble_local_tmpfile=$_ble_local_tmpfile.$BASHPID } else function ble/util/assign/mktmp { _ble_local_tmpfile=$_ble_util_assign_base.$((_ble_util_assign_level++)) ((BASH_SUBSHELL)) && _ble_local_tmpfile=$_ble_local_tmpfile.$RANDOM } fi function ble/util/assign/rmtmp { ((_ble_util_assign_level--)) if ((BASH_SUBSHELL)); then printf 'caller %s\n' "${FUNCNAME[@]}" >| "$_ble_local_tmpfile" else >| "$_ble_local_tmpfile" fi } if ((_ble_bash>=50300)); then function ble/util/assign { builtin eval "$1=\${ builtin eval -- \"\$2\"; }" } elif ((_ble_bash>=40000)); then function ble/util/assign { local _ble_local_tmpfile; ble/util/assign/mktmp builtin eval -- "$2" >| "$_ble_local_tmpfile" local _ble_local_ret=$? _ble_local_arr= mapfile -t _ble_local_arr < "$_ble_local_tmpfile" ble/util/assign/rmtmp IFS=$'\n' builtin eval "$1=\"\${_ble_local_arr[*]}\"" return "$_ble_local_ret" } else function ble/util/assign { local _ble_local_tmpfile; ble/util/assign/mktmp builtin eval -- "$2" >| "$_ble_local_tmpfile" local _ble_local_ret=$? IFS= ble/bash/read -d '' "$1" < "$_ble_local_tmpfile" ble/util/assign/rmtmp builtin eval "$1=\${$1%\$_ble_term_nl}" return "$_ble_local_ret" } fi if ((_ble_bash>=40000)); then function ble/util/assign-array { local _ble_local_tmpfile; ble/util/assign/mktmp builtin eval -- "$2" >| "$_ble_local_tmpfile" local _ble_local_ret=$? mapfile -t "$1" < "$_ble_local_tmpfile" ble/util/assign/rmtmp return "$_ble_local_ret" } else function ble/util/assign-array { local _ble_local_tmpfile; ble/util/assign/mktmp builtin eval -- "$2" >| "$_ble_local_tmpfile" local _ble_local_ret=$? ble/util/mapfile "$1" < "$_ble_local_tmpfile" ble/util/assign/rmtmp return "$_ble_local_ret" } fi if ! ((_ble_bash>=40400)); then function ble/util/assign-array0 { local _ble_local_tmpfile; ble/util/assign/mktmp builtin eval -- "$2" >| "$_ble_local_tmpfile" local _ble_local_ret=$? mapfile -d '' -t "$1" < "$_ble_local_tmpfile" ble/util/assign/rmtmp return "$_ble_local_ret" } else function ble/util/assign-array0 { local _ble_local_tmpfile; ble/util/assign/mktmp builtin eval -- "$2" >| "$_ble_local_tmpfile" local _ble_local_ret=$? local IFS= i=0 _ble_local_arr while ble/bash/read -d '' "_ble_local_arr[i++]"; do :; done < "$_ble_local_tmpfile" ble/util/assign/rmtmp [[ ${_ble_local_arr[--i]} ]] || builtin unset -v "_ble_local_arr[i]" ble/util/unlocal i IFS builtin eval "$1=(\"\${_ble_local_arr[@]}\")" return "$_ble_local_ret" } fi function ble/util/assign.has-output { local _ble_local_tmpfile; ble/util/assign/mktmp builtin eval -- "$1" >| "$_ble_local_tmpfile" [[ -s $_ble_local_tmpfile ]] local _ble_local_ret=$? ble/util/assign/rmtmp return "$_ble_local_ret" } function ble/util/assign-words { ble/util/assign "$1" "$2" ble/string#split-words "$1" "${!1}" } ble/bin/awk/.instantiate if ((_ble_bash>=30200)); then function ble/is-function { declare -F -- "$1" &>/dev/null } else function ble/is-function { local type ble/util/type type "$1" [[ $type == function ]] } fi if ((_ble_bash>=30200)); then function ble/function#getdef { local name=$1 ble/is-function "$name" || return 1 if [[ -o posix ]]; then ble/util/assign def 'builtin type -- "$name"' def=${def#*$'\n'} else ble/util/assign def 'declare -f -- "$name"' fi } else function ble/function#getdef { local name=$1 ble/is-function "$name" || return 1 ble/util/assign def 'builtin type -- "$name"' def=${def#*$'\n'} } fi function ble/function#evaldef { ble/base/evaldef "$1" } builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_util_function_traced}" function ble/function#trace { local func for func; do declare -ft -- "$func" &>/dev/null || continue ble/gdict#set _ble_util_function_traced "$func" 1 done } function ble/function#has-trace { ble/gdict#has _ble_util_function_traced "$1" } function ble/function#has-attr { local __ble_tmp=$1 ble/util/assign-array __ble_tmp 'declare -pf -- "$__ble_tmp" 2>/dev/null' local nline=${#__ble_tmp[@]} ((nline)) && ble/string#match "${__ble_tmp[nline-1]}" '^declare -([a-zA-Z]*)' && [[ ${BASH_REMATCH[1]} == *["$2"]* ]] } function ble/function/is-global-trace-context { local func depth=1 ndepth=${#FUNCNAME[*]} for func in "${FUNCNAME[@]:1}"; do local src=${BASH_SOURCE[depth]} [[ $- == *T* && ( $func == ble || $func == ble[-/]* || $func == source && $src == "$_ble_base_blesh_raw" ) ]] || [[ $func == source && depth -eq ndepth-1 && BASH_LINENO[depth] -eq 0 && ( ${src##*/} == .bashrc || ${src##*/} == .bash_profile || ${src##*/} == .profile ) ]] || ble/gdict#has _ble_util_function_traced "$func" || return 1 ((depth++)) done return 0 } function ble/function#try { local lastexit=$? ble/is-function "$1" || return 127 ble/util/setexit "$lastexit" "$@" } function ble/function#get-source-and-lineno { local func=$1 ret unset_extdebug= shopt -q extdebug || { unset_extdebug=1; shopt -s extdebug; } ble/util/assign ret 'declare -F -- "$func" 2>/dev/null'; local ext=$? [[ ! $unset_extdebug ]] || shopt -u extdebug if ((ext==0)); then ret=${ret#*' '} lineno=${ret%%' '*} source=${ret#*' '} [[ $lineno && ! ${lineno//[0-9]} && $source ]] || return 1 fi return "$ext" } function ble/function#advice/do { ble/util/setexit "$advice_lastexit" "$advice_lastarg" ble/function#advice/original:"${ADVICE_WORDS[@]}" ADVICE_EXIT=$? } function ble/function#advice/.proc { local advice_lastexit=$? advice_lastarg=$_ local ADVICE_WORDS ADVICE_EXIT=127 ADVICE_WORDS=("$@") local -a ADVICE_FUNCNAME=() local func for func in "${FUNCNAME[@]}"; do [[ $func == ble/function#advice/* ]] || ble/array#push ADVICE_FUNCNAME "$func" done ble/util/unlocal func ble/function#try "ble/function#advice/before:$1" if ble/is-function "ble/function#advice/around:$1"; then "ble/function#advice/around:$1" else ble/function#advice/do fi ble/function#try "ble/function#advice/after:$1" return "$ADVICE_EXIT" } function ble/function#advice { local type=$1 name=$2 proc=$3 if ! ble/is-function "$name"; then local t=; ble/util/type t "$name" case $t in (builtin|file) builtin eval "function $name { : ZBe85Oe28nBdg; command $name \"\$@\"; }" ;; (*) ble/util/print "ble/function#advice: $name is not a function." >&2 return 1 ;; esac fi local def; ble/function#getdef "$name" case $type in (remove) if [[ $def == *'ble/function#advice/.proc'* ]]; then ble/function#getdef "ble/function#advice/original:$name" if [[ $def ]]; then if [[ $def == *ZBe85Oe28nBdg* ]]; then builtin unset -f "$name" else ble/function#evaldef "${def#*:}" fi fi fi builtin unset -f ble/function#advice/{before,after,around,original}:"$name" 2>/dev/null return 0 ;; (before|after|around) if [[ $def != *'ble/function#advice/.proc'* ]]; then ble/function#evaldef "ble/function#advice/original:$def" builtin eval "function $name { ble/function#advice/.proc \"\$FUNCNAME\" \"\$@\"; }" fi local q=\' Q="'\''" builtin eval "ble/function#advice/$type:$name() { builtin eval '${proc//$q/$Q}'; }" return 0 ;; (*) ble/util/print "ble/function#advice unknown advice type '$type'" >&2 return 2 ;; esac } function ble/function#push { local name=$1 proc=$2 if ble/is-function "$name"; then local index=0 while ble/is-function "ble/function#push/$index:$name"; do ((++index)) done local def; ble/function#getdef "$name" ble/function#evaldef "ble/function#push/$index:$def" fi if [[ $proc ]]; then local q=\' Q="'\''" builtin eval "function $name { builtin eval -- '${proc//$q/$Q}'; }" else builtin unset -f "$name" fi return 0 } function ble/function#pop { local name=$1 proc=$2 local index=-1 while ble/is-function "ble/function#push/$((index+1)):$name"; do ((++index)) done if ((index<0)); then if ble/is-function "$name"; then builtin unset -f "$name" return 0 elif ble/bin#has "$name"; then ble/util/print "ble/function#pop: $name is not a function." >&2 return 1 else return 0 fi else local def; ble/function#getdef "ble/function#push/$index:$name" ble/function#evaldef "${def#*:}" builtin unset -f "ble/function#push/$index:$name" return 0 fi } function ble/function#push/call-top { local func=${FUNCNAME[1]} if ! ble/is-function "$func"; then ble/util/print "ble/function#push/call-top: This function should be called from a function" >&2 return 1 fi local index=0 if [[ $func == ble/function#push/?*:?* ]]; then index=${func#*/*/}; index=${index%%:*} func=${func#*:} else while ble/is-function "ble/function#push/$index:$func"; do ((index++)); done fi if ((index==0)); then command "$func" "$@" else "ble/function#push/$((index-1)):$func" "$@" fi } : "${_ble_util_lambda_count:=0}" function ble/function#lambda { local _ble_local_q=\' _ble_local_Q="'\''" ble/util/set "$1" ble/function#lambda/$((_ble_util_lambda_count++)) builtin eval -- "function ${!1} { builtin eval -- '${2//$_ble_local_q/$_ble_local_Q}'; }" } function ble/function#suppress-stderr { local name=$1 if ! ble/is-function "$name"; then ble/util/print "$FUNCNAME: '$name' is not a function name" >&2 return 2 fi local lambda=ble/function#suppress-stderr:$name if ! ble/is-function "$lambda"; then local def; ble/function#getdef "$name" ble/function#evaldef "ble/function#suppress-stderr:$def" fi builtin eval "function $name { $lambda \"\$@\" 2>/dev/null; }" return 0 } if ((_ble_bash>=40100)); then function ble/util/set { builtin printf -v "$1" %s "$2" } else function ble/util/set { builtin eval -- "$1=\"\$2\"" } fi if ((_ble_bash>=30100)); then function ble/util/sprintf { builtin printf -v "$@" } else function ble/util/sprintf { local -a args; args=("${@:2}") ble/util/assign "$1" 'builtin printf "${args[@]}"' } fi function ble/util/type { ble/util/assign-array "$1" 'builtin type -a -t -- "$3" 2>/dev/null' "$2" } if ((_ble_bash>=40000)); then function ble/is-alias { [[ $1 && ${BASH_ALIASES[$1]+set} ]] } function ble/alias#active { shopt -q expand_aliases && [[ $1 && ${BASH_ALIASES[$1]+set} ]] } function ble/alias#expand { ret=$1 shopt -q expand_aliases && [[ $1 ]] && ret=${BASH_ALIASES[$ret]-$ret} } function ble/alias/list { ret=("${!BASH_ALIASES[@]}") } else function ble/is-alias { [[ $1 != *=* ]] && alias "$1" &>/dev/null } function ble/alias#active { shopt -q expand_aliases && [[ $1 != *=* ]] && alias "$1" &>/dev/null } function ble/alias#expand { ret=$1 local type; ble/util/type type "$ret" [[ $type != alias ]] && return 1 local data; ble/util/assign data 'LC_ALL=C alias "$ret"' &>/dev/null [[ $data == 'alias '*=* ]] && builtin eval "ret=${data#alias *=}" } function ble/alias/list { ret=() local data iret=0 ble/util/assign-array data 'alias -p' for data in "${data[@]}"; do [[ $data == 'alias '*=* ]] && data=${data%%=*} && builtin eval "ret[iret++]=${data#alias }" done } fi function ble/util/load-standard-builtin { local ret; ble/util/readlink "$BASH" local bash_prefix=${ret%/*/*} if [[ -s $bash_prefix/lib/bash/$1 ]] && ( enable -f "$bash_prefix/lib/bash/$1" "$1" && help "$1" && { [[ ! $2 ]] || builtin eval -- "$2"; } ) &>/dev/null then enable -f "$bash_prefix/lib/bash/$1" "$1" return 0 else return 1 fi } if ((_ble_bash>=40000)); then function ble/util/is-stdin-ready { local IFS= LC_ALL= LC_CTYPE=C builtin read -t 0 } ble/function#suppress-stderr ble/util/is-stdin-ready else function ble/util/is-stdin-ready { return "${1:-1}"; } fi if ((_ble_bash>=40000)); then function ble/util/getpid { return 0; } function ble/util/is-running-in-subshell { [[ $$ != $BASHPID ]]; } else function ble/util/getpid { local command='echo $PPID' ble/util/assign BASHPID 'ble/bin/sh -c "$command"' } function ble/util/is-running-in-subshell { ((BASH_SUBSHELL==0)) || return 0 local BASHPID; ble/util/getpid [[ $$ != $BASHPID ]] } fi _ble_util_fd_is_open_stdout= _ble_util_fd_is_open_stderr= if ((_ble_bash>=40000)) && [[ -d /proc/$BASHPID/fd ]]; then function ble/fd#is-open { [[ $1 && -e /proc/$BASHPID/fd/$1 ]]; } function ble/fd#is-open/.upgrade { builtin unset -f "$FUNCNAME"; } else function ble/fd#is-open { builtin : 9>&"$1"; } 2>/dev/null function ble/fd#is-open/.upgrade { if ! { [[ $_ble_util_fd_null ]] && ((1)) >&"$_ble_util_fd_null"; } 2>/dev/null; then ble/util/print "$FUNCNAME: [FATAL] call this function after \$_ble_util_fd_null is ready" >&2 return 1 fi local fd1 fd2 ble/fd#alloc/.nextfd fd1 ble/fd#alloc/.nextfd fd2 _ble_util_fd_is_open_stdout=$fd1 _ble_util_fd_is_open_stderr=$fd2 builtin eval -- " ble/fd#alloc/.exec $fd1 '>/dev/null' # disable=#D1835 ble/fd#alloc/.exec $fd2 '>&$fd1' # disable=#D1835 function ble/fd#is-open { ble/string#match \"\$1\" '^[0-9]+$' || return 1 [[ \$1 == $fd1 || \$1 == $fd2 || \$1 == $_ble_util_fd_null ]] && return 0 ble/fd#alloc/.exec $fd2 '>&2' # disable=#D1835 exec 2>&$_ble_util_fd_null # disable=#D1835 ble/fd#alloc/.exec $fd1 \">&\$1\" # disable=#D1835 local ext=\$? exec 2>&$fd2 # disable=#D1835 ble/fd#alloc/.exec $fd1 '>&$_ble_util_fd_null' # disable=#D1835 ble/fd#alloc/.exec $fd2 '>&$fd1' # disable=#D1835 return \"\$ext\" } " builtin unset -f "$FUNCNAME" } fi function ble/fd#alloc/.close { builtin eval "exec $1<&-"; } # disable=#D2164 if ((30100<=_ble_bash&&_ble_bash<30200)); then function ble/fd#alloc/.close/.upgrade { if ! { [[ $_ble_util_fd_null ]] && ((1)) >&"$_ble_util_fd_null"; } 2>/dev/null; then ble/util/print "$FUNCNAME: [FATAL] call this function after \$_ble_util_fd_null is ready" >&2 return 1 fi builtin eval -- " function ble/fd#alloc/.close { ((\$1==$_ble_util_fd_null||\$1==2)) && return 1 exec $_ble_util_fd_null<&\"\$1\"- } 2>/dev/null" builtin unset -f "$FUNCNAME" } else function ble/fd#alloc/.close/.upgrade { builtin unset -f "$FUNCNAME"; } fi function ble/fd/.validate-shared-fds { local -a close_fd=() if [[ ${_ble_util_fdvars_export-} ]]; then local ret var fd ble/string#split ret : "$_ble_util_fdvars_export" for var in "${ret[@]}"; do ble/string#match "$var" '^[a-zA-Z_][a-zA-Z_0-9]*$' || continue fd=${!var} ble/string#match "$fd" '^[0-9]+$' || continue if ! ble/fd#is-open "$fd"; then ble/array#push close_fd "$fd" builtin unset -v "$var" fi done for var in "${!_ble_util_fd_@}"; do fd=${!var} ble/string#match "$fd" '^[0-9]{2,}$' || continue if ! ble/fd#is-open "$fd"; then ble/array#push close_fd "$fd" builtin unset -v "$var" fi done _ble_util_fdvars_export= fi if [[ ${_ble_util_fdlist_cloexec-} ]]; then local ret fd ble/string#split ret : "$_ble_util_fdlist_cloexec" for fd in "${ret[@]}"; do ble/string#match "$fd" '^([0-9]+)(=(.*))?' || continue local fd=${BASH_REMATCH[1]} type=${BASH_REMATCH[3]-} case $type in (L*) [[ -h /proc/$$/fd/$1 ]] && ble/util/readlink "/proc/$$/fd/$1" && [[ ${ret//:} == "${type#L}" ]] || continue ;; (t) [[ -t $fd ]] || continue ;; (o) [[ ! -t $fd ]] || continue ;; esac ble/array#push close_fd "$fd" done _ble_util_fdlist_cloexec= fi if ((${#close_fd[@]})); then "${_ble_util_set_declare[@]//NAME/mark}" # disable=#D1570 local fd for fd in "${close_fd[@]}"; do ble/set#contains mark "$fd" && continue ble/set#add mark "$fd" ble/fd#alloc/.close "$fd" done fi } ble/fd/.validate-shared-fds _ble_util_fdlist_cloexit= export _ble_util_fdlist_cloexec= export _ble_util_fdvars_export= _ble_util_openat_nextfd= function ble/fd#alloc/.nextfd { [[ $_ble_util_openat_nextfd ]] || _ble_util_openat_nextfd=${bleopt_openat_base:-30} local _ble_local_init=${2:-$_ble_util_openat_nextfd} local _ble_local_limit=$((_ble_local_init+1024)) local _ble_local_nextfd=$_ble_local_init while ((_ble_local_nextfd<_ble_local_limit)) && ble/fd#is-open "$_ble_local_nextfd"; do ((_ble_local_nextfd++)) done if ((_ble_local_nextfd>=_ble_local_limit)); then _ble_local_nextfd=$_ble_local_init ble/fd#alloc/.close "$_ble_local_nextfd" fi (($1=_ble_local_nextfd++)) [[ ${2-} || :${3-}: == *:no-increment:* ]] || _ble_util_openat_nextfd=$_ble_local_nextfd } if [[ :$bleopt_connect_tty: == *:inherit:* ]]; then if [[ ! ${_ble_util_fd_null-} ]] || ! ble/fd#is-open "$_ble_util_fd_null"; then builtin eval "exec $_ble_util_fd_null<>/dev/null" ble/opts#append-unique _ble_util_fdvars_export _ble_util_fd_null export _ble_util_fd_null ble/fd#alloc/.nextfd _ble_util_fd_null fi else ble/fd#alloc/.nextfd _ble_util_fd_null builtin eval "exec $_ble_util_fd_null<>/dev/null" ble/opts#append-unique _ble_util_fdlist_cloexit "$_ble_util_fd_null" fi ble/fd#alloc/.close/.upgrade function ble/fd#alloc/.exec { ble/fd#alloc/.close "$1" builtin eval "exec $1$2" } ble/fd#is-open/.upgrade if [[ -d /proc/$$/fd ]]; then function ble/fd#list/adjust-glob { set=$- shopt= gignore=$GLOBIGNORE ble/base/list-shopt failglob dotglob shopt -u failglob set +f GLOBIGNORE= } function ble/fd#list/restore-glob { GLOBIGNORE=$gignore if [[ :$shopt: == *:dotglob:* ]]; then shopt -s dotglob; else shopt -u dotglob; fi [[ $set == *f* ]] && set -f [[ :$shopt: == *:failglob:* ]] && shopt -s failglob } function ble/fd#list { ret=() local set shopt gignore ble/fd#list/adjust-glob local pid=${1-} if [[ ! $pid ]]; then if ((_ble_bash<40000)); then local BASHPID ble/util/getpid fi pid=$BASHPID fi local fd for fd in /proc/"$pid"/fd/[0-9]*; do fd=${fd##*/} [[ $fd && ! ${fd//[0-9]} ]] && ble/array#push ret "$fd" done ble/fd#list/restore-glob } else function ble/fd#list { ret=() local fd for fd in {0..255}; do ble/fd#is-open "$fd" && ble/array#push ret "$fd" done } fi if ((_ble_bash>=40400)) && ble/util/load-standard-builtin fdflags 'builtin fdflags 0; (($?<=2))'; then function ble/fd#cloexec/.add { builtin fdflags -s +cloexec "$1"; } function ble/fd#cloexec/.remove { builtin fdflags -s -cloexec "$1"; } elif ((_ble_bash>=40000)); then if [[ -d /proc/$$/fd ]]; then function ble/fd#cloexec/.listfd { local fd for fd in /proc/"$$"/fd/*; do fd=${fd##*/} [[ $fd && ! ${fd//[0-9]} ]] && ble/util/set "$1[fd]" 1 done } function ble/fd#cloexec/.probe { local fdset2 ble/fd#cloexec/.listfd fdset2 local fd for fd in "${!fdset1[@]}"; do builtin unset -v 'fdset2[fd]'; done fd=("${!fdset2[@]}") ((${#fd[@]}==1)) && ble/fd#alloc/.nextfd ret '' no-increment && builtin eval -- "exec $ret<&$fd" && return 0 ret= return 1 } function ble/fd#cloexec/.dup-undo-redirection-fd { local set shopt gignore ble/fd#list/adjust-glob local fd=$1 fdset1 ble/fd#cloexec/.listfd fdset1 builtin eval -- "ble/fd#cloexec/.probe $fd&- $fd>&$ret $ret>&-" # disable=#D2164 (here bash4+) } 2>/dev/null function ble/fd#cloexec/.remove { local fd=$1 if ((fd!=0)); then builtin eval -- "exec 0<&$fd $fd<&- $fd<&0" &$fd $fd>&- $fd>&1" >/dev/null # disable=#D2164 (here bash4+) fi } else function ble/fd#cloexec/.add { false; } function ble/fd#cloexec/.remove { false; } fi function ble/fd#add-cloexec { ble/fd#cloexec/.add "$1" && return 0 local type if [[ -h /proc/$$/fd/$1 ]] && ble/util/readlink "/proc/$$/fd/$1"; then type=L${ret//:} elif [[ -t ${!1} ]]; then type=t else type=o fi ble/opts#remove _ble_util_fdlist_cloexec "$1" ble/opts#append _ble_util_fdlist_cloexec "$1=$type" } function ble/fd#remove-cloexec { ble/fd#cloexec/.remove "$1" || return "$?" ble/opts#remove _ble_util_fdlist_cloexec "$1" return 0 } function ble/fd#alloc { local _ble_local_opts=$3 if [[ :$_ble_local_opts: == *:inherit:* ]]; then [[ ${!1-} ]] && ble/fd#is-open "${!1}" && return 0 _ble_local_opts=$_ble_local_opts:export elif [[ :$_ble_local_opts: == *:inherit-tty:* ]]; then [[ ${!1-} && -t ${!1-} ]] && return 0 _ble_local_opts=$_ble_local_opts:export fi if [[ :$_ble_local_opts: == *:share:* ]]; then if ble/string#match "$2" '[<>]&['"$_ble_term_IFS"']*([0-9]+)['"$_ble_term_IFS"']*$'; then builtin eval -- "$1=${BASH_REMATCH[1]}" return 0 fi fi if [[ ${!1-} && :$_ble_local_opts: == *:overwrite:* ]]; then _ble_local_opts=$_ble_local_opts:preserve ble/fd#alloc/.exec "${!1}" "$2" elif ((_ble_bash>=40100)) && [[ :$_ble_local_opts: != *:base:* ]]; then builtin eval "exec {$1}$2" else ble/fd#alloc/.nextfd "$1" ble/fd#alloc/.exec "${!1}" "$2" fi; local _ble_local_ext=$? if ((_ble_local_ext==0)); then if [[ :$_ble_local_opts: == *:export:* ]]; then export "$1" ble/opts#append-unique _ble_util_fdvars_export "$1" elif [[ :$_ble_local_opts: != *:preserve:* ]]; then ble/opts#append-unique _ble_util_fdlist_cloexit "${!1}" ble/fd#add-cloexec "${!1}" fi fi return "$_ble_local_ext" } function ble/fd#finalize { local fds fd ble/string#split fds : "$_ble_util_fdlist_cloexit" for fd in "${fds[@]}"; do [[ $fd ]] || continue ble/fd#alloc/.close "$fd" done _ble_util_fdlist_cloexit= _ble_util_fdlist_cloexec= } function ble/fd#is-cloexit { [[ :$_ble_util_fdlist_cloexit: == *:"$fd":* ]] } function ble/fd#close { set -- "$(($1))" (($1>=3)) || return 1 ble/fd#alloc/.close "$1" ble/opts#remove _ble_util_fdlist_cloexit "$1" ble/opts#remove _ble_util_fdlist_cloexec "$1" return 0 } bleopt/declare -v connect_tty 1 export bleopt_connect_tty ble/fd#add-cloexec "$_ble_util_fd_null" _ble_util_fd_zero= if [[ -c /dev/zero ]] && ! ble/base/is-msys1; then if [[ :$bleopt_connect_tty: == *:inherit:* ]]; then ble/fd#alloc _ble_util_fd_zero '< /dev/zero' base:inherit else ble/fd#alloc _ble_util_fd_zero '< /dev/zero' base fi fi function ble/fd/.initialize-standard-stream { local var_tty=_ble_util_fd_tty_$1 local var_cmd=_ble_util_fd_cmd_$1 local var_tui=_ble_util_fd_tui_$1 local fd=${2::1} redir=${2:1} ble/fd#alloc "$var_cmd" "$redir&$fd" base if [[ -t $fd ]]; then local alloc_opts=base [[ $bleopt_connect_tty == inherit ]] && alloc_opts=$alloc_opts:overwrite:export ble/fd#alloc "$var_tty" "$redir&$fd" "$alloc_opts" ble/util/set "$var_tui" "${!var_tty}" return 0 fi if [[ ! $_ble_init_command && $bleopt_connect_tty ]]; then local alloc_opts=base [[ $bleopt_connect_tty == inherit ]] && alloc_opts=$alloc_opts:inherit-tty if ble/fd#alloc "$var_tty" "$redir /dev/tty" "$alloc_opts"; then ble/util/set "$var_tui" "${!var_tty}" builtin eval -- "exec $fd$redir&${!var_tui}" return 0 else builtin unset -v "$var_tty" fi fi ble/util/set "$var_tui" "${!var_cmd}" } ble/fd/.initialize-standard-stream stdin '0<' ble/fd/.initialize-standard-stream stdout '1>' ble/fd/.initialize-standard-stream stderr '2>' function ble/fd/save-external-standard-streams { ble/fd#alloc _ble_util_fd_cmd_stdin "<&${1:-0}" base:overwrite ble/fd#alloc _ble_util_fd_cmd_stdout ">&${2:-1}" base:overwrite ble/fd#alloc _ble_util_fd_cmd_stderr ">&${3:-2}" base:overwrite ble/fd#add-cloexec "$_ble_util_fd_cmd_stdin" ble/fd#add-cloexec "$_ble_util_fd_cmd_stdout" ble/fd#add-cloexec "$_ble_util_fd_cmd_stderr" } function ble/fd#close-all-tty { local ret ble/fd#list local fd for fd in "${ret[@]}"; do if ble/string#match "$fd" '^[0-9]+$' && [[ -t $fd ]]; then ble/fd#alloc/.exec "$fd" ">&$_ble_util_fd_null" ble/opts#remove _ble_util_fdlist_cloexit "$fd" fi done } function ble/util/nohup { if ((!BASH_SUBSHELL)); then (ble/util/nohup "$@") return "$?" fi ble/fd#close-all-tty shopt -u huponexit builtin eval -- "$1" &>/dev/null =40000)); then ble/util/assign __ble_decl "declare -p $__ble_name" 2>/dev/null __ble_decl=${__ble_decl#declare -* } else ble/util/assign __ble_decl "ble/util/declare-print-definitions $__ble_name" 2>/dev/null fi if ble/is-array "$__ble_name"; then __ble_decl="declare -a $__ble_decl" else __ble_decl="declare -A $__ble_decl" fi else __ble_decl=${!__ble_name} __ble_decl="declare $__ble_name='${__ble_decl//$__ble_q/$__ble_Q}'" fi ble/util/print "$__ble_decl" } function ble/util/print-global-definitions { local __ble_opts= [[ $1 == --hidden-only ]] && { __ble_opts=hidden-only; shift; } ble/util/for-global-variables ble/util/print-global-definitions/.print-decl "$__ble_opts" "$@" } function ble/util/for-global-variables { local __ble_proc=$1 __ble_opts=$2; shift 2 local __ble_hidden_only= [[ :$__ble_opts: == *:hidden-only:* ]] && __ble_hidden_only=1 ( ble/util/joblist/__suppress__ ((_ble_bash>=50000)) && shopt -u localvar_unset __ble_error= __ble_q="'" __ble_Q="'\''" __ble_MaxLoop=20 builtin unset -v "${!_ble_processed_@}" for __ble_name; do [[ ${__ble_name//[_a-zA-Z0-9]} || $__ble_name == __ble_* ]] && continue ((__ble_processed_$__ble_name)) && continue ((__ble_processed_$__ble_name=1)) __ble_found= if ((_ble_bash>=40200)); then declare -g -r "$__ble_name" for ((__ble_i=0;__ble_i<__ble_MaxLoop;__ble_i++)); do if ! builtin unset -v "$__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" fi break fi done else for ((__ble_i=0;__ble_i<__ble_MaxLoop;__ble_i++)); do if ble/variable#is-global "$__ble_name"; then __ble_found=1 [[ $__ble_hidden_only && $__ble_i == 0 ]] || "$__ble_proc" "$__ble_name" break fi builtin unset -v "$__ble_name" || break done fi if [[ ! $__ble_found ]]; then __ble_error=1 [[ $__ble_hidden_only && $__ble_i == 0 ]] || "$__ble_proc" "$__ble_name" unset fi done [[ ! $__ble_error ]] ) 2>/dev/null } function ble/util/has-glob-pattern { [[ $1 ]] || return 1 local restore=: if ! shopt -q nullglob 2>/dev/null; then restore="$restore;shopt -u nullglob" shopt -s nullglob fi if shopt -q failglob 2>/dev/null; then restore="$restore;shopt -s failglob" shopt -u failglob fi local dummy=$_ble_base_run/$$.dummy ret builtin eval "ret=(\"\$dummy\"/${1#/})" 2>/dev/null builtin eval -- "$restore" [[ ! $ret ]] } function ble/util/is-cygwin-slow-glob { [[ ( $OSTYPE == cygwin || $OSTYPE == msys ) && ${1#\'} == //* && ! -o noglob ]] && ble/util/has-glob-pattern "$1" } function ble/util/eval-pathname-expansion { ret=() if ble/util/is-cygwin-slow-glob; then # Note: #D1168 if shopt -q failglob &>/dev/null; then return 1 elif shopt -q nullglob &>/dev/null; then return 0 else set -f ble/util/eval-pathname-expansion "$1"; local ext=$1 set +f return "$ext" fi fi local canon= if [[ :$2: == *:canonical:* ]]; then canon=1 local set=$- shopt gignore=$GLOBIGNORE ble/base/list-shopt failglob nullglob extglob dotglob shopt -u failglob shopt -s nullglob shopt -s extglob set +f GLOBIGNORE= fi builtin eval "ret=($1)" 2>/dev/null; local ext=$? if [[ $canon ]]; then GLOBIGNORE=$gignore if [[ :$shopt: == *:dotglob:* ]]; then shopt -s dotglob; else shopt -u dotglob; fi [[ $set == *f* ]] && set -f [[ :$shopt: != *:extglob:* ]] && shopt -u extglob [[ :$shopt: != *:nullglob:* ]] && shopt -u nullglob [[ :$shopt: == *:failglob:* ]] && shopt -s failglob fi return "$ext" } _ble_util_rex_isprint='^[ -~]+' function ble/util/isprint+ { local LC_ALL= LC_COLLATE=C [[ $1 =~ $_ble_util_rex_isprint ]] } ble/function#suppress-stderr ble/util/isprint+ _ble_util_mktime_tzdelta= function ble/util/mktime { if (($#==6||$#==7)); then local tz=${7-} if [[ ! $tz ]]; then if [[ ! ${_ble_util_mktime_tzdelta-} ]]; then ble/util/assign _ble_util_mktime_tzdelta 'ble/bin/date +%z' fi tz=$_ble_util_mktime_tzdelta fi local tzdelta if ble/string#match "$tz" '^[-+]([0-9]{1,2})([0-9]{2})$'; then tzdelta=${tz::1}$(((10#0${BASH_REMATCH[1]}*60+10#0${BASH_REMATCH[2]})*60)) else tzdelta=0 fi local Y=$((10#0$1)) m=$((10#0$2)) d=$((10#0$3)) local H=$((10#0$4)) M=$((10#0$5)) S=$((10#0$6)) ((m<3)) && ((Y--,m+=12)) local day_delta=$((365*(Y-1970)+(Y/4-Y/100+Y/400-477)+(m+1)*306/10-63+(d-1))) ((ret=((day_delta*24+H)*60+M)*60+S-tzdelta)) return 0 elif ble/string#match "${1-}" '^([0-9]{4})-([01]?[0-9])-([0-3]?[0-9]) ([0-2]?[0-9]):([0-5]?[0-9]):([0-5]?[0-9])( ([-+][0-9]{3,4}))?$'; then ble/util/mktime "${BASH_REMATCH[@]:1:6}" "${BASH_REMATCH[8]-}" else ble/util/print "$FUNCNAME: invalid argument '${1-}'" >&2 return 2 fi } if ((_ble_bash>=40200)); then function ble/util/strftime { if [[ $1 = -v ]]; then builtin printf -v "$2" "%($3)T" "${4:--1}" else builtin printf "%($1)T" "${2:--1}" fi } else function ble/util/strftime { if [[ $1 = -v ]]; then local fmt=$3 time=$4 ble/util/assign "$2" "ble/bin/date +\"\$fmt\" $time" else ble/bin/date +"$1" $2 fi } fi if ((_ble_bash>=50000)); then function ble/util/time { ret=$EPOCHSECONDS; } function ble/util/timeval { ret=${EPOCHREALTIME//[!0-9]}; } else function ble/util/time { if ble/util/strftime -v ret '%s' 2>/dev/null && ble/string#match '^[0-9]{3,}$'; then function ble/util/time { ble/util/strftime -v ret '%s'; } else function ble/util/time { ble/util/strftime -v ret '%F %T %z' ble/util/mktime "$ret" } ble/util/time fi if ((_ble_bash<40200)) && ble/string#match "${SECONDS-}" '^[0-9]+$'; then builtin readonly SECONDS _ble_util_time_base=$((ret-SECONDS)) function ble/util/time { ((ret=_ble_util_time_base+SECONDS)); } fi } function ble/util/timeval { ble/util/time; ((ret*=1000000)); } fi function blehook/.print { (($#)) || return 0 local out= q=\' Q="'\''" nl=$'\n' local sgr0= sgr1= sgr2= sgr3= if [[ $flags == *c* ]]; then local ret ble/color/face2sgr command_function; sgr1=$ret ble/color/face2sgr syntax_varname; sgr2=$ret ble/color/face2sgr syntax_quoted; sgr3=$ret sgr0=$_ble_term_sgr0 Q=$q$sgr0"\'"$sgr3$q fi local elem op_assign code=' if ((${#_ble_hook_h_NAME[@]})); then op_assign== for elem in "${_ble_hook_h_NAME[@]}"; do out="${out}${sgr1}blehook$sgr0 ${sgr2}NAME$sgr0$op_assign${sgr3}$q${elem//$q/$Q}$q$sgr0$nl" op_assign=+= done else out="${out}${sgr1}blehook$sgr0 ${sgr2}NAME$sgr0=$nl" fi' local hookname for hookname; do ble/is-array "$hookname" || continue builtin eval -- "${code//NAME/${hookname#_ble_hook_h_}}" done ble/util/put "$out" } function blehook/.print-help { ble/util/print-lines \ 'usage: blehook [NAME[[=|+=|-=|-+=]COMMAND]]...' \ ' Add or remove hooks. Without arguments, this prints all the existing hooks.' \ '' \ ' Options:' \ ' --help Print this help.' \ ' -a, --all Print all hooks including the internal ones.' \ ' --color[=always|never|auto]' \ ' Change color settings.' \ '' \ ' Arguments:' \ ' NAME Print the corresponding hooks.' \ ' NAME=COMMAND Set hook after removing the existing hooks.' \ ' NAME+=COMMAND Add hook.' \ ' NAME-=COMMAND Remove hook.' \ ' NAME!=COMMAND Add hook if the command is not registered.' \ ' NAME-+=COMMAND Append the hook and remove the duplicates.' \ ' NAME+-=COMMAND Prepend the hook and remove the duplicates.' \ '' \ ' NAME:' \ ' The hook name. The characters "@", "*", and "?" may be used as wildcards.' \ '' } function blehook/.read-arguments { flags= print=() process=() local opt_color=auto while (($#)); do local arg=$1; shift if [[ $arg == -* ]]; then case $arg in (--help) flags=H$flags ;; (--color) opt_color=always ;; (--color=always|--color=auto|--color=never) opt_color=${arg#*=} ;; (--color=*) ble/util/print "blehook: '${arg#*=}': unrecognized option argument for '--color'." >&2 flags=E$flags ;; (--all) flags=a$flags ;; (--*) ble/util/print "blehook: unrecognized long option '$arg'." >&2 flags=E$flags ;; (-) ble/util/print "blehook: unrecognized argument '$arg'." >&2 flags=E$flags ;; (*) local i c for ((i=1;i<${#arg};i++)); do c=${arg:i:1} case $c in (a) flags=a$flags ;; (*) ble/util/print "blehook: unrecognized option '-$c'." >&2 flags=E$flags ;; esac done ;; esac elif [[ $arg =~ $rex1 ]]; then if [[ $arg == *[@*?]* ]] || ble/is-array "_ble_hook_h_$arg"; then ble/array#push print "$arg" else ble/util/print "blehook: undefined hook '$arg'." >&2 fi elif [[ $arg =~ $rex2 ]]; then local name=${BASH_REMATCH[1]} if [[ $name == *[@*?]* ]]; then if [[ ${BASH_REMATCH[2]} == :* ]]; then ble/util/print "blehook: hook pattern cannot be combined with '${BASH_REMATCH[2]}'." >&2 flags=E$flags continue fi else local var_counter=_ble_hook_c_$name if [[ ! ${!var_counter+set} ]]; then if [[ ${BASH_REMATCH[2]} == :* ]]; then (($var_counter=0)) else ble/util/print "blehook: hook \"$name\" is not defined." >&2 flags=E$flags continue fi fi fi ble/array#push process "$arg" else ble/util/print "blehook: invalid hook spec \"$arg\"" >&2 flags=E$flags fi done local pat ret out; out=() for pat in "${print[@]}"; do if [[ $pat == *[@*?]* ]]; then bleopt/expand-variable-pattern "_ble_hook_h_$pat" ble/array#filter ret ble/is-array [[ $pat == *[a-z]* || $flags == *a* ]] || ble/array#remove-by-glob ret '_ble_hook_h_*[a-z]*' if ((!${#ret[@]})); then ble/util/print "blehook: '$pat': matching hook not found." >&2 flags=E$flags continue fi else ret=("_ble_hook_h_$pat") fi ble/array#push out "${ret[@]}" done print=("${out[@]}") out=() for pat in "${process[@]}"; do [[ $pat =~ $rex2 ]] local name=${BASH_REMATCH[1]} if [[ $name == *[@*?]* ]]; then local type=${BASH_REMATCH[3]} local value=${BASH_REMATCH[4]} bleopt/expand-variable-pattern "_ble_hook_h_$pat" ble/array#filter ret ble/is-array [[ $pat == *[a-z]* || $flags == *a* ]] || ble/array#remove-by-glob ret '_ble_hook_h_*[a-z]*' if ((!${#ret[@]})); then ble/util/print "blehook: '$pat': matching hook not found." >&2 flags=E$flags continue fi if ((_ble_bash>=40300)) && ! shopt -q compat42; then ret=("${ret[@]/%/"$type$value"}") # WA #D1570 #D1751 checked else ret=("${ret[@]/%/$type$value}") # WA #D1570 #D1738 checked fi else ret=("_ble_hook_h_$pat") fi ble/array#push out "${ret[@]}" done process=("${out[@]}") [[ $opt_color == always || $opt_color == auto && -t 1 ]] && flags=c$flags } function blehook { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" local set shopt ble/base/adjust-BASH_REMATCH ble/base/.adjust-bash-options set shopt local LC_ALL= LC_COLLATE=C 2>/dev/null # suppress locale error #D1440 local flags print process local rex1='^([_a-zA-Z@*?][_a-zA-Z0-9@*?]*)$' local rex2='^([_a-zA-Z@*?][_a-zA-Z0-9@*?]*)(:?([-+!]|-\+|\+-)?=)(.*)$' blehook/.read-arguments "$@" if [[ $flags == *[HE]* ]]; then if [[ $flags == *H* ]]; then [[ $flags == *E* ]] && ble/util/print >&2 blehook/.print-help fi [[ $flags != *E* ]]; local ext=$? ble/util/unlocal LC_ALL LC_COLLATE 2>/dev/null # suppress locale error #D1440 ble/base/.restore-bash-options set shopt ble/base/restore-BASH_REMATCH builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_leave" return "$ext" fi if ((${#print[@]}==0&&${#process[@]}==0)); then print=("${!_ble_hook_h_@}") [[ $flags == *a* ]] || ble/array#remove-by-glob print '_ble_hook_h_*[a-z]*' fi local proc ext=0 for proc in "${process[@]}"; do [[ $proc =~ $rex2 ]] local name=${BASH_REMATCH[1]} local type=${BASH_REMATCH[3]} local value=${BASH_REMATCH[4]} local append=$value case $type in (*-*) # -=, -+=, +-= local ret ble/array#last-index "$name" "$value" if ((ret>=0)); then ble/array#remove-at "$name" "$ret" elif [[ ${type#:} == '-=' ]]; then ext=1 fi if [[ $type != -+ ]]; then append= [[ $type == +- ]] && ble/array#unshift "$name" "$value" fi ;; ('!') # != local ret ble/array#last-index "$name" "$value" ((ret>=0)) && append= ;; ('') builtin eval "$name=()" ;; # = ('+'|*) ;; # += esac [[ $append ]] && ble/array#push "$name" "$append" done if ((${#print[@]})); then blehook/.print "${print[@]}" fi ble/util/unlocal LC_ALL LC_COLLATE 2>/dev/null # suppress locale error #D1440 ble/base/.restore-bash-options set shopt ble/base/restore-BASH_REMATCH ble/util/setexit "$ext" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" } blehook/.compatibility-ble-0.3 function blehook/has-hook { builtin eval "local count=\${#_ble_hook_h_$1[@]}" ((count)) } function blehook/invoke.sandbox { if ble/bin#has "$_ble_local_hook"; then ble/util/setexit "$_ble_local_lastexit" "$_ble_local_lastarg" "$_ble_local_hook" "$@" 2>&3 else ble/util/setexit "$_ble_local_lastexit" "$_ble_local_lastarg" builtin eval -- "$_ble_local_hook" 2>&3 fi } function blehook/invoke { local _ble_local_lastexit=$? _ble_local_lastarg=$_ FUNCNEST= ((_ble_hook_c_$1++)) local -a _ble_local_hooks builtin eval "_ble_local_hooks=(\"\${_ble_hook_h_$1[@]}\")"; shift local _ble_local_hook _ble_local_ext=0 for _ble_local_hook in "${_ble_local_hooks[@]}"; do blehook/invoke.sandbox "$@" || _ble_local_ext=$? done return "$_ble_local_ext" } 3>&2 2>/dev/null # set -x 対策 #D0930 function blehook/eval-after-load { local hook_name=${1}_load value=$2 if ((_ble_hook_c_$hook_name)); then builtin eval -- "$value" else blehook "$hook_name+=$value" fi } _ble_builtin_trap_inside= # ble/builtin/trap 処理中かどうか function ble/builtin/trap/.read-arguments { flags= command= sigspecs=() while (($#)); do local arg=$1; shift if [[ $arg == -?* && flags != *A* ]]; then if [[ $arg == -- ]]; then flags=A$flags continue elif [[ $arg == --* ]]; then case $arg in (--help) flags=h$flags continue ;; (*) ble/util/print "ble/builtin/trap: unknown long option \"$arg\"." >&2 flags=E$flags continue ;; esac fi local i for ((i=1;i<${#arg};i++)); do case ${arg:i:1} in (l) flags=l$flags ;; (p) flags=p$flags ;; (P) flags=P$flags ;; (*) ble/util/print "ble/builtin/trap: unknown option \"-${arg:i:1}\"." >&2 flags=E$flags ;; esac done else if [[ $flags != *[pc]* ]]; then command=$arg flags=c$flags else ble/array#push sigspecs "$arg" fi fi done if [[ $flags != *[hlpPE]* ]]; then if [[ $flags != *c* ]]; then flags=p$flags elif ((${#sigspecs[@]}==0)); then sigspecs=("$command") command=- fi elif [[ $flags == *p* && $flags == *P* ]]; then ble/util/print "ble/builtin/trap: cannot specify both -p and -P" >&2 flags=E${flags//[pP]} fi } builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_builtin_trap_name2sig}" _ble_builtin_trap_sig_name=() _ble_builtin_trap_sig_opts=() _ble_builtin_trap_sig_base=1000 _ble_builtin_trap_EXIT= _ble_builtin_trap_DEBUG= _ble_builtin_trap_RETURN= _ble_builtin_trap_ERR= function ble/builtin/trap/sig#register { local sig=$1 name=$2 _ble_builtin_trap_sig_name[sig]=$name ble/gdict#set _ble_builtin_trap_name2sig "$name" "$sig" } function ble/builtin/trap/sig#reserve { local ret ble/builtin/trap/sig#resolve "$1" || return 1 _ble_builtin_trap_sig_opts[ret]=${2:-1} } function ble/builtin/trap/sig#resolve { ble/builtin/trap/sig#init if [[ $1 && ! ${1//[0-9]} ]]; then ret=$1 return 0 else ble/gdict#get _ble_builtin_trap_name2sig "$1" [[ $ret ]] && return 0 ble/string#toupper "$1"; local upper=$ret ble/gdict#get _ble_builtin_trap_name2sig "$upper" || ble/gdict#get _ble_builtin_trap_name2sig "SIG$upper" || return 1 ble/gdict#set _ble_builtin_trap_name2sig "$1" "$ret" return 0 fi } function ble/builtin/trap/sig#new { local name=$1 opts=$2 local sig=$((_ble_builtin_trap_$name=_ble_builtin_trap_sig_base++)) ble/builtin/trap/sig#register "$sig" "$name" if [[ :$opts: != *:builtin:* ]]; then ble/builtin/trap/sig#reserve "$sig" "$opts" fi } function ble/builtin/trap/sig#init { function ble/builtin/trap/sig#init { return 0; } local ret i ble/util/assign-words ret 'builtin trap -l' 2>/dev/null for ((i=0;i<${#ret[@]};i+=2)); do local index=${ret[i]%')'} local name=${ret[i+1]} ble/builtin/trap/sig#register "$index" "$name" done _ble_builtin_trap_EXIT=0 ble/builtin/trap/sig#register "$_ble_builtin_trap_EXIT" EXIT ble/builtin/trap/sig#new DEBUG builtin ble/builtin/trap/sig#new RETURN builtin ble/builtin/trap/sig#new ERR builtin } _ble_builtin_trap_handlers=() _ble_builtin_trap_handlers_RETURN=() function ble/builtin/trap/user-handler#load { local sig=$1 name=${_ble_builtin_trap_sig_name[$1]} if [[ $name == RETURN ]]; then ble/builtin/trap/user-handler#load:RETURN else _ble_trap_handler=${_ble_builtin_trap_handlers[sig]-} [[ ${_ble_builtin_trap_handlers[sig]+set} ]] fi } function ble/builtin/trap/user-handler#save { local sig=$1 name=${_ble_builtin_trap_sig_name[$1]} handler=$2 if [[ $name == RETURN ]]; then ble/builtin/trap/user-handler#save:RETURN "$handler" else if [[ $handler == - ]]; then builtin unset -v '_ble_builtin_trap_handlers[sig]' else _ble_builtin_trap_handlers[sig]=$handler fi fi return 0 } function ble/builtin/trap/user-handler#save:RETURN { local handler=$1 local offset= for ((offset=1;offset<${#FUNCNAME[@]};offset++)); do case ${FUNCNAME[offset]} in (trap | ble/builtin/trap) ;; (ble/builtin/trap/user-handler#save) ;; (*) break ;; esac done local current_level=$((${#FUNCNAME[@]}-offset)) local level for level in "${!_ble_builtin_trap_handlers_RETURN[@]}"; do if ((level>current_level)); then builtin unset -v '_ble_builtin_trap_handlers_RETURN[level]' fi done if [[ $handler == - ]]; then if [[ $- == *T* ]] || shopt -q extdebug; then for ((level=current_level;level>=0;level--)); do builtin unset -v '_ble_builtin_trap_handlers_RETURN[level]' done else for ((level=current_level;level>=0;level--,offset++)); do builtin unset -v '_ble_builtin_trap_handlers_RETURN[level]' ((level)) && ble/function#has-attr "${FUNCNAME[offset]}" t || break done fi else _ble_builtin_trap_handlers_RETURN[current_level]=$handler fi return 0 } function ble/builtin/trap/user-handler#load:RETURN { local offset= in_trap= for ((offset=1;offset<${#FUNCNAME[@]};offset++)); do case ${FUNCNAME[offset]} in (trap | ble/builtin/trap) ;; (ble/builtin/trap/.handler) ;; (ble/builtin/trap/user-handler#load) ;; (ble/builtin/trap/user-handler#has) ;; (ble/builtin/trap/finalize) ;; (ble/builtin/trap/install-hook) ;; (ble/builtin/trap/invoke) ;; (*) break ;; esac done local search_level= if [[ $- == *T* ]] || shopt -q extdebug; then search_level=0 else for ((;offset<${#FUNCNAME[@]};offset++)); do ble/function#has-attr "${FUNCNAME[offset]}" t || break done search_level=$((${#FUNCNAME[@]}-offset)) fi local level found= handler= for level in "${!_ble_builtin_trap_handlers_RETURN[@]}"; do ((level>=search_level)) || continue found=1 handler=${_ble_builtin_trap_handlers_RETURN[level]} done _ble_trap_handler=$handler [[ $found ]] } function ble/builtin/trap/user-handler#update:RETURN { local offset=2 # ... ble/builtin/trap/.handler から直接呼び出されると仮定 local current_level=$((${#FUNCNAME[@]}-offset)) ((current_level>0)) || return 0 local level found= handler= for level in "${!_ble_builtin_trap_handlers_RETURN[@]}"; do ((level>=current_level)) || continue found=1 handler=${_ble_builtin_trap_handlers_RETURN[level]} if ((level>=current_level)); then builtin unset -v '_ble_builtin_trap_handlers_RETURN[level]' fi done if [[ $found ]]; then _ble_builtin_trap_handlers_RETURN[current_level-1]=$handler fi } function ble/builtin/trap/user-handler#has { local _ble_trap_handler ble/builtin/trap/user-handler#load "$1" } function ble/builtin/trap/user-handler#init { local script _ble_builtin_trap_user_handler_init=1 ble/util/assign script 'builtin trap -p' builtin eval -- "$script" } function ble/builtin/trap/user-handler/is-internal { case $1 in ('ble/builtin/trap/'*) return 0 ;; # ble-0.4 ('ble/base/unload'*|'ble-edit/'*) return 0 ;; # bash-0.3 以前 (*) return 1 ;; esac } function ble/builtin/trap/finalize { _ble_builtin_trap_handlers_reload=() local sig unload_opts=$1 for sig in "${!_ble_builtin_trap_sig_opts[@]}"; do local name=${_ble_builtin_trap_sig_name[sig]} local opts=${_ble_builtin_trap_sig_opts[sig]} [[ $name && :$opts: == *:override-builtin-signal:* ]] || continue if [[ :$opts: == *:readline:* && :$unload_opts: == *:reload:* ]]; then if local _ble_trap_handler; ble/builtin/trap/user-handler#load "$sig"; then local q=\' Q="'\''" _ble_builtin_trap_handlers_reload[sig]="trap -- '${_ble_trap_handler//$q/$Q}' $name" else _ble_builtin_trap_handlers_reload[sig]= fi continue fi if local _ble_trap_handler; ble/builtin/trap/user-handler#load "$sig"; then builtin trap -- "$_ble_trap_handler" "$name" else builtin trap -- - "$name" fi done } function ble/builtin/trap { local set shopt; ble/base/.adjust-bash-options set shopt local flags command sigspecs ble/builtin/trap/.read-arguments "$@" if [[ $flags == *h* ]]; then builtin trap --help ble/base/.restore-bash-options set shopt return 2 elif [[ $flags == *E* ]]; then builtin trap --usage 2>&1 1>/dev/null | ble/bin/grep ^trap >&2 ble/base/.restore-bash-options set shopt return 2 elif [[ $flags == *l* ]]; then builtin trap -l fi [[ ! $_ble_attached || $_ble_edit_exec_inside_userspace ]] && ble/base/adjust-BASH_REMATCH if [[ $flags == *[pP]* ]]; then local -a indices=() if ((${#sigspecs[@]})); then local spec ret for spec in "${sigspecs[@]}"; do if ! ble/builtin/trap/sig#resolve "$spec"; then ble/util/print "ble/builtin/trap: invalid signal specification \"$spec\"." >&2 continue fi ble/array#push indices "$ret" done else indices=("${!_ble_builtin_trap_handlers[@]}" "$_ble_builtin_trap_RETURN") fi local q=\' Q="'\''" index _ble_trap_handler for index in "${indices[@]}"; do if ble/builtin/trap/user-handler#load "$index"; then if [[ $flags == *p* ]]; then local n=${_ble_builtin_trap_sig_name[index]} _ble_trap_handler="trap -- '${_ble_trap_handler//$q/$Q}' $n" fi ble/util/print "$_ble_trap_handler" fi done else [[ $_ble_builtin_trap_user_handler_init ]] && ble/builtin/trap/user-handler/is-internal "$command" && return 0 local _ble_builtin_trap_inside=1 local spec ret for spec in "${sigspecs[@]}"; do if ! ble/builtin/trap/sig#resolve "$spec"; then ble/util/print "ble/builtin/trap: invalid signal specification \"$spec\"." >&2 continue fi local sig=$ret local name=${_ble_builtin_trap_sig_name[sig]} ble/builtin/trap/user-handler#save "$sig" "$command" [[ $_ble_builtin_trap_user_handler_init ]] && continue local trap_command='builtin trap -- "$command" "$spec"' local install_opts=${_ble_builtin_trap_sig_opts[sig]} if [[ $install_opts ]]; then local custom_trap=ble/builtin/trap:$name if ble/is-function "$custom_trap"; then trap_command='"$custom_trap" "$command" "$spec"' elif [[ :$install_opts: == *:readline:* ]] && ! ble/util/is-running-in-subshell; then trap_command= elif [[ $command == - ]]; then if [[ :$install_opts: == *:inactive:* ]]; then trap_command='builtin trap - "$spec"' else trap_command= fi elif [[ :$install_opts: == *:override-builtin-signal:* ]]; then ble/builtin/trap/install-hook/.compose-trap_command "$sig" trap_command="builtin $trap_command" else trap_command= fi fi if [[ $trap_command ]]; then if [[ $name == ERR && $command == - && $- != *E* ]]; then command= fi builtin eval -- "$trap_command" fi done fi [[ ! $_ble_attached || $_ble_edit_exec_inside_userspace ]] && ble/base/restore-BASH_REMATCH ble/base/.restore-bash-options set shopt return 0 } function trap { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" ble/builtin/trap "$@" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" } ble/builtin/trap/user-handler#init function ble/builtin/trap/.TRAPRETURN { local IFS=$_ble_term_IFS local backtrace=" ${BLE_TRAP_FUNCNAME[*]-} " case $backtrace in (' trap '* | ' ble/builtin/trap '*) return 126 ;; (*' ble/builtin/trap/.handler '*) case ${backtrace%%' ble/builtin/trap/.handler '*}' ' in (' '*' blehook/invoke.sandbox '* | ' '*' ble/builtin/trap/invoke.sandbox '*) ;; (*) return 126 ;; esac ;; (*' _ble_edit_exec_gexec__save_lastarg ' | ' _ble_edit_exec_gexec__TRAPDEBUG_adjust ') return 126 ;; esac return 0 } blehook internal_RETURN!=ble/builtin/trap/.TRAPRETURN _ble_builtin_trap_user_lastcmd= _ble_builtin_trap_user_lastarg= _ble_builtin_trap_user_lastexit= function ble/builtin/trap/invoke.sandbox { local _ble_trap_count for ((_ble_trap_count=0;_ble_trap_count<1;_ble_trap_count++)); do _ble_trap_done=return ble/util/setexit "$_ble_trap_lastexit" "$_ble_trap_lastarg" builtin eval -- "$_ble_trap_handler"$'\n_ble_trap_lastexit=$? _ble_trap_lastarg=$_' 2>&3 _ble_trap_done=done return 0 done _ble_trap_lastexit=$? _ble_trap_lastarg=$_ if ((_ble_trap_count==0)); then _ble_trap_done=break else _ble_trap_done=continue fi return 0 } function ble/builtin/trap/invoke { local _ble_trap_lastexit=$? _ble_trap_lastarg=$_ _ble_trap_sig=$1; shift if [[ ${_ble_trap_sig//[0-9]} ]]; then local ret ble/builtin/trap/sig#resolve "$_ble_trap_sig" || return 1 _ble_trap_sig=$ret ble/util/unlocal ret fi local _ble_trap_handler ble/builtin/trap/user-handler#load "$_ble_trap_sig" [[ $_ble_trap_handler ]] || return 0 if [[ $_ble_attached && ! $_ble_edit_exec_inside_userspace ]]; then if [[ $_ble_builtin_trap_user_lastcmd != $_ble_edit_CMD ]]; then _ble_builtin_trap_user_lastcmd=$_ble_edit_CMD _ble_builtin_trap_user_lastexit=$_ble_edit_exec_lastexit _ble_builtin_trap_user_lastarg=$_ble_edit_exec_lastarg fi _ble_trap_lastexit=$_ble_builtin_trap_user_lastexit _ble_trap_lastarg=$_ble_builtin_trap_user_lastarg fi local _ble_trap_done= ble/builtin/trap/invoke.sandbox "$@"; local ext=$? case $_ble_trap_done in (done) _ble_builtin_trap_lastarg[_ble_trap_sig]=$_ble_trap_lastarg _ble_builtin_trap_postproc[_ble_trap_sig]="ble/util/setexit $_ble_trap_lastexit" ;; (break | continue) _ble_builtin_trap_lastarg[_ble_trap_sig]=$_ble_trap_lastarg if ble/string#match "$_ble_trap_lastarg" '^-?[0-9]+$'; then _ble_builtin_trap_postproc[_ble_trap_sig]="$_ble_trap_done $_ble_trap_lastarg" else _ble_builtin_trap_postproc[_ble_trap_sig]=$_ble_trap_done fi ;; (return) _ble_builtin_trap_lastarg[_ble_trap_sig]=$ext _ble_builtin_trap_postproc[_ble_trap_sig]="return $ext" ;; (exit) _ble_builtin_trap_lastarg[_ble_trap_sig]=$_ble_trap_lastarg _ble_builtin_trap_postproc[_ble_trap_sig]="ble/builtin/exit $_ble_trap_lastarg" ;; esac if [[ $_ble_attached && ! $_ble_edit_exec_inside_userspace ]]; then _ble_builtin_trap_user_lastexit=$_ble_trap_lastexit _ble_builtin_trap_user_lastarg=$_ble_trap_lastarg fi return 0 } 3>&2 2>/dev/null # set -x 対策 #D0930 _ble_builtin_trap_processing= _ble_builtin_trap_postproc=() _ble_builtin_trap_lastarg=() function ble/builtin/trap/install-hook/.compose-trap_command { local sig=$1 name=${_ble_builtin_trap_sig_name[$1]} local handler='ble/builtin/trap/.handler SIGNUM "$BASH_COMMAND" "$@"; builtin eval -- "${_ble_builtin_trap_postproc[SIGNUM]}" \# "${_ble_builtin_trap_lastarg[SIGNUM]}"' trap_command="trap -- '${handler//SIGNUM/$sig}' $name" # WA #D1738 checked (sig is integer) } _ble_trap_builtin_handler_DEBUG_filter= function ble/builtin/trap/.handler { local _ble_trap_lastexit=$? _ble_trap_lastarg=$_ FUNCNEST= IFS=$_ble_term_IFS local _ble_trap_sig=$1 _ble_trap_bash_command=$2 shift 2 if [[ $_ble_bash_read_winch && ${_ble_builtin_trap_sig_name[_ble_trap_sig]} == SIGWINCH ]]; then local ret ble/string#quote-command "$FUNCNAME" "$_ble_trap_sig" "$_ble_trap_bash_command" "$@" _ble_bash_read_winch=$ret$'\n''builtin eval -- "${_ble_builtin_trap_postproc['$_ble_trap_sig']}"' return 0 fi if ((_ble_trap_sig==_ble_builtin_trap_DEBUG)) && ! builtin eval -- "$_ble_trap_builtin_handler_DEBUG_filter"; then _ble_builtin_trap_lastarg[_ble_trap_sig]=${_ble_trap_lastarg//*$_ble_term_nl*} _ble_builtin_trap_postproc[_ble_trap_sig]="ble/util/setexit $_ble_trap_lastexit" return 0 fi local _ble_trap_set _ble_trap_shopt; ble/base/.adjust-bash-options _ble_trap_set _ble_trap_shopt local _ble_trap_name=${_ble_builtin_trap_sig_name[_ble_trap_sig]#SIG} local -a _ble_trap_args; _ble_trap_args=("$@") if [[ ! $_ble_trap_bash_command ]] || ((_ble_bash<30200)); then if [[ $_ble_attached ]]; then _ble_trap_bash_command=$_ble_edit_exec_BASH_COMMAND else ble/util/assign _ble_trap_bash_command 'HISTTIMEFORMAT=__ble_ext__ builtin history 1' _ble_trap_bash_command=${_ble_trap_bash_command#*__ble_ext__} fi fi local _ble_builtin_trap_processing=${BASH_SUBSHELL:-0}/$_ble_trap_sig _ble_builtin_trap_lastarg[_ble_trap_sig]=$_ble_trap_lastarg _ble_builtin_trap_postproc[_ble_trap_sig]="ble/util/setexit $_ble_trap_lastexit" if [[ $_ble_builtin_exit_processing ]]; then exec 1>&- 1>&"$_ble_builtin_exit_stdout" exec 2>&- 2>&"$_ble_builtin_exit_stderr" fi local BLE_TRAP_FUNCNAME BLE_TRAP_SOURCE BLE_TRAP_LINENO BLE_TRAP_FUNCNAME=("${FUNCNAME[@]:1}") BLE_TRAP_SOURCE=("${BASH_SOURCE[@]:1}") BLE_TRAP_LINENO=("${BASH_LINENO[@]}") [[ $_ble_attached ]] && BLE_TRAP_LINENO[${#BASH_LINENO[@]}-1]=$_ble_edit_LINENO ble/util/joblist.check ble/util/setexit "$_ble_trap_lastexit" "$_ble_trap_lastarg" blehook/invoke "internal_$_ble_trap_name"; local internal_ext=$? ble/util/joblist.check ignore-volatile-jobs if ((internal_ext!=126)); then if ! ble/util/is-running-in-subshell; then ble/util/setexit "$_ble_trap_lastexit" "$_ble_trap_lastarg" BASH_COMMAND=$_ble_trap_bash_command \ blehook/invoke "$_ble_trap_name" ble/util/joblist.check ignore-volatile-jobs fi local install_opts=${_ble_builtin_trap_sig_opts[_ble_trap_sig]} if [[ :$install_opts: == *:user-trap-in-postproc:* ]]; then local q=\' Q="'\''" _ble_trap_handler postproc= ble/builtin/trap/user-handler#load "$_ble_trap_sig" if [[ $_ble_trap_handler == *[![:space:]]* ]]; then postproc="ble/util/setexit $_ble_trap_lastexit '${_ble_trap_lastarg//$q/$Q}'" postproc=$postproc";LINENO=$BLE_TRAP_LINENO builtin eval -- '${_ble_trap_handler//$q/$Q}'" else postproc="ble/util/setexit $_ble_trap_lastexit" fi _ble_builtin_trap_postproc[_ble_trap_sig]=$postproc else ble/util/setexit "$_ble_trap_lastexit" "$_ble_trap_lastarg" BASH_COMMAND=$_ble_trap_bash_command LINENO=$BLE_TRAP_LINENO \ ble/builtin/trap/invoke "$_ble_trap_sig" "${_ble_trap_args[@]}" fi fi if [[ $_ble_builtin_trap_processing == */exit:* && ${_ble_builtin_trap_postproc[_ble_trap_sig]} != 'ble/builtin/exit '* ]]; then _ble_builtin_trap_postproc[_ble_trap_sig]="ble/builtin/exit ${_ble_builtin_trap_processing#*/exit:}" fi [[ ${_ble_builtin_trap_lastarg[_ble_trap_sig]} == *$'\n'* ]] && _ble_builtin_trap_lastarg[_ble_trap_sig]= if ((_ble_trap_sig==_ble_builtin_trap_EXIT)); then ble/base/unload EXIT elif ((_ble_trap_sig==_ble_builtin_trap_RETURN)); then ble/builtin/trap/user-handler#update:RETURN fi ble/base/.restore-bash-options _ble_trap_set _ble_trap_shopt } function ble/builtin/trap/install-hook { local ret opts=${2-} ble/builtin/trap/sig#resolve "$1" local sig=$ret name=${_ble_builtin_trap_sig_name[ret]} ble/builtin/trap/sig#reserve "$sig" "override-builtin-signal:$opts" local trap_command; ble/builtin/trap/install-hook/.compose-trap_command "$sig" local trap_string; ble/util/assign trap_string "builtin trap -p $name" if [[ :$opts: == *:readline:* ]] && ! ble/util/is-running-in-subshell; then [[ $trap_command == "$trap_string" ]] && trap_command= trap_string= [[ $trap_string ]] || trap_string=${_ble_builtin_trap_handlers_reload[sig]-} fi [[ ! $trap_command || :$opts: == *:inactive:* && ! $trap_string ]] || builtin eval "builtin $trap_command"; local ext=$? local q=\' if [[ $trap_string == "trap -- '"* ]] && ! ble/builtin/trap/user-handler/is-internal "${trap_string#*$q}"; then ((sig<1000)) && ! ble/builtin/trap/user-handler#has "$sig" && builtin eval -- "ble/builtin/$trap_string" fi return "$ext" } if ! builtin type ble/util/print &>/dev/null; then function ble/util/unlocal { builtin unset -v "$@"; } function ble/util/print { builtin printf '%s\n' "$1"; } function ble/util/print-lines { builtin printf '%s\n' "$@"; } fi function ble-measure/.loop { builtin eval "function _target { ${2:+"$2; "}return 0; }" local __ble_i __ble_n=$1 for ((__ble_i=0;__ble_i<__ble_n;__ble_i++)); do _target done } if ((BASH_VERSINFO[0]>=5)) || { [[ ${ZSH_VERSION-} ]] && zmodload zsh/datetime &>/dev/null && [[ ${EPOCHREALTIME-} ]]; } || [[ ${SECONDS-} == *.??? ]] then if [[ ${EPOCHREALTIME-} ]]; then _ble_measure_resolution=1 # [usec] function ble-measure/.get-realtime { local LC_ALL= LC_NUMERIC=C ret=$EPOCHREALTIME } else _ble_measure_resolution=1000 # [usec] function ble-measure/.get-realtime { ret=$SECONDS } fi function ble-measure/.time { ble-measure/.get-realtime 2>/dev/null; local __ble_time1=$ret ble-measure/.loop "$1" "$2" &>/dev/null ble-measure/.get-realtime 2>/dev/null; local __ble_time2=$ret local __ble_frac [[ $__ble_time1 == *.* ]] || __ble_time1=${__ble_time1}. __ble_frac=${__ble_time1##*.}000000 __ble_time1=${__ble_time1%%.*}${__ble_frac:0:6} [[ $__ble_time2 == *.* ]] || __ble_time2=${__ble_time2}. __ble_frac=${__ble_time2##*.}000000 __ble_time2=${__ble_time2%%.*}${__ble_frac:0:6} ((ret=__ble_time2-__ble_time1)) ((ret==0&&(ret=_ble_measure_resolution))) ((ret>0)) } elif [[ ${ZSH_VERSION-} ]]; then _ble_measure_resolution=1000 # [usec] function ble-measure/.time { local result= result=$({ time ( ble-measure/.loop "$1" "$2" ; ) } 2>&1 ) result=${result##*cpu } local rex='(([0-9]+):)?([0-9]+)\.([0-9]+) total$' if [[ $result =~ $rex ]]; then if [[ -o KSH_ARRAYS ]]; then local m=${match[1]} s=${match[2]} ms=${match[3]} else local m=${match[2]} s=${match[3]} ms=${match[4]} fi m=${m:-0} ms=${ms}000; ms=${ms:0:3} ((ret=((10#0$m*60+10#0$s)*1000+10#0$ms)*1000)) return 0 else builtin echo "ble-measure: failed to read the result of \`time': $result." >&2 ret=0 return 1 fi } else _ble_measure_resolution=1000 # [usec] function ble-measure/.time { ret=0 local result TIMEFORMAT='[%R]' __ble_n=$1 __ble_command=$2 if declare -f ble/util/assign &>/dev/null; then ble/util/assign result '{ time ble-measure/.loop "$__ble_n" "$__ble_command" &>/dev/null;} 2>&1' else result=$({ time ble-measure/.loop "$1" "$2" &>/dev/null;} 2>&1) fi local rex='\[([0-9]+)(\.([0-9]+))?\]' [[ $result =~ $rex ]] || return 1 local s=${BASH_REMATCH[1]} local ms=${BASH_REMATCH[3]}000; ms=${ms::3} ((ret=(10#0$s*1000+10#0$ms)*1000)) return 0 } fi _ble_measure_base= # [nsec] _ble_measure_base_nestcost=0 # [nsec/10] _ble_measure_base_real=() _ble_measure_base_guess=() _ble_measure_count=1 # 同じ倍率で _ble_measure_count 回計測して最小を取る。 _ble_measure_threshold=100000 # 一回の計測が threshold [usec] 以上になるようにする function ble-measure/calibrate.0 { ble-measure -qc"$calibrate_count" ''; } function ble-measure/calibrate.1 { ble-measure/calibrate.0; } function ble-measure/calibrate.2 { ble-measure/calibrate.1; } function ble-measure/calibrate.3 { ble-measure/calibrate.2; } function ble-measure/calibrate.4 { ble-measure/calibrate.3; } function ble-measure/calibrate.5 { ble-measure/calibrate.4; } function ble-measure/calibrate.6 { ble-measure/calibrate.5; } function ble-measure/calibrate.7 { ble-measure/calibrate.6; } function ble-measure/calibrate.8 { ble-measure/calibrate.7; } function ble-measure/calibrate.9 { ble-measure/calibrate.8; } function ble-measure/calibrate.A { ble-measure/calibrate.9; } function ble-measure/calibrate { local ret= nsec= local calibrate_count=1 _ble_measure_base=0 _ble_measure_base_nestcost=0 local nest0=$((${#FUNCNAME[@]}+2)) [[ ${ZSH_VERSION-} ]] && nest0=$((${#funcstack[@]}+2)) ble-measure/calibrate.0; local x0=$nsec ble-measure/calibrate.A; local xA=$nsec local nest_cost=$((xA-x0)) _ble_measure_base=$((x0-nest_cost*nest0/10)) _ble_measure_base_nestcost=$nest_cost } function ble-measure/fit { local ret nsec _ble_measure_base=0 _ble_measure_base_nestcost=0 local calibrate_count=10 local c= nest_level=${#FUNCNAME[@]} for c in {0..9} A; do "ble-measure/calibrate.$c" ble/util/print "$((nest_level++)) $nsec" done > ble-measure-fit.txt gnuplot - <&2 if ! ble-measure/.time "$n" "$command"; then builtin eval -- "${_ble_bash_POSIXLY_CORRECT_local_leave-}" return 1 fi [[ $flags != *V* ]] && printf '\r\e[2K' >&2 ((utot=ret,utot>=measure_threshold||n==__ble_max_n)) || continue prev_n=$n prev_utot=$utot local min_utot=$utot if [[ $count ]]; then local sum_utot=$utot sum_count=1 i for ((i=2;i<=count;i++)); do [[ $flags != *V* ]] && printf '%s' "$command (x$n $i/$count)..." >&2 if ble-measure/.time "$n" "$command"; then ((utot=ret,utot&2 done if [[ $flags == *a* ]]; then ((utot=sum_utot/sum_count)) else utot=$min_utot fi fi if ((min_utot<0x7FFFFFFFFFFFFFFF/1000)); then 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=$__ble_base if [[ $flags != *q* ]]; then local reso=$_ble_measure_resolution local awk=ble/bin/awk builtin type -- "$awk" &>/dev/null || awk=awk local -x title="$command (x$n)" "$awk" -v utot="$utot" -v nsec0="$nsec0" -v n="$n" -v reso="$reso" ' function genround(x, mod) { return int(x / mod + 0.5) * mod; } BEGIN { title = ENVIRON["title"]; printf("%12.3f usec/eval: %s\n", genround(utot / n - nsec0 / 1000, reso / 10.0 / n), title); exit }' fi local out ((out=utot/n)) if ((n>=1000)); then ((nsec=utot/(n/1000))) else ((nsec=utot*1000/n)) fi ((out-=nsec0/1000,nsec-=nsec0)) ret=$out builtin eval -- "${_ble_bash_POSIXLY_CORRECT_local_leave-}" return 0 done builtin eval -- "${_ble_bash_POSIXLY_CORRECT_local_return-}" } function ble/util/msleep/.check-sleep-decimal-support { local version; ble/util/assign version 'LC_ALL=C ble/bin/sleep --version 2>&1' 2>/dev/null # suppress locale error #D1440 [[ $version == *'GNU coreutils'* || $OSTYPE == darwin* && $version == 'usage: sleep seconds' ]] } _ble_util_msleep_delay=2000 # [usec] function ble/util/msleep/.core { local sec=${1%%.*} ((10#0${1##*.}&&sec++)) # 小数部分は切り上げ ble/bin/sleep "$sec" } function ble/util/msleep { local v=$((1000*$1-_ble_util_msleep_delay)) ((v<=0)) && v=0 ble/util/sprintf v '%d.%06d' "$((v/1000000))" "$((v%1000000))" ble/util/msleep/.core "$v" } _ble_util_msleep_calibrate_count=0 function ble/util/msleep/.calibrate-loop { local _ble_measure_threshold=10000 local ret nsec _ble_measure_count=1 v=0 _ble_util_msleep_delay=0 ble-measure -q 'ble/util/msleep 1' local delay=$((nsec/1000-1000)) count=$_ble_util_msleep_calibrate_count ((count<=0||delay<_ble_util_msleep_delay)) && _ble_util_msleep_delay=$delay # 最小値 } function ble/util/msleep/calibrate { ble/util/msleep/.calibrate-loop &>/dev/null ((++_ble_util_msleep_calibrate_count<5)) && ble/util/idle.continue } function ble/util/msleep/.use-read-timeout { local msleep_type=$1 opts=${2-} _ble_util_msleep_fd= case $msleep_type in (socket) _ble_util_msleep_delay1=10000 # short msleep にかかる時間 [usec] _ble_util_msleep_delay2=50000 # /bin/sleep 0 にかかる時間 [usec] function ble/util/msleep/.core2 { ((v-=_ble_util_msleep_delay2)) ble/bin/sleep "$((v/1000000))" ((v%=1000000)) } function ble/util/msleep { local v=$((1000*$1-_ble_util_msleep_delay1)) ((v<=0)) && v=100 ((v>1000000+_ble_util_msleep_delay2)) && ble/util/msleep/.core2 ble/util/sprintf v '%d.%06d' "$((v/1000000))" "$((v%1000000))" ! ble/bash/read-timeout "$v" v < /dev/udp/0.0.0.0/80 } function ble/util/msleep/.calibrate-loop { local _ble_measure_threshold=10000 local ret nsec _ble_measure_count=1 v=0 _ble_util_msleep_delay1=0 ble-measure 'ble/util/msleep 1' local delay=$((nsec/1000-1000)) count=$_ble_util_msleep_calibrate_count ((count<=0||delay<_ble_util_msleep_delay1)) && _ble_util_msleep_delay1=$delay # 最小値 _ble_util_msleep_delay2=0 ble-measure 'ble/util/msleep/.core2' local delay=$((nsec/1000)) ((count<=0||delay<_ble_util_msleep_delay2)) && _ble_util_msleep_delay2=$delay # 最小値 } ;; (procsub) _ble_util_msleep_delay=300 ble/fd#alloc _ble_util_msleep_fd '< <( [[ $- == *i* ]] && builtin trap -- '' INT QUIT while kill -0 $$; do command sleep 300; done &>/dev/null )' function ble/util/msleep { local v=$((1000*$1-_ble_util_msleep_delay)) ((v<=0)) && v=100 ble/util/sprintf v '%d.%06d' "$((v/1000000))" "$((v%1000000))" ! ble/bash/read-timeout "$v" -u "$_ble_util_msleep_fd" v } ;; (*.*) if local rex='^(fifo|zero|ptmx)\.(open|exec)([12])(-[_a-zA-Z0-9]+)?$'; [[ $msleep_type =~ $rex ]]; then local file=${BASH_REMATCH[1]} local open=${BASH_REMATCH[2]} local direction=${BASH_REMATCH[3]} local fall=${BASH_REMATCH[4]} case $file in (fifo) _ble_util_msleep_tmp=$_ble_base_run/$$.util.msleep.pipe if [[ ! -p $_ble_util_msleep_tmp ]]; then [[ -e $_ble_util_msleep_tmp ]] && ble/bin/rm -rf "$_ble_util_msleep_tmp" ble/bin/mkfifo "$_ble_util_msleep_tmp" fi ;; (zero) open=dup _ble_util_msleep_tmp=$_ble_util_fd_zero ;; (ptmx) _ble_util_msleep_tmp=/dev/ptmx ;; esac local redir='<' ((direction==2)) && redir='<>' if [[ $open == dup ]]; then _ble_util_msleep_fd=$_ble_util_msleep_tmp _ble_util_msleep_read='! ble/bash/read-timeout "$v" -u "$_ble_util_msleep_fd" v' elif [[ $open == exec ]]; then ble/fd#alloc _ble_util_msleep_fd "$redir \"\$_ble_util_msleep_tmp\"" base _ble_util_msleep_read='! ble/bash/read-timeout "$v" -u "$_ble_util_msleep_fd" v' else _ble_util_msleep_read='! ble/bash/read-timeout "$v" v '$redir' "$_ble_util_msleep_tmp"' fi if [[ $fall == '-coreutil' ]]; then _ble_util_msleep_switch=200 # [msec] _ble_util_msleep_delay1=2000 # short msleep にかかる時間 [usec] _ble_util_msleep_delay2=50000 # /bin/sleep 0 にかかる時間 [usec] function ble/util/msleep { if (($1<_ble_util_msleep_switch)); then local v=$((1000*$1-_ble_util_msleep_delay1)) ((v<=0)) && v=100 ble/util/sprintf v '%d.%06d' "$((v/1000000))" "$((v%1000000))" builtin eval -- "$_ble_util_msleep_read" else local v=$((1000*$1-_ble_util_msleep_delay2)) ((v<=0)) && v=100 ble/util/sprintf v '%d.%06d' "$((v/1000000))" "$((v%1000000))" ble/bin/sleep "$v" fi } function ble/util/msleep/.calibrate-loop { local _ble_measure_threshold=10000 local ret nsec _ble_measure_count=1 _ble_util_msleep_switch=200 _ble_util_msleep_delay1=0 ble-measure 'ble/util/msleep 1' local delay=$((nsec/1000-1000)) count=$_ble_util_msleep_calibrate_count ((count<=0||delay<_ble_util_msleep_delay1)) && _ble_util_msleep_delay1=$delay # 最小値を選択 _ble_util_msleep_delay2=0 ble-measure 'ble/bin/sleep 0' local delay=$((nsec/1000)) ((count<=0||delay<_ble_util_msleep_delay2)) && _ble_util_msleep_delay2=$delay # 最小値を選択 ((_ble_util_msleep_switch=_ble_util_msleep_delay2/1000+10)) } else function ble/util/msleep { local v=$((1000*$1-_ble_util_msleep_delay)) ((v<=0)) && v=100 ble/util/sprintf v '%d.%06d' "$((v/1000000))" "$((v%1000000))" builtin eval -- "$_ble_util_msleep_read" } fi fi ;; esac if [[ :$opts: == *:check:* && $_ble_util_msleep_fd ]]; then if ble/bash/read-timeout 0.000001 -u "$_ble_util_msleep_fd" _ble_util_msleep_dummy 2>/dev/null; (($?<=128)); then ble/fd#close _ble_util_msleep_fd _ble_util_msleep_fd= return 1 fi fi return 0 } _ble_util_msleep_builtin_available= if ((_ble_bash>=40400)) && ble/util/load-standard-builtin sleep; then _ble_util_msleep_builtin_available=1 _ble_util_msleep_delay=300 function ble/util/msleep/.core { builtin sleep "$1"; } function ble/builtin/sleep/.read-time { a1=0 b1=0 local unit= exp= if local rex='^\+?([0-9]*)\.([0-9]*)([eE][-+]?[0-9]+)?([smhd]?)$'; [[ $1 =~ $rex ]]; then a1=${BASH_REMATCH[1]} b1=${BASH_REMATCH[2]}00000000000000 b1=$((10#0${b1::14})) exp=${BASH_REMATCH[3]} unit=${BASH_REMATCH[4]} elif rex='^\+?([0-9]+)([eE][-+]?[0-9]+)?([smhd]?)$'; [[ $1 =~ $rex ]]; then a1=${BASH_REMATCH[1]} exp=${BASH_REMATCH[2]} unit=${BASH_REMATCH[3]} else ble/util/print "ble/builtin/sleep: invalid time spec '$1'" >&2 flags=E$flags return 2 fi if [[ $exp ]]; then case $exp in ([eE]-*) ((exp=10#0${exp:2})) while ((exp--)); do ((b1=a1%10*frac_scale/10+b1/10,a1/=10)) done ;; ([eE]*) exp=${exp:1} ((exp=${exp#+})) while ((exp--)); do ((b1*=10,a1=a1*10+b1/frac_scale,b1%=frac_scale)) done ;; esac fi local scale= case $unit in (d) ((scale=24*3600)) ;; (h) ((scale=3600)) ;; (m) ((scale=60)) ;; esac if [[ $scale ]]; then ((b1*=scale)) ((a1=a1*scale+b1/frac_scale)) ((b1%=frac_scale)) fi return 0 } function ble/builtin/sleep { local set shopt; ble/base/.adjust-bash-options set shopt local frac_scale=100000000000000 local a=0 b=0 flags= if (($#==0)); then ble/util/print "ble/builtin/sleep: no argument" >&2 flags=E$flags fi while (($#)); do case $1 in (--version) flags=v$flags ;; (--help) flags=h$flags ;; (-*) flags=E$flags ble/util/print "ble/builtin/sleep: unknown option '$1'" >&2 ;; (*) if local a1 b1; ble/builtin/sleep/.read-time "$1"; then ((b+=b1)) ((a=a+a1+b/frac_scale)) ((b%=frac_scale)) fi ;; esac shift done if [[ $flags == *h* ]]; then ble/util/print-lines \ 'usage: sleep NUMBER[SUFFIX]...' \ 'Pause for the time specified by the sum of the arguments. SUFFIX is one of "s"' \ '(seconds), "m" (minutes), "h" (hours) or "d" (days).' \ '' \ 'OPTIONS' \ ' --help Show this help.' \ ' --version Show version.' fi if [[ $flags == *v* ]]; then ble/util/print "sleep (ble) $BLE_VERSION" fi if [[ $flags == *E* ]]; then ble/util/setexit 2 elif [[ $flags == *[vh]* ]]; then ble/util/setexit 0 else b=00000000000000$b b=${b:${#b}-14} builtin sleep "$a.$b" fi local ext=$? ble/base/.restore-bash-options set shopt 1 return "$ext" } function sleep { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" ble/builtin/sleep "$@" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" } elif [[ -f $_ble_base/lib/init-msleep.sh ]] && source "$_ble_base/lib/init-msleep.sh" && ble/util/msleep/.load-compiled-builtin then function ble/util/msleep { ble/builtin/msleep "$1"; } elif ((40000<=_ble_bash&&!(40300<=_ble_bash&&_ble_bash<50200))) && [[ $OSTYPE != cygwin* && $OSTYPE != mingw* && $OSTYPE != haiku* && $OSTYPE != minix* ]] then ble/util/msleep/.use-read-timeout fifo.exec2 elif ((_ble_bash>=40000)) && ble/fd#is-open "$_ble_util_fd_zero"; then ble/util/msleep/.use-read-timeout zero.exec1-coreutil elif ble/bin#freeze-utility-path sleepenh; then function ble/util/msleep/.core { ble/bin/sleepenh "$1" &>/dev/null; } elif ble/bin#freeze-utility-path usleep; then function ble/util/msleep { local v=$((1000*$1-_ble_util_msleep_delay)) ((v<=0)) && v=0 ble/bin/usleep "$v" &>/dev/null } elif ble/util/msleep/.check-sleep-decimal-support; then function ble/util/msleep/.core { ble/bin/sleep "$1"; } fi function ble/util/sleep { local msec=$((${1%%.*}*1000)) if [[ $1 == *.* ]]; then frac=${1##*.}000 ((msec+=10#0${frac::3})) fi ble/util/msleep "$msec" } function ble/util/conditional-sync/.collect-descendant-pids { local pid=$1 awk_script=' $1 ~ /^[0-9]+$/ && $2 ~ /^[0-9]+$/ { child[$2,child[$2]++]=$1; } function print_recursive(pid, _, n, i) { if (child[pid]) { n = child[pid]; child[pid] = 0; # avoid infinite loop for (i = 0; i < n; i++) { print_recursive(child[pid, i]); } } print pid; } END { print_recursive(pid); } ' ble/util/assign ret 'ble/bin/ps -A -o pid,ppid' ble/util/assign-array ret 'ble/bin/awk -v pid="$pid" "$awk_script" <<< "$ret"' } function ble/util/conditional-sync/.kill { [[ $__ble_pid ]] || return 0 local kill_pids if [[ :$__ble_opts: == *:killall:* ]]; then ble/util/conditional-sync/.collect-descendant-pids "$__ble_pid" kill_pids=("${ret[@]}") else kill_pids=("$__ble_pid") fi if [[ $OSTYPE == cygwin* || $OSTYPE == msys* ]]; then (ble/util/setexit 0) fi if [[ :$__ble_opts: == *:SIGKILL:* ]]; then builtin kill -9 "${kill_pids[@]}" &>/dev/null else builtin kill -- "${kill_pids[@]}" &>/dev/null fi } &>/dev/null function ble/util/conditional-sync { 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 __ble_timeout= __ble_rex=':timeout=([^:]+):' [[ :$__ble_opts: =~ $__ble_rex ]] && ((__ble_timeout=BASH_REMATCH[1])) [[ :$__ble_opts: == *:progressive-weight:* ]] && local __ble_weight_max=$__ble_weight __ble_weight=1 local ret ble/opts#extract-last-optarg "$__ble_opts" pid local __ble_pid=$ret ble/util/unlocal ret local sync_elapsed=0 if [[ $__ble_timeout ]] && ((__ble_timeout<=0)); then ble/util/conditional-sync/.kill return 142 fi builtin eval -- "$__ble_continue" || return 148 ( ble/util/joblist/__suppress__ [[ $__ble_pid ]] || { builtin eval -- "$__ble_command" & __ble_pid=$!; } while if [[ $__ble_timeout ]]; then if ((__ble_timeout<=0)); then ble/util/conditional-sync/.kill return 142 fi ((__ble_weight>__ble_timeout)) && __ble_weight=$__ble_timeout ((__ble_timeout-=__ble_weight)) fi 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))) [[ ! $__ble_pid ]] || builtin kill -0 "$__ble_pid" &>/dev/null do if ! builtin eval -- "$__ble_continue"; then ble/util/conditional-sync/.kill return 148 fi done [[ ! $__ble_pid || :$__ble_opts: == *:no-wait-pid:* ]] || wait "$__ble_pid" ) } function ble/util/cat/.impl { local content= IFS= while ble/bash/read -d '' content; do printf '%s\0' "$content" done [[ $content ]] && printf '%s' "$content" } function ble/util/cat { if (($#)); then local file for file; do ble/util/cat/.impl < "$1"; done else ble/util/cat/.impl fi } _ble_util_less_fallback= function ble/util/get-pager { if [[ ! $_ble_util_less_fallback ]]; then if ble/bin#has less; then _ble_util_less_fallback=less elif ble/bin#has pager; then _ble_util_less_fallback=pager elif ble/bin#has more; then _ble_util_less_fallback=more else _ble_util_less_fallback=cat fi fi builtin eval "$1=\${bleopt_pager:-\${PAGER:-\$_ble_util_less_fallback}}" } function ble/util/pager { local pager; ble/util/get-pager pager builtin eval -- "$pager \"\$@\"" } _ble_util_file_stat= function ble/file/has-stat { if [[ ! $_ble_util_file_stat ]]; then _ble_util_file_stat=- if ble/bin#freeze-utility-path -n stat; then if ble/bin/stat -c %Y / &>/dev/null; then _ble_util_file_stat=c elif ble/bin/stat -f %m / &>/dev/null; then _ble_util_file_stat=f fi fi fi function ble/file/has-stat { [[ $_ble_util_file_stat != - ]]; } || return 1 ble/file/has-stat } function ble/file#mtime { function ble/file#mtime { ble/util/time; ret=("$ret"); } || return 1 if ble/bin/date -r / +%s &>/dev/null; then function ble/file#mtime { local file=$1; ble/util/assign-words ret 'ble/bin/date -r "$file" +"%s %N"' 2>/dev/null; } elif ble/file/has-stat; then case $_ble_util_file_stat in (c) function ble/file#mtime { local file=$1; ble/util/assign ret 'ble/bin/stat -c %Y "$file"' 2>/dev/null; } ;; (f) function ble/file#mtime { local file=$1; ble/util/assign ret 'ble/bin/stat -f %m "$file"' 2>/dev/null; } ;; esac fi ble/file#mtime "$@" } function ble/file#inode { function ble/file#inode { ret=; ((0)); } || return 1 if ble/bin#freeze-utility-path -n ls && ble/util/assign-words ret 'ble/bin/ls -di /' 2>/dev/null && ((${#ret[@]}==2)) && ble/string#match "$ret" '^[0-9]+$' then function ble/file#inode { local file=$1; ble/util/assign-words ret 'ble/bin/ls -di "$file"' 2>/dev/null; } elif ble/file/has-stat; then case $_ble_util_file_stat in (c) function ble/file#inode { local file=$1; ble/util/assign-words ret 'ble/bin/stat -c %i "$file"' 2>/dev/null; } ;; (f) function ble/file#inode { local file=$1; ble/util/assign-words ret 'ble/bin/stat -f %i "$file"' 2>/dev/null; } ;; esac fi ble/file#inode "$@" } function ble/file#hash { local file=$1 size if ! ble/util/assign size 'ble/bin/wc -c "$file" 2>/dev/null'; then ret=error:$RANDOM return 1 fi ble/string#split-words size "$size" ble/file#hash/.impl } if ble/bin#freeze-utility-path -n git; then function ble/file#hash/.impl { ble/util/assign ret 'ble/bin/git hash-object "$file"' ret="size:$size;hash:$ret" } elif ble/bin#freeze-utility-path -n openssl; then function ble/file#hash/.impl { ble/util/assign-words ret 'ble/bin/openssl sha1 -r "$file"' ret="size:$size;sha1:$ret" } elif ble/bin#freeze-utility-path -n sha1sum; then function ble/file#hash/.impl { ble/util/assign-words ret 'ble/bin/sha1sum "$file"' ret="size:$size;sha1:$ret" } elif ble/bin#freeze-utility-path -n sha1; then function ble/file#hash/.impl { ble/util/assign-words ret 'ble/bin/sha1 -r "$file"' ret="size:$size;sha1:$ret" } elif ble/bin#freeze-utility-path -n md5sum; then function ble/file#hash/.impl { ble/util/assign-words ret 'ble/bin/md5sum "$file"' ret="size:$size;md5:$ret" } elif ble/bin#freeze-utility-path -n md5; then function ble/file#hash/.impl { ble/util/assign-words ret 'ble/bin/md5 -r "$file"' ret="size:$size;md5:$ret" } elif ble/bin#freeze-utility-path -n cksum; then function ble/file#hash/.impl { ble/util/assign-words ret 'ble/bin/cksum "$file"' ret="size:$size;cksum:$ret" } else function ble/file#hash/.impl { ret="size:$size" } fi _ble_util_buffer=() function ble/util/buffer { _ble_util_buffer[${#_ble_util_buffer[@]}]=$1 } function ble/util/buffer.print { ble/util/buffer "$1"$'\n' } function ble/util/buffer.print-lines { local line for line; do ble/util/buffer "$line"$'\n' done } function ble/util/buffer.flush { IFS= builtin eval 'local text="${_ble_util_buffer[*]-}"' _ble_util_buffer=() [[ $text ]] || return 0 if [[ $_ble_term_state == internal ]]; then if [[ $_ble_term_cursor_hidden_current == hidden ]]; then text=$_ble_term_civis$text else text=$_ble_term_civis$text$_ble_term_rmcivis fi [[ $bleopt_term_synchronized_update_mode == on ]] && text=$'\e[?2026h'$text$'\e[?2026l' fi ble/util/put "$text" >&"$_ble_util_fd_tui_stderr" } function ble/util/buffer.clear { _ble_util_buffer=() } function ble/dirty-range#load { local prefix= if [[ $1 == --prefix=* ]]; then prefix=${1#--prefix=} ((beg=${prefix}beg, end=${prefix}end, end0=${prefix}end0)) fi } function ble/dirty-range#clear { local prefix= if [[ $1 == --prefix=* ]]; then prefix=${1#--prefix=} shift fi ((${prefix}beg=-1, ${prefix}end=-1, ${prefix}end0=-1)) } function ble/dirty-range#update { local prefix= if [[ $1 == --prefix=* ]]; then prefix=${1#--prefix=} shift [[ $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)) local delta if ((begA<0)); then ((beg=begB, end=endB, end0=endB0)) else ((beg=begA0?(end+=delta):(end0-=delta))) fi fi if [[ $prefix ]]; then ((${prefix}beg=beg, ${prefix}end=end, ${prefix}end0=end0)) fi } function ble/urange#clear { local prefix= if [[ $1 == --prefix=* ]]; then prefix=${1#*=}; shift fi ((${prefix}umin=-1,${prefix}umax=-1)) } function ble/urange#update { local prefix= if [[ $1 == --prefix=* ]]; then prefix=${1#*=}; shift fi local min=$1 max=$2 ((0<=min&&min=0)) || return 1 [[ $shift ]] || ((shift=dend-dend0)) ((${prefix}umin>=0&&( dbeg<=${prefix}umin&&(${prefix}umin<=dend0?(${prefix}umin=dend):(${prefix}umin+=shift)), dbeg<=${prefix}umax&&(${prefix}umax<=dend0?(${prefix}umax=dbeg):(${prefix}umax+=shift))), ${prefix}umin<${prefix}umax||( ${prefix}umin=-1, ${prefix}umax=-1))) } _ble_util_joblist_jobs= _ble_util_joblist_list=() _ble_util_joblist_events=() function ble/util/joblist { local opts=$1 jobs0 ble/util/assign jobs0 'jobs' ((_ble_bash>=50300)) && jobs >/dev/null if [[ $jobs0 == "$_ble_util_joblist_jobs" ]]; then joblist=("${_ble_util_joblist_list[@]}") return 0 elif [[ ! $jobs0 ]]; then _ble_util_joblist_jobs= _ble_util_joblist_list=() joblist=() return 0 fi local lines list ijob ble/string#split lines $'\n' "$jobs0" if ((${#lines[@]})); then ble/util/joblist.split list "${lines[@]}" else list=() fi if [[ $jobs0 != "$_ble_util_joblist_jobs" ]]; then for ijob in "${!list[@]}"; do if [[ ${_ble_util_joblist_list[ijob]} && ${list[ijob]#'['*']'[-+ ]} != "${_ble_util_joblist_list[ijob]#'['*']'[-+ ]}" ]]; then ble/array#push _ble_util_joblist_events "${list[ijob]}" list[ijob]= fi done fi ble/util/assign _ble_util_joblist_jobs 'jobs' _ble_util_joblist_list=() if [[ $_ble_util_joblist_jobs != "$jobs0" ]]; then ble/string#split lines $'\n' "$_ble_util_joblist_jobs" ble/util/joblist.split _ble_util_joblist_list "${lines[@]}" if [[ :$opts: != *:ignore-volatile-jobs:* ]]; then for ijob in "${!list[@]}"; do local job0=${list[ijob]} if [[ $job0 && ! ${_ble_util_joblist_list[ijob]} ]]; then ble/array#push _ble_util_joblist_events "$job0" fi done fi else for ijob in "${!list[@]}"; do [[ ${list[ijob]} ]] && _ble_util_joblist_list[ijob]=${list[ijob]} done fi joblist=("${_ble_util_joblist_list[@]}") } 2>/dev/null function ble/util/joblist/__suppress__ { return 0; } function ble/util/joblist.split { local arr=$1; shift local line ijob= rex_ijob='^\[([0-9]+)\]' local -a out=() for line; do [[ $line =~ $rex_ijob ]] && ijob=${BASH_REMATCH[1]} [[ $ijob ]] && out[ijob]=${out[ijob]:+${out[ijob]}$_ble_term_nl}$line done for ijob in "${!out[@]}"; do [[ ${out[ijob]} != *'ble/util/joblist/__suppress__'* ]] && builtin eval -- "$arr[ijob]=\${out[ijob]}" done } function ble/util/joblist.check { local joblist ble/util/joblist "$@" } function ble/util/joblist.has-events { local joblist ble/util/joblist ((${#_ble_util_joblist_events[@]})) } function ble/util/joblist.flush { local joblist ble/util/joblist ((${#_ble_util_joblist_events[@]})) || return 1 printf '%s\n' "${_ble_util_joblist_events[@]}" _ble_util_joblist_events=() } function ble/util/joblist.bflush { local joblist out ble/util/joblist ((${#_ble_util_joblist_events[@]})) || return 1 ble/util/sprintf out '%s\n' "${_ble_util_joblist_events[@]}" ble/util/buffer "$out" _ble_util_joblist_events=() } function ble/util/joblist.clear { _ble_util_joblist_jobs= _ble_util_joblist_list=() } function ble/util/save-editing-mode { if [[ -o emacs ]]; then builtin eval "$1=emacs" elif [[ -o vi ]]; then builtin eval "$1=vi" else builtin eval "$1=none" fi } function ble/util/restore-editing-mode { case ${!1} in (emacs) set -o emacs ;; (vi) set -o vi ;; (none) set +o emacs ;; esac } function ble/util/reset-keymap-of-editing-mode { if [[ -o emacs ]]; then set -o emacs elif [[ -o vi ]]; then set -o vi fi } function ble/util/rlvar#load { ble/util/assign _ble_local_rlvars 'builtin bind -v 2>/dev/null' _ble_local_rlvars=$'\n'$_ble_local_rlvars } function ble/util/rlvar#has { if [[ ! ${_ble_local_rlvars:-} ]]; then local _ble_local_rlvars ble/util/rlvar#load fi [[ $_ble_local_rlvars == *$'\n'"set $1 "* ]] } function ble/util/rlvar#test { if [[ ! ${_ble_local_rlvars:-} ]]; then local _ble_local_rlvars ble/util/rlvar#load fi if [[ $_ble_local_rlvars == *$'\n'"set $1 on"* ]]; then return 0 elif [[ $_ble_local_rlvars == *$'\n'"set $1 off"* ]]; then return 1 elif (($#>=2)); then (($2)) return "$?" else return 2 fi } function ble/util/rlvar#read { [[ ${2+set} ]] && ret=$2 if [[ ! ${_ble_local_rlvars:-} ]]; then local _ble_local_rlvars ble/util/rlvar#load fi local rhs=${_ble_local_rlvars#*$'\n'"set $1 "} [[ $rhs != "$_ble_local_rlvars" ]] && ret=${rhs%%$'\n'*} } function ble/util/rlvar#bind-bleopt { local name=$1 bleopt=$2 opts=$3 if [[ ! ${_ble_local_rlvars:-} ]]; then local _ble_local_rlvars ble/util/rlvar#load fi if ble/util/rlvar#has "$name"; then if [[ :$_ble_base_arguments_opts: == *:keep-rlvars:* ]]; then local ret; ble/util/rlvar#read "$name" [[ :$opts: == *:bool:* && $ret == off ]] && ret= bleopt "$bleopt=$ret" else local var=bleopt_$bleopt val=off [[ ${!var:-} ]] && val=on builtin bind "set $name $val" 2>/dev/null fi local proc_original= if ble/is-function "bleopt/check:$bleopt"; then ble/function#push "bleopt/check:$bleopt" proc_original='ble/function#push/call-top "$@" || return "$?"' fi local proc_set='builtin bind "set '$name' $value" 2>/dev/null' if [[ :$opts: == *:bool:* ]]; then proc_set=' if [[ $value ]]; then builtin bind "set '$name' on" 2>/dev/null else builtin bind "set '$name' off" 2>/dev/null fi' fi builtin eval -- " function bleopt/check:$bleopt { $proc_original $proc_set return 0 }" fi local proc_bleopt='bleopt '$bleopt'="$1"' if [[ :$opts: == *:bool:* ]]; then proc_bleopt=' local value; ble/string#split-words value "$1" if [[ ${value-} == 1 || ${value-} == [Oo][Nn] ]]; then bleopt '$bleopt'="$value" else bleopt '$bleopt'= fi' fi builtin eval -- " function ble/builtin/bind/set:$name { $proc_bleopt return 0 }" } function ble/util/invoke-hook { local -a hooks; builtin eval "hooks=(\"\${$1[@]}\")" local hook ext=0 for hook in "${hooks[@]}"; do builtin eval -- "$hook \"\${@:2}\"" || ext=$?; done return "$ext" } function ble/util/.read-arguments-for-no-option-command { local commandname=$1; shift flags= args=() local flag_literal= while (($#)); do local arg=$1; shift if [[ ! $flag_literal ]]; then case $arg in (--) flag_literal=1 ;; (--help) flags=h$flags ;; (-*) ble/util/print "$commandname: unrecognized option '$arg'" >&2 flags=e$flags ;; (*) ble/array#push args "$arg" ;; esac else ble/array#push args "$arg" fi done } function ble/util/autoload { local file=$1; shift ble/util/import/is-loaded "$file" && return 0 local q=\' Q="'\''" funcname for funcname; do builtin eval "function $funcname { builtin unset -f $funcname ble-import '${file//$q/$Q}' && $funcname \"\$@\" }" done } function ble/util/autoload/.print-usage { ble/util/print 'usage: ble-autoload SCRIPTFILE FUNCTION...' ble/util/print ' Setup delayed loading of functions defined in the specified script file.' } >&2 function ble/util/autoload/.read-arguments { file= flags= functions=() local args ble/util/.read-arguments-for-no-option-command ble-autoload "$@" local arg index=0 for arg in "${args[@]}"; do if [[ ! $arg ]]; then if ((index==0)); then ble/util/print 'ble-autoload: the script filename should not be empty.' >&2 else ble/util/print 'ble-autoload: function names should not be empty.' >&2 fi flags=e$flags fi ((index++)) done [[ $flags == *h* ]] && return 0 if ((${#args[*]}==0)); then ble/util/print 'ble-autoload: script filename is not specified.' >&2 flags=e$flags elif ((${#args[*]}==1)); then ble/util/print 'ble-autoload: function names are not specified.' >&2 flags=e$flags fi file=${args[0]} functions=("${args[@]:1}") } function ble-autoload { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" local file flags local -a functions=() ble/util/autoload/.read-arguments "$@" if [[ $flags == *[eh]* ]]; then [[ $flags == *e* ]] && builtin printf '\n' ble/util/autoload/.print-usage local ext=0 [[ $flags == *e* ]] && ext=2 builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_leave" return "$ext" fi ble/util/autoload "$file" "${functions[@]}" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" } _ble_util_import_files=() bleopt/declare -n import_path "${XDG_DATA_HOME:-$HOME/.local/share}/blesh/local" function ble/util/import/search/.check-directory { local name=$1 dir=${2%/} [[ -d ${dir:=/} ]] || return 1 if [[ $name == lib/* ]]; then [[ $dir == */lib ]] || return 1 dir=${dir%/lib} elif [[ $name == contrib/* ]]; then [[ $dir == */contrib ]] || return 1 dir=${dir%/contrib} fi if [[ -f $dir/$name ]]; then ret=$dir/$name return 0 elif [[ $name != *.bash && -f $dir/$name.bash ]]; then ret=$dir/$name.bash return 0 elif [[ $name != *.sh && -f $dir/$name.sh ]]; then ret=$dir/$name.sh return 0 fi return 1 } function ble/util/import/search { ret=$1 if [[ $ret != /* && $ret != ./* && $ret != ../* ]]; then local -a dirs=() if [[ $bleopt_import_path ]]; then local tmp; ble/string#split tmp : "$bleopt_import_path" ble/array#push dirs "${tmp[@]}" fi ble/array#push dirs "$_ble_base"{,/contrib,/lib} "${_ble_util_set_declare[@]//NAME/checked}" # WA #D1570 checked local path for path in "${dirs[@]}"; do ble/set#contains checked "$path" && continue ble/set#add checked "$path" ble/util/import/search/.check-directory "$ret" "$path" && break done fi [[ -e $ret && ! -d $ret ]] } function ble/util/import/encode-filename { ret=$1 local chars=%$'\t\n !"$&\'();<>\\^`|' # if [[ $ret == *["$chars"]* ]]; then local i n=${#chars} reps a b reps=(%{25,08,0A,2{0..2},24,2{6..9},3B,3C,3E,5C,5E,60,7C}) for ((i=0;i&2 flags=E$flags fi ;; (*) ble/util/print "ble-import: unrecognized option '$arg'" >&2 flags=E$flags ;; esac continue ;; (-?*) local i c for ((i=1;i<${#arg};i++)); do c=${arg:i:1} case $c in ([dfq]) flags=$c$flags ;; (C) if ((i+1<${#arg})); then ble/array#push callbacks "${arg:i+1}" elif (($#)); then ble/array#push callbacks "$1" shift else ble/util/print "ble-import: missing optarg for '-C'" >&2 flags=E$flags fi break ;; (*) ble/util/print "ble-import: unrecognized option '-$c'" >&2 flags=E$flags ;; esac done continue ;; esac fi local ret if ! ble/util/import/search "$arg"; then ble/array#push not_found "$arg" continue fi; local file=$ret ble/array#push files "$file" done if ((${#not_found[@]})); then flags=N$flags if [[ $flags != *[fq]* ]]; then local file for file in "${not_found[@]}"; do ble/util/print "ble-import: file '$file' not found" >&2 done flags=E$flags fi fi return 0 } function ble/util/import { local files file ext=0 ret enc files=("$@") set -- # Note #D1859: source によって引数が継承されるのを防ぐ for file in "${files[@]}"; do ble/util/import/encode-filename "$file"; enc=$ret local guard=ble/util/import/guard:$enc ble/is-function "$guard" && return 0 [[ -e $file ]] || return 1 source "$file" || { ext=$?; continue; } builtin eval "function $guard { return 0; }" ble/array#push _ble_util_import_files "$file" local onload=ble/util/import/onload:$enc ble/function#try "$onload" ble/util/invoke-hook done return "$ext" } function ble/util/import/option:query { if [[ $flags == *N* ]]; then return 127 elif ((${#files[@]})); then local file for file in "${files[@]}"; do ble/util/import/is-loaded "$file" || return 1 done return 0 else ble/util/print-lines "${_ble_util_import_files[@]}" return "$?" fi } function ble/util/import/.dispatch { local files flags callbacks ble/util/import/.read-arguments "$@" if [[ $flags == *[Eh]* ]]; then [[ $flags == *E* ]] && ble/util/print ble/util/print-lines \ 'usage: ble-import [-dfq|--delay|--force|--query]' \ ' [-C CALLBACK|--callback=CALLBACK]+ [--] [SCRIPTFILE...]' \ 'usage: ble-import --help' \ '' \ ' Search and source script files that have not yet been loaded. When none of' \ ' -q, --query, -d, --delay, -C, --callback is specified, SCRIPTFILEs are' \ ' sourced.' \ '' \ ' OPTIONS' \ ' --help Show this help.' \ ' -d, --delay Register SCRIPTFILEs for later loading in idle time.' \ ' -f, --force Ignore non-existent files without errors.' \ ' -q, --query When SCRIPTFILEs are specified, test if all of these files' \ ' are already loaded. Without SCRIPTFILEs, print the list of' \ ' already imported files.' \ ' -C, --callback=CALLBACK' \ ' Specify a command that will be evaluated when all of' \ ' SCRIPTFILEs are loaded. If all of SCRIPTFILEs are already' \ ' loaded, the callback is immediately evaluated.' \ '' \ >&2 [[ $flags == *E* ]] && return 2 return 0 fi if [[ $flags == *q* ]]; then ble/util/import/option:query return "$?" fi if ((!${#files[@]})); then [[ $flags == *f* ]] && return 0 ble/util/print 'ble-import: files are not specified.' >&2 return 2 fi if ((${#callbacks[@]})); then local file i q=\' Q="'\''" for file in "${files[@]}"; do ble/util/import/is-loaded "$file" && continue for i in "${!callbacks[@]}"; do callbacks[i]="ble/util/import/eval-after-load '${file//$q/$Q}' '${callbacks[i]//$q/$Q}'" done done local cb for cb in "${callbacks[@]}"; do builtin eval -- "$cb" done fi if [[ $flags == *d* ]] && ble/is-function ble/util/idle.push; then local ret ble/string#quote-command ble/util/import "${files[@]}" ble/util/idle.push "$ret" return 0 fi ((${#callbacks[@]})) || ble/util/import "${files[@]}" } function ble-import { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" ble/util/import/.dispatch "$@" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" } _ble_util_import_onload_count=0 function ble/util/import/eval-after-load { local ret file if ! ble/util/import/search "$1"; then ble/util/print "ble-import: file '$1' not found." >&2 return 2 fi; file=$ret ble/util/import/encode-filename "$file"; local enc=$ret local guard=ble/util/import/guard:$enc if ble/is-function "$guard"; then builtin eval -- "$2" else local onload=ble/util/import/onload:$enc if ! ble/is-function "$onload"; then local q=\' Q="'\''" list=_ble_util_import_onload_$((_ble_util_import_onload_count++)) builtin eval -- "$list=(); function $onload { \"\$1\" $list \"\${@:2}\"; }" fi "$onload" ble/array#push "$2" fi } _ble_util_stackdump_title=stackdump _ble_util_stackdump_start= function ble/util/stackdump { ((bleopt_internal_stackdump_enabled)) || return 1 local message=$1 nl=$'\n' IFS=$_ble_term_IFS message="$_ble_term_sgr0$_ble_util_stackdump_title: $message$nl" local extdebug= iarg=$BASH_ARGC args= shopt -q extdebug 2>/dev/null && extdebug=1 local i i0=${_ble_util_stackdump_start:-1} iN=${#FUNCNAME[*]} for ((i=i0;i&2 [[ $flags == *e* ]] && ext=2 return 1 fi return 0 } function ble-stackdump { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" local args ext if ble/util/stackdump/.read-arguments "$@"; then local _ble_util_stackdump_start=2 local IFS=$_ble_term_IFS ble/util/stackdump "${args[*]}" ext=$? fi builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_leave" return "$ext" } function ble/util/assert { local expr=$1 message=$2 if ! builtin eval -- "$expr"; then shift local _ble_util_stackdump_title='assertion failure' local _ble_util_stackdump_start=3 ble/util/stackdump "$expr$_ble_term_nl$message" >&2 return 1 else return 0 fi } function ble/util/assert/.read-arguments { ext=0 local flags ble/util/.read-arguments-for-no-option-command ble-assert "$@" if [[ $flags != *h* ]]; then if ((${#args[@]}==0)); then ble/util/print 'ble-assert: command is not specified.' >&2 flags=e$flags fi fi if [[ $flags == *[eh]* ]]; then [[ $flags == *e* ]] && ble/util/print { ble/util/print 'usage: ble-assert command [message]' ble/util/print ' Evaluate command and print stackdump on fail.' } >&2 [[ $flags == *e* ]] && ext=2 return 1 fi return 0 } function ble-assert { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" local args ext if ble/util/assert/.read-arguments "$@"; then local IFS=$_ble_term_IFS ble/util/assert "${args[0]}" "${args[*]:1}" ext=$? fi builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_leave" return "$ext" } bleopt/declare -v debug_idle '' _ble_util_clock_base= _ble_util_clock_reso= _ble_util_clock_type= function ble/util/clock/.initialize { local LC_ALL= LC_NUMERIC=C if ((_ble_bash>=50000)) && { local now=$EPOCHREALTIME [[ $now == *.???* && $now != $EPOCHREALTIME ]]; }; then builtin readonly EPOCHREALTIME _ble_util_clock_base=$((10#0${now%.*})) _ble_util_clock_reso=1 _ble_util_clock_type=EPOCHREALTIME function ble/util/clock { local LC_ALL= LC_NUMERIC=C local now=$EPOCHREALTIME local integral=$((10#0${now%%.*}-_ble_util_clock_base)) local mantissa=${now#*.}000; mantissa=${mantissa::3} ((ret=integral*1000+10#0$mantissa)) } ble/function#suppress-stderr ble/util/clock # locale elif [[ -r /proc/uptime ]] && { local uptime ble/util/readfile uptime /proc/uptime ble/string#split-words uptime "$uptime" [[ $uptime == *.* ]]; }; then _ble_util_clock_base=$((10#0${uptime%.*})) _ble_util_clock_reso=10 _ble_util_clock_type=uptime function ble/util/clock { local now ble/util/readfile now /proc/uptime ble/string#split-words now "$now" local integral=$((10#0${now%%.*}-_ble_util_clock_base)) local fraction=${now#*.}000; fraction=${fraction::3} ((ret=integral*1000+10#0$fraction)) } elif ((_ble_bash>=40200)); then local ret ble/util/time _ble_util_clock_base=$ret _ble_util_clock_reso=1000 _ble_util_clock_type=printf function ble/util/clock { ble/util/time ((ret=(ret-_ble_util_clock_base)*1000)) } elif [[ $SECONDS && ! ${SECONDS//[0-9]} ]]; then builtin readonly SECONDS _ble_util_clock_base=$SECONDS _ble_util_clock_reso=1000 _ble_util_clock_type=SECONDS function ble/util/clock { local now=$SECONDS ((ret=(now-_ble_util_clock_base)*1000)) } else local ret ble/util/time _ble_util_clock_base=$ret _ble_util_clock_reso=1000 _ble_util_clock_type=date function ble/util/clock { ble/util/time ((ret=(ret-_ble_util_clock_base)*1000)) } fi } ble/util/clock/.initialize 2>/dev/null if ((_ble_bash>=40000)); then function ble/util/idle/IS_IDLE { ! ble/util/is-stdin-ready; } _ble_util_idle_sclock=0 function ble/util/idle/.sleep { local msec=$1 ((msec<=0)) && return 0 ble/util/msleep "$msec" ((_ble_util_idle_sclock+=msec)) } function ble/util/idle.clock/.initialize { function ble/util/idle.clock/.initialize { return 0; } function ble/util/idle.clock/.restart { return 0; } if [[ ! $_ble_util_clock_type || $_ble_util_clock_type == date ]]; then function ble/util/idle.clock { ret=$_ble_util_idle_sclock } elif ((_ble_util_clock_reso<=100)); then function ble/util/idle.clock { ble/util/clock } else _ble_util_idle_aclock_shift= _ble_util_idle_aclock_tick_rclock= _ble_util_idle_aclock_tick_sclock= function ble/util/idle.clock/.restart { _ble_util_idle_aclock_shift= _ble_util_idle_aclock_tick_rclock= _ble_util_idle_aclock_tick_sclock= } function ble/util/idle/.adjusted-clock { local resolution=$_ble_util_clock_reso local sclock=$_ble_util_idle_sclock local ret; ble/util/clock; local rclock=$((ret/resolution*resolution)) if [[ $_ble_util_idle_aclock_tick_rclock != "$rclock" ]]; then if [[ $_ble_util_idle_aclock_tick_rclock && ! $_ble_util_idle_aclock_shift ]]; then local delta=$((sclock-_ble_util_idle_aclock_tick_sclock)) ((_ble_util_idle_aclock_shift=delta50000)) && [[ $_ble_util_msleep_builtin_available ]] && interval=20 bleopt/declare -v idle_interval "$interval" } ble/util/idle/.initialize-options _ble_util_idle_task=() _ble_util_idle_lasttask= _ble_util_idle_SEP=$_ble_term_FS function ble/util/idle.do { local IFS=$_ble_term_IFS ble/util/idle/IS_IDLE || return 1 ((${#_ble_util_idle_task[@]}==0)) && return 1 ble/util/buffer.flush local ret ble/util/idle.clock/.initialize ble/util/idle.clock/.restart ble/util/idle.clock 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 _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 _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.do/.check-clock "$_ble_idle_status" && _ble_idle_to_process=1 ;; (W) ble/util/idle.do/.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[_ble_idle_key]' esac 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" ((_ble_idle_after_task++)) elif [[ $_ble_idle_status == [FEPC]* ]]; then _ble_idle_waiting=1 fi done _ble_idle_is_first= ble/util/idle.do/.sleep-until-next; local ext=$? ((ext==148)) && break [[ $_ble_idle_next_itime$_ble_idle_next_time$_ble_idle_running$_ble_idle_waiting ]] || break done [[ $_ble_idle_info_shown ]] && ble/edit/info/immediate-default ble/util/idle.do/.do-after-task [[ $_ble_idle_processed ]] } function ble/util/idle.do/.do-after-task { if ((_ble_idle_after_task)); then blehook/invoke idle_after_task _ble_idle_after_task=0 fi } function ble/util/idle.do/.call-task { local _ble_local_command=$1 local ble_util_idle_status= 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 -- "$_ble_local_command"; local ext=$? if ((ext==148)); then _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[_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=_ble_idle_next_itime else local next=_ble_idle_next_time fi if [[ ! ${!next} ]] || ((scheduled_time0)) do local ble_util_idle_elapsed=$((_ble_util_idle_sclock-_ble_idle_sclock_start)) ((sleep_amount>50)) && ble/util/idle.do/.do-after-task local interval=$((bleopt_idle_interval)) if [[ ! $sleep_amount ]] || ((intervalret)) || return 1 fi ble_util_idle_status=S$1 } function ble/util/idle.isleep-until { [[ ${ble_util_idle_status+set} ]] || return 2 if [[ :$2: == *:checked:* ]]; then (($1>_ble_util_idle_sclock)) || return 1 fi ble_util_idle_status=W$1 } function ble/util/idle.wait-user-input { [[ ${ble_util_idle_status+set} ]] || return 2 ble_util_idle_status=I } function ble/util/idle.wait-process { [[ ${ble_util_idle_status+set} ]] || return 2 ble_util_idle_status=P$1 } function ble/util/idle.wait-file-content { [[ ${ble_util_idle_status+set} ]] || return 2 ble_util_idle_status=F$1 } function ble/util/idle.wait-filename { [[ ${ble_util_idle_status+set} ]] || return 2 ble_util_idle_status=E$1 } function ble/util/idle.wait-condition { [[ ${ble_util_idle_status+set} ]] || return 2 ble_util_idle_status=C$1 } function ble/util/idle.continue { [[ ${ble_util_idle_status+set} ]] || return 2 ble_util_idle_status=R } function ble/util/idle/.delare-external-modifier { local name=$1 builtin eval -- 'function ble/util/idle#'$name' { local index=$1 [[ ${_ble_util_idle_task[index]+set} ]] || return 2 local ble_util_idle_status=${_ble_util_idle_task[index]%%"$_ble_util_idle_SEP"*} local ble_util_idle_command=${_ble_util_idle_task[index]#*"$_ble_util_idle_SEP"} ble/util/idle.'$name' "${@:2}" _ble_util_idle_task[index]=$ble_util_idle_status$_ble_util_idle_SEP$ble_util_idle_command }' } ble/util/idle/.delare-external-modifier suspend ble/util/idle/.delare-external-modifier sleep ble/util/idle/.delare-external-modifier isleep ble/util/idle.push-background 'ble/util/msleep/calibrate' else function ble/util/idle.do { false; } fi _ble_util_fiberchain=() _ble_util_fiberchain_prefix= function ble/util/fiberchain#initialize { _ble_util_fiberchain=() _ble_util_fiberchain_prefix=$1 } function ble/util/fiberchain#resume/.core { _ble_util_fiberchain=() local fib_clock=0 local fib_ntask=$# while (($#)); do ((fib_ntask--)) local fiber=${1%%:*} fib_suspend= fib_kill= local argv; ble/string#split-words argv "$fiber" [[ $1 == *:* ]] && fib_suspend=${1#*:} "$_ble_util_fiberchain_prefix/$argv.fib" "${argv[@]:1}" if [[ $fib_kill ]]; then break elif [[ $fib_suspend ]]; then _ble_util_fiberchain=("$fiber:$fib_suspend" "${@:2}") return 148 fi shift done } function ble/util/fiberchain#resume { ble/util/fiberchain#resume/.core "${_ble_util_fiberchain[@]}" } function ble/util/fiberchain#push { ble/array#push _ble_util_fiberchain "$@" } function ble/util/fiberchain#clear { _ble_util_fiberchain=() } bleopt/declare -v vbell_default_message ' Wuff, -- Wuff!! ' bleopt/declare -v vbell_duration 2000 bleopt/declare -n vbell_align right function ble/term:cygwin/initialize.hook { printf '\eM\e[B' >&"$_ble_util_fd_tui_stderr" _ble_term_ri=$'\e[A' function ble/canvas/put-dl.draw { local value=${1-1} i ((value)) || return 1 DRAW_BUFF[${#DRAW_BUFF[*]}]=$'\e[2K' if ((value>1)); then local ret ble/string#repeat $'\e[B\e[2K' "$((value-1))"; local a=$ret DRAW_BUFF[${#DRAW_BUFF[*]}]=$ret$'\e['$((value-1))'A' fi DRAW_BUFF[${#DRAW_BUFF[*]}]=${_ble_term_dl//'%d'/$value} } } function ble/term/DA2R.hook { blehook term_DA2R-=ble/term/DA2R.hook case $_ble_term_TERM in (contra:*) _ble_term_cuu=$'\e[%dk' _ble_term_cud=$'\e[%de' _ble_term_cuf=$'\e[%da' _ble_term_cub=$'\e[%dj' _ble_term_cup=$'\e[%l;%cf' ;; (cygwin:*) ble/term:cygwin/initialize.hook ;; esac } function ble/term/.initialize { if [[ -s $_ble_base_cache/term.$TERM && $_ble_base_cache/term.$TERM -nt $_ble_base/lib/init-term.sh ]]; then source "$_ble_base_cache/term.$TERM" else source "$_ble_base/lib/init-term.sh" fi ble/string#reserve-prototype "$_ble_term_it" blehook term_DA2R!=ble/term/DA2R.hook } ble/term/.initialize function ble/term/put { BUFF[${#BUFF[@]}]=$1 } function ble/term/cup { local x=$1 y=$2 esc=$_ble_term_cup esc=${esc//'%x'/$x} esc=${esc//'%y'/$y} esc=${esc//'%c'/$((x+1))} esc=${esc//'%l'/$((y+1))} BUFF[${#BUFF[@]}]=$esc } function ble/term/flush { IFS= builtin eval 'ble/util/put "${BUFF[*]}"' BUFF=() } function ble/term/audible-bell { ble/util/put '' >&2 } _ble_term_visible_bell_prev=() _ble_term_visible_bell_ftime=$_ble_base_run/$$.visible-bell.time _ble_term_visible_bell_show='%message%' _ble_term_visible_bell_clear= function ble/term/visible-bell:term/init { if [[ ! $_ble_term_visible_bell_clear ]]; then local -a BUFF=() ble/term/put "$_ble_term_ri_or_cuu1$_ble_term_sc$_ble_term_sgr0" ble/term/cup 0 0 ble/term/put "$_ble_term_el%message%$_ble_term_sgr0$_ble_term_rc${_ble_term_cud//'%d'/1}" IFS= builtin eval '_ble_term_visible_bell_show="${BUFF[*]}"' BUFF=() ble/term/put "$_ble_term_sc$_ble_term_sgr0" ble/term/cup 0 0 ble/term/put "$_ble_term_el2$_ble_term_rc" IFS= builtin eval '_ble_term_visible_bell_clear="${BUFF[*]}"' fi local cols=${COLUMNS:-80} ((_ble_term_xenl||cols--)) local message=${1::cols} _ble_term_visible_bell_prev=(term "$message") } function ble/term/visible-bell:term/show { local sgr=$1 message=${_ble_term_visible_bell_prev[1]} message=${_ble_term_visible_bell_show//'%message%'/"$sgr$message"} ble/util/put "$message" >&2 } function ble/term/visible-bell:term/update { ble/term/visible-bell:term/show "$@" } function ble/term/visible-bell:term/clear { local sgr=$1 ble/util/put "$_ble_term_visible_bell_clear" >&2 } function ble/term/visible-bell:canvas/init { local message=$1 local lines=1 cols=${COLUMNS:-80} ((_ble_term_xenl||cols--)) local x= y= local ret sgr0= sgr1= ble/canvas/trace-text "$message" nonewline:external-sgr message=$ret local x0=$((COLUMNS-1-x)) y0=0 ((x0<0)) && x0=0 case :$bleopt_vbell_align: in (*:left:*) x0=0 ;; (*:center:*) ((x0/=2)) ;; esac _ble_term_visible_bell_prev=(canvas "$message" "$x0" "$y0" "$x" "$y") } function ble/term/visible-bell:canvas/show { local sgr=$1 opts=$2 local message=${_ble_term_visible_bell_prev[1]} local x0=${_ble_term_visible_bell_prev[2]} local y0=${_ble_term_visible_bell_prev[3]} local x=${_ble_term_visible_bell_prev[4]} local y=${_ble_term_visible_bell_prev[5]} local -a DRAW_BUFF=() [[ :$opts: != *:update:* && $_ble_attached ]] && # WA #D1495 [[ $_ble_term_ri || :$opts: != *:erased:* && :$opts: != *:update:* ]] && ble/canvas/panel/ensure-tmargin.draw if [[ $_ble_term_rc ]]; then local ret= [[ :$opts: != *:update:* && $_ble_attached ]] && ble/canvas/panel/save-position goto-top-dock # WA #D1495 ble/canvas/put.draw "$_ble_term_ri_or_cuu1$_ble_term_sc$_ble_term_sgr0" ble/canvas/put-cup.draw "$((y0+1))" "$((x0+1))" ble/canvas/put.draw "$sgr$message$_ble_term_sgr0" ble/canvas/put.draw "$_ble_term_rc" ble/canvas/put-cud.draw 1 [[ :$opts: != *:update:* && $_ble_attached ]] && ble/canvas/panel/load-position.draw "$ret" # WA #D1495 else ble/canvas/put.draw "$_ble_term_ri_or_cuu1$_ble_term_sgr0" ble/canvas/put-hpa.draw "$((1+x0))" ble/canvas/put.draw "$sgr$message$_ble_term_sgr0" ble/canvas/put-cud.draw 1 ble/canvas/put-hpa.draw "$((1+_ble_canvas_x))" fi ble/canvas/bflush.draw ble/util/buffer.flush } function ble/term/visible-bell:canvas/update { ble/term/visible-bell:canvas/show "$@" } function ble/term/visible-bell:canvas/clear { local sgr=$1 local x0=${_ble_term_visible_bell_prev[2]} local y0=${_ble_term_visible_bell_prev[3]} local x=${_ble_term_visible_bell_prev[4]} local y=${_ble_term_visible_bell_prev[5]} local -a DRAW_BUFF=() if [[ $_ble_term_rc ]]; then local ret= ble/canvas/put.draw "$_ble_term_sc$_ble_term_sgr0" ble/canvas/put-cup.draw "$((y0+1))" "$((x0+1))" ble/canvas/put.draw "$sgr" ble/canvas/put-spaces.draw "$x" ble/canvas/put.draw "$_ble_term_sgr0$_ble_term_rc" else : # 親プロセスの _ble_canvas_x が分からないので座標がずれる fi ble/canvas/flush.draw >&2 } function ble/term/visible-bell/defface.hook { ble/color/defface vbell reverse ble/color/defface vbell_flash reverse,fg=green ble/color/defface vbell_erase bg=252 } blehook color_defface_load+=ble/term/visible-bell/defface.hook function ble/term/visible-bell/.show { local bell_type=${_ble_term_visible_bell_prev[0]} ble/term/visible-bell:"$bell_type"/show "$@" } function ble/term/visible-bell/.update { local bell_type=${_ble_term_visible_bell_prev[0]} ble/term/visible-bell:"$bell_type"/update "$1" "$2:update" } function ble/term/visible-bell/.clear { local bell_type=${_ble_term_visible_bell_prev[0]} ble/term/visible-bell:"$bell_type"/clear "$@" >| "$_ble_term_visible_bell_ftime" } function ble/term/visible-bell/.erase-previous-visible-bell { local ret workers ble/util/eval-pathname-expansion '"$_ble_base_run/$$.visible-bell."*' canonical workers=("${ret[@]}") local workerfile for workerfile in "${workers[@]}"; do if [[ -s $workerfile && ! ( $workerfile -ot $_ble_term_visible_bell_ftime ) ]]; then ble/term/visible-bell/.clear "$sgr0" return 0 fi done return 1 } function ble/term/visible-bell/.create-workerfile { local i=0 while workerfile=$_ble_base_run/$$.visible-bell.$i [[ -s $workerfile ]] do ((i++)); done ble/util/print 1 >| "$workerfile" } function ble/term/visible-bell/.worker { ble/util/msleep 50 [[ $workerfile -ot $_ble_term_visible_bell_ftime ]] && return 0 >| "$workerfile" ble/term/visible-bell/.update "$sgr2" if [[ :$opts: == *:persistent:* ]]; then local dead_workerfile=$_ble_base_run/$$.visible-bell.Z ble/util/print 1 >| "$dead_workerfile" return 0 >| "$workerfile" fi local msec=$((bleopt_vbell_duration)) ble/util/msleep "$msec" [[ $workerfile -ot $_ble_term_visible_bell_ftime ]] && return 0 >| "$workerfile" ble/term/visible-bell/.clear "$sgr0" >| "$workerfile" } function ble/term/visible-bell { local message=$1 opts=$2 message=${message:-$bleopt_vbell_default_message} ((LINES==1)) && return 0 [[ :$bleopt_vbell_align: == *:panel:* ]] && ble/function#try ble/edit/visible-bell "$message" "$opts" && return 0 local sgr0=$_ble_term_sgr0 local sgr1=${_ble_term_setaf[2]}$_ble_term_rev local sgr2=$_ble_term_rev if ble/is-function ble/color/face2sgr; then local ret ble/color/face2sgr vbell_flash; sgr1=$ret ble/color/face2sgr vbell; sgr2=$ret ble/color/face2sgr vbell_erase; sgr0=$ret fi local show_opts= ble/term/visible-bell/.erase-previous-visible-bell && show_opts=erased if ble/is-function ble/canvas/trace-text; then ble/term/visible-bell:canvas/init "$message" else ble/term/visible-bell:term/init "$message" fi ble/term/visible-bell/.show "$sgr1" "$show_opts" local workerfile; ble/term/visible-bell/.create-workerfile ( ble/util/joblist/__suppress__; ble/term/visible-bell/.worker 1>/dev/null & ) } function ble/term/visible-bell/cancel-erasure { >| "$_ble_term_visible_bell_ftime" } function ble/term/visible-bell/erase { local sgr0=$_ble_term_sgr0 if ble/is-function ble/color/face2sgr; then local ret ble/color/face2sgr vbell_erase; sgr0=$ret fi ble/term/visible-bell/.erase-previous-visible-bell } [[ ${_ble_term_stty_save+set} ]] || _ble_term_stty_save= bleopt/declare -v term_stty_restore '' function bleopt/check:term_stty_restore { if [[ $value && ! $_ble_term_stty_save ]]; then ble/util/assign _ble_term_stty_save 'ble/bin/stty -g' fi return 0 } _ble_term_stty_state= _ble_term_stty_flags_enter=() _ble_term_stty_flags_leave=() ble/array#push _ble_term_stty_flags_enter intr undef quit undef susp undef ble/array#push _ble_term_stty_flags_leave intr '' quit '' susp '' function ble/term/stty/.initialize-flags { if [[ $TERM == minix ]]; then local stty; ble/util/assign stty 'stty -a' if [[ $stty == *' rprnt '* ]]; then ble/array#push _ble_term_stty_flags_enter rprnt undef ble/array#push _ble_term_stty_flags_leave rprnt '' elif [[ $stty == *' reprint '* ]]; then ble/array#push _ble_term_stty_flags_enter reprint undef ble/array#push _ble_term_stty_flags_leave reprint '' fi fi } ble/term/stty/.initialize-flags function ble/term/stty/initialize { if [[ $bleopt_term_stty_restore ]]; then [[ $_ble_term_stty_save ]] || ble/util/assign _ble_term_stty_save 'ble/bin/stty -g' fi ble/bin/stty -ixon -echo -nl -icrnl -icanon \ "${_ble_term_stty_flags_enter[@]}" _ble_term_stty_state=1 } function ble/term/stty/leave { [[ ! $_ble_term_stty_state ]] && return 0 _ble_term_stty_state= if [[ $bleopt_term_stty_restore && $_ble_term_stty_save ]]; then ble/bin/stty "$_ble_term_stty_save" else ble/bin/stty echo -nl icanon "${_ble_term_stty_flags_leave[@]}" fi } function ble/term/stty/enter { [[ $_ble_term_stty_state ]] && return 0 if [[ $bleopt_term_stty_restore ]]; then ble/term/stty/initialize else ble/bin/stty -echo -nl -icrnl -icanon "${_ble_term_stty_flags_enter[@]}" _ble_term_stty_state=1 fi } function ble/term/stty/finalize { ble/term/stty/leave _ble_term_stty_save= } function ble/term/stty/TRAPEXIT { if [[ $bleopt_term_stty_restore && $_ble_term_stty_save ]]; then ble/bin/stty "$_ble_term_stty_save" else ble/bin/stty echo -nl "${_ble_term_stty_flags_leave[@]}" fi } function ble/term/update-winsize { if ((_ble_bash<50200||50300<=_ble_bash)); then function ble/term/update-winsize { if shopt -q checkwinsize; then (:) else shopt -s checkwinsize (:) shopt -u checkwinsize fi 2>&"$_ble_util_fd_tui_stderr" } ble/term/update-winsize return 0 fi local ret if ble/bin#freeze-utility-path tput; then if ble/util/assign-words ret 'ble/bin/tput lines cols' 2>/dev/null && [[ ${#ret[@]} -eq 2 && ${ret[0]} =~ ^[0-9]+$ && ${ret[1]} =~ ^[0-9]+$ ]] then LINES=${ret[0]} COLUMNS=${ret[1]} function ble/term/update-winsize { local -x ret LINES= COLUMNS= ble/util/assign-words ret 'ble/bin/tput lines cols' 2>/dev/null ble/util/unlocal LINES COLUMNS [[ ${ret[0]} ]] && LINES=${ret[0]} [[ ${ret[1]} ]] && COLUMNS=${ret[1]} } return 0 elif ble/util/assign-words ret 'ble/bin/tput li co' 2>/dev/null && [[ ${#ret[@]} -eq 2 && ${ret[0]} =~ ^[0-9]+$ && ${ret[1]} =~ ^[0-9]+$ ]] then LINES=${ret[0]} COLUMNS=${ret[1]} function ble/term/update-winsize { local -x ret LINES= COLUMNS= ble/util/assign-words ret 'ble/bin/tput li co' 2>/dev/null ble/util/unlocal LINES COLUMNS [[ ${ret[0]} ]] && LINES=${ret[0]} [[ ${ret[1]} ]] && COLUMNS=${ret[1]} } return 0 fi fi if ble/util/assign-words ret 'ble/bin/stty size' 2>/dev/null && [[ ${#ret[@]} -eq 2 && ${ret[0]} =~ ^[0-9]+$ && ${ret[1]} =~ ^[0-9]+$ ]] then LINES=${ret[0]} COLUMNS=${ret[1]} function ble/term/update-winsize { local ret ble/util/assign-words ret 'ble/bin/stty size' 2>/dev/null [[ ${ret[0]} ]] && LINES=${ret[0]} [[ ${ret[1]} ]] && COLUMNS=${ret[1]} } return 0 fi if ble/bin#freeze-utility-path resize && ble/util/assign ret 'ble/bin/resize' && ble/string#match "$ret" 'COLUMNS=([0-9]+).*LINES=([0-9]+)' then LINES=${BASH_REMATCH[2]} COLUMNS=${BASH_REMATCH[1]} function ble/term/update-winsize { local ret ble/util/assign ret 'ble/bin/resize' 2>/dev/null ble/string#match ret 'COLUMNS=([0-9]+).*LINES=([0-9]+)' [[ ${BASH_REMATCH[2]} ]] && LINES=${BASH_REMATCH[2]} [[ ${BASH_REMATCH[1]} ]] && COLUMNS=${BASH_REMATCH[1]} } return 0 fi function ble/term/update-winsize { local ret script='LINES= COLUMNS=; (:); [[ $COLUMNS && $LINES ]] && builtin echo "$LINES $COLUMNS"' ble/util/assign-words ret '"$BASH" -O checkwinsize -c "$script"' 2>&"$_ble_util_fd_tui_stderr" [[ ${ret[0]} ]] && LINES=${ret[0]} [[ ${ret[1]} ]] && COLUMNS=${ret[1]} } ble/term/update-winsize return 0 } if ((50200<=_ble_bash&&_ble_bash<50300)); then function ble/term/update-winsize/.stty-enter.advice { local ret stderr test_command='ble/bin/stty -echo -nl -icrnl -icanon "${_ble_term_stty_flags_enter[@]}" size' if ble/util/assign stderr 'ble/util/assign-words ret "$test_command" 2>&1' && [[ ! $stderr ]] && ((${#ret[@]}==2)) && [[ ${ret[0]} =~ ^[0-9]+$ && ${ret[1]} =~ ^[0-9]+$ ]] then LINES=${ret[0]} COLUMNS=${ret[1]} function ble/term/stty/enter { [[ $_ble_term_stty_state ]] && return 0 local ret if [[ $bleopt_term_stty_restore ]]; then ble/term/stty/initialize ble/util/assign-words ret 'ble/bin/stty size' else ble/util/assign-words ret 'ble/bin/stty -echo -nl -icrnl -icanon "${_ble_term_stty_flags_enter[@]}" size' _ble_term_stty_state=1 fi [[ ${ret[0]} =~ ^[0-9]+$ ]] && LINES=${ret[0]} [[ ${ret[1]} =~ ^[0-9]+$ ]] && COLUMNS=${ret[1]} } else ble/term/update-winsize ble/function#advice before ble/term/stty/enter ble/term/update-winsize fi builtin unset -f "$FUNCNAME" } ble/function#advice before ble/term/stty/enter ble/term/update-winsize/.stty-enter.advice fi bleopt/declare -v term_cursor_external 0 _ble_term_cursor_current=unknown _ble_term_cursor_internal=0 _ble_term_cursor_hidden_current=unknown _ble_term_cursor_hidden_internal=reveal _ble_term_cursor_current=default function ble/term/cursor-state/.update { local state=$(($1)) [[ ${_ble_term_cursor_current/default/0} == "$state" ]] && return 0 if [[ ! $_ble_term_Ss ]]; then case $_ble_term_TERM in (mintty:*|xterm:*|RLogin:*|kitty:*|screen:*|tmux:*|contra:*|cygwin:*|wezterm:*|wt:*) local _ble_term_Ss=$'\e[@1 q' ;; esac fi local ret=${_ble_term_Ss//@1/"$state"} if [[ $ret ]]; then [[ $ret != $'\eP'*$'\e\\' ]] && ble/term/quote-passthrough "$ret" '' all ble/util/buffer "$ret" fi _ble_term_cursor_current=$state } function ble/term/cursor-state/set-internal { _ble_term_cursor_internal=$1 [[ $_ble_term_state == internal ]] && ble/term/cursor-state/.update "$1" } function ble/term/cursor-state/.update-hidden { local state=$1 [[ $state != hidden ]] && state=reveal _ble_term_cursor_hidden_current=$state } function ble/term/cursor-state/hide { _ble_term_cursor_hidden_internal=hidden [[ $_ble_term_state == internal ]] && ble/term/cursor-state/.update-hidden hidden } function ble/term/cursor-state/reveal { _ble_term_cursor_hidden_internal=reveal [[ $_ble_term_state == internal ]] && ble/term/cursor-state/.update-hidden reveal } function ble/term/bracketed-paste-mode/.init { local _ble_local_rlvars; ble/util/rlvar#load bleopt/declare -v term_bracketed_paste_mode on if ((_ble_bash>=50100)) && ! ble/util/rlvar#test enable-bracketed-paste; then bleopt term_bracketed_paste_mode= elif [[ ${TERM%%-*} == eterm ]]; then bleopt term_bracketed_paste_mode= fi function bleopt/check:term_bracketed_paste_mode { if [[ $_ble_term_bracketedPasteMode_internal ]]; then if [[ $value ]]; then [[ $bleopt_term_bracketed_paste_mode ]] || ble/util/buffer $'\e[?2004h' else [[ ! $bleopt_term_bracketed_paste_mode ]] || ble/util/buffer $'\e[?2004l' fi fi } ble/util/rlvar#bind-bleopt enable-bracketed-paste term_bracketed_paste_mode bool builtin unset -f "$FUNCNAME" } ble/term/bracketed-paste-mode/.init _ble_term_bracketedPasteMode_internal= function ble/term/bracketed-paste-mode/enter { _ble_term_bracketedPasteMode_internal=1 [[ ${bleopt_term_bracketed_paste_mode-} ]] && ble/util/buffer $'\e[?2004h' } function ble/term/bracketed-paste-mode/leave { _ble_term_bracketedPasteMode_internal= [[ ${bleopt_term_bracketed_paste_mode-} ]] && ble/util/buffer $'\e[?2004l' } if [[ $TERM == minix ]]; then function ble/term/bracketed-paste-mode/enter { return 0; } function ble/term/bracketed-paste-mode/leave { return 0; } fi bleopt/declare -v term_synchronized_update_mode auto function ble/term/synchronized-update-mode/resolve-auto { [[ $bleopt_term_synchronized_update_mode == auto ]] || return 0 case $_ble_term_TERM in (mintty:*|foot:*|wezterm:*|iTerm2:*|kitty:*|alacritty:*|zellij:*) bleopt_term_synchronized_update_mode=on ;; (*) bleopt_term_synchronized_update_mode= ;; esac } _ble_term_TERM=() _ble_term_DA1R=() _ble_term_DA2R=() _ble_term_TERM_done= function ble/term/DA2/request { case $TERM in (linux) _ble_term_TERM=linux:- ;; (st|st-*) _ble_term_TERM=st:- ;; (*) ble/util/buffer $'\e[>c' # DA2 要求 (ble-decode-char/csi/.decode で受信) esac } 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_vec ble/string#split da2r_vec ';' "$da2r" da2r_vec=("${da2r_vec[@]/#/10#0}") # 0で始まっていても10進数で解釈; WA #D1570 checked (is-array) case $da2r in ('0;271;0') _ble_term_TERM[depth]=terminology:200 ;; # 2012-10-05 https://github.com/borisfaure/terminology/commit/500e7be8b2b876462ed567ef6c90527f37482adb ('41;285;0') _ble_term_TERM[depth]=terminology:300 ;; # 2013-01-22 https://github.com/borisfaure/terminology/commit/526cc2aeacc0ae54825cbc3a3e2ab64f612f83c9 ('61;337;0') _ble_term_TERM[depth]=terminology:10400 ;; # 2019-01-20 https://github.com/borisfaure/terminology/commit/96bbfd054b271f7ad7f31e699b13c12cb8fbb2e2 ('0;0;0') _ble_term_TERM[depth]=wezterm:0 ;; ('1;277;0') _ble_term_TERM[depth]=wezterm:20220408 ;; # 2022-04-07 https://github.com/wez/wezterm/commit/ad91e3776808507cbef9e6d758b89d7ca92a4c7e ('0;115;0') _ble_term_TERM[depth]=konsole:30000 ;; # 2001-09-16 https://github.com/KDE/konsole/commit/2d93fed82aa27e89c9d7301d09d2e24e4fa4416d ('1;115;0') _ble_term_TERM[depth]=konsole:220380 ;; # 2022-02-24 https://github.com/KDE/konsole/commit/0cc64dcf7b90075bd17e46653df3069208d6a590 ('1;96;0') _ble_term_TERM[depth]=mlterm:30102 ;; ('1;277;0') _ble_term_TERM[depth]=mlterm:30402 ;; # Note: wezterm:20220408 と同じ。wezterm の方を優先 ('24;279;0') _ble_term_TERM[depth]=mlterm:30702 ;; ('0;95;0') _ble_term_TERM[depth]=iTerm2:${LC_TERMINAL_VERSION-2.9+} ;; ('41;2500;0') _ble_term_TERM[depth]=iTerm2:${LC_TERMINAL_VERSION-3.5+} ;; ('0;10;1') # Windows Terminal _ble_term_TERM[depth]=wt:0 ;; ('0;'*';1') if ((da2r_vec[1]>=3000)); then _ble_term_TERM[depth]=zellij:$((da2r_vec[1])) elif ((da2r_vec[1]>=1001)); then _ble_term_TERM[depth]=alacritty:$((da2r_vec[1])) fi ;; ('1;0'?????';0') _ble_term_TERM[depth]=foot:${da2r:3:5} ;; ('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 _ble_term_Ss= fi fi ;; ('65;'*) 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_vec[1])) fi ;; ('77;'*';0') _ble_term_TERM[depth]=mintty:$((da2r_vec[1])) ;; ('83;'*) local rex='^83;[0-9]+;0$' [[ $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_vec[1])) ;; esac [[ ${_ble_term_TERM[depth]} ]] && return 0 if rex='^xterm(-|$)'; [[ $TERM =~ $rex ]]; then local version=$((da2r_vec[1])) if rex='^1;[0-9]+;0$'; [[ $da2r =~ $rex ]]; then true 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 ((280<=version)) elif rex='^32;[0-9]+;0$'; [[ $da2r =~ $rex ]]; then ((354<=version&&version<2000)) else false fi && { _ble_term_TERM[depth]=xterm:$version; return 0; } fi _ble_term_TERM[depth]=unknown:- return 0 } function ble/term/DA1/notify { _ble_term_DA1R=$1; blehook/invoke term_DA1R; } function ble/term/DA2/notify { local depth=${#_ble_term_DA2R[@]} if ((depth==0)) || ble/string#match "${_ble_term_TERM[depth-1]}" '^(screen|tmux):'; then _ble_term_DA2R[depth]=$1 ble/term/DA2/initialize-term "$depth" local is_outermost=1 case ${_ble_term_TERM[depth]} in (screen:*|tmux:*) local ret is_outermost= ble/term/quote-passthrough $'\e[>c' "$((depth+1))" ble/util/buffer "$ret" ;; (contra:*) if [[ ! ${_ble_term_Ss-} ]]; then _ble_term_Ss=$'\e[@1 q' fi ;; (terminology:*) _ble_term_sc=$'\e7' _ble_term_rc=$'\r\e8' ;; esac if ((depth==0)); then ble/term/synchronized-update-mode/resolve-auto fi if [[ $is_outermost ]]; then _ble_term_TERM_done=1 ble/term/modifyOtherKeys/reset fi ((depth)) && return 0 fi blehook/invoke term_DA2R } function ble/term/quote-passthrough { local seq=$1 level=${2:-$((${#_ble_term_DA2R[@]}-1))} opts=$3 local all=; [[ :$opts: == *:all:* ]] && all=1 ret=$seq [[ $seq ]] || return 0 local i for ((i=level;--i>=0;)); do if [[ ${_ble_term_TERM[i]} == tmux:* ]]; then ret=$'\ePtmux;'${ret//$'\e'/$'\e\e'}$'\e\\'${all:+$seq} else ret=$'\eP'${ret//$'\e\\'/$'\e\e\\\eP\\'}$'\e\\'${all:+$seq} fi done } _ble_term_DECSTBM= _ble_term_DECSTBM_reset= function ble/term/test-DECSTBM.hook1 { (($1==2)) && _ble_term_DECSTBM=$'\e[%s;%sr' } function ble/term/test-DECSTBM.hook2 { if [[ $_ble_term_DECSTBM ]]; then if (($1==2)); then _ble_term_DECSTBM_reset=$'\e[r' else _ble_term_DECSTBM_reset=$'\e[;r' fi fi } function ble/term/test-DECSTBM { local -a DRAW_BUFF=() ble/canvas/panel/goto-top-dock.draw ble/canvas/put.draw "$_ble_term_sc"$'\e[1;2r' ble/canvas/put-cup.draw 2 1 ble/canvas/put-cud.draw 1 ble/term/CPR/request.draw ble/term/test-DECSTBM.hook1 ble/canvas/put.draw $'\e[;r' ble/canvas/put-cup.draw 2 1 ble/canvas/put-cud.draw 1 ble/term/CPR/request.draw ble/term/test-DECSTBM.hook2 ble/canvas/put.draw $'\e[r'"$_ble_term_rc" ble/canvas/bflush.draw } _ble_term_CPR_timeout=60 _ble_term_CPR_last_seconds=$SECONDS _ble_term_CPR_hook=() function ble/term/CPR/request.buff { ((SECONDS>_ble_term_CPR_last_seconds+_ble_term_CPR_timeout)) && _ble_term_CPR_hook=() _ble_term_CPR_last_seconds=$SECONDS ble/array#push _ble_term_CPR_hook "$1" ble/util/buffer $'\e[6n' return 147 } function ble/term/CPR/request.draw { ((SECONDS>_ble_term_CPR_last_seconds+_ble_term_CPR_timeout)) && _ble_term_CPR_hook=() _ble_term_CPR_last_seconds=$SECONDS ble/array#push _ble_term_CPR_hook "$1" ble/canvas/put.draw $'\e[6n' return 147 } function ble/term/CPR/notify { local hook=${_ble_term_CPR_hook[0]} ble/array#shift _ble_term_CPR_hook [[ ! $hook ]] || builtin eval -- "$hook $1 $2" } bleopt/declare -v term_modifyOtherKeys_external auto bleopt/declare -v term_modifyOtherKeys_internal auto bleopt/declare -v term_modifyOtherKeys_passthrough_kitty_protocol '' _ble_term_modifyOtherKeys_current= _ble_term_modifyOtherKeys_current_method= _ble_term_modifyOtherKeys_current_TERM= function ble/term/modifyOtherKeys/.update { local IFS=$_ble_term_IFS state=${1%%:*} [[ $1 == "$_ble_term_modifyOtherKeys_current" ]] && [[ $state != 2 || "${_ble_term_TERM[*]}" == "$_ble_term_modifyOtherKeys_current_TERM" ]] && return 0 local previous=${_ble_term_modifyOtherKeys_current%%:*} method if [[ $state == 2 ]]; then case $_ble_term_TERM in (RLogin:*) method=RLogin_modifyStringKeys ;; (kitty:*) 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 fi ;; (screen:*|tmux:*) method=modifyOtherKeys if [[ $bleopt_term_modifyOtherKeys_passthrough_kitty_protocol ]]; then local index=$((${#_ble_term_TERM[*]}-1)) if [[ ${_ble_term_TERM[index]} == kitty:* ]]; then local da2r_vec ble/string#split da2r_vec ';' "${_ble_term_DA2R[index]}" ((da2r_vec[2]>=23)) && method=kitty_keyboard_protocol fi fi ;; (*) method=modifyOtherKeys if [[ $1 == *:auto ]]; then ble/term/modifyOtherKeys/.supported || method=disabled fi ;; esac [[ $MC_SID ]] && method=disabled if ((previous>=2)) && [[ $method != "$_ble_term_modifyOtherKeys_current_method" ]] then ble/term/modifyOtherKeys/.update 1 previous=1 fi else method=$_ble_term_modifyOtherKeys_current_method fi _ble_term_modifyOtherKeys_current=$1 _ble_term_modifyOtherKeys_current_method=$method _ble_term_modifyOtherKeys_current_TERM="${_ble_term_TERM[*]}" case $method in (RLogin_modifyStringKeys) case $state in (0) ble/util/buffer $'\e[>5;0m' ;; (1) ble/util/buffer $'\e[>5;1m' ;; (2) ble/util/buffer $'\e[>5;1m\e[>5;2m' ;; esac ;; # fallback to modifyOtherKeys (kitty_modifyOtherKeys) case $state in (0|1) ble/util/buffer $'\e[>4;0m\e[>4m' ;; (2) ble/util/buffer $'\e[>4;1m\e[>4;2m\e[m' ;; esac return 0 ;; (kitty_keyboard_protocol) local seq= case $state in (0|1) # pop keyboard mode [[ $previous ]] || return 0 ((previous>=2)) && seq=$'\e[=2)) || seq=$'\e[>1u' ;; esac if [[ $seq ]]; then local ret ble/term/quote-passthrough "$seq" ble/util/buffer "$ret" local level for ((level=1;level<${#_ble_term_TERM[@]}-1;level++)); do [[ ${_ble_term_TERM[level]} == tmux:* ]] || continue case $state in (0) seq=$'\e[>4;0m\e[m' ;; (1) seq=$'\e[>4;1m\e[m' ;; (2) seq=$'\e[>4;1m\e[>4;2m\e[m' ;; esac ble/term/quote-passthrough "$seq" "$level" ble/util/buffer "$ret" break done fi return 0 ;; (disabled) return 0 ;; esac case $state in (0) ble/util/buffer $'\e[>4;0m\e[m' ;; (1) ble/util/buffer $'\e[>4;1m\e[m' ;; (2) ble/util/buffer $'\e[>4;1m\e[>4;2m\e[m' ;; esac } function ble/term/modifyOtherKeys/.supported { [[ $_ble_term_TERM_done ]] || return 1 [[ $_ble_term_TERM == vte:* ]] && return 1 [[ $MWG_LOGINTERM == rosaterm ]] && return 1 case $TERM in (linux) return 1 ;; (minix|sun*) return 1 ;; (st|st-*) return 1 ;; esac return 0 } function ble/term/modifyOtherKeys/enter { local value=$bleopt_term_modifyOtherKeys_internal if [[ $value == auto ]]; then value=2:auto fi ble/term/modifyOtherKeys/.update "$value" } function ble/term/modifyOtherKeys/leave { local value=$bleopt_term_modifyOtherKeys_external if [[ $value == auto ]]; then value=1:auto fi ble/term/modifyOtherKeys/.update "$value" } function ble/term/modifyOtherKeys/reset { ble/term/modifyOtherKeys/.update "$_ble_term_modifyOtherKeys_current" } _ble_term_altscr_state= function ble/term/enter-altscr { [[ $_ble_term_altscr_state ]] && return 0 _ble_term_altscr_state=("$_ble_canvas_x" "$_ble_canvas_y") if [[ $_ble_term_rmcup ]]; then ble/util/buffer "$_ble_term_smcup" else local -a DRAW_BUFF=() ble/canvas/put.draw $'\e[?1049h' ble/canvas/put-cup.draw "$LINES" 0 ble/canvas/put-ind.draw "$LINES" ble/canvas/bflush.draw fi } function ble/term/leave-altscr { [[ $_ble_term_altscr_state ]] || return 0 if [[ $_ble_term_rmcup ]]; then ble/util/buffer "$_ble_term_rmcup" else local -a DRAW_BUFF=() ble/canvas/put-cup.draw "$LINES" 0 ble/canvas/put-ind.draw ble/canvas/put.draw $'\e[?1049l' ble/canvas/bflush.draw fi _ble_canvas_x=${_ble_term_altscr_state[0]} _ble_canvas_y=${_ble_term_altscr_state[1]} _ble_term_altscr_state=() } _ble_term_rl_convert_meta_adjusted= _ble_term_rl_convert_meta_external= function ble/term/rl-convert-meta/enter { [[ $_ble_term_rl_convert_meta_adjusted ]] && return 0 _ble_term_rl_convert_meta_adjusted=1 if ble/util/rlvar#test convert-meta; then _ble_term_rl_convert_meta_external=on builtin bind 'set convert-meta off' else _ble_term_rl_convert_meta_external=off fi } function ble/term/rl-convert-meta/leave { [[ $_ble_term_rl_convert_meta_adjusted ]] || return 1 _ble_term_rl_convert_meta_adjusted= [[ $_ble_term_rl_convert_meta_external == on ]] && builtin bind 'set convert-meta on' } _ble_term_attached= _ble_term_state=external function ble/term/enter-for-widget { ble/term/bracketed-paste-mode/enter ble/term/modifyOtherKeys/enter ble/term/cursor-state/.update "$_ble_term_cursor_internal" ble/term/cursor-state/.update-hidden "$_ble_term_cursor_hidden_internal" [[ :$1: == *:noflush:* ]] || ble/util/buffer.flush } function ble/term/leave-for-widget { ble/term/visible-bell/erase ble/term/bracketed-paste-mode/leave ble/term/modifyOtherKeys/leave ble/term/cursor-state/.update "$bleopt_term_cursor_external" ble/term/cursor-state/.update-hidden reveal ble/util/buffer.flush } function ble/term/enter { [[ $_ble_term_state == internal ]] && return 0 _ble_term_state=internal ble/term/stty/enter ble/term/rl-convert-meta/enter ble/term/enter-for-widget "$1" } function ble/term/leave { [[ $_ble_term_state == external ]] && return 0 ble/term/stty/leave ble/term/rl-convert-meta/leave ble/term/leave-for-widget [[ $_ble_term_cursor_current == default ]] || _ble_term_cursor_current=unknown # vim は復元してくれない _ble_term_cursor_hidden_current=unknown _ble_term_state=external } function ble/term/initialize { ble/term/DA2/request ble/term/test-DECSTBM } function ble/term/attach { [[ $_ble_term_attached ]] && return 0 _ble_term_attached=1 ble/term/stty/initialize ble/term/enter "$1" } function ble/term/detach { [[ $_ble_term_attached ]] || return 0 _ble_term_attached= ble/term/stty/finalize ble/term/leave ble/util/buffer.flush } _ble_util_s2c_table_enabled= if ((_ble_bash>=50300)); then function ble/util/s2c { builtin printf -v ret %d "'$1" } elif ((_ble_bash>=40100)); then function ble/util/s2c { if ble/util/is-unicode-output; then builtin printf -v ret %d "'μ" else builtin printf -v ret %d "'x" fi builtin printf -v ret %d "'$1" } elif ((_ble_bash>=40000&&!_ble_bash_loaded_in_function)); then declare -A _ble_util_s2c_table _ble_util_s2c_table_enabled=1 function ble/util/s2c { [[ $_ble_util_locale_triple != "$LC_ALL:$LC_CTYPE:$LANG" ]] && ble/util/.cache/update-locale local s=${1::1} ret=${_ble_util_s2c_table[x$s]} [[ $ret ]] && return 0 ble/util/sprintf ret %d "'$s" _ble_util_s2c_table[x$s]=$ret } elif ((_ble_bash>=40000)); then function ble/util/s2c { ble/util/sprintf ret %d "'${1::1}" } else function ble/util/s2c { local s=${1::1} if [[ $s == [$'\x01'-$'\x7F'] ]]; then if [[ $s == $'\x7F' ]]; then ret=127 else ble/util/sprintf ret %d "'$s" fi return 0 fi local bytes byte ble/util/assign bytes ' local IFS= while ble/bash/read -n 1 byte; do builtin printf "%d " "'\''$byte" done <<< "$s" IFS=$_ble_term_IFS ' "ble/encoding:$bleopt_input_encoding/b2c" $bytes } fi if ((_ble_bash>=40200)); then function ble/util/.has-bashbug-printf-uffff { ((40200<=_ble_bash&&_ble_bash<50000)) || return 1 local LC_ALL=C.UTF-8 2>/dev/null local ret builtin printf -v ret '\uFFFF' ((${#ret}==2)) } ble/function#suppress-stderr ble/util/.has-bashbug-printf-uffff if ble/util/.has-bashbug-printf-uffff; then function ble/util/c2s.impl { if ((0xE000<=$1&&$1<=0xFFFF)) && [[ $_ble_util_locale_encoding == UTF-8 ]]; then builtin printf -v ret '\\x%02x' "$((0xE0|$1>>12&0x0F))" "$((0x80|$1>>6&0x3F))" "$((0x80|$1&0x3F))" else builtin printf -v ret '\\U%08x' "$1" fi builtin eval "ret=\$'$ret'" } function ble/util/chars2s.impl { if [[ $_ble_util_locale_encoding == UTF-8 ]]; then local -a buff=() local c i=0 for c; do ble/util/c2s.cached "$c" buff[i++]=$ret done IFS= builtin eval 'ret="${buff[*]}"' else builtin printf -v ret '\\U%08x' "$@" builtin eval "ret=\$'$ret'" fi } else function ble/util/c2s.impl { builtin printf -v ret '\\U%08x' "$1" builtin eval "ret=\$'$ret'" } function ble/util/chars2s.impl { builtin printf -v ret '\\U%08x' "$@" builtin eval "ret=\$'$ret'" } fi else _ble_text_xdigit=(0 1 2 3 4 5 6 7 8 9 A B C D E F) _ble_text_hexmap=() for ((i=0;i<256;i++)); do _ble_text_hexmap[i]=${_ble_text_xdigit[i>>4&0xF]}${_ble_text_xdigit[i&0xF]} done function ble/util/c2s.impl { if (($1<0x80)); then builtin eval "ret=\$'\\x${_ble_text_hexmap[$1]}'" return 0 fi local bytes i iN seq= ble/encoding:"$_ble_util_locale_encoding"/c2b "$1" for ((i=0,iN=${#bytes[@]};i/dev/null function ble/util/c2keyseq { local char=$(($1)) case $char in (7) ret='\a' ;; (8) ret='\b' ;; (9) ret='\t' ;; (10) ret='\n' ;; (11) ret='\v' ;; (12) ret='\f' ;; (13) ret='\r' ;; (27) ret='\e' ;; (92) ret='\\' ;; (127) ret='\d' ;; (28) ret='\x1c' ;; # workaround \C-\, \C-\\ (156) ret='\x9c' ;; # workaround \M-\C-\, \M-\C-\\ (*) if ((char<32||128<=char&&char<160)); then local char7=$((char&0x7F)) if ((1<=char7&&char7<=26)); then ble/util/c2s "$((char7+96))" else ble/util/c2s "$((char7+64))" fi ret='\C-'$ret ((char&0x80)) && ret='\M-'$ret else ble/util/c2s "$char" fi ;; esac } function ble/util/chars2keyseq { local char str= for char; do ble/util/c2keyseq "$char" str=$str$ret done ret=$str } function ble/util/keyseq2chars { local keyseq=$1 local -a chars=() local mods= local rex='^([^\]+)|^\\([CM]-|[0-7]{1,3}|x[0-9a-fA-F]{1,2}|.)?' while [[ $keyseq ]]; do local text=${keyseq::1} esc [[ $keyseq =~ $rex ]] && text=${BASH_REMATCH[1]} esc=${BASH_REMATCH[2]} if [[ $text ]]; then keyseq=${keyseq:${#text}} ble/util/s2chars "$text" else keyseq=${keyseq:1+${#esc}} ret=() case $esc in ([CM]-) mods=$mods${esc::1}; continue ;; (x?*) ret=$((16#${esc#x})) ;; ([0-7]*) ret=$((8#$esc)) ;; (a) ret=7 ;; (b) ret=8 ;; (t) ret=9 ;; (n) ret=10 ;; (v) ret=11 ;; (f) ret=12 ;; (r) ret=13 ;; (e) ret=27 ;; (d) ret=127 ;; (*) ble/util/s2c "$esc" ;; esac fi [[ $mods == *C* ]] && ((ret=ret==63?127:(ret&0x1F))) [[ $mods == *M* ]] && ble/array#push chars 27 mods= ble/array#push chars "${ret[@]}" done if [[ $mods ]]; then [[ $mods == *M* ]] && ble/array#push chars 27 ble/array#push chars 0 fi ret=("${chars[@]}") } function ble/encoding:UTF-8/b2c { local bytes b0 n i bytes=("$@") ret=0 ((b0=bytes[0]&0xFF)) ((n=b0>=0xF0 ?(b0>=0xFC?5:(b0>=0xF8?4:3)) :(b0>=0xE0?2:(b0>=0xC0?1:0)), ret=n?b0&0x7F>>n:b0)) for ((i=1;i<=n;i++)); do ((ret=ret<<6|0x3F&bytes[i])) done } function ble/encoding:UTF-8/c2b { local code=$1 n i ((code=code&0x7FFFFFFF, n=code<0x80?0:( code<0x800?1:( code<0x10000?2:( code<0x200000?3:( code<0x4000000?4:5)))))) if ((n==0)); then bytes=("$code") else bytes=() for ((i=n;i;i--)); do ((bytes[i]=0x80|code&0x3F, code>>=6)) done ((bytes[0]=code&0x3F>>n|0xFF80>>n&0xFF)) fi } function ble/encoding:C/b2c { local byte=$1 ((ret=byte&0xFF)) } function ble/encoding:C/c2b { local code=$1 bytes=("$((code&0xFF))") } 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=() 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 ble/array#push list CC LESS MANOPT MANPAGER PAGER PATH MANPATH 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 ble/array#push list PRETTY_NAME NAME VERSION # edit (/etc/os-release) local v for v in "${list[@]}"; do ble/gdict#set _ble_builtin_readonly_blacklist "$v" 1; done } function ble/builtin/readonly/.check-variable-name { ble/variable#is-global "$1" || return 0 if [[ $1 == _* && $1 != _ble* && $1 != __ble* ]]; then return 0 fi 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 ble/builtin/readonly/.initialize-blacklist if ble/gdict#has _ble_builtin_readonly_blacklist "$1"; then return 1 fi if [[ $1 != *[a-z]* ]]; then return 0 fi return 1 } builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_builtin_readonly_mark}" _ble_builtin_readonly_message_count=0 blehook internal_PREEXEC!='_ble_builtin_readonly_message_count=0' function ble/builtin/readonly/.print-warning { [[ -t 2 ]] || return 0 if [[ ! $_ble_local_caller ]]; then _ble_local_caller=- local i n=${#FUNCNAME[@]} for ((i=1;i&2 return 0 } function ble/builtin/readonly { local _ble_local_set _ble_local_shopt ble/base/.adjust-bash-options _ble_local_set _ble_local_shopt local LC_ALL= LC_COLLATE=C 2>/dev/null # suppress locale error #D1440 local _ble_local_flags= local -a _ble_local_options=() local _ble_local_caller= # used by print-warning 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 ble/builtin/readonly/.print-warning "$1" 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 local _ble_local_ext=0 if [[ $_ble_local_flags != *v* || $_ble_local_flags == *r* ]]; then builtin readonly "${_ble_local_options[@]}" _ble_local_ext=$? fi ble/util/unlocal LC_ALL LC_COLLATE 2>/dev/null # suppress locale error #D1440 ble/base/.restore-bash-options _ble_local_set _ble_local_shopt return "$?" } function readonly { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" ble/builtin/readonly "$@" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" } >| "$_ble_base_run/$$.util.message-listening" >> "$_ble_base_run/$$.util.message" _ble_util_message_precmd=() function ble/util/message/.encode-data { local target=$1 data=$2 if ((${#data}<256)); then ble/string#quote-word "$data" ret=eval:$ret else if ((_ble_bash<40000)); then local BASHPID ble/util/getpid fi local index=0 file while file=$_ble_base_run/$target.util.message.data-$BASHPID-$index [[ -e $file ]] do ((++index)); done ble/util/put "$data" >| "$file" ret=file:${file##*.} fi } function ble/util/message/.decode-data { ret=$1 case $ret in (eval:*) local value=${ret#eval:} ble/syntax:bash/simple-word/is-simple "$value" && builtin eval -- "ret=($value)" ;; (file:*) local file=$_ble_base_run/$$.util.message.${ret#file:} ble/util/readfile ret "$file" ble/array#push _ble_local_remove "$file" esac } function ble/util/message.post { local target=${1:-$$} event=${2-} type=${3-} data=${4-} if ! [[ $type && $type != *["$_ble_term_IFS"]* ]]; then ble/util/print "ble/util/message: invalid message type format '$type'" >&2 return 2 elif [[ $target == $$ ]] && ! ble/is-function ble/util/message/handler:"$type"; then ble/util/print "ble/util/message: unknown message type name '$type'" >&2 return 2 fi case $event in (precmd) ;; (*) ble/util/print "ble/util/message: unknown event type '$event'" >&2 return 2 ;; esac if [[ $target == broadcast ]]; then local ret file ble/util/eval-pathname-expansion '"$_ble_base_run"/+([0-9]).util.message-listening' canonical for file in "${ret[@]}"; do file=${file%-listening} local pid=${file##*/}; pid=${pid%%.*} if builtin kill -0 "$pid"; then ble/util/message/.encode-data "$pid" "$data" ble/util/print "$event $type $ret" >> "$file" fi done elif ble/string#match "$target" '^[0-9]+$'; then if ! builtin kill -0 "$target"; then ble/util/print "ble/util/message: target process $target is not found" >&2 return 2 elif [[ ! -f $_ble_base_run/$target.util.message-listening ]]; then ble/util/print "ble/util/message: target process $target is not listening ble-messages" >&2 return 2 fi local ret ble/util/message/.encode-data "$target" "$data" ble/util/print "$event $type $ret" >> "$_ble_base_run/$target.util.message" else ble/util/print "ble/util/message: unknown target '$target'" >&2 return 2 fi } function ble/util/message.check { local file=$_ble_base_run/$$.util.message while [[ -f $file && -s $file ]]; do local fread=$file ble/bin/mv -f "$file" "$file-reading" && fread=$file-reading local IFS=$_ble_term_IFS event type data while ble/bash/read event type data || [[ $event ]]; do [[ $type ]] && ble/is-function ble/util/message/handler:"$type" || continue case $event in (precmd) ble/array#push _ble_util_message_precmd "$type $data" ;; esac done < "$fread" >| "$fread" done } function ble/util/message.process { ble/util/message.check local event=$1 case $event in (precmd) local _ble_local_messages _ble_local_messages=("${_ble_util_message_precmd[@]}") _ble_util_message_precmd=() local _ble_local_message local -a _ble_local_remove=() for _ble_local_message in "${_ble_local_messages[@]}"; do local _ble_local_event=${_ble_local_message%%' '*} local ret; ble/util/message/.decode-data "${_ble_local_message#* }" local _ble_local_data=$ret ble/util/unlocal ret ble/util/message/handler:"$_ble_local_event" "$_ble_local_data" done ((${#_ble_local_remove[@]})) && ble/bin/rm -f "${_ble_local_remove[@]}" ;; (*) ble/util/print "ble/util/message: unknown event type '$event'" >&2 return 2 ;; esac } function ble/util/message/handler:print { ble/edit/enter-command-layout # #D1800 pair=leave-command-layout ble/util/print "$1" >&2 ble/edit/leave-command-layout # #D1800 pair=enter-command-layout } blehook internal_PRECMD!='ble/util/message.process precmd' bleopt/declare -v debug_xtrace '' bleopt/declare -v debug_xtrace_ps4 '+ ' ble/bin#freeze-utility-path "${_ble_init_posix_command_list[@]}" # <- this uses ble/util/assign. ble/bin#freeze-utility-path man ble/bin#freeze-utility-path groff nroff mandoc gzip bzcat lzcat xzcat # used by core-complete.sh ble/function#trace trap ble/builtin/trap ble/builtin/trap/finalize ble/function#trace ble/builtin/trap/.handler ble/builtin/trap/invoke ble/builtin/trap/invoke.sandbox ble/builtin/trap/install-hook EXIT ble/builtin/trap/install-hook INT ble/builtin/trap/install-hook ERR inactive ble/builtin/trap/install-hook RETURN inactive function ble/base/initialize-session { local ret ble/string#split ret / "${_ble_base_session-}" [[ ${ret[1]} == "$$" ]] && return 0 ble/util/timeval; local start_time=$ret ((start_time-=SECONDS*1000000)) _ble_base_session=${start_time::${#start_time}-6}.${start_time:${#start_time}-6}/$$ export BLE_SESSION_ID=$_ble_base_session } ble/base/initialize-session function ble/base/check-bash-debug-version { case ${BASH_VERSINFO[4]} in (alp*|bet*|dev*|rc*|releng*|maint*) ;; (*) return 0 ;; esac local type=check ret ble/opts#extract-last-optarg "$_ble_base_arguments_opts" bash-debug-version check && type=$ret [[ $type == ignore ]] && return 0 local file=$_ble_base_cache/base.bash-debug-version-checked.txt local -a checked=() [[ ! -d $file && -r $file && -s $file ]] && ble/util/mapfile checked < "$file" if ble/array#index checked "$BASH_VERSION"; then [[ $type == once ]] && return 0 else ble/util/print "$BASH_VERSION" >> "$file" fi local sgr0=$_ble_term_sgr0 local sgr1=${_ble_term_setaf[4]} local sgr2=${_ble_term_setaf[6]} local sgr3=${_ble_term_setaf[2]} local sgrC=${_ble_term_setaf[8]} local bold=$_ble_term_bold if [[ $type == short || $_ble_init_command ]]; then ble/util/print-lines \ "Note: ble.sh can be very slow in a debug version of Bash: $sgr3$BASH_VERSION$sgr0" else ble/util/print-lines \ "$bold# ble.sh with debug version of Bash$sgr0" \ '' \ 'ble.sh may become very slow because this is a debug version of Bash (version' \ "\`$sgr3$BASH_VERSION$sgr0', release status: \`$sgr3${BASH_VERSINFO[4]}$sgr0'). We recommend using" \ 'ble.sh with a release version of Bash. If you want to use ble.sh with a' \ 'non-release version of Bash, it is highly recommended to build Bash with the' \ "configure option \`$sgr2--with-bash-malloc=no$sgr0' for practical performance:" \ '' \ " $sgr1./configure $bold--with-bash-malloc=no$sgr0" \ '' \ 'To suppress this startup warning message, please specify the option' \ "\`$sgr2--bash-debug-version=short$sgr0' or \`${sgr2}once$sgr0' or \`${sgr2}ignore$sgr0' to \`ble.sh':" \ '' \ " ${sgrC}# Show a short version of the message$sgr0" \ " ${sgr1}source /path/to/ble.sh $bold--bash-debug-version=short$sgr0" \ '' \ " ${sgrC}# Do not print the warning message more than once$sgr0" \ " ${sgr1}source /path/to/ble.sh $bold--bash-debug-version=once$sgr0" \ '' \ " ${sgrC}# Show the warning message only once for each debug version of Bash$sgr0" \ " ${sgr1}source /path/to/ble.sh $bold--bash-debug-version=ignore$sgr0" \ '' fi } ble/base/check-bash-debug-version bleopt/declare -v decode_error_char_abell '' bleopt/declare -v decode_error_char_vbell 1 bleopt/declare -v decode_error_char_discard '' bleopt/declare -v decode_error_cseq_abell '' bleopt/declare -v decode_error_cseq_vbell '' bleopt/declare -v decode_error_cseq_discard 1 bleopt/declare -v decode_error_kseq_abell 1 bleopt/declare -v decode_error_kseq_vbell 1 bleopt/declare -v decode_error_kseq_discard 1 bleopt/declare -n default_keymap auto function bleopt/check:default_keymap { case $value in (auto|emacs|vi|safe) if [[ $_ble_decode_bind_state != none ]]; then local bleopt_default_keymap=$value ble/decode/reset-default-keymap fi return 0 ;; (*) ble/util/print "bleopt: Invalid value default_keymap='value'. The value should be one of \`auto', \`emacs', \`vi'." >&2 return 1 ;; esac } function bleopt/get:default_keymap { ret=$bleopt_default_keymap if [[ $ret == auto ]]; then if [[ -o vi ]]; then ret=vi else ret=emacs fi fi } bleopt/declare -n decode_isolated_esc auto function bleopt/check:decode_isolated_esc { case $value in (meta|esc|auto) ;; (*) ble/util/print "bleopt: Invalid value decode_isolated_esc='$value'. One of the values 'auto', 'meta' or 'esc' is expected." >&2 return 1 ;; esac } function ble/decode/uses-isolated-esc { if [[ $bleopt_decode_isolated_esc == esc ]]; then return 0 elif [[ $bleopt_decode_isolated_esc == auto ]]; then if local ret; bleopt/get:default_keymap; [[ $ret == vi ]]; then return 0 elif [[ ! $_ble_decode_key__seq ]]; then local dicthead=_ble_decode_${_ble_decode_keymap}_kmap_ key=$((_ble_decode_Ctrl|91)) builtin eval "local ent=\${$dicthead$_ble_decode_key__seq[key]-}" [[ ${ent:2} ]] && return 0 fi fi return 1 } bleopt/declare -n decode_abort_char 28 bleopt/declare -n decode_macro_limit 1024 _ble_decode_Meta=0x08000000 _ble_decode_Ctrl=0x04000000 _ble_decode_Shft=0x02000000 _ble_decode_Hypr=0x01000000 _ble_decode_Supr=0x00800000 _ble_decode_Altr=0x00400000 _ble_decode_MaskChar=0x001FFFFF _ble_decode_MaskFlag=0x7FC00000 _ble_decode_Erro=0x40000000 _ble_decode_Macr=0x20000000 _ble_decode_Flag3=0x10000000 # unused _ble_decode_FlagA=0x00200000 # unused _ble_decode_IsolatedESC=$((0x07FC)) _ble_decode_EscapedNUL=$((0x07FB)) # charlog#encode で用いる _ble_decode_FunctionKeyBase=0x110000 function ble/decode/mod2flag { ret=0 local mod=$1 ((mod&0x01&&(ret|=_ble_decode_Shft), mod&0x02&&(ret|=_ble_decode_Meta), mod&0x04&&(ret|=_ble_decode_Ctrl), mod&0x08&&(ret|=_ble_decode_Supr), mod&0x10&&(ret|=_ble_decode_Hypr), mod&0x20&&(ret|=_ble_decode_Altr))) } function ble/decode/flag2mod { ret=0 local flag=$1 ((flag&_ble_decode_Shft&&(ret|=0x01), flag&_ble_decode_Meta&&(ret|=0x02), flag&_ble_decode_Ctrl&&(ret|=0x04), flag&_ble_decode_Supr&&(ret|=0x08), flag&_ble_decode_Hypr&&(ret|=0x10), flag&_ble_decode_Altr&&(ret|=0x20))) } _ble_decode_kbd_ver=gdict _ble_decode_kbd__n=0 _ble_decode_kbd__c2k=() builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_decode_kbd__k2c}" ble/is-assoc _ble_decode_kbd__k2c || _ble_decode_kbd_ver=adict function ble-decode-kbd/.set-keycode { local keyname=$1 local code=$2 : "${_ble_decode_kbd__c2k[code]:=$keyname}" ble/gdict#set _ble_decode_kbd__k2c "$keyname" "$code" } function ble-decode-kbd/.get-keycode { ble/gdict#get _ble_decode_kbd__k2c "$1" } function ble-decode-kbd/.get-keyname { local keycode=$1 ret=${_ble_decode_kbd__c2k[keycode]} if [[ ! $ret ]] && ((keycode<_ble_decode_FunctionKeyBase)); then ble/util/c2s "$keycode" fi } function ble-decode-kbd/generate-keycode { local keyname=$1 if ((${#keyname}==1)); then ble/util/s2c "$1" 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++)) ble-decode-kbd/.set-keycode "$keyname" "$ret" fi else ret=-1 return 1 fi } function ble-decode-kbd/.initialize { ble-decode-kbd/.set-keycode TAB 9 ble-decode-kbd/.set-keycode RET 13 ble-decode-kbd/.set-keycode NUL 0 ble-decode-kbd/.set-keycode SOH 1 ble-decode-kbd/.set-keycode STX 2 ble-decode-kbd/.set-keycode ETX 3 ble-decode-kbd/.set-keycode EOT 4 ble-decode-kbd/.set-keycode ENQ 5 ble-decode-kbd/.set-keycode ACK 6 ble-decode-kbd/.set-keycode BEL 7 ble-decode-kbd/.set-keycode BS 8 ble-decode-kbd/.set-keycode HT 9 # aka TAB ble-decode-kbd/.set-keycode LF 10 ble-decode-kbd/.set-keycode VT 11 ble-decode-kbd/.set-keycode FF 12 ble-decode-kbd/.set-keycode CR 13 # aka RET ble-decode-kbd/.set-keycode SO 14 ble-decode-kbd/.set-keycode SI 15 ble-decode-kbd/.set-keycode DLE 16 ble-decode-kbd/.set-keycode DC1 17 ble-decode-kbd/.set-keycode DC2 18 ble-decode-kbd/.set-keycode DC3 19 ble-decode-kbd/.set-keycode DC4 20 ble-decode-kbd/.set-keycode NAK 21 ble-decode-kbd/.set-keycode SYN 22 ble-decode-kbd/.set-keycode ETB 23 ble-decode-kbd/.set-keycode CAN 24 ble-decode-kbd/.set-keycode EM 25 ble-decode-kbd/.set-keycode SUB 26 ble-decode-kbd/.set-keycode ESC 27 ble-decode-kbd/.set-keycode FS 28 ble-decode-kbd/.set-keycode GS 29 ble-decode-kbd/.set-keycode RS 30 ble-decode-kbd/.set-keycode US 31 ble-decode-kbd/.set-keycode SP 32 ble-decode-kbd/.set-keycode DEL 127 ble-decode-kbd/.set-keycode PAD 128 ble-decode-kbd/.set-keycode HOP 129 ble-decode-kbd/.set-keycode BPH 130 ble-decode-kbd/.set-keycode NBH 131 ble-decode-kbd/.set-keycode IND 132 ble-decode-kbd/.set-keycode NEL 133 ble-decode-kbd/.set-keycode SSA 134 ble-decode-kbd/.set-keycode ESA 135 ble-decode-kbd/.set-keycode HTS 136 ble-decode-kbd/.set-keycode HTJ 137 ble-decode-kbd/.set-keycode VTS 138 ble-decode-kbd/.set-keycode PLD 139 ble-decode-kbd/.set-keycode PLU 140 ble-decode-kbd/.set-keycode RI 141 ble-decode-kbd/.set-keycode SS2 142 ble-decode-kbd/.set-keycode SS3 143 ble-decode-kbd/.set-keycode DCS 144 ble-decode-kbd/.set-keycode PU1 145 ble-decode-kbd/.set-keycode PU2 146 ble-decode-kbd/.set-keycode STS 147 ble-decode-kbd/.set-keycode CCH 148 ble-decode-kbd/.set-keycode MW 149 ble-decode-kbd/.set-keycode SPA 150 ble-decode-kbd/.set-keycode EPA 151 ble-decode-kbd/.set-keycode SOS 152 ble-decode-kbd/.set-keycode SGCI 153 ble-decode-kbd/.set-keycode SCI 154 ble-decode-kbd/.set-keycode CSI 155 ble-decode-kbd/.set-keycode ST 156 ble-decode-kbd/.set-keycode OSC 157 ble-decode-kbd/.set-keycode PM 158 ble-decode-kbd/.set-keycode APC 159 ble-decode-kbd/.set-keycode @ESC "$_ble_decode_IsolatedESC" ble-decode-kbd/.set-keycode @NUL "$_ble_decode_EscapedNUL" local ret ble-decode-kbd/generate-keycode __batch_char__ _ble_decode_KCODE_BATCH_CHAR=$ret ble-decode-kbd/generate-keycode __defchar__ _ble_decode_KCODE_DEFCHAR=$ret ble-decode-kbd/generate-keycode __default__ _ble_decode_KCODE_DEFAULT=$ret ble-decode-kbd/generate-keycode __before_widget__ _ble_decode_KCODE_BEFORE_WIDGET=$ret ble-decode-kbd/generate-keycode __after_widget__ _ble_decode_KCODE_AFTER_WIDGET=$ret ble-decode-kbd/generate-keycode __attach__ _ble_decode_KCODE_ATTACH=$ret ble-decode-kbd/generate-keycode __detach__ _ble_decode_KCODE_DETACH=$ret ble-decode-kbd/generate-keycode shift _ble_decode_KCODE_SHIFT=$ret ble-decode-kbd/generate-keycode alter _ble_decode_KCODE_ALTER=$ret ble-decode-kbd/generate-keycode control _ble_decode_KCODE_CONTROL=$ret ble-decode-kbd/generate-keycode meta _ble_decode_KCODE_META=$ret ble-decode-kbd/generate-keycode super _ble_decode_KCODE_SUPER=$ret ble-decode-kbd/generate-keycode hyper _ble_decode_KCODE_HYPER=$ret ble-decode-kbd/generate-keycode __ignore__ _ble_decode_KCODE_IGNORE=$ret ble-decode-kbd/generate-keycode __error__ _ble_decode_KCODE_ERROR=$ret ble-decode-kbd/generate-keycode __line_limit__ _ble_decode_KCODE_LINE_LIMIT=$ret ble-decode-kbd/generate-keycode mouse _ble_decode_KCODE_MOUSE=$ret ble-decode-kbd/generate-keycode mouse_move _ble_decode_KCODE_MOUSE_MOVE=$ret ble-decode-kbd/generate-keycode auto_complete_enter } ble-decode-kbd/.initialize function ble-decode-kbd { local IFS=$_ble_term_IFS local spec="$*" case $spec in (keys:*) ret="${spec#*:}" return 0 ;; (chars:*) local chars ble/string#split-words chars "${spec#*:}" ble/decode/cmap/decode-chars "${ret[@]}" ret="${keys[*]}" return 0 ;; (keyseq:*) # i.e. untranslated keyseq local keys ble/util/keyseq2chars "${spec#*:}" ble/decode/cmap/decode-chars "${ret[@]}" ret="${keys[*]}" return 0 ;; (raw:*) # i.e. translated keyseq ble/util/s2chars "${spec#*:}" ble/decode/cmap/decode-chars "${ret[@]}" ret="${keys[*]}" return 0 ;; (kspecs:*) spec=${spec#*:} ;; esac local kspecs; ble/string#split-words kspecs "$spec" local kspec code codes codes=() for kspec in "${kspecs[@]}"; do code=0 while [[ $kspec == ?-* ]]; do case ${kspec::1} in (S) ((code|=_ble_decode_Shft)) ;; (C) ((code|=_ble_decode_Ctrl)) ;; (M) ((code|=_ble_decode_Meta)) ;; (A) ((code|=_ble_decode_Altr)) ;; (s) ((code|=_ble_decode_Supr)) ;; (H) ((code|=_ble_decode_Hypr)) ;; (*) ((code|=_ble_decode_Erro)) ;; esac kspec=${kspec:2} done if [[ $kspec == ? ]]; then ble/util/s2c "$kspec" ((code|=ret)) elif [[ $kspec && ! ${kspec//[@_a-zA-Z0-9]} ]]; then ble-decode-kbd/.get-keycode "$kspec" [[ $ret ]] || ble-decode-kbd/generate-keycode "$kspec" ((code|=ret)) elif [[ $kspec == ^? ]]; then if [[ $kspec == '^?' ]]; then ((code|=0x7F)) elif [[ $kspec == '^`' ]]; then ((code|=0x20)) else ble/util/s2c "${kspec:1}" ((code|=ret&0x1F)) fi elif local rex='^U\+([0-9a-fA-F]+)$'; [[ $kspec =~ $rex ]]; then ((code|=0x${BASH_REMATCH[1]})) else ((code|=_ble_decode_Erro)) fi codes[${#codes[@]}]=$code done ret="${codes[*]}" } function ble-decode-unkbd/.single-key { local key=$1 local f_unknown= local char=$((key&_ble_decode_MaskChar)) ble-decode-kbd/.get-keyname "$char" if [[ ! $ret ]]; then f_unknown=1 ret=__UNKNOWN__ fi ((key&_ble_decode_Shft)) && ret=S-$ret ((key&_ble_decode_Meta)) && ret=M-$ret ((key&_ble_decode_Ctrl)) && ret=C-$ret ((key&_ble_decode_Altr)) && ret=A-$ret ((key&_ble_decode_Supr)) && ret=s-$ret ((key&_ble_decode_Hypr)) && ret=H-$ret [[ ! $f_unknown ]] } function ble-decode-unkbd { local IFS=$_ble_term_IFS local -a kspecs local key for key in $*; do ble-decode-unkbd/.single-key "$key" kspecs[${#kspecs[@]}]=$ret done ret="${kspecs[*]}" } function ble/decode/keys2chars { local -a keys=() local key for key; do local flag=$((key&_ble_decode_MaskFlag)) local char=$((key&_ble_decode_MaskChar)) if ((flag&_ble_decode_Meta)); then ble/array#push keys 27 ((flag&=~_ble_decode_Meta)) fi if ((flag==_ble_decode_Ctrl&&(char==63||char==64||91<=char&&char<=95||97<=char&&char<=122))); then ble/array#push keys "$((char==63?127:(char&0x1F)))" continue fi local mod_param= if ((flag)); then ble/decode/flag2mod "$flag" mod_param=$((ret+1)) fi local csi=${_ble_decode_csimap_dict[char]-} if [[ $csi == tilde:* ]]; then local params=${csi#*:} if [[ $mod_param ]]; then params=$params';'$mod_param fi ble/util/s2chars "$params" ble/array#push keys 27 91 "${ret[@]}" 126 elif [[ $csi == alpha:* ]]; then if [[ $mod_param ]]; then ble/util/s2chars "1;$mod_param" else ret=() fi ble/array#push keys 27 91 "${ret[@]}" "${csi#*:}" elif ((flag||char>=_ble_decode_FunctionKeyBase)); then ble/util/s2chars "27;${mod_param:-1};$char" ble/array#push keys 27 91 "${ret[@]}" 126 else ble/array#push keys "$char" fi done ret=("${keys[@]}") } function ble-decode/PROLOGUE { return 0; } function ble-decode/EPILOGUE { return 0; } _ble_decode_input_buffer=() _ble_decode_input_count=0 _ble_decode_input_original_info=() _ble_decode_show_progress_hook=ble-decode/.hook/show-progress _ble_decode_erase_progress_hook=ble-decode/.hook/erase-progress function ble-decode/.hook/show-progress { if [[ $_ble_edit_info_scene == store ]]; then _ble_decode_input_original_info=("${_ble_edit_info[@]}") return 0 elif [[ $_ble_edit_info_scene == default ]]; then _ble_decode_input_original_info=() elif [[ $_ble_edit_info_scene != decode_input_progress ]]; then return 0 fi local progress_opts= opt_percentage=1 if [[ $ble_batch_insert_count ]]; then local total=$ble_batch_insert_count local value=$ble_batch_insert_index local label='constructing text...' local sgr=$'\e[1;38;5;204;48;5;253m' elif ((${#_ble_decode_input_buffer[@]})); then local total=10000 local value=$((${#_ble_decode_input_buffer[@]}%10000)) local label="${#_ble_decode_input_buffer[@]} bytes received..." local sgr=$'\e[1;38;5;135;48;5;253m' progress_opts=unlimited opt_percentage= elif ((_ble_decode_input_count)); then local total=${#chars[@]} local value=$((total-_ble_decode_input_count-1)) local label='decoding input...' local sgr=$'\e[1;38;5;69;48;5;253m' elif ((ble_decode_char_total)); then local total=$ble_decode_char_total local value=$((total-ble_decode_char_rest-1)) local label='processing input...' local sgr=$'\e[1;38;5;71;48;5;253m' else return 0 fi if [[ $opt_percentage ]]; then local mill=$((value*1000/total)) local cent=${mill::${#mill}-1} frac=${mill:${#mill}-1} label="${cent:-0}.$frac% $label" fi local text="($label)" if ble/util/is-unicode-output; then local ret ble/string#create-unicode-progress-bar "$value" "$total" 10 "$progress_opts" text=$sgr$ret$'\e[m '$text fi ble/edit/info/show ansi "$text" _ble_edit_info_scene=decode_input_progress } function ble-decode/.hook/erase-progress { [[ $_ble_edit_info_scene == decode_input_progress ]] || return 1 if ((${#_ble_decode_input_original_info[@]})); then ble/edit/info/show store "${_ble_decode_input_original_info[@]}" else ble/edit/info/default fi } function ble-decode/.check-abort { if (($1==bleopt_decode_abort_char)); then local nbytes=${#_ble_decode_input_buffer[@]} local nchars=${#_ble_decode_char_buffer[@]} ((nbytes||nchars)); return "$?" fi (($1==0x7e||$1==0x75)) || return 1 local i=$((${#_ble_decode_input_buffer[@]}-1)) local n ((n=bleopt_decode_abort_char, n+=(1<=n&&n<=26?96:64))) if (($1==0x7e)); then for ((;n;n/=10)); do ((i>=0)) && ((_ble_decode_input_buffer[i--]==n%10+48)) || return 1 done ((i>=4)) || return 1 ((_ble_decode_input_buffer[i--]==59)) || return 1 ((_ble_decode_input_buffer[i--]==53)) || return 1 ((_ble_decode_input_buffer[i--]==59)) || return 1 ((_ble_decode_input_buffer[i--]==55)) || return 1 ((_ble_decode_input_buffer[i--]==50)) || return 1 elif (($1==0x75)); then ((i>=1)) || return 1 ((_ble_decode_input_buffer[i--]==53)) || return 1 ((_ble_decode_input_buffer[i--]==59)) || return 1 for ((;n;n/=10)); do ((i>=0)) && ((_ble_decode_input_buffer[i--]==n%10+48)) || return 1 done fi ((i>=0)) && ((_ble_decode_input_buffer[i]==62&&i--)) ((i>=0)) || return 1 if ((_ble_decode_input_buffer[i]==0x5B)); then if ((i>=1&&_ble_decode_input_buffer[i-1]==0x1B)); then ((i-=2)) elif ((i>=2&&_ble_decode_input_buffer[i-1]==0x9B&&_ble_decode_input_buffer[i-2]==0xC0)); then ((i-=3)) else return 1 fi elif ((_ble_decode_input_buffer[i]==0x9B)); then ((--i>=0)) && ((_ble_decode_input_buffer[i--]==0xC2)) || return 1 else return 1 fi (((i>=0||${#_ble_decode_char_buffer[@]}))); return "$?" return 0 } if ((_ble_bash>=40400)); then function ble/decode/nonblocking-read { local timeout=${1:-0.01} ntimeout=${2:-1} loop=${3:-100} local LC_ALL= LC_CTYPE=C IFS= local -a data=() local line buff ext while ((loop--)); do ble/bash/read-timeout "$timeout" -r -d '' buff; ext=$? [[ $buff ]] && line=$line$buff if ((ext==0)); then ble/array#push data "$line" line= elif ((ext>128)); then ((--ntimeout)) || break [[ $buff ]] || break else break fi done ble/util/assign ret '{ ((${#data[@]})) && printf %s\\0 "${data[@]}" [[ $line ]] && printf %s "$line" } | ble/bin/od -A n -t u1 -v' ble/string#split-words ret "$ret" } ble/function#suppress-stderr ble/decode/nonblocking-read elif ((_ble_bash>=40000)); then function ble/decode/nonblocking-read { local timeout=${1:-0.01} ntimeout=${2:-1} loop=${3:-100} local LC_ALL= LC_CTYPE=C IFS= 2>/dev/null local -a data=() local line buff while ((loop--)); do builtin read -t 0 || break ble/bash/read -d '' -n 1 buff || break if [[ $buff ]]; then line=$line$buff else ble/array#push data "$line" line= fi done ble/util/assign ret '{ ((${#data[@]})) && printf %s\\0 "${data[@]}" [[ $line ]] && printf %s "$line" } | ble/bin/od -A n -t u1 -v' ble/string#split-words ret "$ret" } ble/function#suppress-stderr ble/decode/nonblocking-read fi function ble-decode/.hook/adjust-volatile-options { if [[ $_ble_bash_options_adjusted ]]; then set +ev fi } _ble_decode_hook_count=${_ble_decode_hook_count:+0} _ble_decode_hook_Processing= function _ble_decode_hook { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_unset" ((_ble_decode_hook_count++)) if ble/util/is-stdin-ready; then ble/array#push _ble_decode_input_buffer "$@" local buflen=${#_ble_decode_input_buffer[@]} if ((buflen%257==0&&buflen>=2000)); then ble-decode/.hook/adjust-volatile-options local IFS=$_ble_term_IFS local _ble_decode_hook_Processing=prologue ble-decode/PROLOGUE _ble_decode_hook_Processing=body local char=${_ble_decode_input_buffer[buflen-1]} if ((_ble_bash<40000||char==0xC0||char==0xDF)); then builtin eval -- "$_ble_decode_show_progress_hook" else while ble/util/is-stdin-ready; do builtin eval -- "$_ble_decode_show_progress_hook" local ret; ble/decode/nonblocking-read 0.02 1 527 ble/array#push _ble_decode_input_buffer "${ret[@]}" done fi _ble_decode_hook_Processing=epilogue ble-decode/EPILOGUE ble/util/unlocal _ble_decode_hook_Processing local ret ble/array#pop _ble_decode_input_buffer _ble_decode_hook "$ret" fi return 0 fi ble-decode/.hook/adjust-volatile-options local IFS=$_ble_term_IFS local _ble_decode_hook_Processing=prologue ble-decode/PROLOGUE _ble_decode_hook_Processing=body if ble-decode/.check-abort "$1"; then _ble_decode_char__hook= _ble_decode_input_buffer=() _ble_decode_char_buffer=() ble/term/visible-bell "Abort by 'bleopt decode_abort_char=$bleopt_decode_abort_char'" shift fi local chars ble/array#set chars "${_ble_decode_input_buffer[@]}" "$@" _ble_decode_input_buffer=() _ble_decode_input_count=${#chars[@]} if ((_ble_decode_input_count>=200)); then local i N=${#chars[@]} local B=$((N/100)) ((B<100)) && B=100 || ((B>1000)) && B=1000 for ((i=0;i=0)); then if ((33<=key&&key<_ble_decode_FunctionKeyBase)); then local term=${_ble_term_TERM[0]+${_ble_term_TERM[${#_ble_term_TERM[@]}-1]}} if (((mod&0x01)&&0x31<=key&&key<=0x39)) && [[ $term == RLogin:* ]]; then ((key-=16,mod&=~0x01)) elif ((mod==0x01)); then if [[ $term != contra:* ]]; then ((mod&=~0x01)) fi elif ((65<=key&&key<=90)); then ((key|=0x20)) fi fi local ret ble/decode/mod2flag "$mod" ((key|=ret)) fi } function ble-decode-char/csi/.decode { local char=$1 rex key if ((char==126)); then # ~ if rex='^>?27;([0-9]+);?([0-9]+)$' && [[ $_ble_decode_csi_args =~ $rex ]]; then local param1=$((10#0${BASH_REMATCH[1]})) local param2=$((10#0${BASH_REMATCH[2]})) local key=$((param2&_ble_decode_MaskChar)) ble-decode-char/csi/.modify-key "$param1" csistat=$key return 0 fi if rex='^>?([0-9]+)(;([0-9]+))?$' && [[ $_ble_decode_csi_args =~ $rex ]]; then local param1=$((10#0${BASH_REMATCH[1]})) local param3=$((10#0${BASH_REMATCH[3]})) key=${_ble_decode_csimap_tilde[param1]} if [[ $key ]]; then ble-decode-char/csi/.modify-key "$param3" csistat=$key return 0 fi fi elif ((char==117)); then # u if rex='^([0-9]*)(;[0-9]*)?$'; [[ $_ble_decode_csi_args =~ $rex ]]; then local rematch1=${BASH_REMATCH[1]} if [[ $rematch1 != 1 ]]; then local key=$((10#0$rematch1)) mods=$((10#0${BASH_REMATCH:${#rematch1}+1})) [[ $_ble_term_TERM == kitty:* ]] && ble-decode/char/csi/.translate-kitty-csi-u ble-decode-char/csi/.modify-key "$mods" csistat=$key fi return 0 fi elif ((char==94||char==64)); then # ^, @ if rex='^[0-9]+$' && [[ $_ble_decode_csi_args =~ $rex ]]; then local param1=$((10#0${BASH_REMATCH[1]})) local param3=$((10#0${BASH_REMATCH[3]})) key=${_ble_decode_csimap_tilde[param1]} if [[ $key ]]; then ((key|=_ble_decode_Ctrl, char==64&&(key|=_ble_decode_Shft))) ble-decode-char/csi/.modify-key "$param3" csistat=$key return 0 fi fi elif ((char==99)); then # c if rex='^[?>]'; [[ $_ble_decode_csi_args =~ $rex ]]; then if [[ $_ble_decode_csi_args == '?'* ]]; then ble/term/DA1/notify "${_ble_decode_csi_args:1}" else ble/term/DA2/notify "${_ble_decode_csi_args:1}" fi csistat=$_ble_decode_KCODE_IGNORE return 0 fi elif ((char==82||char==110)); then # R or n if rex='^([0-9]+);([0-9]+)$'; [[ $_ble_decode_csi_args =~ $rex ]]; then local param1=$((10#0${BASH_REMATCH[1]})) local param2=$((10#0${BASH_REMATCH[2]})) ble/term/CPR/notify "$param1" "$param2" csistat=$_ble_decode_KCODE_IGNORE return 0 fi elif ((char==77||char==109)); then # M or m if rex='^<([0-9]+);([0-9]+);([0-9]+)$'; [[ $_ble_decode_csi_args =~ $rex ]]; then local param1=$((10#0${BASH_REMATCH[1]})) local param2=$((10#0${BASH_REMATCH[2]})) local param3=$((10#0${BASH_REMATCH[3]})) local button=$param1 ((_ble_term_mouse_button=button&~0x1C, char==109&&(_ble_term_mouse_button|=0x70), _ble_term_mouse_x=param2-1, _ble_term_mouse_y=param3-1)) local key=$_ble_decode_KCODE_MOUSE ((button&32)) && key=$_ble_decode_KCODE_MOUSE_MOVE ble-decode-char/csi/.modify-key "$((button>>2&0x07))" csistat=$key return 0 fi elif ((char==116)); then # t if rex='^<([0-9]+);([0-9]+)$'; [[ $_ble_decode_csi_args =~ $rex ]]; then local param1=$((10#0${BASH_REMATCH[1]})) local param2=$((10#0${BASH_REMATCH[2]})) ((_ble_term_mouse_button=128, _ble_term_mouse_x=param1-1, _ble_term_mouse_y=param2-1)) local key=$_ble_decode_KCODE_MOUSE csistat=$key fi fi key=${_ble_decode_csimap_alpha[char]} if [[ $key ]]; then if rex='^(1?|>?1;([0-9]+))$' && [[ $_ble_decode_csi_args =~ $rex ]]; then local param2=$((10#0${BASH_REMATCH[2]})) ble-decode-char/csi/.modify-key "$param2" csistat=$key return 0 fi fi csistat=$_ble_decode_KCODE_ERROR } function ble-decode-char/csi/consume { csistat= ((_ble_decode_csi_mode==0&&$1!=27&&$1!=155)) && return 1 local char=$1 case $_ble_decode_csi_mode in (0) ((_ble_decode_csi_mode=$1==155?2:1)) _ble_decode_csi_args= csistat=_ ;; (1) if ((char!=91)); then _ble_decode_csi_mode=0 return 1 else _ble_decode_csi_mode=2 _ble_decode_csi_args= csistat=_ fi ;; (2) if ((32<=char&&char<64)); then local ret; ble/util/c2s "$char" _ble_decode_csi_args=$_ble_decode_csi_args$ret csistat=_ elif ((64<=char&&char<127)); then _ble_decode_csi_mode=0 ble-decode-char/csi/.decode "$char" ((csistat==27)) && csistat=$_ble_decode_IsolatedESC else _ble_decode_csi_mode=0 fi ;; esac } _ble_decode_char_buffer=() function ble/decode/has-input-for-char { ((_ble_decode_input_count)) || ble/util/is-stdin-ready || ble/encoding:"$bleopt_input_encoding"/is-intermediate } _ble_decode_char__hook= _ble_decode_cmap_=() _ble_decode_char2_seq= _ble_decode_char2_reach_key= _ble_decode_char2_reach_seq= _ble_decode_char2_modifier= _ble_decode_char2_modkcode= _ble_decode_char2_modseq=() function ble-decode-char { if [[ $ble_decode_char_nest && ! $ble_decode_char_sync ]]; then ble/array#push _ble_decode_char_buffer "$@" return 148 fi local ble_decode_char_nest=1 local iloop=0 local ble_decode_char_total=$# local ble_decode_char_rest=$# local ble_decode_char_char= local chars ichar char ent chars=("$@") ichar=0 while if ((iloop++%50==0)); then ((iloop>=200)) && builtin eval -- "$_ble_decode_show_progress_hook" if [[ ! $ble_decode_char_sync ]] && ble/decode/has-input-for-char; then ble/array#push _ble_decode_char_buffer "${chars[@]:ichar}" return 148 fi fi if ((${#_ble_decode_char_buffer[@]})); then ((ble_decode_char_total+=${#_ble_decode_char_buffer[@]})) ((ble_decode_char_rest+=${#_ble_decode_char_buffer[@]})) ble/array#set chars "${_ble_decode_char_buffer[@]}" "${chars[@]:ichar}" ichar=0 _ble_decode_char_buffer=() fi ((ble_decode_char_rest)) do char=${chars[ichar]} ble_decode_char_char=$char # 補正前 char (_ble_decode_Macr 判定の為) ((ble_decode_char_rest--,ichar++)) ((_ble_debug_keylog_enabled)) && ble/array#push _ble_debug_keylog_chars "$char" if [[ $_ble_decode_keylog_chars_enabled ]]; then if ! ((char&_ble_decode_Macr)); then ble/array#push _ble_decode_keylog_chars "$char" ((_ble_decode_keylog_chars_count++)) fi fi ((char&=~_ble_decode_Macr)) if ((char&_ble_decode_Erro)); then ((char&=~_ble_decode_Erro)) if [[ $bleopt_decode_error_char_vbell ]]; then local name; ble/util/sprintf name 'U+%04x' "$char" ble/term/visible-bell "received a misencoded char $name" fi [[ $bleopt_decode_error_char_abell ]] && ble/term/audible-bell [[ $bleopt_decode_error_char_discard ]] && continue fi if [[ $_ble_decode_char__hook ]]; then ((char==_ble_decode_IsolatedESC)) && char=27 # isolated ESC -> ESC local hook=$_ble_decode_char__hook _ble_decode_char__hook= ble-decode/widget/.call-async-read "$hook $char" "$char" continue fi ble-decode-char/.getent # -> ent if [[ ! $ent ]]; then if [[ $_ble_decode_char2_reach_key ]]; then local key=$_ble_decode_char2_reach_key local seq=$_ble_decode_char2_reach_seq local rest=${_ble_decode_char2_seq:${#seq}} ble/string#split-words rest "${rest//_/ } $ble_decode_char_char" _ble_decode_char2_seq= _ble_decode_char2_reach_key= _ble_decode_char2_reach_seq= ble-decode-char/csi/clear ble/decode/send-unmodified-key "$key" "$seq" ((ble_decode_char_total+=${#rest[@]})) ((ble_decode_char_rest+=${#rest[@]})) chars=("${rest[@]}" "${chars[@]:ichar}") ichar=0 else local ret ble/decode/process-char/.convert-c0 "$char" ble/decode/send-unmodified-key "$ret" "_$char" fi elif [[ $ent == *_ ]]; then _ble_decode_char2_seq=${_ble_decode_char2_seq}_$char if [[ ${ent%_} ]]; then _ble_decode_char2_reach_key=${ent%_} _ble_decode_char2_reach_seq=$_ble_decode_char2_seq elif [[ ! $_ble_decode_char2_reach_key ]]; then local ret ble/decode/process-char/.convert-c0 "$char" _ble_decode_char2_reach_key=$ret _ble_decode_char2_reach_seq=$_ble_decode_char2_seq fi else local seq=${_ble_decode_char2_seq}_$char _ble_decode_char2_seq= _ble_decode_char2_reach_key= _ble_decode_char2_reach_seq= ble-decode-char/csi/clear ble/decode/send-unmodified-key "$ent" "$seq" fi done return 0 } function ble/decode/char-hook/next-char { ((ble_decode_char_rest)) || return 1 ((char=chars[ichar]&~_ble_decode_Macr)) ((char&_ble_decode_Erro)) && return 1 ((iloop%1000==0)) && return 1 ((char==_ble_decode_IsolatedESC)) && char=27 ((ble_decode_char_rest--,ichar++,iloop++)) return 0 } function ble-decode-char/.getent { builtin eval "ent=\${_ble_decode_cmap_$_ble_decode_char2_seq[char]-}" if [[ $ent == ?*_ || $ent == _ && $_ble_decode_char2_seq == _27 ]]; then ble/decode/wait-input 5 char || ent=${ent%_} fi local csistat= ble-decode-char/csi/consume "$char" if [[ $csistat && ! ${ent%_} ]]; then if ((csistat==_ble_decode_KCODE_ERROR)); then if [[ $bleopt_decode_error_cseq_vbell ]]; then local ret; ble-decode-unkbd ${_ble_decode_char2_seq//_/ } $char ble/term/visible-bell "unrecognized CSI sequence: $ret" fi [[ $bleopt_decode_error_cseq_abell ]] && ble/term/audible-bell if [[ $bleopt_decode_error_cseq_discard ]]; then csistat=$_ble_decode_KCODE_IGNORE else csistat= fi fi if [[ ! $ent ]]; then ent=$csistat else ent=${csistat%_}_ fi fi } function ble/decode/process-char/.convert-c0 { ret=$1 if ((0<=ret&&ret<32)); then ((ret|=(ret==0||ret>26?64:96)|_ble_decode_Ctrl)) elif ((ret==127)); then # C-? ((ret=63|_ble_decode_Ctrl)) fi } function ble/decode/send-unmodified-key/.add-modifier { local mflag1=$1 mflag=$_ble_decode_char2_modifier if ((mflag1&mflag)); then return 1 else ((_ble_decode_char2_modkcode=key|mflag, _ble_decode_char2_modifier=mflag1|mflag)) ble/array#push _ble_decode_char2_modseq "${seq[@]}" return 0 fi } function ble/decode/send-unmodified-key { local key=$1 ((key==_ble_decode_KCODE_IGNORE)) && return 0 local seq ble/string#split-words seq "${2//_/ }" ((seq[0]==_ble_decode_IsolatedESC)) && seq[0]=27 if [[ $2 == _27 ]]; then ble/decode/send-unmodified-key/.add-modifier "$_ble_decode_Meta" && return 0 fi if if ((key==_ble_decode_IsolatedESC)); then if [[ $2 == "_$_ble_decode_IsolatedESC" ]]; then key=$((_ble_decode_Ctrl|91)) else key=27 fi else ((key==27)) fi then if ! ble/decode/uses-isolated-esc; then ble/decode/send-unmodified-key/.add-modifier "$_ble_decode_Meta" && return 0 fi fi if ((_ble_decode_KCODE_SHIFT<=key&&key<=_ble_decode_KCODE_HYPER)); then case $1 in ($_ble_decode_KCODE_SHIFT) ble/decode/send-unmodified-key/.add-modifier "$_ble_decode_Shft" && return 0 ;; ($_ble_decode_KCODE_CONTROL) ble/decode/send-unmodified-key/.add-modifier "$_ble_decode_Ctrl" && return 0 ;; ($_ble_decode_KCODE_ALTER) ble/decode/send-unmodified-key/.add-modifier "$_ble_decode_Altr" && return 0 ;; ($_ble_decode_KCODE_META) ble/decode/send-unmodified-key/.add-modifier "$_ble_decode_Meta" && return 0 ;; ($_ble_decode_KCODE_SUPER) ble/decode/send-unmodified-key/.add-modifier "$_ble_decode_Supr" && return 0 ;; ($_ble_decode_KCODE_HYPER) ble/decode/send-unmodified-key/.add-modifier "$_ble_decode_Hypr" && return 0 ;; esac fi if [[ $_ble_decode_char2_modifier ]]; then local mflag mcode mseq mflag=$_ble_decode_char2_modifier mcode=$_ble_decode_char2_modkcode mseq=("${_ble_decode_char2_modseq[@]}") _ble_decode_char2_modifier= _ble_decode_char2_modkcode= _ble_decode_char2_modseq=() if ((key&mflag)); then local _ble_decode_key__chars _ble_decode_key__chars=("${mseq[@]}") ble-decode-key "$mcode" else seq=("${mseq[@]}" "${seq[@]}") ((key|=mflag)) fi fi local _ble_decode_key__chars _ble_decode_key__chars=("${seq[@]}") ble-decode-key "$key" } function ble-decode-char/is-intermediate { [[ $_ble_decode_char2_seq ]]; } function ble-decode-char/bind { local -a seq; ble/string#split-words seq "$1" local kc=$2 local i iN=${#seq[@]} char tseq= for ((i=0;i| "$delay" fi } function ble/decode/keymap#load { local opts=:$2: ble/decode/keymap#registered "$1" && return 0 local init=ble-decode/keymap:$1/define ble/is-function "$init" || return 1 ble/decode/keymap#.register "$1" local ble_bind_keymap=$1 if ! "$init" || ble/decode/keymap#is-empty "$1"; then ble/decode/keymap#.unregister "$1" return 1 fi [[ $opts == *:dump:* ]] && ble/decode/keymap#dump "$1" >&3 ble/decode/keymap#.onload "$1" return 0 } function ble/decode/keymap#unload { if (($#==0)); then local list; ble/string#split-words list "${_ble_decode_keymap_list//:/ }" set -- "${list[@]}" fi while (($#)); do local array_names array_name builtin eval -- "array_names=(\"\${!_ble_decode_${1}_kmap_@}\")" for array_name in "${array_names[@]}"; do builtin unset -v "$array_name" done ble/decode/keymap#.unregister "$1" shift done } if [[ ${_ble_decode_kmaps-} ]]; then function ble/decode/keymap/cleanup-old-keymaps { local -a list=() local var for var in "${!_ble_decode_@}"; do [[ $var == _ble_decode_*_kmap_ ]] || continue var=${var#_ble_decode_} var=${var%_kmap_} ble/array#push list "$var" done local keymap_name for keymap_name in "${list[@]}"; do ble/decode/keymap#unload "$keymap_name" done builtin unset -v _ble_decode_kmaps } ble/decode/keymap/cleanup-old-keymaps fi function ble/decode/keymap#dump { if (($#)); then local kmap=$1 arrays builtin eval "arrays=(\"\${!_ble_decode_${kmap}_kmap_@}\")" ble/util/print "ble/decode/keymap#.register $kmap" ble/util/declare-print-definitions "${arrays[@]}" ble/util/print "ble/decode/keymap#.onload $kmap" else local list; ble/string#split-words list "${_ble_decode_keymap_list//:/ }" local keymap_name for keymap_name in "${list[@]}"; do ble/decode/keymap#dump "$keymap_name" done fi } function ble-decode/GET_BASEMAP { [[ $1 == -v ]] || return 1 local ret; bleopt/get:default_keymap [[ $ret == vi ]] && ret=vi_imap builtin eval "$2=\$ret" } function ble-decode/INITIALIZE_DEFMAP { ble-decode/GET_BASEMAP "$@" && ble/decode/keymap#load "${!2}" && return 0 ble/decode/keymap#load safe && builtin eval -- "$2=safe" && bleopt_default_keymap=safe } function ble/widget/.SHELL_COMMAND { local IFS=$_ble_term_IFS; builtin eval -- "$*"; } function ble/widget/.EDIT_COMMAND { local IFS=$_ble_term_IFS; builtin eval -- "$*"; } function ble-decode-key/bind { if ! ble/decode/keymap#registered "$1"; then ble/util/print-quoted-command "$FUNCNAME" "$@" >> "$_ble_base_run/$$.bind.delay.$1" return 0 fi local kmap=$1 keys=$2 cmd=$3 if local widget=${cmd%%[$_ble_term_IFS]*}; ! ble/is-function "$widget"; then local message="ble-bind: Unknown widget \`${widget#'ble/widget/'}'." [[ $command == ble/widget/ble/widget/* ]] && message="$message Note: The prefix 'ble/widget/' is redundant." ble/util/print "$message" >&2 return 1 fi local dicthead=_ble_decode_${kmap}_kmap_ local -a seq; ble/string#split-words seq "$keys" local i iN=${#seq[@]} tseq= for ((i=0;i> "$_ble_base_run/$$.bind.delay.$1" return 0 fi local kmap=$1 keys=$2 timeout=$3 local dicthead=_ble_decode_${kmap}_kmap_ local -a seq; ble/string#split-words seq "$keys" [[ $timeout == - ]] && timeout= local i iN=${#seq[@]} local key=${seq[iN-1]} local tseq= for ((i=0;i&2 return 1 fi } function ble-decode-key/unbind { if ! ble/decode/keymap#registered "$1"; then ble/util/print-quoted-command "$FUNCNAME" "$@" >> "$_ble_base_run/$$.bind.delay.$1" return 0 fi local kmap=$1 keys=$2 local dicthead=_ble_decode_${kmap}_kmap_ local -a seq; ble/string#split-words seq "$keys" local i iN=${#seq[@]} local key=${seq[iN-1]} local tseq= for ((i=0;i> "$_ble_base_run/$$.bind.delay.$keymap" return 0 fi builtin eval "_ble_decode_${keymap}_kmap_cursor=\$cursor" if [[ $keymap == "$_ble_decode_keymap" && $cursor ]]; then ble/term/cursor-state/set-internal "$((cursor))" fi } function ble/decode/keymap#print { local kmap if (($#==0)); then for kmap in ${_ble_decode_keymap_list//:/ }; do ble/util/print "$sgrc# keymap $kmap$sgr0" ble/decode/keymap#print "$kmap" done return 0 fi [[ $ble_bind_print ]] || local sgr0= sgrf= sgrq= sgrc= sgro= local kmap=$1 tseq=$2 nseq=$3 local dicthead=_ble_decode_${kmap}_kmap_ local kmapopt= [[ $kmap ]] && kmapopt=" $sgro-m$sgr0 $sgrq'$kmap'$sgr0" local q=\' Q="'\''" local key keys builtin eval "keys=(\${!$dicthead$tseq[@]})" for key in "${keys[@]}"; do local ret; ble-decode-unkbd "$key" local knames=$nseq${nseq:+ }$ret builtin eval "local ent=\${$dicthead$tseq[key]}" local qknames if [[ $sgrq ]]; then ble/string#quote-word "$knames" quote-empty:sgrq="$sgrq":sgr0="$sgr0"; qknames=$ret else qknames="'${knames//$q/$Q}'" fi if [[ $ent == *:* ]]; then local cmd=${ent#*:} local o v case $cmd in ('ble/widget/.SHELL_COMMAND '*) o=c v=${cmd#'ble/widget/.SHELL_COMMAND '}; builtin eval "v=$v" ;; ('ble/widget/.EDIT_COMMAND '*) o=x v=${cmd#'ble/widget/.EDIT_COMMAND '} ; builtin eval "v=$v" ;; ('ble/widget/.MACRO '*) o=s; ble/util/chars2keyseq ${cmd#*' '}; v=$ret ;; ('ble/widget/'*) o=f v=${cmd#ble/widget/} ;; (*) o=@ v=$cmd ;; esac local qv if [[ $sgrq ]]; then ble/string#quote-word "$v" quote-empty:sgrq="$sgrq":sgr0="$sgr0"; qv=$ret else qv="'${v//$q/$Q}'" fi ble/util/print "${sgrf}ble-bind$sgr0$kmapopt $sgro-$o$sgr0 $qknames $qv" fi if [[ ${ent::1} == _ ]]; then ble/decode/keymap#print "$kmap" "${tseq}_$key" "$knames" if [[ $ent == _[0-9]* ]]; then local timeout=${ent%%:*}; timeout=${timeout:1} ble/util/print "${sgrf}ble-bind$sgr0$kmapopt $sgro-T$sgr0 $qknames $timeout" fi fi done } _ble_decode_keymap= _ble_decode_keymap_stack=() function ble/decode/keymap/push { if ble/decode/keymap#registered "$1"; then ble/array#push _ble_decode_keymap_stack "$_ble_decode_keymap" _ble_decode_keymap=$1 local cursor; ble/decode/keymap#get-cursor "$1" [[ $cursor ]] && ble/term/cursor-state/set-internal "$((cursor))" return 0 elif ble/decode/keymap#load "$1" && ble/decode/keymap#registered "$1"; then ble/decode/keymap/push "$1" # 再実行 else ble/util/print "[ble: keymap '$1' not found]" >&2 return 1 fi } function ble/decode/keymap/pop { local count=${#_ble_decode_keymap_stack[@]} local last=$((count-1)) ble/util/assert '((last>=0))' || return 1 local cursor ble/decode/keymap#get-cursor "$_ble_decode_keymap" if [[ $cursor ]]; then local i for ((i=last;i>=0;i--)); do ble/decode/keymap#get-cursor "${_ble_decode_keymap_stack[i]}" [[ $cursor ]] && break done ble/term/cursor-state/set-internal "$((${cursor:-0}))" fi local old_keymap=_ble_decode_keymap _ble_decode_keymap=${_ble_decode_keymap_stack[last]} builtin unset -v '_ble_decode_keymap_stack[last]' } function ble/decode/keymap/get-parent { local len=${#_ble_decode_keymap_stack[@]} if ((len)); then ret=${_ble_decode_keymap_stack[len-1]} else ret= fi } _ble_decode_key__chars=() _ble_decode_key__seq= _ble_decode_key__hook= function ble-decode-key/is-intermediate { [[ $_ble_decode_key__seq ]]; } _ble_decode_key_batch=() function ble-decode-key/batch/flush { ((${#_ble_decode_key_batch[@]})) || return 1 local dicthead=_ble_decode_${_ble_decode_keymap}_kmap_ builtin eval "local command=\${${dicthead}[_ble_decode_KCODE_BATCH_CHAR]-}" command=${command:2} if [[ $command ]]; then local chars; chars=("${_ble_decode_key_batch[@]}") _ble_decode_key_batch=() ble/decode/widget/call-interactively "$command" "${chars[@]}"; local ext=$? ((ext!=125)) && return 0 fi ble/decode/widget/call-interactively ble/widget/__batch_char__.default "${chars[@]}"; local ext=$? return "$ext" } function ble/widget/__batch_char__.default { builtin eval "local widget_defchar=\${${dicthead}[_ble_decode_KCODE_DEFCHAR]-}" widget_defchar=${widget_defchar:2} builtin eval "local widget_default=\${${dicthead}[_ble_decode_KCODE_DEFAULT]-}" widget_default=${widget_default:2} local -a unprocessed_chars=() local key command for key in "${KEYS[@]}"; do if [[ $widget_defchar ]]; then ble/decode/widget/call-interactively "$widget_defchar" "$key"; local ext=$? ((ext!=125)) && continue fi if [[ $widget_default ]]; then ble/decode/widget/call-interactively "$widget_default" "$key"; local ext=$? ((ext!=125)) && continue fi ble/array#push unprocessed_chars "$key" done if ((${#unprocessed_chars[@]})); then local ret; ble-decode-unkbd "${unprocessed_chars[@]}" [[ $bleopt_decode_error_kseq_vbell ]] && ble/term/visible-bell "unprocessed chars: $ret" [[ $bleopt_decode_error_kseq_abell ]] && ble/term/audible-bell fi return 0 } function ble-decode-key { local CHARS CHARS=("${_ble_decode_key__chars[@]}") local key while (($#)); do key=$1; shift ((_ble_debug_keylog_enabled)) && ble/array#push _ble_debug_keylog_keys "$key" if [[ $_ble_decode_keylog_keys_enabled && $_ble_decode_keylog_depth == 0 ]]; then ble/array#push _ble_decode_keylog_keys "$key" ((_ble_decode_keylog_keys_count++)) fi local dicthead=_ble_decode_${_ble_decode_keymap}_kmap_ if (((key&_ble_decode_MaskChar)==_ble_decode_KCODE_MOUSE_MOVE)); then builtin eval "local command=\${${dicthead}[key]-}" command=${command:2} ble-decode/widget/.call-keyseq continue fi if [[ $_ble_decode_key__hook ]]; then local hook=$_ble_decode_key__hook _ble_decode_key__hook= ble-decode/widget/.call-async-read "$hook $key" "$key" continue fi builtin eval "local ent=\${$dicthead$_ble_decode_key__seq[key]-}" if [[ $ent == _[0-9]* ]]; then local node_type=_ if (($#==0)) && ! ble/decode/has-input; then local timeout=${ent%%:*}; timeout=${timeout:1} ble/decode/wait-input "$timeout" || node_type=1 fi if [[ $ent == *:* ]]; then ent=$node_type:${ent#*:} else ent=$node_type fi fi if [[ $ent == 1:* ]]; then local command=${ent:2} if [[ $command ]]; then ble-decode/widget/.call-keyseq else _ble_decode_key__seq= fi elif [[ $ent == _ || $ent == _:* ]]; then _ble_decode_key__seq=${_ble_decode_key__seq}_$key else ble-decode-key/.invoke-partial-match "$key" && continue local kseq=${_ble_decode_key__seq}_$key ret ble-decode-unkbd "${kseq//_/ }" local kspecs=$ret [[ $bleopt_decode_error_kseq_vbell ]] && ble/term/visible-bell "unbound keyseq: $kspecs" [[ $bleopt_decode_error_kseq_abell ]] && ble/term/audible-bell if [[ $_ble_decode_key__seq ]]; then if [[ $bleopt_decode_error_kseq_discard ]]; then _ble_decode_key__seq= else local -a keys ble/string#split-words keys "${_ble_decode_key__seq//_/ } $key" _ble_decode_key__seq= ble-decode-key "${keys[@]:1}" fi fi fi done if ((${#_ble_decode_key_batch[@]})); then if ! ble/decode/has-input || ((${#_ble_decode_key_batch[@]}>=50)); then ble-decode-key/batch/flush fi fi return 0 } function ble-decode-key/.invoke-partial-match { local dicthead=_ble_decode_${_ble_decode_keymap}_kmap_ local next=$1 if [[ $_ble_decode_key__seq ]]; then local last=${_ble_decode_key__seq##*_} _ble_decode_key__seq=${_ble_decode_key__seq%_*} builtin eval "local ent=\${$dicthead$_ble_decode_key__seq[last]-}" if [[ $ent == _*:* ]]; then local command=${ent#*:} if [[ $command ]]; then ble-decode/widget/.call-keyseq else _ble_decode_key__seq= fi ble-decode-key "$next" return 0 else # ent = _ if ble-decode-key/.invoke-partial-match "$last"; then ble-decode-key "$next" return 0 else _ble_decode_key__seq=${_ble_decode_key__seq}_$last return 1 fi fi else local key=$1 if ble-decode-key/ischar "$key"; then if ble/decode/has-input && builtin eval "[[ \${${dicthead}[_ble_decode_KCODE_BATCH_CHAR]-} ]]"; then ble/array#push _ble_decode_key_batch "$key" return 0 fi builtin eval "local command=\${${dicthead}[_ble_decode_KCODE_DEFCHAR]-}" command=${command:2} if [[ $command ]]; then local seq_save=$_ble_decode_key__seq ble-decode/widget/.call-keyseq; local ext=$? ((ext!=125)) && return 0 _ble_decode_key__seq=$seq_save # 125 の時はまた元に戻して次の試行を行う fi fi builtin eval "local command=\${${dicthead}[_ble_decode_KCODE_DEFAULT]-}" command=${command:2} ble-decode/widget/.call-keyseq; local ext=$? ((ext!=125)) && return 0 return 1 fi } function ble-decode-key/ischar { local key=$1 (((key&_ble_decode_MaskFlag)==0&&32<=key&&key<_ble_decode_FunctionKeyBase)) } _ble_decode_widget_last= function ble-decode/widget/.invoke-hook { local key=$1 local dicthead=_ble_decode_${_ble_decode_keymap}_kmap_ builtin eval "local hook=\${$dicthead[key]-}" hook=${hook:2} [[ $hook ]] && builtin eval -- "$hook" } function ble-decode/widget/.call-keyseq { ble-decode-key/batch/flush [[ $command ]] || return 125 local _ble_decode_keylog_depth=$((_ble_decode_keylog_depth+1)) local WIDGET=$command KEYMAP=$_ble_decode_keymap LASTWIDGET=$_ble_decode_widget_last local -a KEYS; ble/string#split-words KEYS "${_ble_decode_key__seq//_/ } $key" _ble_decode_widget_last=$WIDGET _ble_decode_key__seq= ble-decode/widget/.invoke-hook "$_ble_decode_KCODE_BEFORE_WIDGET" builtin eval -- "$WIDGET"; local ext=$? ble-decode/widget/.invoke-hook "$_ble_decode_KCODE_AFTER_WIDGET" ((_ble_decode_keylog_depth==1)) && _ble_decode_keylog_chars_count=0 _ble_decode_keylog_keys_count=0 return "$ext" } function ble-decode/widget/.call-async-read { local _ble_decode_keylog_depth=$((_ble_decode_keylog_depth+1)) local WIDGET=$1 KEYMAP=$_ble_decode_keymap LASTWIDGET=$_ble_decode_widget_last local -a KEYS; ble/string#split-words KEYS "$2" builtin eval -- "$WIDGET"; local ext=$? ((_ble_decode_keylog_depth==1)) && _ble_decode_keylog_chars_count=0 _ble_decode_keylog_keys_count=0 return "$ext" } function ble/decode/widget/call-interactively { local WIDGET=$1 KEYMAP=$_ble_decode_keymap LASTWIDGET=$_ble_decode_widget_last local -a KEYS; KEYS=("${@:2}") _ble_decode_widget_last=$WIDGET ble-decode/widget/.invoke-hook "$_ble_decode_KCODE_BEFORE_WIDGET" builtin eval -- "$WIDGET"; local ext=$? ble-decode/widget/.invoke-hook "$_ble_decode_KCODE_AFTER_WIDGET" return "$ext" } function ble/decode/widget/call { local WIDGET=$1 KEYMAP=$_ble_decode_keymap LASTWIDGET=$_ble_decode_widget_last local -a KEYS; KEYS=("${@:2}") _ble_decode_widget_last=$WIDGET builtin eval -- "$WIDGET" } function ble/decode/widget/dispatch { local ret; ble/string#quote-command "ble/widget/${1#ble/widget/}" "${@:2}" local WIDGET=$ret _ble_decode_widget_last=$WIDGET builtin eval -- "$WIDGET" } function ble/decode/widget/suppress-widget { WIDGET= } function ble/decode/widget/redispatch-by-keys { ble/decode/widget/skip-lastwidget if ((_ble_decode_keylog_depth==1)); then ble/decode/keylog#pop _ble_decode_keylog_depth=0 fi ble-decode-key "$@" } function ble/decode/widget/redispatch { ble/decode/widget/redispatch-by-keys "${KEYS[@]}" } function ble/decode/widget/skip-lastwidget { _ble_decode_widget_last=$LASTWIDGET } function ble/decode/widget/keymap-dispatch { local name=${FUNCNAME[1]#ble/widget/} local widget=ble/widget/$_ble_decode_keymap/$name ble/is-function "$widget" || widget=ble/widget/default/$name "$widget" "$@" } function ble/decode/has-input { ((_ble_decode_input_count||ble_decode_char_rest)) || ble/util/is-stdin-ready || ble/encoding:"$bleopt_input_encoding"/is-intermediate || ble-decode-char/is-intermediate } function ble/decode/has-input-char { ((_ble_decode_input_count||ble_decode_char_rest)) || ble/util/is-stdin-ready || ble/encoding:"$bleopt_input_encoding"/is-intermediate } function ble/decode/wait-input { local timeout=$1 type=${2-} if [[ $type == char ]]; then ble/decode/has-input-char && return 0 else ble/decode/has-input && return 0 fi while ((timeout>0)); do local w=$((timeout<20?timeout:20)) ble/util/msleep "$w" ((timeout-=w)) ble/util/is-stdin-ready 0 && return 0 done return 1 } function ble/util/idle/IS_IDLE { ! ble/decode/has-input } _ble_debug_keylog_enabled=0 _ble_debug_keylog_bytes=() _ble_debug_keylog_chars=() _ble_debug_keylog_keys=() function ble/debug/keylog#start { _ble_debug_keylog_enabled=1 } function ble/debug/keylog#end { { local IFS=$_ble_term_IFS ble/util/print '===== bytes =====' ble/util/print "${_ble_debug_keylog_bytes[*]}" ble/util/print ble/util/print '===== chars =====' local ret; ble-decode-unkbd "${_ble_debug_keylog_chars[@]}" ble/string#split ret ' ' "$ret" ble/util/print "${ret[*]}" ble/util/print ble/util/print '===== keys =====' local ret; ble-decode-unkbd "${_ble_debug_keylog_keys[@]}" ble/string#split ret ' ' "$ret" ble/util/print "${ret[*]}" ble/util/print } | fold -w 40 _ble_debug_keylog_enabled=0 _ble_debug_keylog_bytes=() _ble_debug_keylog_chars=() _ble_debug_keylog_keys=() } _ble_decode_keylog_depth=0 _ble_decode_keylog_keys_enabled= _ble_decode_keylog_keys_count=0 _ble_decode_keylog_keys=() _ble_decode_keylog_chars_enabled= _ble_decode_keylog_chars_count=0 _ble_decode_keylog_chars=() function ble/decode/keylog#start { [[ $_ble_decode_keylog_keys_enabled ]] && return 1 _ble_decode_keylog_keys_enabled=${1:-1} _ble_decode_keylog_keys=() } function ble/decode/keylog#end { ret=("${_ble_decode_keylog_keys[@]}") _ble_decode_keylog_keys_enabled= _ble_decode_keylog_keys=() } function ble/decode/keylog#pop { [[ $_ble_decode_keylog_keys_enabled && $_ble_decode_keylog_depth == 1 ]] || return 1 local new_size=$((${#_ble_decode_keylog_keys[@]}-_ble_decode_keylog_keys_count)) ((new_size<0)) && new_size=0 _ble_decode_keylog_keys=("${_ble_decode_keylog_keys[@]::new_size}") _ble_decode_keylog_keys_count=0 } function ble/decode/charlog#start { [[ $_ble_decode_keylog_chars_enabled ]] && return 1 _ble_decode_keylog_chars_enabled=${1:-1} _ble_decode_keylog_chars=() } function ble/decode/charlog#end { [[ $_ble_decode_keylog_chars_enabled ]] || { ret=(); return 1; } ret=("${_ble_decode_keylog_chars[@]}") _ble_decode_keylog_chars_enabled= _ble_decode_keylog_chars=() } function ble/decode/charlog#end-exclusive { ret=() [[ $_ble_decode_keylog_chars_enabled ]] || return 1 local size=$((${#_ble_decode_keylog_chars[@]}-_ble_decode_keylog_chars_count)) ((size>0)) && ret=("${_ble_decode_keylog_chars[@]::size}") _ble_decode_keylog_chars_enabled= _ble_decode_keylog_chars=() } function ble/decode/charlog#end-exclusive-depth1 { if ((_ble_decode_keylog_depth==1)); then ble/decode/charlog#end-exclusive else ble/decode/charlog#end fi } function ble/decode/charlog#encode { local -a buff=() for char; do ((char==0)) && char=$_ble_decode_EscapedNUL ble/util/c2s "$char" ble/array#push buff "$ret" done IFS= builtin eval 'ret="${buff[*]}"' } function ble/decode/charlog#decode { local text=$1 n=${#1} i chars chars=() for ((i=0;i=bleopt_decode_macro_limit)); then ((_ble_decode_macro_count==bleopt_decode_macro_limit+1)) && ble/term/visible-bell "Macro invocation is canceled by decode_macro_limit" return 1 fi else _ble_decode_macro_count=0 fi local -a chars=() local char for char; do ble/array#push chars "$((char|_ble_decode_Macr))" done ble-decode-char "${chars[@]}" } function ble/widget/.CHARS { ble-decode-char "$@" } function ble/decode/c2dqs { local i=$1 if ((0<=i&&i<32)); then if ((1<=i&&i<=26)); then ble/util/c2s "$((i+96))" ret="\\C-$ret" elif ((i==27)); then ret="\\e" elif ((i==28)); then ret="\\x1c" else ble/decode/c2dqs "$((i+64))" ret="\\C-$ret" fi elif ((32<=i&&i<127)); then ble/util/c2s "$i" if ((i==34||i==92)); then ret='\'"$ret" fi elif ((128<=i&&i<160)); then ble/util/sprintf ret '\\%03o' "$i" else ble/util/sprintf ret '\\%03o' "$i" fi } function ble/decode/cmap/.generate-binder-template { local tseq=$1 qseq=$2 nseq=$3 depth=${4:-1} ccode local apos="'" escapos="'\\''" builtin eval "local -a ccodes; ccodes=(\${!_ble_decode_cmap_$tseq[@]})" for ccode in "${ccodes[@]}"; do local ret ble/decode/c2dqs "$ccode" local qseq1=$qseq$ret local nseq1="$nseq $ccode" builtin eval "local ent=\${_ble_decode_cmap_$tseq[ccode]}" if [[ ${ent%_} ]]; then if ((depth>=3)); then ble/util/print "\$binder \"$qseq1\" \"${nseq1# }\"" fi fi if [[ ${ent//[0-9]} == _ ]]; then ble/decode/cmap/.generate-binder-template "${tseq}_$ccode" "$qseq1" "$nseq1" "$((depth+1))" fi done } function ble/decode/cmap/.emit-bindx { local q="'" Q="'\''" ble/util/print "builtin bind -x '\"${1//$q/$Q}\":_ble_decode_hook $2; builtin eval -- \"\$_ble_decode_bind_hook\"'" } function ble/decode/cmap/.emit-bindr { ble/util/print "builtin bind -r \"$1\"" } _ble_decode_cmap_initialized= function ble/decode/cmap/initialize { [[ $_ble_decode_cmap_initialized ]] && return 0 _ble_decode_cmap_initialized=1 local init=$_ble_base/lib/init-cmap.sh local dump=$_ble_base_cache/decode.cmap.$_ble_decode_kbd_ver.$TERM.dump if [[ -s $dump && $dump -nt $init ]]; then source "$dump" else ble/edit/info/immediate-show text 'ble.sh: generating "'"$dump"'"...' source "$init" ble-bind -D | ble/bin/awk ' { sub(/^declare +(-[aAilucnrtxfFgGI]+ +)?/, ""); sub(/^-- +/, ""); } /^_ble_decode_(cmap|csimap|kbd)/ { if (!($0 ~ /^_ble_decode_csimap_kitty_u/)) gsub(/["'\'']/, ""); print } ' >| "$dump" fi if ((_ble_bash>=40300)); then local fbinder=$_ble_base_cache/decode.cmap.allseq _ble_decode_bind_fbinder=$fbinder if ! [[ -s $_ble_decode_bind_fbinder.bind && $_ble_decode_bind_fbinder.bind -nt $init && -s $_ble_decode_bind_fbinder.unbind && $_ble_decode_bind_fbinder.unbind -nt $init ]]; then ble/edit/info/immediate-show text 'ble.sh: initializing multi-character sequence binders... ' ble/decode/cmap/.generate-binder-template >| "$fbinder" binder=ble/decode/cmap/.emit-bindx source "$fbinder" >| "$fbinder.bind" binder=ble/decode/cmap/.emit-bindr source "$fbinder" >| "$fbinder.unbind" ble/edit/info/immediate-show text 'ble.sh: initializing multi-character sequence binders... done' fi fi } function ble/decode/cmap/decode-chars.hook { ble/array#push ble_decode_bind_keys "$1" _ble_decode_key__hook=ble/decode/cmap/decode-chars.hook } function ble/decode/cmap/decode-chars { ble/decode/cmap/initialize local _ble_decode_csi_mode=0 local _ble_decode_csi_args= local _ble_decode_char2_seq= local _ble_decode_char2_reach_key= local _ble_decode_char2_reach_seq= local _ble_decode_char2_modifier= local _ble_decode_char2_modkcode= local -a _ble_decode_char2_modseq=() local _ble_decode_char__hook= local _ble_debug_keylog_enabled= local _ble_decode_keylog_keys_enabled= local _ble_decode_keylog_chars_enabled= local _ble_decode_show_progress_hook= local _ble_decode_erase_progress_hook= local bleopt_decode_error_cseq_abell= local bleopt_decode_error_cseq_vbell= local bleopt_decode_error_cseq_discard= local -a ble_decode_bind_keys=() local _ble_decode_key__hook=ble/decode/cmap/decode-chars.hook local ble_decode_char_sync=1 # ユーザ入力があっても中断しない ble-decode-char "$@" "$_ble_decode_KCODE_IGNORE" keys=("${ble_decode_bind_keys[@]}") if [[ $_ble_decode_char2_modkcode ]]; then ble/array#push keys "$_ble_decode_char2_modkcode" fi } _ble_decode_bind_hook= _ble_decode_bind__uvwflag= function ble/decode/readline/adjust-uvw { [[ $_ble_decode_bind__uvwflag ]] && return 0 _ble_decode_bind__uvwflag=1 builtin bind -x $'"\025":_ble_decode_hook 21; builtin eval -- "$_ble_decode_bind_hook"' # ^U builtin bind -x $'"\026":_ble_decode_hook 22; builtin eval -- "$_ble_decode_bind_hook"' # ^V builtin bind -x $'"\027":_ble_decode_hook 23; builtin eval -- "$_ble_decode_bind_hook"' # ^W builtin bind -x $'"\177":_ble_decode_hook 127; builtin eval -- "$_ble_decode_bind_hook"' # ^? builtin bind -x $'"\010":_ble_decode_hook 8; builtin eval -- "$_ble_decode_bind_hook"' # ^H } if ((_ble_bash>=50100)); then function ble/base/workaround-POSIXLY_CORRECT { [[ $_ble_decode_bind_state == none ]] && return 0 builtin bind -x '"\C-i":_ble_decode_hook 9; builtin eval -- "$_ble_decode_bind_hook"' } fi function ble/decode/readline/.generate-source-to-unbind-default { { if ((_ble_bash>=40300)); then ble/util/print '__BINDX__' builtin bind -X fi ble/util/print '__BINDP__' builtin bind -sp } | ble/decode/readline/.generate-source-to-unbind-default/.process } 2>/dev/null function ble/decode/readline/.generate-source-to-unbind-default/.process { local q=\' Q="'\''" LC_ALL=C ble/bin/awk -v q="$q" ' BEGIN { IS_XPG4 = AWKTYPE == "xpg4"; rep_Q = str2rep(q "\\" q q); rep_bslash = str2rep("\\"); rep_kseq_1c5c = str2rep("\"\\x1c\\x5c\""); rep_kseq_1c = str2rep("\"\\x1c\""); mode = 1; } function str2rep(str) { if (IS_XPG4) sub(/\\/, "\\\\\\\\", str); return str; } function quote(text) { gsub(q, rep_Q, text); return q text q; } function unescape_control_modifier(str, _, i, esc, chr) { for (i = 0; i < 32; i++) { if (i == 0 || i == 31) esc = sprintf("\\\\C-%c", i + 64); else if (27 <= i && i <= 30) esc = sprintf("\\\\C-\\%c", i + 64); else esc = sprintf("\\\\C-%c", i + 96); chr = sprintf("%c", i); gsub(esc, chr, str); } gsub(/\\C-\?/, sprintf("%c", 127), str); return str; } function unescape(str) { if (str ~ /\\C-/) str = unescape_control_modifier(str); gsub(/\\e/, sprintf("%c", 27), str); gsub(/\\"/, "\"", str); gsub(/\\\\/, rep_bslash, str); return str; } function output_bindr(line0, _seq) { if (match(line0, /^"(([^"\\]|\\.)+)"/) > 0) { _seq = substr(line0, 2, RLENGTH - 2); gsub(/\\M-/, "\\e", _seq); print "builtin bind -r " quote(_seq); } } /^__BINDP__$/ { mode = 1; next; } /^__BINDX__$/ { mode = 2; next; } mode == 1 && $0 ~ /^"/ { sub(/^"\\C-\\\\\\"/, rep_kseq_1c5c); sub(/^"\\C-\\\\?"/, rep_kseq_1c); output_bindr($0); print "builtin bind " quote($0) > "/dev/stderr"; } mode == 2 && $0 ~ /^"/ { output_bindr($0); line = $0; if (line ~ /(^|[^[:alnum:]])(ble-decode\/.hook|_ble_decode_hook)($|[^[:alnum:]])/) next; if (match(line, /^("([^"\\]|\\.)*":) "(([^"\\]|\\.)*)"/) > 0) { rlen = RLENGTH; match(line, /^"([^"\\]|\\.)*":/); rlen1 = RLENGTH; rlen2 = rlen - rlen1 - 3; sequence = substr(line, 1 , rlen1); command = substr(line, rlen1 + 3, rlen2); if (command ~ /\\/) command = unescape(command); line = sequence command; } print "builtin bind -x " quote(line) > "/dev/stderr"; } ' 2>| "$_ble_base_run/$$.bind.save" } _ble_decode_bind_state=none _ble_decode_bind_bindp= _ble_decode_bind_encoding= function ble/decode/readline/bind { _ble_decode_bind_encoding=$bleopt_input_encoding local file=$_ble_base_cache/decode.bind.$_ble_bash.$_ble_decode_bind_encoding.bind [[ -s $file && $file -nt $_ble_base/lib/init-bind.sh ]] || source "$_ble_base/lib/init-bind.sh" ble/term/rl-convert-meta/enter source "$file" _ble_decode_bind__uvwflag= ble/util/assign _ble_decode_bind_bindp 'builtin bind -p' # TERM 変更検出用 } function ble/decode/readline/unbind { ble/function#try ble/encoding:"$bleopt_input_encoding"/clear source "$_ble_base_cache/decode.bind.$_ble_bash.$_ble_decode_bind_encoding.unbind" } function ble/decode/readline/rebind { [[ $_ble_decode_bind_state == none ]] && return 0 ble/decode/readline/unbind ble/decode/readline/bind } function ble/decode/bind/.initialize-kmap { [[ $kmap ]] && return 0 ble-decode/GET_BASEMAP -v kmap if ! ble/decode/is-keymap "$kmap"; then ble/util/print "ble-bind: the default keymap '$kmap' is unknown." >&2 flags=R$flags return 1 fi return 0 } function ble/decode/bind/option:help { ble/util/cat <=1)) || return 0 if [[ $3 ]]; then ((req--)) ble/array#push optarg "${4-$3}" fi ((req>=1)) || return 0 if ((${#args[@]}-iarg&2 else ble/util/print "ble-bind: the option \`$label' requires $req arguments." >&2 fi return 2 fi ble/array#push optarg "${args[@]:iarg:req}" ((iarg+=req)) return 0 } function ble/decode/bind/option:csi { local ret key= if [[ $2 ]]; then ble-decode-kbd "$2" ble/string#split-words key "$ret" if ((${#key[@]}!=1)); then ble/util/print "ble-bind --csi: the second argument is not a single key!" >&2 return 1 elif ((key&~_ble_decode_MaskChar)); then ble/util/print "ble-bind --csi: the second argument should not have modifiers!" >&2 return 1 fi fi local rex if rex='^([1-9][0-9]*)~$' && [[ $1 =~ $rex ]]; then _ble_decode_csimap_tilde[BASH_REMATCH[1]]=$key if [[ ! ${_ble_decode_csimap_dict[key]} ]]; then _ble_decode_csimap_dict[key]=tilde:${BASH_REMATCH[1]} fi local -a cseq cseq=(27 91) local ret i iN num="${BASH_REMATCH[1]}\$" for ((i=0,iN=${#num};i&2 return 1 fi } function ble/decode/bind/option:list-widgets { declare -f | ble/bin/sed -n 's/^ble\/widget\/\([a-zA-Z][^.[:space:]();&|]\{1,\}\)[[:space:]]*()[[:space:]]*$/\1/p' } function ble/decode/bind/option:dump { if (($#)); then local keymap for keymap; do ble/decode/keymap#dump "$keymap" done else ble/util/declare-print-definitions "${!_ble_decode_kbd__@}" "${!_ble_decode_cmap_@}" "${!_ble_decode_csimap_@}" ble/decode/keymap#dump fi } function ble/decode/bind/option:print { local ble_bind_print=1 local sgr0= sgrf= sgrq= sgrc= sgro= if [[ $flags == *c* || $flags != *n* && -t 1 ]]; then local ret ble/color/face2sgr command_function; sgrf=$ret ble/color/face2sgr syntax_quoted; sgrq=$ret ble/color/face2sgr syntax_comment; sgrc=$ret ble/color/face2sgr argument_option; sgro=$ret sgr0=$_ble_term_sgr0 fi local keymap ble-decode/INITIALIZE_DEFMAP -v keymap # 初期化を強制する if (($#)); then for keymap; do ble/decode/keymap#print "$keymap" done else ble-decode-char/csi/print ble-decode-char/print ble/decode/keymap#print fi } function ble-bind { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" ble/decode/bind "$@" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" } function ble/decode/bind { local set shopt [[ $_ble_bash_options_adjusted ]] || ble/base/.adjust-bash-options set shopt local IFS=$_ble_term_IFS q=\' Q="''\'" local flags= kmap=${ble_bind_keymap-} ret local -a keymaps; keymaps=() ble/decode/initialize local -a args args=("$@") local iarg=0 arg c optarg while ((iarg<$#)); do local arg=${args[iarg++]} if [[ $arg == --?* ]]; then local name=${arg:2} has_optarg= optarg= if [[ $name == *=* ]]; then has_optarg=set optarg=${name#*=} name=${name%%=*} fi case $name in (color) if [[ ! $has_optarg || $optarg == always ]]; then flags=c${flags//[cn]} elif [[ $optarg == never ]]; then flags=n${flags//[cn]} elif [[ $optarg == auto ]]; then flags=${flags//[cn]} else flags=E$flags ble/util/print "ble-bind: unrecognized color '--color=$optarg'." >&2 fi ;; (help) ble/decode/bind/option:help flags=D$flags ;; (csi) flags=D$flags ble/decode/bind/get-optarg --csi 2 "$has_optarg" "$optarg" || break ble/decode/bind/option:csi "${optarg[0]}" "${optarg[1]}" ;; (cursor) flags=D$flags ble/decode/bind/get-optarg --cursor 1 "$has_optarg" "$optarg" || break ble/decode/bind/.initialize-kmap && ble/decode/keymap#set-cursor "$kmap" "${optarg[0]}" ;; (list-widgets|list-functions) flags=D$flags ble/decode/bind/option:list-widgets ;; (dump) flags=D$flags ble/decode/bind/option:dump "${keymaps[@]}" ;; (print) flags=D$flags ble/decode/bind/option:print "${keymaps[@]}" ;; (*) flags=E$flags ble/util/print "ble-bind: unrecognized long option $arg" >&2 ;; esac elif [[ $arg == -?* ]]; then arg=${arg:1} while ((${#arg})); do c=${arg::1} arg=${arg:1} case $c in (k) flags=D$flags ble/decode/bind/get-optarg -k 2 "$arg" || break 2 arg= ble-decode-kbd "${optarg[0]}"; local cseq=$ret if [[ ${optarg[1]} && ${optarg[1]} != - ]]; then ble-decode-kbd "${optarg[1]}"; local kc=$ret ble-decode-char/bind "$cseq" "$kc" else ble-decode-char/unbind "$cseq" fi ;; (m) ble/decode/bind/get-optarg -m 1 "$arg" || break 2 arg= if ! ble/decode/is-keymap "$optarg"; then ble/util/print "ble-bind: the keymap '$optarg' is unknown." >&2 flags=E$flags continue fi kmap=$optarg ble/array#push keymaps "$optarg" ;; (D) flags=D$flags ble/decode/bind/option:dump "${keymaps[@]}" ;; ([Pd]) flags=D$flags ble/decode/bind/option:print "${keymaps[@]}" ;; (['fxc@s']) flags=D$flags [[ $c != f && $arg == f* ]] && arg=${arg:1} ble/decode/bind/get-optarg "-$c" 2 "$arg" || break 2 arg= ble-decode-kbd "${optarg[0]}"; local kbd=$ret if [[ ${optarg[1]} && ${optarg[1]} != - ]]; then local command=${optarg[1]} case $c in (f) command=ble/widget/$command ;; # ble/widget/ 関数 (x) command="ble/widget/.EDIT_COMMAND '${command//$q/$Q}'" ;; # 編集用の関数 (c) command="ble/widget/.SHELL_COMMAND '${command//$q/$Q}'" ;; # コマンド実行 (s) local ret; ble/util/keyseq2chars "$command"; command="ble/widget/.MACRO ${ret[*]}" ;; ('@') ;; # 直接実行 (*) ble/util/print "error: unsupported binding type \`-$c'." >&2 continue ;; esac ble/decode/bind/.initialize-kmap && ble-decode-key/bind "$kmap" "$kbd" "$command" else ble/decode/bind/.initialize-kmap && ble-decode-key/unbind "$kmap" "$kbd" fi ;; (T) flags=D$flags ble/decode/bind/get-optarg -T 2 "$arg" || break 2 arg= ble-decode-kbd "${optarg[0]}"; local kbd=$ret ble/decode/bind/.initialize-kmap && ble-decode-key/set-timeout "$kmap" "$kbd" "${optarg[1]}" ;; (L) flags=D$flags ble/decode/bind/option:list-widgets ;; (*) ble/util/print "ble-bind: unrecognized short option \`-$c'." >&2 flags=E$flags ;; esac done else ble/util/print "ble-bind: unrecognized argument \`$arg'." >&2 flags=E$flags fi done local ext=0 case $flags in (*E*) ext=2 ;; (*R*) ext=1 ;; (*D*) ;; (*) ble/decode/bind/option:print "${keymaps[@]}" ;; esac [[ $_ble_bash_options_adjusted ]] || ble/base/.restore-bash-options set shopt return "$ext" } function ble/decode/read-inputrc/test { local text=$1 if [[ ! $text ]]; then ble/util/print "ble.sh (bind):\$if: test condition is not supplied." >&2 return 1 elif local rex=$'[ \t]*([<>]=?|[=!]?=)[ \t]*(.*)$'; [[ $text =~ $rex ]]; then local op=${BASH_REMATCH[1]} local rhs=${BASH_REMATCH[2]} local lhs=${text::${#text}-${#BASH_REMATCH}} else local lhs=application local rhs=$text fi case $lhs in (application) local ret; ble/string#tolower "$rhs" [[ $ret == bash || $ret == blesh ]] return "$?" ;; (mode) if [[ -o emacs ]]; then builtin test emacs "$op" "$rhs" elif [[ -o vi ]]; then builtin test vi "$op" "$rhs" else false fi return "$?" ;; (term) if [[ $op == '!=' ]]; then builtin test "$TERM" "$op" "$rhs" && builtin test "${TERM%%-*}" "$op" "$rhs" else builtin test "$TERM" "$op" "$rhs" || builtin test "${TERM%%-*}" "$op" "$rhs" fi return "$?" ;; (version) local lhs_major lhs_minor if ((_ble_bash<40400)); then ((lhs_major=2+_ble_bash/10000, lhs_minor=_ble_bash/100%100)) elif ((_ble_bash<50000)); then ((lhs_major=7,lhs_minor=0)) else ((lhs_major=3+_ble_bash/10000, lhs_minor=_ble_bash/100%100)) fi local rhs_major rhs_minor if [[ $rhs == *.* ]]; then local version ble/string#split version . "$rhs" rhs_major=${version[0]} rhs_minor=${version[1]} else ((rhs_major=rhs,rhs_minor=0)) fi local lhs_ver=$((lhs_major*10000+lhs_minor)) local rhs_ver=$((rhs_major*10000+rhs_minor)) [[ $op == '=' ]] && op='==' let "$lhs_ver$op$rhs_ver" return "$?" ;; (*) if local ret; ble/util/rlvar#read "$lhs"; then builtin test "$ret" "$op" "$rhs" return "$?" else ble/util/print "ble.sh (bind):\$if: unknown readline variable '${lhs//$q/$Q}'." >&2 return 1 fi ;; esac } function ble/decode/read-inputrc { local file=$1 ref=$2 q=\' Q="''\'" if [[ -f $ref && $ref == */* && $file != /* ]]; then local relative_file=${ref%/*}/$file [[ -f $relative_file ]] && file=$relative_file fi if [[ ! -f $file ]]; then ble/util/print "ble.sh (bind):\$include: the file '${1//$q/$Q}' not found." >&2 return 1 fi local -a script=() local ret line= iline=0 while ble/bash/read line || [[ $line ]]; do ((++iline)) ble/string#trim "$line"; line=$ret [[ ! $line || $line == '#'* ]] && continue if [[ $line == '$'* ]]; then local directive=${line%%[$IFS]*} case $directive in ('$if') local args=${line#'$if'} ble/string#trim "$args"; args=$ret ble/array#push script "if ble/decode/read-inputrc/test '${args//$q/$Q}'; then :" ;; ('$else') ble/array#push script 'else :' ;; ('$endif') ble/array#push script 'fi' ;; ('$include') local args=${line#'$include'} ble/string#trim "$args"; args=$ret ble/array#push script "ble/decode/read-inputrc '${args//$q/$Q}' '${file//$q/$Q}'" ;; (*) ble/util/print "ble.sh (bind):$file:$iline: unrecognized directive '$directive'." >&2 ;; esac else ble/array#push script "ble/builtin/bind/.process -- '${line//$q/$Q}'" fi done < "$file" IFS=$'\n' builtin eval 'script="${script[*]}"' builtin eval -- "$script" } _ble_builtin_bind_keymap= function ble/builtin/bind/set-keymap { local opt_keymap= flags= ble/builtin/bind/option:m "$1" && _ble_builtin_bind_keymap=$opt_keymap return 0 } function ble/builtin/bind/option:m { local name=$1 local ret; ble/string#tolower "$name"; local keymap=$ret case $keymap in (emacs|emacs-standard|emacs-meta|emacs-ctlx) ;; (vi|vi-command|vi-move|vi-insert) ;; (*) keymap= ;; esac if [[ ! $keymap ]]; then ble/util/print "ble.sh (bind): unrecognized keymap name '$name'" >&2 flags=e$flags return 1 else opt_keymap=$keymap return 0 fi } function ble/builtin/bind/.unquote-macro-string { local value=$1 q=\' Q="'\''" local delim=${1::1} if [[ $delim != [\"\'] ]]; then ret=$value fi local rex='^'$delim'(([^\'$delim']|\\.)*)'$delim'['$_ble_term_IFS']*' if ! [[ $value =~ $rex ]]; then ble/util/print "ble.sh (bind): no closing '${delim//$q/$Q}' in spec: '${spec//$q/$Q}'" >&2 return 1 elif ((${#BASH_REMATCH}<${#value})); then local fragment=${value:${#BASH_REMATCH}} ble/util/print "ble.sh (bind): warning: unprocessed fragments '${fragment//$q/$Q}' in spec: '${spec//$q/$Q}'" >&2 fi ret=${BASH_REMATCH[1]} } function ble/builtin/bind/.decompose-pair.impl { local LC_ALL= LC_CTYPE=C local ret; ble/string#ltrim "$1" local spec=$ret ifs=$_ble_term_IFS q=\' Q="'\''" keyseq= value= [[ ! $spec || $spec == 'set'["$ifs"]* ]] && return 3 local rex_keyseq='^(("([^\"]|\\.)*"|[^":'$ifs'])*("([^\"]|\\.)*)?)' if [[ :$2: == *:user-command:* ]]; then if ! ble/string#match "$spec" "$rex_keyseq[$ifs]*[:$ifs]"; then ble/util/print "ble.sh (bind): no colon or space after keyseq: '${spec//$q/$Q}'" >&3 return 1 fi local rematch=$BASH_REMATCH keyseq=${BASH_REMATCH[1]} ble/string#ltrim "${spec:${#BASH_REMATCH}}" if [[ $rematch == *: ]]; then if [[ $ret == [\"\']* ]]; then ble/builtin/bind/.unquote-macro-string "$ret" 2>&3 || return 1 fi else if [[ $ret == \"* ]]; then ble/builtin/bind/.unquote-macro-string "$ret" 2>&3 || return 1 ble/util/keyseq2chars "$ret" ble/util/chars2s "${ret[@]}" else ble/util/print "ble.sh (bind): the user command needs to be surrounded by \"..\": '${spec//$q/$Q}'" >&3 return 1 fi fi value=command:$ret else ble/string#match "$spec" "$rex_keyseq[$ifs]*(:[$ifs]*)?" keyseq=${BASH_REMATCH[1]} ble/string#trim "${spec:${#BASH_REMATCH}}" if [[ $ret == [\"\']* ]]; then ble/builtin/bind/.unquote-macro-string "$ret" 2>&3 || return 1 value=macro:$ret else value=rlfunc:$ret fi fi if [[ $keyseq == '$'* ]]; then return 3 elif [[ ! $keyseq ]]; then ble/util/print "ble.sh (bind): empty keyseq in spec: '${spec//$q/$Q}'" >&3 return 1 elif ble/string#match "$keyseq" '^"([^\"]|\\.)*$'; then ble/util/print "ble.sh (bind): no closing '\"' in keyseq: '${keyseq//$q/$Q}'" >&3 return 1 elif ble/string#match "$keyseq" '^"([^\"]|\\.)*"'; then local rematch=${BASH_REMATCH[0]} if ((${#rematch}<${#keyseq})); then local fragment=${keyseq:${#rematch}} ble/util/print "ble.sh (bind): warning: unprocessed fragments in keyseq '${fragment//$q/$Q}'" >&3 fi keyseq=$rematch return 0 else return 0 fi } function ble/builtin/bind/.decompose-pair { ble/builtin/bind/.decompose-pair.impl "$@" 3>&2 2>/dev/null # suppress locale error #D1440 } function ble/builtin/bind/.parse-keyname { local ret mflags= ble/string#tolower "$1"; local lower=$ret if [[ $1 == *-* ]]; then ble/string#split ret - "$lower" local mod for mod in "${ret[@]::${#ret[@]}-1}"; do case $mod in (*m|*meta) mflags=m$mflags ;; (*c|*ctrl|*control) mflags=c$mflags ;; esac done fi local name=${lower##*-} ch= case $name in (rubout|del) ch=$'\177' ;; (escape|esc) ch=$'\033' ;; (newline|lfd) ch=$'\n' ;; (return|ret) ch=$'\r' ;; (space|spc) ch=' ' ;; (tab) ch=$'\t' ;; (*) ble/util/substr "${1##*-}" 0 1; ch=$ret ;; esac ble/util/s2c "$ch"; local key=$ret [[ $mflags == *c* ]] && ((key&=0x1F)) [[ $mflags == *m* ]] && ((key|=0x80)) chars=("$key") } function ble/builtin/bind/.initialize-kmap { local keymap=$1 kmap= case $keymap in (emacs|emacs-standard) kmap=emacs ;; (emacs-ctlx) kmap=emacs; keys=(24 "${keys[@]}") ;; (emacs-meta) kmap=emacs; keys=(27 "${keys[@]}") ;; (vi-insert) kmap=vi_imap ;; (vi|vi-command|vi-move) kmap=vi_nmap ;; (*) ble-decode/GET_BASEMAP -v kmap ;; esac if ! ble/decode/is-keymap "$kmap"; then ble/util/print "ble/builtin/bind: the keymap '$kmap' is unknown." >&2 return 1 fi return 0 } function ble/builtin/bind/.initialize-keys-and-value { local spec=$1 opts=$2 keys= value= local keyseq ble/builtin/bind/.decompose-pair "$spec" "$opts" || return "$?" local chars if [[ $keyseq == \"*\" ]]; then local ret; ble/util/keyseq2chars "${keyseq:1:${#keyseq}-2}" chars=("${ret[@]}") ((${#chars[@]})) || ble/util/print "ble.sh (bind): warning: empty keyseq" >&2 else [[ :$opts: == *:nokeyname:* ]] && ble/util/print "ble.sh (bind): warning: readline \"bind -x\" does not support \"keyname\" spec" >&2 ble/builtin/bind/.parse-keyname "$keyseq" fi ble/decode/cmap/decode-chars "${chars[@]}" } function ble/builtin/bind/option:x { local q=\' Q="''\'" local keys value kmap if ! ble/builtin/bind/.initialize-keys-and-value "$1" nokeyname:user-command; then ble/util/print "ble.sh (bind): unrecognized user-command spec '${1//$q/$Q}'." >&2 flags=e$flags return 1 elif ! ble/builtin/bind/.initialize-kmap "$opt_keymap"; then ble/util/print "ble.sh (bind): sorry, failed to initialize keymap:'$opt_keymap'." >&2 flags=e$flags return 1 fi value=${value#command:} local command="ble/widget/.EDIT_COMMAND '${value//$q/$Q}'" ble-decode-key/bind "$kmap" "${keys[*]}" "$command" } function ble/builtin/bind/option:r { local keyseq=$1 local ret chars keys ble/util/keyseq2chars "$keyseq"; chars=("${ret[@]}") ble/decode/cmap/decode-chars "${chars[@]}" local kmap ble/builtin/bind/.initialize-kmap "$opt_keymap" || return 1 ble-decode-key/unbind "$kmap" "${keys[*]}" } _ble_decode_rlfunc2widget_emacs=() _ble_decode_rlfunc2widget_vi_imap=() _ble_decode_rlfunc2widget_vi_nmap=() function ble/builtin/bind/rlfunc2widget { local kmap=$1 rlfunc=$2 local IFS=$_ble_term_IFS local rlfunc_file= rlfunc_dict= case $kmap in (emacs) rlfunc_file=$_ble_base/lib/core-decode.emacs-rlfunc.txt rlfunc_dict=_ble_decode_rlfunc2widget_emacs ;; (vi_imap) rlfunc_file=$_ble_base/lib/core-decode.vi_imap-rlfunc.txt rlfunc_dict=_ble_decode_rlfunc2widget_vi_imap ;; (vi_nmap) rlfunc_file=$_ble_base/lib/core-decode.vi_nmap-rlfunc.txt rlfunc_dict=_ble_decode_rlfunc2widget_vi_nmap ;; esac if [[ $rlfunc_file ]]; then local dict script=' ((${#NAME[@]})) || ble/util/mapfile NAME < "$rlfunc_file" dict=("${NAME[@]}") '; builtin eval -- "${script//NAME/$rlfunc_dict}" local line for line in "${dict[@]}"; do [[ $line == "$rlfunc "* ]] || continue [[ $OSTYPE == msys* ]] && line=${line%$'\r'} local rl widget; ble/bash/read rl widget <<< "$line" if [[ $widget == - ]]; then ble/util/print "ble.sh (bind): unsupported readline function '${rlfunc//$q/$Q}' for keymap '$kmap'." >&2 return 1 elif [[ $widget == '' ]]; then return 2 fi ret=ble/widget/$widget return 0 done fi if ble/is-function ble/widget/"${rlfunc%%[$IFS]*}"; then ret=ble/widget/$rlfunc return 0 fi ble/util/print "ble.sh (bind): unsupported readline function '${rlfunc//$q/$Q}'." >&2 return 1 } function ble/builtin/bind/option:u { local rlfunc=$1 local kmap if ! ble/builtin/bind/.initialize-kmap "$opt_keymap" || ! ble/decode/keymap#load "$kmap"; then ble/util/print "ble.sh (bind): sorry, failed to initialize keymap:'$opt_keymap'." >&2 flags=e$flags return 1 fi local ret ble/builtin/bind/rlfunc2widget "$kmap" "$rlfunc" || return 0 local command=$ret local -a unbind_keys_list=() ble/builtin/bind/option:u/search-recursive "$kmap" local keys for keys in "${unbind_keys_list[@]}"; do ble-decode-key/unbind "$kmap" "$keys" done } function ble/builtin/bind/option:u/search-recursive { local kmap=$1 tseq=$2 local dicthead=_ble_decode_${kmap}_kmap_ local key keys builtin eval "keys=(\${!$dicthead$tseq[@]})" for key in "${keys[@]}"; do builtin eval "local ent=\${$dicthead$tseq[key]}" if [[ ${ent:2} == "$command" ]]; then ble/array#push unbind_keys_list "${tseq//_/ } $key" fi if [[ ${ent::1} == _ ]]; then ble/builtin/bind/option:u/search-recursive "$kmap" "${tseq}_$key" fi done } function ble/builtin/bind/option:- { local ret; ble/string#trim "$1"; local arg=$ret [[ ! $arg || $arg == '#'* ]] && return 0 local ifs=$_ble_term_IFS if [[ $arg == 'set'["$ifs"]* ]]; then if [[ $_ble_decode_bind_state != none ]]; then local variable= value= rex=$'^set[ \t]+([^ \t]+)[ \t]+([^ \t].*)$' [[ $arg =~ $rex ]] && variable=${BASH_REMATCH[1]} value=${BASH_REMATCH[2]} case $variable in (keymap) ble/builtin/bind/set-keymap "$value" return 0 ;; (editing-mode) _ble_builtin_bind_keymap= ;; esac ble/function#try ble/builtin/bind/set:"$variable" "$value" && return 0 builtin bind "$arg" fi return 0 fi local keys value kmap if ! ble/builtin/bind/.initialize-keys-and-value "$arg"; then local q=\' Q="''\'" ble/util/print "ble.sh (bind): unrecognized readline command '${arg//$q/$Q}'." >&2 flags=e$flags return 1 elif ! ble/builtin/bind/.initialize-kmap "$opt_keymap"; then ble/util/print "ble.sh (bind): sorry, failed to initialize keymap:'$opt_keymap'." >&2 flags=e$flags return 1 fi if [[ $value == macro:* ]]; then value=${value#macro:} local bind_keys="${keys[*]}" local ret chars; ble/util/keyseq2chars "$value"; chars=("${ret[@]}") local command="ble/widget/.MACRO ${chars[*]}" ble/decode/cmap/decode-chars "${chars[@]}" [[ ${keys[*]} != "$bind_keys" ]] && ble-decode-key/bind "$kmap" "$bind_keys" "$command" elif [[ $value == rlfunc:?* ]]; then value=${value#rlfunc:} local ret; ble/builtin/bind/rlfunc2widget "$kmap" "$value"; local ext=$? if ((ext==0)); then local command=$ret ble-decode-key/bind "$kmap" "${keys[*]}" "$command" return 0 elif ((ext==2)); then return 0 else flags=e$flags return 1 fi else ble/util/print "ble.sh (bind): readline function name is not specified ($arg)." >&2 return 1 fi } function ble/builtin/bind/.process { flags= local IFS=$_ble_term_IFS local opt_literal= opt_keymap=$_ble_builtin_bind_keymap opt_print= local -a opt_queries=() while (($#)); do local arg=$1; shift if [[ ! $opt_literal ]]; then case $arg in (--) opt_literal=1 continue ;; (--help) if ((_ble_bash<40400)); then ble/util/print "ble.sh (bind): unrecognized option $arg" >&2 flags=e$flags else [[ $_ble_decode_bind_state != none ]] && (builtin bind --help) flags=h$flags fi continue ;; (--*) ble/util/print "ble.sh (bind): unrecognized option $arg" >&2 flags=e$flags continue ;; (-*) arg=${arg:1} while [[ $arg ]]; do local c=${arg::1} arg=${arg:1} case $c in ([lpPsSvVX]) opt_print=$opt_print$c ;; ([mqurfx]) local optarg=$arg arg= if [[ ! $optarg ]]; then if (($#==0)); then ble/util/print "ble.sh (bind): missing option argument for -$c" >&2 flags=e$flags break fi optarg=$1; shift fi case $c in (m) ble/builtin/bind/option:m "$optarg" ;; (x) ble/builtin/bind/option:x "$optarg" ;; (r) ble/builtin/bind/option:r "$optarg" ;; (u) ble/builtin/bind/option:u "$optarg" ;; (q) ble/array#push opt_queries "$optarg" ;; (f) ble/decode/read-inputrc "$optarg" ;; (*) ble/util/print "ble.sh (bind): unsupported option -$c $optarg" >&2 flags=e$flags ;; esac ;; (*) ble/util/print "ble.sh (bind): unrecognized option -$c" >&2 flags=e$flags ;; esac done continue ;; esac fi ble/builtin/bind/option:- "$arg" opt_literal=1 done if [[ $_ble_decode_bind_state != none ]]; then if [[ $opt_print == *[pPsSX]* ]] || ((${#opt_queries[@]})); then ( ble/decode/readline/unbind [[ -s "$_ble_base_run/$$.bind.save" ]] && source "$_ble_base_run/$$.bind.save" [[ $opt_print ]] && builtin bind ${opt_keymap:+-m $opt_keymap} -$opt_print declare rlfunc for rlfunc in "${opt_queries[@]}"; do builtin bind ${opt_keymap:+-m $opt_keymap} -q "$rlfunc" done ) elif [[ $opt_print ]]; then builtin bind ${opt_keymap:+-m $opt_keymap} -$opt_print fi fi return 0 } _ble_builtin_bind_inputrc_done= function ble/builtin/bind/initialize-inputrc { [[ $_ble_builtin_bind_inputrc_done ]] && return 0 _ble_builtin_bind_inputrc_done=1 if [[ $1 == all ]]; then local sys_inputrc=/etc/inputrc [[ -e $sys_inputrc ]] && ble/decode/read-inputrc "$sys_inputrc" fi local inputrc=${INPUTRC:-$HOME/.inputrc} [[ -e $inputrc ]] && ble/decode/read-inputrc "$inputrc" } _ble_builtin_bind_user_settings_loaded= function ble/builtin/bind/read-user-settings/.collect { local map for map in vi-insert vi-command emacs; do local cache=$_ble_base_cache/decode.readline.$_ble_bash.$map.txt if ! [[ -s $cache && $cache -nt $_ble_base/ble.sh ]]; then INPUTRC=/dev/null "$BASH" --noprofile --norc -i -c "builtin bind -m $map -p" 2>/dev/null | LC_ALL= LC_CTYPE=C ble/bin/sed '/^#/d;s/"\\M-/"\\e/' >| "$cache.part" && ble/bin/mv "$cache.part" "$cache" || continue fi local cache_content ble/util/readfile cache_content "$cache" ble/util/print __CLEAR__ ble/util/print KEYMAP="$map" ble/util/print __BIND0__ ble/util/print "${cache_content%$_ble_term_nl}" if ((_ble_bash>=40300)); then ble/util/print __BINDX__ builtin bind -m "$map" -X 2>/dev/null fi ble/util/print __BINDS__ builtin bind -m "$map" -s 2>/dev/null ble/util/print __BINDP__ builtin bind -m "$map" -p 2>/dev/null ble/util/print __PRINT__ done } function ble/builtin/bind/read-user-settings/.reconstruct { local collect q=\' ble/util/assign collect ble/builtin/bind/read-user-settings/.collect <<< "$collect" LC_ALL= LC_CTYPE=C ble/bin/awk -v q="$q" -v _ble_bash="$_ble_bash" ' function keymap_register(key, val, type) { if (!haskey[key]) { keys[nkey++] = key; haskey[key] = 1; } keymap[key] = val; keymap_type[key] = type; } function keymap_clear(_, i, key) { for(i = 0; i < nkey; i++) { key = keys[i]; delete keymap[key]; delete keymap_type[key]; delete keymap0[key]; haskey[key] = 0; } nkey = 0; } function keymap_print(_, i, key, type, value, text, line) { for (i = 0; i < nkey; i++) { key = keys[i]; type = keymap_type[key]; value = keymap[key]; if (type == "" && value == keymap0[key]) continue; text = key ": " value; gsub(/'$q'/, q "\\" q q, text); line = "bind"; if (KEYMAP != "") line = line " -m " KEYMAP; if (type == "x") line = line " -x"; line = line " " q text q; print line; } } /^__BIND0__$/ { mode = 0; next; } /^__BINDX__$/ { mode = 1; next; } /^__BINDS__$/ { mode = 2; next; } /^__BINDP__$/ { mode = 3; next; } /^__CLEAR__$/ { keymap_clear(); next; } /^__PRINT__$/ { keymap_print(); next; } sub(/^KEYMAP=/, "") { KEYMAP = $0; } /(ble-decode\/.hook|_ble_decode_hook) / { next; } function workaround_bashbug(keyseq, _, rex, out, unit) { out = ""; while (keyseq != "") { if (mode == 0 || mode == 3) { match(keyseq, /^\\C-\\(\\"$)?|^\\M-|^\\.|^./); } else { match(keyseq, /^\\[CM]-|^\\.|^./); } unit = substr(keyseq, 1, RLENGTH); keyseq = substr(keyseq, 1 + RLENGTH); if (unit == "\\C-\\") { unit = unit "\\"; } else if (unit == "\\M-") { unit = "\\e"; } out = out unit; } return out; } function process_line(line, _, key, val) { if (match(line, /^"(\\.|[^"])+": /)) { key = substr(line, 1, RLENGTH - 2); val = substr(line, 1 + RLENGTH); } else if (mode == 1 && _ble_bash >= 50300 && match(line, /^"(\\.|[^"])+" /)) { key = substr(line, 1, RLENGTH - 1); val = substr(line, 1 + RLENGTH); } else { return 0; } if (_ble_bash < 50100) key = workaround_bashbug(key); if (mode) { type = mode == 1 ? "x" : mode == 2 ? "s" : ""; keymap_register(key, val, type); } else { keymap0[key] = val; } } { process_line($0); } ' 2>/dev/null # suppress LC_ALL error messages } function ble/builtin/bind/read-user-settings/.cache-enabled { local keymap use_cache=1 for keymap in emacs vi_imap vi_nmap; do ble/decode/keymap#registered "$keymap" && return 1 [[ -s $delay_prefix.$keymap ]] && return 1 done return 0 } function ble/builtin/bind/read-user-settings/.cache-alive { [[ -e $cache_prefix.settings ]] || return 1 [[ $cache_prefix.settings -nt $_ble_base/lib/init-cmap.sh ]] || return 1 local keymap for keymap in emacs vi_imap vi_nmap; do [[ $cache_prefix.settings -nt $_ble_base/core-decode.$cache-rlfunc.txt ]] || return 1 [[ -e $cache_prefix.$keymap ]] || return 1 done local content ble/util/readfile content "$cache_prefix.settings" [[ ${content%$'\n'} == "$settings" ]] } function ble/builtin/bind/read-user-settings/.cache-save { local keymap content fail= for keymap in emacs vi_imap vi_nmap; do if [[ -s $delay_prefix.$keymap ]]; then ble/util/copyfile "$delay_prefix.$keymap" "$cache_prefix.$keymap" else >| "$cache_prefix.$keymap" fi || fail=1 done [[ $fail ]] && return 1 ble/util/print "$settings" >| "$cache_prefix.settings" } function ble/builtin/bind/read-user-settings/.cache-load { local keymap for keymap in emacs vi_imap vi_nmap; do ble/util/copyfile "$cache_prefix.$keymap" "$delay_prefix.$keymap" done } function ble/builtin/bind/read-user-settings { if [[ $_ble_decode_bind_state == none ]]; then [[ $_ble_builtin_bind_user_settings_loaded ]] && return 0 _ble_builtin_bind_user_settings_loaded=1 builtin bind 2>/dev/null local settings ble/util/assign settings ble/builtin/bind/read-user-settings/.reconstruct [[ $settings ]] || return 0 local cache_prefix=$_ble_base_cache/decode.inputrc.$_ble_decode_kbd_ver.$TERM local delay_prefix=$_ble_base_run/$$.bind.delay if ble/builtin/bind/read-user-settings/.cache-enabled; then if ble/builtin/bind/read-user-settings/.cache-alive; then ble/builtin/bind/read-user-settings/.cache-load else builtin eval -- "$settings" 2>/dev/null # suppress "line editing not enabled" ble/builtin/bind/read-user-settings/.cache-save fi else builtin eval -- "$settings" 2>/dev/null # suppress "line editing not enabled" fi fi } function ble/builtin/bind { local set shopt; ble/base/.adjust-bash-options set shopt [[ ! $_ble_attached || $_ble_edit_exec_inside_userspace ]] && ble/base/adjust-BASH_REMATCH ble/decode/initialize local flags= ext=0 ble/builtin/bind/.process "$@" if [[ $_ble_decode_bind_state == none ]]; then builtin bind "$@"; ext=$? elif [[ $flags == *[eh]* ]]; then [[ $flags == *e* ]] && builtin bind --usage 2>&1 1>/dev/null | ble/bin/grep ^bind >&2 ext=2 fi [[ ! $_ble_attached || $_ble_edit_exec_inside_userspace ]] && ble/base/restore-BASH_REMATCH ble/base/.restore-bash-options set shopt return "$ext" } function bind { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" ble/builtin/bind "$@" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" } function ble/decode/initialize/.has-broken-suse-inputrc { local content= [[ -s /etc/inputrc.keys && -r /etc/os-release ]] && ble/util/readfile content /etc/os-release && [[ $content == *'SUSE'* ]] || return 1 return 0 } _ble_decode_initialized= _ble_decode_initialize_inputrc=auto function ble/decode/initialize { [[ $_ble_decode_initialized ]] && return 0 _ble_decode_initialized=1 ble/decode/cmap/initialize if [[ $_ble_decode_initialize_inputrc == auto ]]; then if ble/decode/initialize/.has-broken-suse-inputrc; then [[ ${INPUTRC-} == /etc/inputrc || ${INPUTRC-} == /etc/inputrc.keys ]] && local INPUTRC=~/.inputrc _ble_decode_initialize_inputrc=user else _ble_decode_initialize_inputrc=diff fi fi case $_ble_decode_initialize_inputrc in (all) ble/builtin/bind/initialize-inputrc all ;; (user) ble/builtin/bind/initialize-inputrc ;; (diff) ble/builtin/bind/read-user-settings ;; esac } function ble/decode/reset-default-keymap { local old_base_keymap=${_ble_decode_keymap_stack[0]:-$_ble_decode_keymap} ble-decode/INITIALIZE_DEFMAP -v _ble_decode_keymap # 0ms _ble_decode_keymap_stack=() if [[ $_ble_decode_keymap != "$old_base_keymap" ]]; then [[ $old_base_keymap ]] && _ble_decode_keymap=$old_base_keymap ble-decode/widget/.invoke-hook "$_ble_decode_KCODE_DETACH" ble-decode/widget/.invoke-hook "$_ble_decode_KCODE_ATTACH" # 7ms for vi-mode local cursor; ble/decode/keymap#get-cursor "$_ble_decode_keymap" [[ $cursor ]] && ble/term/cursor-state/set-internal "$((cursor))" fi } function ble/decode/attach { if ble/decode/keymap#is-empty "$_ble_decode_keymap"; then ble/util/print "ble.sh: The keymap '$_ble_decode_keymap' is empty." >&2 return 1 fi [[ $_ble_decode_bind_state != none ]] && return 0 ble/util/save-editing-mode _ble_decode_bind_state [[ $_ble_decode_bind_state == none ]] && return 1 ble/term/attach # 3ms ble/util/reset-keymap-of-editing-mode builtin eval -- "$(ble/decode/readline/.generate-source-to-unbind-default)" # 21ms ble/decode/readline/bind # 20ms return 0 } function ble/decode/detach { [[ $_ble_decode_bind_state != none ]] || return 1 local current_editing_mode= ble/util/save-editing-mode current_editing_mode [[ $_ble_decode_bind_state == "$current_editing_mode" ]] || ble/util/restore-editing-mode _ble_decode_bind_state ble/term/detach ble/decode/readline/unbind if [[ -s "$_ble_base_run/$$.bind.save" ]]; then source "$_ble_base_run/$$.bind.save" >| "$_ble_base_run/$$.bind.save" fi [[ $_ble_decode_bind_state == "$current_editing_mode" ]] || ble/util/restore-editing-mode current_editing_mode _ble_decode_bind_state=none } function ble/encoding:UTF-8/generate-binder { return 0; } _ble_encoding_utf8_decode_mode=0 _ble_encoding_utf8_decode_code=0 _ble_encoding_utf8_decode_table=( 'M&&E,A[i++]='{0..127} 'C=C<<6|'{0..63}',--M==0&&(A[i++]=C)' 'M&&E,C='{0..31}',M=1' 'M&&E,C='{0..15}',M=2' 'M&&E,C='{0..7}',M=3' 'M&&E,C='{0..3}',M=4' 'M&&E,C='{0..1}',M=5' 'M&&E,A[i++]=_ble_decode_Erro|'{254,255} ) function ble/encoding:UTF-8/clear { _ble_encoding_utf8_decode_mode=0 _ble_encoding_utf8_decode_code=0 } function ble/encoding:UTF-8/is-intermediate { ((_ble_encoding_utf8_decode_mode)) } function ble/encoding:UTF-8/decode { local C=$_ble_encoding_utf8_decode_code local M=$_ble_encoding_utf8_decode_mode local E='M=0,A[i++]=_ble_decode_Erro|C' local -a A=() local i=0 b for b; do ((_ble_encoding_utf8_decode_table[b&255])) done _ble_encoding_utf8_decode_code=$C _ble_encoding_utf8_decode_mode=$M ((i)) && ble-decode-char "${A[@]}" } function ble/encoding:UTF-8/c2bc { local code=$1 ((ret=code<0x80?1: (code<0x800?2: (code<0x10000?3: (code<0x200000?4:5))))) } function ble/encoding:C/generate-binder { ble/init:bind/bind-s '"\C-@":"\x9B\x80"' ble/init:bind/bind-s '"\e":"\x9B\x8B"' # isolated ESC (U+07FC) に後で変換 local i ret for i in {0..255}; do ble/decode/c2dqs "$i" ble/init:bind/bind-s "\"\e$ret\": \"\x9B\x9B$ret\"" done } _ble_encoding_c_csi= function ble/encoding:C/clear { _ble_encoding_c_csi= } function ble/encoding:C/is-intermediate { [[ $_ble_encoding_c_csi ]] } function ble/encoding:C/decode { local -a A=() local i=0 b for b; do if [[ $_ble_encoding_c_csi ]]; then _ble_encoding_c_csi= case $b in (155) A[i++]=27 # ESC continue ;; (139) A[i++]=2044 # isolated ESC U+07FC continue ;; (128) A[i++]=0 # C-@ continue ;; esac A[i++]=155 fi if ((b==155)); then _ble_encoding_c_csi=1 else A[i++]=$b fi done ((i)) && ble-decode-char "${A[@]}" } function ble/encoding:C/c2bc { ret=1 } _ble_color_gflags_Bold=0x01 _ble_color_gflags_Italic=0x02 _ble_color_gflags_Underline=0x04 _ble_color_gflags_Revert=0x08 _ble_color_gflags_Invisible=0x10 _ble_color_gflags_Strike=0x20 _ble_color_gflags_Blink=0x40 _ble_color_gflags_DecorationMask=0x77 _ble_color_gflags_FgMask=0x00000000FFFFFF00 _ble_color_gflags_BgMask=0x00FFFFFF00000000 _ble_color_gflags_FgShift=8 _ble_color_gflags_BgShift=32 _ble_color_gflags_FgIndexed=0x0100000000000000 _ble_color_gflags_BgIndexed=0x0200000000000000 _ble_color_index_colors_default=$_ble_term_colors if [[ $TERM == xterm* || $TERM == *-256color || $TERM == kterm* ]]; then _ble_color_index_colors_default=256 elif [[ $TERM == *-88color ]]; then _ble_color_index_colors_default=88 fi bleopt/declare -v term_true_colors semicolon bleopt/declare -v term_index_colors auto function bleopt/check:term_true_colors { ble/color/g2sgr/.clear-cache return 0 } function bleopt/check:term_index_colors { ble/color/g2sgr/.clear-cache return 0 } function ble/color/initialize-term-colors { local fields ble/string#split fields \; "$_ble_term_DA2R" if [[ $bleopt_term_true_colors == auto ]]; then local value= if [[ $TERM == *-24bit || $TERM == *-direct ]]; then value=colon elif [[ $TERM == *-24bits || $TERM == *-truecolor || $COLORTERM == *24bit* || $COLORTERM == *truecolor* ]]; then value=semicolon else case ${fields[0]} in (83) # screen (truecolor on にしている必要がある。判定方法は不明) if ((fields[1]>=49900)); then value=semicolon fi ;; (67) if ((fields[1]>=100000)); then : # cygwin terminal else value=colon fi ;; esac fi [[ $value ]] && bleopt term_true_colors="$value" fi } blehook term_DA2R!=ble/color/initialize-term-colors function ble/color/palette/.print-indexed-colors { local cols=$(((${COLUMNS:-80}-1)/4)) ((cols<1?(cols=1):(cols>16&&(cols=16)))) local bg bg0 bgN ret gflags=$((_ble_color_gflags_BgIndexed|_ble_color_gflags_FgIndexed)) for ((bg0=0;bg0<256;bg0+=cols)); do ((bgN=bg0+cols,bgN<256||(bgN=256))) for ((bg=bg0;bg=12?3+p:p)) for ((B=0;B<6;B++)); do ((bg=16+R*36+G*6+B)) ble/color/g2sgr "$((gflags|bg<<_ble_color_gflags_BgShift|(l%2?15:0)<<_ble_color_gflags_FgShift))" printf '%s%03d ' "$ret" "$bg" done if ((p+1<3)); then printf '%s ' "$_ble_term_sgr0" else printf '%s\n' "$_ble_term_sgr0" fi done done local l c K for ((l=0;l<4;l++)); do for ((c=0;c<12;c++)); do ((K=l/2*12+c)) ((bg=232+K)) ble/color/g2sgr "$((gflags|bg<<_ble_color_gflags_BgShift|(l%2?15:0)<<_ble_color_gflags_FgShift))" printf '%s%03d ' "$ret" "$bg" done printf '%s\n' "$_ble_term_sgr0" done return 0 } function ble-color-show { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" if (($#)); then ble/base/print-usage-for-no-argument-command 'Update and reload ble.sh.' "$@" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_leave" return 2 fi ble/color/palette/.print-indexed-colors builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" } function ble-palette { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" if (($#)); then ble/base/print-usage-for-no-argument-command 'Update and reload ble.sh.' "$@" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_leave" return 2 fi if ((${COLUMNS:-80}<80)); then ble/color/palette/.print-indexed-colors else ble/color/palette/.print-xterm-256color fi builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" } _ble_color_g2sgr_version=0 _ble_color_g2sgr=() _ble_color_g2sgr_ansi=() function ble/color/g2sgr/.impl { local g=$(($1)) local sgr=0 ((g&_ble_color_gflags_Bold)) && sgr="$sgr;${_ble_term_sgr_bold:-1}" ((g&_ble_color_gflags_Italic)) && sgr="$sgr;${_ble_term_sgr_sitm:-3}" ((g&_ble_color_gflags_Underline)) && sgr="$sgr;${_ble_term_sgr_smul:-4}" ((g&_ble_color_gflags_Blink)) && sgr="$sgr;${_ble_term_sgr_blink:-5}" ((g&_ble_color_gflags_Revert)) && sgr="$sgr;${_ble_term_sgr_rev:-7}" ((g&_ble_color_gflags_Invisible)) && sgr="$sgr;${_ble_term_sgr_invis:-8}" ((g&_ble_color_gflags_Strike)) && sgr="$sgr;${_ble_term_sgr_strike:-9}" if ((g&_ble_color_gflags_FgIndexed)); then local fg=$((g>>8&0xFF)) ble/color/.color2sgrfg "$fg" sgr="$sgr;$ret" elif ((g&_ble_color_gflags_FgMask)); then local rgb=$((1<<24|g>>8&0xFFFFFF)) ble/color/.color2sgrfg "$rgb" sgr="$sgr;$ret" fi if ((g&_ble_color_gflags_BgIndexed)); then local bg=$((g>>32&0xFF)) ble/color/.color2sgrbg "$bg" sgr="$sgr;$ret" elif ((g&_ble_color_gflags_BgMask)); then local rgb=$((1<<24|g>>32&0xFFFFFF)) ble/color/.color2sgrbg "$rgb" sgr="$sgr;$ret" fi ret=$'\e['$sgr'm' _ble_color_g2sgr[$1]=$ret } function ble/color/g2sgr/.clear-cache { _ble_color_g2sgr=() ((_ble_color_g2sgr_version++)) } function ble/color/g2sgr { ret=${_ble_color_g2sgr[$1]} [[ $ret ]] || ble/color/g2sgr/.impl "$1" } function ble/color/g2sgr-ansi/.impl { local g=$(($1)) local sgr=0 ((g&_ble_color_gflags_Bold)) && sgr="$sgr;1" ((g&_ble_color_gflags_Italic)) && sgr="$sgr;3" ((g&_ble_color_gflags_Underline)) && sgr="$sgr;4" ((g&_ble_color_gflags_Blink)) && sgr="$sgr;5" ((g&_ble_color_gflags_Revert)) && sgr="$sgr;7" ((g&_ble_color_gflags_Invisible)) && sgr="$sgr;8" ((g&_ble_color_gflags_Strike)) && sgr="$sgr;9" if ((g&_ble_color_gflags_FgIndexed)); then local fg=$((g>>8&0xFF)) sgr="$sgr;38:5:$fg" elif ((g&_ble_color_gflags_FgMask)); then local rgb=$((1<<24|g>>8&0xFFFFFF)) local R=$((rgb>>16&0xFF)) G=$((rgb>>8&0xFF)) B=$((rgb&0xFF)) sgr="$sgr;38:2::$R:$G:$B" fi if ((g&_ble_color_gflags_BgIndexed)); then local bg=$((g>>32&0xFF)) sgr="$sgr;48:5:$bg" elif ((g&_ble_color_gflags_BgMask)); then local rgb=$((1<<24|g>>32&0xFFFFFF)) local R=$((rgb>>16&0xFF)) G=$((rgb>>8&0xFF)) B=$((rgb&0xFF)) sgr="$sgr;48:2::$R:$G:$B" fi ret=$'\e['$sgr'm' _ble_color_g2sgr_ansi[$1]=$ret } function ble/color/g2sgr-ansi { ret=${_ble_color_g2sgr_ansi[$1]} [[ $ret ]] || ble/color/g2sgr-ansi/.impl "$1" } function ble/color/g#setfg-clear { (($1&=~(_ble_color_gflags_FgIndexed|_ble_color_gflags_FgMask))) } function ble/color/g#setbg-clear { (($1&=~(_ble_color_gflags_BgIndexed|_ble_color_gflags_BgMask))) } function ble/color/g#setfg-index { local _ble_local_color=$2 (($1=$1&~_ble_color_gflags_FgMask|_ble_color_gflags_FgIndexed|(_ble_local_color&0xFF)<<8)) # index color } function ble/color/g#setbg-index { local _ble_local_color=$2 (($1=$1&~_ble_color_gflags_BgMask|_ble_color_gflags_BgIndexed|(_ble_local_color&0xFF)<<32)) # index color } function ble/color/g#setfg-rgb { local _ble_local_R=$2 local _ble_local_G=$3 local _ble_local_B=$4 ((_ble_local_R&=0xFF,_ble_local_G&=0xFF,_ble_local_B&=0xFF)) if ((_ble_local_R==0&&_ble_local_G==0&&_ble_local_B==0)); then ble/color/g#setfg-index "$1" 16 else (($1=$1&~(_ble_color_gflags_FgIndexed|_ble_color_gflags_FgMask)|_ble_local_R<<24|_ble_local_G<<16|_ble_local_B<<8)) # true color fi } function ble/color/g#setbg-rgb { local _ble_local_R=$2 local _ble_local_G=$3 local _ble_local_B=$4 ((_ble_local_R&=0xFF,_ble_local_G&=0xFF,_ble_local_B&=0xFF)) if ((_ble_local_R==0&&_ble_local_G==0&&_ble_local_B==0)); then ble/color/g#setbg-index "$1" 16 else (($1=$1&~(_ble_color_gflags_BgIndexed|_ble_color_gflags_BgMask)|_ble_local_R<<48|_ble_local_G<<40|_ble_local_B<<32)) # true color fi } function ble/color/g#setfg-cmyk { local _ble_local_C=$2 local _ble_local_M=$3 local _ble_local_Y=$4 local _ble_local_K=${5:-0} ((_ble_local_K=~_ble_local_K&0xFF, _ble_local_C=(~_ble_local_C&0xFF)*_ble_local_K/255, _ble_local_M=(~_ble_local_M&0xFF)*_ble_local_K/255, _ble_local_Y=(~_ble_local_Y&0xFF)*_ble_local_K/255)) ble/color/g#setfg-rgb "$_ble_local_C" "$_ble_local_M" "$_ble_local_Y" } function ble/color/g#setbg-cmyk { local _ble_local_C=$2 local _ble_local_M=$3 local _ble_local_Y=$4 local _ble_local_K=${5:-0} ((_ble_local_K=~_ble_local_K&0xFF, _ble_local_C=(~_ble_local_C&0xFF)*_ble_local_K/255, _ble_local_M=(~_ble_local_M&0xFF)*_ble_local_K/255, _ble_local_Y=(~_ble_local_Y&0xFF)*_ble_local_K/255)) ble/color/g#setbg-rgb "$1" "$_ble_local_C" "$_ble_local_M" "$_ble_local_Y" } function ble/color/g#setfg { local _ble_local_color=$2 if ((_ble_local_color<0)); then ble/color/g#setfg-clear "$1" 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)|(_ble_local_color&0xFFFFFF)<<8)) # true color fi else ble/color/g#setfg-index "$1" "$_ble_local_color" fi } function ble/color/g#setbg { local _ble_local_color=$2 if ((_ble_local_color<0)); then ble/color/g#setbg-clear "$1" 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)|(_ble_local_color&0xFFFFFF)<<32)) # true color fi else ble/color/g#setbg-index "$1" "$_ble_local_color" fi } function ble/color/g#append { 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))) ((_ble_local_g2&(_ble_color_gflags_BgMask|_ble_color_gflags_BgIndexed))) && (($1&=~(_ble_color_gflags_BgMask|_ble_color_gflags_BgIndexed))) (($1|=_ble_local_g2)) } function ble/color/g#compose { (($1=($2))) 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 "$@"; } function ble/color/g.setbg { ble/color/g#setbg g "$@"; } function ble/color/g.setfg-clear { ble/color/g#setfg-clear g "$@"; } function ble/color/g.setbg-clear { ble/color/g#setbg-clear g "$@"; } function ble/color/g.setfg-index { ble/color/g#setfg-index g "$@"; } function ble/color/g.setbg-index { ble/color/g#setbg-index g "$@"; } function ble/color/g.setfg-rgb { ble/color/g#setfg-rgb g "$@"; } function ble/color/g.setbg-rgb { ble/color/g#setbg-rgb g "$@"; } function ble/color/g.setfg-cmyk { ble/color/g#setfg-cmyk g "$@"; } function ble/color/g.setbg-cmyk { ble/color/g#setbg-cmyk g "$@"; } function ble/color/g.append { ble/color/g#append g "$@"; } function ble/color/g.compose { ble/color/g#compose g "$@"; } function ble/color/g#getfg { local g=$1 if ((g&_ble_color_gflags_FgIndexed)); then ((ret=g>>8&0xFF)) elif ((g&_ble_color_gflags_FgMask)); then ((ret=0x1000000|(g>>8&0xFFFFFF))) else ((ret=-1)) fi } function ble/color/g#getbg { local g=$1 if ((g&_ble_color_gflags_BgIndexed)); then ((ret=g>>32&0xFF)) elif ((g&_ble_color_gflags_BgMask)); then ((ret=0x1000000|(g>>32&0xFFFFFF))) else ((ret=-1)) fi } function ble/color/g#compute-fg { local g=$1 if ((g&_ble_color_gflags_Invisible)); then ble/color/g#compute-bg "$g" elif ((g&_ble_color_gflags_Revert)); then ble/color/g#getbg "$g" else ble/color/g#getfg "$g" fi } function ble/color/g#compute-bg { local g=$1 if ((g&_ble_color_gflags_Revert)); then ble/color/g#getfg "$g" else ble/color/g#getbg "$g" fi } function ble/color/gspec2g { local g=0 entry for entry in ${1//,/ }; do case $entry in (bold) ((g|=_ble_color_gflags_Bold)) ;; (underline) ((g|=_ble_color_gflags_Underline)) ;; (blink) ((g|=_ble_color_gflags_Blink)) ;; (invis) ((g|=_ble_color_gflags_Invisible)) ;; (reverse) ((g|=_ble_color_gflags_Revert)) ;; (strike) ((g|=_ble_color_gflags_Strike)) ;; (italic) ((g|=_ble_color_gflags_Italic)) ;; (standout) ((g|=_ble_color_gflags_Revert|_ble_color_gflags_Bold)) ;; (fg=*) ble/color/.name2color "${entry:3}" ble/color/g.setfg "$ret" ;; (bg=*) ble/color/.name2color "${entry:3}" ble/color/g.setbg "$ret" ;; (none) g=0 ;; esac done ret=$g } function ble/color/g2gspec { local g=$1 gspec= if ((g&_ble_color_gflags_FgIndexed)); then local fg=$((g>>8&0xFF)) ble/color/.color2name "$fg" gspec=$gspec,fg=$ret elif ((g&_ble_color_gflags_FgMask)); then local rgb=$((1<<24|g>>8&0xFFFFFF)) ble/color/.color2name "$rgb" gspec=$gspec,fg=$ret fi if ((g&_ble_color_gflags_BgIndexed)); then local bg=$((g>>32&0xFF)) ble/color/.color2name "$bg" gspec=$gspec,bg=$ret elif ((g&_ble_color_gflags_BgMask)); then local rgb=$((1<<24|g>>32&0xFFFFFF)) ble/color/.color2name "$rgb" gspec=$gspec,bg=$ret fi ((g&_ble_color_gflags_Bold)) && gspec=$gspec,bold ((g&_ble_color_gflags_Underline)) && gspec=$gspec,underline ((g&_ble_color_gflags_Blink)) && gspec=$gspec,blink ((g&_ble_color_gflags_Invisible)) && gspec=$gspec,invis ((g&_ble_color_gflags_Revert)) && gspec=$gspec,reverse ((g&_ble_color_gflags_Strike)) && gspec=$gspec,strike ((g&_ble_color_gflags_Italic)) && gspec=$gspec,italic gspec=${gspec#,} ret=${gspec:-none} } function ble/color/gspec2sgr { local sgr=0 entry for entry in ${1//,/ }; do case $entry in (bold) sgr="$sgr;${_ble_term_sgr_bold:-1}" ;; (underline) sgr="$sgr;${_ble_term_sgr_smul:-4}" ;; (blink) sgr="$sgr;${_ble_term_sgr_blink:-5}" ;; (invis) sgr="$sgr;${_ble_term_sgr_invis:-8}" ;; (reverse) sgr="$sgr;${_ble_term_sgr_rev:-7}" ;; (strike) sgr="$sgr;${_ble_term_sgr_strike:-9}" ;; (italic) sgr="$sgr;${_ble_term_sgr_sitm:-3}" ;; (standout) sgr="$sgr;${_ble_term_sgr_bold:-1};${_ble_term_sgr_rev:-7}" ;; (fg=*) ble/color/.name2color "${entry:3}" ble/color/.color2sgrfg "$ret" sgr="$sgr;$ret" ;; (bg=*) ble/color/.name2color "${entry:3}" ble/color/.color2sgrbg "$ret" sgr="$sgr;$ret" ;; (none) sgr=0 ;; esac done ret="[${sgr}m" } function ble/color/.name2color/.clamp { local text=$1 max=$2 if [[ $text == *% ]]; then ((ret=10#0${text%'%'}*max/100)) else ((ret=10#0$text)) fi ((ret>max)) && ret=max } function ble/color/.name2color/.wrap { local text=$1 max=$2 if [[ $text == *% ]]; then ((ret=10#0${text%'%'}*max/100)) else ((ret=10#0$text)) fi ((ret%=max)) } function ble/color/.hxx2color { local H=$1 Min=$2 Range=$3 Unit=$4 local h1 h2 x=$Min y=$Min z=$Min ((h1=H%120,h2=120-h1, x+=Range*(h2<60?h2:60)/60, y+=Range*(h1<60?h1:60)/60)) ((x=x*255/Unit, y=y*255/Unit, z=z*255/Unit)) case $((H/120)) in (0) local R=$x G=$y B=$z ;; (1) local R=$z G=$x B=$y ;; (2) local R=$y G=$z B=$x ;; esac ((ret=1<<24|R<<16|G<<8|B)) } function ble/color/.hsl2color { local H=$1 S=$2 L=$3 Unit=$4 local Range=$((2*(L<=Unit/2?L:Unit-L)*S/Unit)) local Min=$((L-Range/2)) ble/color/.hxx2color "$H" "$Min" "$Range" "$Unit" } function ble/color/.hsb2color { local H=$1 S=$2 B=$3 Unit=$4 local Range=$((B*S/Unit)) local Min=$((B-Range)) ble/color/.hxx2color "$H" "$Min" "$Range" "$Unit" } function ble/color/.name2color { local colorName=$1 if [[ ! ${colorName//[0-9]} ]]; then ((ret=10#0$colorName&255)) elif [[ $colorName == '#'* ]]; then if local rex='^#[0-9a-fA-F]{3}$'; [[ $colorName =~ $rex ]]; then let "ret=1<<24|16#${colorName:1:1}*0x11<<16|16#${colorName:2:1}*0x11<<8|16#${colorName:3:1}*0x11" elif rex='^#[0-9a-fA-F]{6}$'; [[ $colorName =~ $rex ]]; then let "ret=1<<24|16#${colorName:1:2}<<16|16#${colorName:3:2}<<8|16#${colorName:5:2}" else ret=-1 fi elif [[ $colorName == *:* ]]; then if local rex='^rgb:([0-9]+%?)/([0-9]+%?)/([0-9]+%?)$'; [[ $colorName =~ $rex ]]; then ble/color/.name2color/.clamp "${BASH_REMATCH[1]}" 255; local R=$ret ble/color/.name2color/.clamp "${BASH_REMATCH[2]}" 255; local G=$ret ble/color/.name2color/.clamp "${BASH_REMATCH[3]}" 255; local B=$ret ((ret=1<<24|R<<16|G<<8|B)) elif local rex1='^cmy:([0-9]+%?)/([0-9]+%?)/([0-9]+%?)$' local rex2='^cmyk:([0-9]+%?)/([0-9]+%?)/([0-9]+%?)/([0-9]+%?)$' [[ $colorName =~ $rex1 || $colorName =~ $rex2 ]] then ble/color/.name2color/.clamp "${BASH_REMATCH[1]}" 255; local C=$ret ble/color/.name2color/.clamp "${BASH_REMATCH[2]}" 255; local M=$ret ble/color/.name2color/.clamp "${BASH_REMATCH[3]}" 255; local Y=$ret ble/color/.name2color/.clamp "${BASH_REMATCH[4]:-0}" 255; local K=$ret local K=$((~K&0xFF)) local R=$(((~C&0xFF)*K/255)) local G=$(((~M&0xFF)*K/255)) local B=$(((~Y&0xFF)*K/255)) ((ret=1<<24|R<<16|G<<8|B)) elif rex='^hs[lvb]:([0-9]+)/([0-9]+%)/([0-9]+%)$'; [[ $colorName =~ $rex ]]; then ble/color/.name2color/.wrap "${BASH_REMATCH[1]}" 360; local H=$ret ble/color/.name2color/.clamp "${BASH_REMATCH[2]}" 1000; local S=$ret ble/color/.name2color/.clamp "${BASH_REMATCH[3]}" 1000; local X=$ret if [[ $colorName == hsl:* ]]; then ble/color/.hsl2color "$H" "$S" "$X" 1000 else ble/color/.hsb2color "$H" "$S" "$X" 1000 fi else ret=-1 fi else case $colorName in (black) ret=0 ;; (brown) ret=1 ;; (green) ret=2 ;; (olive) ret=3 ;; (navy) ret=4 ;; (purple) ret=5 ;; (teal) ret=6 ;; (silver) ret=7 ;; (gr[ae]y) ret=8 ;; (red) ret=9 ;; (lime) ret=10 ;; (yellow) ret=11 ;; (blue) ret=12 ;; (magenta) ret=13 ;; (cyan) ret=14 ;; (white) ret=15 ;; (orange) ret=202 ;; (transparent|default) ret=-1 ;; (*) ret=-1 ;; esac fi } function ble/color/.color2name { if (($1>=0x1000000)); then ble/util/sprintf ret '#%06x' "$(($1&0xFFFFFF))" return 0 fi ((ret=(10#0$1&255))) case $ret in (0) ret=black ;; (1) ret=brown ;; (2) ret=green ;; (3) ret=olive ;; (4) ret=navy ;; (5) ret=purple ;; (6) ret=teal ;; (7) ret=silver ;; (8) ret=gray ;; (9) ret=red ;; (10) ret=lime ;; (11) ret=yellow ;; (12) ret=blue ;; (13) ret=magenta ;; (14) ret=cyan ;; (15) ret=white ;; (202) ret=orange ;; esac } function ble/color/convert-color88-to-color256 { local color=$1 if ((color>=16)); then if ((color>=80)); then local L=$((((color-80+1)*25+4)/9)) ((color=L==0?16:(L==25?231:232+(L-1)))) else ((color-=16)) local R=$((color/16)) G=$((color/4%4)) B=$((color%4)) ((R=(R*5+1)/3,G=(G*5+1)/3,B=(B*5+1)/3, color=16+R*36+G*6+B)) fi fi ret=$color } function ble/color/convert-color256-to-color88 { local color=$1 if ((color>=16)); then if ((color>=232)); then local L=$((((color-232+1)*9+12)/25)) ((color=L==0?16:(L==9?79:80+(L-1)))) else ((color-=16)) local R=$((color/36)) G=$((color/6%6)) B=$((color%6)) ((R=(R*3+2)/5,G=(G*3+2)/5,B=(B*3+2)/5, color=16+R*16+G*4+B)) fi fi ret=$color } function ble/color/convert-rgb24-to-color256 { local R=$1 G=$2 B=$3 if ((R!=G||G!=B)); then local r=$((R<=47?0:(R<=95?1:(R-35)/40))) local g=$((G<=47?0:(G<=95?1:(G-35)/40))) local b=$((B<=47?0:(B<=95?1:(B-35)/40))) if ((r!=g||g!=b)); then ((ret=16+36*r+6*g+b)) return 0 fi fi local W=$(((R+G+B+1)/3)) if ((W<=3)); then ret=16 elif ((W>=247)); then ret=231 elif ((W>=92&&(W-92)%40<5)); then ((ret=59+43*(W-92)/40)) else local level=$(((W-3)/10)) ((ret=232+(level<=23?level:23))) fi } function ble/color/convert-rgb24-to-color88 { local R=$1 G=$2 B=$3 if ((R!=G||G!=B)); then local r=$((R<=69?0:(R<=168?1:(R-52)/58))) local g=$((G<=69?0:(G<=168?1:(G-52)/58))) local b=$((B<=69?0:(B<=168?1:(B-52)/58))) if ((r!=g||g!=b)); then ((ret=16+16*r+4*g+b)) return 0 fi fi local W=$(((R+G+B+1)/3)) if ((W<=22)); then ret=16 # 4x4x4 cube (0,0,0)=0:0:0 elif ((W>=239)); then ret=79 # 4x4x4 cube (3,3,3)=255:255:255 elif ((131<=W&&W<=142)); then ret=37 # 4x4x4 cube (1,1,1)=139:139:139 elif ((197<=W&&W<=208)); then ret=58 # 4x4x4 cube (2,2,2)=197:197:197 else local level=$(((W-34)/25)) ((ret=80+(level<=7?level:7))) fi } _ble_color_color2sgr_filter= function ble/color/.color2sgr-impl { local ccode=$1 prefix=$2 # 3 for fg, 4 for bg builtin eval -- "$_ble_color_color2sgr_filter" if ((ccode<0)); then ret=${prefix}9 elif ((ccode<16&&ccode<_ble_term_colors)); then if ((prefix==4)); then ret=${_ble_term_sgr_ab[ccode]} else ret=${_ble_term_sgr_af[ccode]} fi elif ((ccode<256)); then local index_colors=$_ble_color_index_colors_default [[ $bleopt_term_index_colors == auto ]] || ((index_colors=bleopt_term_index_colors)) if ((index_colors>=256)); then ret="${prefix}8;5;$ccode" elif ((index_colors>=88)); then ble/color/convert-color256-to-color88 "$ccode" ret="${prefix}8;5;$ret" elif ((ccode=16||_ble_term_colors==8)); then if ((ccode>=16)); then if ((ccode>=232)); then local L=$((((ccode-232+1)*3+12)/25)) ((ccode=L==0?0:(L==1?8:(L==2?7:15)))) else ((ccode-=16)) local R=$((ccode/36)) G=$((ccode/6%6)) B=$((ccode%6)) if ((R==G&&G==B)); then local L=$(((R*3+2)/5)) ((ccode=L==0?0:(L==1?8:(L==2?7:15)))) else local min max ((Rmax&&(max=B)))) local Range=$((max-min)) ((R=(R-min+Range/2)/Range, G=(G-min+Range/2)/Range, B=(B-min+Range/2)/Range, ccode=R+G*2+B*4+(min+max>=5?8:0))) fi fi fi ((_ble_term_colors==8&&ccode>=8&&(ccode-=8))) if ((prefix==4)); then ret=${_ble_term_sgr_ab[ccode]} else ret=${_ble_term_sgr_af[ccode]} fi else ret=${prefix}9 fi elif ((0x1000000<=ccode&&ccode<0x2000000)); then local R=$((ccode>>16&0xFF)) G=$((ccode>>8&0xFF)) B=$((ccode&0xFF)) if [[ $bleopt_term_true_colors == semicolon ]]; then ret="${prefix}8;2;$R;$G;$B" elif [[ $bleopt_term_true_colors == colon ]]; then ret="${prefix}8:2::$R:$G:$B" else local index_colors=$_ble_color_index_colors_default [[ $bleopt_term_index_colors == auto ]] || ((index_colors=bleopt_term_index_colors)) local index= if ((index_colors>=256)); then ble/color/convert-rgb24-to-color256 "$R" "$G" "$B" index=$ret elif ((index_colors>=88)); then ble/color/convert-rgb24-to-color88 "$R" "$G" "$B" index=$ret else ble/color/convert-rgb24-to-color256 "$R" "$G" "$B" if ((ret5)) && ble/color/read-sgrspec/.arg-next -v S ble/color/read-sgrspec/.arg-next -v R ble/color/read-sgrspec/.arg-next -v G ble/color/read-sgrspec/.arg-next -v B ble/color/g.setfg-rgb "$R" "$G" "$B" elif ((cspace==3||cspace==4)); then local S C M Y K=0 ((${#fields[@]}>2+cspace)) && ble/color/read-sgrspec/.arg-next -v S ble/color/read-sgrspec/.arg-next -v C ble/color/read-sgrspec/.arg-next -v M ble/color/read-sgrspec/.arg-next -v Y ((cspace==4)) && ble/color/read-sgrspec/.arg-next -v K ble/color/g.setfg-cmyk "$C" "$M" "$Y" "$K" else ble/color/g.setfg-clear fi elif ((arg==48)); then local j=1 color cspace ble/color/read-sgrspec/.arg-next -v cspace if ((cspace==5)); then ble/color/read-sgrspec/.arg-next -v color if [[ :$opts: != *:ansi:* ]] && ((bleopt_term_index_colors==88)); then local ret; ble/color/convert-color88-to-color256 "$color"; color=$ret fi ble/color/g.setbg-index "$color" elif ((cspace==2)); then local S R G B ((${#fields[@]}>5)) && ble/color/read-sgrspec/.arg-next -v S ble/color/read-sgrspec/.arg-next -v R ble/color/read-sgrspec/.arg-next -v G ble/color/read-sgrspec/.arg-next -v B ble/color/g.setbg-rgb "$R" "$G" "$B" elif ((cspace==3||cspace==4)); then local S C M Y K=0 ((${#fields[@]}>2+cspace)) && ble/color/read-sgrspec/.arg-next -v S ble/color/read-sgrspec/.arg-next -v C ble/color/read-sgrspec/.arg-next -v M ble/color/read-sgrspec/.arg-next -v Y ((cspace==4)) && ble/color/read-sgrspec/.arg-next -v K ble/color/g.setbg-cmyk "$C" "$M" "$Y" "$K" else ble/color/g.setbg-clear fi elif ((arg==39)); then ble/color/g.setfg-clear elif ((arg==49)); then ble/color/g.setbg-clear fi elif ((90<=arg&&arg<98)); then local color=$((arg-90+8)) ble/color/g.setfg-index "$color" elif ((100<=arg&&arg<108)); then local color=$((arg-100+8)) ble/color/g.setbg-index "$color" else case $arg in (1) ((g|=_ble_color_gflags_Bold)) ;; (22) ((g&=~_ble_color_gflags_Bold)) ;; (4) ((g|=_ble_color_gflags_Underline)) ;; (24) ((g&=~_ble_color_gflags_Underline)) ;; (7) ((g|=_ble_color_gflags_Revert)) ;; (27) ((g&=~_ble_color_gflags_Revert)) ;; (9807) ((g^=_ble_color_gflags_Revert)) ;; # toggle (for internal use) (3) ((g|=_ble_color_gflags_Italic)) ;; (23) ((g&=~_ble_color_gflags_Italic)) ;; (5) ((g|=_ble_color_gflags_Blink)) ;; (25) ((g&=~_ble_color_gflags_Blink)) ;; (8) ((g|=_ble_color_gflags_Invisible)) ;; (28) ((g&=~_ble_color_gflags_Invisible)) ;; (9) ((g|=_ble_color_gflags_Strike)) ;; (29) ((g&=~_ble_color_gflags_Strike)) ;; esac fi done } function ble/color/sgrspec2g { local g=0 ble/color/read-sgrspec "$1" ret=$g } function ble/color/ansi2g { local x=0 y=0 g=0 ble/function#try ble/canvas/trace "$1" # -> ret ret=$g } if [[ ! ${_ble_faces_count-} ]]; then # reload #D0875 _ble_faces_count=0 _ble_faces=() fi function ble/color/setface/.check-argument { local rex='^[_a-zA-Z0-9]+$' [[ $# == 2 && $1 =~ $rex && $2 ]] && return 0 local flags=a while (($#)); do local arg=$1; shift case $arg in (--help) flags=H$flags ;; (--color|--color=always) flags=c${flags//[ac]} ;; (--color=auto) flags=a${flags//[ac]} ;; (--color=never) flags=${flags//[ac]} ;; (-*) ble/util/print "${FUNCNAME[1]}: unrecognized option '$arg'." >&2 flags=E$flags ;; (*) ble/util/print "${FUNCNAME[1]}: unrecognized argument '$arg'." >&2 flags=E$flags ;; esac done if [[ $flags == *E* ]]; then ext=2; return 1 elif [[ $flags == *H* ]]; then ble/util/print-lines \ "usage: $name FACE_NAME [TYPE:]SPEC" \ ' Set face.' \ '' \ ' TYPE Specifies the format of SPEC. The following values are available.' \ ' gspec Comma separated graphic attribute list' \ ' g Integer value' \ ' ref Face name or id (reference)' \ ' copy Face name or id (copy value)' \ ' sgrspec Parameters to the control function SGR' \ ' ansi ANSI Sequences' >&2 ext=0; return 1 fi local opts= [[ $flags == *c* || $flags == *a* && -t 1 ]] && opts=$opts:color ble/color/list-faces "$opts"; ext=$?; return 1 } function ble-color-defface { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" local set shopt [[ $_ble_bash_options_adjusted ]] || ble/base/.adjust-bash-options set shopt if local ext; ble/color/setface/.check-argument "$@"; then ble/color/defface "$@" ext=$? fi [[ $_ble_bash_options_adjusted ]] || ble/base/.restore-bash-options set shopt builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_leave" return "$ext" } function ble-color-setface { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" local set shopt [[ $_ble_bash_options_adjusted ]] || ble/base/.adjust-bash-options set shopt if local ext; ble/color/setface/.check-argument "$@"; then ble/color/setface "$@" ext=$? fi [[ $_ble_bash_options_adjusted ]] || ble/base/.restore-bash-options set shopt builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_leave" return "$ext" } function ble/color/defface { local q=\' Q="'\''"; blehook color_defface_load+="ble/color/defface '${1//$q/$Q}' '${2//$q/$Q}'"; } function ble/color/setface { local q=\' Q="'\''"; blehook color_setface_load+="ble/color/setface '${1//$q/$Q}' '${2//$q/$Q}'"; } function ble/color/face2g { ble/color/initialize-faces && ble/color/face2g "$@"; } function ble/color/face2sgr { ble/color/initialize-faces && ble/color/face2sgr "$@"; } function ble/color/iface2g { ble/color/initialize-faces && ble/color/iface2g "$@"; } function ble/color/iface2sgr { ble/color/initialize-faces && ble/color/iface2sgr "$@"; } function ble/color/spec2g { ble/color/initialize-faces && ble/color/spec2g "$@"; } function ble/color/face2sgr-ansi { ble/color/initialize-faces && ble/color/face2sgr "$@"; } _ble_color_faces_initialized= function ble/color/initialize-faces { local _ble_color_faces_initializing=1 local -a _ble_color_faces_errors=() function ble/color/face2g { ((ret=_ble_faces[_ble_faces__$1])) } function ble/color/face2sgr { ble/color/g2sgr "$((_ble_faces[_ble_faces__$1]))"; } function ble/color/face2sgr-ansi { ble/color/g2sgr-ansi "$((_ble_faces[_ble_faces__$1]))"; } function ble/color/iface2g { ((ret=_ble_faces[$1])) } function ble/color/iface2sgr { ble/color/g2sgr "$((_ble_faces[$1]))" } function ble/color/spec2g { ble/color/setface/.spec2gexpr "$@" prefix-face ((ret=ret)) } function ble/color/setface/.spec2gexpr { local spec=$1 value=${1#*:} opts=$2 case $spec in (gspec:*) ble/color/gspec2g "$value" ;; (g:*) ret=$(($value)) ;; (ref:*) if [[ ! ${value//[0-9]} ]]; then ret=_ble_faces[$((value))] else ret=_ble_faces[_ble_faces__$value] fi ;; (copy:*|face:*|iface:*) [[ $spec == copy:* || $spec == face:* && :$opts: == *:prefix-face:* ]] || ble/util/print "ble-face: \"${spec%%:*}:*\" is obsoleted. Use \"copy:*\" instead." >&2 if [[ ! ${value//[0-9]} ]]; then ble/color/iface2g "$value" else ble/color/face2g "$value" fi ;; (sgrspec:*) ble/color/sgrspec2g "$value" ;; (ansi:*) ble/color/ansi2g "$value" ;; (*) ble/color/gspec2g "$spec" ;; esac } function ble/color/defface { local name=_ble_faces__$1 spec=$2 ret (($name)) && return 0 (($name=++_ble_faces_count)) ble/color/setface/.spec2gexpr "$spec" _ble_faces[$name]=$ret _ble_faces_def[$name]=$ret } function ble/color/setface { local name=_ble_faces__$1 spec=$2 ret if [[ ${!name} ]]; then ble/color/setface/.spec2gexpr "$spec"; _ble_faces[$name]=$ret else local message="ble.sh: the specified face \`$1' is not defined." if [[ $_ble_color_faces_initializing ]]; then ble/array#push _ble_color_faces_errors "$message" else ble/util/print "$message" >&2 fi return 1 fi } _ble_color_faces_initialized=1 blehook/invoke color_defface_load blehook/invoke color_setface_load blehook color_defface_load= blehook color_setface_load= if ((${#_ble_color_faces_errors[@]})); then if ((_ble_edit_attached)) && [[ ! $_ble_textarea_invalidated && $_ble_term_state == internal ]]; then IFS=$'\n' builtin eval 'local message="${_ble_color_faces_errors[*]}"' ble/widget/print "$message" else printf '%s\n' "${_ble_color_faces_errors[@]}" >&2 fi return 1 else return 0 fi } ble/function#try ble/util/idle.push ble/color/initialize-faces function ble/color/list-faces { local flags= [[ :$1: == *:color:* ]] && flags=c local ret sgr0= sgr1= sgr2= if [[ $flags == *c* ]]; then sgr0=$_ble_term_sgr0 ble/color/face2sgr command_function; sgr1=$ret ble/color/face2sgr syntax_varname; sgr2=$ret fi local key for key in "${!_ble_faces__@}"; do ble/color/face/.print-face "$key" done } function ble/color/face/.read-arguments/process-set { local o=$1 face=$2 value=$3 if local rex='^[_a-zA-Z0-9@][_a-zA-Z0-9@]*$'; ! [[ $face =~ $rex ]]; then ble/util/print "ble-face: invalid face name '$face'." >&2 flags=E$flags return 1 elif [[ $o == '-d' && $face == *@* ]]; then ble/util/print "ble-face: wildcards cannot be used in the face name '$face' for definition." >&2 flags=E$flags return 1 fi local assign='=' [[ $o == -d ]] && assign=':=' ble/array#push setface "$face$assign$value" } function ble/color/face/.read-arguments { flags= setface=() print=() local opt_color=auto local args iarg narg=$#; args=("$@") for ((iarg=0;iarg&2 flags=E$flags else case $arg in (--help) flags=H$flags ;; (--color) opt_color=always ;; (--color=always|--color=auto|--color=never) opt_color=${arg#*=} ;; (--color=*) ble/util/print "ble-face: '${arg#*=}': unrecognized option argument for '--color'." >&2 flags=E$flags ;; (--reset) flags=r$flags ;; (--changed) flags=u$flags ;; (--) flags=L$flags ;; (--*) ble/util/print "ble-face: unrecognized long option '$arg'." >&2 flags=E$flags ;; (-?*) local i c for ((i=1;i<${#arg};i++)); do c=${arg:i:1} case $c in ([ru]) flags=$c$flags ;; ([sd]) if ((i+1<${#arg})); then local lhs=${arg:i+1} else local lhs=${args[iarg++]} fi local rhs=${args[iarg++]} if ((iarg>narg)); then ble/util/print "ble-face: missing option argument for '-$c FACE SPEC'." >&2 flags=E$flags continue fi ble/color/face/.read-arguments/process-set "${arg::2}" "$lhs" "$rhs" break ;; (*) ble/util/print "ble-face: unrecognized option '-$c'." >&2 flags=E$flags ;; esac done ;; (-) ble/util/print "ble-face: unrecognized argument '$arg'." >&2 flags=E$flags ;; esac fi elif [[ $arg == *=* ]]; then if local rex='^[_a-zA-Z@][_a-zA-Z0-9@]*:?='; [[ $arg =~ $rex ]]; then ble/array#push setface "$arg" else local lhs=${arg%%=*}; lhs=${lhs%:} ble/util/print "ble-face: invalid left-hand side '$lhs' ($arg)." >&2 flags=E$flags fi else if local rex='^[_a-zA-Z@][_a-zA-Z0-9@]*$'; [[ $arg =~ $rex ]]; then ble/array#push print "$arg" else ble/util/print "ble-face: unrecognized form of argument '$arg'." >&2 flags=E$flags fi fi done [[ $opt_color == auto && -t 1 || $opt_color == always ]] && flags=c$flags [[ $flags != *E* ]] } function ble/color/face/.print-help { ble/util/print-lines >&2 \ 'ble-face --help' \ 'ble-face [FACEPAT[:=|=][TYPE:]SPEC | -[sd] FACEPAT [TYPE:]SPEC]]...' \ 'ble-face [-ur|--color[=WHEN]] [FACE...]' \ '' \ ' OPTIONS/ARGUMENTS' \ '' \ ' FACEPAT=[TYPE:]SPEC' \ ' -s FACEPAT [TYPE:]SPEC' \ ' Set a face. FACEPAT can include a wildcard @ which matches one or' \ ' more characters.' \ '' \ ' FACE:=[TYPE:]SPEC' \ ' -d FACE [TYPE:]SPEC' \ ' Define a face' \ '' \ ' [-u | --color[=always|never|auto]]... FACEPAT...' \ ' Print faces. If faces are not specified, all faces are selected.' \ ' If -u is specified, only the faces with different values from their' \ ' default will be printed. The option "--color" controls the output' \ ' color settings. The default is "auto".' \ '' \ ' -r FACEPAT...' \ ' Reset faces. If faces are not specified, all faces are selected.' \ '' \ ' FACEPAT Specifies a face name. The characters "@", "*", and "?" in the' \ ' face name are treated as wildcards.' \ '' \ ' FACE Specifies a face name. The wildcards "@", "*", and "?" cannot be' \ ' used.' \ '' \ ' TYPE Specifies the format of SPEC. The following values are available.' \ ' gspec Comma separated graphic attribute list' \ ' g Integer value' \ ' ref Face name or id (reference)' \ ' copy Face name or id (copy value)' \ ' sgrspec Parameters to the control function SGR' \ ' ansi ANSI Sequences' \ '' return 0 } function ble/color/face/.print-face { local key=$1 ret local name=${key#_ble_faces__} local cur=${_ble_faces[key]} if [[ $flags == *u* ]]; then local def=_ble_faces_def[key] [[ ${!def+set} && $cur == "${!def}" ]] && return 0 fi local def=${_ble_faces[key]} if [[ $cur == '_ble_faces['*']' ]]; then cur=${cur#'_ble_faces['} cur=${cur%']'} cur=ref:${cur#_ble_faces__} else ble/color/g2gspec "$((cur))"; cur=$ret fi if [[ $flags == *c* ]]; then ble/color/iface2sgr "$((key))" cur=$ret$cur$_ble_term_sgr0 fi printf '%s %s=%s\n' "${sgr1}ble-face$sgr0" "$sgr2$name$sgr0" "$cur" } function ble/color/face/.reset-face { local key=$1 ret [[ ${_ble_faces_def[key]+set} ]] && _ble_faces[key]=${_ble_faces_def[key]} } function ble/color/face { local set shopt reset= if [[ ! $_ble_bash_options_adjusted ]]; then ble/base/.adjust-bash-options set shopt reset='ble/base/.restore-bash-options set shopt' fi local flags setface print ble/color/face/.read-arguments "$@" if [[ $flags == *H* ]]; then ble/color/face/.print-help builtin eval -- "$reset" return 2 elif [[ $flags == *E* ]]; then builtin eval -- "$reset" return 2 fi if ((!${#print[@]}&&!${#setface[@]})); then print=('?@') fi ((${#print[@]})) && ble/color/initialize-faces if [[ ! $_ble_color_faces_initialized ]]; then local ret ble/string#quote-command ble-face "${setface[@]}" blehook color_setface_load+="$ret" builtin eval -- "$reset" return 0 fi local spec for spec in "${setface[@]}"; do if local rex='^([_a-zA-Z@*?][_a-zA-Z0-9@*?]*)(:?=)(.*)$'; ! [[ $spec =~ $rex ]]; then ble/util/print "ble-face: unrecognized setting '$spec'" >&2 flags=E$flags continue fi local var=${BASH_REMATCH[1]} local type=${BASH_REMATCH[2]} local value=${BASH_REMATCH[3]} if [[ $type == ':=' ]]; then if [[ $var == *[@*?]* ]]; then ble/util/print "ble-face: wildcards @*? cannot be used for face definition ($spec)." >&2 flags=E$flags else ble/color/defface "$var" "$value" fi else local ret face if bleopt/expand-variable-pattern "_ble_faces__$var"; then for face in "${ret[@]}"; do ble/color/setface "${face#_ble_faces__}" "$value" done else ble/util/print "ble-face: face '$var' not found" >&2 flags=E$flags fi fi done if ((${#print[@]})); then local ret sgr0= sgr1= sgr2= if [[ $flags == *c* ]]; then sgr0=$_ble_term_sgr0 ble/color/face2sgr command_function; sgr1=$ret ble/color/face2sgr syntax_varname; sgr2=$ret fi local spec for spec in "${print[@]}"; do local ret face if bleopt/expand-variable-pattern "_ble_faces__$spec"; then if [[ $flags == *r* ]]; then for face in "${ret[@]}"; do ble/color/face/.reset-face "$face" done else for face in "${ret[@]}"; do ble/color/face/.print-face "$face" done fi else ble/util/print "ble-face: face '$spec' not found" >&2 flags=E$flags fi done fi [[ $flags != *E* ]] local ext=$? builtin eval -- "$reset" return "$ext" } function ble-face { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" ble/color/face "$@" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" } _ble_highlight_layer_list=(plain) function ble/highlight/layer/update { local text=$1 iN=${#1} opts=$2 local DMIN=${3:-0} DMAX=${4:-$iN} DMAX0=${5:-0} local PREV_BUFF=_ble_highlight_layer_plain_buff local PREV_UMIN=-1 local PREV_UMAX=-1 local layer player=plain LEVEL local nlevel=${#_ble_highlight_layer_list[@]} for ((LEVEL=0;LEVELumin)&&(PREV_UMIN=umin), (PREV_UMAX<0||PREV_UMAX=0)); then ble/array#reserve-prototype "$((DMAX-DMIN))" builtin eval " $_ble_local_dstarr=( \"\${$_ble_local_srcarr[@]::DMIN}\" \"\${_ble_array_prototype[@]::DMAX-DMIN}\" \"\${$_ble_local_srcarr[@]:DMAX0}\")" else [[ $_ble_local_dstarr != "$_ble_local_srcarr" ]] && builtin eval -- "$_ble_local_dstarr=(\"\${$_ble_local_srcarr[@]}\")" fi } function ble/highlight/layer/update/getg { g= local LEVEL=$LEVEL while ((--LEVEL>=0)); do "ble/highlight/layer:${_ble_highlight_layer_list[LEVEL]}/getg" "$1" [[ $g ]] && return 0 done g=0 } function ble/highlight/layer/getg { LEVEL=${#_ble_highlight_layer_list[*]} ble/highlight/layer/update/getg "$1" } _ble_highlight_layer_plain_VARNAMES=( _ble_highlight_layer_plain_buff) function ble/highlight/layer:plain/initialize-vars { _ble_highlight_layer_plain_buff=() } ble/highlight/layer:plain/initialize-vars function ble/highlight/layer:plain/update/.getch { [[ $ch == [' '-'~'] ]] && return 0 if [[ $ch == [$'\t\n\177'] ]]; then if [[ $ch == $'\t' ]]; then ch=${_ble_string_prototype::it} elif [[ $ch == $'\n' ]]; then ch=$_ble_term_el$_ble_term_nl elif [[ $ch == $'\177' ]]; then ch='^?' fi else local ret; ble/util/s2c "$ch" local cs=${_ble_unicode_GraphemeCluster_ControlRepresentation[ret]} if [[ $cs ]]; then ch=$cs elif ((ret<0x20)); then ble/util/c2s "$((ret+64))" ch="^$ret" elif ((0x80<=ret&&ret<=0x9F)); then ble/util/c2s "$((ret-64))" ch="M-^$ret" fi fi } function ble/highlight/layer:plain/update { if ((DMIN>=0)); then ble/highlight/layer/update/shift _ble_highlight_layer_plain_buff local i text=$1 ch local it=${bleopt_tab_width:-$_ble_term_it} for ((i=DMIN;ip)&&(umin=p), (umax<0||umax=0)); then local k for ((k=0;k=2&&sel[0]<=PREV_UMIN&&PREV_UMAX<=sel[1]))); then if [[ ${sel[*]} == "${osel[*]}" && ${gflags[*]} == "${ogflags[*]}" ]]; then [[ ${sel[*]} ]] && PREV_BUFF=${layer_prefix}buff return 0 fi else [[ ! ${sel[*]} && ! ${osel[*]} ]] && return 0 fi local umin=-1 umax=-1 if ((rlen)); then local rmin=${sel[0]} local rmax=${sel[rlen-1]} local -a buff=() local g ret local k=0 inext iprev=0 for inext in "${sel[@]}"; do if ((inext>iprev)); then if ((k==0)); then ble/array#push buff "\"\${$PREV_BUFF[@]::$inext}\"" elif ((k%2)); then ble/color/g2sgr "${gflags[k/2]}" ble/array#push buff "\"$ret\${_ble_highlight_layer_plain_buff[@]:$iprev:$((inext-iprev))}\"" else ble/highlight/layer/update/getg "$iprev" ble/color/g2sgr "$g" ble/array#push buff "\"$ret\${$PREV_BUFF[@]:$iprev:$((inext-iprev))}\"" fi fi ((iprev=inext,k++)) done ble/highlight/layer/update/getg "$iprev" ble/color/g2sgr "$g" ble/array#push buff "\"$ret\${$PREV_BUFF[@]:$iprev}\"" builtin eval -- "${layer_prefix}buff=(${buff[*]})" PREV_BUFF=${layer_prefix}buff if ((DMIN>=0)); then ble/highlight/layer:{selection}/.invalidate "$DMIN" "$DMAX" fi if ((olen==2&&rlen==2)); then if [[ ${gflags[0]} != "${ogflags[0]}" ]]; then ble/highlight/layer:{selection}/.invalidate "$omin" "$omax" ble/highlight/layer:{selection}/.invalidate "$rmin" "$rmax" else ble/highlight/layer:{selection}/.invalidate "$omin" "$rmin" ble/highlight/layer:{selection}/.invalidate "$omax" "$rmax" fi elif ((omin>=0)); then local k m local min_len=$((olenrlen?olen:rlen)) for ((k=0;kosel[oind]?sel[rind]:osel[oind])) ((smin=0;k-=2)); do if ((sel[k+1]=4)); then local l=0 u=$((olen-1)) m while ((l+1_ble_edit_ind)); then selection=("$_ble_edit_ind" "$_ble_edit_mark") elif ((_ble_edit_mark<_ble_edit_ind)); then selection=("$_ble_edit_mark" "$_ble_edit_ind") fi fi local face=region ble/function#try ble/highlight/layer:region/mark:"$_ble_edit_mark_active"/get-face local ret; ble/color/face2g "$face"; local g=$ret sel=("${selection[@]}") ble/array#fill-range gflags 0 "$((${#selection[@]}/2))" "$g" fi ble/highlight/layer:{selection}/update region "$@" } function ble/highlight/layer:region/getg { ble/highlight/layer:{selection}/getg region "$@" } _ble_highlight_layer_disabled_VARNAMES=( _ble_highlight_layer_disabled_prev _ble_highlight_layer_disabled_buff) function ble/highlight/layer:disabled/initialize-vars { _ble_highlight_layer_disabled_prev= _ble_highlight_layer_disabled_buff=() } ble/highlight/layer:disabled/initialize-vars function ble/highlight/layer:disabled/update { if [[ $_ble_edit_line_disabled ]]; then if ((DMIN>=0)) || [[ ! $_ble_highlight_layer_disabled_prev ]]; then local ret; ble/color/face2sgr disabled; local sgr=$ret _ble_highlight_layer_disabled_buff=("$sgr""${_ble_highlight_layer_plain_buff[@]}") fi PREV_BUFF=_ble_highlight_layer_disabled_buff if [[ $_ble_highlight_layer_disabled_prev ]]; then PREV_UMIN=$DMIN PREV_UMAX=$DMAX else PREV_UMIN=0 PREV_UMAX=${#1} fi else if [[ $_ble_highlight_layer_disabled_prev ]]; then PREV_UMIN=0 PREV_UMAX=${#1} fi fi _ble_highlight_layer_disabled_prev=$_ble_edit_line_disabled } function ble/highlight/layer:disabled/getg { if [[ $_ble_highlight_layer_disabled_prev ]]; then local ret; ble/color/face2g disabled; g=$ret fi } _ble_highlight_layer_overwrite_mode_VARNAMES=( _ble_highlight_layer_overwrite_mode_index _ble_highlight_layer_overwrite_mode_buff) function ble/highlight/layer:overwrite_mode/initialize-vars { _ble_highlight_layer_overwrite_mode_index=-1 _ble_highlight_layer_overwrite_mode_buff=() } ble/highlight/layer:overwrite_mode/initialize-vars function ble/highlight/layer:overwrite_mode/update { local oindex=$_ble_highlight_layer_overwrite_mode_index if ((DMIN>=0)); then if ((oindex>=DMAX0)); then ((oindex+=DMAX-DMAX0)) elif ((oindex>=DMIN)); then oindex=-1 fi fi local index=-1 if [[ $_ble_edit_overwrite_mode && ! $_ble_edit_mark_active ]]; then local next=${_ble_edit_str:_ble_edit_ind:1} if [[ $next && $next != [$'\n\t'] ]]; then index=$_ble_edit_ind local g ret if ((PREV_UMIN<0&&oindex>=0)); then ble/highlight/layer/update/getg "$oindex" ble/color/g2sgr "$g" _ble_highlight_layer_overwrite_mode_buff[oindex]=$ret${_ble_highlight_layer_plain_buff[oindex]} else builtin eval "_ble_highlight_layer_overwrite_mode_buff=(\"\${$PREV_BUFF[@]}\")" fi PREV_BUFF=_ble_highlight_layer_overwrite_mode_buff ble/color/face2g overwrite_mode ble/color/g2sgr "$ret" _ble_highlight_layer_overwrite_mode_buff[index]=$ret${_ble_highlight_layer_plain_buff[index]} if ((index+1<${#1})); then ble/highlight/layer/update/getg "$((index+1))" ble/color/g2sgr "$g" _ble_highlight_layer_overwrite_mode_buff[index+1]=$ret${_ble_highlight_layer_plain_buff[index+1]} fi fi fi if ((index>=0)); then ble/term/cursor-state/hide else ble/term/cursor-state/reveal fi if ((index!=oindex)); then ((oindex>=0)) && ble/highlight/layer/update/add-urange "$oindex" "$((oindex+1))" ((index>=0)) && ble/highlight/layer/update/add-urange "$index" "$((index+1))" fi _ble_highlight_layer_overwrite_mode_index=$index } function ble/highlight/layer:overwrite_mode/getg { local index=$_ble_highlight_layer_overwrite_mode_index if ((index>=0&&index==$1)); then local ret; ble/color/face2g overwrite_mode; g=$ret fi } _ble_highlight_layer_list=(plain syntax region overwrite_mode disabled) bleopt/declare -v tab_width '' function bleopt/check:tab_width { local old_width=${bleopt_tab_width:-$_ble_term_it} if [[ $value ]] && (((value=value)<=0)); then ble/util/print "bleopt: an empty string or a positive value is required for tab_width." >&2 return 1 fi if ((value!=old_width)); then local ret if ble/string#index-of "$_ble_edit_str" $'\t'; then local beg=$ret ble/string#last-index-of "$_ble_edit_str" $'\t' ble-edit/content/.update-dirty-range "$beg" "$ret" "$ret" tab_width fi fi } function ble/arithmetic/sum { IFS=+ builtin eval 'let "ret=$*+0"' } _ble_util_c2w=() _ble_util_c2w_cache=() function ble/util/c2w/clear-cache { _ble_util_c2w_cache=() } bleopt/declare -n char_width_mode auto function bleopt/check:char_width_mode { if ! ble/is-function "ble/util/c2w:$value"; then ble/util/print "bleopt: Invalid value char_width_mode='$value'. A function 'ble/util/c2w:$value' is not defined." >&2 return 1 fi case $value in (auto) _ble_unicode_c2w_ambiguous=1 ble && ble/util/c2w:auto/test.buff first-line ;; (west) _ble_unicode_c2w_ambiguous=1 ;; (east) _ble_unicode_c2w_ambiguous=2 ;; esac ((_ble_prompt_version++)) ble/util/c2w/clear-cache } function ble/util/c2w { ret=${_ble_util_c2w_cache[$1]:-${_ble_util_c2w[$1]}} if [[ ! $ret ]]; then "ble/util/c2w:$bleopt_char_width_mode" "$1" _ble_util_c2w_cache[$1]=$ret fi } function ble/util/c2w-edit { local cs=${_ble_unicode_GraphemeCluster_ControlRepresentation[$1]} if [[ $cs ]]; then ret=${#cs} elif (($1<32||127<=$1&&$1<160)); then ret=2 ((128<=$1&&(ret=4))) else ble/util/c2w "$1" fi } function ble/util/s2w-edit { local text=$1 iN=${#1} flags=$2 i ret=0 for ((i=0;i&2 return 1 fi } _ble_unicode_c2w_custom[173]=1 # U+00ad Cf A SHY(soft-hyphen) let '_ble_unicode_c2w_custom['{1536..1541}']=1' # U+0600..0605 Cf 1 アラブの数字? _ble_unicode_c2w_custom[1757]=1 # U+06dd Cf 1 ARABIC END OF AYAH _ble_unicode_c2w_custom[1807]=1 # U+070f Cf 1 SYRIAC ABBREVIATION MARK _ble_unicode_c2w_custom[2274]=1 # U+08e2 Cf 1 ARABIC DISPUTED END OF AYAH _ble_unicode_c2w_custom[69821]=1 # U+110bd Cf 1 KAITHI NUMBER SIGN _ble_unicode_c2w_custom[69837]=1 # U+110cd Cf 1 KAITHI NUMBER SIGN ABOVE let '_ble_unicode_c2w_custom['{12872..12879}']=2' # U+3248..324f No A 囲み文字10-80 (8字) let '_ble_unicode_c2w_custom['{19904..19967}']=2' # U+4dc0..4dff So 1 易経記号 (6字) let '_ble_unicode_c2w_custom['{4448..4607}']=0' # U+1160..11ff Lo 1 HANGUL JAMO (160字) let '_ble_unicode_c2w_custom['{55216..55238}']=0' # U+d7b0..d7c6 Lo 1 HANGUL JAMO EXTENDED-B (1) (23字) let '_ble_unicode_c2w_custom['{55243..55291}']=0' # U+d7cb..d7fb Lo 1 HANGUL JAMO EXTENDED-B (2) (49字) function ble/unicode/c2w { local c=$1 ret=${_ble_unicode_c2w_custom[c]} [[ $ret ]] && return 0 ret=${_ble_unicode_c2w[c]} if [[ ! $ret ]]; then ret=${_ble_unicode_c2w_index[c<0x20000?c>>8:((c>>12)-32+512)]} if [[ $ret == *:* ]]; then local l=${ret%:*} u=${ret#*:} m while ((l+1&2 return 1 else ble/util/print "bleopt: Unsupported emoji_version: '$value'." >&2 return 1 fi fi _ble_unicode_EmojiStatus_version=$ret ((_ble_prompt_version++)) ble/util/c2w/clear-cache return 0 } function bleopt/check:emoji_width { ble/util/c2w/clear-cache; } _ble_unicode_EmojiStatus_xIsEmoji='ret&&ret!=_ble_unicode_EmojiStatus_Unqualified' function bleopt/check:emoji_opts { _ble_unicode_EmojiStatus_xIsEmoji='ret' [[ :$value: != *:unqualified:* ]] && _ble_unicode_EmojiStatus_xIsEmoji=$_ble_unicode_EmojiStatus_xIsEmoji'&&ret!=_ble_unicode_EmojiStatus_Unqualified' local rex=':min=U\+([0-9a-fA-F]+):' [[ :$value: =~ $rex ]] && _ble_unicode_EmojiStatus_xIsEmoji=$_ble_unicode_EmojiStatus_xIsEmoji'&&code>=0x'${BASH_REMATCH[1]} ((_ble_prompt_version++)) ble/util/c2w/clear-cache return 0 } function ble/unicode/EmojiStatus { local code=$1 V=$_ble_unicode_EmojiStatus_version ret=${_ble_unicode_EmojiStatus[code]} if [[ ! $ret ]]; then ret=$_ble_unicode_EmojiStatus_None if ((_ble_unicode_EmojiStatus_xmaybe)); then local l=0 u=${#_ble_unicode_EmojiStatus_ranges[@]} m while ((l+1=0x80?2:1 ):(ah==0x2f?( ret=2 ):(ah==0x30?( ret=al!=0x3f?2:1 ):(ah==0xf9||ah==0xfa?( ret=2 ):(ah==0xfe?( ret=0x30<=al&&al<0x70?2:1 ):(ah==0xff?( ret=0x01<=al&&al<0x61||0xE0<=al&&al<=0xE7?2:1 ):(ret=1)))))))))) )) )) [[ $tIndex ]] || return 0 if ((tIndex<_ble_util_c2w_emacs_wranges[0])); then ret=1 return 0 fi local l=0 u=${#_ble_util_c2w_emacs_wranges[@]} m while ((l+1&2 return 1 ;; esac } _ble_unicode_GraphemeClusterBreak_Count=18 _ble_unicode_GraphemeClusterBreak_Other=0 _ble_unicode_GraphemeClusterBreak_Control=1 _ble_unicode_GraphemeClusterBreak_ZWJ=2 _ble_unicode_GraphemeClusterBreak_Prepend=3 _ble_unicode_GraphemeClusterBreak_Extend=4 _ble_unicode_GraphemeClusterBreak_SpacingMark=5 _ble_unicode_GraphemeClusterBreak_Regional_Indicator=6 _ble_unicode_GraphemeClusterBreak_L=7 _ble_unicode_GraphemeClusterBreak_V=8 _ble_unicode_GraphemeClusterBreak_T=9 _ble_unicode_GraphemeClusterBreak_LV=10 _ble_unicode_GraphemeClusterBreak_LVT=11 _ble_unicode_GraphemeClusterBreak_Pictographic=12 _ble_unicode_GraphemeClusterBreak_HighSurrogate=13 _ble_unicode_GraphemeClusterBreak_LowSurrogate=14 _ble_unicode_GraphemeClusterBreak_InCB_Consonant=15 _ble_unicode_GraphemeClusterBreak_InCB_Linker=16 _ble_unicode_GraphemeClusterBreak_InCB_Extend=17 _ble_unicode_GraphemeClusterBreak_MaxCode=921600 _ble_unicode_GraphemeClusterBreak=( [169]=12 [173]=1 [174]=12 [847]=4 [1160]=4 [1161]=4 [1470]=0 [1471]=17 [1472]=0 [1473]=17 [1474]=17 [1475]=0 [1476]=17 [1477]=17 [1478]=0 [1479]=17 [1563]=0 [1564]=1 [1648]=17 [1757]=3 [1758]=0 [1765]=0 [1766]=0 [1767]=17 [1768]=17 [1769]=0 [1807]=3 [1808]=0 [1809]=17 [2045]=17 [2074]=0 [2084]=0 [2088]=0 [2192]=3 [2193]=3 [2274]=3 [2307]=5 [2362]=4 [2363]=5 [2364]=17 [2365]=0 [2381]=16 [2382]=5 [2383]=5 [2384]=0 [2400]=0 [2401]=0 [2402]=4 [2403]=4 [2432]=0 [2433]=4 [2434]=5 [2435]=5 [2473]=0 [2481]=0 [2482]=15 [2490]=0 [2491]=0 [2492]=17 [2493]=0 [2494]=4 [2495]=5 [2496]=5 [2501]=0 [2502]=0 [2503]=5 [2504]=5 [2505]=0 [2506]=0 [2507]=5 [2508]=5 [2509]=16 [2519]=4 [2524]=15 [2525]=15 [2526]=0 [2527]=15 [2528]=0 [2529]=0 [2530]=4 [2531]=4 [2544]=15 [2545]=15 [2558]=17 [2559]=0 [2560]=0 [2561]=4 [2562]=4 [2563]=5 [2620]=17 [2621]=0 [2625]=4 [2626]=4 [2631]=4 [2632]=4 [2633]=0 [2634]=0 [2641]=4 [2672]=4 [2673]=4 [2677]=4 [2689]=4 [2690]=4 [2691]=5 [2729]=0 [2737]=0 [2738]=15 [2739]=15 [2740]=0 [2746]=0 [2747]=0 [2748]=17 [2749]=0 [2758]=0 [2759]=4 [2760]=4 [2761]=5 [2762]=0 [2763]=5 [2764]=5 [2765]=16 [2786]=4 [2787]=4 [2809]=15 [2816]=0 [2817]=4 [2818]=5 [2819]=5 [2857]=0 [2865]=0 [2866]=15 [2867]=15 [2868]=0 [2874]=0 [2875]=0 [2876]=17 [2877]=0 [2878]=4 [2879]=4 [2880]=5 [2885]=0 [2886]=0 [2887]=5 [2888]=5 [2889]=0 [2890]=0 [2891]=5 [2892]=5 [2893]=16 [2908]=15 [2909]=15 [2910]=0 [2911]=15 [2912]=0 [2913]=0 [2914]=4 [2915]=4 [2929]=15 [2946]=4 [3006]=4 [3007]=5 [3008]=4 [3009]=5 [3010]=5 [3017]=0 [3021]=4 [3031]=4 [3072]=4 [3076]=4 [3113]=0 [3130]=0 [3131]=0 [3132]=17 [3133]=0 [3141]=0 [3145]=0 [3149]=16 [3157]=17 [3158]=17 [3159]=0 [3170]=4 [3171]=4 [3201]=4 [3202]=5 [3203]=5 [3260]=17 [3261]=0 [3262]=5 [3263]=4 [3264]=5 [3265]=5 [3266]=4 [3267]=5 [3268]=5 [3269]=0 [3270]=4 [3271]=5 [3272]=5 [3273]=0 [3274]=5 [3275]=5 [3276]=4 [3277]=4 [3285]=4 [3286]=4 [3298]=4 [3299]=4 [3315]=5 [3328]=4 [3329]=4 [3330]=5 [3331]=5 [3387]=17 [3388]=17 [3389]=0 [3390]=4 [3391]=5 [3392]=5 [3397]=0 [3401]=0 [3405]=16 [3406]=3 [3415]=4 [3426]=4 [3427]=4 [3457]=4 [3458]=5 [3459]=5 [3530]=4 [3535]=4 [3536]=5 [3537]=5 [3541]=0 [3542]=4 [3543]=0 [3551]=4 [3570]=5 [3571]=5 [3633]=4 [3634]=0 [3635]=5 [3655]=4 [3761]=4 [3762]=0 [3763]=5 [3771]=4 [3772]=4 [3864]=17 [3865]=17 [3893]=17 [3894]=0 [3895]=17 [3896]=0 [3897]=17 [3902]=5 [3903]=5 [3953]=17 [3954]=17 [3955]=4 [3956]=17 [3966]=4 [3967]=5 [3968]=17 [3969]=4 [3973]=0 [3974]=17 [3975]=17 [3992]=0 [4038]=17 [4145]=5 [4151]=17 [4152]=0 [4153]=17 [4154]=17 [4155]=5 [4156]=5 [4157]=4 [4158]=4 [4182]=5 [4183]=5 [4184]=4 [4185]=4 [4226]=4 [4227]=0 [4228]=5 [4229]=4 [4230]=4 [4237]=17 [4253]=4 [5906]=4 [5907]=4 [5908]=17 [5909]=5 [5938]=4 [5939]=4 [5940]=5 [5970]=4 [5971]=4 [6002]=4 [6003]=4 [6068]=4 [6069]=4 [6070]=5 [6086]=4 [6087]=5 [6088]=5 [6098]=17 [6099]=4 [6109]=17 [6158]=1 [6159]=4 [6277]=4 [6278]=4 [6313]=17 [6439]=4 [6440]=4 [6448]=5 [6449]=5 [6450]=4 [6679]=17 [6680]=17 [6681]=5 [6682]=5 [6683]=4 [6741]=5 [6742]=4 [6743]=5 [6751]=0 [6752]=17 [6753]=0 [6754]=4 [6755]=0 [6756]=0 [6771]=4 [6772]=4 [6781]=0 [6782]=0 [6783]=17 [6846]=4 [6916]=5 [6964]=17 [6971]=5 [6972]=4 [6978]=4 [6979]=5 [6980]=5 [7040]=4 [7041]=4 [7042]=5 [7073]=5 [7078]=5 [7079]=5 [7080]=4 [7081]=4 [7082]=5 [7083]=17 [7084]=4 [7085]=4 [7142]=17 [7143]=5 [7144]=4 [7145]=4 [7149]=4 [7150]=5 [7154]=5 [7155]=5 [7220]=5 [7221]=5 [7222]=4 [7223]=17 [7379]=0 [7393]=5 [7405]=17 [7412]=17 [7413]=0 [7414]=0 [7415]=5 [7416]=17 [7417]=17 [8203]=1 [8204]=4 [8205]=2 [8206]=1 [8207]=1 [8252]=12 [8265]=12 [8417]=17 [8482]=12 [8505]=12 [8617]=12 [8618]=12 [8986]=12 [8987]=12 [9000]=12 [9096]=12 [9167]=12 [9410]=12 [9642]=12 [9643]=12 [9654]=12 [9664]=12 [9727]=0 [9734]=0 [9747]=0 [9990]=0 [9991]=0 [10003]=0 [10004]=12 [10005]=0 [10006]=12 [10013]=12 [10017]=12 [10024]=12 [10035]=12 [10036]=12 [10052]=12 [10053]=0 [10054]=0 [10055]=12 [10060]=12 [10061]=0 [10062]=12 [10070]=0 [10071]=12 [10145]=12 [10160]=12 [10175]=12 [10548]=12 [10549]=12 [11035]=12 [11036]=12 [11088]=12 [11093]=12 [11647]=17 [12336]=12 [12349]=12 [12441]=17 [12442]=17 [12951]=12 [12952]=0 [12953]=12 [42607]=17 [42611]=0 [42654]=17 [42655]=17 [42736]=17 [42737]=17 [43010]=4 [43014]=4 [43019]=4 [43043]=5 [43044]=5 [43045]=4 [43046]=4 [43047]=5 [43052]=17 [43136]=5 [43137]=5 [43204]=4 [43205]=4 [43263]=4 [43346]=5 [43347]=5 [43395]=5 [43443]=17 [43444]=5 [43445]=5 [43450]=5 [43451]=5 [43452]=4 [43453]=4 [43493]=4 [43567]=5 [43568]=5 [43569]=4 [43570]=4 [43571]=5 [43572]=5 [43573]=4 [43574]=4 [43587]=4 [43596]=4 [43597]=5 [43644]=4 [43696]=17 [43697]=0 [43701]=0 [43702]=0 [43703]=17 [43704]=17 [43710]=17 [43711]=17 [43712]=0 [43713]=17 [43755]=5 [43756]=4 [43757]=4 [43758]=5 [43759]=5 [43765]=5 [43766]=17 [44003]=5 [44004]=5 [44005]=4 [44006]=5 [44007]=5 [44008]=4 [44009]=5 [44010]=5 [44011]=0 [44012]=5 [44013]=17 [44032]=10 [44060]=10 [44088]=10 [44116]=10 [44144]=10 [44172]=10 [44200]=10 [44228]=10 [44256]=10 [44284]=10 [44312]=10 [44340]=10 [44368]=10 [44396]=10 [44424]=10 [44452]=10 [44480]=10 [44508]=10 [44536]=10 [44564]=10 [44592]=10 [44620]=10 [44648]=10 [44676]=10 [44704]=10 [44732]=10 [44760]=10 [44788]=10 [44816]=10 [44844]=10 [44872]=10 [44900]=10 [44928]=10 [44956]=10 [44984]=10 [45012]=10 [45040]=10 [45068]=10 [45096]=10 [45124]=10 [45152]=10 [45180]=10 [45208]=10 [45236]=10 [45264]=10 [45292]=10 [45320]=10 [45348]=10 [45376]=10 [45404]=10 [45432]=10 [45460]=10 [45488]=10 [45516]=10 [45544]=10 [45572]=10 [45600]=10 [45628]=10 [45656]=10 [45684]=10 [45712]=10 [45740]=10 [45768]=10 [45796]=10 [45824]=10 [45852]=10 [45880]=10 [45908]=10 [45936]=10 [45964]=10 [45992]=10 [46020]=10 [46048]=10 [46076]=10 [46104]=10 [46132]=10 [46160]=10 [46188]=10 [46216]=10 [46244]=10 [46272]=10 [46300]=10 [46328]=10 [46356]=10 [46384]=10 [46412]=10 [46440]=10 [46468]=10 [46496]=10 [46524]=10 [46552]=10 [46580]=10 [46608]=10 [46636]=10 [46664]=10 [46692]=10 [46720]=10 [46748]=10 [46776]=10 [46804]=10 [46832]=10 [46860]=10 [46888]=10 [46916]=10 [46944]=10 [46972]=10 [47000]=10 [47028]=10 [47056]=10 [47084]=10 [47112]=10 [47140]=10 [47168]=10 [47196]=10 [47224]=10 [47252]=10 [47280]=10 [47308]=10 [47336]=10 [47364]=10 [47392]=10 [47420]=10 [47448]=10 [47476]=10 [47504]=10 [47532]=10 [47560]=10 [47588]=10 [47616]=10 [47644]=10 [47672]=10 [47700]=10 [47728]=10 [47756]=10 [47784]=10 [47812]=10 [47840]=10 [47868]=10 [47896]=10 [47924]=10 [47952]=10 [47980]=10 [48008]=10 [48036]=10 [48064]=10 [48092]=10 [48120]=10 [48148]=10 [48176]=10 [48204]=10 [48232]=10 [48260]=10 [48288]=10 [48316]=10 [48344]=10 [48372]=10 [48400]=10 [48428]=10 [48456]=10 [48484]=10 [48512]=10 [48540]=10 [48568]=10 [48596]=10 [48624]=10 [48652]=10 [48680]=10 [48708]=10 [48736]=10 [48764]=10 [48792]=10 [48820]=10 [48848]=10 [48876]=10 [48904]=10 [48932]=10 [48960]=10 [48988]=10 [49016]=10 [49044]=10 [49072]=10 [49100]=10 [49128]=10 [49156]=10 [49184]=10 [49212]=10 [49240]=10 [49268]=10 [49296]=10 [49324]=10 [49352]=10 [49380]=10 [49408]=10 [49436]=10 [49464]=10 [49492]=10 [49520]=10 [49548]=10 [49576]=10 [49604]=10 [49632]=10 [49660]=10 [49688]=10 [49716]=10 [49744]=10 [49772]=10 [49800]=10 [49828]=10 [49856]=10 [49884]=10 [49912]=10 [49940]=10 [49968]=10 [49996]=10 [50024]=10 [50052]=10 [50080]=10 [50108]=10 [50136]=10 [50164]=10 [50192]=10 [50220]=10 [50248]=10 [50276]=10 [50304]=10 [50332]=10 [50360]=10 [50388]=10 [50416]=10 [50444]=10 [50472]=10 [50500]=10 [50528]=10 [50556]=10 [50584]=10 [50612]=10 [50640]=10 [50668]=10 [50696]=10 [50724]=10 [50752]=10 [50780]=10 [50808]=10 [50836]=10 [50864]=10 [50892]=10 [50920]=10 [50948]=10 [50976]=10 [51004]=10 [51032]=10 [51060]=10 [51088]=10 [51116]=10 [51144]=10 [51172]=10 [51200]=10 [51228]=10 [51256]=10 [51284]=10 [51312]=10 [51340]=10 [51368]=10 [51396]=10 [51424]=10 [51452]=10 [51480]=10 [51508]=10 [51536]=10 [51564]=10 [51592]=10 [51620]=10 [51648]=10 [51676]=10 [51704]=10 [51732]=10 [51760]=10 [51788]=10 [51816]=10 [51844]=10 [51872]=10 [51900]=10 [51928]=10 [51956]=10 [51984]=10 [52012]=10 [52040]=10 [52068]=10 [52096]=10 [52124]=10 [52152]=10 [52180]=10 [52208]=10 [52236]=10 [52264]=10 [52292]=10 [52320]=10 [52348]=10 [52376]=10 [52404]=10 [52432]=10 [52460]=10 [52488]=10 [52516]=10 [52544]=10 [52572]=10 [52600]=10 [52628]=10 [52656]=10 [52684]=10 [52712]=10 [52740]=10 [52768]=10 [52796]=10 [52824]=10 [52852]=10 [52880]=10 [52908]=10 [52936]=10 [52964]=10 [52992]=10 [53020]=10 [53048]=10 [53076]=10 [53104]=10 [53132]=10 [53160]=10 [53188]=10 [53216]=10 [53244]=10 [53272]=10 [53300]=10 [53328]=10 [53356]=10 [53384]=10 [53412]=10 [53440]=10 [53468]=10 [53496]=10 [53524]=10 [53552]=10 [53580]=10 [53608]=10 [53636]=10 [53664]=10 [53692]=10 [53720]=10 [53748]=10 [53776]=10 [53804]=10 [53832]=10 [53860]=10 [53888]=10 [53916]=10 [53944]=10 [53972]=10 [54000]=10 [54028]=10 [54056]=10 [54084]=10 [54112]=10 [54140]=10 [54168]=10 [54196]=10 [54224]=10 [54252]=10 [54280]=10 [54308]=10 [54336]=10 [54364]=10 [54392]=10 [54420]=10 [54448]=10 [54476]=10 [54504]=10 [54532]=10 [54560]=10 [54588]=10 [54616]=10 [54644]=10 [54672]=10 [54700]=10 [54728]=10 [54756]=10 [54784]=10 [54812]=10 [54840]=10 [54868]=10 [54896]=10 [54924]=10 [54952]=10 [54980]=10 [55008]=10 [55036]=10 [55064]=10 [55092]=10 [55120]=10 [55148]=10 [55176]=10 [64286]=17 [65279]=1 [65438]=4 [65439]=4 [66045]=17 [66272]=17 [68100]=0 [68101]=4 [68102]=4 [68108]=4 [68109]=17 [68110]=4 [68111]=17 [68159]=17 [68325]=17 [68326]=17 [69291]=17 [69292]=17 [69632]=5 [69633]=4 [69634]=5 [69744]=17 [69745]=0 [69746]=0 [69747]=4 [69748]=4 [69759]=17 [69760]=4 [69761]=4 [69762]=5 [69815]=5 [69816]=5 [69817]=4 [69818]=17 [69819]=0 [69820]=0 [69821]=3 [69826]=4 [69837]=3 [69932]=5 [69939]=17 [69940]=17 [69957]=5 [69958]=5 [70003]=17 [70016]=4 [70017]=4 [70018]=5 [70079]=5 [70080]=5 [70081]=0 [70082]=3 [70083]=3 [70089]=4 [70090]=17 [70091]=4 [70092]=4 [70093]=0 [70094]=5 [70095]=4 [70194]=5 [70195]=5 [70196]=4 [70197]=5 [70198]=17 [70199]=4 [70206]=4 [70207]=0 [70208]=0 [70209]=4 [70367]=4 [70377]=17 [70378]=17 [70400]=4 [70401]=4 [70402]=5 [70403]=5 [70459]=17 [70460]=17 [70461]=0 [70462]=4 [70463]=5 [70464]=4 [70469]=0 [70470]=0 [70471]=5 [70472]=5 [70473]=0 [70474]=0 [70487]=4 [70498]=5 [70499]=5 [70500]=0 [70501]=0 [70720]=5 [70721]=5 [70725]=5 [70726]=17 [70750]=17 [70832]=4 [70833]=5 [70834]=5 [70841]=5 [70842]=4 [70843]=5 [70844]=5 [70845]=4 [70846]=5 [70847]=4 [70848]=4 [70849]=5 [70850]=4 [70851]=17 [71087]=4 [71088]=5 [71089]=5 [71094]=0 [71095]=0 [71100]=4 [71101]=4 [71102]=5 [71103]=4 [71104]=17 [71132]=4 [71133]=4 [71227]=5 [71228]=5 [71229]=4 [71230]=5 [71231]=4 [71232]=4 [71339]=4 [71340]=5 [71341]=4 [71342]=5 [71343]=5 [71350]=5 [71351]=17 [71456]=0 [71457]=0 [71462]=5 [71467]=17 [71736]=5 [71737]=4 [71738]=17 [71984]=4 [71990]=0 [71991]=5 [71992]=5 [71993]=0 [71994]=0 [71995]=4 [71996]=4 [71997]=5 [71998]=17 [71999]=3 [72000]=5 [72001]=3 [72002]=5 [72003]=17 [72152]=0 [72153]=0 [72154]=4 [72155]=4 [72160]=4 [72164]=5 [72243]=4 [72244]=17 [72249]=5 [72250]=3 [72263]=17 [72279]=5 [72280]=5 [72343]=5 [72344]=4 [72345]=17 [72751]=5 [72759]=0 [72766]=5 [72767]=4 [72872]=0 [72873]=5 [72881]=5 [72882]=4 [72883]=4 [72884]=5 [72885]=4 [72886]=4 [73018]=4 [73019]=0 [73020]=4 [73021]=4 [73022]=0 [73026]=17 [73027]=4 [73028]=17 [73029]=17 [73030]=3 [73031]=4 [73103]=0 [73104]=4 [73105]=4 [73106]=0 [73107]=5 [73108]=5 [73109]=4 [73110]=5 [73111]=17 [73459]=4 [73460]=4 [73461]=5 [73462]=5 [73472]=4 [73473]=4 [73474]=3 [73475]=5 [73524]=5 [73525]=5 [73534]=5 [73535]=5 [73536]=4 [73537]=5 [73538]=17 [78912]=4 [94031]=4 [94032]=0 [94180]=4 [94192]=5 [94193]=5 [113821]=4 [113822]=17 [113823]=0 [118574]=0 [118575]=0 [119141]=17 [119142]=5 [119149]=5 [119171]=0 [119172]=0 [121461]=4 [121476]=4 [121504]=0 [122887]=0 [122905]=0 [122906]=0 [122914]=0 [122915]=17 [122916]=17 [122917]=0 [123023]=17 [123566]=17 [127279]=12 [127358]=12 [127359]=12 [127374]=12 [127375]=0 [127376]=0 [127488]=0 [127514]=12 [127535]=12 [127536]=0 [127537]=0 [127547]=0 [129339]=0 [129350]=0 [0]=1 [32]=0 [127]=1 [160]=0 [768]=17 [880]=0 [1155]=17 [1162]=0 [1425]=17 [1480]=0 [1536]=3 [1542]=0 [1552]=17 [1565]=0 [1611]=17 [1632]=0 [1750]=17 [1774]=0 [1840]=17 [1867]=0 [1958]=4 [1969]=0 [2027]=17 [2036]=0 [2070]=17 [2094]=0 [2137]=17 [2140]=0 [2200]=17 [2208]=0 [2250]=17 [2304]=4 [2308]=0 [2325]=15 [2366]=5 [2369]=4 [2377]=5 [2385]=17 [2389]=4 [2392]=15 [2404]=0 [2424]=15 [2436]=0 [2453]=15 [2483]=0 [2486]=15 [2497]=4 [2510]=0 [2622]=5 [2627]=0 [2635]=4 [2638]=0 [2709]=15 [2750]=5 [2753]=4 [2766]=0 [2810]=4 [2820]=0 [2837]=15 [2881]=4 [2894]=0 [2901]=4 [2904]=0 [3014]=5 [3022]=0 [3073]=5 [3077]=0 [3093]=15 [3134]=4 [3137]=5 [3142]=4 [3150]=0 [3160]=15 [3163]=0 [3349]=15 [3393]=4 [3398]=5 [3407]=0 [3538]=4 [3544]=5 [3552]=0 [3636]=4 [3640]=17 [3643]=0 [3656]=17 [3660]=4 [3663]=0 [3764]=4 [3768]=17 [3773]=0 [3784]=17 [3788]=4 [3791]=0 [3957]=4 [3962]=17 [3976]=0 [3981]=4 [4029]=0 [4141]=4 [4159]=0 [4190]=4 [4193]=0 [4209]=4 [4213]=0 [4352]=7 [4448]=8 [4520]=9 [4608]=0 [4957]=17 [4960]=0 [6071]=4 [6078]=5 [6089]=4 [6100]=0 [6155]=4 [6160]=0 [6432]=4 [6435]=5 [6444]=0 [6451]=5 [6457]=17 [6460]=0 [6744]=4 [6765]=5 [6773]=17 [6784]=0 [6832]=17 [6863]=0 [6912]=4 [6917]=0 [6965]=4 [6973]=5 [6981]=0 [7019]=17 [7028]=0 [7074]=4 [7086]=0 [7146]=5 [7151]=4 [7156]=0 [7204]=5 [7212]=4 [7224]=0 [7376]=17 [7401]=0 [7616]=17 [7680]=0 [8232]=1 [8239]=0 [8288]=1 [8304]=0 [8400]=17 [8413]=4 [8421]=17 [8433]=0 [8596]=12 [8602]=0 [9193]=12 [9204]=0 [9208]=12 [9211]=0 [9723]=12 [9862]=0 [9872]=12 [10007]=0 [10067]=12 [10072]=0 [10083]=12 [10088]=0 [10133]=12 [10136]=0 [11013]=12 [11016]=0 [11503]=17 [11506]=0 [11744]=17 [11776]=0 [12330]=17 [12337]=0 [42608]=4 [42612]=17 [42622]=0 [43188]=5 [43206]=0 [43232]=17 [43250]=0 [43302]=4 [43307]=17 [43310]=0 [43335]=4 [43348]=0 [43360]=7 [43389]=0 [43392]=4 [43396]=0 [43446]=4 [43454]=5 [43457]=0 [43561]=4 [43575]=0 [43698]=17 [43705]=0 [44033]=11 [55204]=0 [55216]=8 [55239]=0 [55243]=9 [55292]=0 [55296]=13 [56320]=14 [57344]=0 [65024]=4 [65040]=0 [65056]=17 [65072]=0 [65520]=1 [65532]=0 [66422]=17 [66427]=0 [68097]=4 [68103]=0 [68152]=17 [68155]=0 [68900]=17 [68904]=0 [69373]=17 [69376]=0 [69446]=17 [69457]=0 [69506]=17 [69510]=0 [69688]=4 [69703]=0 [69808]=5 [69811]=4 [69822]=0 [69888]=17 [69891]=0 [69927]=4 [69941]=0 [70067]=5 [70070]=4 [70084]=0 [70188]=5 [70191]=4 [70200]=0 [70368]=5 [70371]=4 [70379]=0 [70465]=5 [70478]=0 [70502]=17 [70509]=0 [70512]=17 [70517]=0 [70709]=5 [70712]=4 [70727]=0 [70835]=4 [70852]=0 [71090]=4 [71096]=5 [71105]=0 [71216]=5 [71219]=4 [71233]=0 [71344]=4 [71352]=0 [71453]=4 [71468]=0 [71724]=5 [71727]=4 [71739]=0 [71985]=5 [72004]=0 [72145]=5 [72148]=4 [72156]=5 [72161]=0 [72193]=4 [72203]=0 [72245]=4 [72255]=0 [72273]=4 [72284]=0 [72324]=3 [72330]=4 [72346]=0 [72752]=4 [72768]=0 [72850]=4 [72887]=0 [73009]=4 [73015]=0 [73023]=4 [73032]=0 [73098]=5 [73112]=0 [73526]=4 [73531]=0 [78896]=1 [78913]=0 [78919]=4 [78934]=0 [92912]=17 [92917]=0 [92976]=17 [92983]=0 [94033]=5 [94088]=0 [94095]=4 [94099]=0 [113824]=1 [113828]=0 [118528]=4 [118599]=0 [119143]=17 [119146]=0 [119150]=17 [119155]=1 [119163]=17 [119180]=0 [119210]=17 [119214]=0 [119362]=17 [119365]=0 [121344]=4 [121399]=0 [121403]=4 [121453]=0 [121499]=4 [121520]=0 [122880]=17 [122923]=0 [123184]=17 [123191]=0 [123628]=17 [123632]=0 [124140]=17 [124144]=0 [125136]=17 [125143]=0 [125252]=17 [125259]=0 [126976]=12 [127232]=0 [127245]=12 [127248]=0 [127340]=12 [127346]=0 [127377]=12 [127387]=0 [127405]=12 [127462]=6 [127489]=12 [127504]=0 [127538]=12 [127552]=0 [127561]=12 [127995]=4 [128000]=12 [128318]=0 [128326]=12 [128592]=0 [128640]=12 [128768]=0 [128884]=12 [128896]=0 [128981]=12 [129024]=0 [129036]=12 [129040]=0 [129096]=12 [129104]=0 [129114]=12 [129120]=0 [129160]=12 [129168]=0 [129198]=12 [129280]=0 [129292]=12 [129792]=0 [130048]=12 [131070]=0 [917504]=1 [917536]=4 [917632]=1 [917760]=4 [918000]=1 ) _ble_unicode_GraphemeClusterBreak_ranges=( 0 32 127 160 768 880 1155 1162 1425 1480 1536 1542 1552 1565 1611 1632 1750 1774 1840 1867 1958 1969 2027 2036 2070 2094 2137 2140 2200 2208 2250 2304 2308 2325 2366 2369 2377 2385 2389 2392 2404 2424 2436 2453 2483 2486 2497 2510 2622 2627 2635 2638 2709 2750 2753 2766 2810 2820 2837 2881 2894 2901 2904 3014 3022 3073 3077 3093 3134 3137 3142 3150 3160 3163 3349 3393 3398 3407 3538 3544 3552 3636 3640 3643 3656 3660 3663 3764 3768 3773 3784 3788 3791 3957 3962 3976 3981 4029 4141 4159 4190 4193 4209 4213 4352 4448 4520 4608 4957 4960 6071 6078 6089 6100 6155 6160 6432 6435 6444 6451 6457 6460 6744 6765 6773 6784 6832 6863 6912 6917 6965 6973 6981 7019 7028 7074 7086 7146 7151 7156 7204 7212 7224 7376 7401 7616 7680 8232 8239 8288 8304 8400 8413 8421 8433 8596 8602 9193 9204 9208 9211 9723 9862 9872 10007 10067 10072 10083 10088 10133 10136 11013 11016 11503 11506 11744 11776 12330 12337 42608 42612 42622 43188 43206 43232 43250 43302 43307 43310 43335 43348 43360 43389 43392 43396 43446 43454 43457 43561 43575 43698 43705 44033 55204 55216 55239 55243 55292 55296 56320 57344 65024 65040 65056 65072 65520 65532 66422 66427 68097 68103 68152 68155 68900 68904 69373 69376 69446 69457 69506 69510 69688 69703 69808 69811 69822 69888 69891 69927 69941 70067 70070 70084 70188 70191 70200 70368 70371 70379 70465 70478 70502 70509 70512 70517 70709 70712 70727 70835 70852 71090 71096 71105 71216 71219 71233 71344 71352 71453 71468 71724 71727 71739 71985 72004 72145 72148 72156 72161 72193 72203 72245 72255 72273 72284 72324 72330 72346 72752 72768 72850 72887 73009 73015 73023 73032 73098 73112 73526 73531 78896 78913 78919 78934 92912 92917 92976 92983 94033 94088 94095 94099 113824 113828 118528 118599 119143 119146 119150 119155 119163 119180 119210 119214 119362 119365 121344 121399 121403 121453 121499 121520 122880 122923 123184 123191 123628 123632 124140 124144 125136 125143 125252 125259 126976 127232 127245 127248 127340 127346 127377 127387 127405 127462 127489 127504 127538 127552 127561 127995 128000 128318 128326 128592 128640 128768 128884 128896 128981 129024 129036 129040 129096 129104 129114 129120 129160 129168 129198 129280 129292 129792 130048 131070 917504 917536 917632 917760 918000 921600 ) _ble_unicode_GraphemeClusterBreak_rule=( 0 0 1 0 1 2 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 2 0 0 0 0 0 0 3 0 0 6 1 1 2 0 1 2 1 2 2 2 2 2 2 2 2 2 2 2 1 1 0 0 1 0 1 2 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 1 2 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 1 2 4 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 1 2 0 1 1 0 1 1 0 0 0 0 1 1 0 0 1 0 1 2 0 0 1 1 0 0 0 0 0 0 1 1 0 0 1 0 1 2 0 0 0 1 0 0 0 0 0 0 1 1 0 0 1 0 1 2 0 0 1 1 0 0 0 0 0 0 1 1 0 0 1 0 1 2 0 0 0 1 0 0 0 0 0 0 1 1 0 0 1 0 1 2 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 1 2 0 0 0 0 0 0 0 0 5 0 1 1 0 0 1 0 1 2 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 1 2 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 1 2 0 0 0 0 0 0 0 0 0 6 1 1 0 0 1 0 1 2 0 0 0 0 0 0 0 0 0 6 1 1 ) _ble_unicode_GraphemeClusterBreak_custom[0x1F3FB]=$_ble_unicode_GraphemeClusterBreak_Pictographic _ble_unicode_GraphemeClusterBreak_custom[0x1F3FC]=$_ble_unicode_GraphemeClusterBreak_Pictographic _ble_unicode_GraphemeClusterBreak_custom[0x1F3FD]=$_ble_unicode_GraphemeClusterBreak_Pictographic _ble_unicode_GraphemeClusterBreak_custom[0x1F3FE]=$_ble_unicode_GraphemeClusterBreak_Pictographic _ble_unicode_GraphemeClusterBreak_custom[0x1F3FF]=$_ble_unicode_GraphemeClusterBreak_Pictographic _ble_unicode_GraphemeClusterBreak_custom[0xFF9E]=$_ble_unicode_GraphemeClusterBreak_Other _ble_unicode_GraphemeClusterBreak_custom[0xFF9F]=$_ble_unicode_GraphemeClusterBreak_Other function ble/unicode/GraphemeCluster/c2break { local code=$1 ret=${_ble_unicode_GraphemeClusterBreak_custom[code]} [[ $ret ]] && return 0 ret=${_ble_unicode_GraphemeClusterBreak[code]} [[ $ret ]] && return 0 ((ret>_ble_unicode_GraphemeClusterBreak_MaxCode)) && { ret=0; return 0; } local l=0 u=${#_ble_unicode_GraphemeClusterBreak_ranges[@]} m while ((l+1/dev/null # suppress locale error #D1440 ble/unicode/GraphemeCluster/s2break/.initialize function ble/unicode/GraphemeCluster/s2break/.combine-surrogate { local code1=$1 code2=$2 s=$3 if ((0xDC00<=code2&&code2<=0xDFFF)); then ((c=0x10000+(code1-0xD800)*1024+(code2&0x3FF))) else local ret ble/util/s2bytes "$s" ble/encoding:UTF-8/b2c "${ret[@]}" c=$ret fi } if ((_ble_unicode_GraphemeCluster_bomlen==2&&40300<=_ble_bash&&_ble_bash<50000)); then function ble/unicode/GraphemeCluster/s2break/.wa-bash43bug-uFFFF { local code=$1 ((0xD7F8<=code&&code<0xD800)) && ble/util/is-unicode-output && ret=$_ble_unicode_GraphemeClusterBreak_HighSurrogate } else function ble/unicode/GraphemeCluster/s2break/.wa-bash43bug-uFFFF { ((0)); } fi if ((_ble_unicode_GraphemeCluster_ucs4len==2)); then if ((_ble_bash<50000)); then function ble/unicode/GraphemeCluster/s2break/.wa-cygwin-LSG { local code=$1 ((code==0)) && ble/util/is-unicode-output && ret=$_ble_unicode_GraphemeClusterBreak_LowSurrogate } else function ble/unicode/GraphemeCluster/s2break/.wa-cygwin-LSG { local code=$1 ((0x80<=code&&code<0xC0)) && ble/util/is-unicode-output && ret=$_ble_unicode_GraphemeClusterBreak_LowSurrogate } fi else function ble/unicode/GraphemeCluster/s2break/.wa-cygwin-LSG { ((0)); } fi function ble/unicode/GraphemeCluster/s2break-left { ret=0 local s=$1 N=${#1} i=$2 opts=$3 sh=1 ((i>0)) && ble/util/s2c "${s:i-1:2}"; local c=$ret code2=$ret # Note2 (上述) ble/unicode/GraphemeCluster/c2break "$code2"; local break=$ret ((i-1=0&&ret==_ble_unicode_GraphemeClusterBreak_LowSurrogate)); then ble/util/s2c "${s:i-2:2}"; local code1=$ret # Note2 (上述) ble/unicode/GraphemeCluster/c2break "$code1" ble/unicode/GraphemeCluster/s2break/.wa-bash43bug-uFFFF "$code1" if ((ret==_ble_unicode_GraphemeClusterBreak_HighSurrogate)); then ble/unicode/GraphemeCluster/s2break/.combine-surrogate "$code1" "$code2" "${s:i-2:2}" ble/unicode/GraphemeCluster/c2break "$c" break=$ret sh=2 fi elif ((i0;j-=shift)); do ble/unicode/GraphemeCluster/s2break-left "$text" "$j" shift ((_ble_unicode_GraphemeClusterBreak_isExtend[ret])) || break done if ((j==0||ret!=_ble_unicode_GraphemeClusterBreak_Pictographic)); then ((ret=i)) return 0 else ((i=j-shift,b1=ret)) return 1 fi } function ble/unicode/GraphemeCluster/find-previous-boundary/.RI { if [[ :$bleopt_emoji_opts: != *:ri:* ]]; then ((ret=i)) return 0 fi local j1=$((i-shift)) local j shift=1 countRI=1 for ((j=j1;j>0;j-=shift,countRI++)); do ble/unicode/GraphemeCluster/s2break-left "$text" "$j" shift ((ret==_ble_unicode_GraphemeClusterBreak_Regional_Indicator)) || break done if ((j==j1)); then ((i=j,b1=_ble_unicode_GraphemeClusterBreak_Regional_Indicator)) return 1 else ((ret=countRI%2==1?j1:i)) return 0 fi } function ble/unicode/GraphemeCluster/find-previous-boundary/.InCB { if [[ $bleopt_grapheme_cluster != extended ]] || ((_ble_unicode_c2w_version<17)); then ret=$i return 0 fi local out=$i j=$i count_linker=0 local b1=$b1 shift=$shift while case $b1 in ("$_ble_unicode_GraphemeClusterBreak_InCB_Consonant") if ((count_linker)); then count_linker=0 ((out=j-shift)) fi ;; ("$_ble_unicode_GraphemeClusterBreak_InCB_Linker") ((count_linker++)) ;; ("$_ble_unicode_GraphemeClusterBreak_InCB_Extend"|"$_ble_unicode_GraphemeClusterBreak_ZWJ") ;; (*) break ;; esac ((j-=shift,j>0)) do ble/unicode/GraphemeCluster/s2break-left "$text" "$j" shift b1=$ret done if ((out0)); do local b2=$b1 ble/unicode/GraphemeCluster/s2break-left "$text" "$i" shift; local b1=$ret case ${_ble_unicode_GraphemeClusterBreak_rule[b1*_ble_unicode_GraphemeClusterBreak_Count+b2]} in (0) break ;; (1) ((i-=shift)) ;; (2) [[ $bleopt_grapheme_cluster != extended ]] && break; ((i-=shift)) ;; (3) ble/unicode/GraphemeCluster/find-previous-boundary/.ZWJ && return 0 ;; (4) ble/unicode/GraphemeCluster/find-previous-boundary/.RI && return 0 ;; (6) ble/unicode/GraphemeCluster/find-previous-boundary/.InCB && return 0;; (5) ((i-=shift)) ble/unicode/GraphemeCluster/s2break-right "$text" "$i"; b1=$ret ;; esac done fi ret=$i return 0 } _ble_unicode_GraphemeClusterBreak_isCore=() _ble_unicode_GraphemeClusterBreak_isCore[_ble_unicode_GraphemeClusterBreak_Other]=1 _ble_unicode_GraphemeClusterBreak_isCore[_ble_unicode_GraphemeClusterBreak_Control]=1 _ble_unicode_GraphemeClusterBreak_isCore[_ble_unicode_GraphemeClusterBreak_Regional_Indicator]=1 _ble_unicode_GraphemeClusterBreak_isCore[_ble_unicode_GraphemeClusterBreak_L]=1 _ble_unicode_GraphemeClusterBreak_isCore[_ble_unicode_GraphemeClusterBreak_V]=1 _ble_unicode_GraphemeClusterBreak_isCore[_ble_unicode_GraphemeClusterBreak_T]=1 _ble_unicode_GraphemeClusterBreak_isCore[_ble_unicode_GraphemeClusterBreak_LV]=1 _ble_unicode_GraphemeClusterBreak_isCore[_ble_unicode_GraphemeClusterBreak_LVT]=1 _ble_unicode_GraphemeClusterBreak_isCore[_ble_unicode_GraphemeClusterBreak_Pictographic]=1 _ble_unicode_GraphemeClusterBreak_isCore[_ble_unicode_GraphemeClusterBreak_HighSurrogate]=1 _ble_unicode_GraphemeClusterBreak_isCore[_ble_unicode_GraphemeClusterBreak_InCB_Consonant]=1 _ble_unicode_GraphemeClusterBreak_isExtend=() _ble_unicode_GraphemeClusterBreak_isExtend[_ble_unicode_GraphemeClusterBreak_Extend]=1 _ble_unicode_GraphemeClusterBreak_isExtend[_ble_unicode_GraphemeClusterBreak_InCB_Extend]=1 _ble_unicode_GraphemeClusterBreak_isExtend[_ble_unicode_GraphemeClusterBreak_InCB_Linker]=1 function ble/unicode/GraphemeCluster/extend-ascii { extend=0 [[ $_ble_util_locale_encoding != UTF-8 || ! $bleopt_grapheme_cluster ]] && return 1 local text=$1 iN=${#1} i=$2 ret shift=1 for ((;i=iN)); then c=0 w=0 cs= cb= extend=0 return 1 elif ! ble/util/is-unicode-output || [[ ! $bleopt_grapheme_cluster ]]; then cs=${text:i:1} ble/util/s2c "$cs"; c=$ret if [[ $flags != *R* ]] && { ble/unicode/GraphemeCluster/c2break "$c" ((ret==_ble_unicode_GraphemeClusterBreak_Control)); }; then ble/unicode/GraphemeCluster/.get-ascii-rep "$c" w=${#cs} else ble/util/c2w "$c"; w=$ret fi extend=0 return 0 fi local b0 b1 b2 c0 c2 shift code ble/unicode/GraphemeCluster/s2break-right "$text" "$i" code:shift; c0=$code b0=$ret local coreb= corec= npre=0 vs= ri= InCB_state= c2=$c0 b2=$b0 while ((j=17&&InCB_state)) || break ;; (5) ble/unicode/GraphemeCluster/s2break-left "$text" "$((j+shift))" code; c2=$code b2=$ret ;; esac done c=$corec cb=$coreb cs=${text:i:j-i} ((extend=j-i-1)) if [[ ! $corec ]]; then if [[ $flags != *R* ]]; then ((c=c0,cb=0,corec=0x25CC)) # 基底が存在しない時は点線円 ble/util/c2s "$corec" cs=${text:i:npre}$ret${text:i+npre:j-i-npre} else local code ble/unicode/GraphemeCluster/s2break-right "$cs" 0 code c=$code corec=$code cb=$ret fi fi if ((cb==_ble_unicode_GraphemeClusterBreak_Control)); then if [[ $flags != *R* ]]; then ble/unicode/GraphemeCluster/.get-ascii-rep "$c" w=${#cs} else w=0 fi else if [[ $vs == tpvs && :$bleopt_emoji_opts: == *:tpvs:* ]]; then bleopt_emoji_width= ble/util/c2w "$corec"; w=$ret elif [[ $vs == epvs && :$bleopt_emoji_opts: == *:epvs:* ]]; then w=${bleopt_emoji_width:-2} else ble/util/c2w "$corec"; w=$ret fi fi return 0 } function ble/canvas/attach { ble/util/c2w:auto/check } function ble/canvas/put.draw { DRAW_BUFF[${#DRAW_BUFF[*]}]=$1 } function ble/canvas/put-ind.draw { local count=${1-1} ind=$_ble_term_ind [[ :$2: == *:true-ind:* ]] && ind=$'\eD' local ret; ble/string#repeat "$ind" "$count" DRAW_BUFF[${#DRAW_BUFF[*]}]=$ret } function ble/canvas/put-ri.draw { local count=${1-1} local ret; ble/string#repeat "$_ble_term_ri" "$count" DRAW_BUFF[${#DRAW_BUFF[*]}]=$ret } function ble/canvas/put-il.draw { local value=${1-1} ((value>0)) || return 0 DRAW_BUFF[${#DRAW_BUFF[*]}]=${_ble_term_il//'%d'/$value} DRAW_BUFF[${#DRAW_BUFF[*]}]=$_ble_term_el2 # Note #D1214: 最終行対策 cygwin, linux } function ble/canvas/put-dl.draw { local value=${1-1} ((value>0)) || return 0 DRAW_BUFF[${#DRAW_BUFF[*]}]=$_ble_term_el2 # Note #D1214: 最終行対策 cygwin, linux DRAW_BUFF[${#DRAW_BUFF[*]}]=${_ble_term_dl//'%d'/$value} } if ((_ble_bash>=40000)) && [[ ( $OSTYPE == cygwin || $OSTYPE == msys ) && $TERM == xterm-256color ]]; then function ble/canvas/.is-il-workaround-required { local value=$1 opts=$2 [[ ! $_ble_term_DA2R ]] || return 1 ((value==1)) || return 1 [[ :$opts: == *:vfill:* || :$opts: == *:no-lastline:* ]] && return 1 [[ :$opts: == *:panel:* ]] && ! ble/canvas/panel/is-last-line && return 1 return 0 } function ble/canvas/put-il.draw { local value=${1-1} opts=$2 ((value>0)) || return 0 if ble/canvas/.is-il-workaround-required "$value" "$2"; then if [[ :$opts: == *:panel:* ]]; then DRAW_BUFF[${#DRAW_BUFF[*]}]=$_ble_term_el2 else DRAW_BUFF[${#DRAW_BUFF[*]}]=$'\e[S\e[A\e[L\e[B\e[T' fi else DRAW_BUFF[${#DRAW_BUFF[*]}]=${_ble_term_il//'%d'/$value} DRAW_BUFF[${#DRAW_BUFF[*]}]=$_ble_term_el2 # Note #D1214: 最終行対策 cygwin, linux fi } function ble/canvas/put-dl.draw { local value=${1-1} opts=$2 ((value>0)) || return 0 if ble/canvas/.is-il-workaround-required "$value" "$2"; then if [[ :$opts: == *:panel:* ]]; then DRAW_BUFF[${#DRAW_BUFF[*]}]=$_ble_term_el2 else DRAW_BUFF[${#DRAW_BUFF[*]}]=$'\e[S\e[A\e[M\e[B\e[T' fi else DRAW_BUFF[${#DRAW_BUFF[*]}]=$_ble_term_el2 # Note #D1214: 最終行対策 cygwin, linux DRAW_BUFF[${#DRAW_BUFF[*]}]=${_ble_term_dl//'%d'/$value} fi } fi function ble/canvas/put-cuu.draw { local value=${1-1} DRAW_BUFF[${#DRAW_BUFF[*]}]=${_ble_term_cuu//'%d'/$value} } function ble/canvas/put-cud.draw { local value=${1-1} DRAW_BUFF[${#DRAW_BUFF[*]}]=${_ble_term_cud//'%d'/$value} } function ble/canvas/put-cuf.draw { local value=${1-1} DRAW_BUFF[${#DRAW_BUFF[*]}]=${_ble_term_cuf//'%d'/$value} } function ble/canvas/put-cub.draw { local value=${1-1} DRAW_BUFF[${#DRAW_BUFF[*]}]=${_ble_term_cub//'%d'/$value} } function ble/canvas/put-cup.draw { local l=${1-1} c=${2-1} local out=$_ble_term_cup out=${out//'%l'/$l} out=${out//'%c'/$c} out=${out//'%y'/$((l-1))} out=${out//'%x'/$((c-1))} DRAW_BUFF[${#DRAW_BUFF[*]}]=$out } function ble/canvas/put-hpa.draw { local c=${1-1} local out=$_ble_term_hpa out=${out//'%c'/$c} out=${out//'%x'/$((c-1))} DRAW_BUFF[${#DRAW_BUFF[*]}]=$out } function ble/canvas/put-vpa.draw { local l=${1-1} local out=$_ble_term_vpa out=${out//'%l'/$l} out=${out//'%y'/$((l-1))} DRAW_BUFF[${#DRAW_BUFF[*]}]=$out } function ble/canvas/put-ech.draw { local value=${1:-1} esc if [[ $_ble_term_ech ]]; then esc=${_ble_term_ech//'%d'/$value} else ble/string#reserve-prototype "$value" esc=${_ble_string_prototype::value}${_ble_term_cub//'%d'/$value} fi DRAW_BUFF[${#DRAW_BUFF[*]}]=$esc } function ble/canvas/put-spaces.draw { local value=${1:-1} ble/string#reserve-prototype "$value" DRAW_BUFF[${#DRAW_BUFF[*]}]=${_ble_string_prototype::value} } function ble/canvas/put-move-x.draw { local dx=$1 ((dx)) || return 1 if ((dx>0)); then ble/canvas/put-cuf.draw "$dx" else ble/canvas/put-cub.draw "$((-dx))" fi } function ble/canvas/put-move-y.draw { local dy=$1 ((dy)) || return 1 if ((dy>0)); then if [[ $MC_SID == $$ ]]; then ble/canvas/put-ind.draw "$dy" true-ind else ble/canvas/put-cud.draw "$dy" fi else ble/canvas/put-cuu.draw "$((-dy))" fi } function ble/canvas/put-move.draw { ble/canvas/put-move-x.draw "$1" ble/canvas/put-move-y.draw "$2" } function ble/canvas/flush.draw { IFS= builtin eval 'ble/util/put "${DRAW_BUFF[*]}"' DRAW_BUFF=() } function ble/canvas/sflush.draw { 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 { IFS= builtin eval 'ble/util/buffer "${DRAW_BUFF[*]}"' DRAW_BUFF=() } function ble/canvas/put-clear-lines.draw { local old=${1:-1} local new=${2:-$old} if ((old==1&&new==1)); then ble/canvas/put.draw "$_ble_term_el2" else ble/canvas/put-dl.draw "$old" "$3" ble/canvas/put-il.draw "$new" "$3" fi } function ble/canvas/trace/.put-sgr.draw { local ret g=$1 if ((g==0)); then ble/canvas/put.draw "$opt_sgr0" else ble/color/g.compose "$opt_g0" "$g" "$trace_g2sgr" "$g" ble/canvas/put.draw "$ret" fi } function ble/canvas/trace/.measure-point { if [[ $flag_bbox ]]; then ((x0)) || return 0 if [[ $flag_gbox ]]; then if [[ ! $gx1 ]]; then ((gx1=gx2=x,gy1=gy2=y)) else ((xx2)) && x2=$x [[ $flag_gbox ]] && ((x>gx2)) && gx2=$x if ((x==cols&&!xenl)); then ((y++,x=0)) if [[ $flag_bbox ]]; then ((xy2)) && y2=$y fi fi else if [[ $type == atomic ]]; then ((y++,x=w0&&(x1=0))) ((x2y2)) && y2=$y fi if [[ $flag_gbox ]]; then ((gx1>0&&(gx1=0))) ((gx2gy2)) && gy2=$y fi fi ((x==0&&(lc=32,lg=0))) return 0 } function ble/canvas/trace/.put-atomic.draw { local c=$1 w=$2 if [[ $flag_clip ]]; then ((cy1<=y&&ycx2)) && value=${value::${#value}-(xR-cx2)} xR=$cx2 ble/canvas/put-move.draw "$((x-cx))" "$((y-cy))" ble/canvas/put.draw "$value" ((cx=xR,cy=y)) else ble/canvas/put.draw "$value" fi ble/canvas/trace/.implicit-move "$w" } function ble/canvas/trace/.process-overflow { [[ :$opts: == *:truncate:* ]] && i=$iN # stop if ((y+1==lines)) && [[ :$opts: == *:ellipsis:* ]]; then local ellipsis=... w=3 wmax=$xlimit ((w>wmax)) && ellipsis=${ellipsis::wmax} w=$wmax if ble/util/is-unicode-output; then local symbol='…' ret ble/util/s2c "$symbol" ble/util/c2w "$ret" ((ret<=wmax)) && ellipsis=$symbol w=$ret fi local ox=$x oy=$y ble/canvas/trace/.goto "$((wmax-w))" "$((lines-1))" ble/canvas/trace/.put-atomic.draw "$ellipsis" "$w" ble/canvas/trace/.goto "$ox" "$oy" fi } function ble/canvas/trace/.justify/inc-quote { [[ $trace_flags == *J* ]] || return 0 ((trace_sclevel++)) flag_justify= } function ble/canvas/trace/.justify/dec-quote { [[ $trace_flags == *J* ]] || return 0 ((--trace_sclevel)) || flag_justify=1 } function ble/canvas/trace/.justify/begin-line { ((jx0=x1=x2=x,jy0=y1=y2=y)) gx1= gx2= gy1= gy2= [[ $justify_align == *[cr]* ]] && ble/canvas/trace/.justify/next-field } function ble/canvas/trace/.justify/next-field { local sep=$1 wmin=0 local esc; ble/canvas/sflush.draw -v esc [[ $sep == ' ' ]] && wmin=1 ble/array#push justify_fields "${sep:-\$}:$wmin:$jx0,$jy0,$x,$y:$x1,$y1,$x2,$y2:$gx1,$gy1,$gx2,$gy2:$esc" ((x+=wmin,jx0=x1=x2=x,jy0=y1=y2=y)) } function ble/canvas/trace/.justify/unpack { local data=$1 buff sep=${data::1}; data=${data:2} wmin=${data%%:*}; data=${data#*:} ble/string#split buff , "${data%%:*}"; data=${data#*:} xI=${buff[0]} yI=${buff[1]} xF=${buff[2]} yF=${buff[3]} ble/string#split buff , "${data%%:*}"; data=${data#*:} x1=${buff[0]} y1=${buff[1]} x2=${buff[2]} y2=${buff[3]} ble/string#split buff , "${data%%:*}"; data=${data#*:} gx1=${buff[0]} gy1=${buff[1]} gx2=${buff[2]} gy2=${buff[3]} esc=$data } function ble/canvas/trace/.justify/end-line { if [[ $trace_flags == *B* ]]; then ((yjy2&&(jy2=y))) fi ((${#justify_fields[@]}||${#DRAW_BUFF[@]})) || return 0 ble/canvas/trace/.justify/next-field [[ $justify_align == *c* ]] && ble/canvas/trace/.justify/next-field local i width=0 ispan=0 has_content= for ((i=0;i<${#justify_fields[@]};i++)); do local sep wmin xI yI xF yF x1 y1 x2 y2 gx1 gy1 gx2 gy2 esc ble/canvas/trace/.justify/unpack "${justify_fields[i]}" ((width+=xF-xI)) [[ $esc ]] && has_content=1 ((i+1==${#justify_fields[@]})) && break ((width+=wmin)) ((ispan++)) done if [[ ! $has_content ]]; then justify_fields=() return 0 fi local nspan=$ispan local -a DRAW_BUFF=() local xlimit=$cols [[ $_ble_term_xenl$opt_relative ]] || ((xlimit--)) local span=$((xlimit-width)) x= y= local ispan=0 vx=0 spanx=0 for ((i=0;i<${#justify_fields[@]};i++)); do local sep wmin xI yI xF yF x1 y1 x2 y2 gx1 gy1 gx2 gy2 esc ble/canvas/trace/.justify/unpack "${justify_fields[i]}" if [[ ! $x ]]; then x=$xI y=$yI if [[ $justify_align == right ]]; then ble/canvas/put-move-x.draw "$((cols-1-x))" ((x=cols-1)) fi fi if [[ $esc ]]; then local delta=0 ((vx+x1-xI<0)) && ((delta=-(vx+x1-xI))) ((vx+x2-xI>xlimit)) && ((delta=xlimit-(vx+x2-xI))) ble/canvas/put-move-x.draw "$((vx+delta-x))" ((x=vx+delta)) ble/canvas/put.draw "$esc" if [[ $trace_flags == *B* ]]; then ((x+x1-xIjx2&&(jx2=x+x2-xI))) ((y+y2-yI>jy2&&(jy2=y+y2-yI))) fi if [[ $flag_gbox && $gx1 ]]; then ((gx1+=x-xI,gx2+=x-xI)) ((gy1+=y-yI,gy2+=y-yI)) if [[ ! $jgx1 ]]; then ((jgx1=gx1,jgy1=gy1,jgx2=gx2,jgy2=gy2)) else ((gx1jgx2&&(jgx2=gx2))) ((gy2>jgy2&&(jgy2=gy2))) fi fi ((x+=xF-xI,y+=yF-yI,vx+=xF-xI)) fi ((i+1==${#justify_fields[@]})) && break local new_spanx=$((span*++ispan/nspan)) local wfill=$((wmin+new_spanx-spanx)) ((vx+=wfill,spanx=new_spanx)) if [[ $sep == ' ' ]]; then ble/string#reserve-prototype "$wfill" ble/canvas/put.draw "${_ble_string_prototype::wfill}" ((x+=wfill)) fi done local ret ble/canvas/sflush.draw ble/array#push justify_buff "$ret" justify_fields=() } function ble/canvas/trace/.decsc { [[ ${trace_decsc[5]} ]] || ble/canvas/trace/.justify/inc-quote trace_decsc=("$x" "$y" "$g" "$lc" "$lg" active) if [[ ! $flag_clip ]]; then [[ :$opts: == *:noscrc:* ]] || ble/canvas/put.draw "$_ble_term_sc" fi } function ble/canvas/trace/.decrc { [[ ${trace_decsc[5]} ]] && ble/canvas/trace/.justify/dec-quote if [[ ! $flag_clip ]]; then ble/canvas/trace/.put-sgr.draw "${trace_decsc[2]}" # g を明示的に復元。 if [[ :$opts: == *:noscrc:* ]]; then ble/canvas/put-move.draw "$((trace_decsc[0]-x))" "$((trace_decsc[1]-y))" else ble/canvas/put.draw "$_ble_term_rc" fi fi x=${trace_decsc[0]} y=${trace_decsc[1]} g=${trace_decsc[2]} lc=${trace_decsc[3]} lg=${trace_decsc[4]} trace_decsc[5]= } function ble/canvas/trace/.scosc { [[ ${trace_scosc[5]} ]] || ble/canvas/trace/.justify/inc-quote trace_scosc=("$x" "$y" "$g" "$lc" "$lg" active) if [[ ! $flag_clip ]]; then [[ :$opts: == *:noscrc:* ]] || ble/canvas/put.draw "$_ble_term_sc" fi } function ble/canvas/trace/.scorc { [[ ${trace_scosc[5]} ]] && ble/canvas/trace/.justify/dec-quote if [[ ! $flag_clip ]]; then ble/canvas/trace/.put-sgr.draw "$g" # g は変わらない様に。 if [[ :$opts: == *:noscrc:* ]]; then ble/canvas/put-move.draw "$((trace_scosc[0]-x))" "$((trace_scosc[1]-y))" else ble/canvas/put.draw "$_ble_term_rc" fi fi x=${trace_scosc[0]} y=${trace_scosc[1]} lc=${trace_scosc[3]} lg=${trace_scosc[4]} trace_scosc[5]= } function ble/canvas/trace/.ps1sc { ble/canvas/trace/.justify/inc-quote trace_brack[${#trace_brack[*]}]="$x $y" } function ble/canvas/trace/.ps1rc { local lastIndex=$((${#trace_brack[*]}-1)) if ((lastIndex>=0)); then ble/canvas/trace/.justify/dec-quote local -a scosc ble/string#split-words scosc "${trace_brack[lastIndex]}" ((x=scosc[0])) ((y=scosc[1])) builtin unset -v "trace_brack[$lastIndex]" fi } function ble/canvas/trace/.NEL { if [[ $opt_nooverflow ]] && ((y+1>=lines)); then ble/canvas/trace/.process-overflow return 1 fi [[ $flag_justify ]] && ble/canvas/trace/.justify/end-line if [[ ! $flag_clip ]]; then if [[ $opt_relative ]]; then ((x)) && ble/canvas/put-cub.draw "$x" ble/canvas/put-cud.draw 1 else ble/canvas/put.draw "$_ble_term_cr" ble/canvas/put.draw "$_ble_term_nl" fi fi ((y++,x=0,lc=32,lg=0)) if [[ $flag_bbox ]]; then ((xy2)) && y2=$y fi [[ $flag_justify ]] && ble/canvas/trace/.justify/begin-line return 0 } function ble/canvas/trace/.SGR { local param=$1 seq=$2 specs i iN if [[ ! $param ]]; then g=0 [[ $flag_clip ]] || ble/canvas/put.draw "$opt_sgr0" return 0 fi if [[ $opt_terminfo ]]; then ble/color/read-sgrspec "$param" else ble/color/read-sgrspec "$param" ansi fi [[ $flag_clip ]] || ble/canvas/trace/.put-sgr.draw "$g" } function ble/canvas/trace/.process-csi-sequence { local seq=$1 seq1=${1:2} rex local char=${seq1:${#seq1}-1:1} param=${seq1::${#seq1}-1} if [[ ! ${param//[0-9:;]} ]]; then case $char in (m) # SGR ble/canvas/trace/.SGR "$param" "$seq" return 0 ;; ([ABCDEFGIZ\`ade]) local arg=0 [[ $param =~ ^[0-9]+$ ]] && ((arg=10#0$param)) ((arg==0&&(arg=1))) local ox=$x oy=$y if [[ $char == A ]]; then ((y-=arg,y<0&&(y=0))) ((!flag_clip&&y=lines&&(y=lines-1))) ((!flag_clip&&y>oy)) && ble/canvas/put-cud.draw "$((y-oy))" elif [[ $char == [Ca] ]]; then ((x+=arg,x>=cols&&(x=cols-1))) ((!flag_clip&&x>ox)) && ble/canvas/put-cuf.draw "$((x-ox))" elif [[ $char == D ]]; then ((x-=arg,x<0&&(x=0))) ((!flag_clip&&x=lines&&(y=lines-1),x=0)) if [[ ! $flag_clip ]]; then ((y>oy)) && ble/canvas/put-cud.draw "$((y-oy))" ble/canvas/put.draw "$_ble_term_cr" fi elif [[ $char == F ]]; then ((y-=arg,y<0&&(y=0),x=0)) if [[ ! $flag_clip ]]; then ((y=cols&&(x=cols-1))) if [[ ! $flag_clip ]]; then if [[ $opt_relative ]]; then ble/canvas/put-move-x.draw "$((x-ox))" else ble/canvas/put-hpa.draw "$((x+1))" fi fi elif [[ $char == d ]]; then ((y=arg-1,y<0&&(y=0),y>=lines&&(y=lines-1))) if [[ ! $flag_clip ]]; then if [[ $opt_relative ]]; then ble/canvas/put-move-y.draw "$((y-oy))" else ble/canvas/put-vpa.draw "$((y+1))" fi fi elif [[ $char == I ]]; then 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 local tx ((tx=((x+it-1)/it-arg)*it, tx<0&&(tx=0))) if ((tx=cols&&(dstx=cols-1), dsty<0&&(dsty=0),dsty>=lines&&(dsty=lines-1))) ble/canvas/trace/.goto "$dstx" "$dsty" lc=-1 lg=0 return 0 ;; ([su]) # SCOSC SCORC if [[ $char == s ]]; then ble/canvas/trace/.scosc else ble/canvas/trace/.scorc fi return 0 ;; esac fi ble/canvas/put.draw "$seq" } function ble/canvas/trace/.process-esc-sequence { local seq=$1 char=${1:1} case $char in (7) # DECSC ble/canvas/trace/.decsc return 0 ;; (8) # DECRC ble/canvas/trace/.decrc return 0 ;; (D) # IND [[ $opt_nooverflow ]] && ((y+1>=lines)) && return 0 if [[ $flag_clip || $opt_relative || $flag_justify ]]; then ((y+1>=lines)) && return 0 ((y++)) [[ $flag_clip ]] || ble/canvas/put-cud.draw 1 else ((y++)) ble/canvas/put.draw "$_ble_term_ind" [[ $_ble_term_ind != $'\eD' ]] && ble/canvas/put-hpa.draw "$((x+1))" # tput ind が唯の改行の時がある fi lc=-1 lg=0 ble/canvas/trace/.measure-point return 0 ;; (M) # RI [[ $opt_nooverflow ]] && ((y==0)) && return 0 if [[ $flag_clip || $opt_relative || $flag_justify ]]; then ((y==0)) && return 0 ((y--)) [[ $flag_clip ]] || ble/canvas/put-cuu.draw 1 else ((y--)) ble/canvas/put.draw "$_ble_term_ri" fi lc=-1 lg=0 ble/canvas/trace/.measure-point return 0 ;; (E) # NEL ble/canvas/trace/.NEL return 0 ;; esac ble/canvas/put.draw "$seq" } function ble/canvas/trace/.impl { local text=$1 opts=$2 local LC_ALL= LC_COLLATE=C local cols=${COLUMNS:-80} lines=${LINES:-25} local it=${bleopt_tab_width:-$_ble_term_it} xenl=$_ble_term_xenl ble/string#reserve-prototype "$it" local ret rex ble/util/c2s 156; local st=$ret # œ (ST) ((${#st}>=2)) && st= local xinit=$x yinit=$y ginit=$g local trace_flags= local opt_nooverflow=; [[ :$opts: == *:truncate:* || :$opts: == *:confine:* ]] && opt_nooverflow=1 local opt_relative=; [[ :$opts: == *:relative:* ]] && trace_flags=R$trace_flags opt_relative=1 [[ :$opts: == *:measure-bbox:* ]] && trace_flags=B$trace_flags [[ :$opts: == *:measure-gbox:* ]] && trace_flags=G$trace_flags [[ :$opts: == *:left-char:* ]] && trace_flags=L$trace_flags local opt_terminfo=; [[ :$opts: == *:terminfo:* ]] && opt_terminfo=1 if local rex=':(justify(=[^:]+)?|center|right):'; [[ :$opts: =~ $rex ]]; then trace_flags=J$trace_flags local jx0=$x jy0=$y local justify_sep= justify_align= local -a justify_buff=() local -a justify_fields=() case ${BASH_REMATCH[1]} in (justify*) justify_sep=${BASH_REMATCH[2]:1}${BASH_REMATCH[2]:-' '} ;; (center) justify_align=c ;; (right) justify_align=r ;; esac fi if local rex=':clip=([0-9]*),([0-9]*)([-+])([0-9]*),([0-9]*):'; [[ :$opts: =~ $rex ]]; then local cx1 cy1 cx2 cy2 cx cy cg trace_flags=C$trace_flags cx1=${BASH_REMATCH[1]} cy1=${BASH_REMATCH[2]} cx2=${BASH_REMATCH[4]} cy2=${BASH_REMATCH[5]} [[ ${BASH_REMATCH[3]} == + ]] && ((cx2+=cx1,cy2+=cy1)) ((cx1<=cx2)) || local cx1=$cx2 cx2=$cx1 ((cy1<=cy2)) || local cy1=$cy2 cy2=$cy1 ((cx1<0)) && cx1=0 ((cy1<0)) && cy1=0 ((cols0)); then [[ $flag_clip ]] || ble/canvas/put.draw "$s" ((x--,lc=32,lg=g)) ble/canvas/trace/.measure-point fi ;; ($'\t') # HT local tx ((tx=(x+it)/it*it, tx>=cols&&(tx=cols-1))) if ((xwmax)) && w=$wmax is_overflow=1 fi local t=${s::w} if [[ $flag_clip || $opt_relative || $flag_justify ]]; then local tlen=$w len=$((cols-x)) if ((tlen>len)); then while ((tlen>len)); do ble/canvas/trace/.put-ascii.draw "${t::len}" t=${t:len} ((x=cols,tlen-=len,len=cols)) ble/canvas/trace/.NEL done w=${#t} fi fi if [[ $flag_lchar ]]; then local ret ble/util/s2c "${s:w-1:1}" lc=$ret lg=$g fi ble/canvas/trace/.put-ascii.draw "$t" ((i+=${#s})) if local extend; ble/unicode/GraphemeCluster/extend-ascii "$text" "$i"; then ble/canvas/trace/.put-atomic.draw "${text:i:extend}" 0 ((i+=extend)) fi else local c w cs cb extend ble/unicode/GraphemeCluster/match "$text" "$i" R if [[ $opt_nooverflow ]] && ! ((x+w<=xlimit||y+1cols)); then if [[ $flag_clip || $opt_relative || $flag_justify ]]; then ble/canvas/trace/.NEL else ble/canvas/trace/.put-ascii.draw "${_ble_string_prototype::cols-x}" fi fi lc=$c lg=$g ble/canvas/trace/.put-atomic.draw "$cs" "$w" fi ((i+=1+extend)) fi [[ $is_overflow ]] && ble/canvas/trace/.process-overflow done if [[ $trace_flags == *J* ]]; then if [[ ! $flag_justify ]]; then [[ ${trace_scosc[5]} ]] && ble/canvas/trace/.scorc [[ ${trace_decsc[5]} ]] && ble/canvas/trace/.decrc while [[ ${trace_brack[0]} ]]; do ble/canvas/trace/.ps1rc; done fi ble/canvas/trace/.justify/end-line DRAW_BUFF=("${justify_buff[@]}") [[ $trace_flags == *B* ]] && ((x1=jx1,y1=jy1,x2=jx2,y2=jy2)) [[ $trace_flags == *G* ]] && gx1=$jgx1 gy1=$jgy1 gx2=$jgx2 gy2=$jgy2 if [[ $trace_flags == *C* ]]; then ble/canvas/sflush.draw x=$xinit y=$yinit g=$ginit local trace_opts=clip=$cx1,$cy1-$cx2,$cy2 [[ :$opts: == *:ansi:* ]] && trace_opts=$trace_opts:ansi ble/canvas/trace/.impl "$ret" "$trace_opts" cx=$x cy=$y cg=$g fi fi [[ $trace_flags == *B* ]] && ((y2++)) [[ $trace_flags == *G* ]] && ((gy2++)) if [[ $trace_flags == *C* ]]; then x=$cx y=$cy g=$cg if [[ $trace_flags == *B* ]]; then ((x1cx2)) && x1=$cx2 ((x2cx2)) && x2=$cx2 ((y1cy2)) && y1=$cy2 ((y2cy2)) && y2=$cy2 fi if [[ $trace_flags == *G* ]]; then if ((gx2<=cx1||cx2<=gx1||gy2<=cy1||cy2<=gy1)); then gx1= gx2= gy1= gy2= else ((gx1cx2)) && gx2=$cx2 ((gy1cy2)) && gy2=$cy2 fi fi fi } function ble/canvas/trace.draw { ble/canvas/trace/.impl "$@" 2>/dev/null # Note: suppress LC_COLLATE errors #D1205 #D1341 #D1440 } function ble/canvas/trace { local -a DRAW_BUFF=() ble/canvas/trace/.impl "$@" 2>/dev/null # Note: suppress LC_COLLATE errors #D1205 #D1341 #D1440 ble/canvas/sflush.draw # -> ret } function ble/canvas/trace-text/.put-simple { local nchar=$1 ((nchar)) || return 0 local nput=$((cols*lines-!_ble_term_xenl-(y*cols+x))) ((nput>0)) || return 1 ((nput>nchar)) && nput=$nchar out=$out${2::nput} ((x+=nput,y+=x/cols,x%=cols)) ((_ble_term_xenl&&x==0&&(y--,x=cols))) ((nput==nchar)); return "$?" } function ble/canvas/trace-text/.put-atomic { local w=$1 c=$2 ((y*cols+x+w<=cols*lines-!_ble_term_xenl)) || return 1 if ((xlimit)); then ble/string#reserve-prototype "$((limit-x))" local pad=${_ble_string_prototype::limit-x} out=$out$sgr1${pad//?/'#'}$sgr0 x=$limit ((y+10)); then local ret ble/unicode/GraphemeCluster/find-previous-boundary "$text" "$dbeg"; dbeg=$ret local pos ble/string#split-words pos "${_ble_textmap_pos[dbeg]}" ((x=pos[0])) ((y=pos[1])) fi fi _ble_textmap_cols=$cols _ble_textmap_length=$iN ble/util/assert '((dbeg<0||(dbeg<=dend&&dbeg<=dend0)))' "($dbeg $dend $dend0) <- ($_ble_textmap_dbeg $_ble_textmap_dend $_ble_textmap_dend0)" ble/array#reserve-prototype "$iN" local -a old_pos old_ichg old_pos=("${_ble_textmap_pos[@]:dend0:iN-dend+1}") old_ichg=("${_ble_textmap_ichg[@]}") _ble_textmap_pos=( "${_ble_textmap_pos[@]::dbeg+1}" "${_ble_array_prototype[@]::dend-dbeg}" "${_ble_textmap_pos[@]:dend0+1:iN-dend}") _ble_textmap_glyph=( "${_ble_textmap_glyph[@]::dbeg}" "${_ble_array_prototype[@]::dend-dbeg}" "${_ble_textmap_glyph[@]:dend0:iN-dend}") _ble_textmap_ichg=() ble/urange#shift --prefix=_ble_textmap_ "$dbeg" "$dend" "$dend0" local i extend for ((i=dbeg;i=cols)); then cs=' ' w=0 ble/textmap#update/.wrap else local x2 ((x2=(x/it+1)*it, x2>=cols&&(x2=cols-1), w=x2-x, w!=it&&(changed=1))) cs=${_ble_string_prototype::w} fi elif ((c==10)); then w=0 if [[ :$opts: == *:relative:* ]]; then local pad=$((cols-x)) eraser= if ((pad)); then if [[ $_ble_term_ech ]]; then eraser=${_ble_term_ech//'%d'/$pad} else eraser=${_ble_string_prototype::pad} ((x=cols)) fi fi local move=${_ble_term_cub//'%d'/$x}${_ble_term_cud//'%d'/1} cs=$eraser$move changed=1 else cs=$_ble_term_el$_ble_term_nl fi ((y++,x=0)) fi fi local wrapping=0 if ((w>0)); then if ((xcols)); do ((y++,x-=cols)) done if ((x==cols)); then ble/textmap#update/.wrap fi fi _ble_textmap_glyph[i]=$cs ((changed)) && ble/array#push _ble_textmap_ichg "$i" _ble_textmap_pos[i+1]="$x $y $wrapping" ((i++)) fi while ((extend--)); do _ble_textmap_glyph[i]= _ble_textmap_pos[++i]="$x $y 0" done if ((i>=dend)); then [[ ${old_pos[i-dend]} == "${_ble_textmap_pos[i]}" ]] && break if [[ ${old_pos[i-dend]%%[$IFS]*} == "${_ble_textmap_pos[i]%%[$IFS]*}" ]]; then local -a opos npos pos opos=(${old_pos[i-dend]}) npos=(${_ble_textmap_pos[i]}) local ydelta=$((npos[1]-opos[1])) while ((i=dend0)&&(ichg+=dend-dend0), (0<=ichg&&ichg_ble_textmap_endy)); then (($__ble_var=_ble_textmap_length)) elif ((__ble_y<_ble_textmap_begy)); then (($__ble_var=0)) else 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_yy||yh==y&&xh>x)); then index=$end lx=$x ly=$y rx=$x ry=$y elif "$getxy" "$beg"; ((yh0)) || continue ((count++)) ((min_delta<0||min_delta>delta)) && min_delta=$delta done ((count==0)) && break if ((count*min_delta<=room)); then for ((i=0;i0)) || continue ((heights[i]+=min_delta)) done ((room-=count*min_delta)) else local delta=$((room/count)) rem=$((room%count)) count=0 for ((i=0;i0)) || continue ((heights[i]+=delta)) ((count++=0;i--)); do local sub=$((heights[i]-heights[i]*lines/min)) if ((sub_ble_canvas_panel_height[i])) && ble/canvas/panel#set-height.draw "$i" "${heights[i]}" done } function ble/canvas/panel/is-last-line { local ret ble/arithmetic/sum "${_ble_canvas_panel_height[@]}" ((_ble_canvas_y==ret-1)) } function ble/canvas/panel/goto-bottom-dock.draw { if [[ ! $_ble_canvas_panel_bottom ]]; then _ble_canvas_panel_bottom=1 ble/canvas/excursion-start.draw ble/canvas/put-cup.draw "$LINES" 0 # 一番下の行に移動 ble/arithmetic/sum "${_ble_canvas_panel_height[@]}" ((_ble_canvas_x=0,_ble_canvas_y=ret-1)) fi } function ble/canvas/panel/goto-top-dock.draw { if [[ $_ble_canvas_panel_bottom ]]; then _ble_canvas_panel_bottom= ble/canvas/excursion-end.draw fi } function ble/canvas/panel/goto-vfill.draw { ble/canvas/panel/has-bottom-dock || return 1 local ret ble/canvas/panel/goto-top-dock.draw ble/arithmetic/sum "${_ble_canvas_panel_height[@]::_ble_canvas_panel_vfill}" ble/canvas/goto.draw 0 "$ret" sgr0 return 0 } function ble/canvas/panel/save-position { ret=$_ble_canvas_x:$_ble_canvas_y:$_ble_canvas_panel_bottom [[ :$2: == *:goto-top-dock:* ]] && ble/canvas/panel/goto-top-dock.draw } function ble/canvas/panel/load-position { local -a DRAW_BUFF=() ble/canvas/panel/load-position.draw "$@" ble/canvas/bflush.draw } function ble/canvas/panel/load-position.draw { local data=$1 local x=${data%%:*}; data=${data#*:} local y=${data%%:*}; data=${data#*:} local bottom=$data if [[ $bottom ]]; then ble/canvas/panel/goto-bottom-dock.draw else ble/canvas/panel/goto-top-dock.draw fi ble/canvas/goto.draw "$x" "$y" } function ble/canvas/panel/has-bottom-dock { local ret; ble/canvas/panel/bottom-dock#height ((ret)) } function ble/canvas/panel/bottom-dock#height { ret=0 [[ $_ble_canvas_panel_vfill && $_ble_term_rc ]] || return 0 ble/arithmetic/sum "${_ble_canvas_panel_height[@]:_ble_canvas_panel_vfill}" } function ble/canvas/panel/top-dock#height { if [[ $_ble_canvas_panel_vfill && $_ble_term_rc ]]; then ble/arithmetic/sum "${_ble_canvas_panel_height[@]::_ble_canvas_panel_vfill}" else ble/arithmetic/sum "${_ble_canvas_panel_height[@]}" fi } function ble/canvas/panel/bottom-dock#invalidate { [[ $_ble_canvas_panel_vfill && $_ble_term_rc ]] || return 0 local index n=${#_ble_canvas_panel_class[@]} for ((index=_ble_canvas_panel_vfill;index=_ble_canvas_panel_vfill)) } function ble/canvas/panel#get-origin { local ret index=$1 prefix= [[ $2 == --prefix=* ]] && prefix=${2#*=} ble/arithmetic/sum "${_ble_canvas_panel_height[@]::index}" ((${prefix}x=0,${prefix}y=ret)) } function ble/canvas/panel#goto.draw { local index=$1 x=${2-0} y=${3-0} opts=$4 ret if ble/canvas/panel#is-bottom "$index"; then ble/canvas/panel/goto-bottom-dock.draw else ble/canvas/panel/goto-top-dock.draw fi ble/arithmetic/sum "${_ble_canvas_panel_height[@]::index}" ble/canvas/goto.draw "$x" "$((ret+y))" "$opts" } function ble/canvas/panel#put.draw { ble/canvas/put.draw "$2" ble/canvas/panel#report-cursor-position "$1" "$3" "$4" } function ble/canvas/panel#report-cursor-position { local index=$1 x=${2-0} y=${3-0} ret ble/arithmetic/sum "${_ble_canvas_panel_height[@]::index}" ((_ble_canvas_x=x,_ble_canvas_y=ret+y)) } function ble/canvas/panel/increase-total-height.draw { local delta=$1 ((delta>0)) || return 1 local ret ble/canvas/panel/top-dock#height; local top_height=$ret ble/canvas/panel/bottom-dock#height; local bottom_height=$ret if ((bottom_height)); then ble/canvas/panel/goto-top-dock.draw if [[ $_ble_term_DECSTBM ]]; then ble/canvas/excursion-start.draw ble/canvas/put.draw $'\e[1;'$((LINES-bottom_height))'r' ble/canvas/excursion-end.draw ble/canvas/goto.draw 0 "$((top_height==0?0:top_height-1))" sgr0 ble/canvas/put-ind.draw "$((top_height-1+delta-_ble_canvas_y))" ((_ble_canvas_y=top_height-1+delta)) ble/canvas/excursion-start.draw ble/canvas/put.draw "$_ble_term_DECSTBM_reset" ble/canvas/excursion-end.draw return 0 else ble/canvas/panel/bottom-dock#invalidate fi fi local old_height=$((top_height+bottom_height)) local new_height=$((old_height+delta)) ble/canvas/goto.draw 0 "$((top_height==0?0:top_height-1))" sgr0 ble/canvas/put-ind.draw "$((new_height-1-_ble_canvas_y))"; ((_ble_canvas_y=new_height-1)) ble/canvas/panel/goto-vfill.draw && ble/canvas/put-il.draw "$delta" vfill } function ble/canvas/panel#set-height.draw { local index=$1 new_height=$2 opts=$3 ((new_height<0)) && new_height=0 local old_height=${_ble_canvas_panel_height[index]} local delta=$((new_height-old_height)) if ((delta==0)); then if [[ :$opts: == *:clear:* ]]; then ble/canvas/panel#clear.draw "$index" return "$?" else return 1 fi elif ((delta>0)); then ble/canvas/panel/increase-total-height.draw "$delta" ble/canvas/panel/goto-vfill.draw && ble/canvas/put-dl.draw "$delta" vfill ((_ble_canvas_panel_height[index]=new_height)) case :$opts: in (*:clear:*) ble/canvas/panel#goto.draw "$index" 0 0 sgr0 ble/canvas/put-clear-lines.draw "$old_height" "$new_height" panel ;; (*:shift:*) # 先頭に行挿入 ble/canvas/panel#goto.draw "$index" 0 0 sgr0 ble/canvas/put-il.draw "$delta" panel ;; (*) # 末尾に行挿入 ble/canvas/panel#goto.draw "$index" 0 "$old_height" sgr0 ble/canvas/put-il.draw "$delta" panel ;; esac else ((delta=-delta)) case :$opts: in (*:clear:*) ble/canvas/panel#goto.draw "$index" 0 0 sgr0 ble/canvas/put-clear-lines.draw "$old_height" "$new_height" panel ;; (*:shift:*) # 先頭を削除 ble/canvas/panel#goto.draw "$index" 0 0 sgr0 ble/canvas/put-dl.draw "$delta" panel ;; (*) # 末尾を削除 ble/canvas/panel#goto.draw "$index" 0 "$new_height" sgr0 ble/canvas/put-dl.draw "$delta" panel ;; esac ((_ble_canvas_panel_height[index]=new_height)) ble/canvas/panel/goto-vfill.draw && ble/canvas/put-il.draw "$delta" vfill fi ble/function#try "${_ble_canvas_panel_class[index]}#panel::onHeightChange" "$index" return 0 } function ble/canvas/panel#increase-height.draw { local index=$1 delta=$2 opts=$3 ble/canvas/panel#set-height.draw "$index" "$((_ble_canvas_panel_height[index]+delta))" "$opts" } function ble/canvas/panel#set-height-and-clear.draw { local index=$1 new_height=$2 ble/canvas/panel#set-height.draw "$index" "$new_height" clear } function ble/canvas/panel#clear.draw { local index=$1 local height=${_ble_canvas_panel_height[index]} if ((height)); then ble/canvas/panel#goto.draw "$index" 0 0 sgr0 ble/canvas/put-clear-lines.draw "$height" fi } function ble/canvas/panel#clear-after.draw { local index=$1 x=$2 y=$3 local height=${_ble_canvas_panel_height[index]} ((yLINES)) && tmargin=$LINES ((tmargin>0)) || return 0 local ret ble/canvas/panel/save-position; local pos=$ret ble/canvas/panel/goto-top-dock.draw ble/canvas/panel/top-dock#height; local top_height=$ret ble/canvas/panel/bottom-dock#height; local bottom_height=$ret if ((bottom_height)); then if [[ $_ble_term_DECSTBM ]]; then ble/canvas/excursion-start.draw ble/canvas/put.draw $'\e[1;'$((LINES-bottom_height))'r' ble/canvas/excursion-end.draw ble/canvas/goto.draw 0 0 sgr0 if [[ $_ble_term_ri ]]; then ble/canvas/put-ri.draw "$tmargin" ble/canvas/put-cud.draw "$tmargin" else ble/canvas/put-ind.draw "$((top_height-1+tmargin))" ble/canvas/put-cuu.draw "$((top_height-1+tmargin))" ble/canvas/excursion-start.draw ble/canvas/put-cup.draw 1 1 ble/canvas/put-il.draw "$tmargin" no-lastline ble/canvas/excursion-end.draw fi ble/canvas/excursion-start.draw ble/canvas/put.draw "$_ble_term_DECSTBM_reset" ble/canvas/excursion-end.draw ble/canvas/panel/load-position.draw "$pos" return 0 else ble/canvas/panel/bottom-dock#invalidate fi fi ble/canvas/goto.draw 0 0 sgr0 if [[ $_ble_term_ri ]]; then ble/canvas/put-ri.draw "$tmargin" ble/canvas/put-cud.draw "$tmargin" else local total_height=$((top_height+bottom_height)) ble/canvas/put-ind.draw "$((total_height-1+tmargin))" ble/canvas/put-cuu.draw "$((total_height-1+tmargin))" if [[ $_ble_term_rc ]]; then ble/canvas/excursion-start.draw ble/canvas/put-cup.draw 1 1 ble/canvas/put-il.draw "$tmargin" no-lastline ble/canvas/excursion-end.draw else ble/canvas/put-il.draw "$tmargin" no-lastline fi ble/canvas/put-cud.draw "$tmargin" fi ble/canvas/panel/load-position.draw "$pos" } bleopt/declare -v history_limit_length 10000 _ble_history=() _ble_history_edit=() _ble_history_dirt=() _ble_history_index=0 _ble_history_count= function ble/builtin/history/is-empty { ! ble/util/assign.has-output 'builtin history 1' } if ((_ble_bash>=50000)); then function ble/builtin/history/.check-timestamp-sigsegv { return 0; } else function ble/builtin/history/.check-timestamp-sigsegv { local stat=$1 ((stat)) || return 0 local ret=11 ble/builtin/trap/sig#resolve SIGSEGV ((stat==128+ret)) || return 0 local msg="bash: SIGSEGV: suspicious timestamp in HISTFILE" local histfile=${HISTFILE-} if [[ -s $histfile ]]; then msg="$msg='$histfile'" local rex_broken_timestamp='^#[0-9]\{12\}' ble/util/assign line 'ble/bin/grep -an "$rex_broken_timestamp" "$histfile"' ble/string#split line : "$line" [[ $line =~ ^[0-9]+$ ]] && msg="$msg (line $line)" fi if [[ ${_ble_edit_io_fname2-} ]]; then ble/util/print $'\n'"$msg" >> "$_ble_edit_io_fname2" else ble/util/print "$msg" >&2 fi } fi if ((_ble_bash<40000)); then function ble/builtin/history/.dump.proc { local LC_ALL= LC_MESSAGES=C 2>/dev/null builtin history "${args[@]}" ble/util/unlocal LC_ALL LC_MESSAGES 2>/dev/null } function ble/builtin/history/.dump { local -a args; args=("$@") ble/util/conditional-sync \ ble/builtin/history/.dump.proc \ true 100 progressive-weight:timeout=3000:SIGKILL local ext=$? if ((ext==142)); then printf 'ble.sh: timeout: builtin history %s' "$*" >&"$_ble_util_fd_tui_stderr" local ret=11 ble/builtin/trap/sig#resolve SIGSEGV ((ext=128+ret)) fi ble/builtin/history/.check-timestamp-sigsegv "$ext" return "$ext" } else function ble/builtin/history/.dump { local LC_ALL= LC_MESSAGES=C 2>/dev/null builtin history "$@" ble/util/unlocal LC_ALL LC_MESSAGES 2>/dev/null } fi if ((_ble_bash>=50200)); then function ble/builtin/history/.get-min { if ((${_ble_trap_sig-0}==_ble_builtin_trap_EXIT)); then ble/string#split-words min "$(builtin history | ble/bin/sed -n '1{p;q;}')" else ble/util/assign-words min 'builtin history | ble/bin/sed -n "1{p;q;}"' fi min=${min/'*'} } elif ((_ble_bash>=40000)); then function ble/builtin/history/.get-min { ble/util/assign-words min 'builtin history | ble/bin/sed -n "1{p;q;}"' min=${min/'*'} } else function ble/builtin/history/.get-min { ble/util/assign-words min 'ble/builtin/history/.dump | ble/bin/sed -n "1{p;q;}"' min=${min/'*'} } fi function ble/builtin/history/.get-max { ble/util/assign-words max 'builtin history 1' max=${max/'*'} } _ble_history_load_done= function ble/history:bash/clear-background-load { blehook/invoke history_reset_background } if ((_ble_bash>=40000)); then _ble_history_load_resume=0 _ble_history_load_bgpid= function ble/history:bash/load/.background-initialize { if ble/builtin/history/is-empty; then builtin history -n fi local HISTTIMEFORMAT=__ble_ext__ local -x INDEX_FILE=$history_indfile local -x opt_source= opt_null= if [[ $load_strategy == source ]]; then opt_source=1 elif [[ $load_strategy == mapfile ]]; then opt_null=1 fi if [[ ! $_ble_util_writearray_rawbytes ]]; then local IFS=$_ble_term_IFS __ble_tmp; __ble_tmp=('\'{2,3}{0..7}{0..7}) builtin eval "local _ble_util_writearray_rawbytes=\$'${__ble_tmp[*]}'" fi local -x __ble_rawbytes=$_ble_util_writearray_rawbytes # used by _ble_bin_awk_libES local -x fname_stderr=${_ble_edit_io_fname2:-} local apos=\' ble/builtin/history/.dump ${arg_count:+"$arg_count"} | ble/bin/awk -v apos="$apos" -v arg_offset="$arg_offset" -v _ble_bash="$_ble_bash" ' '"$_ble_bin_awk_libES"' BEGIN { es_initialize(); INDEX_FILE = ENVIRON["INDEX_FILE"]; opt_null = ENVIRON["opt_null"]; opt_source = ENVIRON["opt_source"]; if (!opt_null && !opt_source) printf("") > INDEX_FILE; # create file fname_stderr = ENVIRON["fname_stderr"]; fname_stderr_count = 0; n = 0; hindex = arg_offset; } function flush_line() { if (n < 1) return; if (opt_null) { if (t ~ /^eval -- \$'"$apos"'([^'"$apos"'\\]|\\.)*'"$apos"'$/) t = es_unescape(substr(t, 11, length(t) - 11)); printf("%s%c", t, 0); } else if (opt_source) { if (t ~ /^eval -- \$'"$apos"'([^'"$apos"'\\]|\\.)*'"$apos"'$/) t = es_unescape(substr(t, 11, length(t) - 11)); gsub(/'"$apos"'/, "'"$apos"'\\'"$apos$apos"'", t); print "_ble_history[" hindex "]=" apos t apos; } else { if (n == 1) { if (t ~ /^eval -- \$'"$apos"'([^'"$apos"'\\]|\\.)*'"$apos"'$/) print hindex > INDEX_FILE; } else { gsub(/['"$apos"'\\]/, "\\\\&", t); gsub(/\n/, "\\n", t); print hindex > INDEX_FILE; t = "eval -- $" apos t apos; } print t; } hindex++; n = 0; t = ""; } function check_invalid_timestamp(line) { if (line ~ /^ *[0-9]+\*? +.+: invalid timestamp/ && fname_stderr != "") { sub(/^ *0*/, "bash: history !", line); sub(/: invalid timestamp.*$/, ": invalid timestamp", line); if (fname_stderr_count++ == 0) print "" >> fname_stderr; print line >> fname_stderr; } } { check_invalid_timestamp($0); if (sub(/^ *[0-9]+\*? +(__ble_ext__|\?\?|.+: invalid timestamp)/, "", $0)) flush_line(); t = ++n == 1 ? $0 : t "\n" $0; } END { flush_line(); } ' >| "$history_tmpfile.part" ble/builtin/history/.check-timestamp-sigsegv "${PIPESTATUS[0]}" ble/bin/mv -f "$history_tmpfile.part" "$history_tmpfile" } function ble/history:bash/load { local opts=$1 local opt_async=; [[ :$opts: == *:async:* ]] && opt_async=1 local load_strategy=mapfile if [[ $OSTYPE == cygwin* || $OSTYPE == msys* ]]; then load_strategy=source elif ((_ble_bash<50200)); then load_strategy=nlfix fi local arg_count= arg_offset=0 [[ :$opts: == *:append:* ]] && arg_offset=${#_ble_history[@]} local rex=':count=([0-9]+):'; [[ :$opts: =~ $rex ]] && arg_count=${BASH_REMATCH[1]} local history_tmpfile=$_ble_base_run/$$.history.load local history_indfile=$_ble_base_run/$$.history.multiline-index [[ $opt_async || :$opts: == *:init:* ]] || _ble_history_load_resume=0 [[ ! $opt_async ]] && ((_ble_history_load_resume<6)) && blehook/invoke history_message "loading history ..." while :; do case $_ble_history_load_resume in (0) # 履歴ファイル生成を Background で開始 if [[ $_ble_history_load_bgpid ]]; then builtin kill -9 "$_ble_history_load_bgpid" &>/dev/null _ble_history_load_bgpid= fi >| "$history_tmpfile" if [[ $opt_async ]]; then _ble_history_load_bgpid=$(ble/util/nohup 'ble/history:bash/load/.background-initialize' print-bgpid) function ble/history:bash/load/.background-initialize-completed { local history_tmpfile=$_ble_base_run/$$.history.load [[ -s $history_tmpfile ]] || ! builtin kill -0 "$_ble_history_load_bgpid" } &>/dev/null ((_ble_history_load_resume++)) else ble/history:bash/load/.background-initialize ((_ble_history_load_resume+=3)) fi ;; (1) if [[ $opt_async ]] && ble/util/is-running-in-idle; then ble/util/idle.wait-condition ble/history:bash/load/.background-initialize-completed ((_ble_history_load_resume++)) return 147 fi ((_ble_history_load_resume++)) ;; (2) while ! ble/history:bash/load/.background-initialize-completed; do ble/util/msleep 50 [[ $opt_async ]] && ! ble/util/idle/IS_IDLE && return 148 done ((_ble_history_load_resume++)) ;; (3) _ble_history_load_bgpid= ((arg_offset==0)) && _ble_history=() if [[ $load_strategy == source ]]; then source "$history_tmpfile" elif [[ $load_strategy == nlfix ]]; then builtin mapfile -O "$arg_offset" -t _ble_history < "$history_tmpfile" else builtin mapfile -O "$arg_offset" -t -d '' _ble_history < "$history_tmpfile" fi ble/builtin/history/erasedups/update-base ((_ble_history_load_resume++)) ;; (4) ((arg_offset==0)) && _ble_history_edit=() if [[ $load_strategy == source ]]; then _ble_history_edit=("${_ble_history[@]}") elif [[ $load_strategy == nlfix ]]; then builtin mapfile -O "$arg_offset" -t _ble_history_edit < "$history_tmpfile" else builtin mapfile -O "$arg_offset" -t -d '' _ble_history_edit < "$history_tmpfile" fi >| "$history_tmpfile" if [[ $load_strategy != nlfix ]]; then ((_ble_history_load_resume+=3)) continue else ((_ble_history_load_resume++)) fi ;; (5) local -a indices_to_fix ble/util/mapfile indices_to_fix < "$history_indfile" local i rex='^eval -- \$'\''([^\'\'']|\\.)*'\''$' for i in "${indices_to_fix[@]}"; do [[ ${_ble_history[i]} =~ $rex ]] && builtin eval "_ble_history[i]=${_ble_history[i]:8}" done ((_ble_history_load_resume++)) ;; (6) local -a indices_to_fix [[ ${indices_to_fix+set} ]] || ble/util/mapfile indices_to_fix < "$history_indfile" local i for i in "${indices_to_fix[@]}"; do [[ ${_ble_history_edit[i]} =~ $rex ]] && builtin eval "_ble_history_edit[i]=${_ble_history_edit[i]:8}" done ((_ble_history_load_resume++)) ;; (7) [[ $opt_async ]] || blehook/invoke history_message ((_ble_history_load_resume++)) return 0 ;; (*) return 1 ;; esac [[ $opt_async ]] && ! ble/util/idle/IS_IDLE && return 148 done } blehook history_reset_background!=_ble_history_load_resume=0 else function ble/history:bash/load/.generate-source { if ble/builtin/history/is-empty; then builtin history -n fi local HISTTIMEFORMAT=__ble_ext__ local apos="'" ble/builtin/history/.dump ${arg_count:+"$arg_count"} | ble/bin/awk -v apos="'" ' BEGIN { n = ""; } /^ *[0-9]+\*? +(__ble_ext__|\?\?)#[0-9]/ { next; } /^ *[0-9]+\*? +(__ble_ext__|\?\?|.+: invalid timestamp)/ { if (n != "") { n = ""; print " " apos t apos; } n = $1; t = ""; sub(/^ *[0-9]+\*? +(__ble_ext__|\?\?|.+: invalid timestamp)/, "", $0); } { line = $0; if (line ~ /^eval -- \$'"$apos"'([^'"$apos"'\\]|\\.)*'"$apos"'$/) line = apos substr(line, 9) apos; else gsub(apos, apos "\\" apos apos, line); gsub(/\001/, "'"$apos"'${_ble_term_SOH}'"$apos"'", line); gsub(/\177/, "'"$apos"'${_ble_term_DEL}'"$apos"'", line); gsub(/\015/, "'"$apos"'${_ble_term_CR}'"$apos"'", line); t = t != "" ? t "\n" line : line; } END { if (n != "") { n = ""; print " " apos t apos; } } ' } function ble/history:bash/load { local opts=$1 local opt_append= [[ :$opts: == *:append:* ]] && opt_append=1 local arg_count= rex=':count=([0-9]+):' [[ :$opts: =~ $rex ]] && arg_count=${BASH_REMATCH[1]} blehook/invoke history_message "loading history..." local result=$(ble/history:bash/load/.generate-source) local IFS=$_ble_term_IFS if [[ $opt_append ]]; then if ((_ble_bash>=30100)); then builtin eval -- "_ble_history+=($result)" builtin eval -- "_ble_history_edit+=($result)" else local -a A; builtin eval -- "A=($result)" _ble_history=("${_ble_history[@]}" "${A[@]}") _ble_history_edit=("${_ble_history[@]}" "${A[@]}") fi else builtin eval -- "_ble_history=($result)" _ble_history_edit=("${_ble_history[@]}") fi ble/builtin/history/erasedups/update-base ble/util/unlocal IFS blehook/invoke history_message } fi function ble/history:bash/initialize { [[ $_ble_history_load_done ]] && return 0 ble/history:bash/load "init:$@"; local ext=$? ((ext)) && return "$ext" local old_count=$_ble_history_count new_count=${#_ble_history[@]} _ble_history_load_done=1 _ble_history_count=$new_count _ble_history_index=$_ble_history_count ble/history/.update-position local delta=$((new_count-old_count)) ((delta>0)) && blehook/invoke history_change insert "$old_count" "$delta" } if ((_ble_bash>=30100)); then _ble_history_mlfix_done= _ble_history_mlfix_resume=0 _ble_history_mlfix_bgpid= function ble/history:bash/resolve-multiline/.awk { local ret ble/util/time local -x epoch=$ret local -x reason=$1 local apos=\' ble/bin/awk -v apos="$apos" -v _ble_bash="$_ble_bash" ' BEGIN { q = apos; Q = apos "\\" apos apos; reason = ENVIRON["reason"]; is_resolve = reason == "resolve"; TMPBASE = ENVIRON["tmpfile_base"]; filename_source = TMPBASE ".part"; if (is_resolve) print "builtin history -c" > filename_source entry_nline = 0; entry_text = ""; entry_time = ""; if (_ble_bash >= 40400) entry_time = ENVIRON["epoch"]; command_count = 0; multiline_count = 0; modification_count = 0; read_section_count = 0; } function write_flush(_, i, filename_section, t, c) { if (command_count == 0) return; if (command_count >= 2 || entry_time) { filename_section = TMPBASE "." read_section_count++ ".part"; for (i = 0; i < command_count; i++) { t = command_time[i]; c = command_text[i]; if (t) print "#" t > filename_section; print c > filename_section; } print "HISTTIMEFORMAT=%s builtin history -r " filename_section > filename_source; } else { for (i = 0; i < command_count; i++) { c = command_text[i]; gsub(/'"$apos"'/, Q, c); print "builtin history -s -- " q c q > filename_source; } } command_count = 0; } function write_complex(value) { write_flush(); print "builtin history -s -- " value > filename_source; } function register_command(cmd) { command_time[command_count] = entry_time; command_text[command_count] = cmd; command_count++; } function is_escaped_command(cmd) { return cmd ~ /^eval -- \$'"$apos"'([^'"$apos"'\\]|\\[\\'"$apos"'nt])*'"$apos"'$/; } function unescape_command(cmd) { cmd = substr(cmd, 11, length(cmd) - 11); gsub(/\\\\/, "\\q", cmd); gsub(/\\n/, "\n", cmd); gsub(/\\t/, "\t", cmd); gsub(/\\'"$apos"'/, "'"$apos"'", cmd); gsub(/\\q/, "\\", cmd); return cmd; } function register_escaped_command(cmd) { multiline_count++; modification_count++; if (_ble_bash >= 40400) { register_command(unescape_command(cmd)); } else { write_complex(substr(cmd, 9)); } } function register_multiline_command(cmd) { multiline_count++; if (_ble_bash >= 40040) { register_command(cmd); } else { gsub(/'"$apos"'/, Q, cmd); write_complex(q cmd q); } } function flush_entry() { if (entry_nline < 1) return; if (is_escaped_command(entry_text)) { register_escaped_command(entry_text) } else if (entry_nline > 1) { register_multiline_command(entry_text); } else { register_command(entry_text); } entry_nline = 0; entry_text = ""; } function save_timestamp(line) { if (is_resolve) { if (line ~ /^ *[0-9]+\*? +__ble_time_[0-9]*__/) { sub(/^ *[0-9]+\*? +__ble_time_/, "", line); sub(/__.*$/, "", line); entry_time = line; } } else { if (line ~ /^#[0-9]/) { sub(/^#/, "", line); sub(/[^0-9].*$/, "", line); entry_time = line; } } } { if (is_resolve) { save_timestamp($0); if (sub(/^ *[0-9]+\*? +(__ble_time_[0-9]*__|\?\?|.+: invalid timestamp)/, "", $0)) flush_entry(); entry_text = ++entry_nline == 1 ? $0 : entry_text "\n" $0; } else { if ($0 ~ /^#[0-9]/) { save_timestamp($0); next; } else { flush_entry(); entry_text = $0; entry_nline = 1; } } } END { flush_entry(); write_flush(); if (is_resolve) print "builtin history -a /dev/null" > filename_source print "multiline_count=" multiline_count; print "modification_count=" modification_count; } ' } function ble/history:bash/resolve-multiline/.cleanup { local file for file in "$tmpfile_base".*; do >| "$file"; done } function ble/history:bash/resolve-multiline/.worker { local HISTTIMEFORMAT=__ble_time_%s__ 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 "$tmpfile_base.part" "$tmpfile_base.sh" else ble/util/print : >| "$tmpfile_base.sh" fi } function ble/history:bash/resolve-multiline/.load { local tmpfile_base=$_ble_base_run/$$.history.mlfix local HISTCONTROL= HISTSIZE= HISTIGNORE= source "$tmpfile_base.sh" ble/history:bash/resolve-multiline/.cleanup } function ble/history:bash/resolve-multiline.impl { local opts=$1 local opt_async=; [[ :$opts: == *:async:* ]] && opt_async=1 local history_tmpfile=$_ble_base_run/$$.history.mlfix.sh [[ $opt_async || :$opts: == *:init:* ]] || _ble_history_mlfix_resume=0 [[ ! $opt_async ]] && ((_ble_history_mlfix_resume<=4)) && blehook/invoke history_message "resolving multiline history ..." while :; do case $_ble_history_mlfix_resume in (0) if [[ $opt_async ]] && ble/builtin/history/is-empty; then ble/util/idle.wait-user-input ((_ble_history_mlfix_resume++)) return 147 fi ((_ble_history_mlfix_resume++)) ;; (1) # 履歴ファイル生成を Background で開始 if [[ $_ble_history_mlfix_bgpid ]]; then builtin kill -9 "$_ble_history_mlfix_bgpid" &>/dev/null _ble_history_mlfix_bgpid= fi >| "$history_tmpfile" if [[ $opt_async ]]; then _ble_history_mlfix_bgpid=$(ble/util/nohup 'ble/history:bash/resolve-multiline/.worker' print-bgpid) function ble/history:bash/resolve-multiline/.worker-completed { local history_tmpfile=$_ble_base_run/$$.history.mlfix.sh [[ -s $history_tmpfile ]] || ! builtin kill -0 "$_ble_history_mlfix_bgpid" } &>/dev/null ((_ble_history_mlfix_resume++)) else ble/history:bash/resolve-multiline/.worker ((_ble_history_mlfix_resume+=3)) fi ;; (2) if [[ $opt_async ]] && ble/util/is-running-in-idle; then ble/util/idle.wait-condition ble/history:bash/resolve-multiline/.worker-completed ((_ble_history_mlfix_resume++)) return 147 fi ((_ble_history_mlfix_resume++)) ;; (3) while ! ble/history:bash/resolve-multiline/.worker-completed; do ble/util/msleep 50 [[ $opt_async ]] && ! ble/util/idle/IS_IDLE && return 148 done ((_ble_history_mlfix_resume++)) ;; (4) _ble_history_mlfix_bgpid= ble/history:bash/resolve-multiline/.load [[ $opt_async ]] || blehook/invoke history_message ((_ble_history_mlfix_resume++)) return 0 ;; (*) return 1 ;; esac [[ $opt_async ]] && ! ble/util/idle/IS_IDLE && return 148 done } function ble/history:bash/resolve-multiline { [[ $_ble_history_mlfix_done ]] && return 0 if [[ $1 == sync ]]; then ((_ble_bash>=40000)) && [[ $BASHPID != $$ ]] && return 0 ble/builtin/history/is-empty && return 0 fi ble/history:bash/resolve-multiline.impl "$@"; local ext=$? ((ext)) && return "$ext" _ble_history_mlfix_done=1 return 0 } ((_ble_bash>=40000)) && ble/util/idle.push 'ble/history:bash/resolve-multiline async' blehook history_reset_background!=_ble_history_mlfix_resume=0 function ble/history:bash/resolve-multiline/readfile { local filename=$1 local -x tmpfile_base=$_ble_base_run/$$.history.read ble/history:bash/resolve-multiline/.awk read < "$filename" &>/dev/null source "$tmpfile_base.part" ble/history:bash/resolve-multiline/.cleanup } else function ble/history:bash/resolve-multiline/readfile { builtin history -r "$filename"; } function ble/history:bash/resolve-multiline { return 0; } fi function ble/history:bash/unload.hook { ble/util/is-running-in-subshell && return 0 if shopt -q histappend &>/dev/null; then ble/builtin/history -a else ble/builtin/history -w fi } blehook unload!=ble/history:bash/unload.hook function ble/history:bash/reset { if ((_ble_bash>=40000)); then _ble_history_load_done= ble/history:bash/clear-background-load ble/util/idle.push 'ble/history:bash/initialize async' elif ((_ble_bash>=30100)) && [[ $bleopt_history_lazyload ]]; then _ble_history_load_done= else ble/history:bash/initialize fi } function ble/builtin/history/.touch-histfile { local touch=$_ble_base_run/$$.history.touch >| "$touch" } if [[ ! ${_ble_builtin_history_initialized+set} ]]; then _ble_builtin_history_initialized= _ble_builtin_history_histnew_count=0 _ble_builtin_history_histapp_count=0 _ble_builtin_history_wskip=0 _ble_builtin_history_prevmax=0 builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_builtin_history_rskip_dict}" function ble/builtin/history/.get-rskip { local file=$1 ret ble/gdict#get _ble_builtin_history_rskip_dict "$file" rskip=$ret } function ble/builtin/history/.set-rskip { local file=$1 ble/gdict#set _ble_builtin_history_rskip_dict "$file" "$2" } function ble/builtin/history/.add-rskip { local file=$1 ret ble/gdict#get _ble_builtin_history_rskip_dict "$file" ((ret+=$2)) ble/gdict#set _ble_builtin_history_rskip_dict "$file" "$ret" } fi function ble/builtin/history/.initialize { [[ $_ble_builtin_history_initialized ]] && return 0 local line; ble/util/assign line 'builtin history 1' [[ ! $_ble_decode_hook_count && ! $line && :$1: == *:skip0:* ]] && return 1 _ble_builtin_history_initialized=1 local histnew=$_ble_base_run/$$.history.new >| "$histnew" if [[ $line ]]; then local histini=$_ble_base_run/$$.history.ini local histapp=$_ble_base_run/$$.history.app HISTTIMEFORMAT=1 builtin history -a "$histini" if [[ -s $histini ]]; then ble/bin/sed '/^#\([0-9].*\)/{s// 0 __ble_time_\1__/;N;s/\n//;}' "$histini" >> "$histapp" >| "$histini" fi else ble/builtin/history/option:r fi local histfile=${HISTFILE-} rskip=0 [[ -e $histfile ]] && rskip=$(ble/bin/wc -l "$histfile" 2>/dev/null) ble/string#split-words rskip "$rskip" local min; ble/builtin/history/.get-min local max; ble/builtin/history/.get-max ((max&&max-min+1=50000&&beg=beg;i--)); do builtin history -d "$i" done fi } function ble/builtin/history/.check-uncontrolled-change { [[ $_ble_decode_bind_state == none ]] && return 0 local filename=${1-} opts=${2-} prevmax=$_ble_builtin_history_prevmax local max; ble/builtin/history/.get-max if ((max!=prevmax)); then if [[ $filename && :$opts: == *:append:* ]] && ((_ble_builtin_history_wskip0)) || return 0 if [[ ! $_ble_history_load_done ]]; then ble/history:bash/clear-background-load _ble_history_count= return 0 fi if ((_ble_bash>=40000&&delta>=10000)); then ble/history:bash/reset return 0 fi ble/history:bash/load append:count=$delta local ocount=$_ble_history_count ncount=${#_ble_history[@]} ((_ble_history_index==_ble_history_count)) && _ble_history_index=$ncount _ble_history_count=$ncount ble/history/.update-position blehook/invoke history_change insert "$ocount" "$delta" } function ble/builtin/history/.read { local file=$1 skip=${2:-0} fetch=$3 local -x histnew=$_ble_base_run/$$.history.new if [[ -s $file ]]; then local script=$(ble/bin/awk -v skip="$skip" ' BEGIN { histnew = ENVIRON["histnew"]; count = 0; } NR <= skip { next; } { print $0 >> histnew; count++; } END { print "ble/builtin/history/.set-rskip \"$file\" " NR; print "((_ble_builtin_history_histnew_count+=" count "))"; } ' "$file") builtin eval -- "$script" else ble/builtin/history/.set-rskip "$file" 0 fi if [[ ! $fetch && -s $histnew ]]; then local nline=$_ble_builtin_history_histnew_count ble/history:bash/resolve-multiline/readfile "$histnew" >| "$histnew" _ble_builtin_history_histnew_count=0 ble/builtin/history/.load-recent-entries "$nline" local max; ble/builtin/history/.get-max _ble_builtin_history_wskip=$max _ble_builtin_history_prevmax=$max fi } function ble/builtin/history/.write { local -x file=$1 skip=${2:-0} opts=$3 local -x histapp=$_ble_base_run/$$.history.app declare -p HISTTIMEFORMAT &>/dev/null local -x flag_timestamp=$(($?==0)) local min; ble/builtin/history/.get-min local max; ble/builtin/history/.get-max ((skip0)); then local HISTTIMEFORMAT=__ble_time_%s__ if [[ :$opts: == *:append:* ]]; then ble/builtin/history/.dump "$delta" >> "$histapp" ((_ble_builtin_history_histapp_count+=delta)) else ble/builtin/history/.dump "$delta" >| "$histapp" _ble_builtin_history_histapp_count=$delta fi fi if [[ ! -e $file ]]; then (umask 077; >| "$file") elif [[ :$opts: != *:append:* ]]; then >| "$file" fi if [[ :$opts: != *:fetch:* && -s $histapp ]]; then local apos=\' < "$histapp" ble/bin/awk ' BEGIN { file = ENVIRON["file"]; flag_timestamp = ENVIRON["flag_timestamp"]; timestamp = ""; mode = 0; } function flush_line() { if (!mode) return; mode = 0; if (text ~ /\n/) { gsub(/['"$apos"'\\]/, "\\\\&", text); gsub(/\n/, "\\n", text); gsub(/\t/, "\\t", text); text = "eval -- $'"$apos"'" text "'"$apos"'" } if (timestamp != "") print timestamp >> file; print text >> file; } function extract_timestamp(line) { if (!sub(/^ *[0-9]+\*? +__ble_time_/, "", line)) return ""; if (!sub(/__.*$/, "", line)) return ""; if (!(line ~ /^[0-9]+$/)) return ""; return "#" line; } /^ *[0-9]+\*? +(__ble_time_[0-9]*__|\?\?|.+: invalid timestamp)?/ { flush_line(); mode = 1; text = ""; if (flag_timestamp) timestamp = extract_timestamp($0); sub(/^ *[0-9]+\*? +(__ble_time_[0-9]*__|\?\?|.+: invalid timestamp)?/, "", $0); } { text = text != "" ? text "\n" $0 : $0; } END { flush_line(); } ' ble/builtin/history/.add-rskip "$file" "$_ble_builtin_history_histapp_count" >| "$histapp" _ble_builtin_history_histapp_count=0 fi _ble_builtin_history_wskip=$max _ble_builtin_history_prevmax=$max } function ble/builtin/history/array#delete-hindex { local array_name=$1; shift local script=' local -a out=() local i shift=0 for i in "${!NAME[@]}"; do local delete= while (($#)); do if [[ $1 == *-* ]]; then local b=${1%-*} e=${1#*-} ((imax&&(beg=max)))) ((end<0)) && ((end+=max+1)); ((endmax&&(end=max)))) ((beg<=end)) || return 0 ble/builtin/history/.delete-range "$beg" "$end" if ((_ble_builtin_history_wskip>=end)); then ((_ble_builtin_history_wskip-=end-beg+1)) elif ((_ble_builtin_history_wskip>beg-1)); then ((_ble_builtin_history_wskip=beg-1)) fi if [[ $_ble_decode_bind_state != none ]]; then if [[ $_ble_history_load_done ]]; then local N=${#_ble_history[@]} local b=$((beg-1+N-max)) e=$((end+N-max)) blehook/invoke history_change delete "$b-$e" if ((_ble_history_index>=e)); then ((_ble_history_index-=e-b)) elif ((_ble_history_index>=b)); then _ble_history_index=$b fi _ble_history=("${_ble_history[@]::b}" "${_ble_history[@]:e}") _ble_history_edit=("${_ble_history_edit[@]::b}" "${_ble_history_edit[@]:e}") _ble_history_count=${#_ble_history[@]} else ble/history:bash/clear-background-load _ble_history_count= fi ble/history/.update-position fi local max; ble/builtin/history/.get-max _ble_builtin_history_prevmax=$max } function ble/builtin/history/.get-histfile { histfile=${1:-${HISTFILE-}} if [[ ! $histfile ]]; then local opt=-a [[ ${FUNCNAME[1]} == *:[!:] ]] && opt=-${FUNCNAME[1]##*:} if [[ ${1+set} ]]; then ble/util/print "ble/builtin/history $opt: the history filename is empty." >&2 else ble/util/print "ble/builtin/history $opt: the history file is not specified." >&2 fi return 1 fi } function ble/builtin/history/option:a { ble/builtin/history/.initialize skip0 || return "$?" local histfile; ble/builtin/history/.get-histfile "$@" || return "$?" ble/builtin/history/.check-uncontrolled-change "$histfile" append local rskip; ble/builtin/history/.get-rskip "$histfile" ble/builtin/history/.write "$histfile" "$_ble_builtin_history_wskip" append:fetch [[ -r $histfile ]] && ble/builtin/history/.read "$histfile" "$rskip" fetch ble/builtin/history/.write "$histfile" "$_ble_builtin_history_wskip" append builtin history -a /dev/null # Bash 終了時に書き込まない } function ble/builtin/history/option:n { local histfile; ble/builtin/history/.get-histfile "$@" || return "$?" if [[ $histfile == ${HISTFILE-} ]]; then local touch=$_ble_base_run/$$.history.touch [[ $touch -nt ${HISTFILE-} ]] && return 0 >| "$touch" fi ble/builtin/history/.initialize local rskip; ble/builtin/history/.get-rskip "$histfile" ble/builtin/history/.read "$histfile" "$rskip" } function ble/builtin/history/option:w { ble/builtin/history/.initialize skip0 || return "$?" local histfile; ble/builtin/history/.get-histfile "$@" || return "$?" local rskip; ble/builtin/history/.get-rskip "$histfile" [[ -r $histfile ]] && ble/builtin/history/.read "$histfile" "$rskip" fetch ble/builtin/history/.write "$histfile" 0 builtin history -a /dev/null # Bash 終了時に書き込まない } function ble/builtin/history/option:r { local histfile; ble/builtin/history/.get-histfile "$@" || return "$?" ble/builtin/history/.initialize ble/builtin/history/.read "$histfile" 0 } function ble/builtin/history/option:p { ((_ble_bash>=40000)) || ble/builtin/history/is-empty || ble/history:bash/resolve-multiline sync local line1= line2= ble/util/assign line1 'HISTTIMEFORMAT= builtin history 1' builtin history -p -- '' &>/dev/null ble/util/assign line2 'HISTTIMEFORMAT= builtin history 1' if [[ $line1 != "$line2" ]]; then local rex_head='^[[:space:]]*[0-9]+\*?[[:space:]]*' [[ $line1 =~ $rex_head ]] && line1=${line1:${#BASH_REMATCH}} if ((_ble_bash<30100)); then local tmp=$_ble_base_run/$$.history.tmp printf '%s\n' "$line1" "$line1" >| "$tmp" builtin history -r "$tmp" else builtin history -s -- "$line1" builtin history -s -- "$line1" fi fi builtin history -p -- "$@" } bleopt/declare -v history_erasedups_limit 0 : "${_ble_history_erasedups_base=}" function ble/builtin/history/erasedups/update-base { if [[ ! ${_ble_history_erasedups_base:-} ]]; then _ble_history_erasedups_base=${#_ble_history[@]} else local value=${#_ble_history[@]} ((value<_ble_history_erasedups_base&&(_ble_history_erasedups_base=value))) fi } function ble/builtin/history/erasedups/.impl-for { local cmd=$1 delete_indices=() shift_histindex_next=0 shift_wskip=0 local i for ((i=0;i| "$itmp1" & local pid1=$! ble/util/writearray "${writearray_options[@]}" _ble_history_edit >| "$itmp2" wait "$pid1" ) local -x erasedups_cmd=$cmd local -x erasedups_out1=$otmp1 local -x erasedups_out2=$otmp2 local -x erasedups_histindex_next=$HISTINDEX_NEXT local -x erasedups_wskip=$_ble_builtin_history_wskip local awk_script=' '"$_ble_bin_awk_libES"' '"$_ble_bin_awk_libNLFIX"' BEGIN { NLFIX_READ = ENVIRON["erasedups_nlfix_read"] != ""; cmd = ENVIRON["erasedups_cmd"]; out1 = ENVIRON["erasedups_out1"]; out2 = ENVIRON["erasedups_out2"]; histindex_next = ENVIRON["erasedups_histindex_next"]; wskip = ENVIRON["erasedups_wskip"]; if (NLFIX_READ) es_initialize(); else RS = "\0"; NLFIX_WRITE = _ble_bash < 50200; if (NLFIX_WRITE) nlfix_begin(); hist_index = 0; edit_index = 0; delete_count = 0; shift_histindex_next = 0; shift_wskip = 0; } function process_hist(elem) { if (hist_index < N - 1 && elem == cmd) { delete_indices[delete_count++] = hist_index; delete_table[hist_index] = 1; if (hist_index < wskip ) shift_wskip++; if (hist_index < histindex_next) shift_histindex_next++; } else { if (NLFIX_WRITE) nlfix_push(elem, out1); else printf("%s%c", elem, 0) > out1; } hist_index++; } function process_edit(elem) { if (delete_count == 0) exit; if (NLFIX_WRITE) { if (edit_index == 0) { nlfix_end(out1); nlfix_begin(); } if (!delete_table[edit_index++]) nlfix_push(elem, out2); } else { if (!delete_table[edit_index++]) printf("%s%c", elem, 0) > out2; } } mode == "edit" { if (NLFIX_READ) { edit[edit_index++] = $0; } else { process_edit($0); } next; } { if (NLFIX_READ) hist[hist_index++] = $0; else process_hist($0); } END { if (NLFIX_READ) { n = split(hist[hist_index - 1], indices) for (i = 1; i <= n; i++) { elem = hist[indices[i]]; if (elem ~ /^\$'\''.*'\''/) hist[indices[i]] = es_unescape(substr(elem, 3, length(elem) - 3)); } n = hist_index - 1; hist_index = 0; for (i = 0; i < n; i++) process_hist(hist[i]); n = split(edit[edit_index - 1], indices) for (i = 1; i <= n; i++) { elem = edit[indices[i]]; if (elem ~ /^\$'\''.*'\''/) edit[indices[i]] = es_unescape(substr(elem, 3, length(elem) - 3)); } n = edit_index - 1; edit_index = 0; for (i = 0; i < n; i++) process_edit(edit[i]); } if (NLFIX_WRITE) nlfix_end(out2); line = "delete_indices=(" for (i = 0; i < delete_count; i++) { if (i != 0) line = line " "; line = line delete_indices[i]; } line = line ")"; print line; print "shift_wskip=" shift_wskip; print "shift_histindex_next=" shift_histindex_next; } ' local awk_result ble/util/assign awk_result '"$awk" -v _ble_bash="$_ble_bash" -v N="$N" "$awk_script" "$itmp1" mode=edit "$itmp2"' builtin eval -- "$awk_result" if ((${#delete_indices[@]})); then if ((_ble_bash<50200)); then ble/util/readarray --nlfix _ble_history < "$otmp1" ble/util/readarray --nlfix _ble_history_edit < "$otmp2" else mapfile -d '' -t _ble_history < "$otmp1" mapfile -d '' -t _ble_history_edit < "$otmp2" fi fi _ble_local_tmpfile=$itmp2 ble/util/assign/rmtmp _ble_local_tmpfile=$itmp1 ble/util/assign/rmtmp _ble_local_tmpfile=$otmp2 ble/util/assign/rmtmp _ble_local_tmpfile=$otmp1 ble/util/assign/rmtmp } function ble/builtin/history/erasedups/.impl-ranged { local cmd=$1 beg=$2 delete_indices=() shift_histindex_next=0 shift_wskip=0 ble/path#remove HISTCONTROL erasedups HISTCONTROL=$HISTCONTROL:ignoredups local i j=$beg for ((i=beg;i=0;i--)); do builtin history -d "$((delete_indices[i]-max_index+max))" done fi } function ble/builtin/history/erasedups { local cmd=$1 local beg=0 N=${#_ble_history[@]} if [[ $bleopt_history_erasedups_limit ]]; then local limit=$((bleopt_history_erasedups_limit)) if ((limit<=0)); then ((beg=_ble_history_erasedups_base+limit)) else ((beg=N-1-limit)) fi ((beg<0)) && beg=0 fi local delete_indices shift_histindex_next shift_wskip if ((beg>=N)); then ble/path#remove HISTCONTROL erasedups return 0 elif ((beg>0)); then ble/builtin/history/erasedups/.impl-ranged "$cmd" "$beg" else if ((_ble_bash>=40000&&N>=20000)); then ble/builtin/history/erasedups/.impl-awk "$cmd" else ble/builtin/history/erasedups/.impl-for "$cmd" fi fi if ((${#delete_indices[@]})); then blehook/invoke history_change delete "${delete_indices[@]}" ((_ble_builtin_history_wskip-=shift_wskip)) [[ ${HISTINDEX_NEXT+set} ]] && ((HISTINDEX_NEXT-=shift_histindex_next)) else ((N)) && [[ ${_ble_history[N-1]} == "$cmd" ]] && return 9 fi } function ble/builtin/history/option:s { ble/builtin/history/.initialize if [[ $_ble_decode_bind_state == none ]]; then builtin history -s -- "$@" return 0 fi local cmd=$1 if [[ $HISTIGNORE ]]; then local pats pat ble/string#split pats : "$HISTIGNORE" for pat in "${pats[@]}"; do [[ $cmd == $pat ]] && return 0 done local HISTIGNORE= fi local HISTCONTROL=$HISTCONTROL if [[ $HISTCONTROL ]]; then [[ :$HISTCONTROL: == *:ignoreboth:* ]] && HISTCONTROL=$HISTCONTROL:ignorespace:ignoredups if [[ :$HISTCONTROL: == *:ignorespace:* ]]; then [[ $cmd == [' ']* ]] && return 0 fi if [[ :$HISTCONTROL: == *:strip:* ]]; then local ret ble/string#rtrim "$cmd" ble/string#match "$ret" $'^[ \t]*(\n([ \t]*\n)*)?' cmd=${ret:${#BASH_REMATCH}} [[ $BASH_REMATCH == *$'\n'* && $cmd == *$'\n'* ]] && cmd=$'\n'$cmd fi fi local use_bash300wa= if [[ $_ble_history_load_done ]]; then if [[ $HISTCONTROL ]]; then if [[ :$HISTCONTROL: == *:ignoredups:* ]]; then local lastIndex=$((${#_ble_history[@]}-1)) ((lastIndex>=0)) && [[ $cmd == "${_ble_history[lastIndex]}" ]] && return 0 fi if [[ :$HISTCONTROL: == *:erasedups:* ]]; then ble/builtin/history/erasedups "$cmd" (($?==9)) && return 0 fi fi local topIndex=${#_ble_history[@]} _ble_history[topIndex]=$cmd _ble_history_edit[topIndex]=$cmd _ble_history_count=$((topIndex+1)) _ble_history_index=$_ble_history_count ((_ble_bash<30100)) && use_bash300wa=1 else if [[ $HISTCONTROL ]]; then _ble_history_count= else [[ $_ble_history_count ]] && ((_ble_history_count++)) fi fi ble/history/.update-position if [[ $use_bash300wa ]]; then if [[ $cmd == *$'\n'* ]]; then ble/util/sprintf cmd 'eval -- %q' "$cmd" fi local tmp=$_ble_base_run/$$.history.tmp [[ ${HISTFILE-} && ! $bleopt_history_share ]] && ble/util/print "$cmd" >> "${HISTFILE-}" ble/util/print "$cmd" >| "$tmp" builtin history -r "$tmp" else ble/history:bash/clear-background-load builtin history -s -- "$cmd" fi local max; ble/builtin/history/.get-max _ble_builtin_history_prevmax=$max } function ble/builtin/history { local set shopt; ble/base/.adjust-bash-options set shopt local opt_d= flag_error= local opt_c= opt_p= opt_s= local opt_a= flags= while [[ $1 == -* ]]; do local arg=$1; shift [[ $arg == -- ]] && break if [[ $arg == --help ]]; then flags=h$flags continue fi local i n=${#arg} for ((i=1;i&2 flag_error=1 elif ((i+1&2 flag_error=1 elif ((i+1&2 flag_error=1 ;; esac done done if [[ $flag_error ]]; then builtin history --usage 2>&1 1>/dev/null | ble/bin/grep ^history >&2 ble/base/.restore-bash-options set shopt return 2 fi if [[ $flags == *h* ]]; then builtin history --help local ext=$? ble/base/.restore-bash-options set shopt return "$ext" fi [[ ! $_ble_attached || $_ble_edit_exec_inside_userspace ]] && ble/base/adjust-BASH_REMATCH local flag_processed= if [[ $opt_c ]]; then ble/builtin/history/option:c flag_processed=1 fi if [[ $opt_s ]]; then local IFS=$_ble_term_IFS ble/builtin/history/option:s "$*" flag_processed=1 elif [[ $opt_d ]]; then ble/builtin/history/option:d "$opt_d" flag_processed=1 elif [[ $opt_a ]]; then ble/builtin/history/option:"$opt_a" "$@" flag_processed=1 fi if [[ $flag_processed ]]; then ble/base/.restore-bash-options set shopt return 0 fi if [[ $opt_p ]]; then ble/builtin/history/option:p "$@" else builtin history "$@" fi; local ext=$? [[ ! $_ble_attached || $_ble_edit_exec_inside_userspace ]] && ble/base/restore-BASH_REMATCH ble/base/.restore-bash-options set shopt return "$ext" } function history { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" ble/builtin/history "$@" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" } _ble_history_prefix= function ble/history/set-prefix { _ble_history_prefix=$1 ble/history/.update-position } _ble_history_COUNT= _ble_history_INDEX= function ble/history/.update-position { if [[ $_ble_history_prefix ]]; then builtin eval -- "_ble_history_COUNT=\${#${_ble_history_prefix}_history[@]}" ((_ble_history_INDEX=${_ble_history_prefix}_history_index)) else if [[ ! $_ble_history_load_done ]]; then if [[ ! $_ble_history_count ]]; then local min max ble/builtin/history/.get-min ble/builtin/history/.get-max ((_ble_history_count=max-min+1)) fi _ble_history_index=$_ble_history_count fi _ble_history_COUNT=$_ble_history_count _ble_history_INDEX=$_ble_history_index fi } function ble/history/update-position { [[ $_ble_history_prefix$_ble_history_load_done ]] || ble/history/.update-position } function ble/history/onleave.fire { blehook/invoke history_leave "$@" } function ble/history/initialize { [[ ! $_ble_history_prefix ]] && ble/history:bash/initialize } function ble/history/get-count { local _ble_local_var=count [[ $1 == -v ]] && { _ble_local_var=$2; shift 2; } ble/history/.update-position (($_ble_local_var=_ble_history_COUNT)) } function ble/history/get-index { local _ble_local_var=index [[ $1 == -v ]] && { _ble_local_var=$2; shift 2; } ble/history/.update-position (($_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 _ble_local_var=entry [[ $1 == -v ]] && { _ble_local_var=$2; shift 2; } if [[ $_ble_history_prefix$_ble_history_load_done ]]; then builtin eval -- "$_ble_local_var=\${${_ble_history_prefix:-_ble}_history[\$1]}" else builtin eval -- "$_ble_local_var=" fi } function ble/history/get-edited-entry { local _ble_local_var=entry [[ $1 == -v ]] && { _ble_local_var=$2; shift 2; } if [[ $_ble_history_prefix$_ble_history_load_done ]]; then builtin eval -- "$_ble_local_var=\${${_ble_history_prefix:-_ble}_history_edit[\$1]}" else builtin eval -- "$_ble_local_var=\$_ble_edit_str" fi } function ble/history/set-edited-entry { ble/history/initialize local index=$1 str=$2 local code=' if [[ ! ${PREFIX_history_edit[index]+set} || ${PREFIX_history_edit[index]} != "$str" ]]; then PREFIX_history_edit[index]=$str PREFIX_history_dirt[index]=1 fi' builtin eval -- "${code//PREFIX/${_ble_history_prefix:-_ble}}" } function ble/history/.add-command-history { [[ -o history ]] || ((_ble_bash<30200)) || return 1 [[ $MC_SID == $$ && $_ble_edit_LINENO -le 2 && ( $1 == *PROMPT_COMMAND=* || $1 == *PS1=* ) ]] && return 1 if [[ $_ble_history_load_done ]]; then _ble_history_index=${#_ble_history[@]} ble/history/.update-position local index for index in "${!_ble_history_dirt[@]}"; do _ble_history_edit[index]=${_ble_history[index]} done _ble_history_dirt=() ble-edit/undo/clear-all fi if [[ $bleopt_history_share ]]; then ble/builtin/history/option:n ble/builtin/history/option:s "$1" ble/builtin/history/option:a ble/builtin/history/.touch-histfile else ble/builtin/history/option:s "$1" fi } function ble/history/add { local command=$1 ((bleopt_history_limit_length>0&&${#command}>bleopt_history_limit_length)) && return 1 if [[ $_ble_history_prefix ]]; then local code=' local index for index in "${!PREFIX_history_dirt[@]}"; do PREFIX_history_edit[index]=${PREFIX_history[index]} done PREFIX_history_dirt=() local topIndex=${#PREFIX_history[@]} PREFIX_history[topIndex]=$command PREFIX_history_edit[topIndex]=$command PREFIX_history_index=$((++topIndex)) _ble_history_COUNT=$topIndex _ble_history_INDEX=$topIndex' builtin eval -- "${code//PREFIX/$_ble_history_prefix}" else blehook/invoke ADDHISTORY "$command" && ble/history/.add-command-history "$command" fi } function ble/history/.read-isearch-options { local opts=$1 search_type=fixed case :$opts: in (*:regex:*) search_type=regex ;; (*:glob:*) search_type=glob ;; (*:head:*) search_type=head ;; (*:tail:*) search_type=tail ;; (*:condition:*) search_type=condition ;; (*:predicate:*) search_type=predicate ;; esac [[ :$opts: != *:stop_check:* ]]; has_stop_check=$? [[ :$opts: != *:progress:* ]]; has_progress=$? [[ :$opts: != *:backward:* ]]; has_backward=$? } function ble/history/isearch-backward-blockwise { local opts=$1 local search_type has_stop_check has_progress has_backward ble/history/.read-isearch-options "$opts" ble/history/initialize if [[ $_ble_history_prefix ]]; then local -a _ble_history_edit builtin eval "_ble_history_edit=(\"\${${_ble_history_prefix}_history_edit[@]}\")" fi local isearch_block=1000 # 十分高速なのでこれぐらい大きくてOK local isearch_quantum=$((isearch_block*2)) # 倍数である必要有り local irest block j i=$index index= local flag_icase=; [[ :$opts: == *:ignore-case:* ]] && flag_icase=1 local flag_cycled= range_min range_max while :; do if ((i<=start)); then range_min=0 range_max=$start else flag_cycled=1 range_min=$((start+1)) range_max=$i fi while ((i>=range_min)); do ((block=range_max-i, block<5&&(block=5), block>i+1-range_min&&(block=i+1-range_min), irest=isearch_block-isearch_time%isearch_block, block>irest&&(block=irest))) [[ $flag_icase ]] && shopt -s nocasematch case $search_type in (regex) for ((j=i-block;++j<=i;)); do [[ ${_ble_history_edit[j]} =~ $needle ]] && index=$j done ;; (glob) for ((j=i-block;++j<=i;)); do [[ ${_ble_history_edit[j]} == $needle ]] && index=$j done ;; (head) for ((j=i-block;++j<=i;)); do [[ ${_ble_history_edit[j]} == "$needle"* ]] && index=$j done ;; (tail) for ((j=i-block;++j<=i;)); do [[ ${_ble_history_edit[j]} == *"$needle" ]] && index=$j done ;; (condition) builtin eval "function ble-edit/isearch/.search-block.proc { local LINE INDEX for ((j=i-block;++j<=i;)); do LINE=\${_ble_history_edit[j]} INDEX=\$j { $needle; } && index=\$j done }" ble-edit/isearch/.search-block.proc ;; (predicate) for ((j=i-block;++j<=i;)); do "$needle" "${_ble_history_edit[j]}" "$j" && index=$j done ;; (*) for ((j=i-block;++j<=i;)); do [[ ${_ble_history_edit[j]} == *"$needle"* ]] && index=$j done ;; esac [[ $flag_icase ]] && shopt -u nocasematch ((isearch_time+=block)) [[ $index ]] && return 0 ((i-=block)) if ((has_stop_check&&isearch_time%isearch_block==0)) && ble/decode/has-input; then index=$i return 148 elif ((has_progress&&isearch_time%isearch_quantum==0)); then "$isearch_progress_callback" "$i" fi done if [[ ! $flag_cycled && :$opts: == *:cyclic:* ]]; then ((i=${#_ble_history_edit[@]}-1)) ((start=start)); then expr_cond="index<${#_ble_history_edit[@]}" expr_incr='index++' else expr_cond="indexstart)) || return 1 else ((index=0)) ((index&2 return 1 fi } function ble/edit/performs-on-graphical-line { [[ $edit_line_type == graphical ]] || return 1 ble/textmap#is-up-to-date && return 0 ((bleopt_edit_forced_textmap)) || return 1 ble/widget/.update-textmap return 0 } bleopt/declare -n info_display top function bleopt/check:info_display { case $value in (top) [[ $_ble_canvas_panel_vfill == 4 ]] && return 0 _ble_canvas_panel_vfill=4 [[ $_ble_attached ]] && ble/canvas/panel/clear return 0 ;; (bottom) [[ $_ble_canvas_panel_vfill == 2 ]] && return 0 _ble_canvas_panel_vfill=2 [[ $_ble_attached ]] && ble/canvas/panel/clear return 0 ;; (*) ble/util/print "bleopt: Invalid value for 'info_display': $value" return 1 ;; esac } bleopt/declare -v prompt_ps1_final '' bleopt/declare -v prompt_ps1_transient '' bleopt/declare -v prompt_rps1 '' bleopt/declare -v prompt_rps1_final '' bleopt/declare -v prompt_rps1_transient '' bleopt/declare -v prompt_xterm_title '' bleopt/declare -v prompt_screen_title '' bleopt/declare -v prompt_term_status '' bleopt/declare -o rps1 prompt_rps1 bleopt/declare -o rps1_transient prompt_rps1_transient bleopt/declare -v prompt_eol_mark $'\e[94m[ble: EOF]\e[m' bleopt/declare -v prompt_ruler '' bleopt/declare -v prompt_status_line '' bleopt/declare -n prompt_status_align $'justify=\r' ble/color/defface prompt_status_line fg=231,bg=240 bleopt/declare -v prompt_command_changes_layout '' function bleopt/check:prompt_status_align { case $value in (left|right|center|justify|justify=?*) ble/prompt/unit#clear _ble_prompt_status hash return 0 ;; (*) ble/util/print "bleopt prompt_status_align: unsupported value: '$value'" >&2 return 1 ;; esac } bleopt/declare -n internal_exec_type gexec function bleopt/check:internal_exec_type { if ! ble/is-function "ble-edit/exec:$value/process"; then ble/util/print "bleopt: Invalid value internal_exec_type='$value'. A function 'ble-edit/exec:$value/process' is not defined." >&2 return 1 fi } bleopt/declare -v internal_exec_int_trace '' bleopt/declare -v internal_suppress_bash_output 1 bleopt/declare -n internal_ignoreeof_trap 'Use "exit" to leave the shell.' bleopt/declare -v allow_exit_with_jobs '' bleopt/declare -v history_share '' bleopt/declare -v accept_line_threshold 5 bleopt/declare -v exec_restore_pipestatus '' bleopt/declare -v edit_marker $'\e[94m[ble: %s]\e[m' bleopt/declare -v edit_marker_error $'\e[91m[ble: %s]\e[m' function ble/edit/marker#get { local msg=$1 opts=${2-} ret=$msg if [[ :$opts: != *:bare:* ]]; then if [[ :$opts: == *:error:* ]]; then ble/util/sprintf ret "$bleopt_edit_marker_error" "$ret" else ble/util/sprintf ret "$bleopt_edit_marker" "$ret" fi fi if [[ ! $ret && $msg && :$opts: == *:non-empty:* ]]; then if [[ :$opts: == *:error:* ]]; then ret=$'\e[91m[ble: '$msg$']\e[m' else ret=$'\e[94m[ble: '$msg$']\e[m' fi fi [[ $ret ]] } function ble/edit/marker#instantiate { ble/edit/marker#get "$@" if [[ $ret ]]; then ret=${ret%$'\e[m'}$'\e[m' x=0 y=0 g=0 LINES=1 ble/canvas/trace "$ret" confine:truncate fi [[ $ret ]] } function ble/edit/marker#declare-config { local name=$1 value=$2 opts=$3 if [[ :$opts: == *:error:* ]]; then value=$'\e[91m[ble: '$value$']\e[m' else value=$'\e[94m[ble: '$value$']\e[m' fi bleopt/declare -v "$name" "$value" } function ble/edit/marker#get-config { bleopt/default "$1" local default_value=$ret local current_ref=bleopt_$1 local current_value=${!current_ref} ret=$current_value if [[ $current_value == "$default_value" ]]; then if ble/string#match "$current_value" $'^\e\[94m\[ble: (.*)]\e\[m$'; then ble/util/sprintf ret "$bleopt_edit_marker" "${BASH_REMATCH[1]}" elif ble/string#match "$current_value" $'^\e\[91m\[ble: (.*)\]\e\[m$'; then ble/util/sprintf ret "$bleopt_edit_marker_error" "${BASH_REMATCH[1]}" fi fi [[ $ret ]] } function ble/edit/marker#instantiate-config { ble/edit/marker#get-config "$1" && ret=${ret%$'\e[m'}$'\e[m' && x=0 y=0 g=0 LINES=1 ble/canvas/trace "$ret" confine:truncate [[ $ret ]] } ble/edit/marker#declare-config exec_errexit_mark 'exit %d' error ble/edit/marker#declare-config exec_elapsed_mark 'elapsed %s (CPU %s%%)' bleopt/declare -v exec_elapsed_enabled 'usr+sys>=10000' ble/edit/marker#declare-config exec_exit_mark 'exit' bleopt/declare -v line_limit_length 10000 bleopt/declare -v line_limit_type none _ble_app_render_mode=panel _ble_app_winsize=() function ble/application/.set-up-render-mode { [[ $1 == "$_ble_app_render_mode" ]] && return 0 case $1 in (panel) ble/term/leave-altscr ble/canvas/panel/invalidate ;; (forms:*) ble/term/enter-altscr ble/util/buffer "$_ble_term_clear" ble/util/buffer $'\e[H' _ble_canvas_x=0 _ble_canvas_y=0 ;; (*) ble/util/print "ble/edit: unrecognized render mode '$1'." return 1 ;; esac } function ble/application/push-render-mode { ble/application/.set-up-render-mode "$1" || return 1 ble/array#unshift _ble_app_render_mode "$1" } function ble/application/pop-render-mode { [[ ${_ble_app_render_mode[1]} ]] || return 1 ble/application/.set-up-render-mode "${_ble_app_render_mode[1]}" ble/array#shift _ble_app_render_mode } function ble/application/render { if [[ $_ble_app_onwinch_Deferred ]]; then ble/application/onwinch return "$?" fi local _ble_app_onwinch_Suppress=1 { local render=$_ble_app_render_mode case $render in (panel) local _ble_prompt_update=owner ble/prompt/update ble/canvas/panel/render ;; (forms:*) ble/forms/render "${render#*:}" ;; # NYI esac _ble_app_winsize=("$COLUMNS" "$LINES") ble/util/buffer.flush } ble/util/unlocal _ble_app_onwinch_Suppress if [[ $_ble_app_onwinch_Deferred ]]; then ble/application/onwinch fi } blehook idle_after_task!=ble/application/render function ble/application/onwinch/panel.process-redraw-here { local old_w=${_ble_app_winsize[0]} local -a DRAW_BUFF=() if ((COLUMNS>old_w)); then ble/canvas/panel/goto-top-dock.draw local i npanel=${#_ble_canvas_panel_class[@]} local y0=0 local nchar=0 for ((i=0;i=y0)) && ((nchar+=(_ble_canvas_y-y0)*(old_w-1)*_ble_canvas_x)) local new_y_min=$(((nchar-1)/COLUMNS)) ((_ble_canvas_y>new_y_min)) && _ble_canvas_y=$new_y_min fi ble/canvas/panel#goto.draw 0 0 0 ble/canvas/bflush.draw return 0 } _ble_app_onwinch_Suppress= _ble_app_onwinch_Deferred= function ble/application/onwinch { if [[ $_ble_app_onwinch_Suppress || $_ble_decode_hook_Processing == body || $_ble_decode_hook_Processing == prologue ]]; then _ble_app_onwinch_Deferred=1 return 0 fi local _ble_app_onwinch_Suppress=1 _ble_app_onwinch_Deferred= _ble_textmap_cols= local old_size= i for ((i=0;i<20;i++)); do (ble/util/msleep 50) if ble/util/is-running-in-subshell || ((50200<=_ble_bash&&_ble_bash<50300)); then ble/term/update-winsize fi ble/util/joblist.check ignore-volatile-jobs local size=$LINES:$COLUMNS [[ $size == "$old_size" ]] && break old_size=$size local render=$_ble_app_render_mode case $render in (panel) case $bleopt_canvas_winch_action in (clear) _ble_prompt_trim_opwd= ble/util/buffer "$_ble_term_clear" ;; (redraw-here) ble/application/onwinch/panel.process-redraw-here ;; (redraw-prev) local -a DRAW_BUFF=() ble/canvas/panel#goto.draw 0 0 0 ble/canvas/bflush.draw ;; (redraw-safe) ;; esac ble/canvas/panel/invalidate height ;; (forms:*) ble/forms/invalidate "${render#*:}" ;; # NYI esac ble/application/render done ble/util/unlocal _ble_app_onwinch_Suppress if [[ $_ble_app_onwinch_Deferred ]]; then ble/application/onwinch fi } _ble_canvas_panel_focus=0 _ble_canvas_panel_class=(ble/textarea ble/textarea ble/edit/info ble/edit/visible-bell ble/prompt/status) _ble_canvas_panel_height=(1 0 0 0 0) _ble_canvas_panel_vfill=4 _ble_edit_command_layout_level=0 function ble/edit/enter-command-layout { ((_ble_edit_command_layout_level++==0)) || return 0 ble/edit/info#collapse "$_ble_edit_info_panel" ble/edit/visible-bell#collapse ble/prompt/status#collapse } function ble/edit/leave-command-layout { ((_ble_edit_command_layout_level>0&& --_ble_edit_command_layout_level==0)) || return 0 blehook/invoke info_reveal ble/edit/info/default } function ble/edit/clear-command-layout { ((_ble_edit_command_layout_level>0)) || return 0 _ble_edit_command_layout_level=1 ble/edit/leave-command-layout } function ble/edit/is-command-layout { ((_ble_edit_command_layout_level>0)) } _ble_prompt_status_panel=4 _ble_prompt_status_dirty= _ble_prompt_status_data=() _ble_prompt_status_bbox=() function ble/prompt/status#panel::invalidate { _ble_prompt_status_dirty=1 } function ble/prompt/status#panel::render { [[ $_ble_prompt_status_dirty ]] || return 0 _ble_prompt_status_dirty= local index=$1 local height; ble/prompt/status#panel::getHeight "$index" [[ ${height#*:} == 1 ]] || return 0 local -a DRAW_BUFF=() height=$3 if ((height!=1)); then ble/canvas/panel/reallocate-height.draw ble/canvas/bflush.draw height=${_ble_canvas_panel_height[index]} ((height==0)) && return 0 fi local esc=${_ble_prompt_status_data[10]} if [[ $esc ]]; then local prox=${_ble_prompt_status_data[11]} local proy=${_ble_prompt_status_data[12]} ble/canvas/panel#goto.draw "$_ble_prompt_status_panel" ble/canvas/panel#put.draw "$_ble_prompt_status_panel" "$esc" "$prox" "$proy" else ble/canvas/panel#clear.draw "$_ble_prompt_status_panel" fi ble/canvas/bflush.draw } function ble/prompt/status#panel::getHeight { if ble/edit/is-command-layout || [[ ! ${_ble_prompt_status_data[10]} ]]; then height=0:0 else height=0:1 fi } function ble/prompt/status#panel::onHeightChange { ble/prompt/status#panel::invalidate } function ble/prompt/status#collapse { local -a DRAW_BUFF=() ble/canvas/panel#set-height.draw "$_ble_prompt_status_panel" 0 ble/canvas/bflush.draw } _ble_edit_vbell_panel=3 _ble_edit_vbell_state=('' '' 0) function ble/edit/visible-bell#panel::getHeight { if [[ ${_ble_edit_vbell_state[0]} ]]; then height=0:1 else height=0:0 fi } function ble/edit/visible-bell#panel::invalidate { (($1!=_ble_edit_vbell_panel)) && return 0 _ble_edit_vbell_state[2]=1 } function ble/edit/visible-bell#panel::render { (($1!=_ble_edit_vbell_panel)) && return 0 ble/edit/is-command-layout && return 0 ((_ble_edit_vbell_state[2]==1)) || return 0 local message=${_ble_edit_vbell_state[0]} local -a DRAW_BUFF=() if [[ ! $message ]]; then ble/canvas/panel#set-height.draw "$_ble_edit_vbell_panel" 0 else ble/canvas/panel/reallocate-height.draw local panel_height=${_ble_canvas_panel_height[$1]} if ((panel_height>=1)); then local ret ble/canvas/panel/save-position; local pos=$ret ble/canvas/put.draw "$_ble_term_sgr0" ble/canvas/panel#clear.draw "$_ble_edit_vbell_panel" ble/canvas/panel#goto.draw "$_ble_edit_vbell_panel" local lines=1 cols=${COLUMNS:-80} ((_ble_term_xenl||COLUMNS--)) if ((cols!=_ble_edit_vbell_state[5])); then local x=0 y=0 ret= sgr0= sgr1= ble/canvas/trace-text "$message" nonewline:external-sgr _ble_edit_vbell_state[4]=$ret _ble_edit_vbell_state[5]=$cols _ble_edit_vbell_state[6]=$x fi local sgr=${_ble_edit_vbell_state[3]} local esc=${_ble_edit_vbell_state[4]} local esc_w=${_ble_edit_vbell_state[6]} local margin=$((cols-esc_w)) case :$bleopt_vbell_align: in (*:left:*) margin=0;; (*:center:*) ((margin/=2)) ;; (*:right:*) ;; esac ble/canvas/put.draw "$_ble_term_cr" ((margin>0)) && ble/canvas/put-cuf.draw "$margin" ble/canvas/put.draw "$sgr$esc" ((_ble_canvas_x=margin+esc_w)) ble/canvas/panel/load-position.draw "$pos" fi fi ble/canvas/bflush.draw _ble_edit_vbell_state[2]=0 } function ble/edit/visible-bell#collapse { ble/util/idle.cancel ble/edit/visible-bell/.async-1.idle ble/util/idle.cancel ble/edit/visible-bell/.async-2.idle _ble_edit_vbell_state=('' '' 0) local -a DRAW_BUFF=() ble/canvas/panel#set-height.draw "$_ble_edit_vbell_panel" 0 ble/canvas/bflush.draw } function ble/edit/visible-bell/.show { [[ ${_ble_edit_vbell_state[0]} ]] || return 0 local ret ble/color/face2sgr "$1"; local sgr=$ret if [[ $sgr != "${_ble_edit_vbell_state[2]}" ]]; then _ble_edit_vbell_state[2]=1 # invalidate _ble_edit_vbell_state[3]=$sgr fi ble/edit/visible-bell#panel::render "$_ble_edit_vbell_panel" ble/util/buffer.flush } function ble/edit/visible-bell/.clear { ble/edit/visible-bell#collapse ble/util/buffer.flush } function ble/edit/visible-bell { [[ $_ble_attached ]] || return 1 ble/util/is-running-in-subshell && return 1 ble/is-function ble/util/idle.push || return 1 ble/util/is-running-in-idle && return 1 local message=$1 opts=$2 if [[ ! $message ]]; then ble/edit/visible-bell/.clear return 0 fi ble/util/idle.cancel ble/edit/visible-bell/.async-1.idle ble/util/idle.cancel ble/edit/visible-bell/.async-2.idle _ble_edit_vbell_state=("$message" "$opts" 1) ble/edit/visible-bell/.show vbell_flash ble/util/idle.push --sleep=50 ble/edit/visible-bell/.async-1.idle return 0 } function ble/edit/visible-bell/.async-1.idle { ble/edit/visible-bell/.show vbell if [[ :${_ble_edit_vbell_state[1]}: != *:persistent:* ]]; then local msec=$((bleopt_vbell_duration)) ble/util/idle.push --sleep="$msec" ble/edit/visible-bell/.async-2.idle fi return 0 } function ble/edit/visible-bell/.async-2.idle { ble/edit/visible-bell/.clear return 0 } _ble_prompt_hash= _ble_prompt_version=0 function ble/prompt/.escape-control-characters { ret=$1 local ctrl=$'\001-\037\177' case $_ble_util_locale_encoding in (UTF-8) ctrl=$ctrl$'\302\200-\302\237' ;; (C) ctrl=$ctrl$'\200-\237' ;; esac local LC_ALL= LC_COLLATE=C glob_ctrl=[$ctrl] [[ $ret == *$glob_ctrl* ]] || return 0 local out= head tail=$ret cs while head=${tail%%$glob_ctrl*}; [[ $head != "$tail" ]]; do ble/util/s2c "${tail:${#head}:1}" ble/unicode/GraphemeCluster/.get-ascii-rep "$ret" # -> cs out=$out$head$'\e[9807m'$cs$'\e[9807m' tail=${tail#*$glob_ctrl} done ret=$out$tail } ble/function#suppress-stderr ble/prompt/.escape-control-characters # LC_COLLATE function ble/prompt/.initialize-constant { local _ble_local_ps=$1 local _ble_local_defeval=$2 local _ble_local_opts=$3 if ((_ble_bash>=40400)); then ret=${_ble_local_ps@P} else builtin eval -- "$_ble_local_defeval" fi if [[ $_ble_local_opts == *:escape:* ]]; then if ((_ble_bash>=50200)); then if [[ $ret == *\^['A'-'Z[\]^_?']* ]]; then builtin eval -- "$_ble_local_defeval" ble/prompt/.escape-control-characters "$ret" elif [[ $ret == *$'\t'* ]]; then ble/prompt/.escape-control-characters "$ret" fi else ble/prompt/.escape-control-characters "$_ble_prompt_const_s" fi fi } function ble/prompt/initialize { local ret ble/prompt/.initialize-constant '\H' 'ret=${HOSTNAME:-$_ble_base_env_HOSTNAME}' escape _ble_prompt_const_H=$ret if local rex='^[0-9]+(\.[0-9]){3}$'; [[ $_ble_prompt_const_H =~ $rex ]]; then _ble_prompt_const_h=$_ble_prompt_const_H else _ble_prompt_const_h=${_ble_prompt_const_H%%.*} fi ble/prompt/.initialize-constant '\l' 'ble/util/assign ret "ble/bin/tty 2>/dev/null";ret=${ret##*/}' _ble_prompt_const_l=$ret ble/prompt/.initialize-constant '\s' 'ret=${0##*/}' escape _ble_prompt_const_s=$ret ble/prompt/.initialize-constant '\u' 'ret=${USER:-$_ble_base_env_USER}' escape _ble_prompt_const_u=$ret ble/util/sprintf _ble_prompt_const_v '%d.%d' "${BASH_VERSINFO[0]}" "${BASH_VERSINFO[1]}" ble/util/sprintf _ble_prompt_const_V '%d.%d.%d' "${BASH_VERSINFO[0]}" "${BASH_VERSINFO[1]}" "${BASH_VERSINFO[2]}" if [[ $EUID -eq 0 ]]; then _ble_prompt_const_root='#' else _ble_prompt_const_root='$' fi if [[ $OSTYPE == cygwin* ]]; then local windir=/cygdrive/c/Windows if [[ $WINDIR == [a-zA-Z]:\\* ]]; then local bsl='\' sl=/ local c=${WINDIR::1} path=${WINDIR:3} if ble/string#isupper "$c"; then if ((_ble_bash>=40000)); then c=${c,?} else local ret ble/util/s2c "$c" ble/util/c2s "$((ret+32))" c=$ret fi fi windir=/cygdrive/$c/${path//"$bsl"/"$sl"} fi if [[ -e $windir && -w $windir ]]; then _ble_prompt_const_root='#' fi elif [[ $OSTYPE == msys* ]]; then if ble/bin#has id getent; then local id getent ble/util/assign id 'id -G' ble/util/assign getent 'getent -w group S-1-16-12288' ble/string#split getent : "$getent" [[ " $id " == *" ${getent[1]} "* ]] && _ble_prompt_const_root='#' fi fi } function ble/prompt/unit#update { local unit=$1 local prompt_unit_changed= local prompt_unit_expired= local ohashref=${unit}_data[1]; ohashref=${!ohashref-} if [[ ! $ohashref ]]; then prompt_unit_expired=1 else ble/prompt/unit#update/.update-dependencies "$ohashref" local ohash=${unit}_data[2]; ohash=${!ohash} builtin eval -- "local nhash=\"$ohashref\"" 2>/dev/null [[ $nhash != "$ohash" ]] && prompt_unit_expired=1 fi if [[ $prompt_unit_expired ]]; then local prompt_unit=$unit local prompt_hashref_dep= # プロンプト間依存性 local prompt_hashref_var= # 変数に対する依存性 ble/prompt/unit:"$unit"/update "$unit" && ((prompt_unit_changed=1,${unit}_data[0]++)) local hashref=${prompt_hashref_base-'$_ble_prompt_version'}:$prompt_hashref_dep:$prompt_hashref_var builtin eval -- "${unit}_data[1]=\$hashref" builtin eval -- "${unit}_data[2]=\"$hashref\"" 2>/dev/null ble/util/unlocal prompt_unit prompt_hashref_dep fi if [[ $prompt_unit ]]; then local ref1='$'$unit'_data' [[ ,$prompt_hashref_dep, != *,"$ref1",* ]] && prompt_hashref_dep=$prompt_hashref_dep${prompt_hashref_dep:+,}$ref1 fi [[ $prompt_unit_changed ]] } function ble/prompt/unit#update/.update-dependencies { local ohashref=$1 local otree=${ohashref#*:}; otree=${otree%%:*} if [[ $otree ]]; then ble/string#split otree , "$otree" if [[ ! $ble_prompt_unit_processing ]]; then local ble_prompt_unit_processing=1 "${_ble_util_set_declare[@]//NAME/ble_prompt_unit_mark}" # WA #D1570 checked elif ble/set#contains ble_prompt_unit_mark "$unit"; then ble/util/print "ble/prompt: FATAL: detected cyclic dependency ($unit required by $ble_prompt_unit_parent)" >&"$_ble_util_fd_tui_stderr" return 1 fi local ble_prompt_unit_parent=$unit ble/set#add ble_prompt_unit_mark "$unit" local prompt_unit= # 依存関係の登録はしない local child for child in "${otree[@]}"; do [[ $child == '$'?*'_data' ]] || continue child=${child:1:${#child}-6} ble/is-function ble/prompt/unit:"$child"/update && ble/prompt/unit#update "$child" done ble/set#remove ble_prompt_unit_mark "$unit" fi } function ble/prompt/unit#clear { local prefix=$1 builtin eval -- "${prefix}_data[2]=" } function ble/prompt/unit/assign { local var=$1 value=$2 [[ $value == "${!var}" ]] && return 1 prompt_unit_changed=1 builtin eval -- "$var=\$value" } function ble/prompt/unit/add-hash { [[ $prompt_unit && ,$prompt_hashref_var, != *,"$1",* ]] && prompt_hashref_var=$prompt_hashref_var${prompt_hashref_var:+,}$1 return 0 } _ble_prompt_ps1_dirty= _ble_prompt_ps1_data=(0 '' '' 0 0 0 32 0 '' '') _ble_prompt_ps1_bbox=() _ble_prompt_rps1_dirty= _ble_prompt_rps1_data=() _ble_prompt_rps1_gbox=() _ble_prompt_rps1_shown= _ble_prompt_xterm_title_dirty= _ble_prompt_xterm_title_data=() _ble_prompt_screen_title_dirty= _ble_prompt_screen_title_data=() _ble_prompt_term_status_dirty= _ble_prompt_term_status_data=() function ble/prompt/print { local ret=$1 [[ $prompt_noesc ]] || ble/string#escape-characters "$ret" '\$"`' ble/canvas/put.draw "$ret" } function ble/prompt/process-prompt-string { local ps1=$1 local i=0 iN=${#ps1} local rex_letters='^[^\]+|\\$' while ((i=0)) && ble/widget/.update-textmap local fmt=${1:-'(%s,%s)'} pos ble/prompt/unit/add-hash '${_ble_textmap_pos[_ble_edit_ind]}' ble/string#split-words pos "${_ble_textmap_pos[_ble_edit_ind]}" ble/util/sprintf pos "$fmt" "$((pos[1]+1))" "$((pos[0]+1))" ble/prompt/print "$pos" } function ble/prompt/backslash:row { ((_ble_textmap_dbeg>=0)) && ble/widget/.update-textmap local pos ble/prompt/unit/add-hash '${_ble_textmap_pos[_ble_edit_ind]}' ble/string#split-words pos "${_ble_textmap_pos[_ble_edit_ind]}" ble/prompt/print "$((pos[1]+1))" } function ble/prompt/backslash:column { ((_ble_textmap_dbeg>=0)) && ble/widget/.update-textmap local pos ble/prompt/unit/add-hash '${_ble_textmap_pos[_ble_edit_ind]}' ble/string#split-words pos "${_ble_textmap_pos[_ble_edit_ind]}" ble/prompt/print "$((pos[0]+1))" } function ble/prompt/backslash:point { ble/prompt/unit/add-hash '$_ble_edit_ind' ble/prompt/print "$_ble_edit_ind" } function ble/prompt/backslash:mark { ble/prompt/unit/add-hash '$_ble_edit_mark' ble/prompt/print "$_ble_edit_mark" } function ble/prompt/backslash:history-index { ble/prompt/unit/add-hash '$_ble_history_INDEX' ble/canvas/put.draw "$((_ble_history_INDEX+1))" } function ble/prompt/backslash:history-percentile { ble/prompt/unit/add-hash '$_ble_history_INDEX' ble/prompt/unit/add-hash '$_ble_history_COUNT' local index=$_ble_history_INDEX local count=$_ble_history_COUNT ((count||count++)) ble/canvas/put.draw "$((index*100/count))%" } function ble/prompt/.update-working-directory { [[ $prompt_cache_wd ]] && return 0 if [[ ! ${PWD//'/'} ]]; then prompt_cache_wd=$PWD return 0 fi local head= body=${PWD%/} if [[ $body == "$HOME" ]]; then prompt_cache_wd='~' return 0 elif [[ $body == "$HOME"/* ]]; then head='~/' body=${body#"$HOME"/} fi if [[ $PROMPT_DIRTRIM ]]; then local dirtrim=$((PROMPT_DIRTRIM)) local pat='[^/]' local count=${body//$pat} if ((${#count}>=dirtrim)); then local ret ble/string#repeat '/*' "$dirtrim" local omit=${body%$ret} ((${#omit}>3)) && body=...${body:${#omit}} fi fi prompt_cache_wd=$head$body } function ble/prompt/.escape/check-double-quotation { if [[ $tail == '"'* ]]; then if [[ ! $nest ]]; then out=$out'\"' tail=${tail:1} else out=$out'"' tail=${tail:1} nest=\"$nest ble/prompt/.escape/update-rex_skip fi return 0 else return 1 fi } function ble/prompt/.escape/check-command-substitution { if [[ $tail == '$('* ]]; then out=$out'$(' tail=${tail:2} nest=')'$nest ble/prompt/.escape/update-rex_skip return 0 else return 1 fi } function ble/prompt/.escape/check-parameter-expansion { if [[ $tail == '${'* ]]; then out=$out'${' tail=${tail:2} nest='}'$nest ble/prompt/.escape/update-rex_skip return 0 else return 1 fi } function ble/prompt/.escape/check-incomplete-quotation { if [[ $tail == '`'* ]]; then local rex='^`([^\`]|\\.)*\\$' [[ $tail =~ $rex ]] && tail=$tail'\' out=$out$tail'`' tail= return 0 elif [[ $nest == ['})']* && $tail == \'* ]]; then out=$out$tail$q tail= return 0 elif [[ $nest == ['})']* && $tail == \$\'* ]]; then local rex='^\$'$q'([^\'$q']|\\.)*\\$' [[ $tail =~ $rex ]] && tail=$tail'\' out=$out$tail$q tail= return 0 elif [[ $tail == '\' ]]; then out=$out'\\' tail= return 0 else return 1 fi } function ble/prompt/.escape/update-rex_skip { if [[ $nest == \)* ]]; then rex_skip=$rex_skip_paren elif [[ $nest == \}* ]]; then rex_skip=$rex_skip_brace else rex_skip=$rex_skip_dquot fi } function ble/prompt/.escape { local tail=$1 out= nest= local q=\' local rex_bq='`([^\`]|\\.)*`' local rex_sq=$q'[^'$q']*'$q'|\$'$q'([^\'$q']|\\.)*'$q local rex_skip local rex_skip_dquot='^([^\"$`]|'$rex_bq'|\\.)+' local rex_skip_brace='^([^\"$`'$q'}]|'$rex_bq'|'$rex_sq'|\\.)+' local rex_skip_paren='^([^\"$`'$q'()]|'$rex_bq'|'$rex_sq'|\\.)+' ble/prompt/.escape/update-rex_skip while [[ $tail ]]; do if [[ $tail =~ $rex_skip ]]; then out=$out$BASH_REMATCH tail=${tail:${#BASH_REMATCH}} elif [[ $nest == ['})"']* && $tail == "${nest::1}"* ]]; then out=$out${nest::1} tail=${tail:1} nest=${nest:1} ble/prompt/.escape/update-rex_skip elif [[ $nest == \)* && $tail == \(* ]]; then out=$out'(' tail=${tail:1} nest=')'$nest elif ble/prompt/.escape/check-double-quotation; then continue elif ble/prompt/.escape/check-command-substitution; then continue elif ble/prompt/.escape/check-parameter-expansion; then continue elif ble/prompt/.escape/check-incomplete-quotation; then continue else out=$out${tail::1} tail=${tail:1} fi done ret=$out$nest } function ble/prompt/.get-keymap-for-current-mode { ble/prompt/unit/add-hash '$_ble_decode_keymap,${_ble_decode_keymap_stack[*]}' keymap=$_ble_decode_keymap local index=${#_ble_decode_keymap_stack[@]} while :; do case $keymap in (vi_?map|emacs) return 0 ;; esac ((--index<0)) && break keymap=${_ble_decode_keymap_stack[index]} done return 1 } function ble/prompt/.uses-builtin-prompt-expansion { ((_ble_bash>=40400)) || return 1 local ps=$1 local chars_safe_esc='][0-7aenrdtAT@DhHjlsuvV!$\wW' [[ ( $OSTYPE == cygwin || $OSTYPE == msys ) && $_ble_prompt_const_root == '#' ]] && chars_safe_esc=${chars_safe_esc//'$'} # Note: cygwin では ble.sh 独自の方法で \$ を処理する。 [[ $ps == *'\'[!"$chars_safe_esc"]* ]] && return 1 local glob_ctrl=$'[\001-\037\177]' [[ $ps == *'\'[wW]* && $PWD == *$glob_ctrl* ]] && return 1 [[ $ps == *'\s'* && $_ble_prompt_const_s == *$'\e'* ]] && return 1 [[ $ps == *'\u'* && $_ble_prompt_const_u == *$'\e'* ]] && return 1 [[ $ps == *'\h'* && $_ble_prompt_const_h == *$'\e'* ]] && return 1 [[ $ps == *'\H'* && $_ble_prompt_const_H == *$'\e'* ]] && return 1 return 0 } function ble/prompt/.instantiate { trace_hash= esc= x=0 y=0 g=0 lc=32 lg=0 local ps=$1 opts=$2 x0=$3 y0=$4 g0=$5 lc0=$6 lg0=$7 esc0=$8 trace_hash0=$9 [[ ! $ps ]] && return 0 local expanded= if ble/prompt/.uses-builtin-prompt-expansion "$ps"; then [[ $ps == *'\'[wW]* ]] && ble/prompt/unit/add-hash '$PWD' ble-edit/exec/.setexit "$_ble_edit_exec_lastarg" LINENO=$_ble_edit_LINENO \ BASH_COMMAND=$_ble_edit_exec_BASH_COMMAND \ builtin eval 'expanded=${ps@P}' else local prompt_noesc= shopt -q promptvars &>/dev/null || prompt_noesc=1 local -a DRAW_BUFF=() ble/prompt/process-prompt-string "$ps" local processed; ble/canvas/sflush.draw -v processed if [[ ! $prompt_noesc ]]; then local ret ble/prompt/.escape "$processed"; local escaped=$ret expanded=${trace_hash0#*:} # Note: これは次行が失敗した時の既定値 ble-edit/exec/.setexit "$_ble_edit_exec_lastarg" LINENO=$_ble_edit_LINENO \ BASH_COMMAND=$_ble_edit_exec_BASH_COMMAND \ builtin eval "expanded=\"$escaped\"" else expanded=$processed fi fi if [[ :$opts: == *:show-mode-in-prompt:* ]]; then if ble/util/rlvar#test show-mode-in-prompt; then local keymap; ble/prompt/.get-keymap-for-current-mode local ret= case $keymap in (vi_imap) ble/util/rlvar#read vi-ins-mode-string '(ins)' ;; # Note: bash-4.3 では '+' (vi_[noxs]map) ble/util/rlvar#read vi-cmd-mode-string '(cmd)' ;; # Note: bash-4.3 では ':' (emacs) ble/util/rlvar#read emacs-mode-string '@' ;; esac [[ $ret ]] && expanded=$ret$expanded fi fi if [[ :$opts: == *:no-trace:* ]]; then x=0 y=0 g=0 lc=32 lg=0 esc=$expanded elif local ret g0=0 if ble/string#match ":$opts:" ':g0=([^:]+):'; then ((g0=BASH_REMATCH[1])) elif ble/string#match ":$opts:" ':face0=([^:]+):'; then ble/color/face2g "${BASH_REMATCH[1]}" && g0=$ret fi local rows=${prompt_rows:-${LINES:-25}} local cols=${prompt_cols:-${COLUMNS:-80}} local color=$_ble_color_g2sgr_version local bleopt=$bleopt_char_width_mode,$bleopt_char_width_version,$bleopt_emoji_version,$bleopt_emoji_opts trace_hash=$opts#$rows,$cols,$color,$g0#$bleopt#$expanded [[ $trace_hash != "$trace_hash0" ]] then local trace_opts=$opts:prompt [[ $bleopt_internal_suppress_bash_output ]] || trace_opts=$trace_opts:left-char x=0 y=0 g=0 lc=32 lg=0 local ret LINES=$rows COLUMNS=$cols ble/canvas/trace "$expanded" "$trace_opts"; local traced=$ret ((lc<0&&(lc=0))) esc=$traced return 0 else x=$x0 y=$y0 g=$g0 lc=$lc0 lg=$lg0 esc=$esc0 return 2 fi } function ble/prompt/unit:{section}/clear { local prefix=$1 type=${2:-hash:draw} [[ :$type: == *:hash:* ]] && builtin eval -- "${prefix}_data[2]=" [[ :$type: == *:tail:* ]] && builtin eval -- "${prefix}_data=(\"\${${prefix}_data[@]::10}\")" [[ :$type: == *:draw:* ]] && builtin eval -- "${prefix}_dirty=1" [[ :$type: == *:all:* ]] && builtin eval -- "${prefix}_data=(\"\${${prefix}_data[0]}\")" return 0 } function ble/prompt/unit:{section}/get { local ref=${1}_data[8]; ret=${!ref} } function ble/prompt/unit:{section}/update { local prefix=$1 ps=$2 opts=$3 local -a vars; vars=(data dirty) [[ :$opts: == *:measure-bbox:* ]] && ble/array#push vars bbox [[ :$opts: == *:measure-gbox:* ]] && ble/array#push vars gbox local "${vars[@]/%/=}" # WA #D1570 checked ble/util/restore-vars "${prefix}_" "${vars[@]}" local has_changed= if [[ $prompt_unit_expired ]]; then local original_esc=${data[8]}:${data[9]}:${data[10]} # esc:trace_hash:tailor if [[ $ps ]]; then [[ :$opts: == *:measure-bbox:* ]] && local x1=${bbox[0]} y1=${bbox[1]} x2=${bbox[2]} y2=${bbox[3]} [[ :$opts: == *:measure-gbox:* ]] && local gx1=${gbox[0]} gy1=${gbox[1]} gx2=${gbox[2]} gy2=${gbox[3]} local trace_hash esc x y g lc lg ble/prompt/.instantiate "$ps" "$opts" "${data[@]:3:7}" data=("${data[0]:-0}" '' '' "$x" "$y" "$g" "$lc" "$lg" "$esc" "$trace_hash" "${data[@]:10}") [[ :$opts: == *:measure-bbox:* ]] && bbox=("$x1" "$y1" "$x2" "$y2") [[ :$opts: == *:measure-gbox:* ]] && gbox=("$gx1" "$gy1" "$gx2" "$gy2") else data=("${data[0]:-0}" '' '' 0 0 0 32 0 '' '' "${data[@]:10}") [[ :$opts: == *:measure-bbox:* ]] && bbox=() [[ :$opts: == *:measure-gbox:* ]] && gbox=() fi [[ ${data[8]}:${data[9]}:${data[10]} != "$original_esc" ]] && has_changed=1 fi [[ $has_changed ]] && ((dirty=1)) ble/util/save-vars "${prefix}_" "${vars[@]}" [[ $has_changed ]] } function ble/prompt/unit:_ble_prompt_ps1/update { ble/prompt/unit/add-hash '$prompt_ps1' ble/prompt/unit:{section}/update _ble_prompt_ps1 "$prompt_ps1" show-mode-in-prompt:measure-bbox } function ble/prompt/unit:_ble_prompt_rps1/update { ble/prompt/unit/add-hash '$prompt_rps1' ble/prompt/unit/add-hash '$_ble_prompt_ps1_data' local cols=${COLUMNS-80} local ps1x=${_ble_prompt_ps1_data[3]} local ps1y=${_ble_prompt_ps1_data[4]} local prompt_rows=$((ps1y+1)) prompt_cols=$cols ble/prompt/unit:{section}/update _ble_prompt_rps1 "$prompt_rps1" confine:relative:right:measure-gbox || return 1 local esc=${_ble_prompt_rps1_data[8]} width= if [[ $esc ]]; then ((width=_ble_prompt_rps1_gbox[2]-_ble_prompt_rps1_gbox[0])) ((width&&20+width0)); then ((x+=xshift)) ble/canvas/put-cuf.draw "$xshift" fi ble/canvas/put.draw "$esc" ble/canvas/sflush.draw -v esc _ble_prompt_status_data[10]=$esc _ble_prompt_status_data[11]=$x _ble_prompt_status_data[12]=$y else _ble_prompt_status_data[10]= _ble_prompt_status_data[11]= _ble_prompt_status_data[12]= fi return 0 } if ble/is-function ble/util/idle.push; then _ble_prompt_timeout_task= _ble_prompt_timeout_lineno= function ble/prompt/timeout/process { ble/util/idle.suspend # exit に失敗した時の為 task を suspend にする ble/edit/marker#instantiate 'auto-logout' non-empty local msg="$ret timed out waiting for input" ble/widget/.internal-print-command ' ble/util/print "$msg" _ble_builtin_exit_processing=1 ble/builtin/exit 0' pre-flush return 1 # exit に失敗した時 } >&"$_ble_util_fd_tui_stdout" 2>&"$_ble_util_fd_tui_stderr" function ble/prompt/timeout/check { [[ $_ble_edit_lineno == "$_ble_prompt_timeout_lineno" ]] && return 0 _ble_prompt_timeout_lineno=$_ble_edit_lineno if [[ ${TMOUT:-} =~ ^[0-9]+ ]] && ((BASH_REMATCH>0)); then if [[ ! $_ble_prompt_timeout_task ]]; then ble/util/idle.push -Z 'ble/prompt/timeout/process' _ble_prompt_timeout_task=$_ble_util_idle_lasttask fi ble/util/idle#sleep "$_ble_prompt_timeout_task" "$((BASH_REMATCH*1000))" elif [[ $_ble_prompt_timeout_task ]]; then ble/util/idle#suspend "$_ble_prompt_timeout_task" fi } else function ble/prompt/timeout/check { return 0; } fi function ble/prompt/update/.has-prompt_command { [[ ${_ble_edit_PROMPT_COMMAND[*]} == *[![:space:]]* ]] } function _ble_prompt_update__eval_prompt_command_1 { local _ble_edit_exec_TRAPDEBUG_enabled=1 ble-edit/exec/.setexit "$_ble_edit_exec_lastarg" LINENO=$_ble_edit_LINENO \ BASH_COMMAND=$_ble_edit_exec_BASH_COMMAND \ builtin eval -- "$1" } ble/function#trace _ble_prompt_update__eval_prompt_command_1 function ble/prompt/update/.eval-prompt_command { ((${#PROMPT_COMMAND[@]})) || return 0 local _ble_local_command _ble_edit_exec_TRAPDEBUG_adjusted=1 ble-edit/exec:gexec/.TRAPDEBUG/restore filter 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 } _ble_prompt_update= _ble_prompt_update_dirty= _ble_prompt_rps1_enabled= function ble/prompt/update { local opts=:$1: dirty= local count; ble/history/get-count local version=$COLUMNS:$_ble_edit_lineno:$count if [[ :$opts: == *:check-dirty:* && $_ble_prompt_update == owner ]]; then if [[ $_ble_prompt_update_dirty && :$opts: != *:leave:* && $_ble_prompt_hash == "$version" ]]; then [[ $_ble_prompt_update_dirty == dirty ]]; local ext=$? _ble_prompt_update_dirty=done return "$ext" fi fi ble/prompt/timeout/check _ble_prompt_rps1_enabled= if ((_ble_textarea_panel==0)); then # 補助プロンプトに対しては PROMPT_COMMAND は実行しない if [[ ${_ble_prompt_hash%:*} != "${version%:*}" && $opts != *:leave:* ]]; then ble-edit/exec:gexec/invoke-hook-with-setexit internal_PRECMD if ble/prompt/update/.has-prompt_command || blehook/has-hook PRECMD; then if [[ $bleopt_prompt_command_changes_layout ]]; then ble/edit/enter-command-layout # #D1800 pair=leave-command-layout local -a DRAW_BUFF=() ble/canvas/panel#goto.draw 0 0 0 sgr0 ble/canvas/bflush.draw ble/util/buffer.flush fi ((_ble_edit_attached)) && ble-edit/restore-PS1 ble-edit/exec:gexec/invoke-hook-with-setexit PRECMD ble/prompt/update/.eval-prompt_command ((_ble_edit_attached)) && ble-edit/adjust-PS1 if [[ $bleopt_prompt_command_changes_layout ]]; then ble/edit/leave-command-layout # #D1800 pair=enter-command-layout fi fi fi fi local prompt_opts= local prompt_ps1=$_ble_edit_PS1 local prompt_rps1=$bleopt_prompt_rps1 if [[ $opts == *:leave:* ]]; then local ps1f=$bleopt_prompt_ps1_final local rps1f=$bleopt_prompt_rps1_final local ps1t=$bleopt_prompt_ps1_transient [[ :$ps1t: == *:trim:* || :$ps1t: == *:same-dir:* && $PWD != $_ble_prompt_trim_opwd ]] && ps1t= if [[ $ps1f || $rps1f || $ps1t ]]; then prompt_opts=$prompt_opts:leave-rewrite [[ $ps1f || $ps1t ]] && prompt_ps1=$ps1f [[ $rps1f ]] && prompt_rps1=$rps1f ble/textarea#invalidate fi fi if [[ :$prompt_opts: == *:leave-rewrite:* || $_ble_prompt_hash != "$version" ]]; then _ble_prompt_hash=$version ((_ble_prompt_version++)) fi ble/history/update-position local prompt_hashref_base='$_ble_prompt_version' local prompt_rows=${LINES:-25} local prompt_cols=${COLUMNS:-80} local "${_ble_prompt_cache_vars[@]/%/=}" # WA #D1570 checked local ble_prompt_unit_processing=1 "${_ble_util_set_declare[@]//NAME/ble_prompt_unit_mark}" # disable=#D1570 local prompt_unit= ble/prompt/unit#update _ble_prompt_ps1 && dirty=1 if [[ _ble_textarea_panel -ne 0 || $ble_attach_first_prompt || $MC_SID == $$ ]]; then [[ $dirty ]] return "$?" fi if [[ :$opts: == *:leave:* && ! $rps1f && $bleopt_prompt_rps1_transient ]]; then [[ ${_ble_prompt_rps1_data[10]} ]] && dirty=1 _ble_prompt_rps1_enabled=erase else [[ $prompt_rps1 || ${_ble_prompt_rps1_data[10]} ]] && ble/prompt/unit#update _ble_prompt_rps1 && dirty=1 [[ ${_ble_prompt_rps1_data[10]} ]] && _ble_prompt_rps1_enabled=1 fi case ${_ble_term_TERM:-$TERM:-} in (sun*|minix*|eterm*) ;; # black list (*) [[ $bleopt_prompt_xterm_title || ${_ble_prompt_xterm_title_data[10]} ]] && ble/prompt/unit#update _ble_prompt_xterm_title && dirty=1 ;; esac case ${_ble_term_TERM:-$TERM:-} in (screen:*|tmux:*|contra:*|screen.*|screen-*) [[ $bleopt_prompt_screen_title || ${_ble_prompt_screen_title_data[10]} ]] && ble/prompt/unit#update _ble_prompt_screen_title && dirty=1 ;; esac if [[ $_ble_term_tsl && $_ble_term_fsl ]]; then [[ $bleopt_prompt_term_status || ${_ble_prompt_term_status_data[10]} ]] && ble/prompt/unit#update _ble_prompt_term_status && dirty=1 fi [[ $bleopt_prompt_status_line || ${_ble_prompt_status_data[10]} ]] && ble/prompt/unit#update _ble_prompt_status && dirty=1 [[ $dirty ]] && _ble_prompt_update_dirty=dirty [[ $dirty ]] } function ble/prompt/clear { _ble_prompt_hash= ble/textarea#invalidate } _ble_prompt_ruler=('' '' 0) function ble/prompt/print-ruler.draw { [[ $bleopt_prompt_ruler ]] || return 0 local command=$1 opts=$2 cols=$COLUMNS local rex_eval_prefix='(([!{]|time|if|then|elif|while|until|do|exec|eval|command|env|nice|nohup|xargs|sudo)[[:space:]]+)?' local rex_clear_command='(tput[[:space:]]+)?(clear|reset)' local rex=$'(^|[\n;&|(])[[:space:]]*'$rex_eval_prefix$rex_clear_command'([ \t\n;&|)]|$)' [[ $command =~ $rex ]] && return 0 if [[ :$opts: == *:keep-info:* ]]; then ble/canvas/panel#increase-height.draw "$_ble_textarea_panel" 1 ble/canvas/panel#goto.draw "$_ble_textarea_panel" 0 0 ((_ble_canvas_panel_height[_ble_textarea_panel]--)) fi if [[ $bleopt_prompt_ruler == empty-line ]]; then ble/canvas/put.draw $'\n' else if [[ $bleopt_prompt_ruler != "${_ble_prompt_ruler[0]}" ]]; then if [[ $bleopt_prompt_ruler ]]; then local ret= x=0 y=0 g=0 x1=0 x2=0 y1=0 y2=0 LINES=1 COLUMNS=$cols ble/canvas/trace "$bleopt_prompt_ruler" truncate:measure-bbox _ble_prompt_ruler=("$bleopt_prompt_ruler" "$ret" "$x2") if ((!_ble_prompt_ruler[2])); then _ble_prompt_ruler[1]=${_ble_prompt_ruler[1]}' ' ((_ble_prompt_ruler[2]++)) fi else _ble_prompt_ruler=('' '' 0) fi fi local w=${_ble_prompt_ruler[2]} local repeat=$((cols/w)) ble/string#repeat "${_ble_prompt_ruler[1]}" "$repeat" ble/canvas/put.draw "$ret" ble/string#repeat ' ' "$((cols-repeat*w))" ble/canvas/put.draw "$ret" ((_ble_term_xenl)) && ble/canvas/put.draw $'\n' fi } function ble/prompt/print-ruler.buff { local -a DRAW_BUFF=() ble/prompt/print-ruler.draw "$@" ble/canvas/bflush.draw } function ble/edit/info/.initialize-size { local ret ble/canvas/panel/layout/.get-available-height "$_ble_edit_info_panel" cols=${COLUMNS-80} lines=$ret } _ble_edit_info_panel=2 _ble_edit_info=(0 0 "") _ble_edit_info_invalidated= function ble/edit/info#panel::getHeight { (($1!=_ble_edit_info_panel)) && return 0 if ble/edit/is-command-layout || [[ ! ${_ble_edit_info[2]} ]]; then height=0:0 else height=1:$((_ble_edit_info[1]+1)) fi } function ble/edit/info#panel::invalidate { (($1!=_ble_edit_info_panel)) && return 0 _ble_edit_info_invalidated=1 } function ble/edit/info#panel::render { (($1!=_ble_edit_info_panel)) && return 0 ble/edit/is-command-layout && return 0 [[ $_ble_edit_info_invalidated ]] || return 0 local x=${_ble_edit_info[0]} y=${_ble_edit_info[1]} content=${_ble_edit_info[2]} local -a DRAW_BUFF=() if [[ ! $content ]]; then ble/canvas/panel#set-height.draw "$_ble_edit_info_panel" 0 else ble/canvas/panel/reallocate-height.draw if ((y<_ble_canvas_panel_height[$1])); then ble/canvas/panel#clear.draw "$_ble_edit_info_panel" ble/canvas/panel#goto.draw "$_ble_edit_info_panel" ble/canvas/put.draw "$content" ((_ble_canvas_y+=y,_ble_canvas_x=x)) else _ble_edit_info=(0 0 "") ble/canvas/panel#set-height.draw "$_ble_edit_info_panel" 0 fi fi ble/canvas/bflush.draw _ble_edit_info_invalidated= } function ble/edit/info#collapse { local panel=${1-$_ble_prompt_info_panel} ((panel!=_ble_edit_info_panel)) && return 0 local -a DRAW_BUFF=() ble/canvas/panel#set-height.draw "$panel" 0 ble/canvas/bflush.draw _ble_edit_info_invalidated=1 } function ble/edit/info/.construct-content { local cols lines ble/edit/info/.initialize-size x=0 y=0 content= local type=$1 text=$2 case $1 in (clear) ;; (ansi|esc) local trace_opts=truncate [[ $bleopt_info_display == bottom ]] && trace_opts=$trace_opts:noscrc [[ $1 == esc ]] && trace_opts=$trace_opts:terminfo local ret= g=0 LINES=$lines ble/canvas/trace "$text" "$trace_opts" content=$ret ;; (text) local ret ble/canvas/trace-text "$text" content=$ret ;; (store) x=$2 y=$3 content=$4 ((y&2 ;; esac } function ble/edit/info/.render-content { local x=$1 y=$2 content=$3 opts=$4 if [[ $content != "${_ble_edit_info[2]}" ]]; then _ble_edit_info=("$x" "$y" "$content") _ble_edit_info_invalidated=1 fi [[ :$opts: == *:defer:* ]] && return 0 [[ $_ble_app_render_mode == panel ]] || return 0 ble/edit/info#panel::render "$_ble_edit_info_panel" } _ble_edit_info_default=(0 0 "") _ble_edit_info_scene=default function ble/edit/info/show { local type=$1 text=$2 if [[ $text ]]; then local x y content= ble/edit/info/.construct-content "$@" ble/edit/info/.render-content "$x" "$y" "$content" ble/util/buffer.flush _ble_edit_info_scene=show else ble/edit/info/default fi } function ble/edit/info/set-default { local type=$1 text=$2 local x y content ble/edit/info/.construct-content "$type" "$text" _ble_edit_info_default=("$x" "$y" "$content") [[ $_ble_edit_info_scene == default ]] && ble/edit/info/.render-content "${_ble_edit_info_default[@]}" defer } function ble/edit/info/default { _ble_edit_info_scene=default if (($#)); then ble/edit/info/set-default "$@" else ble/edit/info/.render-content "${_ble_edit_info_default[@]}" defer fi return 0 } function ble/edit/info/clear { [[ ${_ble_edit_info[2]} ]] || return 1 [[ $_ble_app_render_mode == panel ]] || return 0 _ble_edit_info_scene=clear ble/edit/info/.render-content 0 0 "" } function ble/edit/info/immediate-show { local ret; ble/canvas/panel/save-position ble/edit/info/show "$@" ble/canvas/panel/load-position "$ret" ble/util/buffer.flush } function ble/edit/info/immediate-default { local ret; ble/canvas/panel/save-position ble/edit/info/default ble/edit/info/.render-content "${_ble_edit_info_default[@]}" ble/canvas/panel/load-position "$ret" ble/util/buffer.flush } _ble_edit_VARNAMES=( _ble_edit_str _ble_edit_ind _ble_edit_mark _ble_edit_mark_active _ble_edit_overwrite_mode _ble_edit_line_disabled _ble_edit_arg _ble_edit_dirty_draw_beg _ble_edit_dirty_draw_end _ble_edit_dirty_draw_end0 _ble_edit_dirty_syntax_beg _ble_edit_dirty_syntax_end _ble_edit_dirty_syntax_end0 _ble_edit_dirty_observer _ble_edit_kill_index _ble_edit_kill_ring _ble_edit_kill_type) _ble_edit_str= _ble_edit_ind=0 _ble_edit_mark=0 _ble_edit_mark_active= _ble_edit_overwrite_mode= _ble_edit_line_disabled= _ble_edit_arg= _ble_edit_kill_index=0 _ble_edit_kill_ring=() _ble_edit_kill_type=() function ble-edit/content/replace { local beg=$1 end=$2 local ins=$3 reason=${4:-edit} _ble_edit_str="${_ble_edit_str::beg}""$ins""${_ble_edit_str:end}" ble-edit/content/.update-dirty-range "$beg" "$((beg+${#ins}))" "$end" "$reason" ble/util/assert \ '((0<=_ble_edit_dirty_syntax_beg&&_ble_edit_dirty_syntax_end<=${#_ble_edit_str}))' \ "0 <= beg=$_ble_edit_dirty_syntax_beg <= end=$_ble_edit_dirty_syntax_end <= len=${#_ble_edit_str}; beg=$beg, end=$end, ins(${#ins})=$ins" || { _ble_edit_dirty_syntax_beg=0 _ble_edit_dirty_syntax_end=${#_ble_edit_str} _ble_edit_dirty_syntax_end0=0 local olen=$((${#_ble_edit_str}-${#ins}+end-beg)) ((olen<0&&(olen=0), _ble_edit_ind>olen&&(_ble_edit_ind=olen), _ble_edit_mark>olen&&(_ble_edit_mark=olen))) } } function ble-edit/content/reset { local str=$1 reason=${2:-edit} local beg=0 end=${#str} end0=${#_ble_edit_str} _ble_edit_str=$str ble-edit/content/.update-dirty-range "$beg" "$end" "$end0" "$reason" ble/util/assert \ '((0<=_ble_edit_dirty_syntax_beg&&_ble_edit_dirty_syntax_end<=${#_ble_edit_str}))' \ "0 <= beg=$_ble_edit_dirty_syntax_beg <= end=$_ble_edit_dirty_syntax_end <= len=${#_ble_edit_str}; str(${#str})=$str" || { _ble_edit_dirty_syntax_beg=0 _ble_edit_dirty_syntax_end=${#_ble_edit_str} _ble_edit_dirty_syntax_end0=0 } } function ble-edit/content/reset-and-check-dirty { local str=$1 reason=${2:-edit} [[ $_ble_edit_str == "$str" ]] && return 0 local ret pref suff ble/string#common-prefix "$_ble_edit_str" "$str"; pref=$ret local dmin=${#pref} ble/string#common-suffix "${_ble_edit_str:dmin}" "${str:dmin}"; suff=$ret local dmax0=$((${#_ble_edit_str}-${#suff})) dmax=$((${#str}-${#suff})) _ble_edit_str=$str ble-edit/content/.update-dirty-range "$dmin" "$dmax" "$dmax0" "$reason" } function ble-edit/content/replace-limited { insert=$3 if [[ $bleopt_line_limit_type == discard ]]; then local ibeg=$1 iend=$2 opts=:$4: local limit=$((bleopt_line_limit_length)) if ((limit)); then local inslimit=$((limit-${#_ble_edit_str}+(iend-ibeg))) ((inslimitinslimit)) && insert=${insert::inslimit} if [[ ! $insert ]] && ((ibeg==iend)); then [[ $opts == *:nobell:* ]] || ble/widget/.bell "ble: reached line_limit_length=$limit" return 1 fi fi fi ble-edit/content/replace "$1" "$2" "$insert" } function ble-edit/content/check-limit { local opts=:${1:-truncate:editor}: if [[ $opts == *:${bleopt_line_limit_type:-none}:* ]]; then local limit=$((bleopt_line_limit_length)) if ((limit>0&&${#_ble_edit_str}>limit)); then local ble_edit_line_limit=$limit ble-decode-key "$_ble_decode_KCODE_LINE_LIMIT" fi fi } function ble/widget/__line_limit__ { local editor=ble/widget/${1:-edit-and-execute-command.impl} local limit=$ble_edit_line_limit case ${bleopt_line_limit_type:-none} in (editor) local content=$_ble_edit_str ble-edit/content/reset "# reached line_limit_length=$limit" _ble_edit_ind=0 _ble_edit_mark=0 "$editor" "$content" (($?==127)) && ble-edit/content/reset "${content::limit}" return 1 ;; (truncate|*) ble-edit/content/replace "$limit" "${#_ble_edit_str}" '' ((_ble_edit_ind>limit&&(_ble_edit_ind=limit))) ((_ble_edit_mark>limit&&(_ble_edit_mark=limit))) return 1 ;; esac return 0 } _ble_edit_dirty_draw_beg=-1 _ble_edit_dirty_draw_end=-1 _ble_edit_dirty_draw_end0=-1 _ble_edit_dirty_syntax_beg=0 _ble_edit_dirty_syntax_end=0 _ble_edit_dirty_syntax_end0=1 _ble_edit_dirty_observer=() function ble-edit/content/.update-dirty-range { ble/dirty-range#update --prefix=_ble_edit_dirty_draw_ "${@:1:3}" ble/dirty-range#update --prefix=_ble_edit_dirty_syntax_ "${@:1:3}" ble/textmap#update-dirty-range "${@:1:3}" local obs for obs in "${_ble_edit_dirty_observer[@]}"; do "$obs" "$@"; done } function ble-edit/content/update-syntax { if ble/util/import/is-loaded "$_ble_base/lib/core-syntax.sh"; then local beg end end0 ble/dirty-range#load --prefix=_ble_edit_dirty_syntax_ if ((beg>=0)); then ble/dirty-range#clear --prefix=_ble_edit_dirty_syntax_ ble/syntax/parse "$_ble_edit_str" '' "$beg" "$end" "$end0" fi fi } function ble-edit/content/eolp { local pos=${1:-$_ble_edit_ind} ((pos==${#_ble_edit_str})) || [[ ${_ble_edit_str:pos:1} == $'\n' ]] } function ble-edit/content/bolp { local pos=${1:-$_ble_edit_ind} ((pos<=0)) || [[ ${_ble_edit_str:pos-1:1} == $'\n' ]] } function ble-edit/content/find-logical-eol { local index=${1:-$_ble_edit_ind} offset=${2:-0} if ((offset>0)); then local text=${_ble_edit_str:index} local rex=$'^([^\n]*\n){0,'$((offset-1))$'}([^\n]*\n)?[^\n]*' [[ $text =~ $rex ]] ((ret=index+${#BASH_REMATCH})) [[ ${BASH_REMATCH[2]} ]] elif ((offset<0)); then local text=${_ble_edit_str::index} local rex=$'(\n[^\n]*){0,'$((-offset-1))$'}(\n[^\n]*)?$' [[ $text =~ $rex ]] if [[ $BASH_REMATCH ]]; then ((ret=index-${#BASH_REMATCH})) [[ ${BASH_REMATCH[2]} ]] else ble-edit/content/find-logical-eol "$index" 0 return 1 fi else local text=${_ble_edit_str:index} text=${text%%$'\n'*} ((ret=index+${#text})) return 0 fi } function ble-edit/content/find-logical-bol { local index=${1:-$_ble_edit_ind} offset=${2:-0} if ((offset>0)); then local rex=$'^([^\n]*\n){0,'$((offset-1))$'}([^\n]*\n)?' [[ ${_ble_edit_str:index} =~ $rex ]] if [[ $BASH_REMATCH ]]; then ((ret=index+${#BASH_REMATCH})) [[ ${BASH_REMATCH[2]} ]] else ble-edit/content/find-logical-bol "$index" 0 return 1 fi elif ((offset<0)); then ble-edit/content/find-logical-eol "$index" "$offset"; local ext=$? ble-edit/content/find-logical-bol "$ret" 0 return "$ext" else local text=${_ble_edit_str::index} text=${text##*$'\n'} ((ret=index-${#text})) return 0 fi } function ble-edit/content/find-non-space { local bol=$1 local rex=$'^[ \t]*'; [[ ${_ble_edit_str:bol} =~ $rex ]] ret=$((bol+${#BASH_REMATCH})) } function ble-edit/content/is-single-line { [[ $_ble_edit_str != *$'\n'* ]] } function ble-edit/content/get-arg { local default_value=$1 local value=$_ble_edit_arg _ble_edit_arg= if [[ $value == +* ]]; then if [[ $value == + ]]; then arg=4 return 0 fi value=${value#+} fi if [[ $value == -* ]]; then if [[ $value == - ]]; then arg=-1 else arg=$((-10#0${value#-})) fi else if [[ $value ]]; then arg=$((10#0$value)) else arg=$default_value fi fi } function ble-edit/content/clear-arg { _ble_edit_arg= } function ble-edit/content/toggle-arg { if [[ $_ble_edit_arg == + ]]; then _ble_edit_arg= elif [[ $_ble_edit_arg && $_ble_edit_arg != +* ]]; then _ble_edit_arg=+$_ble_edit_arg else _ble_edit_arg=+ fi } function ble/keymap:generic/get-arg { if [[ $_ble_decode_keymap == vi_[noxs]map ]]; then local ARG FLAG REG ble/keymap:vi/get-arg "$1" arg=$ARG else ble-edit/content/get-arg "$1" fi } function ble/keymap:generic/clear-arg { if [[ $_ble_decode_keymap == vi_[noxs]map ]]; then ble/keymap:vi/clear-arg else ble-edit/content/clear-arg fi } function ble/widget/append-arg-or { ble/function#try ble/widget/complete/.select-menu-with-arg "${2-}" && return 0 local n=${#KEYS[@]}; ((n&&n--)) local code=$((KEYS[n]&_ble_decode_MaskChar)) ((code==0)) && return 1 local ret; ble/util/c2s "$code"; local ch=$ret if if [[ $_ble_edit_arg == + ]]; then [[ $ch == [-0-9] ]] && _ble_edit_arg= elif [[ $_ble_edit_arg == +* ]]; then false elif [[ $_ble_edit_arg ]]; then [[ $ch == [0-9] ]] else ((KEYS[n]&_ble_decode_MaskFlag)) fi then ble/decode/widget/skip-lastwidget _ble_edit_arg=$_ble_edit_arg$ch else ble/widget/"$1" fi } function ble/widget/append-arg { ble/widget/append-arg-or self-insert "$@" } function ble/widget/universal-arg { ble/decode/widget/skip-lastwidget ble-edit/content/toggle-arg } function ble-edit/content/prepend-kill-ring { _ble_edit_kill_index=0 local otext=${_ble_edit_kill_ring[0]-} ntext=$1 local otype=${_ble_edit_kill_type[0]-} ntype=$2 if [[ $otype == L || $ntype == L ]]; then ntext=${ntext%$'\n'}$'\n' otext=${otext%$'\n'}$'\n' _ble_edit_kill_ring[0]=$ntext$otext _ble_edit_kill_type[0]=L elif [[ $otype == B:* ]]; then if [[ $ntype != B:* ]]; then ntext=${ntext%$'\n'}$'\n' local ret; ble/string#count-char "$ntext" $'\n' ble/string#repeat '0 ' "$ret" ntype=B:${ret%' '} fi _ble_edit_kill_ring[0]=$ntext$otext _ble_edit_kill_type[0]="B:${ntype#B:} ${otype#B:}" else _ble_edit_kill_ring[0]=$ntext$otext _ble_edit_kill_type[0]=$otype fi } function ble-edit/content/append-kill-ring { _ble_edit_kill_index=0 local otext=${_ble_edit_kill_ring[0]-} ntext=$1 local otype=${_ble_edit_kill_type[0]-} ntype=$2 if [[ $otype == L || $ntype == L ]]; then ntext=${ntext%$'\n'}$'\n' otext=${otext%$'\n'}$'\n' _ble_edit_kill_ring[0]=$otext$ntext _ble_edit_kill_type[0]=L elif [[ $otype == B:* ]]; then if [[ $ntype != B:* ]]; then ntext=${ntext%$'\n'}$'\n' local ret; ble/string#count-char "$ntext" $'\n' ble/string#repeat '0 ' "$ret" ntype=B:${ret%' '} fi _ble_edit_kill_ring[0]=$otext$ntext _ble_edit_kill_type[0]="B:${otype#B:} ${ntype#B:}" else _ble_edit_kill_ring[0]=$otext$ntext _ble_edit_kill_type[0]=$otype fi } function ble-edit/content/push-kill-ring { if ((${#_ble_edit_kill_ring[@]})) && [[ ${LASTWIDGET#ble/widget/} == kill-* || ${LASTWIDGET#ble/widget/} == copy-* ]]; then local proc= local name; ble/string#split-words name "${WIDGET#ble/widget/}" if [[ $3 == backward || $name == kill-backward-* || $name == copy-backward-* ]]; then proc=ble-edit/content/prepend-kill-ring elif [[ $3 == forward || $name == kill-forward-* || $name == copy-forward-* ]]; then proc=ble-edit/content/append-kill-ring elif [[ $name == kill-region* || $name == copy-region* ]]; then proc= elif [[ $3 == [0-9]*:[0-9]* ]] && ((${3##*:}<=_ble_edit_ind)); then proc=ble-edit/content/prepend-kill-ring else proc=ble-edit/content/append-kill-ring fi if [[ $proc ]]; then "$proc" "$1" "$2" return "$?" fi fi _ble_edit_kill_index=0 ble/array#unshift _ble_edit_kill_ring "$1" ble/array#unshift _ble_edit_kill_type "$2" } _ble_edit_PS1_adjusted= _ble_edit_PS1='\s-\v\$ ' _ble_edit_PROMPT_COMMAND= function ble-edit/adjust-PS1 { [[ $_ble_edit_PS1_adjusted ]] && return 0 _ble_edit_PS1_adjusted=1 _ble_edit_PS1=$PS1 if [[ $bleopt_internal_suppress_bash_output ]]; then PS1='[ble: press RET to continue]' else PS1= fi if ble/is-array PROMPT_COMMAND; then ble/idict#copy _ble_edit_PROMPT_COMMAND PROMPT_COMMAND else ble/variable#copy-state PROMPT_COMMAND _ble_edit_PROMPT_COMMAND fi builtin unset -v PROMPT_COMMAND } function ble-edit/restore-PS1 { [[ $_ble_edit_PS1_adjusted ]] || return 1 _ble_edit_PS1_adjusted= PS1=$_ble_edit_PS1 if ble/is-array _ble_edit_PROMPT_COMMAND; then ble/idict#copy PROMPT_COMMAND _ble_edit_PROMPT_COMMAND else ble/variable#copy-state _ble_edit_PROMPT_COMMAND PROMPT_COMMAND fi } _ble_edit_IGNOREEOF_adjusted= _ble_edit_IGNOREEOF= function ble-edit/adjust-IGNOREEOF { [[ $_ble_edit_IGNOREEOF_adjusted ]] && return 0 _ble_edit_IGNOREEOF_adjusted=1 if [[ ${IGNOREEOF+set} ]]; then _ble_edit_IGNOREEOF=$IGNOREEOF else builtin unset -v _ble_edit_IGNOREEOF fi if ((_ble_bash>=40000)); then builtin unset -v IGNOREEOF else IGNOREEOF=9999 fi } function ble-edit/restore-IGNOREEOF { [[ $_ble_edit_IGNOREEOF_adjusted ]] || return 1 _ble_edit_IGNOREEOF_adjusted= if [[ ${_ble_edit_IGNOREEOF+set} ]]; then IGNOREEOF=$_ble_edit_IGNOREEOF else builtin unset -v IGNOREEOF fi } _ble_edit_READLINE=() function ble-edit/adjust-READLINE { [[ $_ble_edit_READLINE ]] && return 0 _ble_edit_READLINE=1 ble/variable#copy-state READLINE_LINE '_ble_edit_READLINE[1]' ble/variable#copy-state READLINE_POINT '_ble_edit_READLINE[2]' ble/variable#copy-state READLINE_MARK '_ble_edit_READLINE[3]' } function ble-edit/restore-READLINE { [[ $_ble_edit_READLINE ]] || return 0 _ble_edit_READLINE= ble/variable#copy-state '_ble_edit_READLINE[1]' READLINE_LINE ble/variable#copy-state '_ble_edit_READLINE[2]' READLINE_POINT ble/variable#copy-state '_ble_edit_READLINE[3]' READLINE_MARK } function ble-edit/eval-IGNOREEOF { local value= if [[ $_ble_edit_IGNOREEOF_adjusted ]]; then value=${_ble_edit_IGNOREEOF-0} else value=${IGNOREEOF-0} fi if [[ $value && ! ${value//[0-9]} ]]; then ret=$((10#0$value)) else ret=10 fi } bleopt/declare -n canvas_winch_action redraw-here function ble-edit/attach/TRAPWINCH { ((_ble_edit_attached)) && [[ $_ble_term_state == internal ]] && ! ble/edit/is-command-layout && ! ble/util/is-running-in-subshell || return 0 ble/application/onwinch 2>&"$_ble_util_fd_tui_stderr" } _ble_edit_attached=0 function ble-edit/attach/.attach { ((_ble_edit_attached)) && return 0 _ble_edit_attached=1 if [[ ! ${_ble_edit_LINENO+set} ]]; then _ble_edit_LINENO=${BASH_LINENO[${#BASH_LINENO[@]}-1]} ((_ble_edit_LINENO<0)) && _ble_edit_LINENO=0 ((_ble_edit_CMD<=_ble_edit_LINENO+1)) && ((_ble_edit_CMD=_ble_edit_LINENO+1)) fi ble/builtin/trap/install-hook WINCH readline blehook internal_WINCH!=ble-edit/attach/TRAPWINCH ble-edit/adjust-PS1 ble-edit/adjust-READLINE ble-edit/adjust-IGNOREEOF [[ $bleopt_internal_exec_type == exec ]] && _ble_edit_IFS=$IFS } function ble-edit/attach/.detach { ((!_ble_edit_attached)) && return 0 ble-edit/restore-PS1 ble-edit/restore-READLINE ble-edit/restore-IGNOREEOF [[ $bleopt_internal_exec_type == exec ]] && IFS=$_ble_edit_IFS _ble_edit_attached=0 } _ble_textarea_VARNAMES=( _ble_textarea_buffer _ble_textarea_bufferName _ble_textarea_cur _ble_textarea_panel _ble_textarea_scroll _ble_textarea_scroll_new _ble_textarea_gendx _ble_textarea_gendy _ble_textarea_invalidated _ble_textarea_version _ble_textarea_caret_state _ble_textarea_cache _ble_textarea_render_defer) _ble_textarea_local_VARNAMES=() function ble/textarea#panel::getHeight { if [[ $1 == "$_ble_textarea_panel" ]]; then local min=$((_ble_prompt_ps1_data[4]+1)) max=$((_ble_textmap_endy+1)) ((min=_ble_app_winsize[0])) && return 1 local height=${_ble_canvas_panel_height[ipanel]} local proy=${_ble_prompt_ps1_data[4]} local newline= reflow= offset= if ((y<=proy)); then ((newline=y,reflow=0,offset=x)) elif ((y=6&&rnline>rheight+2?2:1)) local smin smax ((smin=rcy-rheight+margin, smin>nline-height&&(smin=nline-height), smax=rcy-margin, smax<0&&(smax=0))) if ((scroll>smax)); then scroll=$smax elif ((scrollwmax&&(umax=wmax))) else scroll= if ! ble/util/assert '((height==nline))'; then ble/canvas/panel#set-height.draw "$_ble_textarea_panel" "$nline" height=$nline fi fi } function ble/textarea#render/.perform-scroll { local new_scroll=$1 if ((new_scroll!=_ble_textarea_scroll)); then local scry=$((begy+1)) local scrh=$((height-scry)) local fmin fmax index if ((_ble_textarea_scroll>new_scroll)); then local shift=$((_ble_textarea_scroll-new_scroll)) local draw_shift=$((shift=0)); then dirty=1 elif [[ $_ble_textarea_invalidated ]]; then dirty=1 elif [[ $_ble_textarea_caret_state != "$caret_state" ]]; then dirty=1 elif [[ $_ble_textarea_scroll != "$_ble_textarea_scroll_new" ]]; then dirty=1 elif [[ :$opts: == *:leave:* || :$opts: == *:update:* ]]; then dirty=1 fi if [[ ! $dirty ]]; then ble/textarea#focus return 0 fi local cols=${COLUMNS-80} local subprompt_enabled= ((_ble_textarea_panel==0)) && subprompt_enabled=1 local rps1_enabled=$_ble_prompt_rps1_enabled local rps1_width=${_ble_prompt_rps1_data[11]} if [[ $rps1_enabled ]]; then ((cols-=rps1_width+1,_ble_term_xenl||cols--)) if [[ $rps1_enabled == erase ]]; then ble/textarea#render/.erase-rprompt rps1_enabled= fi fi local text=$_ble_edit_str index=$_ble_edit_ind local iN=${#text} ((index<0?(index=0):(index>iN&&(index=iN)))) local umin=-1 umax=-1 local x=${_ble_prompt_ps1_data[3]} local y=${_ble_prompt_ps1_data[4]} local render_opts= [[ $rps1_enabled ]] && render_opts=relative COLUMNS=$cols ble/textmap#update "$text" "$render_opts" # [ref] x y ble/urange#update "$_ble_textmap_umin" "$_ble_textmap_umax" # [ref] umin umax ble/urange#clear --prefix=_ble_textmap_ if [[ :$opts: == *:leave:* ]]; then local _ble_complete_menu_active= # suppress layer:menu_filter local _ble_edit_mark_active= # suppress layer:region local _ble_edit_overwrite_mode= # suppress layer:overwrite_mode fi local DMIN=$_ble_edit_dirty_draw_beg ble-edit/content/update-syntax ble/textarea#update-text-buffer # [in] text index [ref] lc lg; local lc=32 lg=0 [[ $bleopt_internal_suppress_bash_output ]] || ble/textarea#update-left-char "$index" local -a DRAW_BUFF=() local begx=$_ble_textmap_begx begy=$_ble_textmap_begy local endx=$_ble_textmap_endx endy=$_ble_textmap_endy local cx cy ble/textmap#getxy.cur --prefix=c "$index" # → cx cy local cols=$_ble_textmap_cols local height=${_ble_canvas_panel_height[_ble_textarea_panel]} local scroll=${_ble_textarea_scroll_new:-$_ble_textarea_scroll} ble/textarea#render/.determine-scroll # update: height scroll umin umax local gend gendx gendy if [[ $scroll ]]; then ble/textmap#get-index-at "$cols" "$((height+scroll-1))"; gend=$index ble/textmap#getxy.out --prefix=gend "$gend" ((gendy-=scroll)) else gend=$iN gendx=$endx gendy=$endy fi _ble_textarea_gendx=$gendx _ble_textarea_gendy=$gendy local ret esc_line= esc_line_set= if [[ ! $_ble_textarea_invalidated ]]; then [[ ! $rps1_enabled && $_ble_prompt_rps1_shown || $rps1_enabled && $_ble_prompt_rps1_dirty ]] && ble/textarea#render/.cleanup-trailing-spaces-after-newline ble/textarea#render/.perform-scroll "$scroll" # update: umin umax _ble_textarea_scroll_new=$_ble_textarea_scroll [[ $rps1_enabled ]] && ble/textarea#render/.show-rprompt ble/textarea#render/.show-prompt if [[ $subprompt_enabled ]]; then ble/textarea#render/.show-control-string _ble_prompt_xterm_title ble/textarea#render/.show-control-string _ble_prompt_screen_title ble/textarea#render/.show-control-string _ble_prompt_term_status fi if ((umin=0)); then local endY=$((endy-_ble_textarea_scroll)) if ((endY0)) && ble/canvas/put-cub.draw "$ret" ble/util/c2bc "$lc" READLINE_POINT=$ret fi ble/color/g2sgr "$lg" ble/canvas/put.draw "$ret" fi } function ble/textarea#save-state { local prefix=$1 local -a vars=() ble/array#push vars _ble_edit_PS1 _ble_prompt_ps1_data ble/array#push vars "${_ble_edit_VARNAMES[@]}" ble/array#push vars "${_ble_textmap_VARNAMES[@]}" ble/array#push vars _ble_highlight_layer_list local layer names for layer in "${_ble_highlight_layer_list[@]}"; do local _ble_local_script=' if [[ ${_ble_highlight_layer_LAYER_VARNAMES[@]-} ]]; then ble/array#push vars "${_ble_highlight_layer_LAYER_VARNAMES[@]}" else ble/array#push vars "${!_ble_highlight_layer_LAYER_@}" fi' builtin eval -- "${_ble_local_script//LAYER/$layer}" done ble/array#push vars "${_ble_textarea_VARNAMES[@]}" ble/array#push vars "${_ble_syntax_VARNAMES[@]}" ble/array#push vars "${_ble_textarea_local_VARNAMES[@]}" builtin eval -- "${prefix}_VARNAMES=(\"\${vars[@]}\")" ble/util/save-vars "$prefix" "${vars[@]}" } function ble/textarea#restore-state { local prefix=$1 if builtin eval "[[ \$prefix && \${${prefix}_VARNAMES+set} ]]"; then builtin eval "ble/util/restore-vars $prefix \"\${${prefix}_VARNAMES[@]}\"" else ble/util/print "ble/textarea#restore-state: unknown prefix '$prefix'." >&2 return 1 fi } function ble/textarea#clear-state { local prefix=$1 if [[ $prefix ]]; then local vars=${prefix}_VARNAMES builtin eval "builtin unset -v \"\${$vars[@]/#/$prefix}\" $vars" else ble/util/print "ble/textarea#restore-state: unknown prefix '$prefix'." >&2 return 1 fi } _ble_textarea_render_defer= function ble/textarea#render-defer.idle { ble/util/idle.wait-user-input [[ $_ble_textarea_render_defer ]] || return 0 local ble_textarea_render_defer_running=1 ble/util/buffer.flush _ble_textarea_render_defer= blehook/invoke textarea_render_defer ble/textarea#render update [[ $_ble_textarea_render_defer ]] && ble/util/idle.continue return 0 } ble/function#try ble/util/idle.push-background ble/textarea#render-defer.idle function ble/widget/.update-textmap { local cols=${COLUMNS:-80} render_opts= if [[ $_ble_prompt_rps1_enabled ]]; then local rps1_width=${_ble_prompt_rps1_data[11]} render_opts=relative ((cols-=rps1_width+1,_ble_term_xenl||cols--)) fi local x=$_ble_textmap_begx y=$_ble_textmap_begy COLUMNS=$cols ble/textmap#update "$_ble_edit_str" "$render_opts" } function ble/widget/do-lowercase-version { local n=${#KEYS[@]}; ((n&&n--)) local flag=$((KEYS[n]&_ble_decode_MaskFlag)) local char=$((KEYS[n]&_ble_decode_MaskChar)) if ((65<=char&&char<=90)); then ble/decode/widget/redispatch-by-keys "$((flag|char+32))" "${KEYS[@]:1}" else return 125 fi } function ble/widget/redraw-line { ble-edit/content/clear-arg ble/textarea#invalidate } function ble/widget/clear-screen { ble-edit/content/clear-arg ble/edit/enter-command-layout # #D1800 pair=leave-command-layout _ble_prompt_trim_opwd= ble/textarea#invalidate local -a DRAW_BUFF=() ble/canvas/panel/goto-top-dock.draw ble/canvas/bflush.draw ble/util/buffer "$_ble_term_clear" _ble_canvas_x=0 _ble_canvas_y=0 ble/term/visible-bell/cancel-erasure ble/edit/leave-command-layout # #D1800 pair=enter-command-layout } function ble/widget/clear-display { ble/util/buffer $'\e[3J' ble/widget/clear-screen } function ble/edit/display-version/git-rev-parse { ret= local git_base opts=$2 case $1 in (.) git_base=$PWD ;; (./*) git_base=$PWD/${1#./} ;; (..|../*) git_base=$PWD/$1 ;; (*) git_base=$1 ;; esac "${_ble_util_set_declare[@]//NAME/visited}" # WA #D1570 checked until [[ -s $git_base/HEAD || -s $git_base/.git/HEAD ]]; do ble/set#contains visited "$git_base" && return 1 ble/set#add visited "$git_base" if [[ -f $git_base/.git ]]; then local content ble/util/mapfile content < "$git_base/.git" if ble/string#match "$content" '^gitdir: (.*)'; then git_base=$git_base/${BASH_REMATCH[1]} continue fi fi if [[ :$opts: == *:parent:* && $git_base == */* ]]; then git_base=${git_base%/*} continue fi break done [[ -s $git_base/HEAD ]] || git_base=$git_base/.git local head=$git_base/HEAD if [[ -f $head ]]; then local content ble/util/mapfile content < "$head" if ble/string#match "$content" '^ref: (.*)$'; then head=$git_base/${BASH_REMATCH[1]} ble/util/mapfile content < "$head" fi if ble/string#match "$content" '^[a-f0-9]+$'; then content=${content::8} fi ret=$content [[ $ret ]] return "$?" fi return 1 } function ble/edit/display-version/git-hash-object { local file=$1 size if ! ble/util/assign size 'ble/bin/wc -c "$file" 2>/dev/null'; then ret='error' return 1 fi ble/string#split-words size "$size" if ble/bin#has git; then ble/util/assign ret 'git hash-object "$file"' ret="hash:$ret, $size bytes" elif ble/bin#has sha1sum; then local _ble_local_tmpfile; ble/util/assign/mktmp { printf 'blob %d\0' "$size"; ble/bin/cat "$file"; } >| "$_ble_local_tmpfile" blob_data=$_ble_local_tmpfile ble/util/assign ret 'sha1sum "$blob_data"' ble/util/assign/rmtmp ble/string#split-words ret "$ret" ret="sha1:$ret, $size bytes" elif ble/bin#has cksum; then ble/util/assign-words ret 'cksum "$file"' ble/util/sprintf ret 'cksum:%08x, %d bytes' "$ret" "$size" else ret=size:$size fi } function ble/edit/display-version/add-line { lines[iline++]=$1 } function ble/edit/display-version/check:bash-completion { [[ ${BASH_COMPLETION_VERSINFO[0]-} ]] || return 1 local patch=${BASH_COMPLETION_VERSINFO[2]-} local version=${BASH_COMPLETION_VERSINFO[0]}.${BASH_COMPLETION_VERSINFO[1]:-y}${patch:+.$patch} local source lineno ret if ble/function#get-source-and-lineno _init_completion; then if ble/edit/display-version/git-rev-parse "${source%/*}"; then version=$sgrV$version+$ret$sgr0 elif ble/edit/display-version/git-hash-object "$source"; then version="$sgrV$version$sgr0 ($ret)" fi fi ble/edit/display-version/add-line "${sgrF}bash-completion$sgr0, version $version$label_noarch" } function ble/edit/display-version/check:bash-preexec { local source lineno ret ble/function#get-source-and-lineno __bp_preexec_invoke_exec || return 1 local version="${source/#$HOME/~}$label_noarch" if ble/edit/display-version/git-rev-parse "${source%/*}"; then version="version $sgrV+$ret$sgr0$label_noarch" elif ble/edit/display-version/git-hash-object "$source"; then version="($ret)$label_noarch" fi local file=${source##*/} if [[ $file == bash-preexec.sh || $file == bash-preexec.bash ]]; then file= else file=" ($file)" fi local integ= ble/util/import/is-loaded contrib/bash-preexec && integ=$label_integration ble/edit/display-version/add-line "${sgrF}bash-preexec$sgr0$file, $version$integ" } function ble/edit/display-version/check:fzf { local source lineno ret if ble/function#get-source-and-lineno __fzf_select__; then local version="${source/#$HOME/~}$label_noarch" if ble/edit/display-version/git-rev-parse "${source%/*}" parent; then version="version $sgrV+$ret$sgr0$label_noarch" elif ble/edit/display-version/git-hash-object "$source"; then version="($ret)$label_noarch" fi local integ= ble/util/import/is-loaded integration/fzf-key-bindings && integ=$label_integration ble/edit/display-version/add-line "${sgrC}fzf$sgr0 ${sgrF}key-bindings$sgr0, $version$integ" [[ $integ ]] || ble/edit/display-version/add-line "$label_warning: fzf integration \"integration/fzf-key-bindings\" is not activated." fi if ble/function#get-source-and-lineno __fzf_orig_completion; then local version="${source/#$HOME/~}$label_noarch" if ble/edit/display-version/git-rev-parse "${source%/*}" parent; then version="version $sgrV+$ret$sgr0$label_noarch" elif ble/edit/display-version/git-hash-object "$source"; then version="($ret)$label_noarch" fi local integ= ble/util/import/is-loaded integration/fzf-completion && integ=$label_integration ble/edit/display-version/add-line "${sgrC}fzf$sgr0 ${sgrF}completion$sgr0, $version$integ" [[ $integ ]] || ble/edit/display-version/add-line "$label_warning: fzf integration \"integration/fzf-completion\" is not activated." fi } function ble/edit/display-version/check:starship { local source lineno ble/function#get-source-and-lineno starship_precmd || return 1 local starship sed_script='s/^[[:space:]]*PS1="\$(\(.\{1,\}\) prompt .*)";\{0,1\}$/\1/p' ble/util/assign-array starship 'declare -f starship_precmd | ble/bin/sed -n "$sed_script"' if ! ble/bin#has "$starship"; then { builtin eval -- "starship=$starship" && ble/bin#has "$starship"; } || { starship=starship; ble/bin#has "$starship"; } || return 1 fi local awk_script=' sub(/^starship /, "") { version = $0; next; } sub(/^branch:/, "") { gsub(/['"$_ble_term_space"']/, "_"); if ($0 != "") version = version "-" $0; next; } sub(/^commit_hash:/, "") { gsub(/['"$_ble_term_space"']/, "_"); if ($0 != "") version = version "+" $0; next; } sub(/^build_time:/, "") { build_time = $0; } sub(/^build_env:/, "") { build_env = $0; } END { if (version != "") { print version; print build_env, build_time } } ' local version= ble/util/assign-array version '"$starship" --version | ble/bin/awk "$awk_script"' [[ $version ]] || return 1 local ret; ble/string#trim "${version[1]}"; local build=$ret ble/edit/display-version/add-line "${sgrF}starship${sgr0}, version $sgrV$version$sgr0${build:+ ($build)}" } function ble/edit/display-version/check:bash-it { [[ ${BASH_IT-} ]] && ble/is-function bash-it || return 1 local version= ret if ble/edit/display-version/git-rev-parse "$BASH_IT"; then version="version $sgrV+$ret$sgr0$label_noarch" elif ble/edit/display-version/git-hash-object "$BASH_IT/bash_it.sh"; then version="($ret)$label_noarch" else version="(bash-it version)" fi local modules= if ble/is-function _bash-it-component-item-is-enabled; then local category subdir suffix for category in aliases:alias completion plugins:plugin; do local subdir=${category%:*} suffix=${category#*:} list list=() local file name for file in "$BASH_IT/$subdir/available"/*.*.bash; do name=${file##*/} name=${name%."$suffix"*.bash} _bash-it-component-item-is-enabled "$suffix" "$name" && ble/array#push list "$name" done modules="$modules, $suffix(${list[*]})" done fi ble/edit/display-version/add-line "${sgrF}bash-it$sgr0${theme:+ ($theme)}, $version$modules" } function ble/edit/display-version/check:oh-my-bash { local source lineno ret version= if [[ ${OMB_VERSINFO-set} ]] && ble/function#get-source-and-lineno _omb_module_require; then version=${OMB_VERSINFO[0]}.${OMB_VERSINFO[1]}.${OMB_VERSINFO[2]} if ble/edit/display-version/git-rev-parse "${source%/*}"; then version="version $sgrV$version+$ret$sgr0$label_noarch" elif ble/edit/display-version/git-hash-object "$source"; then version="version $sgrV$version$sgr0 ($ret)$label_noarch" else version="version $sgrV$version$sgr0$label_noarch" fi elif [[ ${OSH_CUSTOM-set} ]] && ble/function#get-source-and-lineno is_plugin; then version="${source/#$HOME/~}$label_noarch" if ble/edit/display-version/git-rev-parse "${source%/*}" parent; then version="version $sgrV+$ret$sgr0$label_noarch" elif ble/edit/display-version/git-hash-object "$source"; then version="($ret)$label_noarch" fi fi if [[ $version ]]; then local theme=${OMB_THEME-${OSH_THEME-}} local modules="aliases(${aliases[*]}), completions(${completions[*]}), plugins(${plugins[*]})" ble/edit/display-version/add-line "${sgrF}oh-my-bash$sgr0${theme:+ ($theme)}, $version, $modules" fi } function ble/edit/display-version/check:sbp { local source lineno ret ble/function#get-source-and-lineno _sbp_set_prompt || return 1 local version="${source/#$HOME/~}$label_noarch" if ble/edit/display-version/git-rev-parse "${source%/*}"; then version="version $sgrV+$ret$sgr0$label_noarch" elif ble/edit/display-version/git-hash-object "$source"; then version="($ret)$label_noarch" fi local hooks="hooks(${settings_hooks[*]-${SBP_HOOKS[*]}})" local left="left(${settings_segments_left[*]-${SBP_SEGMENTS_LEFT[*]}})" local right="right(${settings_segments_right[*]-${RBP_SEGMENTS_RIGHT[*]}})" local modules="$hooks, $left, $right" ble/edit/display-version/add-line "${sgrF}sbp$sgr0, $version, $modules" } function ble/edit/display-version/check:gitstatus { local source lineno ret ble/function#get-source-and-lineno gitstatus_query || return 1 local version="${source/#$HOME/~}$label_noarch" if ble/edit/display-version/git-rev-parse "${source%/*}"; then version="version $sgrV+$ret$sgr0$label_noarch" elif ble/edit/display-version/git-hash-object "$source"; then version="($ret)$label_noarch" fi ble/edit/display-version/add-line "${sgrF}romkatv/gitstatus$sgr0, $version" } function ble/edit/display-version/check:zoxide { ble/is-function __zoxide_hook || return 1 local path= ble/bin#get-path zoxide || return 1 local version= ble/util/assign-array version '\command zoxide --version' [[ $version ]] || return 1 version=${version#zoxide } version=${version#v} local integ= ble/util/import/is-loaded contrib/integration/zoxide && integ=$label_integration ble/edit/display-version/add-line "${sgrF}zoxide${sgr0}, version $sgrV$version$sgr0 ($path)$integ" } function ble/edit/display-version/check:atuin { ble/is-function _atuin_precmd || ble/is-function __atuin_precmd || return 1 local path= ble/bin#get-path atuin || return 1 local version= ble/util/assign-array version '\command atuin --version' [[ $version ]] || return 1 version=${version#atuin } version=${version#v} ble/edit/display-version/add-line "${sgrF}atuin${sgr0}, version $sgrV$version$sgr0 ($path)" } function ble/widget/display-shell-version { ble-edit/content/clear-arg local set shopt [[ $_ble_bash_options_adjusted ]] || ble/base/.adjust-bash-options set shopt local sgrC= sgrF= sgrV= sgrA= sgr2= sgr3= sgr0= bold= if [[ -t 1 ]]; then bold=$_ble_term_bold sgr0=$_ble_term_sgr0 ble/color/face2sgr command_file; sgrC=$ret ble/color/face2sgr command_function; sgrF=$ret ble/color/face2sgr syntax_expr; sgrV=$ret ble/color/face2sgr varname_readonly; sgrA=$ret ble/color/face2sgr syntax_varname; sgr2=$ret ble/color/face2sgr syntax_quoted; sgr3=$ret fi local label_noarch=" (${sgrA}noarch$sgr0)" local label_integration=" $_ble_term_bold(integration: on)$sgr0" local label_warning="${bold}WARNING$sgr0" local os_release= if [[ -s /etc/os-release ]]; then ble/util/assign os_release '( builtin unset -v PRETTY_NAME NAME VERSION source /etc/os-release ble/util/print "${PRETTY_NAME:-${NAME:+$NAME${VERSION:+ $VERSION}}}")' 2>/dev/null fi if [[ ! $os_release && -s /etc/release ]]; then local ret ble/util/mapfile ret < /etc/release ble/string#trim "$ret" os_release=$ret fi local lines="${sgrC}GNU bash$sgr0, version $sgrV$BASH_VERSION$sgr0 ($sgrA$MACHTYPE$sgr0)${os_release:+ [$os_release]}" iline=1 local ble_build_info="${_ble_base_build_git_version/#git version/git}, $_ble_base_build_make_version, $_ble_base_build_gawk_version" lines[iline++]="${sgrF}ble.sh$sgr0, version $sgrV$BLE_VERSION$sgr0$label_noarch [$ble_build_info]" ble/edit/display-version/check:bash-completion ble/edit/display-version/check:fzf ble/edit/display-version/check:bash-preexec ble/edit/display-version/check:starship ble/edit/display-version/check:bash-it ble/edit/display-version/check:oh-my-bash ble/edit/display-version/check:sbp ble/edit/display-version/check:gitstatus ble/edit/display-version/check:zoxide ble/edit/display-version/check:atuin local q=\' local ret='(unset)' local var line=${_ble_term_bold}locale$sgr0: for var in _ble_bash_LANG "${!_ble_bash_LC_@}" LANG "${!LC_@}"; do case $var in (LC_ALL|LC_COLLATE) continue ;; (LANG|LC_CTYPE|LC_MESSAGES|LC_NUMERIC|LC_TIME) [[ ${_ble_bash_LC_ALL-} ]] && continue ;; esac [[ ${!var+set} ]] || continue ble/string#quote-word "${!var}" quote-empty:sgrq="$sgr3":sgr0="$sgr0" line="$line $sgr2${var#_ble_bash_}$sgrV=$sgr0$ret" done lines[iline++]=$line ret='(unset)' [[ ${TERM+set} ]] && ble/string#quote-word "$TERM" quote-empty:sgrq="$sgr3":sgr0="$sgr0" local i line="${_ble_term_bold}terminal$sgr0: ${sgr2}TERM$sgrV=$sgr0$ret" line="$line ${sgr2}wcwidth$sgrV=$sgr0$bleopt_char_width_version-$bleopt_char_width_mode${bleopt_emoji_width:+/$bleopt_emoji_version-$bleopt_emoji_width+$bleopt_emoji_opts}" [[ ${MC_SID-} ]] && line="$line, ${sgrC}mc$sgr0 (${sgrV}MC_SID:$MC_SID$sgr0)" for i in "${!_ble_term_DA2R[@]}"; do line="$line, $sgrC${_ble_term_TERM[i]-unknown}$sgr0 ($sgrV${_ble_term_DA2R[i]}$sgr0)" done lines[iline++]=$line ble/widget/print "${lines[@]}" [[ $_ble_bash_options_adjusted ]] || ble/base/.restore-bash-options set shopt } function ble/widget/readline-dump-functions { ble-edit/content/clear-arg local ret ble/util/assign ret 'ble/builtin/bind -P' ble/widget/print "$ret" } function ble/widget/readline-dump-macros { ble-edit/content/clear-arg local ret ble/util/assign ret 'ble/builtin/bind -S' ble/widget/print "$ret" } function ble/widget/readline-dump-variables { ble-edit/content/clear-arg local ret ble/util/assign ret 'ble/builtin/bind -V' ble/widget/print "$ret" } function ble/widget/re-read-init-file { ble-edit/content/clear-arg local inputrc=$INPUTRC [[ $inputrc && -e $inputrc ]] || inputrc=~/.inputrc [[ -e $inputrc ]] || return 0 ble/decode/read-inputrc "$inputrc" _ble_builtin_bind_keymap= } _ble_edit_rlfunc_history=() _ble_edit_rlfunc_history_edit=() _ble_edit_rlfunc_history_dirt=() _ble_edit_rlfunc_history_index=0 function ble/widget/execute-named-command/accept.hook { local ret rlfunc error= ble/string#split-words rlfunc "$1" if ble/util/assign error 'ble/builtin/bind/rlfunc2widget "$_ble_decode_keymap" "$rlfunc" 2>&1'; then ble/decode/widget/dispatch "$ret" "${rlfunc[@]:1}" elif [[ $error ]]; then ble/widget/bell "$error" fi } function ble/widget/execute-named-command { ble/edit/async-read-mode 'ble/widget/execute-named-command/accept.hook' _ble_edit_async_read_before_widget=ble/edit/async-read-mode/empty-cancel.hook ble/history/set-prefix _ble_edit_rlfunc _ble_edit_PS1='!' return 147 } function ble/widget/overwrite-mode { ble-edit/content/clear-arg if [[ $_ble_edit_overwrite_mode ]]; then _ble_edit_overwrite_mode= else _ble_edit_overwrite_mode=1 fi } function ble/widget/set-mark { ble-edit/content/clear-arg _ble_edit_mark=$_ble_edit_ind _ble_edit_mark_active=1 } function ble/widget/kill-forward-text { ble-edit/content/clear-arg ((_ble_edit_ind>=${#_ble_edit_str})) && return 0 ble-edit/content/push-kill-ring "${_ble_edit_str:_ble_edit_ind}" '' forward ble-edit/content/replace "$_ble_edit_ind" "${#_ble_edit_str}" '' ((_ble_edit_mark>_ble_edit_ind&&(_ble_edit_mark=_ble_edit_ind))) } function ble/widget/kill-backward-text { ble-edit/content/clear-arg ((_ble_edit_ind==0)) && return 0 ble-edit/content/push-kill-ring "${_ble_edit_str::_ble_edit_ind}" '' backward ble-edit/content/replace 0 "$_ble_edit_ind" '' ((_ble_edit_mark=_ble_edit_mark<=_ble_edit_ind?0:_ble_edit_mark-_ble_edit_ind)) _ble_edit_ind=0 } function ble/widget/exchange-point-and-mark { ble-edit/content/clear-arg local m=$_ble_edit_mark p=$_ble_edit_ind _ble_edit_ind=$m _ble_edit_mark=$p } function ble/widget/@marked { local index=$_ble_edit_ind ble/decode/widget/dispatch "$@" if ((_ble_edit_ind!=index)); then _ble_edit_mark=$index _ble_edit_mark_active=S ble/decode/keymap/push selection fi } function ble/widget/selection/exit-default { ble/decode/keymap/pop ble/decode/widget/redispatch local ext=$? [[ $_ble_edit_mark_active == S && $_ble_decode_keymap != selection ]] && _ble_edit_mark_active= return "$ext" } function ble-decode/keymap:selection/bind-shift { local marked=${1:+$1 } ble-decode/keymap:safe/.bind 'S-C-f' "${marked}forward-char" ble-decode/keymap:safe/.bind 'S-right' "${marked}forward-char" ble-decode/keymap:safe/.bind 'S-C-b' "${marked}backward-char" ble-decode/keymap:safe/.bind 'S-left' "${marked}backward-char" ble-decode/keymap:safe/.bind 'S-C-right' "${marked}forward-cword" ble-decode/keymap:safe/.bind 'M-F' "${marked}forward-cword" ble-decode/keymap:safe/.bind 'M-S-f' "${marked}forward-cword" ble-decode/keymap:safe/.bind 'S-C-left' "${marked}backward-cword" ble-decode/keymap:safe/.bind 'M-B' "${marked}backward-cword" ble-decode/keymap:safe/.bind 'M-S-b' "${marked}backward-cword" ble-decode/keymap:safe/.bind 'M-S-right' "${marked}forward-sword" ble-decode/keymap:safe/.bind 'M-S-left' "${marked}backward-sword" ble-decode/keymap:safe/.bind 'S-C-a' "${marked}beginning-of-line" ble-decode/keymap:safe/.bind 'S-home' "${marked}beginning-of-line" ble-decode/keymap:safe/.bind 'S-C-e' "${marked}end-of-line" ble-decode/keymap:safe/.bind 'S-end' "${marked}end-of-line" ble-decode/keymap:safe/.bind 'S-C-p' "${marked}backward-line" ble-decode/keymap:safe/.bind 'S-up' "${marked}backward-line" ble-decode/keymap:safe/.bind 'S-C-n' "${marked}forward-line" ble-decode/keymap:safe/.bind 'S-down' "${marked}forward-line" ble-decode/keymap:safe/.bind 'S-C-home' "${marked}beginning-of-text" ble-decode/keymap:safe/.bind 'S-C-end' "${marked}end-of-text" ble-decode/keymap:safe/.bind 'M-S-m' "${marked}non-space-beginning-of-line" ble-decode/keymap:safe/.bind 'M-M' "${marked}non-space-beginning-of-line" } function ble-decode/keymap:selection/define { ble-bind -f __default__ 'selection/exit-default' ble-bind -f __line_limit__ nop ble-decode/keymap:selection/bind-shift } function ble/widget/.process-range-argument { p0=$1 p1=$2 len=${#_ble_edit_str} local pt (( p0>len?(p0=len):p0<0&&(p0=0), p1>len?(p1=len):p0<0&&(p1=0), p10 )) } function ble/widget/.delete-range { local p0 p1 len ble/widget/.process-range-argument "${@:1:2}" || return 1 if ((len)); then ble-edit/content/replace "$p0" "$p1" '' (( _ble_edit_ind>p1? (_ble_edit_ind-=len): _ble_edit_ind>p0&&(_ble_edit_ind=p0), _ble_edit_mark>p1? (_ble_edit_mark-=len): _ble_edit_mark>p0&&(_ble_edit_mark=p0) )) fi return 0 } function ble/widget/.kill-range { local p0 p1 len ble/widget/.process-range-argument "${@:1:2}" || return 1 ble-edit/content/push-kill-ring "${_ble_edit_str:p0:len}" "$4" "$p0:$p1" if ((len)); then ble-edit/content/replace "$p0" "$p1" '' (( _ble_edit_ind>p1? (_ble_edit_ind-=len): _ble_edit_ind>p0&&(_ble_edit_ind=p0), _ble_edit_mark>p1? (_ble_edit_mark-=len): _ble_edit_mark>p0&&(_ble_edit_mark=p0) )) fi return 0 } function ble/widget/.copy-range { local p0 p1 len ble/widget/.process-range-argument "${@:1:2}" || return 1 ble-edit/content/push-kill-ring "${_ble_edit_str:p0:len}" "$4" "$p0:$p1" } function ble/widget/.replace-range { local p0 p1 len ble/widget/.process-range-argument "${@:1:2}" local insert; ble-edit/content/replace-limited "$p0" "$p1" "$3" local inslen=${#insert} delta ((delta=inslen-len)) && ((_ble_edit_ind>p1?(_ble_edit_ind+=delta): _ble_edit_ind>=p0&&(_ble_edit_ind=p0+inslen), _ble_edit_mark>p1?(_ble_edit_mark+=delta): _ble_edit_mark>p0&&(_ble_edit_mark=p0))) return 0 } function ble/widget/delete-region { ble-edit/content/clear-arg ble/widget/.delete-range "$_ble_edit_mark" "$_ble_edit_ind" _ble_edit_mark_active= } function ble/widget/kill-region { ble-edit/content/clear-arg ble/widget/.kill-range "$_ble_edit_mark" "$_ble_edit_ind" _ble_edit_mark_active= } function ble/widget/copy-region { ble-edit/content/clear-arg ble/widget/.copy-range "$_ble_edit_mark" "$_ble_edit_ind" _ble_edit_mark_active= } function ble/widget/delete-region-or { if [[ $_ble_edit_mark_active ]]; then ble/widget/delete-region else ble/decode/widget/dispatch "$@" fi } function ble/widget/kill-region-or { if [[ $_ble_edit_mark_active ]]; then ble/widget/kill-region else ble/decode/widget/dispatch "$@" fi } function ble/widget/copy-region-or { if [[ $_ble_edit_mark_active ]]; then ble/widget/copy-region else ble/decode/widget/dispatch "$@" fi } function ble/widget/yank { local arg; ble-edit/content/get-arg 1 local nkill=${#_ble_edit_kill_ring[@]} if ((nkill==0)); then ble/widget/.bell 'no strings in kill-ring' _ble_edit_yank_index= return 1 fi local index=$_ble_edit_kill_index local delta=$((arg-1)) if ((delta)); then ((index=(index+delta)%nkill, index=(index+nkill)%nkill)) _ble_edit_kill_index=$index fi local insert=${_ble_edit_kill_ring[index]} _ble_edit_yank_index=$index if [[ $insert ]]; then ble-edit/content/replace-limited "$_ble_edit_ind" "$_ble_edit_ind" "$insert" ((_ble_edit_mark=_ble_edit_ind, _ble_edit_ind+=${#insert})) _ble_edit_mark_active= fi } _ble_edit_yank_index= function ble/edit/yankpop.impl { local arg=$1 local nkill=${#_ble_edit_kill_ring[@]} ((_ble_edit_yank_index=(_ble_edit_yank_index+arg)%nkill, _ble_edit_yank_index=(_ble_edit_yank_index+nkill)%nkill)) local insert=${_ble_edit_kill_ring[_ble_edit_yank_index]} ble-edit/content/replace-limited "$_ble_edit_mark" "$_ble_edit_ind" "$insert" ((_ble_edit_ind=_ble_edit_mark+${#insert})) } function ble/widget/yank-pop { local opts=$1 local arg; ble-edit/content/get-arg 1 if ! [[ $_ble_edit_yank_index && ${LASTWIDGET%%' '*} == ble/widget/yank ]]; then ble/widget/.bell return 1 fi [[ :$opts: == *:backward:* ]] && ((arg=-arg)) ble/edit/yankpop.impl "$arg" _ble_edit_mark_active=insert ble/decode/keymap/push yankpop } function ble/widget/yankpop/next { local arg; ble-edit/content/get-arg 1 ble/edit/yankpop.impl "$arg" } function ble/widget/yankpop/prev { local arg; ble-edit/content/get-arg 1 ble/edit/yankpop.impl "$((-arg))" } function ble/widget/yankpop/exit { ble/decode/keymap/pop _ble_edit_mark_active= } function ble/widget/yankpop/cancel { ble-edit/content/replace "$_ble_edit_mark" "$_ble_edit_ind" '' _ble_edit_ind=$_ble_edit_mark ble/widget/yankpop/exit } function ble/widget/yankpop/exit-default { ble/widget/yankpop/exit ble/decode/widget/redispatch } function ble-decode/keymap:yankpop/define { ble-decode/keymap:safe/bind-arg yankpop/exit-default ble-bind -f __default__ 'yankpop/exit-default' ble-bind -f __line_limit__ nop ble-bind -f 'C-g' 'yankpop/cancel' ble-bind -f 'C-x C-g' 'yankpop/cancel' ble-bind -f 'C-M-g' 'yankpop/cancel' ble-bind -f 'M-y' 'yankpop/next' ble-bind -f 'M-S-y' 'yankpop/prev' ble-bind -f 'M-Y' 'yankpop/prev' } _ble_term_DECSCNM_state= function ble/widget/.bell { [[ :$bleopt_edit_bell: == *:vbell:* ]] && ble/term/visible-bell "$1" [[ :$bleopt_edit_bell: == *:abell:* ]] && ble/term/audible-bell if [[ :$bleopt_edit_bell: == *:visual:* ]]; then ble/util/buffer $'\e[?5h' ble/util/buffer.flush _ble_term_DECSCNM_state=1 if ble/is-function ble/util/idle.push; then ble/util/idle.push --sleep=50 ble/widget/.bell/.clear-DECSCNM else ble/util/msleep 50 ble/widget/.bell/.clear-DECSCNM fi fi return 0 } function ble/widget/.bell/.clear-DECSCNM { [[ $_ble_term_DECSCNM_state ]] || return "$?" _ble_term_DECSCNM_state= ble/util/buffer $'\e[?5l' ble/util/buffer.flush } function ble/widget/bell { ble-edit/content/clear-arg _ble_edit_mark_active= _ble_edit_arg= blehook/invoke widget_bell ble/widget/.bell "$1" } function ble/widget/nop { return 0; } function ble/widget/insert-string { local IFS=$_ble_term_IFS local content="$*" local arg; ble-edit/content/get-arg 1 if ((arg<0)); then ble/widget/.bell "negative repetition number $arg" return 1 elif ((arg==0)); then return 0 elif ((arg>1)); then local ret; ble/string#repeat "$content" "$arg"; content=$ret fi ble/widget/.insert-string "$content" } function ble/widget/.insert-string { local insert=$1 [[ $insert ]] || return 1 ble-edit/content/replace-limited "$_ble_edit_ind" "$_ble_edit_ind" "$insert" local dx=${#insert} (( _ble_edit_mark>_ble_edit_ind&&(_ble_edit_mark+=dx), _ble_edit_ind+=dx )) _ble_edit_mark_active= } if [[ -c /dev/clipboard ]]; then function ble/widget/paste-from-clipboard { local clipboard if ! ble/util/readfile clipboard /dev/clipboard; then ble/widget/.bell return 1 fi ble/widget/insert-string "$clipboard" return 0 } fi _ble_edit_lastarg_index= _ble_edit_lastarg_delta= _ble_edit_lastarg_nth= function ble/widget/insert-arg.impl { local beg=$1 end=$2 index=$3 delta=$4 nth=$5 ((delta)) || delta=1 ble/history/initialize local hit= lastarg= local decl=$( local original=${_ble_edit_str:beg:end-beg} local count=; ((delta>0)) && count=_ble_history_COUNT while :; do if ((delta>0)); then ((index+1>=count)) && break ((index+=delta,delta=1)) ((index>=count&&(index=count-1))) else ((index-1<0)) && break ((index+=delta,delta=-1)) ((index<0&&(index=0))) fi local entry; ble/history/get-edited-entry "$index" builtin history -s -- "$entry" local ret if ble/edit/histexpand '!!:'"$nth" && [[ $ret != "$original" ]]; then hit=1 lastarg=$ret ble/util/declare-print-definitions hit lastarg break fi done _ble_edit_lastarg_index=$index _ble_edit_lastarg_delta=$delta _ble_edit_lastarg_nth=$nth ble/util/declare-print-definitions \ _ble_edit_lastarg_index \ _ble_edit_lastarg_delta \ _ble_edit_lastarg_nth ) builtin eval -- "$decl" if [[ $hit ]]; then local insert; ble-edit/content/replace-limited "$beg" "$end" "$lastarg" ((_ble_edit_mark=beg,_ble_edit_ind=beg+${#insert})) return 0 else ble/widget/.bell return 1 fi } function ble/widget/insert-nth-argument { ble/history/initialize local arg; ble-edit/content/get-arg '^' local beg=$_ble_edit_ind end=$_ble_edit_ind local index=$_ble_history_INDEX local delta=-1 nth=$arg ble/widget/insert-arg.impl "$beg" "$end" "$index" "$delta" "$nth" } function ble/widget/insert-last-argument { ble/history/initialize local arg; ble-edit/content/get-arg '$' local beg=$_ble_edit_ind end=$_ble_edit_ind local index=$_ble_history_INDEX local delta=-1 nth=$arg ble/widget/insert-arg.impl "$beg" "$end" "$index" "$delta" "$nth" || return "$?" _ble_edit_mark_active=insert ble/decode/keymap/push lastarg } function ble/widget/lastarg/next { local arg; ble-edit/content/get-arg 1 local beg=$_ble_edit_mark local end=$_ble_edit_ind local index=$_ble_edit_lastarg_index local delta if [[ $arg ]]; then delta=$((-arg)) else ((delta=_ble_edit_lastarg_delta>=0?1:-1)) fi local nth=$_ble_edit_lastarg_nth ble/widget/insert-arg.impl "$beg" "$end" "$index" "$delta" "$nth" } function ble/widget/lastarg/exit { ble/decode/keymap/pop _ble_edit_mark_active= } function ble/widget/lastarg/cancel { ble-edit/content/replace "$_ble_edit_mark" "$_ble_edit_ind" '' _ble_edit_ind=$_ble_edit_mark ble/widget/lastarg/exit } function ble/widget/lastarg/exit-default { ble/widget/lastarg/exit ble/decode/widget/redispatch } function ble/highlight/layer:region/mark:insert/get-face { face=region_insert } function ble-decode/keymap:lastarg/define { ble-decode/keymap:safe/bind-arg lastarg/exit-default ble-bind -f __default__ 'lastarg/exit-default' ble-bind -f __line_limit__ nop ble-bind -f 'C-g' 'lastarg/cancel' ble-bind -f 'C-x C-g' 'lastarg/cancel' ble-bind -f 'C-M-g' 'lastarg/cancel' ble-bind -f 'M-.' 'lastarg/next' ble-bind -f 'M-_' 'lastarg/next' } function ble/widget/self-insert/.get-code { if ((${#KEYS[@]})); then code=${KEYS[${#KEYS[@]}-1]} local flag=$((code&_ble_decode_MaskFlag)) local char=$((code&_ble_decode_MaskChar)) if ((flag==0&&char<_ble_decode_FunctionKeyBase)); then code=$char return 0 elif ((flag==_ble_decode_Ctrl&&(char==63||91<=char&&char<=122)&&(char&0x1F)!=0)); then ((char=char==63?127:char&0x1F)) code=$char return 0 fi fi if ((${#CHARS[@]})); then code=${CHARS[${#CHARS[@]}-1]} return 0 fi code=0 return 1 } function ble/widget/self-insert { local code; ble/widget/self-insert/.get-code ((code==0)) && return 0 ((code==127&&_ble_bash<30100)) && return 0 local ibeg=$_ble_edit_ind iend=$_ble_edit_ind local ret ins; ble/util/c2s "$code"; ins=$ret local arg; ble-edit/content/get-arg 1 if ((arg<0)); then ble/widget/.bell "negative repetition number $arg" return 1 elif ((arg==0)) || [[ ! $ins ]]; then arg=0 ins= elif ((arg>1)); then ble/string#repeat "$ins" "$arg"; ins=$ret fi if [[ $bleopt_delete_selection_mode && $_ble_edit_mark_active ]]; then ((_ble_edit_mark<_ble_edit_ind?(ibeg=_ble_edit_mark):(iend=_ble_edit_mark), _ble_edit_ind=ibeg)) ((arg==0&&ibeg==iend)) && return 0 elif [[ $_ble_edit_overwrite_mode ]] && ((code!=10&&code!=9)); then ((arg==0)) && return 0 local removed_width if [[ $_ble_edit_overwrite_mode == R ]]; then local removed_text=${_ble_edit_str:ibeg:arg} removed_text=${removed_text%%[$'\n\t']*} removed_width=${#removed_text} ((iend+=removed_width)) else local ret w; ble/util/c2w-edit "$code"; w=$((arg*ret)) local iN=${#_ble_edit_str} for ((removed_width=0;removed_widthw)) && ins=$ins${_ble_string_prototype::removed_width-w} fi if [[ :$ble_widget_self_insert_opts: == *:nolineext:* ]]; then if ((removed_widthibeg&&( _ble_edit_mark=2000)) || return 1 local ble_batch_insert_index=$index local ble_batch_insert_count=$N builtin eval -- "$_ble_decode_show_progress_hook" } function ble/widget/batch-insert { local -a chars; chars=("${KEYS[@]}") local -a KEYS=() local index=0 N=${#chars[@]} if [[ $_ble_edit_overwrite_mode ]]; then while ((index=limit)); then chars=("${chars[@]::limit-${#_ble_edit_str}}") N=${#chars[@]} ((index=5)); then IFS=: builtin eval '_ble_edit_bracketed_paste=("${_ble_edit_bracketed_paste[*]}")' chars=:$_ble_edit_bracketed_paste if [[ $chars == *:50:48:49:126 ]]; then if [[ $chars == *:27:91:50:48:49:126 ]]; then # ESC [ 2 0 1 ~ chars=${chars%:27:91:50:48:49:126} is_end=1 elif [[ $chars == *:155:50:48:49:126 ]]; then # CSI 2 0 1 ~ chars=${chars%:155:50:48:49:126} is_end=1 fi fi fi [[ $is_end ]] || return 1 _ble_decode_char__hook= chars=:${chars//:/::}: chars=${chars//:13::10:/:10:} # CR LF -> LF chars=${chars//:13:/:10:} # CR -> LF ble/string#split-words chars "${chars//:/ }" local proc=$_ble_edit_bracketed_paste_proc _ble_edit_bracketed_paste_proc= [[ $proc ]] && builtin eval -- "$proc \"\${chars[@]}\"" return 0 } function ble/widget/bracketed-paste.hook { ((_ble_edit_bracketed_paste_count%1000==0)) && IFS=: builtin eval '_ble_edit_bracketed_paste=("${_ble_edit_bracketed_paste[*]}")' # contract _ble_edit_bracketed_paste[_ble_edit_bracketed_paste_count++]=$1 (($1==126)) && ble/widget/bracketed-paste.hook/check-end && return 0 if ((!_ble_debug_keylog_enabled)) && [[ ! $_ble_decode_keylog_chars_enabled ]]; then local char while ble/decode/char-hook/next-char; do _ble_edit_bracketed_paste[_ble_edit_bracketed_paste_count++]=$char ((char==126)) && ble/widget/bracketed-paste.hook/check-end && return 0 done fi _ble_decode_char__hook=ble/widget/bracketed-paste.hook return 147 } function ble/widget/bracketed-paste.proc { local -a KEYS; KEYS=("$@") ble/widget/batch-insert } function ble/widget/transpose-chars { local arg; ble-edit/content/get-arg '' if ((arg==0)); then [[ ! $arg ]] && ble-edit/content/eolp && ((_ble_edit_ind>0&&_ble_edit_ind--)) arg=1 fi local p q r if ((arg>0)); then ((p=_ble_edit_ind-1, q=_ble_edit_ind, r=_ble_edit_ind+arg)) else # arg<0 ((p=_ble_edit_ind-1+arg, q=_ble_edit_ind, r=_ble_edit_ind+1)) fi if ((p<0||${#_ble_edit_str}=_ble_edit_ind&&(_ble_edit_mark+=w))) fi fi fi ble-edit/content/replace "$((_ble_edit_ind-a))" "$_ble_edit_ind" "$ins" ((_ble_edit_ind-=a, _ble_edit_ind+a<_ble_edit_mark?(_ble_edit_mark-=a): _ble_edit_ind<_ble_edit_mark&&(_ble_edit_mark=_ble_edit_ind))) return 0 } function ble/widget/.delete-char { local a=${1:-1} if ((a>0)); then if ((${#_ble_edit_str}<_ble_edit_ind+a)); then return 1 else ble-edit/content/replace "$_ble_edit_ind" "$((_ble_edit_ind+a))" '' fi elif ((a<0)); then ble/widget/.delete-backward-char "$((-a))"; return "$?" else if ((${#_ble_edit_str}==0)); then return 1 elif ((_ble_edit_ind<${#_ble_edit_str})); then ble-edit/content/replace "$_ble_edit_ind" "$((_ble_edit_ind+1))" '' else _ble_edit_ind=${#_ble_edit_str} ble/widget/.delete-backward-char 1; return "$?" fi fi ((_ble_edit_mark>_ble_edit_ind&&_ble_edit_mark--)) return 0 } function ble/widget/delete-forward-char { local arg; ble-edit/content/get-arg 1 ((arg==0)) && return 0 ble/widget/.delete-char "$arg" || ble/widget/.bell } function ble/widget/delete-backward-char { local arg; ble-edit/content/get-arg 1 ((arg==0)) && return 0 [[ $_ble_decode_keymap == vi_imap ]] && ble/keymap:vi/undo/add more ble/widget/.delete-char "$((-arg))" || ble/widget/.bell [[ $_ble_decode_keymap == vi_imap ]] && ble/keymap:vi/undo/add more } _ble_edit_exit_count=0 function ble/widget/exit { ble-edit/content/clear-arg if [[ $WIDGET == "$LASTWIDGET" ]]; then ((_ble_edit_exit_count++)) else _ble_edit_exit_count=1 fi local ret; ble-edit/eval-IGNOREEOF if ((_ble_edit_exit_count<=ret)); then local remain=$((ret-_ble_edit_exit_count+1)) ble/widget/.bell 'IGNOREEOF' ble/widget/print "IGNOREEOF($remain): Use \"exit\" to leave the shell." return 0 fi local opts=$1 ((_ble_bash>=40000)) && shopt -q checkjobs &>/dev/null && opts=$opts:checkjobs if [[ $bleopt_allow_exit_with_jobs ]]; then local ret if ble/util/assign ret 'compgen -A stopped -- ""' 2>/dev/null; [[ $ret ]]; then opts=$opts:twice elif [[ :$opts: == *:checkjobs:* ]]; then if ble/util/assign ret 'compgen -A running -- ""' 2>/dev/null; [[ $ret ]]; then opts=$opts:twice fi else opts=$opts:force fi fi if ! [[ :$opts: == *:force:* || :$opts: == *:twice:* && _ble_edit_exit_count -ge 2 ]]; then local joblist ble/util/joblist if ((${#joblist[@]})); then ble/widget/.bell "exit: There are remaining jobs." local q=\' Q="'\''" message= if [[ :$opts: == *:twice:* ]]; then message='There are remaining jobs. Input the same key to exit the shell anyway.' else message='There are remaining jobs. Use "exit" to leave the shell.' fi local ret ble/edit/marker#instantiate "$message" non-empty ble/widget/internal-command "ble/util/print '${ret//$q/$Q}'; jobs" return "$?" fi elif [[ :$opts: == *:checkjobs:* ]]; then local joblist ble/util/joblist ((${#joblist[@]})) && printf '%s\n' "${#joblist[@]}" fi _ble_edit_line_disabled=1 ble/textarea#render ble/edit/enter-command-layout # #D1800 pair=leave-command-layout local -a DRAW_BUFF=() ble/canvas/panel#goto.draw "$_ble_textarea_panel" "$_ble_textarea_gendx" "$_ble_textarea_gendy" ble/canvas/bflush.draw ble/edit/marker#instantiate-config exec_exit_mark ble/util/buffer.print "$ret" ble/util/buffer.flush _ble_builtin_exit_processing=1 ble/builtin/exit 0 ble/edit/leave-command-layout # #D1800 pair=enter-command-layout return 1 } function ble/widget/delete-forward-char-or-exit { if [[ $_ble_edit_str ]]; then ble/widget/delete-forward-char else ble/widget/exit fi } function ble/widget/delete-forward-backward-char { ble-edit/content/clear-arg ble/widget/.delete-char 0 || ble/widget/.bell } function ble/widget/delete-forward-char-or-list { local right=${_ble_edit_str:_ble_edit_ind} if [[ ! $right || $right == $'\n'* ]]; then ble/widget/complete show_menu else ble/widget/delete-forward-char fi } function ble/widget/delete-horizontal-space { local arg; ble-edit/content/get-arg '' local b=0 rex=$'[ \t]+$' [[ ${_ble_edit_str::_ble_edit_ind} =~ $rex ]] && b=${#BASH_REMATCH} local a=0 rex=$'^[ \t]+' [[ ! $arg && ${_ble_edit_str:_ble_edit_ind} =~ $rex ]] && a=${#BASH_REMATCH} ble/widget/.delete-range "$((_ble_edit_ind-b))" "$((_ble_edit_ind+a))" } function ble/widget/.forward-char { ((_ble_edit_ind+=${1:-1})) if ((_ble_edit_ind>${#_ble_edit_str})); then _ble_edit_ind=${#_ble_edit_str} return 1 elif ((_ble_edit_ind<0)); then _ble_edit_ind=0 return 1 fi } function ble/widget/forward-char { local arg; ble-edit/content/get-arg 1 ((arg==0)) && return 0 ble/widget/.forward-char "$arg" || ble/widget/.bell } function ble/widget/backward-char { local arg; ble-edit/content/get-arg 1 ((arg==0)) && return 0 ble/widget/.forward-char "$((-arg))" || ble/widget/.bell } _ble_edit_character_search_arg= function ble/widget/character-search-forward { local arg; ble-edit/content/get-arg 1 _ble_edit_character_search_arg=$arg _ble_edit_mark_active= _ble_decode_char__hook=ble/widget/character-search.hook } function ble/widget/character-search-backward { local arg; ble-edit/content/get-arg 1 ((_ble_edit_character_search_arg=-arg)) _ble_edit_mark_active= _ble_decode_char__hook=ble/widget/character-search.hook } function ble/widget/character-search.hook { local char=${KEYS[0]} local ret; ble/util/c2s "${KEYS[0]}"; local c=$ret [[ $c ]] || return 1 # Note: C-@ の時は無視 local arg=$_ble_edit_character_search_arg if ((arg>0)); then local right=${_ble_edit_str:_ble_edit_ind+1} if ble/string#index-of "$right" "$c" "$arg"; then ((_ble_edit_ind=_ble_edit_ind+1+ret)) elif ble/string#last-index-of "$right" "$c"; then ble/widget/.bell "${arg}th character not found" ((_ble_edit_ind=_ble_edit_ind+1+ret)) else ble/widget/.bell 'character not found' return 1 fi elif ((arg<0)); then local left=${_ble_edit_str::_ble_edit_ind} if ble/string#last-index-of "$left" "$c" "$((-arg))"; then _ble_edit_ind=$ret elif ble/string#index-of "$left" "$c"; then ble/widget/.bell "$((-arg))th last character not found" _ble_edit_ind=$ret else ble/widget/.bell 'character not found' return 1 fi fi return 0 } function ble/widget/.locate-forward-byte { local delta=$1 ret if ((delta==0)); then return 0 elif ((delta>0)); then local right=${_ble_edit_str:index:delta} local rlen=${#right} ble/util/strlen "$right"; local rsz=$ret if ((delta>=rsz)); then ((index+=rlen)) ((delta==rsz)); return "$?" else while ((delta&&rlen>=2)); do local mlen=$((rlen/2)) local m=${right::mlen} ble/util/strlen "$m"; local msz=$ret if ((delta>=msz)); then right=${right:mlen} ((index+=mlen, rlen-=mlen, delta-=msz)) ((rlen>delta)) && right=${right::delta} rlen=$delta else right=$m rlen=$mlen fi done ((delta&&rlen&&index++)) return 0 fi elif ((delta<0)); then ((delta=-delta)) local left=${_ble_edit_str::index} local llen=${#left} ((llen>delta)) && left=${left:llen-delta} llen=$delta ble/util/strlen "$left"; local lsz=$ret if ((delta>=lsz)); then ((index-=llen)) ((delta==lsz)); return "$?" else while ((delta&&llen>=2)); do local mlen=$((llen/2)) local m=${left:llen-mlen} ble/util/strlen "$m"; local msz=$ret if ((delta>=msz)); then left=${left::llen-mlen} ((index-=mlen, llen-=mlen, delta-=msz)) ((llen>delta)) && left=${left:llen-delta} llen=$delta else left=$m llen=$mlen fi done ((delta&&llen&&index--)) return 0 fi fi } function ble/widget/forward-byte { local arg; ble-edit/content/get-arg 1 ((arg==0)) && return 0 local index=$_ble_edit_ind ble/widget/.locate-forward-byte "$arg" || ble/widget/.bell _ble_edit_ind=$index } function ble/widget/backward-byte { local arg; ble-edit/content/get-arg 1 ((arg==0)) && return 0 local index=$_ble_edit_ind ble/widget/.locate-forward-byte "$((-arg))" || ble/widget/.bell _ble_edit_ind=$index } function ble/widget/end-of-text { local arg; ble-edit/content/get-arg '' if [[ $arg ]]; then if ((arg>=10)); then _ble_edit_ind=0 else ((arg<0&&(arg=0))) local index=$(((19-2*arg)*${#_ble_edit_str}/20)) local ret; ble-edit/content/find-logical-bol "$index" _ble_edit_ind=$ret fi else _ble_edit_ind=${#_ble_edit_str} fi } function ble/widget/beginning-of-text { local arg; ble-edit/content/get-arg '' if [[ $arg ]]; then if ((arg>=10)); then _ble_edit_ind=${#_ble_edit_str} else ((arg<0&&(arg=0))) local index=$(((2*arg+1)*${#_ble_edit_str}/20)) local ret; ble-edit/content/find-logical-bol "$index" _ble_edit_ind=$ret fi else _ble_edit_ind=0 fi } function ble/widget/beginning-of-logical-line { local arg; ble-edit/content/get-arg 1 local ret; ble-edit/content/find-logical-bol "$_ble_edit_ind" "$((arg-1))" _ble_edit_ind=$ret } function ble/widget/end-of-logical-line { local arg; ble-edit/content/get-arg 1 local ret; ble-edit/content/find-logical-eol "$_ble_edit_ind" "$((arg-1))" _ble_edit_ind=$ret } function ble/widget/kill-backward-logical-line { local arg; ble-edit/content/get-arg '' if [[ $arg ]]; then local ret; ble-edit/content/find-logical-eol "$_ble_edit_ind" "$((-arg))"; local index=$ret if ((arg>0)); then if ((_ble_edit_ind<=index)); then index=0 else ble/string#count-char "${_ble_edit_str:index:_ble_edit_ind-index}" $'\n' ((ret0)); then if ((index<=_ble_edit_ind)); then index=${#_ble_edit_str} else ble/string#count-char "${_ble_edit_str:_ble_edit_ind:index-_ble_edit_ind}" $'\n' ((ret0?(eofs=arg-1):(arg<0&&(bofs=arg+1)))) ble-edit/content/find-logical-bol "$_ble_edit_ind" "$bofs" && local bol=$ret ble-edit/content/find-logical-eol "$_ble_edit_ind" "$eofs" && local eol=$ret [[ ${_ble_edit_str:eol:1} == $'\n' ]] && ((eol++)) ((bol0?arg:-arg)) if ((arg>0)); then if [[ ! $_ble_history_prefix && ! $_ble_history_load_done ]]; then ble/widget/.bell 'end of history' return 1 fi fi ble/history/initialize local index=$_ble_history_INDEX local expr_next='--index>=0' if ((arg>0)); then local count=$_ble_history_COUNT expr_next="++index<=$count" fi while ((expr_next)); do if ((--rest<=0)); then ble-edit/history/goto "$index" # 位置は goto に任せる return "$?" fi local entry; ble/history/get-edited-entry "$index" if [[ $entry == *$'\n'* ]]; then local ret; ble/string#count-char "$entry" $'\n' if ((rest<=ret)); then ble-edit/history/goto "$index" if ((arg>0)); then ble-edit/content/find-logical-eol 0 "$rest" else ble-edit/content/find-logical-eol "${#entry}" "$((-rest))" fi _ble_edit_ind=$ret return 0 fi ((rest-=ret)) fi done if ((arg>0)); then ble-edit/history/goto "$count" _ble_edit_ind=${#_ble_edit_str} ble/widget/.bell 'end of history' else ble-edit/history/goto 0 _ble_edit_ind=0 ble/widget/.bell 'beginning of history' fi return 0 } function ble/widget/forward-logical-line.impl { local arg=$1 opts=$2 ((arg==0)) && return 0 local ind=$_ble_edit_ind if ((arg>0)); then ((ind<${#_ble_edit_str})) || return 1 else ((ind>0)) || return 1 fi local ret; ble-edit/content/find-logical-bol "$ind" "$arg"; local bol2=$ret if ((arg>0)); then if ((indbol2)); then ble/string#count-char "${_ble_edit_str:bol2:ind-bol2}" $'\n' ((arg+=ret)) fi fi if ((arg==0)); then ble-edit/content/find-logical-bol "$ind" ; local bol1=$ret ble-edit/content/find-logical-eol "$bol2"; local eol2=$ret local dst=$((bol2+ind-bol1)) ((_ble_edit_ind=dst0)); then ble-edit/content/find-logical-eol "$bol2" else ret=$bol2 fi _ble_edit_ind=$ret if [[ :$opts: == *:history:* && ! $_ble_edit_mark_active ]]; then ble/widget/forward-history-line.impl "$arg" return "$?" fi if ((arg>0)); then ble/widget/.bell 'end of string' else ble/widget/.bell 'beginning of string' fi return 0 } function ble/widget/forward-logical-line { local opts=$1 local arg; ble-edit/content/get-arg 1 ble/widget/forward-logical-line.impl "$arg" "$opts" } function ble/widget/backward-logical-line { local opts=$1 local arg; ble-edit/content/get-arg 1 ble/widget/forward-logical-line.impl "$((-arg))" "$opts" } function ble/keymap:emacs/find-graphical-eol { local axis=${1:-$_ble_edit_ind} arg=${2:-0} local x y index ble/textmap#getxy.cur "$axis" ble/textmap#get-index-at 0 "$((y+arg+1))" if ((index>0)); then local ax ay ble/textmap#getxy.cur --prefix=a "$index" ((ay>y+arg&&index--)) fi ret=$index } function ble/widget/beginning-of-graphical-line { ble/textmap#is-up-to-date || ble/widget/.update-textmap local arg; ble-edit/content/get-arg 1 local x y index ble/textmap#getxy.cur "$_ble_edit_ind" ble/textmap#get-index-at 0 "$((y+arg-1))" _ble_edit_ind=$index } function ble/widget/end-of-graphical-line { ble/textmap#is-up-to-date || ble/widget/.update-textmap local arg; ble-edit/content/get-arg 1 local ret; ble/keymap:emacs/find-graphical-eol "$_ble_edit_ind" "$((arg-1))" _ble_edit_ind=$ret } function ble/widget/kill-backward-graphical-line { ble/textmap#is-up-to-date || ble/widget/.update-textmap local arg; ble-edit/content/get-arg '' if [[ ! $arg ]]; then local x y index ble/textmap#getxy.cur "$_ble_edit_ind" ble/textmap#get-index-at 0 "$y" ((index==_ble_edit_ind&&index>0&&index--)) ble/widget/.kill-range "$index" "$_ble_edit_ind" else local ret; ble/keymap:emacs/find-graphical-eol "$_ble_edit_ind" "$((-arg))" ble/widget/.kill-range "$ret" "$_ble_edit_ind" fi } function ble/widget/kill-forward-graphical-line { ble/textmap#is-up-to-date || ble/widget/.update-textmap local arg; ble-edit/content/get-arg '' local x y index ax ay ble/textmap#getxy.cur "$_ble_edit_ind" ble/textmap#get-index-at 0 "$((y+${arg:-1}))" if [[ ! $arg ]] && ((_ble_edit_indy&&index--)) fi ble/widget/.kill-range "$_ble_edit_ind" "$index" } function ble/widget/kill-graphical-line { ble/textmap#is-up-to-date || ble/widget/.update-textmap local arg; ble-edit/content/get-arg 0 local bofs=0 eofs=0 ((arg>0?(eofs=arg-1):(arg<0&&(bofs=arg+1)))) local x y index ax ay ble/textmap#getxy.cur "$_ble_edit_ind" ble/textmap#get-index-at 0 "$((y+bofs))" ; local bol=$index ble/textmap#get-index-at 0 "$((y+eofs+1))"; local eol=$index ((bol0)); then ble/widget/.bell 'end of string' else ble/widget/.bell 'beginning of string' fi return 0 } function ble/widget/forward-graphical-line { local opts=$1 local arg; ble-edit/content/get-arg 1 ble/widget/forward-graphical-line.impl "$arg" "$opts" } function ble/widget/backward-graphical-line { local opts=$1 local arg; ble-edit/content/get-arg 1 ble/widget/forward-graphical-line.impl "$((-arg))" "$opts" } function ble/widget/beginning-of-line { if ble/edit/performs-on-graphical-line; then ble/widget/beginning-of-graphical-line else ble/widget/beginning-of-logical-line fi } function ble/widget/non-space-beginning-of-line { local old=$_ble_edit_ind ble/widget/beginning-of-logical-line local bol=$_ble_edit_ind ret= ble-edit/content/find-non-space "$bol" [[ $ret == $old ]] && ret=$bol # toggle _ble_edit_ind=$ret return 0 } function ble/widget/end-of-line { if ble/edit/performs-on-graphical-line; then ble/widget/end-of-graphical-line else ble/widget/end-of-logical-line fi } function ble/widget/kill-backward-line { if ble/edit/performs-on-graphical-line; then ble/widget/kill-backward-graphical-line else ble/widget/kill-backward-logical-line fi } function ble/widget/kill-forward-line { if ble/edit/performs-on-graphical-line; then ble/widget/kill-forward-graphical-line else ble/widget/kill-forward-logical-line fi } function ble/widget/kill-line { if ble/edit/performs-on-graphical-line; then ble/widget/kill-graphical-line else ble/widget/kill-logical-line fi } function ble/widget/forward-line { if ble/edit/use-textmap; then ble/widget/forward-graphical-line "$@" else ble/widget/forward-logical-line "$@" fi } function ble/widget/backward-line { if ble/edit/use-textmap; then ble/widget/backward-graphical-line "$@" else ble/widget/backward-logical-line "$@" fi } function ble/edit/word:eword/setup { word_class=set2 word_set='a-zA-Z0-9' word_sep="$_ble_term_IFS" } function ble/edit/word:cword/setup { word_class=set2 word_set='_a-zA-Z0-9' word_sep="$_ble_term_IFS" } function ble/edit/word:uword/setup { word_class=set word_sep="$_ble_term_IFS" word_set="^$word_sep" } function ble/edit/word:sword/setup { word_class=set word_sep=$'|&;()<> \t\n' word_set="^$word_sep" } function ble/edit/word:fword/setup { word_class=set word_sep="/$_ble_term_IFS" word_set="^$word_sep" } function ble/edit/word/skip-backward { local set=$1 head=${_ble_edit_str::x} head=${head##*[$set]} ((x-=${#head},${#head})) } function ble/edit/word/skip-forward { local set=$1 tail=${_ble_edit_str:x} tail=${tail%%[$set]*} ((x+=${#tail},${#tail})) } function ble/edit/word/class:set/find-backward-word { ble/edit/word/skip-backward "$word_set" } function ble/edit/word/class:set/find-backward-space { ble/edit/word/skip-backward "$word_sep" } function ble/edit/word/class:set/find-forward-word { ble/edit/word/skip-forward "$word_set" } function ble/edit/word/class:set/find-forward-space { ble/edit/word/skip-forward "$word_sep" } function ble/edit/word/class:set2/find-backward-word { ble/edit/word/skip-backward "!$word_sep" } function ble/edit/word/class:set2/find-backward-space { case ${_ble_edit_str::x} in (*[$word_sep]) return 1 ;; (*[$word_set]) ble/edit/word/skip-backward "!$word_set" ;; (*?) ble/edit/word/skip-backward "$word_set$word_sep" ;; esac } function ble/edit/word/class:set2/find-forward-word { ble/edit/word/skip-forward "!$word_sep" } function ble/edit/word/class:set2/find-forward-space { case ${_ble_edit_str:x} in ([$word_sep]*) return 1 ;; ([$word_set]*) ble/edit/word/skip-forward "!$word_set" ;; (?*) ble/edit/word/skip-forward "$word_set$word_sep" ;; esac } function ble/edit/word/locate-backward { local x=${1:-$_ble_edit_ind} arg=${2:-1} while ((arg--)); do ble/edit/word/class:"$word_class"/find-backward-word; c=$x ble/edit/word/class:"$word_class"/find-backward-space; b=$x done ble/edit/word/class:"$word_class"/find-backward-word; a=$x } function ble/edit/word/locate-forward { local x=${1:-$_ble_edit_ind} arg=${2:-1} while ((arg--)); do ble/edit/word/class:"$word_class"/find-forward-word; s=$x ble/edit/word/class:"$word_class"/find-forward-space; t=$x done ble/edit/word/class:"$word_class"/find-forward-word; u=$x } function ble/edit/word/forward-range { local arg=$1; ((arg)) || arg=1 if ((arg<0)); then ble/edit/word/backward-range "$((-arg))" return "$?" fi local s t u; ble/edit/word/locate-forward "$x" "$arg"; y=$t } function ble/edit/word/backward-range { local arg=$1; ((arg)) || arg=1 if ((arg<0)); then ble/edit/word/forward-range "$((-arg))" return "$?" fi local a b c; ble/edit/word/locate-backward "$x" "$arg"; y=$b } function ble/edit/word/current-range { local arg=$1; ((arg)) || arg=1 if ((arg>0)); then local a b c; ble/edit/word/locate-backward "$x" local s t u; ble/edit/word/locate-forward "$a" "$arg" ((y=a,x0)); then x=$e1 ble/edit/word/class:"$word_class"/find-forward-word; local b2=$x while ble/edit/word/class:"$word_class"/find-forward-space || return 1; ((--arg>0)); do ble/edit/word/class:"$word_class"/find-forward-word done; local e2=$x else x=$b1 ble/edit/word/class:"$word_class"/find-backward-word; local e2=$x while ble/edit/word/class:"$word_class"/find-backward-space || return 1; ((++arg<0)); do ble/edit/word/class:"$word_class"/find-backward-word done; local b2=$x fi fi ((b1>b2)) && local b1=$b2 e1=$e2 b2=$b1 e2=$e1 ((b1=0)); then ((arg==0)) && arg=1 if ble/string#index-of "${_ble_edit_str:_ble_edit_ind}" "$char" "$arg"; then ble/widget/.kill-range "$_ble_edit_ind" "$((_ble_edit_ind+ret+${#char}))" return "$?" fi else if ble/string#last-index-of "${_ble_edit_str::_ble_edit_ind}" "$char" "$((-arg))"; then ble/widget/.kill-range "$ret" "$_ble_edit_ind" return "$?" fi fi if ((arg>0)); then if ((arg==-1)); then ble/widget/.bell "last char '$char' not found" else ble/widget/.bell "$((-arg))th last char '$char' not found" fi else if ((arg==1)); then ble/widget/.bell "next char '$char' not found" else ble/widget/.bell "$arg-th next char '$char' not found" fi fi return 0 } function ble/widget/zap-to-char { _ble_edit_mark_active= _ble_decode_key__hook=ble/widget/zap-to-char.hook return 147 } _ble_edit_exec_lines=() _ble_edit_exec_lastexit=0 _ble_edit_exec_lastarg=$BASH _ble_edit_exec_lastparams=() _ble_edit_exec_BASH_COMMAND=$BASH _ble_edit_exec_PIPESTATUS=() function ble-edit/exec/register { local command=$1 if [[ $command != *[!"$_ble_term_IFS"]* ]]; then ble/edit/leave-command-layout return 1 fi local command_id=$((_ble_edit_CMD++)) # Exposed to blehook exec_register local lineno=$((_ble_edit_LINENO+1)) # Exposed to blehook exec_register ble/array#push _ble_edit_exec_lines "$command_id,$lineno:$command" blehook/invoke exec_register "$command" } function ble-edit/exec/has-pending-commands { ((${#_ble_edit_exec_lines[@]})) } function ble-edit/exec/.setexit { return "$_ble_edit_exec_lastexit" } _ble_prompt_eol_mark=('' '' 0) function ble-edit/exec/.adjust-eol { local cols=${COLUMNS:-80} local -a DRAW_BUFF=() if [[ $bleopt_prompt_eol_mark ]]; then if [[ $bleopt_prompt_eol_mark != "${_ble_prompt_eol_mark[0]}" ]]; then if [[ $bleopt_prompt_eol_mark ]]; then local ret= x=0 y=0 g=0 x1=0 x2=0 y1=0 y2=0 LINES=1 COLUMNS=80 ble/canvas/trace "$bleopt_prompt_eol_mark" truncate:measure-bbox _ble_prompt_eol_mark=("$bleopt_prompt_eol_mark" "$ret" "$x2") else _ble_prompt_eol_mark=('' '' 0) fi fi local eol_mark=${_ble_prompt_eol_mark[1]} ble/canvas/put.draw "$_ble_term_sgr0$_ble_term_sc" local width=${_ble_prompt_eol_mark[2]} limit=$cols [[ $_ble_term_rc ]] || ((limit--)) if ((width>limit)); then local x=0 y=0 g=0 LINES=1 COLUMNS=$limit ble/canvas/trace.draw "$bleopt_prompt_eol_mark" truncate width=$x else ble/canvas/put.draw "$eol_mark" fi [[ $_ble_term_rc ]] || ble/canvas/put-cub.draw "$width" ble/canvas/put.draw "$_ble_term_sgr0$_ble_term_rc" fi local advance=$((_ble_term_xenl?cols-2:cols-3)) if [[ $_ble_term_TERM == cygwin:* ]]; then while ((advance)); do ble/canvas/put-cuf.draw "$((advance-advance/2))" ((advance/=2)) done else ble/canvas/put-cuf.draw "$advance" fi ble/canvas/put.draw " $_ble_term_cr$_ble_term_el" ble/canvas/bflush.draw } _ble_prompt_ps10_data=() function ble/prompt/unit:_ble_prompt_ps10/update { ble/prompt/unit:{section}/update _ble_prompt_ps10 "$PS0" '' } function ble-edit/exec/print-PS0 { if [[ $PS0 ]]; then local version=$COLUMNS,$_ble_edit_lineno,$_ble_history_count,$_ble_edit_CMD local prompt_hashref_base='$version' local prompt_rows=${LINES:-25} local prompt_cols=${COLUMNS:-80} local "${_ble_prompt_cache_vars[@]/%/=}" # WA #D1570 checked ble/prompt/unit#update _ble_prompt_ps10 local ret; ble/prompt/unit:{section}/get _ble_prompt_ps10 ble/util/put "$ret" fi } _ble_builtin_exit_processing= function ble/builtin/exit/.read-arguments { [[ ! $_ble_attached || $_ble_edit_exec_inside_userspace ]] && ble/base/adjust-BASH_REMATCH while (($#)); do local arg=$1; shift if [[ $arg == --help ]]; then opt_flags=${opt_flags}H elif local rex='^[-+]?[0-9]+$'; [[ $arg =~ $rex ]]; then ble/array#push opt_args "$arg" else ble/util/print "exit: unrecognized argument '$arg'" >&2 opt_flags=${opt_flags}E fi done if ((${#opt_args[@]}>=2)); then ble/util/print "exit: too many arguments" >&2 opt_flags=${opt_flags}E fi [[ ! $_ble_attached || $_ble_edit_exec_inside_userspace ]] && ble/base/restore-BASH_REMATCH } function ble/builtin/exit { local ext=$? local trap_processing=$_ble_builtin_trap_processing [[ $_ble_builtin_trap_processing == "${BASH_SUBSHELL:-0}"/* ]] || trap_processing= if [[ ! $trap_processing ]] && { ble/util/is-running-in-subshell || [[ $_ble_decode_bind_state == none ]]; }; then (($#)) || set -- "$ext" builtin exit "$@" return "$?" # オプションの指定間違いなどで失敗する可能性がある。 fi local set shopt; ble/base/.adjust-bash-options set shopt local opt_flags= local -a opt_args=() ble/builtin/exit/.read-arguments "$@" if [[ $opt_flags == *[EH]* ]]; then [[ $opt_flags == *H* ]] && builtin exit --help ble/base/.restore-bash-options set shopt return 2 fi ((${#opt_args[@]})) || ble/array#push opt_args "$ext" if [[ $trap_processing ]]; then shopt -s extdebug _ble_edit_exec_TRAPDEBUG_EXIT=$opt_args ble-edit/exec:gexec/.TRAPDEBUG/trap return 0 fi if [[ ! $_ble_builtin_exit_processing ]]; then local joblist ble/util/joblist if ((${#joblist[@]})); then local ret while local cancel_reason= if ble/util/assign ret 'compgen -A stopped -- ""' 2>/dev/null; [[ $ret ]]; then cancel_reason='stopped jobs' elif [[ :$opts: == *:checkjobs:* ]]; then if ble/util/assign ret 'compgen -A running -- ""' 2>/dev/null; [[ $ret ]]; then cancel_reason='running jobs' fi fi [[ $cancel_reason ]] do jobs ble/builtin/read -ep "\e[38;5;12m[ble: There are $cancel_reason]\e[m Leave the shell anyway? [yes/No] " ret case $ret in ([yY]|[yY][eE][sS]) break ;; ([nN]|[nN][oO]|'') ble/base/.restore-bash-options set shopt return 0 ;; esac done fi local ret ble/edit/marker#instantiate-config exec_exit_mark && ble/util/print "$ret" >&2 fi if ((40400<=_ble_bash&&_ble_bash<50200)); then local global_TIMEFORMAT local_TIMEFORMAT ble/util/assign global_TIMEFORMAT 'ble/util/print-global-definitions TIMEFORMAT' if [[ $global_TIMEFORMAT == 'declare TIMEFORMAT; builtin unset -v TIMEFORMAT' ]]; then global_TIMEFORMAT='declare -g TIMEFORMAT=$'\''\nreal\t%3lR\nuser\t%3lU\nsys %3lS'\' else global_TIMEFORMAT="declare -g ${global_TIMEFORMAT#declare }" fi ble/variable#copy-state TIMEFORMAT local_TIMEFORMAT declare -g TIMEFORMAT= TIMEFORMAT= fi ble/base/.restore-bash-options set shopt _ble_builtin_exit_processing=1 ble/fd#alloc _ble_builtin_exit_stdout '>&1' # EXIT trap で stdin/stdout を復元する ble/fd#alloc _ble_builtin_exit_stderr '>&2' builtin exit "${opt_args[@]}" &>/dev/null builtin exit "${opt_args[@]}" &>/dev/null _ble_builtin_exit_processing= ble/fd#close _ble_builtin_exit_stdout ble/fd#close _ble_builtin_exit_stderr if ((40400<=_ble_bash&&_ble_bash<50200)); then builtin eval -- "$global_TIMEFORMAT" ble/variable#copy-state local_TIMEFORMAT TIMEFORMAT fi return 1 # exit できなかった場合は 1 らしい } function exit { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" ble/builtin/exit "$@" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" } _ble_exec_time_TIMEFILE=$_ble_base_run/$$.exec.time _ble_exec_time_TIMEFORMAT= _ble_exec_time_tot= _ble_exec_time_usr= _ble_exec_time_sys= function ble/exec/time#adjust-TIMEFORMAT { if [[ ${TIMEFORMAT+set} ]]; then _ble_exec_time_TIMEFORMAT=$TIMEFORMAT else builtin unset -v _ble_exec_time_TIMEFORMAT fi TIMEFORMAT='%R %U %S' } function ble/exec/time#restore-TIMEFORMAT { if [[ ${_ble_exec_time_TIMEFORMAT+set} ]]; then TIMEFORMAT=$_ble_exec_time_TIMEFORMAT else builtin unset -v 'TIMEFORMAT[0]' fi local tot usr sys dummy while IFS=' ' ble/bash/read tot usr sys dummy; do ble/string#match "$tot" '^[0-9.ms]+$' && break done < "$_ble_exec_time_TIMEFILE" ((_ble_exec_time_tot=10#0${tot//[!0-9]})) ((_ble_exec_time_usr=10#0${usr//[!0-9]})) ((_ble_exec_time_sys=10#0${sys//[!0-9]})) } _ble_exec_time_TIMES=$_ble_base_run/$$.exec.times _ble_exec_time_usr_self= _ble_exec_time_sys_self= function ble/exec/time/times.parse-time { local rex='^([0-9]+m)?([0-9]*)([^0-9ms][0-9]{3})?s?$' [[ $1 =~ $rex ]] || return 1 local min=$((10#0${BASH_REMATCH[1]%m})) local sec=$((10#0${BASH_REMATCH[2]})) local msc=$((10#0${BASH_REMATCH[3]#?})) ((ret=(min*60+sec)*1000+msc)) return 0 } function ble/exec/time/times.start { builtin times >| "$_ble_exec_time_TIMES" } function ble/exec/time/times.end { builtin times >> "$_ble_exec_time_TIMES" local times ble/util/readfile times "$_ble_exec_time_TIMES" ble/string#split-words times "$times" _ble_exec_time_usr_self= _ble_exec_time_sys_self= local ret= t1 t2 ble/exec/time/times.parse-time "${times[0]}" && t1=$ret && ble/exec/time/times.parse-time "${times[4]}" && t2=$ret && ((_ble_exec_time_usr_self=t2>t1?t2-t1:0, _ble_exec_time_usr_self>_ble_exec_time_usr&&( _ble_exec_time_usr_self=_ble_exec_time_usr))) ble/exec/time/times.parse-time "${times[1]}" && t1=$ret && ble/exec/time/times.parse-time "${times[5]}" && t2=$ret && ((_ble_exec_time_sys_self=t2>t1?t2-t1:0, _ble_exec_time_sys_self>_ble_exec_time_sys&&( _ble_exec_time_sys_self=_ble_exec_time_sys))) return 0 } function ble/exec/time#mark-enabled { local real=$_ble_exec_time_tot local usr=$_ble_exec_time_usr usr_self=$_ble_exec_time_usr_self local sys=$_ble_exec_time_sys sys_self=$_ble_exec_time_sys_self local usr_child=$((usr-usr_self)) local sys_child=$((sys-sys_self)) local cpu=$((real>0?(usr+sys)*100/real:0)) ((bleopt_exec_elapsed_enabled)) } _ble_exec_time_beg= _ble_exec_time_end= _ble_exec_time_ata= function ble/exec/time#start { if ((_ble_bash>=50000)); then _ble_exec_time_EPOCHREALTIME_delay=0 _ble_exec_time_EPOCHREALTIME_beg= _ble_exec_time_EPOCHREALTIME_end= function ble/exec/time#start { ble/exec/time/times.start _ble_exec_time_EPOCHREALTIME_beg= _ble_exec_time_EPOCHREALTIME_end= } function ble/exec/time#end { local beg=${_ble_exec_time_EPOCHREALTIME_beg//[!0-9]} local end=${_ble_exec_time_EPOCHREALTIME_end//[!0-9]} ((beg+=delay,beg>end)) && beg=$end _ble_exec_time_beg=$beg _ble_exec_time_end=$end _ble_exec_time_ata=$((end-beg)) _ble_exec_time_LINENO=$_ble_edit_LINENO ble/exec/time/times.end } function ble/exec/time#calibrate.restore-lastarg { _ble_exec_time_EPOCHREALTIME_beg=$EPOCHREALTIME return "$_ble_edit_exec_lastexit" } function ble/exec/time#calibrate.save-lastarg { _ble_exec_time_EPOCHREALTIME_end=$EPOCHREALTIME ble/exec/time#adjust-TIMEFORMAT } function ble/exec/time#calibrate { local _ble_edit_exec_lastexit=0 local _ble_edit_exec_lastarg=hello local _ble_exec_time_EPOCHREALTIME_beg= local _ble_exec_time_EPOCHREALTIME_end= local _ble_exec_time_tot= local _ble_exec_time_usr= local _ble_exec_time_sys= local TIMEFORMAT= local script1='ble/exec/time#calibrate.restore-lastarg "$_ble_edit_exec_lastarg"' local script2='{ ble/exec/time#calibrate.save-lastarg; } 4>&1 5>&2 &>/dev/null' local script=$script1$_ble_term_nl$script2$_ble_term_nl local -a hist=() local i for i in {00..99}; do { time LINENO=$i builtin eval -- "$script" 0<&"$_ble_util_fd_cmd_stdin" 1>&"$_ble_util_fd_cmd_stdout" 2>&"$_ble_util_fd_cmd_stderr"; } 2>| "$_ble_exec_time_TIMEFILE" ble/exec/time#restore-TIMEFORMAT local beg=${_ble_exec_time_EPOCHREALTIME_beg//[!0-9]} local end=${_ble_exec_time_EPOCHREALTIME_end//[!0-9]} ((hist[end-beg]++)) done local -a keys; keys=("${!hist[@]}") keys=("${keys[@]::(${#keys[@]}+1)/2}") # Remove outliers local s=0 n=0 t for t in "${keys[@]}"; do ((s+=t*hist[t],n+=hist[t])); done ((_ble_exec_time_EPOCHREALTIME_delay=s/n)) } ble/exec/time#calibrate builtin unset -f ble/exec/time#calibrate builtin unset -f ble/exec/time#calibrate.restore-lastarg builtin unset -f ble/exec/time#calibrate.save-lastarg else _ble_exec_time_CLOCK_base=0 _ble_exec_time_CLOCK_beg= _ble_exec_time_CLOCK_end= function ble/exec/time#end.adjust { ((_ble_exec_time_beg/dev/null && ble/string#match "$ret" '^[0-9]+$'; then function ble/exec/time#start { ble/exec/time/times.start _ble_exec_time_CLOCK_beg= _ble_exec_time_CLOCK_end= ble/util/assign _ble_exec_time_CLOCK_beg 'ble/bin/date +%s%6N' } function ble/exec/time#end { ble/util/assign _ble_exec_time_CLOCK_end 'ble/bin/date +%s%6N' local prev_end=$_ble_exec_time_end _ble_exec_time_beg=$_ble_exec_time_CLOCK_beg _ble_exec_time_end=$_ble_exec_time_CLOCK_end _ble_exec_time_ata=$((_ble_exec_time_tot*1000)) ble/exec/time#end.adjust ble/exec/time/times.end } fi ;; esac fi ble/exec/time#start } _ble_edit_exec_TRAPDEBUG_enabled= _ble_edit_exec_TRAPDEBUG_INT= _ble_edit_exec_TRAPDEBUG_EXIT= _ble_edit_exec_inside_begin= _ble_edit_exec_inside_prologue= _ble_edit_exec_inside_userspace= ble/builtin/trap/sig#reserve DEBUG override-builtin-signal:user-trap-in-postproc function ble-edit/exec:gexec/.TRAPDEBUG/trap { local trap_command ble/builtin/trap/install-hook/.compose-trap_command "$_ble_builtin_trap_DEBUG" builtin eval -- "builtin $trap_command" } _ble_edit_exec_TRAPDEBUG_adjusted= function _ble_edit_exec_gexec__TRAPDEBUG_adjust { builtin trap - DEBUG _ble_edit_exec_TRAPDEBUG_adjusted=1 } ble/function#trace _ble_edit_exec_gexec__TRAPDEBUG_adjust function ble-edit/exec:gexec/.TRAPDEBUG/restore { _ble_edit_exec_TRAPDEBUG_adjusted= local opts=$1 if ble/builtin/trap/user-handler#has "$_ble_builtin_trap_DEBUG"; then ble-edit/exec:gexec/.TRAPDEBUG/trap "$opts" fi } function ble-edit/exec:gexec/.TRAPDEBUG/.filter { [[ $_ble_edit_exec_TRAPDEBUG_enabled || ! $_ble_attached ]] || return 1 [[ $_ble_trap_bash_command != *ble-edit/exec:gexec/.* ]] || return 1 [[ ! ( ${FUNCNAME[1]-} == _ble_prompt_update__eval_prompt_command_1 && ( $_ble_trap_bash_command == 'ble-edit/exec/.setexit '* || $_ble_trap_bash_command == 'BASH_COMMAND='*' builtin eval -- '* ) ) ]] || return 1 [[ ! ${_ble_builtin_trap_inside-} ]] || return 1 return 0 } _ble_trap_builtin_handler_DEBUG_filter=ble-edit/exec:gexec/.TRAPDEBUG/.filter function ble-edit/exec:gexec/.TRAPDEBUG { if [[ $_ble_edit_exec_TRAPDEBUG_EXIT ]]; then local flag_clear= flag_exit= postproc= ble/util/unlocal _ble_builtin_trap_processing if [[ ! $_ble_builtin_trap_processing ]] || ((${#BLE_TRAP_FUNCNAME[*]}==0)); then flag_clear=2 flag_exit=$_ble_edit_exec_TRAPDEBUG_EXIT else case " ${BLE_TRAP_FUNCNAME[*]} " in (' ble/builtin/trap/invoke.sandbox ble/builtin/trap/invoke '*) ble/util/unlocal _ble_trap_lastarg # declared in ble/builtin/trap/.handler for DEBUG _ble_trap_done=exit # declared in ble/builtin/trap/invoke for the other signal _ble_trap_lastarg=$_ble_edit_exec_TRAPDEBUG_EXIT # declared in ble/builtin/trap/invoke for the other signal postproc='ble/util/setexit 2' shopt -q extdebug || postproc='return 0' ;; (' blehook/invoke.sandbox blehook/invoke ble/builtin/trap/.handler '*) _ble_local_ext=$_ble_edit_exec_TRAPDEBUG_EXIT _ble_builtin_trap_processing=${_ble_builtin_trap_processing%%/*}/exit:$_ble_edit_exec_TRAPDEBUG_EXIT postproc='ble/util/setexit 2' shopt -q extdebug || postproc='return 0' ;; (' ble/builtin/trap/invoke '* | ' blehook/invoke '*) flag_clear=1 ;; (' ble/builtin/trap/.handler '* | ' ble-edit/exec:gexec/.TRAPDEBUG '*) flag_clear=2 ;; (*) postproc='ble/util/setexit 2' shopt -q extdebug || postproc='return 128' ;; esac fi if [[ $flag_clear ]]; then [[ $flag_clear == 2 ]] || shopt -u extdebug _ble_edit_exec_TRAPDEBUG_EXIT= if ! ble/builtin/trap/user-handler#has "$_ble_trap_sig"; then postproc="builtin trap - DEBUG${postproc:+;$postproc}" fi if [[ $flag_exit ]]; then builtin exit "$flag_exit" fi fi _ble_builtin_trap_postproc[_ble_trap_sig]=$postproc return 126 # skip user hooks/traps elif [[ $_ble_edit_exec_TRAPDEBUG_INT ]]; then ble/util/setexit "$_ble_trap_lastexit" "$_ble_trap_lastarg" BASH_COMMAND=$_ble_trap_bash_command LINENO=$BLE_TRAP_LINENO \ ble/builtin/trap/invoke "$_ble_trap_sig" "${_ble_trap_args[@]}" local depth=${#BLE_TRAP_FUNCNAME[*]} if ((depth>=1)) && ! ble/string#match "${BLE_TRAP_FUNCNAME[*]}" '^ble-edit/exec:gexec/\.|(^| )ble/builtin/trap/\.handler'; then if [[ ${bleopt_internal_exec_int_trace-} ]]; then local source=${_ble_term_setaf[5]}${BLE_TRAP_SOURCE[0]} local sep=${_ble_term_setaf[6]}: local lineno=${_ble_term_setaf[2]}${BLE_TRAP_LINENO[0]} local func=${_ble_term_setaf[6]}' ('${_ble_term_setaf[4]}${BLE_TRAP_FUNCNAME[0]}${1:+ $1}${_ble_term_setaf[6]}')' ble/util/print "${_ble_term_setaf[9]}[SIGINT]$_ble_term_sgr0 $source$sep$lineno$func$_ble_term_sgr0" >&"$_ble_util_fd_tui_stderr" fi _ble_builtin_trap_postproc[_ble_trap_sig]="{ return $_ble_edit_exec_TRAPDEBUG_INT || break; } &>/dev/null" elif ((depth==0)) && ! ble/string#match "$_ble_trap_bash_command" '^ble-edit/exec:gexec/\.'; then if [[ ${bleopt_internal_exec_int_trace-} ]]; then local source=${_ble_term_setaf[5]}global local sep=${_ble_term_setaf[6]}: ble/util/print "${_ble_term_setaf[9]}[SIGINT]$_ble_term_sgr0 $source$sep$_ble_term_sgr0 $_ble_trap_bash_command" >&"$_ble_util_fd_tui_stderr" fi _ble_builtin_trap_postproc[_ble_trap_sig]="break &>/dev/null" fi return 126 # skip user hooks/traps elif ! ble/builtin/trap/user-handler#has "$_ble_trap_sig"; then _ble_builtin_trap_postproc[_ble_trap_sig]='builtin trap -- - DEBUG' return 126 # skip user hooks/traps fi return 0 } blehook internal_DEBUG!=ble-edit/exec:gexec/.TRAPDEBUG _ble_builtin_trap_DEBUG_userTrapInitialized= function ble/builtin/trap:DEBUG { _ble_builtin_trap_DEBUG_userTrapInitialized=1 if [[ $1 != - && ( $_ble_edit_exec_TRAPDEBUG_enabled || ! $_ble_attached ) ]]; then ble-edit/exec:gexec/.TRAPDEBUG/trap fi } function _ble_builtin_trap_DEBUG__initialize { if [[ $_ble_builtin_trap_DEBUG_userTrapInitialized ]]; then builtin eval -- "function $FUNCNAME { return 0; }" return 0 elif [[ $1 == force ]] || ble/function/is-global-trace-context; then _ble_builtin_trap_DEBUG_userTrapInitialized=1 builtin eval -- "function $FUNCNAME { return 0; }" local _ble_local_tmpfile; ble/util/assign/mktmp builtin trap -p DEBUG >| "$_ble_local_tmpfile" local content; ble/util/readfile content "$_ble_local_tmpfile" ble/util/assign/rmtmp case ${content#"trap -- '"} in (ble-edit/exec:gexec/.TRAPDEBUG*|ble/builtin/trap/.handler*) ;; # ble-0.4 (ble-edit/exec:exec/.eval-TRAPDEBUG*|ble-edit/exec:gexec/.eval-TRAPDEBUG*) ;; # ble-0.2 (.ble-edit/exec:exec/eval-TRAPDEBUG*|.ble-edit/exec:gexec/eval-TRAPDEBUG*) ;; # ble-0.1 (*) builtin eval -- "$content" ;; # ble/builtin/trap に処理させる esac return 0 fi } ble/function#trace _ble_builtin_trap_DEBUG__initialize _ble_builtin_trap_DEBUG__initialize function ble-edit/exec:gexec/.TRAPINT { local ret; ble/builtin/trap/sig#resolve INT ble/builtin/trap/user-handler#has "$ret" && return 0 local ext=130 ((_ble_bash>=40300)) || ext=128 # bash-4.2 以下は 128 if [[ $_ble_attached ]]; then if [[ ${bleopt_internal_exec_int_trace-} ]]; then ble/util/print "$_ble_term_bold^C$_ble_term_sgr0" >&"$_ble_util_fd_tui_stderr" fi _ble_edit_exec_TRAPDEBUG_INT=$ext ble-edit/exec:gexec/.TRAPDEBUG/trap else _ble_builtin_trap_postproc="{ return $ext || break; } 2>&$_ble_util_fd_tui_stderr" fi } function ble-edit/exec:gexec/.TRAPINT/reset { blehook internal_INT-='ble-edit/exec:gexec/.TRAPINT' } function ble-edit/exec:gexec/invoke-hook-with-setexit { local -a BLE_PIPESTATUS BLE_PIPESTATUS=("${_ble_edit_exec_PIPESTATUS[@]}") ble-edit/exec/.setexit "$_ble_edit_exec_lastarg" LINENO=${_ble_edit_LINENO:-${BASH_LINENO[${#BASH_LINENO[@]}-1]}} \ BASH_COMMAND=$_ble_edit_exec_BASH_COMMAND \ blehook/invoke "$@" } >&"$_ble_util_fd_tui_stdout" 2>&"$_ble_util_fd_tui_stderr" function ble-edit/exec:gexec/.TRAPERR { if [[ $_ble_attached ]]; then [[ $_ble_edit_exec_inside_userspace ]] || return 126 [[ $_ble_trap_bash_command != *'return "$_ble_edit_exec_lastexit"'* ]] || return 126 fi return 0 } blehook internal_ERR!='ble-edit/exec:gexec/.TRAPERR' _ble_edit_exec_TERM= function ble-edit/exec:gexec/TERM/is-dirty { [[ $TERM != "$_ble_edit_exec_TERM" ]] && return 0 local bindp ble/util/assign bindp 'builtin bind -p' [[ $bindp != "$_ble_decode_bind_bindp" ]] } function ble-edit/exec:gexec/TERM/leave { _ble_edit_exec_TERM=$TERM } function ble-edit/exec:gexec/TERM/enter { if [[ $_ble_decode_bind_state != none ]] && ble-edit/exec:gexec/TERM/is-dirty; then ble/edit/info/immediate-show text 'ble: TERM has changed. rebinding...' ble/decode/detach if ! ble/decode/attach; then ble-detach ble-edit/bind/.check-detach && return 1 fi ble/edit/info/immediate-default fi } function ble-edit/exec:gexec/.begin { _ble_edit_exec_inside_begin=1 local IFS=$_ble_term_IFS _ble_edit_exec_PWD=$PWD ble-edit/exec:gexec/TERM/leave ble/term/leave ble-edit/bind/stdout.on ble/util/buffer.flush ble/builtin/trap/install-hook INT # 何故か改めて実行しないと有効にならない blehook internal_INT!='ble-edit/exec:gexec/.TRAPINT' ble-edit/exec:gexec/.TRAPDEBUG/restore } function ble-edit/exec:gexec/.end { _ble_edit_exec_inside_begin= local IFS=$_ble_term_IFS ble-edit/exec:gexec/.TRAPINT/reset builtin trap -- - DEBUG blehook/invoke exec_end [[ $PWD != "$_ble_edit_exec_PWD" ]] && blehook/invoke CHPWD ble/util/joblist.flush >&"$_ble_util_fd_tui_stderr" ble-edit/bind/.check-detach && return 0 ble/term/enter ble-edit/exec:gexec/TERM/enter || return 0 # rebind に失敗した時 .tail せずに抜ける ble/util/c2w:auto/check ble/edit/clear-command-layout [[ $1 == restore ]] && return 0 # Note: 前回の呼出で .end に失敗した時 #D1170 ble-edit/bind/.tail # flush will be called here } function ble-edit/exec:gexec/.prologue { _ble_edit_exec_inside_prologue=1 local IFS=$_ble_term_IFS _ble_edit_exec_BASH_COMMAND=$1 _ble_edit_exec_command_id=$2 BLE_COMMAND_ID=$2 BLE_PIPESTATUS=("${_ble_edit_exec_PIPESTATUS[@]}") _ble_edit_exec_BASH_COMMAND_eval=$_ble_edit_exec_BASH_COMMAND if [[ $bleopt_exec_restore_pipestatus ]] && ((${#BLE_PIPESTATUS[@]} > 0)); then local i pipe= for ((i=0;i<${#BLE_PIPESTATUS[@]};i++)); do pipe=$pipe'| (exit '${BLE_PIPESTATUS[i]}')' done _ble_edit_exec_BASH_COMMAND_eval="${pipe:2}; $_ble_edit_exec_BASH_COMMAND_eval" fi ble-edit/restore-PS1 ble-edit/restore-READLINE ble-edit/restore-IGNOREEOF builtin unset -v HISTCMD; ble/history/get-count -v HISTCMD _ble_edit_exec_TRAPDEBUG_INT= ble/util/joblist.clear ble-edit/exec:gexec/invoke-hook-with-setexit internal_PREEXEC "$_ble_edit_exec_BASH_COMMAND" ble-edit/exec:gexec/invoke-hook-with-setexit PREEXEC "$_ble_edit_exec_BASH_COMMAND" ble-edit/exec/print-PS0 >&"$_ble_util_fd_tui_stdout" 2>&"$_ble_util_fd_tui_stderr" ble/exec/time#start ble/base/restore-BASH_REMATCH } function ble-edit/exec:gexec/.restore-lastarg { ble/base/restore-bash-options ble/base/restore-builtin-wrappers ble/base/restore-POSIXLY_CORRECT builtin eval -- "$_ble_bash_FUNCNEST_restore" _ble_edit_exec_TRAPDEBUG_enabled=1 _ble_edit_exec_inside_userspace=1 _ble_exec_time_EPOCHREALTIME_beg=$EPOCHREALTIME return "$_ble_edit_exec_lastexit" # set $? } &>/dev/null # set -x 対策 #D0930 function _ble_edit_exec_gexec__save_lastarg { _ble_exec_time_EPOCHREALTIME_end=$EPOCHREALTIME \ _ble_edit_exec_lastexit=$? \ _ble_edit_exec_lastarg=$_ \ _ble_edit_exec_PIPESTATUS=("${PIPESTATUS[@]}") \ _ble_edit_exec_lastparams=("$@") _ble_edit_exec_inside_userspace= _ble_edit_exec_TRAPDEBUG_enabled= builtin eval -- "$_ble_bash_FUNCNEST_adjust" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_adjust" ble/base/adjust-bash-options ble/exec/time#adjust-TIMEFORMAT ble/fd/save-external-standard-streams 0 4 5 return "$_ble_edit_exec_lastexit" } function _ble_edit_exec_gexec__epilogue { _ble_exec_time_EPOCHREALTIME_end=${_ble_exec_time_EPOCHREALTIME_end:-$EPOCHREALTIME} \ _ble_edit_exec_lastexit=$? _ble_edit_exec_inside_userspace= _ble_edit_exec_TRAPDEBUG_enabled= builtin eval -- "$_ble_bash_FUNCNEST_adjust" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_adjust" ble/base/adjust-builtin-wrappers if [[ $_ble_edit_exec_TRAPDEBUG_INT ]]; then if ((_ble_edit_exec_lastexit==0)); then _ble_edit_exec_lastexit=$_ble_edit_exec_TRAPDEBUG_INT fi _ble_edit_exec_TRAPDEBUG_INT= fi local IFS=$_ble_term_IFS builtin trap -- - DEBUG ble/base/adjust-bash-options ble/base/adjust-BASH_REMATCH ble-edit/adjust-IGNOREEOF ble-edit/adjust-READLINE ble/exec/time#restore-TIMEFORMAT ble/exec/time#end ble/util/reset-keymap-of-editing-mode ble-edit/exec/.adjust-eol _ble_edit_exec_inside_prologue= ble/util/buffer.flush ble-edit/exec:gexec/invoke-hook-with-setexit POSTEXEC "$_ble_edit_exec_BASH_COMMAND" local msg= if ((_ble_edit_exec_lastexit)); then ble-edit/exec:gexec/invoke-hook-with-setexit ERREXEC "$_ble_edit_exec_BASH_COMMAND" if local ret; ble/edit/marker#get-config exec_errexit_mark; then ble/util/sprintf ret "$ret" "$_ble_edit_exec_lastexit" msg=$ret fi fi ble-edit/adjust-PS1 if ble/exec/time#mark-enabled; then if local ret; ble/edit/marker#get-config exec_elapsed_mark; then local format=$ret local ata=$((_ble_exec_time_ata/1000)) if ((ata<1000)); then ata="${ata}ms" elif ((ata<1000*1000)); then ata="${ata::${#ata}-3}.${ata:${#ata}-3}s" elif ((ata/=1000,ata<3600*100)); then # ata [s] local min ((min=ata/60,ata%=60)) if ((min<100)); then ata="${min}m${ata}s" else ata="$((min/60))h$((min%60))m${ata}s" fi else local hour ((ata/=60,hour=ata/60,ata%=60)) ata="$((hour/24))d$((hour%24))h${ata}m" fi local cpu='--.-' if ((_ble_exec_time_tot)); then cpu=$(((_ble_exec_time_usr+_ble_exec_time_sys)*1000/_ble_exec_time_tot)) cpu=$((cpu/10)).$((cpu%10)) fi local ret ble/util/sprintf ret "$format" "$ata" "$cpu" msg=$msg$ret ble/string#ltrim "$_ble_edit_exec_BASH_COMMAND" msg="$msg $ret" fi fi local ret ble/edit/marker#instantiate "$msg" bare && ble/util/buffer.print "$ret" local -a DRAW_BUFF=() ble/prompt/print-ruler.draw "$_ble_edit_exec_BASH_COMMAND" ble/canvas/bflush.draw } function ble-edit/exec:gexec/.setup { ((${#_ble_edit_exec_lines[@]})) || [[ ! $_ble_edit_exec_TRAPDEBUG_adjusted ]] || return 1 local buff='_ble_decode_bind_hook=' ibuff=1 if [[ ! $_ble_edit_exec_TRAPDEBUG_adjusted ]]; then buff[ibuff++]='_ble_builtin_trap_DEBUG__initialize force' buff[ibuff++]=_ble_edit_exec_gexec__TRAPDEBUG_adjust fi local count=${#_ble_edit_exec_lines[@]} if ((count)); then ble/util/buffer.flush local q=\' Q="'\''" cmd cmd_id lineno buff[ibuff++]=ble-edit/exec:gexec/.begin for cmd in "${_ble_edit_exec_lines[@]}"; do cmd_id=${cmd%%,*} cmd=${cmd#*,} lineno=${cmd%%:*} cmd=${cmd#*:} buff[ibuff++]="ble-edit/exec:gexec/.prologue '${cmd//$q/$Q}' $cmd_id" buff[ibuff++]='{ time LINENO='$lineno' eval -- "ble-edit/exec:gexec/.restore-lastarg \"\$_ble_edit_exec_lastarg\"' buff[ibuff++]='$_ble_edit_exec_BASH_COMMAND_eval' buff[ibuff++]='{ _ble_edit_exec_gexec__save_lastarg \"\$@\"; } 4>&1 5>&2 &>/dev/null' # Note: &>/dev/null は set -x 対策 #D0930 buff[ibuff++]='" 0<&"$_ble_util_fd_cmd_stdin" 1>&"$_ble_util_fd_cmd_stdout" 2>&"$_ble_util_fd_cmd_stderr"; } 2>| "$_ble_exec_time_TIMEFILE"' buff[ibuff++]='{ _ble_edit_exec_gexec__epilogue; } 3>&2 &>/dev/null' done _ble_edit_exec_lines=() buff[ibuff++]=_ble_edit_exec_gexec__TRAPDEBUG_adjust buff[ibuff++]=ble-edit/exec:gexec/.end fi if ((ibuff>=2)); then IFS=$'\n' builtin eval '_ble_decode_bind_hook="${buff[*]}"' fi ((count>=1)); return "$?" } function ble-edit/exec:gexec/process { ble-edit/exec:gexec/.setup return "$?" } function ble-edit/exec:gexec/restore-state { [[ $_ble_edit_exec_inside_prologue ]] && _ble_edit_exec_gexec__epilogue 3>&2 &>/dev/null [[ $_ble_edit_exec_inside_begin ]] && ble-edit/exec:gexec/.end restore } : "${_ble_edit_lineno:=0}" _ble_prompt_trim_opwd= function ble/edit/.relocate-textarea { ble/textarea#render leave ble/edit/.allocate-textarea "$1" } function ble/edit/.allocate-textarea { local opts=$1 local -a DRAW_BUFF=() if [[ :$opts: == *:keep-info:* && $_ble_textarea_panel == 0 ]] && ! ble/util/joblist.has-events then local textarea_height=${_ble_canvas_panel_height[_ble_textarea_panel]} ble/canvas/panel#increase-height.draw "$_ble_textarea_panel" 1 ble/canvas/panel#goto.draw "$_ble_textarea_panel" 0 "$textarea_height" sgr0 ble/canvas/bflush.draw else ble/edit/enter-command-layout # #D1800 checked=ble/edit/.relocate-textarea ble/canvas/panel#goto.draw "$_ble_textarea_panel" "$_ble_textarea_gendx" "$_ble_textarea_gendy" sgr0 ble/canvas/put.draw "$_ble_term_nl" ble/canvas/bflush.draw ble/util/joblist.bflush [[ :$opts: == *:keep-info:* ]] && ble/edit/leave-command-layout fi ((_ble_edit_lineno++)) _ble_prompt_trim_opwd=$PWD ble/textarea#invalidate _ble_canvas_x=0 _ble_canvas_y=0 _ble_textarea_gendx=0 _ble_textarea_gendy=0 _ble_canvas_panel_height[_ble_textarea_panel]=1 } function ble/widget/.hide-current-line { local opts=$1 y_erase=0 [[ :$opts: == *:keep-header:* ]] && y_erase=${_ble_prompt_ps1_data[4]} local -a DRAW_BUFF=() if ((y_erase)); then ble/canvas/panel#clear-after.draw "$_ble_textarea_panel" 0 "$y_erase" else ble/canvas/panel#clear.draw "$_ble_textarea_panel" fi ble/canvas/panel#goto.draw "$_ble_textarea_panel" 0 "$y_erase" ble/canvas/bflush.draw ble/textarea#invalidate _ble_canvas_x=0 _ble_canvas_y=$y_erase _ble_textarea_gendx=0 _ble_textarea_gendy=$y_erase ((_ble_canvas_panel_height[_ble_textarea_panel]=1+y_erase)) } function ble/widget/.newline/clear-content { [[ $_ble_edit_overwrite_mode ]] && ble/term/cursor-state/reveal ble-edit/content/reset '' newline _ble_edit_ind=0 _ble_edit_mark=0 _ble_edit_mark_active= _ble_edit_overwrite_mode= } function ble/widget/.newline { local opts=$1 _ble_edit_mark_active= if [[ $_ble_complete_menu_active ]]; then [[ $_ble_highlight_layer_menu_filter_beg ]] && ble/textarea#invalidate str # (#D0995) fi ble/edit/.allocate-textarea "$opts" # #D1800 checked=.newline local ret; ble/string#count-char "$_ble_edit_str" $'\n' ((_ble_edit_LINENO+=1+ret)) ble/history/onleave.fire ble/widget/.newline/clear-content } function ble/widget/discard-line { ble-edit/content/clear-arg [[ $bleopt_history_share ]] && ble/builtin/history/option:n _ble_edit_line_disabled=1 ble/textarea#render leave ble/widget/.newline keep-info ble/textarea#render } function ble/edit/histexpand/run { local shopt=$- set -H ble/builtin/history/option:p "$command"; local ext=$? [[ $shopt == *H* ]] || set +H return "$ext" } function ble/edit/histexpand/.impl { ble/edit/histexpand/run 2>/dev/null; local ext=$? ((ext)) && ble/util/print "$command" ble/util/put : return "$ext" } function ble/edit/histexpand { local command=$1 if [[ ! ${command//[ ]} ]]; then ret=$command return 0 elif ble/util/assign ret 'ble/edit/histexpand/.impl'; then ret=${ret%$_ble_term_nl:} return 0 else ret=$command return 1 fi } _ble_edit_integration_mc_precmd_stop= function ble/widget/accept-line/.is-mc-init { [[ $MC_SID == $$ ]] && ((_ble_edit_LINENO<=5)) || return 1 ((_ble_edit_LINENO==0)) && return 0 if [[ $_ble_edit_str == *'PROMPT_COMMAND=${PROMPT_COMMAND:+$PROMPT_COMMAND'* ]]; then if ble/string#match "$_ble_edit_str" 'pwd>&[0-9]+;kill -STOP \$\$'; then _ble_edit_integration_mc_precmd_stop=1 ble/edit/info/set-default clear fi return 0 fi if ble/string#match "$_ble_edit_str" 'bind -x '\''"\\e\+":"([^"'\'']+)"'\'''; then function ble/widget/.mc_exec_command { ble/textarea#redraw ble/util/buffer.flush builtin eval -- "$1" } local str=${_ble_edit_str//"$BASH_REMATCH"/"ble-bind -f M-+ '.mc_exec_command '\''${BASH_REMATCH[1]}'\'''"} && [[ $str != "$_ble_edit_str" ]] && ble-edit/content/reset-and-check-dirty "$str" fi return 1 } function ble/widget/accept-line { ble/decode/widget/keymap-dispatch "$@" } function ble/widget/default/accept-line/.prepare-verify { local new_str=$1 new_ind=$2 ble-edit/content/reset-and-check-dirty "$old_str" _ble_edit_ind=$old_ind _ble_edit_line_disabled=1 ble/edit/.relocate-textarea keep-info ble-edit/content/reset-and-check-dirty "$new_str" _ble_edit_ind=$new_ind _ble_edit_mark=0 _ble_edit_mark_active= return 0 } function ble/widget/default/accept-line { if [[ :$1: == *:syntax:* ]] || ble/widget/accept-line/.is-mc-init; then ble-edit/content/update-syntax if ! ble/syntax:bash/is-complete; then ble/widget/newline return "$?" fi fi ble-edit/content/clear-arg local command=$_ble_edit_str if [[ ! ${command//["$_ble_term_IFS"]} ]]; then [[ $bleopt_history_share ]] && ble/builtin/history/option:n ble/textarea#render leave ble/widget/.newline keep-info ble/prompt/print-ruler.buff '' keep-info ble/textarea#render ble/util/buffer.flush return 0 fi local is_line_expanded= local orig_str=$_ble_edit_str orig_ind=$_ble_edit_ind if [[ :$bleopt_edit_magic_accept: == *:sabbrev:* ]]; then local old_str=$_ble_edit_str old_ind=$_ble_edit_ind if ble/complete/sabbrev/expand; then if [[ :$bleopt_edit_magic_accept: == *:verify:* ]]; then ble/widget/default/accept-line/.prepare-verify "$_ble_edit_str" "$_ble_edit_ind" return 0 fi command=$_ble_edit_str is_line_expanded=1 elif (($?==147)); then return 147 # We entered menu-complete fi fi local expand_type for expand_type in alias autocd; do if [[ :$bleopt_edit_magic_accept: == *:"$expand_type":* ]]; then local old_str=$_ble_edit_str old_ind=$_ble_edit_ind if ble/complete/expand:"$expand_type"; then if [[ :$bleopt_edit_magic_accept: == *:verify:* ]]; then ble/widget/default/accept-line/.prepare-verify "$_ble_edit_str" "$_ble_edit_ind" return 0 fi command=$_ble_edit_str is_line_expanded=1 fi fi done if [[ -o histexpand || :$bleopt_edit_magic_accept: == *:history:* ]]; then local old_str=$_ble_edit_str old_ind=$_ble_edit_ind if local ret; ble/edit/histexpand "$command"; then local expanded=$ret else ble/widget/.internal-print-command \ 'ble/edit/histexpand/run 1>/dev/null' pre-flush # エラーメッセージを表示 shopt -q histreedit &>/dev/null || ble/widget/.newline/clear-content return "$?" fi if [[ $expanded != "$command" ]]; then if shopt -q histverify &>/dev/null; then ble/widget/default/accept-line/.prepare-verify "$expanded" "${#expanded}" return 0 fi is_line_expanded=1 command=$expanded if [[ :$bleopt_edit_magic_accept: == *:history-inline:* ]]; then ble-edit/content/reset-and-check-dirty "$command" _ble_edit_ind=${#command} fi fi fi if [[ $is_line_expanded && :$bleopt_edit_magic_accept: == *:verify-syntax:* ]]; then if [[ $command != "$_ble_edit_str" ]]; then ble-edit/content/reset-and-check-dirty "$command" _ble_edit_ind=${#command} fi ble-edit/content/update-syntax if ! ble/syntax:bash/is-complete; then local old_str=$orig_str old_ind=$orig_ind ble/widget/default/accept-line/.prepare-verify "$_ble_edit_str" "$_ble_edit_ind" return 0 fi fi ble/textarea#render leave ble-edit/exec/register "$command" ble/history/add "$command" local show_expanded [[ $command != "$_ble_edit_str" ]] && show_expanded=1 ble/widget/.newline # #D1800 register if [[ $show_expanded ]]; then local ret ble/edit/marker#instantiate 'expand' non-empty ble/util/buffer.print "$ret $command" fi } function ble/widget/accept-and-next { ble-edit/content/clear-arg ble/history/initialize local index=$_ble_history_INDEX local count=$_ble_history_COUNT if ((index+1/dev/null; then ble-edit/content/update-syntax ble/syntax:bash/is-complete || return 1 fi return 0 } function ble/widget/accept-single-line-or { ble/decode/widget/keymap-dispatch "$@" } function ble/widget/default/accept-single-line-or { if ble-edit/is-single-complete-line; then ble/widget/accept-line else ble/widget/"$@" fi } function ble/widget/accept-single-line-or-newline { ble/widget/accept-single-line-or newline } function ble/widget/edit-and-execute-command.edit { local content=$1 opts=:$2: local file=$_ble_base_run/$$.blesh-fc.bash ble/util/print "$content" >| "$file" local fallback=vi if ble/bin#has emacs; then fallback='emacs -nw' elif ble/bin#has vim; then fallback=vim elif ble/bin#has nano; then fallback=nano fi if [[ $opts != *:no-newline:* ]]; then _ble_edit_line_disabled=1 ble/textarea#render leave ble/widget/.newline # #D1800 (呼び出し元で exec/register) fi ble/term/leave ${bleopt_editor:-${VISUAL:-${EDITOR:-$fallback}}} "$file"; local ext=$? ble/term/enter if ((ext)); then ble/widget/.bell return 127 fi ble/util/readfile ret "$file" return 0 } function ble/widget/edit-and-execute-command.impl { local ret= ble/widget/edit-and-execute-command.edit "$1" local command=$ret ble/string#match "$command" $'[\n]+$' && command=${command::${#command}-${#BASH_REMATCH}} if [[ $command != *[!"$_ble_term_IFS"]* ]]; then ble/edit/leave-command-layout ble/widget/.bell return 1 fi ble/edit/marker#instantiate 'fc' non-empty ble/util/buffer.print "$ret $command" ble-edit/exec/register "$command" ble/history/add "$command" } function ble/widget/edit-and-execute-command { ble-edit/content/clear-arg ble/widget/edit-and-execute-command.impl "$_ble_edit_str" } function ble/widget/insert-comment/.remove-comment { local comment_begin=$1 ret= [[ $comment_begin ]] || return 1 ble/string#escape-for-extended-regex "$comment_begin"; local rex_comment_begin=$ret local rex1=$'([ \t]*'$rex_comment_begin$')[^\n]*(\n|$)|[ \t]+(\n|$)|\n' local rex=$'^('$rex1')*$'; [[ $_ble_edit_str =~ $rex ]] || return 1 local tail=$_ble_edit_str out= while [[ $tail && $tail =~ ^$rex1 ]]; do local rematch1=${BASH_REMATCH[1]} if [[ $rematch1 ]]; then out=$out${rematch1%?}${BASH_REMATCH:${#rematch1}} else out=$out$BASH_REMATCH fi tail=${tail:${#BASH_REMATCH}} done [[ $tail ]] && return 1 ret=$out } function ble/widget/insert-comment/.insert { local arg=$1 local ret; ble/util/rlvar#read comment-begin '#' local comment_begin=${ret::1} local text= if [[ $arg ]] && ble/widget/insert-comment/.remove-comment "$comment_begin"; then text=$ret else text=$comment_begin${_ble_edit_str//$'\n'/$'\n'"$comment_begin"} fi ble-edit/content/reset-and-check-dirty "$text" } function ble/widget/insert-comment { local arg; ble-edit/content/get-arg '' ble/widget/insert-comment/.insert "$arg" ble/widget/accept-line } function ble/widget/alias-expand-line.proc { if ((tchild>=0)); then ble/syntax/tree-enumerate-children \ ble/widget/alias-expand-line.proc elif [[ $wtype && ! ${wtype//[0-9]} ]] && ((wtype==_ble_ctx_CMDI)); then local word=${_ble_edit_str:wbegin:wlen} local ret; ble/alias#expand "$word" [[ $word == "$ret" ]] && return 0 changed=1 ble/widget/.replace-range "$wbegin" "$((wbegin+wlen))" "$ret" fi } function ble/widget/alias-expand-line { ble-edit/content/clear-arg ble-edit/content/update-syntax local iN= changed= ble/syntax/tree-enumerate ble/widget/alias-expand-line.proc [[ $changed ]] && _ble_edit_mark_active= } function ble/widget/tilde-expand { ble-edit/content/clear-arg ble-edit/content/update-syntax local len=${#_ble_edit_str} local i=$len j=$len while ((--i>=0)); do ((_ble_syntax_attr[i])) || continue if ((_ble_syntax_attr[i]==_ble_attr_TILDE)); then local word=${_ble_edit_str:i:j-i} builtin eval "local path=$word" [[ $path != "$word" ]] && ble/widget/.replace-range "$i" "$j" "$path" fi j=$i done } _ble_edit_shell_expand_ExpandWtype=() function ble/widget/shell-expand-line.initialize { function ble/widget/shell-expand-line.initialize { return 0; } _ble_edit_shell_expand_ExpandWtype[_ble_ctx_CMDI]=1 _ble_edit_shell_expand_ExpandWtype[_ble_ctx_ARGI]=1 _ble_edit_shell_expand_ExpandWtype[_ble_ctx_ARGEI]=1 _ble_edit_shell_expand_ExpandWtype[_ble_ctx_ARGVI]=1 _ble_edit_shell_expand_ExpandWtype[_ble_ctx_RDRF]=1 _ble_edit_shell_expand_ExpandWtype[_ble_ctx_RDRD]=1 _ble_edit_shell_expand_ExpandWtype[_ble_ctx_RDRS]=1 _ble_edit_shell_expand_ExpandWtype[_ble_ctx_VALI]=1 _ble_edit_shell_expand_ExpandWtype[_ble_ctx_CONDI]=1 } function ble/widget/shell-expand-line.expand-word { local word=$1 ble/widget/shell-expand-line.initialize if [[ ! ${_ble_edit_shell_expand_ExpandWtype[wtype]} ]]; then ret=$word return 0 fi ret=$word; [[ $ret == '~'* ]] && ret='\'$word ble/syntax:bash/simple-word/eval "$ret" noglob if [[ $word != $ret || ${#ret[@]} -ne 1 ]]; then [[ $opts == *:quote:* ]] && flags=${flags}q return 0 fi if ((wtype==_ble_ctx_CMDI)); then ble/alias#expand "$word" [[ $word != $ret ]] && return 0 fi ret=$word } function ble/widget/shell-expand-line.proc { [[ $wtype ]] || return 0 if [[ ${wtype//[0-9]} ]]; then ble/syntax/tree-enumerate-children ble/widget/shell-expand-line.proc return 0 fi local word=${_ble_edit_str:wbegin:wlen} local rex='^[_a-zA-Z][_a-zA-Z0-9]*=+?\(' if ((wtype==_ble_attr_VAR)) && [[ $word =~ $rex ]]; then ble/syntax/tree-enumerate-children ble/widget/shell-expand-line.proc return 0 fi local flags= local -a ret=() words=() ble/widget/shell-expand-line.expand-word "$word" words=("${ret[@]}") [[ ${#words[@]} -eq 1 && $word == "$ret" ]] && return 0 if ((wtype==_ble_ctx_RDRF||wtype==_ble_ctx_RDRD||wtype==_ble_ctx_RDRS)); then local IFS=$_ble_term_IFS words=("${words[*]}") fi local q=\' Q="'\''" specialchars='\ ["'\''`$|&;<>()*?!^{,}' local w index=0 out= for w in "${words[@]}"; do ((index++)) && out=$out' ' [[ $flags == *q* && $w == *["$specialchars"]* ]] && w=$q${w//$q/$Q}$q out=$out$w done changed=1 ble/widget/.replace-range "$wbegin" "$((wbegin+wlen))" "$out" } function ble/widget/shell-expand-line { local opts=:$1: ble-edit/content/clear-arg ble/widget/history-expand-line ble-edit/content/update-syntax local iN= changed= ble/syntax/tree-enumerate ble/widget/shell-expand-line.proc [[ $changed ]] && _ble_edit_mark_active= } _ble_edit_undo=() _ble_edit_undo_index=0 _ble_edit_undo_history=() _ble_edit_undo_hindex= ble/array#push _ble_textarea_local_VARNAMES \ _ble_edit_undo \ _ble_edit_undo_index \ _ble_edit_undo_history \ _ble_edit_undo_hindex function ble-edit/undo/.check-hindex { local hindex; ble/history/get-index -v hindex [[ $_ble_edit_undo_hindex == "$hindex" ]] && return 0 if [[ $_ble_edit_undo_hindex ]]; then local uindex=${_ble_edit_undo_index:-${#_ble_edit_undo[@]}} local ret; ble/string#quote-words "$uindex" "${_ble_edit_undo[@]}" _ble_edit_undo_history[_ble_edit_undo_hindex]=$ret fi if [[ ${_ble_edit_undo_history[hindex]} ]]; then local data; builtin eval -- "data=(${_ble_edit_undo_history[hindex]})" _ble_edit_undo=("${data[@]:1}") _ble_edit_undo_index=${data[0]} else _ble_edit_undo=() _ble_edit_undo_index=0 fi _ble_edit_undo_hindex=$hindex } function ble-edit/undo/clear-all { _ble_edit_undo=() _ble_edit_undo_index=0 _ble_edit_undo_history=() _ble_edit_undo_hindex= } function ble-edit/undo/history-change.hook { local kind=$1; shift case $kind in (delete) ble/builtin/history/array#delete-hindex _ble_edit_undo_history "$@" _ble_edit_undo_hindex= ;; (clear) ble-edit/undo/clear-all ;; (insert) ble/builtin/history/array#insert-range _ble_edit_undo_history "$@" local beg=$1 len=$2 [[ $_ble_edit_undo_hindex ]] && ((_ble_edit_undo_hindex>=beg)) && ((_ble_edit_undo_hindex+=len)) ;; esac } blehook history_change!=ble-edit/undo/history-change.hook function ble-edit/undo/.get-current-state { if ((_ble_edit_undo_index==0)); then str= if [[ $_ble_history_prefix || $_ble_history_load_done ]]; then local index; ble/history/get-index ble/history/get-entry -v str "$index" fi ind=${#entry} else local entry=${_ble_edit_undo[_ble_edit_undo_index-1]} str=${entry#*:} ind=${entry%%:*} fi } function ble-edit/undo/add { ble-edit/undo/.check-hindex local str ind; ble-edit/undo/.get-current-state [[ $str == "$_ble_edit_str" ]] && return 0 _ble_edit_undo[_ble_edit_undo_index++]=$_ble_edit_ind:$_ble_edit_str if ((${#_ble_edit_undo[@]}>_ble_edit_undo_index)); then _ble_edit_undo=("${_ble_edit_undo[@]::_ble_edit_undo_index}") fi } function ble-edit/undo/.load { local str ind; ble-edit/undo/.get-current-state if [[ $bleopt_undo_point == end || $bleopt_undo_point == beg ]]; then local old=$_ble_edit_str new=$str ret if [[ $bleopt_undo_point == end ]]; then ble/string#common-suffix "${old:_ble_edit_ind}" "$new"; local s1=${#ret} local old=${old::${#old}-s1} new=${new::${#new}-s1} ble/string#common-prefix "${old::_ble_edit_ind}" "$new"; local p1=${#ret} local old=${old:p1} new=${new:p1} ble/string#common-suffix "$old" "$new"; local s2=${#ret} local old=${old::${#old}-s2} new=${new::${#new}-s2} ble/string#common-prefix "$old" "$new"; local p2=${#ret} else ble/string#common-prefix "${old::_ble_edit_ind}" "$new"; local p1=${#ret} local old=${old:p1} new=${new:p1} ble/string#common-suffix "${old:_ble_edit_ind-p1}" "$new"; local s1=${#ret} local old=${old::${#old}-s1} new=${new::${#new}-s1} ble/string#common-prefix "$old" "$new"; local p2=${#ret} local old=${old:p2} new=${new:p2} ble/string#common-suffix "$old" "$new"; local s2=${#ret} fi local beg=$((p1+p2)) end0=$((${#_ble_edit_str}-s1-s2)) end=$((${#str}-s1-s2)) ble-edit/content/replace "$beg" "$end0" "${str:beg:end-beg}" if [[ $bleopt_undo_point == end ]]; then ind=$end else ind=$beg fi else ble-edit/content/reset-and-check-dirty "$str" fi _ble_edit_ind=$ind return 0 } function ble-edit/undo/undo { local arg=${1:-1} ble-edit/undo/.check-hindex ble-edit/undo/add # 最後に add/load してから変更があれば記録 ((_ble_edit_undo_index)) || return 1 ((_ble_edit_undo_index-=arg)) ((_ble_edit_undo_index<0&&(_ble_edit_undo_index=0))) ble-edit/undo/.load } function ble-edit/undo/redo { local arg=${1:-1} ble-edit/undo/.check-hindex ble-edit/undo/add # 最後に add/load してから変更があれば記録 local ucount=${#_ble_edit_undo[@]} ((_ble_edit_undo_index=ucount&&(_ble_edit_undo_index=ucount))) ble-edit/undo/.load } function ble-edit/undo/revert { ble-edit/undo/.check-hindex ble-edit/undo/add # 最後に add/load してから変更があれば記録 ((_ble_edit_undo_index)) || return 1 ((_ble_edit_undo_index=0)) ble-edit/undo/.load } function ble-edit/undo/revert-toggle { local arg=${1:-1} ((arg%2==0)) && return 0 ble-edit/undo/.check-hindex ble-edit/undo/add # 最後に add/load してから変更があれば記録 if ((_ble_edit_undo_index)); then ((_ble_edit_undo_index=0)) ble-edit/undo/.load elif ((${#_ble_edit_undo[@]})); then ((_ble_edit_undo_index=${#_ble_edit_undo[@]})) ble-edit/undo/.load else return 1 fi } _ble_edit_kbdmacro_record= _ble_edit_kbdmacro_last=() _ble_edit_kbdmacro_onplay= function ble/widget/start-keyboard-macro { ble/keymap:generic/clear-arg [[ $_ble_edit_kbdmacro_onplay ]] && return 0 # 再生中は無視 if ! ble/decode/charlog#start kbd-macro; then if [[ $_ble_decode_keylog_chars_enabled == kbd-macro ]]; then ble/widget/.bell 'kbd-macro: recording is already started' else ble/widget/.bell 'kbd-macro: the logging system is currently busy' fi return 1 fi _ble_edit_kbdmacro_record=1 if [[ $_ble_decode_keymap == emacs ]]; then ble/keymap:emacs/update-mode-indicator elif [[ $_ble_decode_keymap == vi_nmap ]]; then ble/keymap:vi/adjust-command-mode fi return 0 } function ble/widget/end-keyboard-macro { ble/keymap:generic/clear-arg [[ $_ble_edit_kbdmacro_onplay ]] && return 0 # 再生中は無視 if [[ $_ble_decode_keylog_chars_enabled != kbd-macro ]]; then ble/widget/.bell 'kbd-macro: recording is not running' return 1 fi _ble_edit_kbdmacro_record= ble/decode/charlog#end-exclusive-depth1 _ble_edit_kbdmacro_last=("${ret[@]}") if [[ $_ble_decode_keymap == emacs ]]; then ble/keymap:emacs/update-mode-indicator elif [[ $_ble_decode_keymap == vi_nmap ]]; then ble/keymap:vi/adjust-command-mode fi return 0 } function ble/widget/call-keyboard-macro { local arg; ble-edit/content/get-arg 1 ble/keymap:generic/clear-arg ((arg>0)) || return 1 [[ $_ble_edit_kbdmacro_onplay ]] && return 0 # 再生中は無視 local _ble_edit_kbdmacro_onplay=1 if ((arg==1)); then ble/widget/.MACRO "${_ble_edit_kbdmacro_last[@]}" else local -a chars=() while ((arg-->0)); do ble/array#push chars "${_ble_edit_kbdmacro_last[@]}" done ble/widget/.MACRO "${chars[@]}" fi [[ $_ble_decode_keymap == vi_nmap ]] && ble/keymap:vi/adjust-command-mode } function ble/widget/print-keyboard-macro { ble/keymap:generic/clear-arg local ret; ble/decode/charlog#encode "${_ble_edit_kbdmacro_last[@]}" ble/edit/info/show text "kbd-macro: $ret" [[ $_ble_decode_keymap == vi_nmap ]] && ble/keymap:vi/adjust-command-mode return 0 } bleopt/declare -v history_preserve_point '' function ble-edit/history/goto { ble/history/initialize local histlen=$_ble_history_COUNT local index0=$_ble_history_INDEX local index1=$1 ((index0==index1)) && return 0 if ((index1>histlen)); then index1=$histlen ble/widget/.bell elif ((index1<0)); then index1=0 ble/widget/.bell fi ((index0==index1)) && return 0 if [[ $bleopt_history_share && ! $_ble_history_prefix && $_ble_decode_keymap != isearch ]]; then if ((index0==histlen||index1==histlen)); then ble/builtin/history/option:n local histlen2=$_ble_history_COUNT if ((histlen!=histlen2)); then ble/textarea#invalidate ble-edit/history/goto "$((index1==histlen?histlen:index1))" return "$?" fi fi fi ble/history/set-edited-entry "$index0" "$_ble_edit_str" ble/history/onleave.fire ble/history/set-index "$index1" local entry; ble/history/get-edited-entry -v entry "$index1" ble-edit/content/reset "$entry" history if [[ $bleopt_history_preserve_point ]]; then if ((_ble_edit_ind>${#_ble_edit_str})); then _ble_edit_ind=${#_ble_edit_str} fi else if ((index1=0)); then ((beg=end=start)) return 0 fi fi fi elif [[ :$opts: == *:B:* ]]; then local start=$((has_extend?_ble_edit_ind:_ble_edit_ind-1)) ((start<0)) && return 1 if ((has_regex)); then ble-edit/isearch/.shift-backward-references local rex="^.{0,$start}($needle)" ((start==0)) && rex="^($needle)" if ble-edit/isearch/search/.match "$_ble_edit_str" "$rex"; then local rematch1=${BASH_REMATCH[1]} if [[ $rematch1 || :$opts: == *:allow_empty:* ]]; then ((end=${#BASH_REMATCH}, beg=end-${#rematch1})) return 0 else flag_empty_retry=1 fi fi else if [[ $needle ]]; then ble-edit/isearch/search/.last-index "${_ble_edit_str::start+${#needle}}" "$needle" && return 0 else if [[ :$opts: == *:allow_empty:* ]] && ((--start>=0)); then ((beg=end=start)) return 0 fi fi fi else local start=$((has_extend?_ble_edit_mark:_ble_edit_ind)) if ((has_regex)); then ble-edit/isearch/.shift-backward-references local rex="($needle).*\$" ((start)) && rex=".{$start}$rex" if ble-edit/isearch/search/.match "$_ble_edit_str" "$rex"; then local rematch1=${BASH_REMATCH[1]} if [[ $rematch1 || :$opts: == *:allow_empty:* ]]; then ((beg=${#_ble_edit_str}-${#BASH_REMATCH}+start)) ((end=beg+${#rematch1})) return 0 else flag_empty_retry=1 fi fi else if [[ $needle ]]; then ble-edit/isearch/search/.index "$_ble_edit_str" "$needle" "$start" && return 0 else if [[ :$opts: == *:allow_empty:* ]] || ((++start<=${#_ble_edit_str})); then ((beg=end=start)) return 0 fi fi fi fi if [[ $flag_empty_retry ]]; then if [[ :$opts: == *:[-B]:* ]]; then if ((--start>=0)); then local mark=$_ble_edit_mark; ((mark&&mark--)) local ind=$_ble_edit_ind; ((ind&&ind--)) opts=$opts:allow_empty _ble_edit_mark=$mark _ble_edit_ind=$ind ble-edit/isearch/search "$needle" "$opts" return 0 fi else if ((++start<=${#_ble_edit_str})); then local mark=$_ble_edit_mark; ((mark<${#_ble_edit_str}&&mark++)) local ind=$_ble_edit_ind; ((ind<${#_ble_edit_str}&&ind++)) opts=$opts:allow_empty _ble_edit_mark=$mark _ble_edit_ind=$ind ble-edit/isearch/search "$needle" "$opts" return 0 fi fi fi return 1 } function ble-edit/isearch/.shift-backward-references { local rex_cc='\[[@][^]@]+[@]\]' # [:space:] [=a=] [.a.] など。 local rex_bracket_expr='\[\^?]?('${rex_cc//@/:}'|'${rex_cc//@/=}'|'${rex_cc//@/.}'|[^][]|\[[^]:=.])*\[?\]' local rex='^('$rex_bracket_expr'|\\[^1-8])*\\[1-8]' local buff= while [[ $needle =~ $rex ]]; do local mlen=${#BASH_REMATCH} buff=$buff${BASH_REMATCH::mlen-1}$((10#0${BASH_REMATCH:mlen-1}+1)) needle=${needle:mlen} done needle=$buff$needle } _ble_edit_isearch_opts= _ble_edit_isearch_str= _ble_edit_isearch_dir=- _ble_edit_isearch_arr=() _ble_edit_isearch_old= function ble-edit/isearch/status/append-progress-bar { ble/util/is-unicode-output || return 1 local pos=$1 count=$2 dir=$3 [[ :$dir: == *:-:* || :$dir: == *:backward:* ]] && ((pos=count-1-pos)) local ret; ble/string#create-unicode-progress-bar "$pos" "$count" 5 text=$text$' \e[1;38;5;69;48;5;253m'$ret$'\e[m ' } function ble-edit/isearch/.show-status-with-progress.fib { local ll rr if [[ $_ble_edit_isearch_dir == - ]]; then ll=\<\< rr=" " else ll=" " rr=">>" fi local index; ble/history/get-index local histIndex='!'$((index+1)) local text="(${#_ble_edit_isearch_arr[@]}: $ll $histIndex $rr) \`$_ble_edit_isearch_str'" if [[ $1 ]]; then local pos=$1 local count; ble/history/get-count text=$text' searching...' ble-edit/isearch/status/append-progress-bar "$pos" "$count" "$_ble_edit_isearch_dir" local percentage=$((count?pos*1000/count:1000)) text=$text" @$pos ($((percentage/10)).$((percentage%10))%)" fi ((fib_ntask)) && text="$text *$fib_ntask" ble/edit/info/show ansi "$text" } function ble-edit/isearch/.show-status.fib { ble-edit/isearch/.show-status-with-progress.fib } function ble-edit/isearch/show-status { local fib_ntask=${#_ble_util_fiberchain[@]} ble-edit/isearch/.show-status.fib } function ble-edit/isearch/erase-status { ble/edit/info/default } function ble-edit/isearch/.set-region { local beg=$1 end=$2 if ((beg=0)) && [[ ${_ble_edit_isearch_arr[ilast]} == "$ind:"[-+]":$hash" ]]; then builtin unset -v "_ble_edit_isearch_arr[$ilast]" return 0 fi local oind; ble/history/get-index -v oind local obeg=$_ble_edit_ind oend=$_ble_edit_mark [[ $_ble_edit_mark_active ]] || oend=$obeg ((obeg>oend)) && local obeg=$oend oend=$obeg local oneedle=$_ble_edit_isearch_str local ohash=$obeg:$oend:$oneedle [[ $ind == "$oind" && $hash == "$ohash" ]] && return 0 ble/array#push _ble_edit_isearch_arr "$oind:$_ble_edit_isearch_dir:$ohash" } function ble-edit/isearch/.goto-match.fib { local ind=$1 beg=$2 end=$3 needle=$4 ble-edit/isearch/.push-isearch-array _ble_edit_isearch_str=$needle [[ $needle ]] && _ble_edit_isearch_old=$needle local oind; ble/history/get-index -v oind ((oind!=ind)) && ble-edit/history/goto "$ind" ble-edit/isearch/.set-region "$beg" "$end" ble-edit/isearch/.show-status.fib ble/textarea#redraw } function ble-edit/isearch/.next.fib { local opts=$1 if [[ ! $fib_suspend ]]; then if [[ :$opts: == *:forward:* || :$opts: == *:backward:* ]]; then if [[ :$opts: == *:forward:* ]]; then _ble_edit_isearch_dir=+ else _ble_edit_isearch_dir=- fi fi local needle=${2-$_ble_edit_isearch_str} local beg= end= search_opts=$_ble_edit_isearch_dir if [[ :$opts: == *:append:* ]]; then search_opts=$search_opts:extend ble/path#remove opts append fi [[ :$opts: == *:ignore-case:* ]] && search_opts=$search_opts:ignore-case if [[ $needle ]] && ble-edit/isearch/search "$needle" "$search_opts"; then local ind; ble/history/get-index -v ind ble-edit/isearch/.goto-match.fib "$ind" "$beg" "$end" "$needle" return 0 fi fi ble-edit/isearch/.next-history.fib "$opts" "$needle" } function ble-edit/isearch/.next-history.fib { local opts=$1 if [[ $fib_suspend ]]; then local needle=${fib_suspend#*:} isAdd= local index start; builtin eval -- "${fib_suspend%%:*}" fib_suspend= else local needle=${2-$_ble_edit_isearch_str} isAdd= [[ :$opts: == *:append:* ]] && isAdd=1 ble/history/initialize local start=$_ble_history_INDEX local index=$start fi if ((!isAdd)); then if [[ $_ble_edit_isearch_dir == - ]]; then ((index--)) else ((index++)) fi fi local isearch_progress_callback=ble-edit/isearch/.show-status-with-progress.fib local isearch_opts=stop_check:progress [[ :$opts: == *:ignore-case:* ]] && isearch_opts=$isearch_opts:ignore-case if [[ $_ble_edit_isearch_dir == - ]]; then ble/history/isearch-backward-blockwise "$isearch_opts" else ble/history/isearch-forward "$isearch_opts" fi local ext=$? if ((ext==0)); then local str; ble/history/get-edited-entry -v str "$index" if [[ $needle ]]; then local ndl=$needle if [[ :$opts: == *:ignore-case:* ]]; then local ret ble/string#tolower "$str"; str=$ret ble/string#tolower "$ndl"; ndl=$ret fi if [[ $_ble_edit_isearch_dir == - ]]; then local prefix=${str%"$ndl"*} else local prefix=${str%%"$ndl"*} fi local beg=${#prefix} end=$((${#prefix}+${#ndl})) else local beg=${#str} end=${#str} fi ble-edit/isearch/.goto-match.fib "$index" "$beg" "$end" "$needle" elif ((ext==148)); then fib_suspend="index=$index start=$start:$needle" return 0 else ble/widget/.bell "isearch: \`$needle' not found" return 0 fi } function ble-edit/isearch/forward.fib { if [[ ! $_ble_edit_isearch_str ]]; then ble-edit/isearch/.next.fib "$_ble_edit_isearch_opts:forward" "$_ble_edit_isearch_old" else ble-edit/isearch/.next.fib "$_ble_edit_isearch_opts:forward" fi } function ble-edit/isearch/backward.fib { if [[ ! $_ble_edit_isearch_str ]]; then ble-edit/isearch/.next.fib "$_ble_edit_isearch_opts:backward" "$_ble_edit_isearch_old" else ble-edit/isearch/.next.fib "$_ble_edit_isearch_opts:backward" fi } function ble-edit/isearch/self-insert.fib { local needle= if [[ ! $fib_suspend ]]; then local code=$1 ((code==0)) && return 0 local ret; ble/util/c2s "$code" needle=$_ble_edit_isearch_str$ret fi ble-edit/isearch/.next.fib "$_ble_edit_isearch_opts:append" "$needle" } function ble-edit/isearch/insert-string.fib { local needle= [[ ! $fib_suspend ]] && needle=$_ble_edit_isearch_str$1 ble-edit/isearch/.next.fib "$_ble_edit_isearch_opts:append" "$needle" } function ble-edit/isearch/history-forward.fib { _ble_edit_isearch_dir=+ ble-edit/isearch/.next-history.fib "$_ble_edit_isearch_opts" } function ble-edit/isearch/history-backward.fib { _ble_edit_isearch_dir=- ble-edit/isearch/.next-history.fib "$_ble_edit_isearch_opts" } function ble-edit/isearch/history-self-insert.fib { local needle= if [[ ! $fib_suspend ]]; then local code=$1 ((code==0)) && return 0 local ret; ble/util/c2s "$code" needle=$_ble_edit_isearch_str$ret fi ble-edit/isearch/.next-history.fib "$_ble_edit_isearch_opts:append" "$needle" } function ble-edit/isearch/prev { local sz=${#_ble_edit_isearch_arr[@]} ((sz==0)) && return 0 local ilast=$((sz-1)) local top=${_ble_edit_isearch_arr[ilast]} builtin unset -v '_ble_edit_isearch_arr[ilast]' local ind dir beg end ind=${top%%:*}; top=${top#*:} dir=${top%%:*}; top=${top#*:} beg=${top%%:*}; top=${top#*:} end=${top%%:*}; top=${top#*:} _ble_edit_isearch_dir=$dir ble-edit/history/goto "$ind" ble-edit/isearch/.set-region "$beg" "$end" _ble_edit_isearch_str=$top [[ $top ]] && _ble_edit_isearch_old=$top ble-edit/isearch/show-status } function ble-edit/isearch/process { local isearch_time=0 ble/util/fiberchain#resume ble-edit/isearch/show-status } function ble/widget/isearch/forward { ble/util/fiberchain#push forward ble-edit/isearch/process } function ble/widget/isearch/backward { ble/util/fiberchain#push backward ble-edit/isearch/process } function ble/widget/isearch/self-insert { local code; ble/widget/self-insert/.get-code ((code==0)) && return 0 ble/util/fiberchain#push "self-insert $code" ble-edit/isearch/process } function ble/widget/isearch/history-forward { ble/util/fiberchain#push history-forward ble-edit/isearch/process } function ble/widget/isearch/history-backward { ble/util/fiberchain#push history-backward ble-edit/isearch/process } function ble/widget/isearch/history-self-insert { local code; ble/widget/self-insert/.get-code ((code==0)) && return 0 ble/util/fiberchain#push "history-self-insert $code" ble-edit/isearch/process } function ble/widget/isearch/prev { local nque if ((nque=${#_ble_util_fiberchain[@]})); then local ret; ble/array#pop _ble_util_fiberchain ble-edit/isearch/process else ble-edit/isearch/prev fi } function ble/widget/isearch/.restore-mark-state { local old_mark_active=${_ble_edit_isearch_save[3]} if [[ $old_mark_active ]]; then local index; ble/history/get-index if ((index==_ble_edit_isearch_save[0])); then _ble_edit_mark=${_ble_edit_isearch_save[2]} if [[ $old_mark_active != S ]] || ((_ble_edit_ind==_ble_edit_isearch_save[1])); then _ble_edit_mark_active=$old_mark_active fi fi fi } function ble/widget/isearch/exit.impl { ble/decode/keymap/pop _ble_edit_isearch_arr=() _ble_edit_isearch_dir= _ble_edit_isearch_str= ble-edit/isearch/erase-status } function ble/widget/isearch/exit-with-region { ble/widget/isearch/exit.impl if [[ $_ble_edit_mark_active ]]; then _ble_edit_mark_active=S ble/decode/keymap/push selection fi } function ble/widget/isearch/exit { ble/widget/isearch/exit.impl _ble_edit_mark_active= ble/widget/isearch/.restore-mark-state } function ble/widget/isearch/cancel { if ((${#_ble_util_fiberchain[@]})); then ble/util/fiberchain#clear ble-edit/isearch/show-status # 進捗状況だけ消去 else if ((${#_ble_edit_isearch_arr[@]})); then local step ble/string#split step : "${_ble_edit_isearch_arr[0]}" ble-edit/history/goto "${step[0]}" fi ble/widget/isearch/exit.impl _ble_edit_ind=${_ble_edit_isearch_save[1]} _ble_edit_mark=${_ble_edit_isearch_save[2]} _ble_edit_mark_active=${_ble_edit_isearch_save[3]} fi } function ble/widget/isearch/exit-default { ble/widget/isearch/exit-with-region ble/decode/widget/redispatch } function ble/widget/isearch/accept-line { if ((${#_ble_util_fiberchain[@]})); then ble/widget/.bell "isearch: now searching..." else ble/widget/isearch/exit ble-decode-key 13 # RET fi } function ble/widget/isearch/exit-delete-forward-char { ble/widget/isearch/exit ble/widget/delete-forward-char } function ble/widget/history-isearch.impl { local opts=$1 ble/keymap:generic/clear-arg ble/decode/keymap/push isearch ble/util/fiberchain#initialize ble-edit/isearch local index; ble/history/get-index _ble_edit_isearch_save=("$index" "$_ble_edit_ind" "$_ble_edit_mark" "$_ble_edit_mark_active") _ble_edit_isearch_opts= ble/util/rlvar#test search-ignore-case 0 && _ble_edit_isearch_opts=ignore-case if [[ :$opts: == *:forward:* ]]; then _ble_edit_isearch_dir=+ else _ble_edit_isearch_dir=- fi _ble_edit_isearch_arr=() _ble_edit_mark=$_ble_edit_ind ble-edit/isearch/show-status } function ble/widget/history-isearch-backward { ble/widget/history-isearch.impl backward } function ble/widget/history-isearch-forward { ble/widget/history-isearch.impl forward } function ble-decode/keymap:isearch/define { ble-bind -f __defchar__ isearch/self-insert ble-bind -f __line_limit__ nop ble-bind -f C-r isearch/backward ble-bind -f C-s isearch/forward ble-bind -f 'C-?' isearch/prev ble-bind -f 'DEL' isearch/prev ble-bind -f 'C-h' isearch/prev ble-bind -f 'BS' isearch/prev ble-bind -f __default__ isearch/exit-default ble-bind -f 'C-g' isearch/cancel ble-bind -f 'C-x C-g' isearch/cancel ble-bind -f 'C-M-g' isearch/cancel ble-bind -f C-m isearch/exit ble-bind -f RET isearch/exit ble-bind -f C-j isearch/accept-line ble-bind -f C-RET isearch/accept-line } _ble_edit_nsearch_input= _ble_edit_nsearch_needle= _ble_edit_nsearch_index0= _ble_edit_nsearch_opts= _ble_edit_nsearch_stack=() _ble_edit_nsearch_match= _ble_edit_nsearch_index= _ble_edit_nsearch_prev= function ble/highlight/layer:region/mark:nsearch/get-face { face=region_match } function ble/highlight/layer:region/mark:nsearch/get-selection { local beg=$_ble_edit_mark local end=$((_ble_edit_mark+${#_ble_edit_nsearch_needle})) selection=("$beg" "$end") } function ble-edit/nsearch/.show-status.fib { [[ :$_ble_edit_nsearch_opts: == *:hide-status:* ]] && return 0 local ll=\<\< rr=">>" # Note: Emacs workaround: '<<' や "<<" と書けない。 local match=$_ble_edit_nsearch_match index0=$_ble_edit_nsearch_index0 if ((match>index0)); then ll=" " elif ((match=2)); then local record_type=${_ble_edit_nsearch_stack[nstack-1]%%,*} if if [[ $opt_forward ]]; then [[ $record_type == backward ]] else [[ $record_type == forward ]] fi then local ret; ble/array#pop _ble_edit_nsearch_stack local record line=${ret#*:} ble/string#split record , "${ret%%:*}" if [[ :$opts: == *:action=load:* ]]; then ble-edit/content/reset-and-check-dirty "$line" else ble-edit/history/goto "${record[1]}" fi _ble_edit_nsearch_match=${record[1]} _ble_edit_nsearch_index=${record[1]} _ble_edit_ind=${record[2]} _ble_edit_mark=${record[3]} if ((_ble_edit_mark!=_ble_edit_ind)); then _ble_edit_mark_active=nsearch else _ble_edit_mark_active= fi ble-edit/nsearch/.show-status.fib ble/textarea#redraw fib_suspend= return 0 fi fi local index start opt_resume= if [[ $fib_suspend ]]; then opt_resume=1 builtin eval -- "$fib_suspend" fib_suspend= else local index=$_ble_edit_nsearch_index if ((nstack==1)); then local index0=$_ble_edit_nsearch_index0 ((opt_forward?indexindex0)) && index=$index0 fi local start=$index fi local needle=$_ble_edit_nsearch_needle if if [[ $opt_forward ]]; then local count; ble/history/get-count [[ $opt_resume ]] || ((++index)) ((index<=count)) else [[ $opt_resume ]] || ((--index)) ((index>=0)) fi then local isearch_time=$fib_clock local isearch_progress_callback=ble-edit/nsearch/.show-status.fib local isearch_opts=stop_check:progress [[ :$opts: != *:substr:* ]] && isearch_opts=$isearch_opts:head [[ :$opts: == *:ignore-case:* ]] && isearch_opts=$isearch_opts:ignore-case if [[ $opt_forward ]]; then ble/history/isearch-forward "$isearch_opts"; local ext=$? else ble/history/isearch-backward-blockwise "$isearch_opts"; local ext=$? fi fib_clock=$isearch_time else local ext=1 fi if ((ext==0)); then ble-edit/nsearch/.goto-match "$index" "$opts" ble-edit/nsearch/.show-status.fib ble/textarea#redraw elif ((ext==148)); then fib_suspend="index=$index start=$start" return 148 else ble/widget/.bell "ble.sh: nsearch: '$needle' not found" ble-edit/nsearch/.show-status.fib if [[ $opt_forward ]]; then local count; ble/history/get-count ((_ble_edit_nsearch_index=count-1)) else ((_ble_edit_nsearch_index=0)) fi return "$ext" fi } function ble-edit/nsearch/forward.fib { ble-edit/nsearch/.search.fib "$_ble_edit_nsearch_opts:forward" } function ble-edit/nsearch/backward.fib { ble-edit/nsearch/.search.fib "$_ble_edit_nsearch_opts:backward" } function ble-edit/nsearch/.test { local str=$1 ndl=$2 opts=$3 [[ :$opts: == *:ignore-case:* ]] && shopt -s nocasematch if [[ :$opts: == *:substr:* ]]; then [[ $str == *"$ndl"* ]] else [[ $str == "$ndl"* ]] fi; local ext=$? shopt -u nocasematch return "$ext" } function ble/widget/history-search { local opts=$1 if [[ :$opts: == *:input:* || :$opts: == *:again:* && ! $_ble_edit_nsearch_input ]]; then ble/builtin/read -ep "nsearch> " _ble_edit_nsearch_needle || return 1 _ble_edit_nsearch_input=$_ble_edit_nsearch_needle elif [[ :$opts: == *:again:* ]]; then _ble_edit_nsearch_needle=$_ble_edit_nsearch_input else local len=$_ble_edit_ind if [[ $_ble_decode_keymap == vi_[noxs]map ]]; then ble-edit/content/eolp || ((len++)) fi _ble_edit_nsearch_needle=${_ble_edit_str::len} fi if [[ ! $_ble_edit_nsearch_needle ]]; then local empty=empty-search local rex='.*:empty=([^:]*):' [[ :$opts: =~ $rex ]] && empty=${BASH_REMATCH[1]} case $empty in (history-move) if [[ :$opts: == *:forward:* ]]; then ble/widget/history-next else ble/widget/history-prev fi && _ble_edit_ind=0 return "$?" ;; (hide-status) opts=$opts:hide-status ;; (emulate-readline) opts=hide-status:point=end:immediate-accept:$opts ;; (previous-search) _ble_edit_nsearch_needle=$_ble_edit_nsearch_prev ;; esac fi _ble_edit_nsearch_prev=$_ble_edit_nsearch_needle ble/keymap:generic/clear-arg [[ :$opts: != *:ignore-case:* && :$opts: != *:match-case:* ]] && ble/util/rlvar#test search-ignore-case 0 && opts=$opts:ignore-case _ble_edit_nsearch_stack=() local index; ble/history/get-index _ble_edit_nsearch_index0=$index _ble_edit_nsearch_opts=$opts ble/path#remove _ble_edit_nsearch_opts forward ble/path#remove _ble_edit_nsearch_opts backward _ble_edit_nsearch_match=$index _ble_edit_nsearch_index=$index _ble_edit_mark_active= ble/decode/keymap/push nsearch if ble-edit/nsearch/.test "$_ble_edit_str" "$_ble_edit_nsearch_needle" "$opts"; then ble-edit/nsearch/.goto-match '' "$opts" fi ble/util/fiberchain#initialize ble-edit/nsearch if [[ :$opts: == *:forward:* ]]; then ble/util/fiberchain#push forward else ble/util/fiberchain#push backward fi ble/util/fiberchain#resume } function ble/widget/history-nsearch-backward { ble/widget/history-search "input:substr:backward:$1" } function ble/widget/history-nsearch-forward { ble/widget/history-search "input:substr:forward:$1" } function ble/widget/history-nsearch-backward-again { ble/widget/history-search "again:substr:backward:$1" } function ble/widget/history-nsearch-forward-again { ble/widget/history-search "again:substr:forward:$1" } function ble/widget/history-search-backward { ble/widget/history-search "backward:$1" } function ble/widget/history-search-forward { ble/widget/history-search "forward:$1" } function ble/widget/history-substring-search-backward { ble/widget/history-search "substr:backward:$1" } function ble/widget/history-substring-search-forward { ble/widget/history-search "substr:forward:$1" } function ble/widget/nsearch/forward { local ntask=${#_ble_util_fiberchain[@]} if ((ntask>=1)) && [[ ${_ble_util_fiberchain[ntask-1]%%:*} == backward ]]; then local ret; ble/array#pop _ble_util_fiberchain else ble/util/fiberchain#push forward fi ble/util/fiberchain#resume } function ble/widget/nsearch/backward { local ntask=${#_ble_util_fiberchain[@]} if ((ntask>=1)) && [[ ${_ble_util_fiberchain[ntask-1]%%:*} == forward ]]; then local ret; ble/array#pop _ble_util_fiberchain else ble/util/fiberchain#push backward fi ble/util/fiberchain#resume } function ble/widget/nsearch/.exit { ble/decode/keymap/pop _ble_edit_mark_active= ble-edit/nsearch/erase-status } function ble/widget/nsearch/exit { if [[ :$_ble_edit_nsearch_opts: == *:immediate-accept:* ]]; then ble/widget/nsearch/accept-line else ble/widget/nsearch/.exit fi } function ble/widget/nsearch/exit-default { ble/widget/nsearch/.exit ble/decode/widget/redispatch } function ble/widget/nsearch/cancel { if ((${#_ble_util_fiberchain[@]})); then ble/util/fiberchain#clear ble-edit/nsearch/show-status else ble/widget/nsearch/.exit local record=${_ble_edit_nsearch_stack[0]} if [[ $record ]]; then local line=${record#*:} ble/string#split record , "${record%%:*}" if [[ :$_ble_edit_nsearch_opts: == *:action=load:* ]]; then ble-edit/content/reset-and-check-dirty "$line" else ble-edit/history/goto "$_ble_edit_nsearch_index0" fi _ble_edit_ind=${record[2]} _ble_edit_mark=${record[3]} fi fi } function ble/widget/nsearch/accept-line { if ((${#_ble_util_fiberchain[@]})); then ble/widget/.bell "nsearch: now searching..." else ble/widget/nsearch/.exit ble-decode-key 13 # RET fi } function ble-decode/keymap:nsearch/define { ble-bind -f __default__ nsearch/exit-default ble-bind -f __line_limit__ nop ble-bind -f 'C-g' nsearch/cancel ble-bind -f 'C-x C-g' nsearch/cancel ble-bind -f 'C-M-g' nsearch/cancel ble-bind -f C-m nsearch/exit ble-bind -f RET nsearch/exit ble-bind -f C-j nsearch/accept-line ble-bind -f C-RET nsearch/accept-line ble-bind -f C-r nsearch/backward ble-bind -f C-s nsearch/forward ble-bind -f C-p nsearch/backward ble-bind -f C-n nsearch/forward ble-bind -f up nsearch/backward ble-bind -f down nsearch/forward ble-bind -f prior nsearch/backward ble-bind -f next nsearch/forward } function ble-decode/keymap:safe/.bind { [[ $ble_bind_nometa && $1 == *M-* ]] && return 0 ble-bind -f "$1" "$2" } function ble-decode/keymap:safe/bind-common { ble-decode/keymap:safe/.bind insert 'overwrite-mode' ble-decode/keymap:safe/.bind __batch_char__ 'batch-insert' ble-decode/keymap:safe/.bind __defchar__ 'self-insert' ble-decode/keymap:safe/.bind 'C-q' 'quoted-insert' ble-decode/keymap:safe/.bind 'C-v' 'quoted-insert' ble-decode/keymap:safe/.bind 'M-C-m' 'newline' ble-decode/keymap:safe/.bind 'M-RET' 'newline' ble-decode/keymap:safe/.bind paste_begin 'bracketed-paste' ble-decode/keymap:safe/.bind 'C-@' 'set-mark' ble-decode/keymap:safe/.bind 'C-SP' 'set-mark' ble-decode/keymap:safe/.bind 'NUL' 'set-mark' ble-decode/keymap:safe/.bind 'M-SP' 'set-mark' ble-decode/keymap:safe/.bind 'C-x C-x' 'exchange-point-and-mark' ble-decode/keymap:safe/.bind 'C-w' 'kill-region-or kill-backward-uword' ble-decode/keymap:safe/.bind 'M-w' 'copy-region-or copy-backward-uword' ble-decode/keymap:safe/.bind 'C-y' 'yank' ble-decode/keymap:safe/.bind 'M-y' 'yank-pop' ble-decode/keymap:safe/.bind 'M-S-y' 'yank-pop backward' ble-decode/keymap:safe/.bind 'M-Y' 'yank-pop backward' ble-decode/keymap:safe/.bind 'S-delete' 'kill-region-or kill-backward-uword' ble-decode/keymap:safe/.bind 'C-insert' 'copy-region-or copy-backward-uword' ble-decode/keymap:safe/.bind 'S-insert' 'yank' ble-decode/keymap:safe/.bind 'M-\' 'delete-horizontal-space' ble-decode/keymap:selection/bind-shift @marked ble-decode/keymap:safe/.bind 'C-f' 'forward-char' ble-decode/keymap:safe/.bind 'C-b' 'backward-char' ble-decode/keymap:safe/.bind 'right' 'forward-char' ble-decode/keymap:safe/.bind 'left' 'backward-char' ble-decode/keymap:safe/.bind 'C-d' 'delete-region-or delete-forward-char' ble-decode/keymap:safe/.bind 'delete' 'delete-region-or delete-forward-char' ble-decode/keymap:safe/.bind 'C-?' 'delete-region-or delete-backward-char' ble-decode/keymap:safe/.bind 'DEL' 'delete-region-or delete-backward-char' ble-decode/keymap:safe/.bind 'C-h' 'delete-region-or delete-backward-char' ble-decode/keymap:safe/.bind 'BS' 'delete-region-or delete-backward-char' ble-decode/keymap:safe/.bind 'C-t' 'transpose-chars' ble-decode/keymap:safe/.bind 'C-right' 'forward-cword' ble-decode/keymap:safe/.bind 'C-left' 'backward-cword' ble-decode/keymap:safe/.bind 'M-right' 'forward-sword' ble-decode/keymap:safe/.bind 'M-left' 'backward-sword' ble-decode/keymap:safe/.bind 'M-d' 'kill-forward-cword' ble-decode/keymap:safe/.bind 'M-h' 'kill-backward-cword' ble-decode/keymap:safe/.bind 'C-delete' 'delete-forward-cword' ble-decode/keymap:safe/.bind 'C-_' 'delete-backward-cword' ble-decode/keymap:safe/.bind 'C-DEL' 'delete-backward-cword' ble-decode/keymap:safe/.bind 'C-BS' 'delete-backward-cword' ble-decode/keymap:safe/.bind 'M-delete' 'copy-forward-sword' ble-decode/keymap:safe/.bind 'M-C-?' 'copy-backward-sword' ble-decode/keymap:safe/.bind 'M-DEL' 'copy-backward-sword' ble-decode/keymap:safe/.bind 'M-C-h' 'copy-backward-sword' ble-decode/keymap:safe/.bind 'M-BS' 'copy-backward-sword' ble-decode/keymap:safe/.bind 'M-f' 'forward-cword' ble-decode/keymap:safe/.bind 'M-b' 'backward-cword' ble-decode/keymap:safe/.bind 'M-c' 'capitalize-eword' ble-decode/keymap:safe/.bind 'M-l' 'downcase-eword' ble-decode/keymap:safe/.bind 'M-u' 'upcase-eword' ble-decode/keymap:safe/.bind 'M-t' 'transpose-ewords' ble-decode/keymap:safe/.bind 'C-a' 'beginning-of-line' ble-decode/keymap:safe/.bind 'C-e' 'end-of-line' ble-decode/keymap:safe/.bind 'home' 'beginning-of-line' ble-decode/keymap:safe/.bind 'end' 'end-of-line' ble-decode/keymap:safe/.bind 'M-m' 'non-space-beginning-of-line' ble-decode/keymap:safe/.bind 'C-p' 'backward-line' # overwritten by bind-history ble-decode/keymap:safe/.bind 'up' 'backward-line' # overwritten by bind-history ble-decode/keymap:safe/.bind 'C-n' 'forward-line' # overwritten by bind-history ble-decode/keymap:safe/.bind 'down' 'forward-line' # overwritten by bind-history ble-decode/keymap:safe/.bind 'C-k' 'kill-forward-line' ble-decode/keymap:safe/.bind 'C-u' 'kill-backward-line' ble-decode/keymap:safe/.bind 'C-home' 'beginning-of-text' ble-decode/keymap:safe/.bind 'C-end' 'end-of-text' ble-decode/keymap:safe/.bind 'C-x (' 'start-keyboard-macro' ble-decode/keymap:safe/.bind 'C-x )' 'end-keyboard-macro' ble-decode/keymap:safe/.bind 'C-x e' 'call-keyboard-macro' ble-decode/keymap:safe/.bind 'C-x P' 'print-keyboard-macro' ble-decode/keymap:safe/.bind 'C-]' 'character-search-forward' ble-decode/keymap:safe/.bind 'M-C-]' 'character-search-backward' ble-decode/keymap:safe/.bind 'M-x' 'execute-named-command' } function ble-decode/keymap:safe/bind-history { ble-decode/keymap:safe/.bind 'C-r' 'history-isearch-backward' ble-decode/keymap:safe/.bind 'C-s' 'history-isearch-forward' ble-decode/keymap:safe/.bind 'M-<' 'history-beginning' ble-decode/keymap:safe/.bind 'M->' 'history-end' ble-decode/keymap:safe/.bind 'C-prior' 'history-beginning' ble-decode/keymap:safe/.bind 'C-next' 'history-end' ble-decode/keymap:safe/.bind 'C-p' 'backward-line history' ble-decode/keymap:safe/.bind 'up' 'backward-line history' ble-decode/keymap:safe/.bind 'C-n' 'forward-line history' ble-decode/keymap:safe/.bind 'down' 'forward-line history' ble-decode/keymap:safe/.bind 'prior' 'history-search-backward' # bash-5.2 ble-decode/keymap:safe/.bind 'next' 'history-search-forward' # bash-5.2 ble-decode/keymap:safe/.bind 'C-x C-p' 'history-search-backward' ble-decode/keymap:safe/.bind 'C-x up' 'history-search-backward' ble-decode/keymap:safe/.bind 'C-x C-n' 'history-search-forward' ble-decode/keymap:safe/.bind 'C-x down' 'history-search-forward' ble-decode/keymap:safe/.bind 'C-x p' 'history-substring-search-backward' ble-decode/keymap:safe/.bind 'C-x n' 'history-substring-search-forward' ble-decode/keymap:safe/.bind 'C-x <' 'history-nsearch-backward' ble-decode/keymap:safe/.bind 'C-x >' 'history-nsearch-forward' ble-decode/keymap:safe/.bind 'C-x ,' 'history-nsearch-backward-again' ble-decode/keymap:safe/.bind 'C-x .' 'history-nsearch-forward-again' ble-decode/keymap:safe/.bind 'M-.' 'insert-last-argument' ble-decode/keymap:safe/.bind 'M-_' 'insert-last-argument' ble-decode/keymap:safe/.bind 'M-C-y' 'insert-nth-argument' } function ble-decode/keymap:safe/bind-complete { ble-decode/keymap:safe/.bind 'C-i' 'complete' ble-decode/keymap:safe/.bind 'TAB' 'complete' ble-decode/keymap:safe/.bind 'M-?' 'complete show_menu' ble-decode/keymap:safe/.bind 'M-*' 'complete insert_all' ble-decode/keymap:safe/.bind 'M-{' 'complete insert_braces' ble-decode/keymap:safe/.bind 'C-TAB' 'menu-complete' ble-decode/keymap:safe/.bind 'S-C-i' 'menu-complete backward' ble-decode/keymap:safe/.bind 'S-TAB' 'menu-complete backward' ble-decode/keymap:safe/.bind 'auto_complete_enter' 'auto-complete-enter' ble-decode/keymap:safe/.bind 'M-/' 'complete context=filename' ble-decode/keymap:safe/.bind 'M-~' 'complete context=username' ble-decode/keymap:safe/.bind 'M-$' 'complete context=variable' ble-decode/keymap:safe/.bind 'M-@' 'complete context=hostname' ble-decode/keymap:safe/.bind 'M-!' 'complete context=command' ble-decode/keymap:safe/.bind 'C-x /' 'complete show_menu:context=filename' ble-decode/keymap:safe/.bind 'C-x ~' 'complete show_menu:context=username' ble-decode/keymap:safe/.bind 'C-x $' 'complete show_menu:context=variable' ble-decode/keymap:safe/.bind 'C-x @' 'complete show_menu:context=hostname' ble-decode/keymap:safe/.bind 'C-x !' 'complete show_menu:context=command' ble-decode/keymap:safe/.bind "M-'" 'sabbrev-expand' ble-decode/keymap:safe/.bind "C-x '" 'sabbrev-expand' ble-decode/keymap:safe/.bind 'C-x C-r' 'dabbrev-expand' ble-decode/keymap:safe/.bind 'M-g' 'complete context=glob' ble-decode/keymap:safe/.bind 'C-x *' 'complete insert_all:context=glob' ble-decode/keymap:safe/.bind 'C-x g' 'complete show_menu:context=glob' ble-decode/keymap:safe/.bind 'M-C-i' 'complete context=dynamic-history' ble-decode/keymap:safe/.bind 'M-TAB' 'complete context=dynamic-history' } function ble-decode/keymap:safe/bind-arg { local append_arg=append-arg${1:+'-or '}$1 ble-decode/keymap:safe/.bind M-C-u 'universal-arg' ble-decode/keymap:safe/.bind M-- "$append_arg" ble-decode/keymap:safe/.bind M-0 "$append_arg" ble-decode/keymap:safe/.bind M-1 "$append_arg" ble-decode/keymap:safe/.bind M-2 "$append_arg" ble-decode/keymap:safe/.bind M-3 "$append_arg" ble-decode/keymap:safe/.bind M-4 "$append_arg" ble-decode/keymap:safe/.bind M-5 "$append_arg" ble-decode/keymap:safe/.bind M-6 "$append_arg" ble-decode/keymap:safe/.bind M-7 "$append_arg" ble-decode/keymap:safe/.bind M-8 "$append_arg" ble-decode/keymap:safe/.bind M-9 "$append_arg" ble-decode/keymap:safe/.bind C-- "$append_arg" ble-decode/keymap:safe/.bind C-0 "$append_arg" ble-decode/keymap:safe/.bind C-1 "$append_arg" ble-decode/keymap:safe/.bind C-2 "$append_arg" ble-decode/keymap:safe/.bind C-3 "$append_arg" ble-decode/keymap:safe/.bind C-4 "$append_arg" ble-decode/keymap:safe/.bind C-5 "$append_arg" ble-decode/keymap:safe/.bind C-6 "$append_arg" ble-decode/keymap:safe/.bind C-7 "$append_arg" ble-decode/keymap:safe/.bind C-8 "$append_arg" ble-decode/keymap:safe/.bind C-9 "$append_arg" ble-decode/keymap:safe/.bind - "$append_arg" ble-decode/keymap:safe/.bind 0 "$append_arg" ble-decode/keymap:safe/.bind 1 "$append_arg" ble-decode/keymap:safe/.bind 2 "$append_arg" ble-decode/keymap:safe/.bind 3 "$append_arg" ble-decode/keymap:safe/.bind 4 "$append_arg" ble-decode/keymap:safe/.bind 5 "$append_arg" ble-decode/keymap:safe/.bind 6 "$append_arg" ble-decode/keymap:safe/.bind 7 "$append_arg" ble-decode/keymap:safe/.bind 8 "$append_arg" ble-decode/keymap:safe/.bind 9 "$append_arg" } function ble/widget/safe/__attach__ { ble/edit/info/set-default text '' } function ble-decode/keymap:safe/define { local ble_bind_nometa= ble-decode/keymap:safe/bind-common ble-decode/keymap:safe/bind-history ble-decode/keymap:safe/bind-complete ble-bind -f 'C-d' 'delete-region-or delete-forward-char-or-exit' ble-bind -f 'SP' magic-space ble-bind -f '/' magic-slash ble-bind -f 'M-^' history-expand-line ble-bind -f __attach__ safe/__attach__ ble-bind -f __line_limit__ __line_limit__ ble-bind -f 'C-c' discard-line ble-bind -f 'C-j' accept-line ble-bind -f 'C-RET' accept-line ble-bind -f 'C-m' accept-single-line-or-newline ble-bind -f 'RET' accept-single-line-or-newline ble-bind -f 'C-o' accept-and-next ble-bind -f 'C-x C-e' edit-and-execute-command ble-bind -f 'M-#' insert-comment ble-bind -f 'M-C-e' shell-expand-line ble-bind -f 'M-&' tilde-expand ble-bind -f 'C-g' bell ble-bind -f 'C-x C-g' bell ble-bind -f 'C-M-g' bell ble-bind -f 'C-l' clear-screen ble-bind -f 'C-M-l' redraw-line ble-bind -f 'f1' command-help ble-bind -f 'C-x C-v' display-shell-version ble-bind -c 'C-z' fg ble-bind -f 'M-z' zap-to-char } function ble-edit/bind/load-editing-mode:safe { ble/decode/keymap#load safe } ble/util/autoload "lib/keymap.emacs.sh" \ ble-decode/keymap:emacs/define ble/util/autoload "lib/keymap.vi.sh" \ ble-decode/keymap:vi_{i,n,o,x,s,c}map/define ble/util/autoload "lib/keymap.vi_digraph.sh" \ ble-decode/keymap:vi_digraph/define function ble/widget/.change-editing-mode { [[ $_ble_decode_bind_state == none ]] && return 0 local mode=$1 if [[ $bleopt_default_keymap == auto ]]; then if [[ ! -o $mode ]]; then set -o "$mode" ble/decode/reset-default-keymap ble/decode/detach ble/decode/attach || ble-detach fi else bleopt default_keymap="$mode" fi } function ble/widget/emacs-editing-mode { ble/widget/.change-editing-mode emacs } function ble/widget/vi-editing-mode { ble/widget/.change-editing-mode vi } _ble_edit_read_accept= _ble_edit_read_result= function ble/widget/read/accept { if [[ $_ble_edit_async_read_prefix ]]; then local prefix=$_ble_edit_async_read_prefix local hook=${prefix}_accept_hook; hook=${!hook} ble/util/set "${prefix}_accept_hook" '' ble/util/set "${prefix}_cancel_hook" '' ble/util/set "${prefix}_before_widget" '' local ret ble/edit/async-read-mode/accept [[ ! $hook ]] || "$hook" "$ret" else _ble_edit_read_accept=1 _ble_edit_read_result=$_ble_edit_str ble/decode/keymap/pop fi } function ble/widget/read/cancel { if [[ $_ble_edit_async_read_prefix ]]; then local hook=${_ble_edit_async_read_prefix}_cancel_hook ble/util/set "${_ble_edit_async_read_prefix}_accept_hook" "${!hook}" ble/widget/read/accept else ble/widget/read/accept _ble_edit_read_accept=2 fi } function ble/widget/read/delete-forward-char-or-cancel { if [[ $_ble_edit_str ]]; then ble/widget/delete-forward-char else ble/widget/read/cancel fi } function ble/widget/read/__line_limit__.edit { local content=$1 ble/widget/edit-and-execute-command.edit "$content" no-newline; local ext=$? ((ext==127)) && return "$ext" ble-edit/content/reset "$ret" ble/widget/read/accept } function ble/widget/read/__line_limit__ { ble/widget/__line_limit__ read/__line_limit__.edit } function ble/widget/read/__before_widget__ { if [[ $_ble_edit_async_read_prefix ]]; then local hook=${_ble_edit_async_read_prefix}_before_widget builtin eval -- "${!hook}" fi } function ble-decode/keymap:read/define { local ble_bind_nometa= ble-decode/keymap:safe/bind-common ble-decode/keymap:safe/bind-history ble-bind -f __before_widget__ read/__before_widget__ ble-bind -f __line_limit__ read/__line_limit__ ble-bind -f 'C-c' read/cancel ble-bind -f 'C-\' read/cancel ble-bind -f 'C-m' read/accept ble-bind -f 'RET' read/accept ble-bind -f 'C-j' read/accept ble-bind -f 'C-d' 'delete-region-or read/delete-forward-char-or-cancel' ble-bind -f 'C-g' bell ble-bind -f 'C-l' redraw-line ble-bind -f 'C-M-l' redraw-line ble-bind -f 'C-x C-v' display-shell-version ble-bind -f 'C-^' bell } _ble_edit_read_history=() _ble_edit_read_history_edit=() _ble_edit_read_history_dirt=() _ble_edit_read_history_index=0 function ble/builtin/read/.process-option { case $1 in (-e) opt_flags=${opt_flags}r ;; (-i) opt_default=$2 ;; (-p) opt_prompt=$2 ;; (-u) opt_fd=$2 ble/array#push opts_in "$@" ;; (-t) opt_timeout=$2 ;; (*) ble/array#push opts "$@" ;; esac } function ble/builtin/read/.read-arguments { local is_normal_args= vars=() opts=() while (($#)); do local arg=$1; shift if [[ $is_normal_args || $arg != -* ]]; then ble/array#push vars "$arg" elif [[ $arg == -- ]]; then is_normal_args=1 elif [[ $arg == --* ]]; then case $arg in (--help) opt_flags=${opt_flags}H ;; (*) ble/util/print "read: unrecognized long option '$arg'" >&2 opt_flags=${opt_flags}E ;; esac else local i n=${#arg} c for ((i=1;i&2 opt_flags=${opt_flags}E fi break ;; ([adinNptu]*) ble/builtin/read/.process-option -$c "${arg:i+1}"; break ;; ([ers]*) ble/builtin/read/.process-option -$c ;; (*) ble/util/print "read: unrecognized option '-$c'" >&2 opt_flags=${opt_flags}E ;; esac done fi done } function ble/builtin/read/.set-up-textarea { ble/decode/keymap/push read || return 1 [[ $_ble_edit_read_context == external ]] && _ble_canvas_panel_height[0]=0 _ble_textarea_panel=1 _ble_canvas_panel_focus=1 ble/textarea#invalidate ble/edit/info/set-default ansi '' _ble_edit_PS1=$opt_prompt _ble_prompt_ps1_data=(0 '' '' 0 0 0 32 0 "" "") _ble_edit_dirty_observer=() ble/widget/.newline/clear-content _ble_edit_arg= ble-edit/content/reset "$opt_default" newline _ble_edit_ind=${#opt_default} ble-edit/undo/clear-all ble/history/set-prefix _ble_edit_read_ _ble_syntax_lang=text _ble_highlight_layer_list=(plain region overwrite_mode disabled) return 0 } function ble/builtin/read/TRAPWINCH { local IFS=$_ble_term_IFS ble/application/onwinch } function ble/builtin/read/.loop { set +m # ジョブ管理を無効にする shopt -u failglob _ble_edit_async_read_prefix= local ret; ble/canvas/panel/save-position; local pos0=$ret ble/builtin/read/.set-up-textarea || return 1 ble/builtin/trap/install-hook WINCH readline blehook internal_WINCH=ble/builtin/read/TRAPWINCH local ret= timeout= if [[ $opt_timeout ]]; then ble/util/clock; local start_time=$ret ((start_time&&(start_time-=_ble_util_clock_reso-1))) if [[ $opt_timeout == *.* ]]; then local mantissa=${opt_timeout%%.*} local fraction=${opt_timeout##*.}000 ((timeout=mantissa*1000+10#0${fraction::3})) else ((timeout=opt_timeout*1000)) fi ((timeout<0)) && timeout= fi ble/application/render local _ble_decode_input_count=0 local ble_decode_char_nest= local -a _ble_decode_char_buffer=() local char= local _ble_edit_read_accept= local _ble_edit_read_result= while [[ ! $_ble_edit_read_accept ]]; do local timeout_option= if [[ $timeout ]]; then if ((_ble_bash>=40000)); then local timeout_frac=000$((timeout%1000)) timeout_option="-t $((timeout/1000)).${timeout_frac:${#timeout_frac}-3}" else timeout_option="-t $((timeout/1000))" fi fi IFS= ble/bash/read -d '' -n 1 $timeout_option char "${opts_in[@]}"; local ext=$? if ((ext>128)); then _ble_edit_read_accept=142 break fi if [[ $timeout ]]; then ble/util/clock; local current_time=$ret ((timeout-=current_time-start_time)) if ((timeout<=0)); then _ble_edit_read_accept=142 break fi start_time=$current_time fi ble/util/s2c "$char" ble-decode-char "$ret" [[ $_ble_edit_read_accept ]] && break ble/util/is-stdin-ready && continue ble-edit/content/check-limit ble-decode/.hook/erase-progress ble/application/render done if [[ $_ble_edit_read_context == internal ]]; then local -a DRAW_BUFF=() ble/canvas/panel#set-height.draw "$_ble_textarea_panel" 0 ble/canvas/panel/load-position.draw "$pos0" ble/canvas/bflush.draw else if ((_ble_edit_read_accept==1)); then ble/edit/.relocate-textarea # #D1800 (既に外部状態なのでOK) else _ble_edit_line_disabled=1 ble/edit/.relocate-textarea # #D1800 (既に外部状態なのでOK) fi fi ble/util/buffer.flush ble/term/visible-bell/erase if ((_ble_edit_read_accept==1)); then local q=\' Q="'\''" printf %s "__ble_input='${_ble_edit_read_result//$q/$Q}'" elif ((_ble_edit_read_accept==142)); then return "$ext" else return 1 fi } function ble/builtin/read/.impl { local -a opts=() vars=() opts_in=() local opt_flags= opt_prompt= opt_default= opt_timeout= opt_fd=0 local rex1='^[0-9]+(\.[0-9]*)?$|^\.[0-9]+$' rex2='^[0.]+$' [[ $TMOUT =~ $rex1 && ! ( $TMOUT =~ $rex2 ) ]] && opt_timeout=$TMOUT ble/builtin/read/.read-arguments "$@" if [[ $opt_flags == *[HE]* ]]; then if [[ $opt_flags == *H* ]]; then builtin read --help elif [[ $opt_flags == *E* ]]; then builtin read --usage 2>&1 1>/dev/null | ble/bin/grep ^read >&2 fi return 2 fi if ! [[ $opt_flags == *r* && -t $opt_fd ]]; then [[ $opt_prompt ]] && ble/array#push opts -p "$opt_prompt" [[ $opt_timeout ]] && ble/array#push opts -t "$opt_timeout" __ble_args=("${opts[@]}" "${opts_in[@]}" -- "${vars[@]}") __ble_command='ble/bash/read "${__ble_args[@]}"' return 0 fi ble/decode/keymap#load read local result _ble_edit_read_context=$_ble_term_state ble/util/buffer.flush [[ $_ble_edit_read_context == external ]] && ble/term/enter # 外側にいたら入る result=$(ble/builtin/read/.loop); local ext=$? [[ $_ble_edit_read_context == external ]] && ble/term/leave # 元の状態に戻る [[ $_ble_edit_read_context == internal ]] && ((_ble_canvas_panel_height[1]=0)) if ((ext==0)); then builtin eval -- "$result" __ble_args=("${opts[@]}" -- "${vars[@]}") __ble_command='ble/bash/read "${__ble_args[@]}" <<< "$__ble_input"' fi return "$ext" } function ble/builtin/read { if [[ $_ble_decode_bind_state == none ]]; then builtin read "$@" return "$?" fi local _ble_local_set _ble_local_shopt ble/base/.adjust-bash-options _ble_local_set _ble_local_shopt [[ $_ble_builtin_read_hook ]] && builtin eval -- "$_ble_builtin_read_hook" local __ble_command= __ble_args= __ble_input= [[ ! $_ble_attached || $_ble_edit_exec_inside_userspace ]] && ble/base/adjust-BASH_REMATCH ble/builtin/read/.impl "$@"; local __ble_ext=$? [[ ! $_ble_attached || $_ble_edit_exec_inside_userspace ]] && ble/base/restore-BASH_REMATCH ble/base/.restore-bash-options _ble_local_set _ble_local_shopt [[ $__ble_command ]] || return "$__ble_ext" builtin eval -- "$__ble_command" } function read { builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" ble/builtin/read "$@" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" } _ble_edit_async_read_prefix= _ble_edit_async_read_accept_hook= _ble_edit_async_read_cancel_hook= _ble_edit_async_read_before_widget= _ble_edit_async_read_history=() _ble_edit_async_read_history_edit=() _ble_edit_async_read_history_dirt=() _ble_edit_async_read_history_index=0 function ble/edit/async-read-mode { local hook=$1 prefix=${2:-_ble_edit_async_read} keymap=${3:-read} ble/util/assert '[[ ! $_ble_edit_async_read_prefix ]]' 'it is already inside the async-read mode.' || return 1 _ble_edit_async_read_prefix=$prefix ble/util/set "${prefix}_accept_hook" "$hook" ble/util/set "${prefix}_cancel_hook" '' ble/textarea#render ble/textarea#save-state "$prefix" ble/util/save-vars "$prefix" _ble_canvas_panel_focus ble/util/set "${prefix}_history_prefix" "$_ble_history_prefix" ble/decode/keymap/push "$keymap" ble/edit/info/default text '' _ble_textarea_panel=1 _ble_canvas_panel_focus=1 ble/textarea#invalidate _ble_edit_PS1=$PS2 _ble_prompt_ps1_data=(0 '' '' 0 0 0 32 0 '' '') _ble_edit_dirty_observer=() ble/widget/.newline/clear-content _ble_edit_arg= ble-edit/undo/clear-all ble/history/set-prefix "$prefix" _ble_syntax_lang=text _ble_highlight_layer_list=(plain region overwrite_mode) return 147 } function ble/edit/async-read-mode/accept { local prefix=$_ble_edit_async_read_prefix ble/util/assert '[[ $prefix ]]' 'it is not inside the async-read mode.' || return 1 ret=$_ble_edit_str [[ $ret ]] && ble/history/add "$ret" # Note: cancel でも登録する local -a DRAW_BUFF=() ble/canvas/panel#set-height.draw "$_ble_textarea_panel" 0 ble/canvas/bflush.draw ble/textarea#restore-state "$prefix" ble/textarea#clear-state "$prefix" ble/util/restore-vars "$prefix" _ble_canvas_panel_focus [[ $_ble_edit_overwrite_mode ]] && ble/util/buffer "$_ble_term_civis" local old_history_prefix_ref=${prefix}_history_prefix ble/history/set-prefix "${!old_history_prefix_ref}" ble/decode/keymap/pop _ble_edit_async_read_prefix= } _ble_edit_async_read_is_cancel_key[63|_ble_decode_Ctrl]=1 # C-? _ble_edit_async_read_is_cancel_key[127]=1 # DEL _ble_edit_async_read_is_cancel_key[104|_ble_decode_Ctrl]=1 # C-h _ble_edit_async_read_is_cancel_key[8]=1 # BS function ble/edit/async-read-mode/empty-cancel.hook { if [[ ! $_ble_edit_str ]] && ((_ble_edit_async_read_is_cancel_key[KEYS[0]])); then ble/widget/read/cancel ble/decode/widget/suppress-widget fi } function ble/widget/command-help/.read-man { local -x _ble_local_tmpfile; ble/util/assign/mktmp local pager="sh -c 'cat >| \"\$_ble_local_tmpfile\"'" MANPAGER=$pager PAGER=$pager MANOPT= man "$@" 2>/dev/null; local ext=$? # 668ms ble/util/readfile man_content "$_ble_local_tmpfile" # 80ms ble/util/assign/rmtmp return "$ext" } function ble/widget/command-help/.locate-in-man-bash { local command=$1 local ret rex local rex_esc=$'(\e\\[[ -?]*[@-~]||.\b)' cr=$'\r' local pager; ble/util/get-pager pager local pager_cmd=${pager%%["$_ble_term_IFS"]*} [[ ${pager_cmd##*/} == less ]] || return 1 local awk=ble/bin/awk; ble/bin#has gawk && awk=gawk local man_content; ble/widget/command-help/.read-man bash || return 1 # 733ms (3 fork: man, sh, cat) local cmd_awk case $command in ('function') cmd_awk='name () compound-command' ;; ('until') cmd_awk=while ;; ('command') cmd_awk='command [' ;; ('source') cmd_awk=. ;; ('typeset') cmd_awk=declare ;; ('readarray') cmd_awk=mapfile ;; ('[') cmd_awk=test ;; (*) cmd_awk=$command ;; esac ble/string#escape-for-awk-regex "$cmd_awk"; local rex_awk=$ret rex='\b$'; [[ $awk == gawk && $cmd_awk =~ $rex ]] && rex_awk=$rex_awk'\y' local awk_script='{ gsub(/'"$rex_esc"'/, ""); if (!par && $0 ~ /^['"$_ble_term_space"']*'"$rex_awk"'/) { print NR; exit; } par = !($0 ~ /^['"$_ble_term_space"']*$/); }' local awk_out; ble/util/assign awk_out '"$awk" "$awk_script" 2>/dev/null <<< "$man_content"' || return 1 # 206ms (1 fork) local iline=${awk_out%$'\n'}; [[ $iline ]] || return 1 ble/string#escape-for-extended-regex "$command"; local rex_ext=$ret rex='\b$'; [[ $command =~ $rex ]] && rex_ext=$rex_ext'\b' rex='^\b'; [[ $command =~ $rex ]] && rex_ext="($rex_esc|\b)$rex_ext" local manpager="$pager -r +'/$rex_ext$cr$((iline-1))g'" builtin eval -- "$manpager" <<< "$man_content" # 1 fork } function ble/widget/command-help/.show-bash-script { local _ble_local_pipeline=$1 local -x LESS="${LESS:+$LESS }-r" # Note: Bash のバグで tempenv builtin eval は消滅するので #D1438 ble/bin#has source-highlight && _ble_local_pipeline='source-highlight -s sh -f esc | '$_ble_local_pipeline builtin eval -- "$_ble_local_pipeline" } function ble/widget/command-help/.locate-function-in-source { local func=$1 source lineno line ble/function#get-source-and-lineno "$func" || return 1 [[ -f $source && -s $source ]] || return 1 # pipe 等は読み取らない local pager; ble/util/get-pager pager local pager_cmd=${pager%%["$_ble_term_IFS"]*} [[ ${pager_cmd##*/} == less ]] || return 1 ble/util/assign line 'ble/bin/sed -n "${lineno}{p;q;}" "$source"' [[ $line == *"$func"* ]] || return 1 ble/widget/command-help/.show-bash-script '"$pager" +"${lineno}g"' < "$source" } function ble/widget/command-help.core { ble/function#try ble/cmdinfo/help:"$command" && return 0 ble/function#try ble/cmdinfo/help "$command" && return 0 if [[ $type == builtin || $type == keyword ]]; then ble/widget/command-help/.locate-in-man-bash "$command" && return 0 elif [[ $type == function ]]; then ble/widget/command-help/.locate-function-in-source "$command" && return 0 local def; ble/function#getdef "$command" ble/widget/command-help/.show-bash-script ble/util/pager <<< "$def" && return 0 fi if ble/is-function ble/bin/man; then MANOPT= ble/bin/man "${command##*/}" 2>/dev/null && return 0 fi if local content; content=$("$command" --help 2>&1) && [[ $content ]]; then ble/util/print "$content" | ble/util/pager return 0 fi ble/util/print "ble: help of \`$command' not found" >&2 return 1 } function ble/widget/command-help/.type/.resolve-alias { local literal=$1 command=$2 type=alias local last_literal=$1 last_command=$2 while [[ $command == "$literal" ]] || break # Note: type=alias local alias_def ble/util/assign alias_def "alias $command" builtin unalias "$command" builtin eval "alias_def=${alias_def#*=}" # remove quote literal=${alias_def%%["$_ble_term_IFS"]*} command= type= local ret; ble/syntax:bash/simple-word/safe-eval "$literal" nonull || break # Note: type= command=$ret ble/util/type type "$command" [[ $type ]] || break # Note: type= last_literal=$literal last_command=$command [[ $type == alias ]] do :; done if [[ ! $type || $type == alias ]]; then literal=$last_literal command=$last_command builtin unalias "$command" &>/dev/null ble/util/type type "$command" fi local q="'" Q="'\''" printf "type='%s'\n" "${type//$q/$Q}" printf "literal='%s'\n" "${literal//$q/$Q}" printf "command='%s'\n" "${command//$q/$Q}" return 0 } 2>/dev/null function ble/widget/command-help/.type { local literal=$1 type= command= local ret; ble/syntax:bash/simple-word/safe-eval "$literal" nonull || return 1; command=$ret ble/util/type type "$command" if [[ $type == alias ]]; then builtin eval -- "$(ble/widget/command-help/.type/.resolve-alias "$literal" "$command")" fi if [[ $type == keyword && $command != "$literal" ]]; then if [[ $command == %* ]] && jobs -- "$command" &>/dev/null; then type=jobs else type=${type[1]} [[ $type ]] || return 1 fi fi } function ble/widget/command-help.impl { local literal=$1 if [[ ! $literal ]]; then ble/widget/.bell return 1 fi local type command; ble/widget/command-help/.type "$literal" if [[ ! $type ]]; then ble/widget/.bell "command \`$command' not found" return 1 fi ble/widget/external-command ble/widget/command-help.core } function ble/widget/command-help { ble-edit/content/clear-arg local comp_cword comp_words comp_line comp_point if ble/syntax:bash/extract-command "$_ble_edit_ind"; then local cmd=${comp_words[0]} else local args; ble/string#split-words args "$_ble_edit_str" local cmd=${args[0]} fi ble/widget/command-help.impl "$cmd" } function ble-edit/bind/stdout.on { :;} function ble-edit/bind/stdout.off { ble/util/buffer.flush;} function ble-edit/bind/stdout.finalize { :;} if [[ $bleopt_internal_suppress_bash_output ]]; then _ble_edit_io_fname2=$_ble_base_run/$$.stderr function ble-edit/bind/stdout.on { exec 2>&"$_ble_util_fd_tui_stderr" } function ble-edit/bind/stdout.off { ble/util/buffer.flush ble-edit/io/check-stderr exec 2>>"$_ble_edit_io_fname2" } function ble-edit/bind/stdout.finalize { ble-edit/bind/stdout.on [[ -f $_ble_edit_io_fname2 ]] && >| "$_ble_edit_io_fname2" } function ble-edit/io/check-stderr { local file=${1:-$_ble_edit_io_fname2} if ble/is-function ble/term/visible-bell; then if [[ -f $file && -s $file ]]; then local message= line while IFS= ble/bash/read line || [[ $line ]]; do if [[ $line == 'bash: '* || $line == "${BASH##*/}: "* || $line == "ble.sh ("*"): "* ]]; then message="$message${message:+; }$line" fi done < "$file" [[ $message ]] && ble/term/visible-bell "$message" >| "$file" fi fi } if ((_ble_bash<40000)); then function ble-edit/io/TRAPUSR1 { [[ $_ble_term_state == internal ]] || return 1 local FUNCNEST= local IFS=$_ble_term_IFS local file=$_ble_edit_io_fname2.proc if [[ -s $file ]]; then local content cmd ble/util/readfile content "$file" >| "$file" for cmd in $content; do case $cmd in (eof) _ble_decode_hook 4 builtin eval -- "$_ble_decode_bind_hook" ;; esac done fi ble/builtin/trap/invoke USR1 } blehook/declare internal_USR1 blehook internal_USR1!=ble-edit/io/TRAPUSR1 ble/builtin/trap/install-hook USR1 function ble-edit/io/check-ignoreeof-message { local line=$1 [[ ( $bleopt_internal_ignoreeof_trap && $line == *$bleopt_internal_ignoreeof_trap* ) || $line == *'Use "exit" to leave the shell.'* || $line == *'ログアウトする為には exit を入力して下さい'* || $line == *'シェルから脱出するには "exit" を使用してください。'* || $line == *'シェルから脱出するのに "exit" を使いなさい.'* || $line == *'Gebruik Kaart na Los Tronk'* ]] && return 0 [[ $line == *exit* ]] && ble/bin/grep -q -F "$line" "$_ble_base"/lib/core-edit.ignoreeof-messages.txt } function ble-edit/io/check-ignoreeof-loop { local line opts=:$1: while IFS= ble/bash/read line; do if [[ $line == *[^$_ble_term_IFS]* ]]; then ble/util/print "$line" >> "$_ble_edit_io_fname2" fi if ble-edit/io/check-ignoreeof-message "$line"; then ble/util/print eof >> "$_ble_edit_io_fname2.proc" kill -USR1 $$ ble/util/msleep 100 # 連続で送ると bash が落ちるかも (落ちた事はないが念の為) fi done } &>/dev/null ble/bin/rm -f "$_ble_edit_io_fname2.pipe" if ble/bin/mkfifo "$_ble_edit_io_fname2.pipe" 2>/dev/null; then { ble-edit/io/check-ignoreeof-loop fifo < "$_ble_edit_io_fname2.pipe" & disown } &>/dev/null ble/fd#alloc _ble_edit_io_fd2 '> "$_ble_edit_io_fname2.pipe"' function ble-edit/bind/stdout.off { ble/util/buffer.flush ble-edit/io/check-stderr exec 2>&"$_ble_edit_io_fd2" } elif . "$_ble_base/lib/init-msys1.sh"; ble-edit/io:msys1/start-background; then function ble-edit/bind/stdout.off { ble/util/buffer.flush ble-edit/io/check-stderr exec 2>/dev/null exec 2>>"$_ble_edit_io_fname2.buff" } fi fi fi [[ ${_ble_edit_detach_flag-} != reload ]] && _ble_edit_detach_flag= function ble-edit/bind/.exit-TRAPRTMAX { local FUNCNEST= ble/base/unload builtin exit 0 } function ble-edit/bind/.check-detach { if [[ ! -o emacs && ! -o vi ]]; then local ret ble/edit/marker#instantiate 'unsupported' error:non-empty ble/util/print "$ret Sorry, ble.sh is supported only with some editing mode (set -o emacs/vi)." >&2 ble-detach fi [[ $_ble_edit_detach_flag == prompt-attach ]] && return 1 if [[ $_ble_edit_detach_flag || ! $_ble_attached ]]; then type=$_ble_edit_detach_flag _ble_edit_detach_flag= local attached=$_ble_attached [[ $attached ]] && ble-detach/impl if [[ $type == exit ]]; then local ret ble/edit/marker#instantiate-config exec_exit_mark && ble-detach/message "$ret" builtin trap 'ble-edit/bind/.exit-TRAPRTMAX' RTMAX kill -RTMAX $$ else local ret ble/edit/marker#instantiate 'detached' non-empty ble-detach/message \ ${ret+"$ret"} \ "Please run \`stty sane' to recover the correct TTY state." if ((_ble_bash>=40000)); then READLINE_LINE=' stty sane;' READLINE_POINT=11 READLINE_MARK=0 printf %s "$READLINE_LINE" fi fi if [[ $attached ]]; then ble/base/restore-BASH_REMATCH ble/base/restore-bash-options ble/base/restore-builtin-wrappers ble/base/restore-POSIXLY_CORRECT builtin eval -- "$_ble_bash_FUNCNEST_restore" # これ以降関数は呼び出せない else ble-edit/exec:"$bleopt_internal_exec_type"/.prologue _ble_edit_exec_inside_prologue= fi return 0 else local state=$_ble_decode_bind_state if [[ ( $state == emacs || $state == vi ) && ! -o $state ]]; then ble/decode/reset-default-keymap ble/decode/detach if ! ble/decode/attach; then ble-detach ble-edit/bind/.check-detach # 改めて終了処理 return "$?" fi fi return 1 fi } if ((_ble_bash>=40100)); then function ble-edit/bind/.head/adjust-bash-rendering { ble/textarea#redraw-cache ble/util/buffer.flush } else function ble-edit/bind/.head/adjust-bash-rendering { ((_ble_canvas_y++,_ble_canvas_x=0)) local -a DRAW_BUFF=() ble/canvas/panel#goto.draw "$_ble_textarea_panel" "${_ble_textarea_cur[0]}" "${_ble_textarea_cur[1]}" ble/canvas/flush.draw } fi function ble-edit/bind/.head { ble-edit/bind/stdout.on ble/base/recover-bash-options [[ $bleopt_internal_suppress_bash_output ]] || ble-edit/bind/.head/adjust-bash-rendering } function ble-edit/bind/.tail-without-draw { ble-edit/bind/stdout.off } if ((_ble_bash>=40000)); then function ble-edit/bind/.tail { ble/application/render ble/util/idle.do ble/textarea#adjust-for-bash-bind # bash-4.0+ ble-edit/bind/stdout.off } else function ble-edit/bind/.tail { ble/application/render ble/util/idle.do ble-edit/bind/stdout.off } fi function ble-decode/PROLOGUE { ble-edit/exec:gexec/restore-state ble-edit/bind/.head ble/decode/readline/adjust-uvw ble/term/enter } function ble-decode/EPILOGUE { if ((_ble_bash>=40000)); then if ble/decode/has-input && ! ble-edit/exec/has-pending-commands; then ble-edit/bind/.tail-without-draw return 0 fi fi ble-edit/content/check-limit ble-edit/exec:"$bleopt_internal_exec_type"/process && return 0 ble-edit/bind/.tail return 0 } function ble/widget/.internal-print-command { local _ble_local_command=$1 _ble_command_opts=$2 _ble_edit_line_disabled=1 ble/edit/.relocate-textarea # #D1800 pair=leave-command-layout [[ :$_ble_command_opts: != *:pre-flush:* ]] || ble/util/buffer.flush BASH_COMMAND=$_ble_local_command builtin eval -- "$_ble_local_command" ble/edit/leave-command-layout # #D1800 pair=ble/edit/.relocate-textarea [[ :$_ble_command_opts: != *:post-flush:* ]] || ble/util/buffer.flush } function ble/widget/print { ble-edit/content/clear-arg local message="$*" lines [[ ${message//["$_ble_term_IFS"]} ]] || return 1 lines=("$@") if [[ ! ${_ble_attached-} || ${_ble_edit_exec_inside_begin-} ]]; then ble/util/print-lines "${lines[@]}" else ble/widget/.internal-print-command ' ble/util/buffer.print-lines "${lines[@]}" ble/util/buffer.flush' pre-flush fi } function ble/widget/internal-command { ble-edit/content/clear-arg local command=$1 [[ ${command//[$_ble_term_IFS]} ]] || return 1 ble/widget/.internal-print-command "$command" } function ble/widget/external-command { ble-edit/content/clear-arg local _ble_local_command=$1 [[ ${_ble_local_command//[$_ble_term_IFS]} ]] || return 1 ble/edit/enter-command-layout # #D1800 pair=leave-command-layout ble/textarea#invalidate local -a DRAW_BUFF=() ble/canvas/panel#set-height.draw "$_ble_textarea_panel" 0 ble/canvas/panel#goto.draw "$_ble_textarea_panel" 0 0 sgr0 ble/canvas/bflush.draw ble/term/leave ble/util/buffer.flush BASH_COMMAND=$_ble_local_command builtin eval -- "$_ble_local_command"; local ext=$? ble/term/enter ble/edit/leave-command-layout # #D1800 pair=enter-command-layout return "$ext" } function ble/widget/execute-command { ble-edit/content/clear-arg local command=$1 if [[ $command != *[!"$_ble_term_IFS"]* ]]; then _ble_edit_line_disabled=1 ble/edit/.relocate-textarea keep-info return 1 fi _ble_edit_line_disabled=1 ble/edit/.relocate-textarea # #D1800 pair=exec/register ble-edit/exec/register "$command" } function ble/widget/.SHELL_COMMAND { ble/widget/execute-command "$@"; } function ble/widget/.EDIT_COMMAND { local command=$1 local -x READLINE_LINE=$_ble_edit_str local -x READLINE_POINT=$_ble_edit_ind local -x READLINE_MARK=$_ble_edit_mark [[ $_ble_edit_arg ]] && local -x READLINE_ARGUMENT=$_ble_edit_arg ble/edit/enter-command-layout # #D1800 pair=leave-command-layout ble/widget/.hide-current-line keep-header ble-edit/restore-PS1 ble/term/leave-for-widget builtin eval -- "$command"; local ext=$? ble/term/enter-for-widget ble-edit/adjust-PS1 ble-edit/content/clear-arg ble/edit/leave-command-layout # #D1800 pair=enter-command-layout [[ $READLINE_LINE != "$_ble_edit_str" ]] && ble-edit/content/reset-and-check-dirty "$READLINE_LINE" ((_ble_edit_ind=READLINE_POINT)) ((_ble_edit_mark=READLINE_MARK)) local N=${#_ble_edit_str} ((_ble_edit_ind<0?_ble_edit_ind=0:(_ble_edit_ind>N&&(_ble_edit_ind=N)))) ((_ble_edit_mark<0?_ble_edit_mark=0:(_ble_edit_mark>N&&(_ble_edit_mark=N)))) return "$ext" } function ble-decode/INITIALIZE_DEFMAP { local ret bleopt/get:default_keymap; local defmap=$ret if ble-edit/bind/load-editing-mode "$defmap"; then local base_keymap=$defmap [[ $defmap == vi ]] && base_keymap=vi_imap builtin eval -- "$2=\$base_keymap" ble/decode/is-keymap "$base_keymap" && return 0 fi ble/edit/marker#instantiate "The definition of the default keymap \"$defmap\" is not found. ble.sh uses \"safe\" keymap instead." error local msg=$ret ble/edit/enter-command-layout # #D1800 pair=leave-command-layout ble/widget/.hide-current-line local -a DRAW_BUFF=() ble/canvas/put.draw "$_ble_term_cr$_ble_term_el$msg$_ble_term_nl" ble/canvas/bflush.draw ble/util/buffer.flush ble/edit/leave-command-layout # #D1800 pair=enter-command-layout ble-edit/bind/load-editing-mode safe && ble/decode/keymap#load safe && builtin eval -- "$2=safe" && bleopt_default_keymap=safe } function ble-edit/bind/load-editing-mode { local name=$1 if ble/is-function ble-edit/bind/load-editing-mode:"$name"; then ble-edit/bind/load-editing-mode:"$name" else ble/util/import "$_ble_base/lib/keymap.$name.sh" fi } function ble-edit/bind/clear-keymap-definition-loader { builtin unset -f ble-edit/bind/load-editing-mode:safe builtin unset -f ble-edit/bind/load-editing-mode:emacs builtin unset -f ble-edit/bind/load-editing-mode:vi } function ble-edit/initialize { ble/prompt/initialize } function ble-edit/attach { _ble_builtin_trap_DEBUG__initialize [[ $_ble_builtin_trap_DEBUG_userTrapInitialized ]] && _ble_edit_exec_gexec__TRAPDEBUG_adjust ble-edit/attach/.attach _ble_canvas_x=0 _ble_canvas_y=0 ble/util/buffer "$_ble_term_cr" } function ble-edit/detach { ble-edit/bind/stdout.finalize ble-edit/attach/.detach ble-edit/exec:gexec/.TRAPDEBUG/restore } ble/function#trace ble-edit/attach function ble/util/message/handler:edit/append-line { local data=${1%$'\n'}; data=${data#$'\n'} [[ ${_ble_edit_str##*$'\n'} ]] && data=$'\n'$data local len=${#_ble_edit_str} ble-edit/content/replace-limited "$len" "$len" "$data" nobell _ble_edit_ind=${#_ble_edit_str} return 0 } function ble-append-line { local data="${*-}" [[ $data ]] || return 0 builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" ble/util/message.post "$$" precmd edit/append-line "$data" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" } function ble/cmdspec/initialize { ble-import "$_ble_base/lib/core-cmdspec.sh"; } ble/is-function ble/util/idle.push && ble-import -d "$_ble_base/lib/core-cmdspec.sh" builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_cmdspec_opts}" function ble/cmdspec/opts { local spec=$1 command; shift for command; do local spec1=$spec if [[ $spec1 == +* ]]; then local ret= ble/gdict#get _ble_cmdspec_opts "$command" "$spec1" spec1=${ret:+$ret:}${spec1:1} fi ble/gdict#set _ble_cmdspec_opts "$command" "$spec1" done } function ble/cmdspec/opts#load { cmdspec_opts=$2 local ret= if ble/gdict#get _ble_cmdspec_opts "$1" || { [[ $1 == */*[!/] ]] && ble/gdict#get _ble_cmdspec_opts "${1##*/}"; } then cmdspec_opts=$ret fi } _ble_syntax_VARNAMES=( _ble_syntax_text _ble_syntax_lang _ble_syntax_stat _ble_syntax_nest _ble_syntax_tree _ble_syntax_attr _ble_syntax_attr_umin _ble_syntax_attr_umax _ble_syntax_word_umin _ble_syntax_word_umax _ble_syntax_vanishing_word_umin _ble_syntax_vanishing_word_umax _ble_syntax_dbeg _ble_syntax_dend) _ble_syntax_lang=bash function ble/syntax/initialize-vars { _ble_syntax_text= _ble_syntax_lang=bash _ble_syntax_stat=() _ble_syntax_nest=() _ble_syntax_tree=() _ble_syntax_attr=() _ble_syntax_attr_umin=-1 _ble_syntax_attr_umax=-1 _ble_syntax_word_umin=-1 _ble_syntax_word_umax=-1 _ble_syntax_vanishing_word_umin=-1 _ble_syntax_vanishing_word_umax=-1 _ble_syntax_dbeg=-1 _ble_syntax_dend=-1 } function ble/highlight/layer:syntax/update { true; } function ble/highlight/layer:syntax/getg { true; } function ble/syntax:bash/is-complete { true; } ble/util/autoload "$_ble_base/lib/core-syntax.sh" \ ble/syntax/parse \ ble/syntax/highlight \ ble/syntax/tree-enumerate \ ble/syntax/tree-enumerate-children \ ble/syntax/completion-context/generate \ ble/syntax/highlight/cmdtype \ ble/syntax/highlight/cmdtype1 \ ble/syntax/highlight/filetype \ ble/syntax/highlight/getg-from-filename \ ble/syntax:bash/extract-command \ ble/syntax:bash/simple-word/eval \ ble/syntax:bash/simple-word/evaluate-path-spec \ ble/syntax:bash/simple-word/is-never-word \ ble/syntax:bash/simple-word/is-simple \ ble/syntax:bash/simple-word/is-simple-or-open-simple \ ble/syntax:bash/simple-word/reconstruct-incomplete-word \ ble/syntax:bash/simple-word/get-rex_element bleopt/declare -v syntax_debug '' bleopt/declare -v filename_ls_colors '' bleopt/declare -v highlight_syntax 1 bleopt/declare -v highlight_filename 1 bleopt/declare -v highlight_variable 1 bleopt/declare -v highlight_timeout_sync 50 bleopt/declare -v highlight_timeout_async 5000 bleopt/declare -v syntax_eval_polling_interval 50 builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_syntax_highlight_filetype}" builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_syntax_highlight_lscolors_ext}" builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_syntax_highlight_lscolors_suffix}" builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_syntax_bash_simple_eval}" builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_syntax_bash_simple_eval_full}" function ble/syntax/attr2g { ble/color/initialize-faces && ble/syntax/attr2g "$@"; } function ble/syntax/defface.onload { function ble/syntax/attr2g { local iface=${_ble_syntax_attr2iface[$1]:-_ble_faces__syntax_default} g=${_ble_faces[iface]} } ble/color/defface syntax_default none ble/color/defface syntax_command fg=brown ble/color/defface syntax_quoted fg=green ble/color/defface syntax_quotation fg=green,bold ble/color/defface syntax_escape fg=magenta ble/color/defface syntax_expr fg=26 ble/color/defface syntax_error bg=203,fg=231 # bg=224 ble/color/defface syntax_varname fg=202 ble/color/defface syntax_delimiter bold ble/color/defface syntax_param_expansion fg=purple ble/color/defface syntax_history_expansion bg=94,fg=231 ble/color/defface syntax_function_name fg=92,bold # fg=purple ble/color/defface syntax_comment fg=242 ble/color/defface syntax_glob fg=198,bold ble/color/defface syntax_brace fg=37,bold ble/color/defface syntax_tilde fg=navy,bold ble/color/defface syntax_document fg=94 ble/color/defface syntax_document_begin fg=94,bold ble/color/defface command_builtin_dot fg=red,bold ble/color/defface command_builtin fg=red ble/color/defface command_alias fg=teal ble/color/defface command_function fg=92 # fg=purple ble/color/defface command_file fg=green ble/color/defface command_keyword fg=blue ble/color/defface command_jobs fg=red,bold ble/color/defface command_directory fg=26,underline ble/color/defface command_suffix fg=white,bg=green ble/color/defface command_suffix_new fg=white,bg=brown ble/color/defface filename_directory underline,fg=26 ble/color/defface filename_directory_sticky underline,fg=white,bg=26 ble/color/defface filename_link underline,fg=teal ble/color/defface filename_orphan underline,fg=teal,bg=224 ble/color/defface filename_setuid underline,fg=black,bg=220 ble/color/defface filename_setgid underline,fg=black,bg=191 ble/color/defface filename_executable underline,fg=green ble/color/defface filename_other underline ble/color/defface filename_socket underline,fg=cyan,bg=black ble/color/defface filename_pipe underline,fg=lime,bg=black ble/color/defface filename_character underline,fg=white,bg=black ble/color/defface filename_block underline,fg=yellow,bg=black ble/color/defface filename_warning underline,fg=red ble/color/defface filename_url underline,fg=blue ble/color/defface filename_ls_colors underline ble/color/defface varname_unset fg=124 ble/color/defface varname_empty fg=31 ble/color/defface varname_number fg=64 ble/color/defface varname_expr fg=92,bold ble/color/defface varname_array fg=orange,bold ble/color/defface varname_hash fg=70,bold ble/color/defface varname_readonly fg=200 ble/color/defface varname_transform fg=29,bold ble/color/defface varname_export fg=200,bold ble/color/defface argument_option fg=teal ble/color/defface argument_error fg=black,bg=225 } blehook/eval-after-load color_defface ble/syntax/defface.onload function ble/syntax/import { ble/util/import "$_ble_base/lib/core-syntax.sh" } ble-import -d lib/core-syntax ble/is-function ble/util/idle.push && ble-import -d "$_ble_base/lib/core-complete.sh" ble/util/autoload "$_ble_base/lib/core-complete.sh" \ ble/widget/complete \ ble/widget/menu-complete \ ble/widget/auto-complete-enter \ ble/widget/sabbrev-expand \ ble/widget/dabbrev-expand function ble-sabbrev { local arg print= for arg; do if [[ $arg != -* && $arg != *=* ]]; then print=1 break fi done if (($#==0)) || [[ $print ]]; then ble-import lib/core-complete && ble-sabbrev "$@" return "$?" fi local ret; ble/string#quote-command "$FUNCNAME" "$@" blehook/eval-after-load complete "$ret" } if ! declare -p _ble_complete_sabbrev &>/dev/null; then # reload #D0875 _ble_complete_sabbrev_version=0 builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_complete_sabbrev}" fi bleopt/declare -n complete_polling_cycle 50 bleopt/declare -o complete_stdin_frequency complete_polling_cycle bleopt/declare -v complete_limit '' bleopt/declare -v complete_limit_auto 2000 bleopt/declare -v complete_limit_auto_menu 100 bleopt/declare -v complete_timeout_auto 5000 bleopt/declare -v complete_timeout_compvar 200 bleopt/declare -v complete_ambiguous 1 bleopt/declare -v complete_contract_function_names 1 bleopt/declare -v complete_auto_complete 1 bleopt/declare -v complete_auto_complete_opts '' bleopt/declare -v complete_auto_history 1 bleopt/declare -n complete_auto_delay 1 bleopt/declare -v complete_auto_wordbreaks "$_ble_term_IFS" bleopt/declare -v complete_auto_menu '' bleopt/declare -v complete_allow_reduction '' bleopt/declare -v complete_requote_threshold 0 bleopt/declare -n complete_menu_style align-nowrap function bleopt/check:complete_menu_style { [[ $value == desc-raw ]] && value=desc if ! ble/is-function "ble/complete/menu-style:$value/construct-page"; then ble/util/print-lines \ "bleopt: Invalid value complete_menu_style='$value'." \ " A function 'ble/complete/menu-style:$value/construct-page' is not defined." >&2 return 1 fi return 0 } ble/util/autoload "$_ble_base/lib/core-complete.sh" \ ble/complete/menu-style:{align,dense}{,-nowrap}/construct-page \ ble/complete/menu-style:linewise/construct-page \ ble/complete/menu-style:desc{,-text,-raw}/construct-page bleopt/declare -v complete_menu_complete 1 bleopt/declare -v complete_menu_complete_opts 'insert-selection' bleopt/declare -v complete_menu_filter 1 bleopt/declare -v complete_menu_maxlines '-1' function bleopt/check:complete_menu_complete_opts { if [[ :$value: == *:hidden:* && :$value: != *:insert-selection:* ]]; then value=$value:insert-selection fi return 0 } bleopt/declare -v complete_skip_matched on bleopt/declare -v complete_menu_color on bleopt/declare -v complete_menu_color_match on function ble/complete/.init-bind-readline-variables { local _ble_local_rlvars; ble/util/rlvar#load ble/util/rlvar#bind-bleopt skip-completed-text complete_skip_matched bool ble/util/rlvar#bind-bleopt colored-stats complete_menu_color bool ble/util/rlvar#bind-bleopt colored-completion-prefix complete_menu_color_match bool builtin unset -f "$FUNCNAME" } ble/complete/.init-bind-readline-variables bleopt/declare -v menu_prefix '' bleopt/declare -v menu_align_prefix '' bleopt/declare -n menu_align_min 4 bleopt/declare -n menu_align_max 20 bleopt/declare -o complete_menu_align menu_align_max bleopt/declare -v menu_dense_prefix '' bleopt/declare -v menu_linewise_prefix '' bleopt/declare -v menu_desc_prefix '' bleopt/declare -v menu_desc_multicolumn_width 65 ble/util/autoload "$_ble_base/lib/core-complete.sh" \ ble/complete/menu#start \ ble-decode/keymap:menu/define \ ble-decode/keymap:auto_complete/define \ ble-decode/keymap:menu_complete/define \ ble-decode/keymap:dabbrev/define \ ble/complete/sabbrev/expand \ ble/complete/expand:alias \ ble/complete/expand:autocd bleopt/declare -v complete_source_sabbrev_opts '' bleopt/declare -v complete_source_sabbrev_ignore '' _ble_complete_source_sabbrev_ignore=() function bleopt/check:complete_source_sabbrev_ignore { if [[ $value ]]; then ble/string#split _ble_complete_source_sabbrev_ignore : "$value" else _ble_complete_source_sabbrev_ignore=() fi } ble/color/defface auto_complete bg=254,fg=238 ble/color/defface cmdinfo_cd_cdpath fg=26,bg=155 ble/color/defface menu_filter_fixed bold ble/color/defface menu_filter_input fg=16,bg=229 ble/color/defface menu_desc_default none ble/color/defface menu_desc_type ref:syntax_delimiter ble/color/defface menu_desc_quote ref:syntax_quoted ble/util/autoload "$_ble_base/lib/core-debug.sh" \ ble/debug/setdbg \ ble/debug/print \ ble/debug/print-variables \ ble/debug/stopwatch/start \ ble/debug/stopwatch/stop \ ble/debug/profiler/start \ ble/debug/profiler/stop bleopt/declare -v debug_profiler_opts line:func bleopt/declare -n debug_profiler_tree_threshold 5.0 function ble/contrib/integration:bash-preexec/loader { if [[ ${bash_preexec_imported-${__bp_imported}} ]]; then blehook ATTACH-=ble/contrib/integration:bash-preexec/loader blehook POSTEXEC-=ble/contrib/integration:bash-preexec/loader if ble/util/import/is-loaded contrib/bash-preexec; then ble/contrib/integration:bash-preexec/attach.hook else ble-import contrib/integration/bash-preexec fi fi } if [[ ${bash_preexec_imported-${__bp_imported}} ]]; then ble-import contrib/integration/bash-preexec else blehook ATTACH!=ble/contrib/integration:bash-preexec/loader blehook POSTEXEC!=ble/contrib/integration:bash-preexec/loader fi ble/function#try ble/util/idle.push ble/base/clean-up-runtime-directory bleopt -I ble/bin#freeze-utility-path ble function ble/dispatch/.help { ble/util/print-lines \ 'usage: ble [SUBCOMMAND [ARGS...]]' \ '' \ 'SUBCOMMAND' \ ' # Manage ble.sh' \ ' attach ... alias of ble-attach' \ ' detach ... alias of ble-detach' \ ' update ... alias of ble-update' \ ' reload ... alias of ble-reload' \ ' help ... Show this help' \ ' version ... Show version' \ ' check ... Run unit tests' \ '' \ ' # Configuration' \ ' opt ... alias of bleopt' \ ' bind ... alias of ble-bind' \ ' face ... alias of ble-face' \ ' hook ... alias of blehook' \ ' sabbrev ... alias of ble-sabbrev' \ ' palette ... alias of ble-color-show' \ '' } function ble/dispatch { if (($#==0)); then [[ $_ble_attached && ! $_ble_edit_exec_inside_userspace ]] return "$?" fi local cmd=$1; shift case $cmd in (attach) ble-attach "$@" ;; (detach) ble-detach "$@" ;; (update) ble-update "$@" ;; (reload) ble-reload "$@" ;; (face) ble-face "$@" ;; (bind) ble-bind "$@" ;; (opt) bleopt "$@" ;; (hook) blehook "$@" ;; (sabbrev) ble-sabbrev "$@" ;; (palette) ble-palette "$@" ;; (help|--help) ble/dispatch/.help "$@" ;; (version|--version) ble/util/print "ble.sh, version $BLE_VERSION (noarch)" ;; (check|--test) ble/base/sub:test "$@" ;; (*) if ble/string#match "$cmd" '^[-a-zA-Z0-9]+$' && ble/is-function "ble-$cmd"; then "ble-$cmd" "$@" elif ble/is-function ble/bin/ble; then ble/bin/ble "$cmd" "$@" else ble/util/print "ble (ble.sh): unrecognized subcommand '$cmd'." >&2 return 2 fi esac } function ble { case ${1-} in (attach|detach|update|reload) "ble-$@" ;; (*) builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" ble/dispatch "$@" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_return" ;; esac } _ble_base_rcfile= _ble_base_rcfile_initialized= function ble/base/load-rcfile { [[ $_ble_base_rcfile_initialized ]] && return 0 _ble_base_rcfile_initialized=1 if [[ ! $_ble_base_rcfile ]]; then { _ble_base_rcfile=$HOME/.blerc; [[ -f $_ble_base_rcfile ]]; } || { _ble_base_rcfile=${XDG_CONFIG_HOME:-$HOME/.config}/blesh/init.sh; [[ -f $_ble_base_rcfile ]]; } || _ble_base_rcfile=$HOME/.blerc fi if [[ -s $_ble_base_rcfile ]]; then source "$_ble_base_rcfile" blehook/.compatibility-ble-0.3/check fi } function ble-attach { if (($# >= 2)); then builtin printf '%s\n' \ 'usage: ble-attach [opts]' \ 'Attach to ble.sh.' >&2 [[ $1 != --help ]] && return 2 return 0 fi if [[ $_ble_edit_detach_flag ]]; then case $_ble_edit_detach_flag in (exit) return 0 ;; (*) _ble_edit_detach_flag= ;; # cancel "detach" esac fi [[ ! $_ble_attached ]] || return 0 _ble_attached=1 BLE_ATTACHED=1 builtin eval -- "$_ble_bash_FUNCNEST_adjust" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_adjust" ble/base/adjust-builtin-wrappers ble/base/adjust-bash-options ble/base/adjust-BASH_REMATCH if [[ ${IN_NIX_SHELL-} ]]; then if [[ "${BASH_SOURCE[*]}" == */rc && $1 != *:force:* ]]; then ble/base/install-prompt-attach _ble_attached= BLE_ATTACHED= ble/base/restore-BASH_REMATCH ble/base/restore-bash-options ble/base/restore-builtin-wrappers ble/base/restore-POSIXLY_CORRECT builtin eval -- "$_ble_bash_FUNCNEST_restore" return 0 fi local ret ble/util/readlink "/proc/$$/exe" [[ -x $ret ]] && BASH=$ret fi ble/fd/save-external-standard-streams exec 0<&"$_ble_util_fd_tui_stdin" exec 1>&"$_ble_util_fd_tui_stdout" exec 2>&"$_ble_util_fd_tui_stderr" ble/term/initialize # 0.4ms ble/term/attach noflush # 2.5ms (起動時のずれ防止の為 stty -echo は早期に) ble/canvas/attach # 1.8ms (requests for char_width_mode=auto) ble/util/buffer.flush # 0.3ms ble-edit/initialize # 0.3ms ble-edit/attach # 2.1ms (_ble_edit_PS1 他の初期化) ble_attach_first_prompt=1 \ ble/canvas/panel/render # 42ms ble/util/buffer.flush # 0.2ms local IFS=$_ble_term_IFS ble/decode/initialize # 7ms ble/decode/reset-default-keymap # 264ms (keymap/vi.sh) if ! ble/decode/attach; then # 53ms _ble_attached= BLE_ATTACHED= ble-edit/detach ble/term/leave ble/base/restore-BASH_REMATCH ble/base/restore-bash-options ble/base/restore-builtin-wrappers ble/base/restore-POSIXLY_CORRECT builtin eval -- "$_ble_bash_FUNCNEST_restore" return 1 fi ble/history:bash/reset # 27s for bash-3.0 ble-edit/restore-PS1 blehook/invoke ATTACH ble-edit/adjust-PS1 ble/textarea#redraw ble/edit/info/default ble-edit/bind/.tail } function ble-detach { if (($#)); then builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_adjust" ble/base/print-usage-for-no-argument-command 'Detach from ble.sh.' "$@" builtin eval -- "$_ble_bash_POSIXLY_CORRECT_local_leave" return 2 fi [[ $_ble_attached && ! $_ble_edit_detach_flag ]] || return 1 _ble_edit_detach_flag=${1:-detach} # schedule detach } function ble-detach/impl { [[ $_ble_attached ]] || return 1 _ble_attached= BLE_ATTACHED= blehook/invoke DETACH ble-edit/detach ble/decode/detach READLINE_LINE='' READLINE_POINT=0 } function ble-detach/message { ble/util/buffer.print-lines "$@" ble/util/buffer.flush ble/edit/info/clear ble/textarea#render ble/util/buffer.flush } function ble/base/unload-for-reload { if [[ $_ble_attached ]]; then ble-detach/impl local ret ble/edit/marker#instantiate 'reload' && ble/util/print "$ret" >&"$_ble_util_fd_tui_stderr" [[ $_ble_edit_detach_flag ]] || _ble_edit_detach_flag=reload fi local _ble_bash=$_ble_bash ble/base/unload reload return 0 } function ble/base/unload { ble/util/is-running-in-subshell && return 1 local IFS=$_ble_term_IFS builtin eval -- "$_ble_bash_POSIXLY_CORRECT_adjust" ble/base/adjust-builtin-wrappers ble/base/adjust-bash-options ble/base/adjust-BASH_REMATCH ble-edit/bind/clear-keymap-definition-loader ble/widget/.bell/.clear-DECSCNM ble/decode/keymap#unload ble/term/stty/TRAPEXIT "$1" ble/term/leave ble/util/buffer.flush blehook/invoke unload ble/builtin/trap/finalize "$1" ble/util/import/finalize ble/base/clean-up-runtime-directory finalize ble/fd#finalize # this is used by the above function ble/base/clear-version-variables return 0 } 0<&"$_ble_util_fd_tui_stdin" 1>&"$_ble_util_fd_tui_stdout" 2>&"$_ble_util_fd_tui_stderr" _ble_base_attach_from_prompt= ((${#_ble_base_attach_PROMPT_COMMAND[@]})) || _ble_base_attach_PROMPT_COMMAND=() function ble/base/install-prompt-attach { [[ ! $_ble_base_attach_from_prompt ]] || return 0 _ble_base_attach_from_prompt=1 if ((_ble_bash>=50100)); then ((${#PROMPT_COMMAND[@]})) || PROMPT_COMMAND[0]= ble/array#push PROMPT_COMMAND ble/base/attach-from-PROMPT_COMMAND if [[ $_ble_edit_detach_flag == reload ]]; then _ble_edit_detach_flag=prompt-attach blehook internal_PRECMD!=ble/base/attach-from-PROMPT_COMMAND fi else local save_index=${#_ble_base_attach_PROMPT_COMMAND[@]} _ble_base_attach_PROMPT_COMMAND[save_index]=${PROMPT_COMMAND-} ble/function#lambda PROMPT_COMMAND \ "ble/base/attach-from-PROMPT_COMMAND $save_index \"\$FUNCNAME\"" ble/function#trace "$PROMPT_COMMAND" if [[ $_ble_edit_detach_flag == reload ]]; then _ble_edit_detach_flag=prompt-attach blehook internal_PRECMD!="$PROMPT_COMMAND" fi fi } _ble_base_attach_from_prompt_lastexit= _ble_base_attach_from_prompt_lastarg= _ble_base_attach_from_prompt_PIPESTATUS=() function ble/base/attach-from-PROMPT_COMMAND { { _ble_base_attach_from_prompt_lastexit=$? \ _ble_base_attach_from_prompt_lastarg=$_ \ _ble_base_attach_from_prompt_PIPESTATUS=("${PIPESTATUS[@]}") if ((BASH_LINENO[${#BASH_LINENO[@]}-1]>=1)); then _ble_edit_exec_lastexit=$_ble_base_attach_from_prompt_lastexit _ble_edit_exec_lastarg=$_ble_base_attach_from_prompt_lastarg _ble_edit_exec_PIPESTATUS=("${_ble_base_attach_from_prompt_PIPESTATUS[@]}") _ble_edit_exec_BASH_COMMAND=$FUNCNAME fi local is_last_PROMPT_COMMAND=1 if (($#==0)); then if local ret; ble/array#index PROMPT_COMMAND ble/base/attach-from-PROMPT_COMMAND; then local keys; keys=("${!PROMPT_COMMAND[@]}") ((ret==keys[${#keys[@]}-1])) || is_last_PROMPT_COMMAND= ble/idict#replace PROMPT_COMMAND ble/base/attach-from-PROMPT_COMMAND fi blehook internal_PRECMD-=ble/base/attach-from-PROMPT_COMMAND || ((1)) # set -e 対策 else local save_index=$1 lambda=$2 local PROMPT_COMMAND=${_ble_base_attach_PROMPT_COMMAND[save_index]} local ble_base_attach_from_prompt_command=processing ble/prompt/update/.eval-prompt_command 2>&"$_ble_util_fd_tui_stderr" ble/util/unlocal ble_base_attach_from_prompt_command _ble_base_attach_PROMPT_COMMAND[save_index]=$PROMPT_COMMAND ble/util/unlocal PROMPT_COMMAND blehook internal_PRECMD-="$lambda" || ((1)) # set -e 対策 if [[ $PROMPT_COMMAND == "$lambda" ]]; then PROMPT_COMMAND=${_ble_base_attach_PROMPT_COMMAND[save_index]} else is_last_PROMPT_COMMAND= fi [[ ${ble_base_attach_from_prompt_command-} != processing ]] || return 0 fi [[ $_ble_base_attach_from_prompt ]] || return 0 _ble_base_attach_from_prompt= if [[ $is_last_PROMPT_COMMAND ]]; then ble-edit/exec:gexec/invoke-hook-with-setexit internal_PRECMD ble-edit/exec:gexec/invoke-hook-with-setexit PRECMD _ble_prompt_hash=$COLUMNS:$_ble_edit_lineno:prompt_attach fi } 2>/dev/null # set -x 対策 #D0930 ble-attach force ble/util/joblist.flush &>/dev/null ble/util/joblist.check } function ble/base/process-blesh-arguments { local opts=$_ble_base_arguments_opts local attach=$_ble_base_arguments_attach local inputrc=$_ble_base_arguments_inputrc _ble_base_rcfile=$_ble_base_arguments_rcfile _ble_decode_initialize_inputrc=$inputrc ble/base/load-rcfile # blerc ble/util/invoke-hook BLE_ONLOAD case $attach in (attach) ble-attach ;; (prompt) ble/base/install-prompt-attach ;; (none) ;; (*) ble/util/print "ble.sh: unrecognized attach method --attach='$attach'." ;; esac } function ble/base/sub:test { local error= logfile= [[ ${LANG-} ]] || local LANG=en_US.UTF-8 ble-import lib/core-test if (($#==0)); then set -- bash main util canvas decode edit syntax complete keymap.vi logfile=$_ble_base_cache/test.$(date +'%Y%m%d.%H%M%S').log >| "$logfile" ble/test/log#open "$logfile" fi if ((!_ble_make_command_check_count)); then ble/test/log "MACHTYPE: $MACHTYPE" ble/test/log "BLE_VERSION: $BLE_VERSION" fi ble/test/log "BASH_VERSION: $BASH_VERSION" local line='locale:' var ret for var in LANG "${!LC_@}"; do ble/string#quote-word "${!var}" line="$line $var=$ret" done ble/test/log "$line" local _ble_test_section_failure_count=0 local section for section; do local file=$_ble_base/lib/test-$section.sh if [[ -f $file ]]; then source "$file" else ble/test/log "ERROR: Test '$section' is not defined." error=1 fi done ((_ble_test_section_failure_count)) && error=1 if [[ $logfile ]]; then ble/test/log#close ble/util/print "ble.sh: The test log was saved to '${_ble_term_setaf[4]}$logfile$_ble_term_sgr0'." fi [[ ! $error ]] } function ble/base/sub:update { ble-update; } function ble/base/sub:clear-cache { (shopt -u failglob; ble/bin/rm -rf "$_ble_base_cache"/*) } function ble/base/sub:install { local insdir=${1:-${XDG_DATA_HOME:-$HOME/.local/share}}/blesh local dir=$insdir sudo= [[ $dir == /* ]] || dir=./$dir while [[ $dir && ! -d $dir ]]; do dir=${dir%/*} done [[ $dir ]] || dir=/ if ! [[ -r $dir && -w $dir && -x $dir ]]; then if ((EUID!=0)) && [[ ! -O $dir ]] && ble/bin#has sudo; then sudo=1 else ble/util/print "ble.sh --install: $dir: permission denied" >&2 return 1 fi fi if [[ ${_ble_base_repository-} == release:nightly-* ]]; then if [[ $insdir == "$_ble_base" ]]; then ble/util/print "ble.sh --install: already installed" >&2 return 1 fi local ret ble/string#quote-word "$insdir"; local qinsdir=$ret ble/string#quote-word "$_ble_base"; local qbase=$ret if [[ $sudo ]]; then ble/util/print "\$ sudo mkdir -p $qinsdir" sudo mkdir -p "$insdir" ble/util/print "\$ sudo cp -Rf $qbase/* $qinsdir/" sudo cp -Rf "$_ble_base"/* "$insdir/" ble/util/print "\$ sudo rm -rf $qinsdir/{cache.d,run}" sudo rm -rf "$insdir"/{cache.d,run} else ble/util/print "\$ mkdir -p $qinsdir" ble/bin/mkdir -p "$insdir" ble/util/print "\$ cp -Rf $qbase/* $qinsdir/" ble/bin/cp -Rf "$_ble_base"/* "$insdir/" ble/util/print "\$ rm -rf $qinsdir/cache.d/*" ble/bin/rm -rf "$insdir/cache.d"/* fi elif local make; ble-update/.check-build-dependencies && ble-update/.check-repository; then ( ble/util/print "cd into $_ble_base_repository..." >&2 && builtin cd "$_ble_base_repository" && ble-update/.make ${sudo:+--sudo} install INSDIR="$insdir" ) else ble/util/print "ble.sh --install: not supported." >&2 return 1 fi } function ble/base/sub:lib { return 0; } # do nothing ble/function#trace ble-attach ble/function#trace ble ble/function#trace ble/dispatch ble/function#trace ble/base/attach-from-PROMPT_COMMAND ble/function#trace ble/base/unload ble-import -f lib/_package if [[ $_ble_init_command ]]; then ble/base/sub:"${_ble_init_command[@]}"; _ble_init_exit=$? [[ $_ble_init_attached ]] && ble-attach ble/util/setexit "$_ble_init_exit" else ble/base/process-blesh-arguments "$@" fi ble/init/clean-up check-attach 2>/dev/null # set -x 対策 #D0930 { builtin eval "return $? || exit $?"; } 2>/dev/null # set -x 対策 #D0930