From c3362aefa2e762211409923cfff065541bebf9e7 Mon Sep 17 00:00:00 2001 From: Saumit Dinesan Date: Sun, 22 May 2022 00:37:40 +0530 Subject: ble.sh & z4h addition --- .local/src/blesh/lib/core-syntax.sh | 5355 +++++++++++++++++++++++++++++++++++ 1 file changed, 5355 insertions(+) create mode 100644 .local/src/blesh/lib/core-syntax.sh (limited to '.local/src/blesh/lib/core-syntax.sh') diff --git a/.local/src/blesh/lib/core-syntax.sh b/.local/src/blesh/lib/core-syntax.sh new file mode 100644 index 0000000..bd566f9 --- /dev/null +++ b/.local/src/blesh/lib/core-syntax.sh @@ -0,0 +1,5355 @@ +# this script is a part of blesh (https://github.com/akinomyoga/ble.sh) under BSD-3-Clause license +function ble/syntax/util/is-directory { + local path=$1 + if [[ ( $OSTYPE == cygwin || $OSTYPE == msys ) && $path == //* ]]; then + [[ $path == // ]] + else + [[ -d $path ]] + fi +} +function ble/syntax/urange#update { + local prefix=$1 + local p1=$2 p2=${3:-$2} + ((0<=p1&&p1p1)&&(${prefix}umin=p1), + (${prefix}umax<0||${prefix}umaxp1)&&(${prefix}umin=p1), + (${prefix}umax<0||${prefix}umax=end0?(${prefix}umin+=shift):( + ${prefix}umin>=beg&&(${prefix}umin=end)), + ${prefix}umax>end0?(${prefix}umax+=shift):( + ${prefix}umax>beg&&(${prefix}umax=beg)), + ${prefix}umin>=${prefix}umax&& + (${prefix}umin=${prefix}umax=-1))) +} +function ble/syntax/wrange#shift { + local prefix=$1 + ((${prefix}umin>=end0?(${prefix}umin+=shift):( + ${prefix}umin>beg&&(${prefix}umin=end)), + ${prefix}umax>=end0?(${prefix}umax+=shift):( + ${prefix}umax>=beg&&(${prefix}umax=beg)), + ${prefix}umin==0&&++${prefix}umin, + ${prefix}umin>${prefix}umax&& + (${prefix}umin=${prefix}umax=-1))) +} +_ble_syntax_text= +_ble_syntax_lang=bash +_ble_syntax_stat=() +_ble_syntax_nest=() +_ble_syntax_tree=() +_ble_syntax_attr=() +_ble_syntax_TREE_WIDTH=5 +function ble/syntax/tree-enumerate/.add-root-element { + local wtype=$1 wlen=$2 tclen=$3 tplen=$4 + [[ ! ${wtype//[0-9]} && ${_ble_syntax_bash_command_EndWtype[wtype]} ]] && + wtype=${_ble_syntax_bash_command_EndWtype[wtype]} + TE_root="$wtype $wlen $tclen $tplen -- $TE_root" +} +function ble/syntax/tree-enumerate/.initialize { + if [[ ! ${_ble_syntax_stat[iN]} ]]; then + TE_root= TE_i=-1 TE_nofs=0 + return 0 + fi + local -a stat nest + ble/string#split-words stat "${_ble_syntax_stat[iN]}" + local wtype=${stat[2]} + local wlen=${stat[1]} + local nlen=${stat[3]} inest + ((inest=nlen<0?nlen:iN-nlen)) + local tclen=${stat[4]} + local tplen=${stat[5]} + TE_root= + ((iN>0)) && TE_root=${_ble_syntax_tree[iN-1]} + while + if ((wlen>=0)); then + ble/syntax/tree-enumerate/.add-root-element "$wtype" "$wlen" "$tclen" "$tplen" + tclen=0 + fi + ((inest>=0)) + do + ble/util/assert '[[ ${_ble_syntax_nest[inest]} ]]' "$FUNCNAME/FATAL1" || break + ble/string#split-words nest "${_ble_syntax_nest[inest]}" + local olen=$((iN-inest)) + tplen=${nest[4]} + ((tplen>=0&&(tplen+=olen))) + ble/syntax/tree-enumerate/.add-root-element "${nest[7]}" "$olen" "$tclen" "$tplen" + wtype=${nest[2]} wlen=${nest[1]} nlen=${nest[3]} tclen=0 tplen=${nest[5]} + ((wlen>=0&&(wlen+=olen), + tplen>=0&&(tplen+=olen), + nlen>=0&&(nlen+=olen), + inest=nlen<0?nlen:iN-nlen)) + ble/util/assert '((nlen<0||nlen>olen))' "$FUNCNAME/FATAL2" || break + done + if [[ $TE_root ]]; then + ((TE_i=iN)) + else + ((TE_i=tclen>=0?iN-tclen:tclen)) + fi + ((TE_nofs=0)) +} +function ble/syntax/tree-enumerate/.impl { + local islast=1 + while ((TE_i>0)); do + local -a node + if ((TE_i=beg;TE_i--)); do + ((TE_i>0)) && [[ ${_ble_syntax_tree[TE_i-1]} ]] || continue + ble/string#split-words node "${_ble_syntax_tree[TE_i-1]}" + local flagUpdateNode= + for ((TE_nofs=0;TE_nofs<${#node[@]};TE_nofs+=_ble_syntax_TREE_WIDTH)); do + local wtype=${node[TE_nofs]} wlen=${node[TE_nofs+1]} wattr=${node[TE_nofs+4]} + local wbeg=$((wlen<0?wlen:TE_i-wlen)) wend=$TE_i + "${@:3}" + done + done +} +function ble/syntax/print-status/.graph { + local char=$1 + if ble/util/isprint+ "$char"; then + graph="'$char'" + return 0 + else + local ret + ble/util/s2c "$char" + local code=$ret + if ((code<32)); then + ble/util/c2s $((code+64)) + graph="$_ble_term_rev^$ret$_ble_term_sgr0" + elif ((code==127)); then + graph="$_ble_term_rev^?$_ble_term_sgr0" + elif ((128<=code&&code<160)); then + ble/util/c2s $((code-64)) + graph="${_ble_term_rev}M-^$ret$_ble_term_sgr0" + else + graph="'$char' ($code)" + fi + fi +} +function ble/syntax/print-status/.tree-prepend { + local j=$1 + local value=$2${tree[j]} + tree[j]=$value + ((max_tree_width<${#value}&&(max_tree_width=${#value}))) +} +function ble/syntax/print-status/.dump-arrays/.append-attr-char { + if (($?==0)); then + attr="${attr}$1" + else + attr="${attr} " + fi +} +function ble/syntax/print-status/ctx#get-text { + local sgr + ble/syntax/ctx#get-name "$1" + ret=${ret#BLE_} + if [[ ! $ret ]]; then + ble/color/face2sgr syntax_error + ret="${ret}CTX$1$_ble_term_sgr0" + fi +} +function ble/syntax/print-status/word.get-text { + local index=$1 + ble/string#split-words word "${_ble_syntax_tree[index]}" + local out= ret + if [[ $word ]]; then + local nofs=$((${#word[@]}/_ble_syntax_TREE_WIDTH*_ble_syntax_TREE_WIDTH)) + while (((nofs-=_ble_syntax_TREE_WIDTH)>=0)); do + local axis=$((index+1)) + local wtype=${word[nofs]} + if [[ $wtype =~ ^[0-9]+$ ]]; then + ble/syntax/print-status/ctx#get-text "$wtype"; wtype=$ret + elif [[ $wtype =~ ^n* ]]; then + wtype=$sgr_quoted\"${wtype:1}\"$_ble_term_sgr0 + else + wtype=$sgr_error${wtype}$_ble_term_sgr0 + fi + local b=$((axis-word[nofs+1])) e=$axis + local _prev=${word[nofs+3]} _child=${word[nofs+2]} + if ((_prev>=0)); then + _prev="@$((axis-_prev-1))>" + else + _prev= + fi + if ((_child>=0)); then + _child=">@$((axis-_child-1))" + else + _child= + fi + local wattr=${word[nofs+4]} _wattr= + if [[ $wattr != - ]]; then + wattr="/(wattr=$wattr)" + else + wattr= + fi + out=" word=$wtype:$_prev$b-$e$_child$wattr$out" + for ((;b=0)); then + ble/syntax/print-status/ctx#get-text "${nest[2]}"; local swtype=$ret + local wbegin=$((index-nest[1])) + nword="$swtype:$wbegin-" + fi + local nnest=- + ((nest[3]>=0)) && nnest="'${nest[7]}':$((index-nest[3]))-" + local nchild=- + if ((nest[4]>=0)); then + local tchild=$((index-nest[4])) + nchild='$'$tchild + if ! ((0=0)); then + local tprev=$((index-nest[5])) + nprev='$'$tprev + if ! ((0=0)); then + ble/syntax/print-status/ctx#get-text "${stat[2]}"; local stat_wtype=$ret + stat_word="$stat_wtype:$((index-stat[1]))-" + fi + local stat_inest=- + if ((stat[3]>=0)); then + local inest=$((index-stat[3])) + stat_inest="@$inest" + if ((inest<0)) || [[ ! ${_ble_syntax_nest[inest]} ]]; then + stat_inest=$sgr_error$stat_inest$_ble_term_sgr0 + fi + fi + local stat_child=- + if ((stat[4]>=0)); then + local tchild=$((index-stat[4])) + stat_child='$'$tchild + if ! ((0=0)); then + local tprev=$((index-stat[5])) + stat_prev='$'$tprev + if ! ((0ilook&&(ilook=i+$1))) +} +function ble/syntax/parse/tree-append { + [[ $debug_p1 ]] && ble/util/assert '((i-1>=debug_p1))' "Wrong call of tree-append: Condition violation (p1=$debug_p1 i=$i iN=$iN)." + local type=$1 + local beg=$2 end=$i + local len=$((end-beg)) + ((len==0)) && return 0 + local tchild=$3 tprev=$4 + local ochild=-1 oprev=-1 + ((tchild>=0&&(ochild=i-tchild))) + ((tprev>=0&&(oprev=i-tprev))) + [[ $type =~ ^[0-9]+$ ]] && ble/syntax/parse/touch-updated-word "$i" + _ble_syntax_tree[i-1]="$type $len $ochild $oprev - ${_ble_syntax_tree[i-1]}" +} +function ble/syntax/parse/word-push { + wtype=$1 wbegin=$2 tprev=$tchild tchild=-1 +} +function ble/syntax/parse/word-pop { + ble/syntax/parse/tree-append "$wtype" "$wbegin" "$tchild" "$tprev" + ((wbegin=-1,wtype=-1,tchild=i)) + ble/syntax/parse/nest-reset-tprev +} +function ble/syntax/parse/word-cancel { + local -a word + ble/string#split-words word "${_ble_syntax_tree[i-1]}" + local wlen=${word[1]} tplen=${word[3]} + local wbegin=$((i-wlen)) + tchild=$((tplen<0?tplen:i-tplen)) + ble/array#fill-range _ble_syntax_tree "$wbegin" "$i" '' +} +function ble/syntax/parse/nest-push { + local wlen=$((wbegin<0?wbegin:i-wbegin)) + local nlen=$((inest<0?inest:i-inest)) + local tclen=$((tchild<0?tchild:i-tchild)) + local tplen=$((tprev<0?tprev:i-tprev)) + _ble_syntax_nest[i]="$ctx $wlen $wtype $nlen $tclen $tplen ${nparam:-none} ${2:-none}" + ((ctx=$1,inest=i,wbegin=-1,wtype=-1,tprev=tchild,tchild=-1)) + nparam= +} +function ble/syntax/parse/nest-pop { + ((inest<0)) && return 1 + local -a parentNest + ble/string#split-words parentNest "${_ble_syntax_nest[inest]}" + local ntype=${parentNest[7]} nbeg=$inest + ble/syntax/parse/tree-append "n$ntype" "$nbeg" "$tchild" "$tprev" + local wlen=${parentNest[1]} nlen=${parentNest[3]} tplen=${parentNest[5]} + ((ctx=parentNest[0])) + ((wtype=parentNest[2])) + ((wbegin=wlen<0?wlen:nbeg-wlen, + inest=nlen<0?nlen:nbeg-nlen, + tchild=i, + tprev=tplen<0?tplen:nbeg-tplen)) + nparam=${parentNest[6]} + [[ $nparam == none ]] && nparam= +} +function ble/syntax/parse/nest-type { + local _var=ntype + [[ $1 == -v ]] && _var=$2 + if ((inest<0)); then + builtin eval "$_var=" + return 1 + else + builtin eval "$_var=\"\${_ble_syntax_nest[inest]##* }\"" + fi +} +function ble/syntax/parse/nest-ctx { + nctx= + ((inest>=0)) || return 1 + nctx=${_ble_syntax_nest[inest]%% *} +} +function ble/syntax/parse/nest-reset-tprev { + if ((inest<0)); then + tprev=-1 + else + local -a nest + ble/string#split-words nest "${_ble_syntax_nest[inest]}" + local tclen=${nest[4]} + ((tprev=tclen<0?tclen:inest-tclen)) + fi +} +function ble/syntax/parse/nest-equals { + local parent_inest=$1 + while :; do + ((parent_inest0))" "invalid word position $1" + ble/syntax/wrange#update _ble_syntax_word_ "$1" +} +_ble_ctx_UNSPECIFIED=0 +_ble_ctx_ARGX=3 +_ble_ctx_ARGX0=18 +_ble_ctx_ARGI=4 +_ble_ctx_ARGQ=61 +_ble_ctx_CMDX=1 +_ble_ctx_CMDX1=17 +_ble_ctx_CMDXT=49 +_ble_ctx_CMDXC=26 +_ble_ctx_CMDXE=43 +_ble_ctx_CMDXD0=38 +_ble_ctx_CMDXD=68 +_ble_ctx_CMDXV=13 +_ble_ctx_CMDI=2 +_ble_ctx_VRHS=11 +_ble_ctx_QUOT=5 +_ble_ctx_EXPR=8 +_ble_attr_ERR=6 +_ble_attr_VAR=7 +_ble_attr_QDEL=9 +_ble_attr_QESC=81 +_ble_attr_DEF=10 +_ble_attr_DEL=12 +_ble_attr_HISTX=21 +_ble_attr_FUNCDEF=22 +_ble_ctx_PARAM=14 +_ble_ctx_PWORD=15 +_ble_ctx_PWORDE=73 +_ble_ctx_PWORDR=72 +_ble_ctx_RDRF=19 +_ble_ctx_RDRD=20 +_ble_ctx_RDRD2=80 +_ble_ctx_RDRS=27 +_ble_ctx_VALX=23 +_ble_ctx_VALI=24 +_ble_ctx_VALR=65 +_ble_ctx_VALQ=66 +_ble_attr_COMMENT=25 +_ble_ctx_ARGVX=28 +_ble_ctx_ARGVI=29 +_ble_ctx_ARGVR=62 +_ble_ctx_CONDX=32 +_ble_ctx_CONDI=33 +_ble_ctx_CONDQ=67 +_ble_ctx_CASE=34 +_ble_ctx_CPATX=76 +_ble_ctx_CPATI=77 +_ble_ctx_CPATQ=79 +_ble_ctx_CPATX0=78 +_ble_ctx_PATN=30 +_ble_attr_GLOB=31 +_ble_ctx_BRAX=54 +_ble_attr_BRACE=55 +_ble_ctx_BRACE1=56 +_ble_ctx_BRACE2=57 +_ble_attr_TILDE=60 +_ble_ctx_FARGX1=16 +_ble_ctx_FARGI1=35 +_ble_ctx_FARGX2=36 +_ble_ctx_FARGI2=37 +_ble_ctx_FARGX3=58 +_ble_ctx_FARGI3=59 +_ble_ctx_FARGQ3=63 +_ble_ctx_SARGX1=48 +_ble_ctx_CARGX1=39 +_ble_ctx_CARGI1=40 +_ble_ctx_CARGQ1=64 +_ble_ctx_CARGX2=41 +_ble_ctx_CARGI2=42 +_ble_ctx_TARGX1=50 +_ble_ctx_TARGI1=51 +_ble_ctx_TARGX2=52 +_ble_ctx_TARGI2=53 +_ble_ctx_RDRH=44 +_ble_ctx_RDRI=45 +_ble_ctx_HERE0=46 +_ble_ctx_HERE1=47 +_ble_ctx_ARGEX=69 +_ble_ctx_ARGEI=70 +_ble_ctx_ARGER=71 +_ble_ctx_COARGX=74 +_ble_ctx_COARGI=75 +_ble_attr_CMD_BOLD=101 +_ble_attr_CMD_BUILTIN=102 +_ble_attr_CMD_ALIAS=103 +_ble_attr_CMD_FUNCTION=104 +_ble_attr_CMD_FILE=105 +_ble_attr_KEYWORD=106 +_ble_attr_KEYWORD_BEGIN=118 +_ble_attr_KEYWORD_END=119 +_ble_attr_KEYWORD_MID=120 +_ble_attr_CMD_JOBS=107 +_ble_attr_CMD_DIR=112 +_ble_attr_FILE_DIR=108 +_ble_attr_FILE_STICKY=124 +_ble_attr_FILE_LINK=109 +_ble_attr_FILE_ORPHAN=121 +_ble_attr_FILE_FILE=111 +_ble_attr_FILE_SETUID=122 +_ble_attr_FILE_SETGID=123 +_ble_attr_FILE_EXEC=110 +_ble_attr_FILE_FIFO=114 +_ble_attr_FILE_CHR=115 +_ble_attr_FILE_BLK=116 +_ble_attr_FILE_SOCK=117 +_ble_attr_FILE_WARN=113 +_ble_attr_FILE_URL=125 +_ble_attr_VAR_UNSET=126 +_ble_attr_VAR_EMPTY=127 +_ble_attr_VAR_NUMBER=128 +_ble_attr_VAR_EXPR=129 +_ble_attr_VAR_ARRAY=130 +_ble_attr_VAR_HASH=132 +_ble_attr_VAR_READONLY=131 +_ble_attr_VAR_TRANSFORM=133 +_ble_attr_VAR_EXPORT=134 +_ble_syntax_bash_ctx_names=( + [0]=_ble_ctx_UNSPECIFIED + [3]=_ble_ctx_ARGX + [18]=_ble_ctx_ARGX0 + [4]=_ble_ctx_ARGI + [61]=_ble_ctx_ARGQ + [1]=_ble_ctx_CMDX + [17]=_ble_ctx_CMDX1 + [49]=_ble_ctx_CMDXT + [26]=_ble_ctx_CMDXC + [43]=_ble_ctx_CMDXE + [38]=_ble_ctx_CMDXD0 + [68]=_ble_ctx_CMDXD + [13]=_ble_ctx_CMDXV + [2]=_ble_ctx_CMDI + [11]=_ble_ctx_VRHS + [5]=_ble_ctx_QUOT + [8]=_ble_ctx_EXPR + [6]=_ble_attr_ERR + [7]=_ble_attr_VAR + [9]=_ble_attr_QDEL + [81]=_ble_attr_QESC + [10]=_ble_attr_DEF + [12]=_ble_attr_DEL + [21]=_ble_attr_HISTX + [22]=_ble_attr_FUNCDEF + [14]=_ble_ctx_PARAM + [15]=_ble_ctx_PWORD + [73]=_ble_ctx_PWORDE + [72]=_ble_ctx_PWORDR + [19]=_ble_ctx_RDRF + [20]=_ble_ctx_RDRD + [80]=_ble_ctx_RDRD2 + [27]=_ble_ctx_RDRS + [23]=_ble_ctx_VALX + [24]=_ble_ctx_VALI + [65]=_ble_ctx_VALR + [66]=_ble_ctx_VALQ + [25]=_ble_attr_COMMENT + [28]=_ble_ctx_ARGVX + [29]=_ble_ctx_ARGVI + [62]=_ble_ctx_ARGVR + [32]=_ble_ctx_CONDX + [33]=_ble_ctx_CONDI + [67]=_ble_ctx_CONDQ + [34]=_ble_ctx_CASE + [76]=_ble_ctx_CPATX + [77]=_ble_ctx_CPATI + [79]=_ble_ctx_CPATQ + [78]=_ble_ctx_CPATX0 + [30]=_ble_ctx_PATN + [31]=_ble_attr_GLOB + [54]=_ble_ctx_BRAX + [55]=_ble_attr_BRACE + [56]=_ble_ctx_BRACE1 + [57]=_ble_ctx_BRACE2 + [60]=_ble_attr_TILDE + [16]=_ble_ctx_FARGX1 + [35]=_ble_ctx_FARGI1 + [36]=_ble_ctx_FARGX2 + [37]=_ble_ctx_FARGI2 + [58]=_ble_ctx_FARGX3 + [59]=_ble_ctx_FARGI3 + [63]=_ble_ctx_FARGQ3 + [48]=_ble_ctx_SARGX1 + [39]=_ble_ctx_CARGX1 + [40]=_ble_ctx_CARGI1 + [64]=_ble_ctx_CARGQ1 + [41]=_ble_ctx_CARGX2 + [42]=_ble_ctx_CARGI2 + [50]=_ble_ctx_TARGX1 + [51]=_ble_ctx_TARGI1 + [52]=_ble_ctx_TARGX2 + [53]=_ble_ctx_TARGI2 + [44]=_ble_ctx_RDRH + [45]=_ble_ctx_RDRI + [46]=_ble_ctx_HERE0 + [47]=_ble_ctx_HERE1 + [69]=_ble_ctx_ARGEX + [70]=_ble_ctx_ARGEI + [71]=_ble_ctx_ARGER + [74]=_ble_ctx_COARGX + [75]=_ble_ctx_COARGI + [101]=_ble_attr_CMD_BOLD + [102]=_ble_attr_CMD_BUILTIN + [103]=_ble_attr_CMD_ALIAS + [104]=_ble_attr_CMD_FUNCTION + [105]=_ble_attr_CMD_FILE + [106]=_ble_attr_KEYWORD + [118]=_ble_attr_KEYWORD_BEGIN + [119]=_ble_attr_KEYWORD_END + [120]=_ble_attr_KEYWORD_MID + [107]=_ble_attr_CMD_JOBS + [112]=_ble_attr_CMD_DIR + [108]=_ble_attr_FILE_DIR + [124]=_ble_attr_FILE_STICKY + [109]=_ble_attr_FILE_LINK + [121]=_ble_attr_FILE_ORPHAN + [111]=_ble_attr_FILE_FILE + [122]=_ble_attr_FILE_SETUID + [123]=_ble_attr_FILE_SETGID + [110]=_ble_attr_FILE_EXEC + [114]=_ble_attr_FILE_FIFO + [115]=_ble_attr_FILE_CHR + [116]=_ble_attr_FILE_BLK + [117]=_ble_attr_FILE_SOCK + [113]=_ble_attr_FILE_WARN + [125]=_ble_attr_FILE_URL + [126]=_ble_attr_VAR_UNSET + [127]=_ble_attr_VAR_EMPTY + [128]=_ble_attr_VAR_NUMBER + [129]=_ble_attr_VAR_EXPR + [130]=_ble_attr_VAR_ARRAY + [132]=_ble_attr_VAR_HASH + [131]=_ble_attr_VAR_READONLY + [133]=_ble_attr_VAR_TRANSFORM + [134]=_ble_attr_VAR_EXPORT +) +function ble/syntax/ctx#get-name { + ret=${_ble_syntax_bash_ctx_names[$1]#_ble_ctx_} +} +_BLE_SYNTAX_FCTX=() +_BLE_SYNTAX_FEND=() +function ble/syntax:text/ctx-unspecified { + ((i+=${#tail})) + return 0 +} +_BLE_SYNTAX_FCTX[_ble_ctx_UNSPECIFIED]=ble/syntax:text/ctx-unspecified +function ble/syntax:text/initialize-ctx { ctx=$_ble_ctx_UNSPECIFIED; } +function ble/syntax:text/initialize-vars { :; } +_ble_syntax_bash_RexSpaces=$'[ \t]+' +_ble_syntax_bash_RexIFSs="[$_ble_term_IFS]+" +_ble_syntax_bash_RexDelimiter="[$_ble_term_IFS;|&<>()]" +_ble_syntax_bash_RexRedirect='((\{[a-zA-Z_][a-zA-Z_0-9]*\}|[0-9]+)?(&?>>?|>[|&]|<[>&]?|<<[-<]?))[ ]*' +_ble_syntax_bash_chars=() +_ble_syntax_bashc_seed= +function ble/syntax:bash/cclass/update/reorder { + builtin eval "local a=\"\${$1}\"" + [[ $a == *']'* ]] && a="]${a//]}" + [[ $a == *'-'* ]] && a="${a//-}-" + builtin eval "$1=\$a" +} +function ble/syntax:bash/cclass/update { + local seed=$_ble_syntax_bash_histc12 + shopt -q extglob && seed=${seed}x + [[ $seed == "$_ble_syntax_bashc_seed" ]] && return 1 + _ble_syntax_bashc_seed=$seed + local key modified= + if [[ $_ble_syntax_bash_histc12 == '!^' ]]; then + for key in "${!_ble_syntax_bash_charsDef[@]}"; do + _ble_syntax_bash_chars[key]=${_ble_syntax_bash_charsDef[key]} + done + _ble_syntax_bashc_simple=$_ble_syntax_bash_chars_simpleDef + else + modified=1 + local histc1=${_ble_syntax_bash_histc12:0:1} + local histc2=${_ble_syntax_bash_histc12:1:1} + for key in "${!_ble_syntax_bash_charsFmt[@]}"; do + local a=${_ble_syntax_bash_charsFmt[key]} + a=${a//@h/"$histc1"} + a=${a//@q/"$histc2"} + _ble_syntax_bash_chars[key]=$a + done + local a=$_ble_syntax_bash_chars_simpleFmt + a=${a//@h/"$histc1"} + a=${a//@q/"$histc2"} + _ble_syntax_bashc_simple=$a + fi + if [[ $seed == *x ]]; then + local extglob='@+!' # *? は既に登録されている筈 + _ble_syntax_bash_chars[_ble_ctx_ARGI]=${_ble_syntax_bash_chars[_ble_ctx_ARGI]}$extglob + _ble_syntax_bash_chars[_ble_ctx_PATN]=${_ble_syntax_bash_chars[_ble_ctx_PATN]}$extglob + _ble_syntax_bash_chars[_ble_ctx_PWORD]=${_ble_syntax_bash_chars[_ble_ctx_PWORD]}$extglob + _ble_syntax_bash_chars[_ble_ctx_PWORDE]=${_ble_syntax_bash_chars[_ble_ctx_PWORDE]}$extglob + _ble_syntax_bash_chars[_ble_ctx_PWORDR]=${_ble_syntax_bash_chars[_ble_ctx_PWORDR]}$extglob + fi + if [[ $modified ]]; then + for key in "${!_ble_syntax_bash_chars[@]}"; do + ble/syntax:bash/cclass/update/reorder _ble_syntax_bash_chars[key] + done + ble/syntax:bash/cclass/update/reorder _ble_syntax_bashc_simple + fi + return 0 +} +_ble_syntax_bash_charsDef=() +_ble_syntax_bash_charsFmt=() +_ble_syntax_bash_chars_simpleDef= +_ble_syntax_bash_chars_simpleFmt= +function ble/syntax:bash/cclass/initialize { + local delimiters="$_ble_term_IFS;|&()<>" + local expansions="\$\"\`\\'" + local glob='[*?' + local tilde='~:' + _ble_syntax_bash_charsDef[_ble_ctx_ARGI]="$delimiters$expansions$glob{$tilde^!" + _ble_syntax_bash_charsDef[_ble_ctx_PATN]="$expansions$glob(|)<>{!" # <> はプロセス置換のため。 + _ble_syntax_bash_charsDef[_ble_ctx_QUOT]="\$\"\`\\!" # 文字列 "~" で特別な意味を持つのは $ ` \ " のみ。+履歴展開の ! も。 + _ble_syntax_bash_charsDef[_ble_ctx_EXPR]="][}()$expansions!" # ()[] は入れ子を数える為。} は ${var:ofs:len} の為。 + _ble_syntax_bash_charsDef[_ble_ctx_PWORD]="}$expansions$glob!" # パラメータ展開 ${~} + _ble_syntax_bash_charsDef[_ble_ctx_PWORDE]="}$expansions$glob!" # パラメータ展開 ${~} エラー + _ble_syntax_bash_charsDef[_ble_ctx_PWORDR]="}/$expansions$glob!" # パラメータ展開 ${~} 置換前 + _ble_syntax_bash_charsDef[_ble_ctx_RDRH]="$delimiters$expansions" + _ble_syntax_bash_charsFmt[_ble_ctx_ARGI]="$delimiters$expansions$glob{$tilde@q@h" + _ble_syntax_bash_charsFmt[_ble_ctx_PATN]="$expansions$glob(|)<>{@h" + _ble_syntax_bash_charsFmt[_ble_ctx_QUOT]="\$\"\`\\@h" + _ble_syntax_bash_charsFmt[_ble_ctx_EXPR]="][}()$expansions@h" + _ble_syntax_bash_charsFmt[_ble_ctx_PWORD]="}$expansions$glob@h" + _ble_syntax_bash_charsFmt[_ble_ctx_PWORDE]="}$expansions$glob@h" + _ble_syntax_bash_charsFmt[_ble_ctx_PWORDR]="}/$expansions$glob@h" + _ble_syntax_bash_charsFmt[_ble_ctx_RDRH]=${_ble_syntax_bash_charsDef[_ble_ctx_RDRH]} + _ble_syntax_bash_chars_simpleDef="$delimiters$expansions^!" + _ble_syntax_bash_chars_simpleFmt="$delimiters$expansions@q@h" + _ble_syntax_bash_histc12='!^' + ble/syntax:bash/cclass/update +} +ble/syntax:bash/cclass/initialize +_ble_syntax_bash_simple_rex_letter= +_ble_syntax_bash_simple_rex_param= +_ble_syntax_bash_simple_rex_bquot= +_ble_syntax_bash_simple_rex_squot= +_ble_syntax_bash_simple_rex_dquot= +_ble_syntax_bash_simple_rex_literal= +_ble_syntax_bash_simple_rex_element= +_ble_syntax_bash_simple_rex_word= +_ble_syntax_bash_simple_rex_open_word= +_ble_syntax_bash_simple_rex_open_dquot= +_ble_syntax_bash_simple_rex_open_squot= +_ble_syntax_bash_simple_rex_incomplete_word1= +_ble_syntax_bash_simple_rex_incomplete_word2= +_ble_syntax_bash_simple_rex_noglob_word1= +_ble_syntax_bash_simple_rex_noglob_word2= +function ble/syntax:bash/simple-word/update { + local q="'" + local letter='\[[!^]|[^'${_ble_syntax_bashc_simple}']' + local param1='\$([-*@#?$!0_]|[1-9][0-9]*|[a-zA-Z_][a-zA-Z_0-9]*)' + local param2='\$\{(#?[-*@#?$!0]|[#!]?([1-9][0-9]*|[a-zA-Z_][a-zA-Z_0-9]*))\}' # ${!!} ${!$} はエラーになる。履歴展開の所為? + local param=$param1'|'$param2 + local bquot='\\.' + local squot=$q'[^'$q']*'$q'|\$'$q'([^'$q'\]|\\.)*'$q + local dquot='\$?"([^'${_ble_syntax_bash_chars[_ble_ctx_QUOT]}']|\\.|'$param')*"' + _ble_syntax_bash_simple_rex_letter=$letter # 0 groups + _ble_syntax_bash_simple_rex_param=$param # 3 groups + _ble_syntax_bash_simple_rex_bquot=$bquot # 0 groups + _ble_syntax_bash_simple_rex_squot=$squot # 1 groups + _ble_syntax_bash_simple_rex_dquot=$dquot # 4 groups + _ble_syntax_bash_simple_rex_literal='^('$letter')+$' + _ble_syntax_bash_simple_rex_element='('$bquot'|'$squot'|'$dquot'|'$param'|'$letter')' + _ble_syntax_bash_simple_rex_word='^'$_ble_syntax_bash_simple_rex_element'+$' + local open_squot=$q'[^'$q']*|\$'$q'([^'$q'\]|\\.)*' + local open_dquot='\$?"([^'${_ble_syntax_bash_chars[_ble_ctx_QUOT]}']|\\.|'$param')*' + _ble_syntax_bash_simple_rex_open_word='^('$_ble_syntax_bash_simple_rex_element'*)(\\|'$open_squot'|'$open_dquot')$' + _ble_syntax_bash_simple_rex_open_squot=$open_squot + _ble_syntax_bash_simple_rex_open_dquot=$open_dquot + local letter1='\[[!^]|[^{'${_ble_syntax_bashc_simple}']' + local letter2='\[[!^]|[^'${_ble_syntax_bashc_simple}']' + _ble_syntax_bash_simple_rex_incomplete_word1='^('$bquot'|'$squot'|'$dquot'|'$param'|'$letter1')+' + _ble_syntax_bash_simple_rex_incomplete_word2='^(('$bquot'|'$squot'|'$dquot'|'$param'|'$letter2')*)(\\|'$open_squot'|'$open_dquot')?$' + local noglob_letter='[^[?*'${_ble_syntax_bashc_simple}']' + _ble_syntax_bash_simple_rex_noglob_word1='^('$bquot'|'$squot'|'$dquot'|'$noglob_letter')+$' + _ble_syntax_bash_simple_rex_noglob_word2='^('$bquot'|'$squot'|'$dquot'|'$param'|'$noglob_letter')+$' +} +ble/syntax:bash/simple-word/update +function ble/syntax:bash/simple-word/is-literal { + [[ $1 =~ $_ble_syntax_bash_simple_rex_literal ]] +} +function ble/syntax:bash/simple-word/is-simple { + [[ $1 =~ $_ble_syntax_bash_simple_rex_word ]] +} +function ble/syntax:bash/simple-word/is-simple-or-open-simple { + [[ $1 =~ $_ble_syntax_bash_simple_rex_word || $1 =~ $_ble_syntax_bash_simple_rex_open_word ]] +} +function ble/syntax:bash/simple-word/is-never-word { + ble/syntax:bash/simple-word/is-simple-or-open-simple && return 1 + local rex=${_ble_syntax_bash_simple_rex_word%'$'}'[ |&;<>()]|^[ |&;<>()]' + [[ $1 =~ $rex ]] +} +function ble/syntax:bash/simple-word/is-simple-noglob { + [[ $1 =~ $_ble_syntax_bash_simple_rex_noglob_word1 ]] && return 0 + if [[ $1 =~ $_ble_syntax_bash_simple_rex_noglob_word2 ]]; then + builtin eval -- "local expanded=$1" 2>/dev/null + local rex='[*?]|\[.+\]|[*?@+!]\(.*\)' + [[ $expanded =~ $rex ]] || return 0 + fi + return 1 +} +function ble/syntax:bash/simple-word/evaluate-last-brace-expansion { + local value=$1 + local bquot=$_ble_syntax_bash_simple_rex_bquot + local squot=$_ble_syntax_bash_simple_rex_squot + local dquot=$_ble_syntax_bash_simple_rex_dquot + local param=$_ble_syntax_bash_simple_rex_param + local letter='\[[!^]|[^{,}'${_ble_syntax_bashc_simple}']' + local symbol='[{,}]' + local rex_range_expansion='^(([-+]?[0-9]+)\.\.\.[-+]?[0-9]+|([a-zA-Z])\.\.[a-zA-Z])(\.\.[-+]?[0-9]+)?$' + local rex0='^('$bquot'|'$squot'|'$dquot'|'$param'|'$letter')+' + local stack; stack=() + local out= comma= index=0 iopen=0 no_brace_length=0 + while [[ $value ]]; do + if [[ $value =~ $rex0 ]]; then + local len=${#BASH_REMATCH} + ((index+=len,no_brace_length+=len)) + out=$out${value::len} + value=${value:len} + elif [[ $value == '{'* ]]; then + ((iopen=++index,no_brace_length=0)) + value=${value:1} + ble/array#push stack "$comma:$out" + out= comma= + elif ((${#stack[@]})) && [[ $value == '}'* ]]; then + ((++index)) + value=${value:1} + ble/array#pop stack + local out0=${ret#*:} comma0=${ret%%:*} + if [[ $comma ]]; then + ((iopen=index,no_brace_length=0)) + out=$out0$out + comma=$comma0 + elif [[ $out =~ $rex_range_expansion ]]; then + ((iopen=index,no_brace_length=0)) + out=$out0${2#+}$3 + comma=$comma0 + else + ((++no_brace_length)) + ble/array#push stack "$comma0:$out0" # cancel pop + out=$out'}' + fi + elif ((${#stack[@]})) && [[ $value == ','* ]]; then + ((iopen=++index,no_brace_length=0)) + value=${value:1} + out= comma=1 + else + ((++index,++no_brace_length)) + out=$out${value::1} + value=${value:1} + fi + done + while ((${#stack[@]})); do + ble/array#pop stack + local out0=${ret#*:} comma0=${ret%%:*} + out=$out0$out + done + ret=$out simple_ibrace=$iopen:$((${#out}-no_brace_length)) +} +function ble/syntax:bash/simple-word/reconstruct-incomplete-word { + local word=$1 + ret= simple_flags= simple_ibrace=0:0 + [[ $word ]] || return 0 + if [[ $word =~ $_ble_syntax_bash_simple_rex_incomplete_word1 ]]; then + ret=${word::${#BASH_REMATCH}} + word=${word:${#BASH_REMATCH}} + [[ $word ]] || return 0 + fi + if [[ $word =~ $_ble_syntax_bash_simple_rex_incomplete_word2 ]]; then + local out=$ret + local m_brace=${BASH_REMATCH[1]} + local m_quote=${word:${#m_brace}} + if [[ $m_brace ]]; then + ble/syntax:bash/simple-word/evaluate-last-brace-expansion "$m_brace" + simple_ibrace=$((${#out}+${simple_ibrace%:*})):$((${#out}+${simple_ibrace#*:})) + out=$out$ret + fi + if [[ $m_quote ]]; then + case $m_quote in + ('$"'*) out=$out$m_quote\" simple_flags=I ;; + ('"'*) out=$out$m_quote\" simple_flags=D ;; + ("$'"*) out=$out$m_quote\' simple_flags=E ;; + ("'"*) out=$out$m_quote\' simple_flags=S ;; + ('\') simple_flags=B ;; + (*) return 1 ;; + esac + fi + ret=$out + return 0 + fi + return 1 +} +function ble/syntax:bash/simple-word/extract-parameter-names { + ret=() + local letter=$_ble_syntax_bash_simple_rex_letter + local bquot=$_ble_syntax_bash_simple_rex_bquot + local squot=$_ble_syntax_bash_simple_rex_squot + local dquot=$_ble_syntax_bash_simple_rex_dquot + local param=$_ble_syntax_bash_simple_rex_param + local value=$1 + local rex0='^('$letter'|'$bquot'|'$squot')+' + local rex1='^('$dquot')' + local rex2='^('$param')' + while [[ $value ]]; do + [[ $value =~ $rex0 ]] && value=${value:${#BASH_REMATCH}} + if [[ $value =~ $rex1 ]]; then + value=${value:${#BASH_REMATCH}} + ble/syntax:bash/simple-word/extract-parameter-names/.process-dquot "$BASH_REMATCH" + fi + [[ $value =~ $rex2 ]] || break + value=${value:${#BASH_REMATCH}} + local var=${BASH_REMATCH[2]}${BASH_REMATCH[3]} + [[ $var == [_a-zA-Z]* ]] && ble/array#push ret "$var" + done +} +function ble/syntax:bash/simple-word/extract-parameter-names/.process-dquot { + local value=$1 + if [[ $value == '$"'*'"' ]]; then + value=${value:2:${#value}-3} + elif [[ $value == '"'*'"' ]]; then + value=${value:1:${#value}-2} + else + return 0 + fi + local rex0='^([^'${_ble_syntax_bash_chars[_ble_ctx_QUOT]}']|\\.)+' + local rex2='^('$param')' + while [[ $value ]]; do + [[ $value =~ $rex0 ]] && value=${value:${#BASH_REMATCH}} + [[ $value =~ $rex2 ]] || break + value=${value:${#BASH_REMATCH}} + local var=${BASH_REMATCH[2]}${BASH_REMATCH[3]} + [[ $var == [_a-zA-Z]* ]] && ble/array#push ret "$var" + done +} +function ble/syntax:bash/simple-word/eval/.set-result { __ble_ret=("$@"); } +function ble/syntax:bash/simple-word/eval/.print-result { + if (($#>=1000)) && [[ $OSTYPE != cygwin ]]; then + if ((_ble_bash>=50200)); then + printf '%s\0' "$@" >| "$__ble_simple_word_tmpfile" + ble/util/print 'ble/util/readarray -d "" __ble_ret < "$__ble_simple_word_tmpfile"' + return 0 + elif ((_ble_bash>=40000)); then + ret=("$@") + ble/util/writearray --nlfix ret >| "$__ble_simple_word_tmpfile" + ble/util/print 'ble/util/readarray --nlfix __ble_ret < "$__ble_simple_word_tmpfile"' + return 0 + fi + fi + local ret; ble/string#quote-words "$@" + ble/util/print "__ble_ret=($ret)" +} +function ble/syntax:bash/simple-word/eval/.impl { + local __ble_word=$1 __ble_opts=$2 __ble_flags= + local -a ret=() + ble/syntax:bash/simple-word/extract-parameter-names "$__ble_word" + if ((${#ret[@]})); then + local __ble_defs + ble/util/assign __ble_defs 'ble/util/print-global-definitions --hidden-only "${ret[@]}"' + builtin eval -- "$__ble_defs" &>/dev/null # 読み取り専用の変数のこともある + fi + if [[ $- != *f* ]] && ! ble/syntax:bash/simple-word/is-simple-noglob "$1"; then + if [[ :$__ble_opts: == *:noglob:* ]]; then + set -f + __ble_flags=f + elif ble/util/is-cygwin-slow-glob "$1"; then # Note: #D1168 + if shopt -q failglob &>/dev/null; then + __ble_ret=() + return 1 + elif shopt -q nullglob &>/dev/null; then + __ble_ret=() + return 0 + else + set -f + __ble_flags=f + fi + elif [[ :$__ble_opts: == *:stopcheck:* ]]; then + ble/decode/has-input && return 148 + if ((_ble_bash>=40000)); then + __ble_flags=s + elif shopt -q globstar &>/dev/null; then + if builtin eval "[[ $__ble_word == *'**'* ]]"; then + [[ :$__ble_opts: == *:timeout=*:* ]] && return 142 + return 148 + fi + fi + fi + fi + __ble_ret=() + if [[ $__ble_flags == *s* ]]; then + local __ble_sync_command="ble/syntax:bash/simple-word/eval/.print-result $__ble_word" + local __ble_sync_opts=progressive-weight + local __ble_sync_weight=$bleopt_syntax_eval_polling_interval + local __ble_sync_timeout=$_ble_syntax_bash_simple_eval_timeout + if [[ $_ble_syntax_bash_simple_eval_timeout_carry ]]; then + __ble_sync_timeout=0 + elif local __ble_rex=':timeout=([^:]*):'; [[ :$__ble_opts: =~ $__ble_rex ]]; then + __ble_sync_timeout=${BASH_REMATCH[1]} + fi + [[ $__ble_sync_timeout ]] && + __ble_sync_opts=$__ble_sync_opts:timeout=$((__ble_sync_timeout)) + local _ble_local_tmpfile; ble/util/assign/.mktmp + local __ble_simple_word_tmpfile=$_ble_local_tmpfile + local __ble_script + ble/util/assign __ble_script 'ble/util/conditional-sync "$__ble_sync_command" "" "$__ble_sync_weight" "$__ble_sync_opts"' &>/dev/null; local ext=$? + builtin eval -- "$__ble_script" + ble/util/assign/.rmtmp + else + builtin eval "ble/syntax:bash/simple-word/eval/.set-result $__ble_word" &>/dev/null; local ext=$? + builtin eval : # Note: bash 3.1/3.2 eval バグ対策 (#D1132) + fi + [[ $__ble_flags == *f* ]] && set +f + return "$ext" +} +_ble_syntax_bash_simple_eval_hash= +function ble/syntax:bash/simple-word/eval/.cache-clear { + ble/gdict#clear _ble_syntax_bash_simple_eval + ble/gdict#clear _ble_syntax_bash_simple_eval_full +} +function ble/syntax:bash/simple-word/eval/.cache-update { + local hash=$-:$BASHOPTS:$_ble_edit_lineno:$_ble_textarea_version:$PWD + if [[ $hash != "$_ble_syntax_bash_simple_eval_hash" ]]; then + _ble_syntax_bash_simple_eval_hash=$hash + ble/syntax:bash/simple-word/eval/.cache-clear + fi +} +function ble/syntax:bash/simple-word/eval/.cache-save { + ((ext==148||ext==142)) && return 0 + local ret; ble/string#quote-words "$3" + ble/gdict#set _ble_syntax_bash_simple_eval "$1" "ext=$2 count=$(($#-2)) ret=$ret" + local ret; ble/string#quote-words "${@:3}" + ble/gdict#set _ble_syntax_bash_simple_eval_full "$1" "ext=$2 count=$(($#-2)) ret=($ret)" +} +function ble/syntax:bash/simple-word/eval/.cache-load { + ext= ret= + if [[ :$2: == *:single:* ]]; then + ble/gdict#get _ble_syntax_bash_simple_eval "$1" || return 1 + else + ble/gdict#get _ble_syntax_bash_simple_eval_full "$1" || return 1 + fi + builtin eval -- "$ret" + return 0 +} +_ble_syntax_bash_simple_eval_timeout= +_ble_syntax_bash_simple_eval_timeout_carry= +function ble/syntax:bash/simple-word/eval { + [[ :$2: != *:count:* ]] && local count + if [[ :$2: == *:cached:* && :$2: != *:noglob:* ]]; then + ble/syntax:bash/simple-word/eval/.cache-update + local ext; ble/syntax:bash/simple-word/eval/.cache-load "$1" "$2" && return "$ext" + fi + local __ble_ret + ble/syntax:bash/simple-word/eval/.impl "$1" "$2"; local ext=$? + ret=("${__ble_ret[@]}") + count=${#ret[@]} + if [[ :$2: == *:cached:* && :$2: != *:noglob:* ]]; then + ble/syntax:bash/simple-word/eval/.cache-save "$1" "$ext" "${ret[@]}" + fi + if ((ext==142)); then + [[ :$2: == *:timeout-carry:* ]] && + _ble_syntax_bash_simple_eval_timeout_carry=1 + if [[ :$2: == *:retry-noglob-on-timeout:* ]]; then + ble/syntax:bash/simple-word/eval "$1" "$2:noglob" + return "$?" + fi + fi + return "$ext" +} +function ble/syntax:bash/simple-word/.get-rex_element { + local sep=$1 + local param=$_ble_syntax_bash_simple_rex_param + local bquot=$_ble_syntax_bash_simple_rex_bquot + local squot=$_ble_syntax_bash_simple_rex_squot + local dquot=$_ble_syntax_bash_simple_rex_dquot + local letter1='\[[!^]|[^'$sep$_ble_syntax_bashc_simple']' + rex_element='('$bquot'|'$squot'|'$dquot'|'$param'|'$letter1')+' +} +function ble/syntax:bash/simple-word/evaluate-path-spec { + local word=$1 sep=${2:-'/:='} opts=$3 + ret=() spec=() path=() + [[ $word ]] || return 0 + local eval_opts=$opts notilde= + [[ :$opts: == *:notilde:* ]] && notilde=\'\' # チルダ展開の抑制 + local rex_element; ble/syntax:bash/simple-word/.get-rex_element "$sep" + local rex='^['$sep']?'$rex_element'|^['$sep']' + [[ :$opts: == *:after-sep:* ]] && + local rex='^'$rex_element'['$sep']?|^['$sep']' + local tail=$word s= p= ext=0 + while [[ $tail =~ $rex ]]; do + local rematch=$BASH_REMATCH + s=$s$rematch + ble/syntax:bash/simple-word/eval "$notilde$s" "$eval_opts"; ext=$? + ((ext==148||ext==142)) && return "$ext" + p=$ret + tail=${tail:${#rematch}} + ble/array#push spec "$s" + ble/array#push path "$p" + done + [[ $tail ]] && return 1 + ((ext)) && return "$ext" + return 0 +} +function ble/syntax:bash/simple-word/detect-separated-path { + local word=$1 sep=${2:-':'} opts=$3 + [[ $word ]] || return 1 + local rex_url='^[a-z]+://' + [[ :$opts: == *:url:* && $word =~ $rex_url ]] && return 1 + local eval_opts=$opts notilde= + [[ :$opts: == *:notilde:* ]] && notilde=\'\' # チルダ展開の抑制 + local rex_element + ble/syntax:bash/simple-word/.get-rex_element / + local rex='^'$rex_element'/?|^/' + local tail=$word head= + while [[ $tail =~ $rex ]]; do + local rematch=$BASH_REMATCH + ble/syntax:bash/simple-word/locate-filename/.exists "$notilde$head$rematch"; local ext=$? + ((ext==148)) && return 148 + ((ext==0)) || break + head=$head$rematch + tail=${tail:${#rematch}} + done + ret= + local i + for ((i=0;i<${#sep};i++)); do + local sep1=${sep:i:1} + ble/syntax:bash/simple-word/.get-rex_element "$sep1" + local rex_nocolon='^('$rex_element')?$' + local rex_hascolon='^('$rex_element')?['$sep1']' + [[ $head =~ $rex_nocolon && $tail =~ $rex_hascolon ]] && ret=$ret$sep1 + done + [[ $ret ]] +} +function ble/syntax:bash/simple-word/locate-filename/.exists { + local word=$1 ret + ble/syntax:bash/simple-word/eval "$word" "$eval_opts" || return "$?" + local path=$ret + if [[ ( $OSTYPE == cygwin || $OSTYPE == msys ) && $path == //* ]]; then + [[ $path == // ]] + else + [[ -e $path || -h $path ]] + fi || [[ :$opts: == *:url:* && $path =~ $rex_url ]] +} +function ble/syntax:bash/simple-word/locate-filename { + local word=$1 sep=${2:-':='} opts=$3 + ret=0 + [[ $word ]] || return 0 + local eval_opts=$opts + local rex_element; ble/syntax:bash/simple-word/.get-rex_element "$sep" + local rex='^'$rex_element'['$sep']|^['$sep']' + local rex_url='^[a-z]+://' + local -a seppos=() + local tail=$word p=0 + while [[ $tail =~ $rex ]]; do + ((p+=${#BASH_REMATCH})) + tail=${tail:${#BASH_REMATCH}} + ble/array#push seppos $((p-1)) + done + ble/syntax:bash/simple-word/is-simple "$tail" && + ble/array#push seppos $((p+${#tail})) + local -a out=() + for ((i=0;i<${#seppos[@]};i++)); do + local j0=$i + [[ :$opts: == *:greedy:* ]] && j0=${#seppos[@]}-1 + for ((j=j0;j>=i;j--)); do + local f1=0 f2=${seppos[j]} + ((i)) && ((f1=seppos[i-1]+1)) + if ((j>i)); then + ble/syntax:bash/simple-word/locate-filename/.exists "${word:f1:f2-f1}" "$opts"; local ext=$? + ((ext==148)) && return 148 + if ((ext==0)); then + ble/array#push out "$f1" "$f2" + ((i=j)) + fi + else + if [[ :$opts: != *:exists:* ]] || + { ble/syntax:bash/simple-word/locate-filename/.exists "${word:f1:f2-f1}" "$opts" + local ext=$?; ((ext==148)) && return 148; ((ext==0)); }; then + ble/array#push out "$f1" "$f2" + fi + fi + done + done + ret=("${out[@]}") + return 0 +} +function ble/syntax:bash/simple-word#break-word { + local word=$1 sep=${2:-':='} + if [[ ! $word ]]; then + ret=('') + return 0 + fi + sep=${sep//[\"\'\$\`]} + local rex_element; ble/syntax:bash/simple-word/.get-rex_element "$sep" + local rex='^('$rex_element')?['$sep']+' + local -a out=() + local tail=$word p=0 + while [[ $tail =~ $rex ]]; do + local rematch1=${BASH_REMATCH[1]} + ble/array#push out "$rematch1" + ble/array#push out "${BASH_REMATCH:${#rematch1}}" + tail=${tail:${#BASH_REMATCH}} + done + ble/array#push out "$tail" + ret=("${out[@]}") + return 0 +} +function ble/syntax:bash/initialize-ctx { + ctx=$_ble_ctx_CMDX # _ble_ctx_CMDX が ble/syntax:bash の最初の文脈 +} +function ble/syntax:bash/initialize-vars { + local histc12 + if [[ ${histchars+set} ]]; then + histc12=${histchars::2} + else + histc12='!^' + fi + _ble_syntax_bash_histc12=$histc12 + if ble/syntax:bash/cclass/update; then + ble/syntax:bash/simple-word/update + fi + local histstop=$' \t\n=' + shopt -q extglob && histstop="$histstop(" + _ble_syntax_bash_histstop=$histstop +} +function ble/syntax/highlight/vartype { + if [[ ! $bleopt_highlight_variable ]]; then + ret=$_ble_attr_VAR + return 0 + fi + local name=$1 opts=$2 tail=$3 rex='^-?[0-9]+(#[0-9a-zA-Z@_]*)?$' + local attr; ble/variable#get-attr "$name" + if [[ ${!name+set} || $attr == *[aA]* ]]; then + if [[ ${!name-} && :$opts: == *:expr:* && ! ( ${!name} =~ $rex ) ]]; then + ret=$_ble_attr_VAR_EXPR + elif [[ ${!name+set} && $attr == *x* ]]; then + ret=$_ble_attr_VAR_EXPORT + elif [[ $attr == *a* ]]; then + ret=$_ble_attr_VAR_ARRAY + elif [[ $attr == *A* ]]; then + ret=$_ble_attr_VAR_HASH + elif [[ $attr == *r* ]]; then + ret=$_ble_attr_VAR_READONLY + elif [[ $attr == *i* ]]; then + ret=$_ble_attr_VAR_NUMBER + elif [[ $attr == *[luc]* ]]; then + ret=$_ble_attr_VAR_TRANSFORM + elif [[ ! ${!name} ]]; then + ret=$_ble_attr_VAR_EMPTY + else + ret=$_ble_attr_VAR + fi + else + if [[ :$opts: == *:readvar:* && $_ble_bash_set == *u* ]]; then + if [[ ! $tail ]] || { + local rex='^:?[-+?=]' + [[ $tail == :* ]] && lookahead=2 + ! [[ $tail =~ $rex ]]; } + then + ret=$_ble_attr_ERR + return 0 + fi + fi + ret=$_ble_attr_VAR_UNSET + fi +} +function ble/syntax:bash/check-plain-with-escape { + local rex='^('$1'|\\.)' is_quote=$2 + [[ $tail =~ $rex ]] || return 1 + if [[ $BASH_REMATCH == '\'? && + ( ! $is_quote || $BASH_REMATCH == '\'[$'\\`$\n"'] ) ]]; then + ((_ble_syntax_attr[i]=_ble_attr_QESC)) + else + ((_ble_syntax_attr[i]=ctx)) + fi + ((i+=${#BASH_REMATCH})) + return 0 +} +function ble/syntax:bash/check-dollar { + [[ $tail == '$'* ]] || return 1 + local rex + if [[ $tail == '${'* ]]; then + local rex1='^(\$\{#)([-*@#?$!0]\}?|[1-9][0-9]*\}?|[a-zA-Z_][a-zA-Z_0-9]*[[}]?)' + local rex2='^(\$\{!?)([-*@#?$!0]|[1-9][0-9]*|[a-zA-Z_][a-zA-Z_0-9]*\[?)' + if + [[ $tail =~ $rex1 ]] && { + [[ ${BASH_REMATCH[2]} == *['[}'] || $BASH_REMATCH == "$tail" ]] || + { ble/syntax/parse/set-lookahead $((${#BASH_REMATCH}+1)); false; } } || + [[ $tail =~ $rex2 ]] + then + local rematch1=${BASH_REMATCH[1]} + local rematch2=${BASH_REMATCH[2]} + local varname=${rematch2%['[}']} + local ntype='${' + if ((ctx==_ble_ctx_QUOT)); then + ntype='"${' + elif ((ctx==_ble_ctx_PWORD||ctx==_ble_ctx_PWORDE||ctx==_ble_ctx_PWORDR||ctx==_ble_ctx_EXPR)); then + local ntype2; ble/syntax/parse/nest-type -v ntype2 + [[ $ntype2 == '"${' ]] && ntype='"${' + fi + local ret lookahead= tail2=${tail:${#rematch1}+${#varname}} + ble/syntax/highlight/vartype "$varname" readvar "$tail2"; local attr=$ret + ble/syntax/parse/nest-push "$_ble_ctx_PARAM" "$ntype" + ((_ble_syntax_attr[i]=ctx, + i+=${#rematch1}, + _ble_syntax_attr[i]=attr, + i+=${#varname})) + [[ $lookahead ]] && ble/syntax/parse/set-lookahead "$lookahead" + if rex='^\$\{![a-zA-Z_][a-zA-Z_0-9]*[*@]\}?'; [[ $tail =~ $rex ]]; then + ble/syntax/parse/set-lookahead 2 + if [[ $BASH_REMATCH == *'}' ]]; then + ((i++,ctx=_ble_ctx_PWORDE)) + fi + elif [[ $rematch2 == *'[' ]]; then + ble/syntax/parse/nest-push "$_ble_ctx_EXPR" 'v[' + ((_ble_syntax_attr[i++]=_ble_ctx_EXPR)) + fi + return 0 + else + ((_ble_syntax_attr[i]=_ble_attr_ERR,i+=2)) + return 0 + fi + elif [[ $tail == '$(('* ]]; then + ((_ble_syntax_attr[i]=_ble_ctx_PARAM)) + ble/syntax/parse/nest-push "$_ble_ctx_EXPR" '$((' + ((i+=3)) + return 0 + elif [[ $tail == '$['* ]]; then + ((_ble_syntax_attr[i]=_ble_ctx_PARAM)) + ble/syntax/parse/nest-push "$_ble_ctx_EXPR" '$[' + ((i+=2)) + return 0 + elif [[ $tail == '$('* ]]; then + ((_ble_syntax_attr[i]=_ble_ctx_PARAM)) + ble/syntax/parse/nest-push "$_ble_ctx_CMDX" '$(' + ((i+=2)) + return 0 + elif rex='^\$([-*@#?$!0_]|[1-9]|[a-zA-Z_][a-zA-Z_0-9]*)' && [[ $tail =~ $rex ]]; then + local rematch=$BASH_REMATCH rematch1=${BASH_REMATCH[1]} + local ret; ble/syntax/highlight/vartype "$rematch1" readvar + ((_ble_syntax_attr[i]=_ble_ctx_PARAM, + _ble_syntax_attr[i+1]=ret, + i+=${#rematch})) + return 0 + else + ((_ble_syntax_attr[i++]=ctx)) + return 0 + fi +} +function ble/syntax:bash/check-quotes { + local rex aqdel=$_ble_attr_QDEL aquot=$_ble_ctx_QUOT + if ((ctx==_ble_ctx_EXPR)); then + local ntype + ble/syntax/parse/nest-type + if [[ $ntype == '${' || $ntype == '$[' || $ntype == '$((' || $ntype == 'NQ(' ]]; then + ((aqdel=_ble_attr_ERR,aquot=_ble_ctx_EXPR)) + elif [[ $ntype == '"${' ]] && ! { [[ $tail == '$'[\'\"]* ]] && shopt -q extquote; }; then + ((aqdel=_ble_attr_ERR,aquot=_ble_ctx_EXPR)) + fi + elif ((ctx==_ble_ctx_PWORD||ctx==_ble_ctx_PWORDE||ctx==_ble_ctx_PWORDR)); then + if [[ $tail == '$'[\'\"]* ]] && ! shopt -q extquote; then + local ntype + ble/syntax/parse/nest-type + if [[ $ntype == '"${' ]]; then + ((aqdel=ctx,aquot=ctx)) + fi + fi + fi + if rex='^`([^`\]|\\(.|$))*(`?)|^'\''[^'\'']*('\''?)' && [[ $tail =~ $rex ]]; then + ((_ble_syntax_attr[i]=aqdel, + _ble_syntax_attr[i+1]=aquot, + i+=${#BASH_REMATCH}, + _ble_syntax_attr[i-1]=${#BASH_REMATCH[3]}||${#BASH_REMATCH[4]}?aqdel:_ble_attr_ERR)) + return 0 + fi + if ((ctx!=_ble_ctx_QUOT)); then + if rex='^(\$?")([^'"${_ble_syntax_bash_chars[_ble_ctx_QUOT]}"']*)("?)' && [[ $tail =~ $rex ]]; then + local rematch1=${BASH_REMATCH[1]} # for bash-3.1 ${#arr[n]} bug + if [[ ${BASH_REMATCH[3]} ]]; then + ((_ble_syntax_attr[i]=aqdel, + _ble_syntax_attr[i+${#rematch1}]=aquot, + i+=${#BASH_REMATCH}, + _ble_syntax_attr[i-1]=aqdel)) + else + ble/syntax/parse/nest-push "$_ble_ctx_QUOT" + if (((ctx==_ble_ctx_PWORD||ctx==_ble_ctx_PWORDE||ctx==_ble_ctx_PWORDR)&&aqdel!=_ble_attr_QDEL)); then + ((_ble_syntax_attr[i]=aqdel, + _ble_syntax_attr[i+${#rematch1}-1]=_ble_attr_QDEL, + _ble_syntax_attr[i+${#rematch1}]=_ble_ctx_QUOT, + i+=${#BASH_REMATCH})) + else + ((_ble_syntax_attr[i]=aqdel, + _ble_syntax_attr[i+${#rematch1}]=_ble_ctx_QUOT, + i+=${#BASH_REMATCH})) + fi + fi + return 0 + elif rex='^\$'\''(([^'\''\]|\\(.|$))*)('\''?)' && [[ $tail =~ $rex ]]; then + ((_ble_syntax_attr[i]=aqdel,i+=2)) + local t=${BASH_REMATCH[1]} rematch4=${BASH_REMATCH[4]} + local rex='\\[abefnrtvE"'\''\?]|\\[0-7]{1,3}|\\c.|\\x[0-9a-fA-F]{1,2}' + ((_ble_bash>=40200)) && rex=$rex'|\\u[0-9a-fA-F]{1,4}|\\U[0-9a-fA-F]{1,8}' + local rex='^([^'\''\]*)('$rex'|(\\.))' + while [[ $t =~ $rex ]]; do + local m1=${BASH_REMATCH[1]} m2=${BASH_REMATCH[2]} + [[ $m1 ]] && ((_ble_syntax_attr[i]=aquot,i+=${#m1})) + if [[ ${BASH_REMATCH[3]} ]]; then + ((_ble_syntax_attr[i]=aquot)) + else + ((_ble_syntax_attr[i]=_ble_attr_QESC)) + fi + ((i+=${#m2})) + t=${t:${#BASH_REMATCH}} + done + [[ $t ]] && ((_ble_syntax_attr[i]=aquot,i+=${#t})) + if [[ $rematch4 ]]; then + ((_ble_syntax_attr[i++]=aqdel)) + else + ((_ble_syntax_attr[i-1]=_ble_attr_ERR)) + fi + return 0 + fi + fi + return 1 +} +function ble/syntax:bash/check-process-subst { + if [[ $tail == ['<>']'('* ]]; then + ble/syntax/parse/nest-push "$_ble_ctx_CMDX" '(' + ((_ble_syntax_attr[i]=_ble_attr_DEL,i+=2)) + return 0 + fi + return 1 +} +function ble/syntax:bash/check-comment { + if shopt -q interactive_comments; then + if ((wbegin<0||wbegin==i)) && local rex=$'^#[^\n]*' && [[ $tail =~ $rex ]]; then + ((_ble_syntax_attr[i]=_ble_attr_COMMENT, + i+=${#BASH_REMATCH})) + return 0 + fi + fi + return 1 +} +function ble/syntax:bash/check-glob { + [[ $tail == ['[?*@+!()|']* ]] || return 1 + local ntype= force_attr= + if ((ctx==_ble_ctx_VRHS||ctx==_ble_ctx_ARGVR||ctx==_ble_ctx_ARGER||ctx==_ble_ctx_VALR||ctx==_ble_ctx_RDRS)); then + force_attr=$ctx + ntype="glob_attr=$force_attr" + elif ((ctx==_ble_ctx_FARGX1||ctx==_ble_ctx_FARGI1)); then + force_attr=$_ble_attr_ERR + ntype="glob_attr=$force_attr" + elif ((ctx==_ble_ctx_PWORD||ctx==_ble_ctx_PWORDE||ctx==_ble_ctx_PWORDR)); then + ntype="glob_ctx=$ctx" + elif ((ctx==_ble_ctx_PATN||ctx==_ble_ctx_BRAX)); then + ble/syntax/parse/nest-type + local exit_attr= + if [[ $ntype == glob_attr=* ]]; then + force_attr=${ntype#*=} + exit_attr=$force_attr + elif ((ctx==_ble_ctx_BRAX)); then + force_attr=$ctx + ntype="glob_attr=$force_attr" + elif ((ctx==_ble_ctx_PATN)); then + ((exit_attr=_ble_syntax_attr[inest])) + [[ $ntype != glob_ctx=* ]] && ntype= + else + ntype= + fi + elif [[ $1 == assign ]]; then + ntype='a[' + fi + if [[ $tail == ['?*@+!']'('* ]] && shopt -q extglob; then + ble/syntax/parse/nest-push "$_ble_ctx_PATN" "$ntype" + ((_ble_syntax_attr[i]=${force_attr:-_ble_attr_GLOB},i+=2)) + return 0 + fi + local histc1=${_ble_syntax_bash_histc12::1} + [[ $histc1 && $tail == "$histc1"* ]] && return 1 + if [[ $tail == '['* ]]; then + if ((ctx==_ble_ctx_BRAX)); then + ((_ble_syntax_attr[i++]=force_attr)) + [[ $tail == '[!'* ]] && ((i++)) + return 0 + fi + ble/syntax/parse/nest-push "$_ble_ctx_BRAX" "$ntype" + ((_ble_syntax_attr[i++]=${force_attr:-_ble_attr_GLOB})) + [[ $tail == '[!'* ]] && ((i++)) + if [[ ${text:i:1} == ']' ]]; then + ((_ble_syntax_attr[i++]=${force_attr:-_ble_ctx_BRAX})) + elif [[ ${text:i:1} == '[' ]]; then + if [[ ${text:i+1:1} == [:=.] ]]; then + ble/syntax/parse/set-lookahead 2 + else + ((_ble_syntax_attr[i++]=${force_attr:-_ble_ctx_BRAX})) + [[ ${text:i:1} == '!'* ]] && ((i++)) + fi + fi + return 0 + elif [[ $tail == ['?*']* ]]; then + ((_ble_syntax_attr[i++]=${force_attr:-_ble_attr_GLOB})) + return 0 + elif [[ $tail == ['@+!']* ]]; then + ((_ble_syntax_attr[i++]=${force_attr:-ctx})) + return 0 + elif ((ctx==_ble_ctx_PATN||ctx==_ble_ctx_BRAX)); then + if [[ $tail == '('* ]]; then + ble/syntax/parse/nest-push "$_ble_ctx_PATN" "$ntype" + ((_ble_syntax_attr[i++]=${force_attr:-ctx})) + return 0 + elif [[ $tail == ')'* ]]; then + if ((ctx==_ble_ctx_PATN)); then + ((_ble_syntax_attr[i++]=exit_attr)) + ble/syntax/parse/nest-pop + else + ((_ble_syntax_attr[i++]=${force_attr:-ctx})) + fi + return 0 + elif [[ $tail == '|'* ]]; then + ((_ble_syntax_attr[i++]=${force_attr:-_ble_attr_GLOB})) + return 0 + fi + fi + return 1 +} +_ble_syntax_bash_histexpand_RexWord= +_ble_syntax_bash_histexpand_RexMods= +_ble_syntax_bash_histexpand_RexEventDef= +_ble_syntax_bash_histexpand_RexQuicksubDef= +_ble_syntax_bash_histexpand_RexEventFmt= +_ble_syntax_bash_histexpand_RexQuicksubFmt= +function ble/syntax:bash/check-history-expansion/.initialize { + local spaces=$_ble_term_IFS nl=$'\n' + local rex_event='-?[0-9]+|[!#]|[^-$^*%:'$spaces'=?!#;&|<>()]+|\?[^?'$nl']*\??' + _ble_syntax_bash_histexpand_RexEventDef='^!('$rex_event')' + local rex_word1='([0-9]+|[$%^])' + local rex_wordsA=':('$rex_word1'?-'$rex_word1'?|\*|'$rex_word1'\*?)' + local rex_wordsB='([$%^]?-'$rex_word1'?|\*|[$^%][*-]?)' + _ble_syntax_bash_histexpand_RexWord='('$rex_wordsA'|'$rex_wordsB')?' + local rex_modifier=':[htrepqx]|:[gGa]?&|:[gGa]?s(/([^\/]|\\.)*){0,2}(/|$)' + _ble_syntax_bash_histexpand_RexMods='('$rex_modifier')*' + _ble_syntax_bash_histexpand_RexQuicksubDef='\^([^^\]|\\.)*\^([^^\]|\\.)*\^' + _ble_syntax_bash_histexpand_RexQuicksubFmt='@A([^@C\]|\\.)*@A([^@C\]|\\.)*@A' + _ble_syntax_bash_histexpand_RexEventFmt='^@A('$rex_event'|@A)' +} +ble/syntax:bash/check-history-expansion/.initialize +function ble/syntax:bash/check-history-expansion/.initialize-event { + local histc1=${_ble_syntax_bash_histc12::1} + if [[ $histc1 == '!' ]]; then + rex_event=$_ble_syntax_bash_histexpand_RexEventDef + else + local A="[$histc1]" + [[ $histc1 == '^' ]] && A='\^' + rex_event=$_ble_syntax_bash_histexpand_RexEventFmt + rex_event=${rex_event//@A/"$A"} + fi +} +function ble/syntax:bash/check-history-expansion/.initialize-quicksub { + local histc2=${_ble_syntax_bash_histc12:1:1} + if [[ $histc2 == '^' ]]; then + rex_quicksub=$_ble_syntax_bash_histexpand_RexQuicksubDef + else + rex_quicksub=$_ble_syntax_bash_histexpand_RexQuicksubFmt + rex_quicksub=${rex_quicksub//@A/"[$histc2]"} + rex_quicksub=${rex_quicksub//@C/"$histc2"} + fi +} +function ble/syntax:bash/check-history-expansion/.check-modifiers { + [[ ${text:i} =~ $_ble_syntax_bash_histexpand_RexMods ]] && + ((i+=${#BASH_REMATCH})) + if local rex='^:[gGa]?s(.)'; [[ ${text:i} =~ $rex ]]; then + local del=${BASH_REMATCH[1]} + local A="[$del]" B="[^$del]" + [[ $del == '^' || $del == ']' ]] && A='\'$del + [[ $del != '\' ]] && B=$B'|\\.' + local rex_substitute='^:[gGa]?s('$A'('$B')*){0,2}('$A'|$)' + if [[ ${text:i} =~ $rex_substitute ]]; then + ((i+=${#BASH_REMATCH})) + ble/syntax:bash/check-history-expansion/.check-modifiers + return 0 + fi + fi + if [[ ${text:i} == ':'[gGa]* ]]; then + ((_ble_syntax_attr[i+1]=_ble_attr_ERR,i+=2)) + elif [[ ${text:i} == ':'* ]]; then + ((_ble_syntax_attr[i]=_ble_attr_ERR,i++)) + fi +} +function ble/syntax:bash/check-history-expansion { + [[ -o histexpand ]] || return 1 + local histc1=${_ble_syntax_bash_histc12:0:1} + local histc2=${_ble_syntax_bash_histc12:1:1} + if [[ $histc1 && $tail == "$histc1"[^"$_ble_syntax_bash_histstop"]* ]]; then + if ((ctx==_ble_ctx_QUOT)); then + local tail=${tail%%'"'*} + [[ $tail == '!' ]] && return 1 + fi + ((_ble_syntax_attr[i]=_ble_attr_HISTX)) + local rex_event + ble/syntax:bash/check-history-expansion/.initialize-event + if [[ $tail =~ $rex_event ]]; then + ((i+=${#BASH_REMATCH})) + elif [[ $tail == "$histc1"['-:0-9^$%*']* ]]; then + ((_ble_syntax_attr[i]=_ble_attr_HISTX,i++)) + else + ((_ble_syntax_attr[i+1]=_ble_attr_ERR,i+=2)) + return 0 + fi + [[ ${text:i} =~ $_ble_syntax_bash_histexpand_RexWord ]] && + ((i+=${#BASH_REMATCH})) + ble/syntax:bash/check-history-expansion/.check-modifiers + return 0 + elif ((i==0)) && [[ $histc2 && $tail == "$histc2"* ]]; then + ((_ble_syntax_attr[i]=_ble_attr_HISTX)) + local rex_quicksub + ble/syntax:bash/check-history-expansion/.initialize-quicksub + if [[ $tail =~ $rex_quicksub ]]; then + ((i+=${#BASH_REMATCH})) + ble/syntax:bash/check-history-expansion/.check-modifiers + return 0 + else + ((i+=${#tail})) + return 0 + fi + fi + return 1 +} +function ble/syntax:bash/starts-with-histchars { + [[ $_ble_syntax_bash_histc12 && $tail == ["$_ble_syntax_bash_histc12"]* ]] +} +_BLE_SYNTAX_FCTX[_ble_ctx_QUOT]=ble/syntax:bash/ctx-quot +function ble/syntax:bash/ctx-quot { + if ble/syntax:bash/check-plain-with-escape "[^${_ble_syntax_bash_chars[_ble_ctx_QUOT]}]+" 1; then + return 0 + elif [[ $tail == '"'* ]]; then + ((_ble_syntax_attr[i]=_ble_attr_QDEL, + i+=1)) + ble/syntax/parse/nest-pop + return 0 + elif ble/syntax:bash/check-quotes; then + return 0 + elif ble/syntax:bash/check-dollar; then + return 0 + elif ble/syntax:bash/starts-with-histchars; then + ble/syntax:bash/check-history-expansion || + ((_ble_syntax_attr[i]=ctx,i++)) + return 0 + fi + return 1 +} +_BLE_SYNTAX_FCTX[_ble_ctx_CASE]=ble/syntax:bash/ctx-case +function ble/syntax:bash/ctx-case { + if [[ $tail =~ ^$_ble_syntax_bash_RexIFSs ]]; then + ((_ble_syntax_attr[i]=ctx,i+=${#BASH_REMATCH})) + return 0 + elif [[ $tail == '('* ]]; then + ((_ble_syntax_attr[i++]=_ble_attr_GLOB,ctx=_ble_ctx_CPATX)) + return 0 + elif [[ $tail == 'esac'$_ble_syntax_bash_RexDelimiter* || $tail == 'esac' ]]; then + ((ctx=_ble_ctx_CMDX)) + ble/syntax:bash/ctx-command + else + ((ctx=_ble_ctx_CPATX)) + ble/syntax:bash/ctx-command-case-pattern-expect + fi +} +_BLE_SYNTAX_FCTX[_ble_ctx_PATN]=ble/syntax:bash/ctx-globpat +_BLE_SYNTAX_FEND[_ble_ctx_PATN]=ble/syntax:bash/ctx-globpat.end +function ble/syntax:bash/ctx-globpat/get-stop-chars { + chars=${_ble_syntax_bash_chars[_ble_ctx_PATN]} + local ntype; ble/syntax/parse/nest-type + if [[ $ntype == glob_ctx=* ]]; then + local gctx=${ntype#glob_ctx=} + if ((gctx==_ble_ctx_PWORD||gctx==_ble_ctx_PWORDE)); then + chars=}$chars + elif ((gctx==_ble_ctx_PWORDR)); then + chars=}/$chars + fi + fi +} +function ble/syntax:bash/ctx-globpat { + local chars; ble/syntax:bash/ctx-globpat/get-stop-chars + if ble/syntax:bash/check-plain-with-escape "[^$chars]+"; then + return 0 + elif ble/syntax:bash/check-process-subst; then + return 0 + elif [[ $tail == ['<>']* ]]; then + ((_ble_syntax_attr[i++]=ctx)) + return 0 + elif ble/syntax:bash/check-quotes; then + return 0 + elif ble/syntax:bash/check-dollar; then + return 0 + elif ble/syntax:bash/check-glob; then + return 0 + elif ble/syntax:bash/check-brace-expansion; then + return 0 + elif ble/syntax:bash/starts-with-histchars; then + ble/syntax:bash/check-history-expansion || + ((_ble_syntax_attr[i]=ctx,i++)) + return 0 + fi + return 1 +} +function ble/syntax:bash/ctx-globpat.end { + local is_end= tail=${text:i} + local ntype; ble/syntax/parse/nest-type + if [[ $ntype == glob_ctx=* ]]; then + local gctx=${ntype#glob_ctx=} + if ((gctx==_ble_ctx_PWORD||gctx==_ble_ctx_PWORDE)); then + [[ ! $tail || $tail == '}'* ]] && is_end=1 + elif ((gctx==_ble_ctx_PWORDR)); then + [[ ! $tail || $tail == ['/}']* ]] && is_end=1 + fi + fi + if [[ $is_end ]]; then + ble/syntax/parse/nest-pop + ble/syntax/parse/check-end + return 0 + fi + return 0 +} +_BLE_SYNTAX_FCTX[_ble_ctx_BRAX]=ble/syntax:bash/ctx-bracket-expression +_BLE_SYNTAX_FEND[_ble_ctx_BRAX]=ble/syntax:bash/ctx-bracket-expression.end +function ble/syntax:bash/ctx-bracket-expression { + local nctx; ble/syntax/parse/nest-ctx + if ((nctx==_ble_ctx_PATN)); then + local chars; ble/syntax:bash/ctx-globpat/get-stop-chars + elif ((nctx==_ble_ctx_PWORD||nctx==_ble_ctx_PWORDE||nctx==_ble_ctx_PWORDR)); then + local chars=${_ble_syntax_bash_chars[nctx]} + else + local chars=${_ble_syntax_bash_chars[_ble_ctx_ARGI]//'~'} + fi + chars="][${chars#']'}" + local ntype; ble/syntax/parse/nest-type + local force_attr=; [[ $ntype == glob_attr=* ]] && force_attr=${ntype#*=} + local rex + if [[ $tail == ']'* ]]; then + ((_ble_syntax_attr[i++]=${force_attr:-_ble_attr_GLOB})) + ble/syntax/parse/nest-pop + if [[ $ntype == 'a[' ]]; then + local is_assign= + if [[ $tail == ']='* ]]; then + ((_ble_syntax_attr[i++]=ctx,is_assign=1)) + elif [[ $tail == ']+'* ]]; then + ble/syntax/parse/set-lookahead 2 + [[ $tail == ']+=' ]] && ((_ble_syntax_attr[i]=ctx,i+=2,is_assign=1)) + fi + if [[ $is_assign ]]; then + ble/util/assert '[[ ${_ble_syntax_bash_command_CtxAssign[ctx]} ]]' + ((ctx=_ble_syntax_bash_command_CtxAssign[ctx])) + if local tail=${text:i}; [[ $tail == '~'* ]]; then + ble/syntax:bash/check-tilde-expansion rhs + fi + fi + fi + return 0 + elif [[ $tail == '['* ]]; then + rex='^\[@([^'$chars']+(@\]?)?)?' + rex=${rex//@/:}'|'${rex//@/'\.'}'|'${rex//@/=}'|^\[' + [[ $tail =~ $rex ]] + ((_ble_syntax_attr[i]=${force_attr:-ctx}, + i+=${#BASH_REMATCH})) + return 0 + elif ctx=${force_attr:-$ctx} ble/syntax:bash/check-plain-with-escape "[^$chars]+"; then + return 0 + elif ble/syntax:bash/check-process-subst; then + return 0 + elif ble/syntax:bash/check-quotes; then + return 0 + elif ble/syntax:bash/check-dollar; then + return 0 + elif ble/syntax:bash/check-glob; then + return 0 + elif ble/syntax:bash/check-brace-expansion; then + return 0 + elif ble/syntax:bash/check-tilde-expansion; then + return 0 + elif ble/syntax:bash/starts-with-histchars; then + ble/syntax:bash/check-history-expansion || + ((_ble_syntax_attr[i++]=${force_attr:-ctx})) + return 0 + elif ((nctx==_ble_ctx_PATN)) && [[ $tail == ['<>']* ]]; then + ((_ble_syntax_attr[i++]=${force_attr:-ctx})) + return 0 + fi + return 1 +} +function ble/syntax:bash/ctx-bracket-expression.end { + local is_end= + local tail=${text:i} + if [[ ! $tail ]]; then + is_end=1 + else + local nctx; ble/syntax/parse/nest-ctx + local external_ctx=$nctx + if ((nctx==_ble_ctx_PATN)); then + local ntype; ble/syntax/parse/nest-type + [[ $ntype == glob_ctx=* ]] && + external_ctx=${ntype#glob_ctx=} + fi + if ((external_ctx==_ble_ctx_PATN)); then + [[ $tail == ')'* ]] && is_end=1 + elif ((external_ctx==_ble_ctx_PWORD||external_ctx==_ble_ctx_PWORDE)); then + [[ $tail == '}'* ]] && is_end=1 + elif ((external_ctx==_ble_ctx_PWORDR)); then + [[ $tail == ['}/']* ]] && is_end=1 + else + if ble/syntax:bash/check-word-end/is-delimiter; then + is_end=1 + elif [[ $tail == ':'* && ${_ble_syntax_bash_command_IsAssign[ctx]} ]]; then + is_end=1 + fi + fi + fi + if [[ $is_end ]]; then + ble/syntax/parse/nest-pop + ble/syntax/parse/check-end + return "$?" + fi + return 0 +} +_BLE_SYNTAX_FCTX[_ble_ctx_PARAM]=ble/syntax:bash/ctx-param +_BLE_SYNTAX_FCTX[_ble_ctx_PWORD]=ble/syntax:bash/ctx-pword +_BLE_SYNTAX_FCTX[_ble_ctx_PWORDR]=ble/syntax:bash/ctx-pword +_BLE_SYNTAX_FCTX[_ble_ctx_PWORDE]=ble/syntax:bash/ctx-pword-error +function ble/syntax:bash/ctx-param { + if [[ $tail == '}'* ]]; then + ((_ble_syntax_attr[i]=_ble_syntax_attr[inest])) + ((i+=1)) + ble/syntax/parse/nest-pop + return 0 + fi + local rex='##?|%%?|:?[-?=+]|:|/[/#%]?' + ((_ble_bash>=40000)) && rex=$rex'|,,?|\^\^?|~~?' + if ((_ble_bash>=50100)); then + rex=$rex'|@[QEPAaUuLK]?' + elif ((_ble_bash>=40400)); then + rex=$rex'|@[QEPAa]?' + fi + rex='^('$rex')' + if [[ $tail =~ $rex ]]; then + ((_ble_syntax_attr[i]=_ble_ctx_PARAM, + i+=${#BASH_REMATCH})) + if [[ $BASH_REMATCH == '/'* ]]; then + ((ctx=_ble_ctx_PWORDR)) + elif [[ $BASH_REMATCH == : ]]; then + ((ctx=_ble_ctx_EXPR,_ble_syntax_attr[i-1]=_ble_ctx_EXPR)) + elif [[ $BASH_REMATCH == @* ]]; then + ((ctx=_ble_ctx_PWORDE)) + else + ((ctx=_ble_ctx_PWORD)) + [[ $BASH_REMATCH == [':-+=?#%']* ]] && + tail=${text:i} ble/syntax:bash/check-tilde-expansion pword + fi + return 0 + else + local i0=$i + ((ctx=_ble_ctx_PWORD)) + ble/syntax:bash/ctx-pword || return 1 + if ((i0+2<=i)); then + ((_ble_syntax_attr[i0+1])) || + ((_ble_syntax_attr[i0+1]=_ble_syntax_attr[i0])) + fi + ((_ble_syntax_attr[i0]=_ble_attr_ERR)) + return 0 + fi +} +function ble/syntax:bash/ctx-pword { + if ble/syntax:bash/check-plain-with-escape "[^${_ble_syntax_bash_chars[ctx]}]+"; then + return 0 + elif ((ctx==_ble_ctx_PWORDR)) && [[ $tail == '/'* ]]; then + ((_ble_syntax_attr[i++]=_ble_ctx_PARAM,ctx=_ble_ctx_PWORD)) + return 0 + elif [[ $tail == '}'* ]]; then + ((_ble_syntax_attr[i]=_ble_syntax_attr[inest])) + ((i+=1)) + ble/syntax/parse/nest-pop + return 0 + elif ble/syntax:bash/check-quotes; then + return 0 + elif ble/syntax:bash/check-dollar; then + return 0 + elif ble/syntax:bash/check-glob; then + return 0 + elif ble/syntax:bash/starts-with-histchars; then + ble/syntax:bash/check-history-expansion || + ((_ble_syntax_attr[i]=ctx,i++)) + return 0 + fi + return 1 +} +function ble/syntax:bash/ctx-pword-error { + local i0=$i + if ble/syntax:bash/ctx-pword; then + [[ $tail == '}'* ]] || + ((_ble_syntax_attr[i0]=_ble_attr_ERR)) + return 0 + else + return 1 + fi +} +_BLE_SYNTAX_FCTX[_ble_ctx_EXPR]=ble/syntax:bash/ctx-expr +function ble/syntax:bash/ctx-expr/.count-paren { + if [[ $char == ')' ]]; then + if [[ $ntype == '((' || $ntype == '$((' ]]; then + if [[ $tail == '))'* ]]; then + ((_ble_syntax_attr[i]=_ble_syntax_attr[inest])) + ((i+=2)) + ble/syntax/parse/nest-pop + else + ((ctx=_ble_ctx_ARGX0, + _ble_syntax_attr[i++]=_ble_syntax_attr[inest])) + fi + return 0 + elif [[ $ntype == '(' || $ntype == 'NQ(' ]]; then + ((_ble_syntax_attr[i++]=ctx)) + ble/syntax/parse/nest-pop + return 0 + fi + elif [[ $char == '(' ]]; then + local ntype2='(' + [[ $ntype == '$((' || $ntype == 'NQ(' ]] && ntype2='NQ(' + ble/syntax/parse/nest-push "$_ble_ctx_EXPR" "$ntype2" + ((_ble_syntax_attr[i++]=ctx)) + return 0 + fi + return 1 +} +function ble/syntax:bash/ctx-expr/.count-bracket { + if [[ $char == ']' ]]; then + if [[ $ntype == '[' || $ntype == '$[' ]]; then + ((_ble_syntax_attr[i]=_ble_syntax_attr[inest])) + ((i++)) + ble/syntax/parse/nest-pop + return 0 + elif [[ $ntype == [ad]'[' ]]; then + ((_ble_syntax_attr[i++]=_ble_ctx_EXPR)) + ble/syntax/parse/nest-pop + if [[ $tail == ']='* ]]; then + ((i++)) + tail=${text:i} ble/syntax:bash/check-tilde-expansion rhs + elif ((_ble_bash>=30100)) && [[ $tail == ']+'* ]]; then + ble/syntax/parse/set-lookahead 2 + if [[ $tail == ']+='* ]]; then + ((i+=2)) + tail=${text:i} ble/syntax:bash/check-tilde-expansion rhs + fi + else + if [[ $ntype == 'a[' ]]; then + if ((ctx==_ble_ctx_VRHS)); then + ((ctx=_ble_ctx_CMDI,wtype=_ble_ctx_CMDI)) + elif ((ctx==_ble_ctx_ARGVR)); then + ((ctx=_ble_ctx_ARGVI,wtype=_ble_ctx_ARGVI)) + elif ((ctx==_ble_ctx_ARGER)); then + ((ctx=_ble_ctx_ARGEI,wtype=_ble_ctx_ARGEI)) + fi + else # ntype == 'd[' + ((ctx=_ble_ctx_VALI,wtype=_ble_ctx_VALI)) + fi + fi + return 0 + elif [[ $ntype == 'v[' ]]; then + ((_ble_syntax_attr[i++]=_ble_ctx_EXPR)) + ble/syntax/parse/nest-pop + return 0 + fi + elif [[ $char == '[' ]]; then + ble/syntax/parse/nest-push "$_ble_ctx_EXPR" '[' + ((_ble_syntax_attr[i++]=ctx)) + return 0 + fi + return 1 +} +function ble/syntax:bash/ctx-expr/.count-brace { + if [[ $char == '}' ]]; then + ((_ble_syntax_attr[i]=_ble_syntax_attr[inest])) + ((i++)) + ble/syntax/parse/nest-pop + return 0 + fi + return 1 +} +function ble/syntax:bash/ctx-expr { + local rex + if rex='^[a-zA-Z_][a-zA-Z_0-9]*'; [[ $tail =~ $rex ]]; then + local rematch=$BASH_REMATCH + local ret; ble/syntax/highlight/vartype "$BASH_REMATCH" readvar:expr + ((_ble_syntax_attr[i]=ret,i+=${#rematch})) + return 0 + elif rex='^0[xX][0-9a-fA-F]*|^[0-9]+(#[0-9a-zA-Z@_]*)?'; [[ $tail =~ $rex ]]; then + ((_ble_syntax_attr[i]=_ble_attr_VAR_NUMBER,i+=${#BASH_REMATCH})) + return 0 + elif ble/syntax:bash/check-plain-with-escape "[^${_ble_syntax_bash_chars[ctx]}a-zA-Z_0-9]+" 1; then + return 0 + elif [[ $tail == ['][()}']* ]]; then + local char=${tail::1} ntype + ble/syntax/parse/nest-type + if [[ $ntype == *'(' ]]; then + ble/syntax:bash/ctx-expr/.count-paren && return 0 + elif [[ $ntype == *'[' ]]; then + ble/syntax:bash/ctx-expr/.count-bracket && return 0 + elif [[ $ntype == '${' || $ntype == '"${' ]]; then + ble/syntax:bash/ctx-expr/.count-brace && return 0 + else + ble/util/assert 'false' "unexpected ntype=$ntype for arithmetic expression" + fi + ((_ble_syntax_attr[i++]=ctx)) + return 0 + elif ble/syntax:bash/check-quotes; then + return 0 + elif ble/syntax:bash/check-dollar; then + return 0 + elif ble/syntax:bash/starts-with-histchars; then + ble/syntax:bash/check-history-expansion || + ((_ble_syntax_attr[i]=ctx,i++)) + return 0 + fi + return 1 +} +function ble/syntax:bash/check-brace-expansion { + [[ $tail == '{'* ]] || return 1 + local rex='^\{[-+0-9a-zA-Z.]*(\}?)' + [[ $tail =~ $rex ]] + local str=$BASH_REMATCH + local force_attr= inactive= + if [[ $- != *B* ]]; then + inactive=1 + elif ((ctx==_ble_ctx_CONDI||ctx==_ble_ctx_CONDQ||ctx==_ble_ctx_RDRS||ctx==_ble_ctx_VRHS)); then + inactive=1 + elif ((ctx==_ble_ctx_PATN||ctx==_ble_ctx_BRAX)); then + local ntype; ble/syntax/parse/nest-type + if [[ $ntype == glob_attr=* ]]; then + force_attr=${ntype#*=} + (((force_attr==_ble_ctx_RDRS||force_attr==_ble_ctx_VRHS||force_attr==_ble_ctx_ARGVR||force_attr==_ble_ctx_ARGER||force_attr==_ble_ctx_VALR)&&(inactive=1))) + elif ((ctx==_ble_ctx_BRAX)); then + local nctx; ble/syntax/parse/nest-ctx + (((nctx==_ble_ctx_CONDI||octx==_ble_ctx_CONDQ)&&(inactive=1))) + fi + elif ((ctx==_ble_ctx_BRACE1||ctx==_ble_ctx_BRACE2)); then + local ntype; ble/syntax/parse/nest-type + if [[ $ntype == glob_attr=* ]]; then + force_attr=${ntype#*=} + fi + fi + if [[ $inactive ]]; then + ((_ble_syntax_attr[i]=${force_attr:-ctx},i+=${#str})) + return 0 + fi + [[ ${_ble_syntax_bash_command_IsAssign[ctx]} ]] && + ctx=${_ble_syntax_bash_command_IsAssign[ctx]} + if rex='^\{(([-+]?[0-9]+)\.\.[-+]?[0-9]+|[a-zA-Z]\.\.[a-zA-Z])(\.\.[-+]?[0-9]+)?\}$'; [[ $str =~ $rex ]]; then + if [[ $force_attr ]]; then + ((_ble_syntax_attr[i]=force_attr,i+=${#str})) + else + local rematch1=${BASH_REMATCH[1]} + local rematch2=${BASH_REMATCH[2]} + local rematch3=${BASH_REMATCH[3]} + local len2=${#rematch2}; ((len2||(len2=1))) + local attr=$_ble_attr_BRACE + if ((ctx==_ble_ctx_RDRF||ctx==_ble_ctx_RDRD||ctx==_ble_ctx_RDRD2)); then + local lhs=${rematch1::len2} rhs=${rematch1:len2+2} + if [[ $rematch2 ]]; then + local lhs1=$((10#0${lhs#[-+]})); [[ $lhs == -* ]] && ((lhs1=-lhs1)) + local rhs1=$((10#0${rhs#[-+]})); [[ $rhs == -* ]] && ((rhs1=-rhs1)) + lhs=$lhs1 rhs=$rhs1 + fi + [[ $lhs != "$rhs" ]] && ((attr=_ble_attr_ERR)) + fi + ((_ble_syntax_attr[i++]=attr)) + ((_ble_syntax_attr[i]=ctx,i+=len2, + _ble_syntax_attr[i]=_ble_attr_BRACE,i+=2, + _ble_syntax_attr[i]=ctx,i+=${#rematch1}-len2-2)) + if [[ $rematch3 ]]; then + ((_ble_syntax_attr[i]=_ble_attr_BRACE,i+=2, + _ble_syntax_attr[i]=ctx,i+=${#rematch3}-2)) + fi + ((_ble_syntax_attr[i++]=attr)) + fi + return 0 + fi + local ntype= + ((ctx==_ble_ctx_RDRF||ctx==_ble_ctx_RDRD||ctx==_ble_ctx_RDRD2)) && force_attr=$ctx + [[ $force_attr ]] && ntype="glob_attr=$force_attr" + ble/syntax/parse/nest-push "$_ble_ctx_BRACE1" "$ntype" + local len=$((${#str}-1)) + ((_ble_syntax_attr[i++]=${force_attr:-_ble_attr_BRACE}, + len&&(_ble_syntax_attr[i]=${force_attr:-ctx},i+=len))) + return 0 +} +_BLE_SYNTAX_FCTX[_ble_ctx_BRACE1]=ble/syntax:bash/ctx-brace-expansion +_BLE_SYNTAX_FCTX[_ble_ctx_BRACE2]=ble/syntax:bash/ctx-brace-expansion +_BLE_SYNTAX_FEND[_ble_ctx_BRACE1]=ble/syntax:bash/ctx-brace-expansion.end +_BLE_SYNTAX_FEND[_ble_ctx_BRACE2]=ble/syntax:bash/ctx-brace-expansion.end +function ble/syntax:bash/ctx-brace-expansion { + if [[ $tail == '}'* ]] && ((ctx==_ble_ctx_BRACE2)); then + local force_attr= + local ntype; ble/syntax/parse/nest-type + [[ $ntype == glob_attr=* ]] && force_attr=$_ble_attr_ERR # ※${ntype#*=} ではなくエラー + ((_ble_syntax_attr[i++]=${force_attr:-_ble_attr_BRACE})) + ble/syntax/parse/nest-pop + return 0 + elif [[ $tail == ','* ]]; then + local force_attr= + local ntype; ble/syntax/parse/nest-type + [[ $ntype == glob_attr=* ]] && force_attr=${ntype#*=} + ((_ble_syntax_attr[i++]=${force_attr:-_ble_attr_BRACE})) + ((ctx=_ble_ctx_BRACE2)) + return 0 + fi + local chars=",${_ble_syntax_bash_chars[_ble_ctx_ARGI]//'~:'}" + ((ctx==_ble_ctx_BRACE2)) && chars="}$chars" + ble/syntax:bash/cclass/update/reorder chars + if ble/syntax:bash/check-plain-with-escape "[^$chars]+"; then + return 0 + elif ble/syntax:bash/check-process-subst; then + return 0 + elif ble/syntax:bash/check-quotes; then + return 0 + elif ble/syntax:bash/check-dollar; then + return 0 + elif ble/syntax:bash/check-glob; then + return 0 + elif ble/syntax:bash/check-brace-expansion; then + return 0 + elif ble/syntax:bash/starts-with-histchars; then + ble/syntax:bash/check-history-expansion || + ((_ble_syntax_attr[i++]=ctx)) + return 0 + fi + return 1 +} +function ble/syntax:bash/ctx-brace-expansion.end { + if ((i==${#text})) || ble/syntax:bash/check-word-end/is-delimiter; then + ble/syntax/parse/nest-pop + ble/syntax/parse/check-end + return "$?" + fi + return 0 +} +function ble/syntax:bash/check-tilde-expansion { + [[ $tail == ['~:']* ]] || return 1 + local rhs_enabled= + { ((ctx==_ble_ctx_VRHS||ctx==_ble_ctx_ARGVR||ctx==_ble_ctx_VALR||ctx==_ble_ctx_ARGER)) || + ! ble/base/is-POSIXLY_CORRECT; } && rhs_enabled=1 + local tilde_enabled=$((i==wbegin||ctx==_ble_ctx_PWORD)) + [[ $1 == rhs && $rhs_enabled ]] && tilde_enabled=1 # = の直後 + if [[ $tail == ':'* ]]; then + _ble_syntax_attr[i++]=$ctx + if [[ $rhs_enabled ]]; then + if ! ((tilde_enabled=_ble_syntax_bash_command_IsAssign[ctx])); then + if ((ctx==_ble_ctx_BRAX)); then + local nctx; ble/syntax/parse/nest-ctx + ((tilde_enabled=_ble_syntax_bash_command_IsAssign[nctx])) + fi + fi + fi + local tail=${text:i} + [[ $tail == '~'* ]] || return 0 + fi + if ((tilde_enabled)); then + local chars="${_ble_syntax_bash_chars[_ble_ctx_ARGI]}/:" + ((ctx==_ble_ctx_PWORD)) && chars=${chars/'{'/'{}'} + ble/syntax:bash/cclass/update/reorder chars + local delimiters="$_ble_term_IFS;|&)<>" + local rex='^(~\+|~[^'$chars']*)([^'$delimiters'/:]?)'; [[ $tail =~ $rex ]] + local str=${BASH_REMATCH[1]} + local path attr=$ctx + builtin eval "path=$str" + if [[ ! ${BASH_REMATCH[2]} && $path != "$str" ]]; then + ((attr=_ble_attr_TILDE)) + if ((ctx==_ble_ctx_BRAX)); then + ble/util/assert 'ble/util/unlocal tail; [[ $tail == ":~"* ]]' + ble/syntax/parse/nest-pop + fi + else + if [[ $str == '~+' ]]; then + ble/syntax/parse/set-lookahead 3 + str='~' + fi + fi + ((_ble_syntax_attr[i]=attr,i+=${#str})) + else + ((_ble_syntax_attr[i]=ctx,i++)) # skip tilde + local chars=${_ble_syntax_bash_chars[_ble_ctx_ARGI]} + ble/syntax:bash/check-plain-with-escape "[^$chars]+" # 追加(失敗してもOK) + fi + return 0 +} +_ble_syntax_bash_command_CtxAssign[_ble_ctx_CMDI]=$_ble_ctx_VRHS +_ble_syntax_bash_command_CtxAssign[_ble_ctx_COARGI]=$_ble_ctx_VRHS +_ble_syntax_bash_command_CtxAssign[_ble_ctx_ARGVI]=$_ble_ctx_ARGVR +_ble_syntax_bash_command_CtxAssign[_ble_ctx_ARGEI]=$_ble_ctx_ARGER +_ble_syntax_bash_command_CtxAssign[_ble_ctx_ARGI]=$_ble_ctx_ARGQ +_ble_syntax_bash_command_CtxAssign[_ble_ctx_FARGI3]=$_ble_ctx_FARGQ3 +_ble_syntax_bash_command_CtxAssign[_ble_ctx_CARGI1]=$_ble_ctx_CARGQ1 +_ble_syntax_bash_command_CtxAssign[_ble_ctx_CPATI]=$_ble_ctx_CPATQ +_ble_syntax_bash_command_CtxAssign[_ble_ctx_VALI]=$_ble_ctx_VALQ +_ble_syntax_bash_command_CtxAssign[_ble_ctx_CONDI]=$_ble_ctx_CONDQ +_ble_syntax_bash_command_IsAssign[_ble_ctx_VRHS]=$_ble_ctx_CMDI +_ble_syntax_bash_command_IsAssign[_ble_ctx_ARGVR]=$_ble_ctx_ARGVI +_ble_syntax_bash_command_IsAssign[_ble_ctx_ARGER]=$_ble_ctx_ARGEI +_ble_syntax_bash_command_IsAssign[_ble_ctx_ARGQ]=$_ble_ctx_ARGI +_ble_syntax_bash_command_IsAssign[_ble_ctx_FARGQ3]=$_ble_ctx_FARGI3 +_ble_syntax_bash_command_IsAssign[_ble_ctx_CARGQ1]=$_ble_ctx_CARGI1 +_ble_syntax_bash_command_IsAssign[_ble_ctx_CPATQ]=$_ble_ctx_CPATI +_ble_syntax_bash_command_IsAssign[_ble_ctx_VALR]=$_ble_ctx_VALI +_ble_syntax_bash_command_IsAssign[_ble_ctx_VALQ]=$_ble_ctx_VALI +_ble_syntax_bash_command_IsAssign[_ble_ctx_CONDQ]=$_ble_ctx_CONDI +function ble/syntax:bash/check-variable-assignment { + ((wbegin==i)) || return 1 + if ((ctx==_ble_ctx_VALI)) && [[ $tail == '['* ]]; then + ((ctx=_ble_ctx_VALR)) + ble/syntax/parse/nest-push "$_ble_ctx_EXPR" 'd[' + ((_ble_syntax_attr[i++]=ctx)) + return 0 + fi + [[ ${_ble_syntax_bash_command_CtxAssign[ctx]} ]] || return 1 + local suffix='[=[]' + ((_ble_bash>=30100)) && suffix=$suffix'|\+=?' + local rex_assign="^([a-zA-Z_][a-zA-Z_0-9]*)($suffix)" + [[ $tail =~ $rex_assign ]] || return 1 + local rematch=$BASH_REMATCH + local rematch1=${BASH_REMATCH[1]} # for bash-3.1 ${#arr[n]} bug + local rematch2=${BASH_REMATCH[2]} # for bash-3.1 ${#arr[n]} bug + if [[ $rematch2 == '+' ]]; then + ble/syntax/parse/set-lookahead $((${#rematch}+1)) + return 1 + fi + local variable_assign= + if ((ctx==_ble_ctx_CMDI||ctx==_ble_ctx_ARGVI||ctx==_ble_ctx_ARGEI&&${#rematch2})); then + local ret; ble/syntax/highlight/vartype "$rematch1" + ((wtype=_ble_attr_VAR, + _ble_syntax_attr[i]=ret, + i+=${#rematch}, + ${#rematch2}&&(_ble_syntax_attr[i-${#rematch2}]=_ble_ctx_EXPR), + variable_assign=1, + ctx=_ble_syntax_bash_command_CtxAssign[ctx])) + else + ((_ble_syntax_attr[i]=ctx, + i+=${#rematch})) + fi + if [[ $rematch2 == '[' ]]; then + if [[ $variable_assign ]]; then + i=$((i-1)) ble/syntax/parse/nest-push "$_ble_ctx_EXPR" 'a[' + else + ((i--)) + tail=${text:i} ble/syntax:bash/check-glob assign + fi + elif [[ $rematch2 == *'=' ]]; then + if [[ $variable_assign && ${text:i} == '('* ]]; then + ble/syntax:bash/ctx-values/enter + ((_ble_syntax_attr[i++]=_ble_attr_DEL)) + else + [[ $variable_assign ]] || ((ctx=_ble_syntax_bash_command_CtxAssign[ctx])) + if local tail=${text:i}; [[ $tail == '~'* ]]; then + ble/syntax:bash/check-tilde-expansion rhs + fi + fi + fi + return 0 +} +_BLE_SYNTAX_FCTX[_ble_ctx_ARGX]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_ARGX0]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_CMDX]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_CMDX1]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_CMDXT]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_CMDXC]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_CMDXE]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_CMDXD]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_CMDXD0]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_CMDXV]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_ARGI]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_ARGQ]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_CMDI]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_VRHS]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_ARGVR]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_ARGER]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FEND[_ble_ctx_CMDI]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FEND[_ble_ctx_ARGI]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FEND[_ble_ctx_ARGQ]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FEND[_ble_ctx_VRHS]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FEND[_ble_ctx_ARGVR]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FEND[_ble_ctx_ARGER]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FCTX[_ble_ctx_ARGVX]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_ARGVI]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FEND[_ble_ctx_ARGVI]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FCTX[_ble_ctx_ARGEX]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_ARGEI]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FEND[_ble_ctx_ARGEI]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FCTX[_ble_ctx_SARGX1]=ble/syntax:bash/ctx-command-compound-expect +_BLE_SYNTAX_FCTX[_ble_ctx_FARGX1]=ble/syntax:bash/ctx-command-compound-expect +_BLE_SYNTAX_FCTX[_ble_ctx_FARGX2]=ble/syntax:bash/ctx-command-compound-expect +_BLE_SYNTAX_FCTX[_ble_ctx_FARGX3]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_FARGI1]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_FARGI2]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_FARGI3]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_FARGQ3]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FEND[_ble_ctx_FARGI1]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FEND[_ble_ctx_FARGI2]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FEND[_ble_ctx_FARGI3]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FEND[_ble_ctx_FARGQ3]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FCTX[_ble_ctx_CARGX1]=ble/syntax:bash/ctx-command-compound-expect +_BLE_SYNTAX_FCTX[_ble_ctx_CARGX2]=ble/syntax:bash/ctx-command-compound-expect +_BLE_SYNTAX_FCTX[_ble_ctx_CPATX]=ble/syntax:bash/ctx-command-case-pattern-expect +_BLE_SYNTAX_FCTX[_ble_ctx_CPATX0]=ble/syntax:bash/ctx-command-case-pattern-expect +_BLE_SYNTAX_FCTX[_ble_ctx_CARGI1]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_CARGQ1]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_CARGI2]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_CPATI]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_CPATQ]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FEND[_ble_ctx_CARGI1]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FEND[_ble_ctx_CARGQ1]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FEND[_ble_ctx_CARGI2]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FEND[_ble_ctx_CPATI]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FEND[_ble_ctx_CPATQ]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FCTX[_ble_ctx_TARGX1]=ble/syntax:bash/ctx-command-time-expect +_BLE_SYNTAX_FCTX[_ble_ctx_TARGX2]=ble/syntax:bash/ctx-command-time-expect +_BLE_SYNTAX_FCTX[_ble_ctx_TARGI1]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FCTX[_ble_ctx_TARGI2]=ble/syntax:bash/ctx-command +_BLE_SYNTAX_FEND[_ble_ctx_TARGI1]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FEND[_ble_ctx_TARGI2]=ble/syntax:bash/ctx-command/check-word-end +_BLE_SYNTAX_FCTX[_ble_ctx_COARGX]=ble/syntax:bash/ctx-command-compound-expect +_BLE_SYNTAX_FEND[_ble_ctx_COARGI]=ble/syntax:bash/ctx-coproc/check-word-end +function ble/syntax:bash/starts-with-delimiter-or-redirect { + local delimiters=$_ble_syntax_bash_RexDelimiter + local redirect=$_ble_syntax_bash_RexRedirect + [[ ( $tail =~ ^$delimiters || $wbegin -lt 0 && $tail =~ ^$redirect || $wbegin -lt 0 && $tail == $'\\\n'* ) && $tail != ['<>']'('* ]] +} +function ble/syntax:bash/starts-with-delimiter { + [[ $tail == ["$_ble_term_IFS;|&<>()"]* && $tail != ['<>']'('* ]] +} +function ble/syntax:bash/check-word-end/is-delimiter { + local tail=${text:i} + if [[ $tail == [!"$_ble_term_IFS;|&<>()"]* ]]; then + return 1 + elif [[ $tail == ['<>']* ]]; then + ble/syntax/parse/set-lookahead 2 + [[ $tail == ['<>']'('* ]] && return 1 + fi + return 0 +} +function ble/syntax:bash/check-here-document-from { + local spaces=$1 + [[ $nparam && $spaces == *$'\n'* ]] || return 1 + local rex="$_ble_term_FS@([RI][QH][^$_ble_term_FS]*)(.*$)" && [[ $nparam =~ $rex ]] || return 1 + local rematch1=${BASH_REMATCH[1]} + local rematch2=${BASH_REMATCH[2]} + local padding=${spaces%%$'\n'*} + ((_ble_syntax_attr[i]=ctx,i+=${#padding})) + nparam=${nparam::${#nparam}-${#BASH_REMATCH}}${nparam:${#nparam}-${#rematch2}} + ble/syntax/parse/nest-push "$_ble_ctx_HERE0" + ((i++)) + nparam=$rematch1 + return 0 +} +function ble/syntax:bash/ctx-coproc/.is-next-compound { + local p=$i ahead=1 tail=${text:i} + if local rex=$'^[ \t]+'; [[ $tail =~ $rex ]]; then + ((p+=${#BASH_REMATCH})) + ahead=1 tail=${text:p} + fi + local is_compound= + if [[ $tail == '('* ]]; then + is_compound=1 + elif rex='^[a-z]+|^\[\[?|^[{}!]'; [[ $tail =~ $rex ]]; then + local rematch=$BASH_REMATCH + ((p+=${#rematch})) + [[ $rematch == ['{}!'] || $rematch == '[[' ]]; ahead=$? + rex='^(\[\[|for|select|case|if|while|until|fi|done|esac|then|elif|else|do|[{}!]|coproc|function)$' + if [[ $rematch =~ $rex ]]; then + if rex='^[;|&()'$_ble_term_IFS']|^$|^[<>]\(?' ahead=1; [[ ${text:p} =~ $rex ]]; then + local rematch=$BASH_REMATCH + ((p+=${#rematch})) + [[ $rematch && $rematch != ['<>'] ]]; ahead=$? + [[ $rematch != ['<>']'(' ]] && is_compound=1 + fi + fi + fi + ble/syntax/parse/set-lookahead $((p+ahead-i)) + [[ $is_compound ]] +} +function ble/syntax:bash/ctx-coproc/check-word-end { + ble/util/assert '((ctx==_ble_ctx_COARGI))' + ((wbegin<0)) && return 1 + ble/syntax:bash/check-word-end/is-delimiter || return 1 + local wbeg=$wbegin wlen=$((i-wbegin)) wend=$i + local word=${text:wbegin:wlen} + local wt=$wtype + if local rex='^[_a-zA-Z0-9]+$'; [[ $word =~ $rex ]]; then + if ble/syntax:bash/ctx-coproc/.is-next-compound; then + ((_ble_syntax_attr[wbegin]=_ble_attr_VAR)) + ((ctx=_ble_ctx_CMDXC,type=_ble_ctx_ARGVI)) + ble/syntax/parse/word-pop + return 0 + fi + fi + ((ctx=_ble_ctx_CMDI,wtype=_ble_ctx_CMDX)) + ble/syntax:bash/ctx-command/check-word-end +} +_ble_syntax_bash_command_EndCtx=() +_ble_syntax_bash_command_EndCtx[_ble_ctx_ARGI]=$_ble_ctx_ARGX +_ble_syntax_bash_command_EndCtx[_ble_ctx_ARGQ]=$_ble_ctx_ARGX +_ble_syntax_bash_command_EndCtx[_ble_ctx_ARGVI]=$_ble_ctx_ARGVX +_ble_syntax_bash_command_EndCtx[_ble_ctx_ARGVR]=$_ble_ctx_ARGVX +_ble_syntax_bash_command_EndCtx[_ble_ctx_ARGEI]=$_ble_ctx_ARGEX +_ble_syntax_bash_command_EndCtx[_ble_ctx_ARGER]=$_ble_ctx_ARGEX +_ble_syntax_bash_command_EndCtx[_ble_ctx_VRHS]=$_ble_ctx_CMDXV +_ble_syntax_bash_command_EndCtx[_ble_ctx_FARGI1]=$_ble_ctx_FARGX2 +_ble_syntax_bash_command_EndCtx[_ble_ctx_FARGI2]=$_ble_ctx_FARGX3 +_ble_syntax_bash_command_EndCtx[_ble_ctx_FARGI3]=$_ble_ctx_FARGX3 +_ble_syntax_bash_command_EndCtx[_ble_ctx_FARGQ3]=$_ble_ctx_FARGX3 +_ble_syntax_bash_command_EndCtx[_ble_ctx_CARGI1]=$_ble_ctx_CARGX2 +_ble_syntax_bash_command_EndCtx[_ble_ctx_CARGQ1]=$_ble_ctx_CARGX2 +_ble_syntax_bash_command_EndCtx[_ble_ctx_CARGI2]=$_ble_ctx_CASE +_ble_syntax_bash_command_EndCtx[_ble_ctx_CPATI]=$_ble_ctx_CPATX0 +_ble_syntax_bash_command_EndCtx[_ble_ctx_CPATQ]=$_ble_ctx_CPATX0 +_ble_syntax_bash_command_EndCtx[_ble_ctx_TARGI1]=$((_ble_bash>=40200?_ble_ctx_TARGX2:_ble_ctx_CMDXT)) #1 +_ble_syntax_bash_command_EndCtx[_ble_ctx_TARGI2]=$_ble_ctx_CMDXT +_ble_syntax_bash_command_EndWtype[_ble_ctx_ARGX]=$_ble_ctx_ARGI +_ble_syntax_bash_command_EndWtype[_ble_ctx_ARGX0]=$_ble_ctx_ARGI +_ble_syntax_bash_command_EndWtype[_ble_ctx_ARGVX]=$_ble_ctx_ARGVI +_ble_syntax_bash_command_EndWtype[_ble_ctx_ARGEX]=$_ble_ctx_ARGEI +_ble_syntax_bash_command_EndWtype[_ble_ctx_CMDX]=$_ble_ctx_CMDI +_ble_syntax_bash_command_EndWtype[_ble_ctx_CMDX1]=$_ble_ctx_CMDI +_ble_syntax_bash_command_EndWtype[_ble_ctx_CMDXT]=$_ble_ctx_CMDI +_ble_syntax_bash_command_EndWtype[_ble_ctx_CMDXC]=$_ble_ctx_CMDI +_ble_syntax_bash_command_EndWtype[_ble_ctx_CMDXE]=$_ble_ctx_CMDI +_ble_syntax_bash_command_EndWtype[_ble_ctx_CMDXD]=$_ble_ctx_CMDI +_ble_syntax_bash_command_EndWtype[_ble_ctx_CMDXD0]=$_ble_ctx_CMDI +_ble_syntax_bash_command_EndWtype[_ble_ctx_CMDXV]=$_ble_ctx_CMDI +_ble_syntax_bash_command_EndWtype[_ble_ctx_FARGX1]=$_ble_ctx_FARGI1 # 変数名 +_ble_syntax_bash_command_EndWtype[_ble_ctx_SARGX1]=$_ble_ctx_ARGI +_ble_syntax_bash_command_EndWtype[_ble_ctx_FARGX2]=$_ble_ctx_FARGI2 # in +_ble_syntax_bash_command_EndWtype[_ble_ctx_FARGX3]=$_ble_ctx_ARGI # in +_ble_syntax_bash_command_EndWtype[_ble_ctx_CARGX1]=$_ble_ctx_ARGI +_ble_syntax_bash_command_EndWtype[_ble_ctx_CARGX2]=$_ble_ctx_CARGI2 # in +_ble_syntax_bash_command_EndWtype[_ble_ctx_CPATX]=$_ble_ctx_CPATI +_ble_syntax_bash_command_EndWtype[_ble_ctx_CPATX0]=$_ble_ctx_CPATI +_ble_syntax_bash_command_EndWtype[_ble_ctx_TARGX1]=$_ble_ctx_ARGI # -p +_ble_syntax_bash_command_EndWtype[_ble_ctx_TARGX2]=$_ble_ctx_ARGI # -- +_ble_syntax_bash_command_Expect=() +_ble_syntax_bash_command_Expect[_ble_ctx_CMDXC]='^(\(|\{|\(\(|\[\[|for|select|case|if|while|until)$' +_ble_syntax_bash_command_Expect[_ble_ctx_CMDXE]='^(\}|fi|done|esac|then|elif|else|do)$' +_ble_syntax_bash_command_Expect[_ble_ctx_CMDXD]='^(\{|do)$' +_ble_syntax_bash_command_Expect[_ble_ctx_CMDXD0]='^(\{|do)$' +function ble/syntax:bash/ctx-command/check-word-end { + ((wbegin<0)) && return 1 + ble/syntax:bash/check-word-end/is-delimiter || return 1 + local wbeg=$wbegin wlen=$((i-wbegin)) wend=$i + local word=${text:wbegin:wlen} + local wt=$wtype + [[ ${_ble_syntax_bash_command_EndWtype[wt]} ]] && + wtype=${_ble_syntax_bash_command_EndWtype[wt]} + local rex_expect_command=${_ble_syntax_bash_command_Expect[wt]} + if [[ $rex_expect_command ]]; then + [[ $word =~ $rex_expect_command ]] || ((wtype=_ble_attr_ERR)) + fi + if ((wt==_ble_ctx_CMDX1)); then + local rex='^(then|elif|else|do|\}|done|fi|esac)$' + [[ $word =~ $rex ]] && ((wtype=_ble_attr_ERR)) + fi + ble/syntax/parse/word-pop + if ((ctx==_ble_ctx_CMDI)); then + local ret + ble/alias#expand "$word"; local word_expanded=$ret + if ((wt!=_ble_ctx_CMDXV)); then # Note: 変数代入の直後はキーワードは処理しない + local processed= + case "$word_expanded" in + ('[[') + ble/syntax/parse/touch-updated-attr "$wbeg" + ((_ble_syntax_attr[wbeg]=_ble_attr_DEL, + ctx=_ble_ctx_ARGX0)) + ble/syntax/parse/word-cancel # 単語 "[[" (とその内部のノード全て) を削除 + if [[ $word == '[[' ]]; then + _ble_syntax_attr[wbeg+1]= # 角括弧式として着色されているのを消去 + fi + i=$wbeg ble/syntax/parse/nest-push "$_ble_ctx_CONDX" + i=$wbeg ble/syntax/parse/word-push "$_ble_ctx_CMDI" "$wbeg" + ble/syntax/parse/word-pop + return 0 ;; + ('time') ((ctx=_ble_ctx_TARGX1)); processed=keyword ;; + ('!') ((ctx=_ble_ctx_CMDXT)) ; processed=keyword ;; + ('if'|'while'|'until') ((ctx=_ble_ctx_CMDX1)) ; processed=begin ;; + ('for') ((ctx=_ble_ctx_FARGX1)); processed=begin ;; + ('select') ((ctx=_ble_ctx_SARGX1)); processed=begin ;; + ('case') ((ctx=_ble_ctx_CARGX1)); processed=begin ;; + ('{') + ((ctx=_ble_ctx_CMDX1)) + if ((wt==_ble_ctx_CMDXD||wt==_ble_ctx_CMDXD0)); then + processed=middle # "for ...; {" などの時 + else + processed=begin + fi ;; + ('then'|'elif'|'else'|'do') ((ctx=_ble_ctx_CMDX1)) ; processed=middle ;; + ('}'|'done'|'fi'|'esac') ((ctx=_ble_ctx_CMDXE)) ; processed=end ;; + ('coproc') + if ((_ble_bash>=40000)); then + if ble/syntax:bash/ctx-coproc/.is-next-compound; then + ((ctx=_ble_ctx_CMDXC)) + else + ((ctx=_ble_ctx_COARGX)) + fi + processed=keyword + fi ;; + ('function') + ((ctx=_ble_ctx_ARGX)) + local isfuncsymx=$'\t\n'' "$&'\''();<>\`|' rex_space=$'[ \t]' rex + if rex="^$rex_space+" && [[ ${text:i} =~ $rex ]]; then + ((_ble_syntax_attr[i]=_ble_ctx_ARGX,i+=${#BASH_REMATCH},ctx=_ble_ctx_ARGX)) + if rex="^([^#$isfuncsymx][^$isfuncsymx]*)($rex_space*)(\(\(|\($rex_space*\)?)?" && [[ ${text:i} =~ $rex ]]; then + local rematch1=${BASH_REMATCH[1]} + local rematch2=${BASH_REMATCH[2]} + local rematch3=${BASH_REMATCH[3]} + ((_ble_syntax_attr[i]=_ble_attr_FUNCDEF,i+=${#rematch1}, + ${#rematch2}&&(_ble_syntax_attr[i]=_ble_ctx_CMDX1,i+=${#rematch2}))) + if [[ $rematch3 == '('*')' ]]; then + ((_ble_syntax_attr[i]=_ble_attr_DEL,i+=${#rematch3},ctx=_ble_ctx_CMDXC)) + elif ((_ble_bash>=40200)) && [[ $rematch3 == '((' ]]; then + ble/syntax/parse/set-lookahead 2 + ((ctx=_ble_ctx_CMDXC)) + elif [[ $rematch3 == '('* ]]; then + ((_ble_syntax_attr[i]=_ble_attr_ERR,ctx=_ble_ctx_ARGX0)) + ble/syntax/parse/nest-push "$_ble_ctx_CMDX1" '(' + ((${#rematch3}>=2&&(_ble_syntax_attr[i+1]=_ble_ctx_CMDX1),i+=${#rematch3})) + else + ((ctx=_ble_ctx_CMDXC)) + fi + processed=keyword + fi + fi + [[ $processed ]] || ((_ble_syntax_attr[i-1]=_ble_attr_ERR)) ;; + esac + if [[ $processed ]]; then + local attr= + case $processed in + (keyword) attr=$_ble_attr_KEYWORD ;; + (begin) attr=$_ble_attr_KEYWORD_BEGIN ;; + (end) attr=$_ble_attr_KEYWORD_END ;; + (middle) attr=$_ble_attr_KEYWORD_MID ;; + esac + if [[ $attr ]]; then + ble/syntax/parse/touch-updated-attr "$wbeg" + ((_ble_syntax_attr[wbeg]=attr)) + fi + return 0 + fi + fi + ((ctx=_ble_ctx_ARGX)) + if local rex='^([ ]*)(\([ ]*\)?)?'; [[ ${text:i} =~ $rex && $BASH_REMATCH ]]; then + local rematch1=${BASH_REMATCH[1]} + local rematch2=${BASH_REMATCH[2]} + if [[ $rematch2 == '('*')' ]]; then + _ble_syntax_tree[i-1]="$_ble_attr_FUNCDEF ${_ble_syntax_tree[i-1]#* }" + ((_ble_syntax_attr[i]=_ble_ctx_CMDX1,i+=${#rematch1}, + _ble_syntax_attr[i]=_ble_attr_DEL,i+=${#rematch2}, + ctx=_ble_ctx_CMDXC)) + elif [[ $rematch2 == '('* ]]; then + ((_ble_syntax_attr[i]=_ble_ctx_ARGX0,i+=${#rematch1}, + _ble_syntax_attr[i]=_ble_attr_ERR, + ctx=_ble_ctx_ARGX0)) + ble/syntax/parse/nest-push "$_ble_ctx_PATN" + ((${#rematch2}>=2&&(_ble_syntax_attr[i+1]=_ble_ctx_CMDXC), + i+=${#rematch2})) + else + ((_ble_syntax_attr[i]=_ble_ctx_ARGX,i+=${#rematch1})) + fi + fi + case $word_expanded in + ('declare'|'readonly'|'typeset'|'local'|'export'|'alias') + ((ctx=_ble_ctx_ARGVX)) ;; + ('eval') + ((ctx=_ble_ctx_ARGEX)) ;; + esac + return 0 + fi + if ((ctx==_ble_ctx_FARGI2)); then + if [[ $word == do ]]; then + ((ctx=_ble_ctx_CMDX1)) + return 0 + fi + fi + if ((ctx==_ble_ctx_FARGI2||ctx==_ble_ctx_CARGI2)); then + if [[ $word != in ]]; then + ble/syntax/parse/touch-updated-attr "$wbeg" + ((_ble_syntax_attr[wbeg]=_ble_attr_ERR)) + fi + fi + if ((_ble_syntax_bash_command_EndCtx[ctx])); then + ((ctx=_ble_syntax_bash_command_EndCtx[ctx])) + fi + return 0 +} +_ble_syntax_bash_command_Opt=() +_ble_syntax_bash_command_Opt[_ble_ctx_ARGX]=1 +_ble_syntax_bash_command_Opt[_ble_ctx_ARGX0]=1 +_ble_syntax_bash_command_Opt[_ble_ctx_ARGVX]=1 +_ble_syntax_bash_command_Opt[_ble_ctx_ARGEX]=1 +_ble_syntax_bash_command_Opt[_ble_ctx_CMDXV]=1 +_ble_syntax_bash_command_Opt[_ble_ctx_CMDXE]=1 +_ble_syntax_bash_command_Opt[_ble_ctx_CMDXD0]=1 +_ble_syntax_bash_is_command_form_for= +function ble/syntax:bash/ctx-command/.check-delimiter-or-redirect { + if [[ $tail =~ ^$_ble_syntax_bash_RexIFSs || $wbegin -lt 0 && $tail == $'\\\n'* ]]; then + local spaces=$BASH_REMATCH + if [[ $tail == $'\\\n'* ]]; then + spaces=$'\\\n' + elif [[ $spaces == *$'\n'* ]]; then + ble/syntax:bash/check-here-document-from "$spaces" && return 0 + if ((ctx==_ble_ctx_ARGX||ctx==_ble_ctx_ARGX0||ctx==_ble_ctx_ARGVX||ctx==_ble_ctx_ARGEX||ctx==_ble_ctx_CMDXV||ctx==_ble_ctx_CMDXT||ctx==_ble_ctx_CMDXE)); then + ((ctx=_ble_ctx_CMDX)) + elif ((ctx==_ble_ctx_FARGX2||ctx==_ble_ctx_FARGX3||ctx==_ble_ctx_CMDXD0)); then + ((ctx=_ble_ctx_CMDXD)) + fi + fi + ((_ble_syntax_attr[i]=ctx,i+=${#spaces})) + return 0 + elif [[ $tail =~ ^$_ble_syntax_bash_RexRedirect ]]; then + local len=${#BASH_REMATCH} + local rematch1=${BASH_REMATCH[1]} + local rematch3=${BASH_REMATCH[3]} + ((_ble_syntax_attr[i]=_ble_attr_DEL, + ${#rematch1}&' ]]; then + ble/syntax/parse/nest-push "$_ble_ctx_RDRD2" "$rematch3" + elif [[ $rematch1 == *'&' ]]; then + ble/syntax/parse/nest-push "$_ble_ctx_RDRD" "$rematch3" + elif [[ $rematch1 == *'<<<' ]]; then + ble/syntax/parse/nest-push "$_ble_ctx_RDRS" "$rematch3" + elif [[ $rematch1 == *\<\< ]]; then + ble/syntax/parse/nest-push "$_ble_ctx_RDRH" "$rematch3" + elif [[ $rematch1 == *\<\<- ]]; then + ble/syntax/parse/nest-push "$_ble_ctx_RDRI" "$rematch3" + else + ble/syntax/parse/nest-push "$_ble_ctx_RDRF" "$rematch3" + fi + fi + ((i+=len)) + return 0 + elif local rex='^(&&|\|[|&]?)|^;(;&?|&)|^[;&]' + ((_ble_bash<40000)) && rex='^(&&|\|\|?)|^;(;)|^[;&]' + [[ $tail =~ $rex ]] + then + if [[ $BASH_REMATCH == ';' ]]; then + if ((ctx==_ble_ctx_FARGX2||ctx==_ble_ctx_FARGX3||ctx==_ble_ctx_CMDXD0)); then + ((_ble_syntax_attr[i++]=_ble_attr_DEL,ctx=_ble_ctx_CMDXD)) + return 0 + elif ((ctx==_ble_ctx_CMDXT)); then + ((_ble_syntax_attr[i++]=_ble_attr_DEL,ctx=_ble_bash>=40400?_ble_ctx_CMDX:_ble_ctx_CMDXE)) + return 0 + fi + fi + local rematch1=${BASH_REMATCH[1]} rematch2=${BASH_REMATCH[2]} + ((_ble_syntax_attr[i]=_ble_attr_DEL, + (_ble_syntax_bash_command_Opt[ctx]||ctx==_ble_ctx_CMDX&&${#rematch2})|| + (_ble_syntax_attr[i]=_ble_attr_ERR))) + ((ctx=${#rematch1}?_ble_ctx_CMDX1:( + ${#rematch2}?_ble_ctx_CASE: + _ble_ctx_CMDX))) + ((i+=${#BASH_REMATCH})) + return 0 + elif local rex='^\(\(?' && [[ $tail =~ $rex ]]; then + local m=${BASH_REMATCH[0]} + if ((ctx==_ble_ctx_CMDX||ctx==_ble_ctx_CMDX1||ctx==_ble_ctx_CMDXT||ctx==_ble_ctx_CMDXC)); then + ((_ble_syntax_attr[i]=_ble_attr_DEL)) + ((ctx=${#m}==1?_ble_ctx_CMDXE:_ble_ctx_ARGX0)) + [[ $_ble_syntax_bash_is_command_form_for && $tail == '(('* ]] && ((ctx=_ble_ctx_CMDXD0)) + ble/syntax/parse/nest-push $((${#m}==1?_ble_ctx_CMDX1:_ble_ctx_EXPR)) "$m" + ((i+=${#m})) + else + ble/syntax/parse/nest-push "$_ble_ctx_PATN" + ((_ble_syntax_attr[i++]=_ble_attr_ERR)) + fi + return 0 + elif [[ $tail == ')'* ]]; then + local ntype + ble/syntax/parse/nest-type + local attr= + if [[ $ntype == '(' || $ntype == '$(' || $ntype == '((' || $ntype == '$((' ]]; then + ((attr=_ble_syntax_attr[inest])) + fi + if [[ $attr ]]; then + ((_ble_syntax_attr[i]=(ctx==_ble_ctx_CMDX||ctx==_ble_ctx_CMDXV||ctx==_ble_ctx_CMDXE||ctx==_ble_ctx_ARGX||ctx==_ble_ctx_ARGX0||ctx==_ble_ctx_ARGVX||ctx==_ble_ctx_ARGEX)?attr:_ble_attr_ERR, + i+=1)) + ble/syntax/parse/nest-pop + return 0 + fi + fi + return 1 +} +_ble_syntax_bash_command_BeginCtx=() +_ble_syntax_bash_command_BeginCtx[_ble_ctx_ARGX]=$_ble_ctx_ARGI +_ble_syntax_bash_command_BeginCtx[_ble_ctx_ARGX0]=$_ble_ctx_ARGI +_ble_syntax_bash_command_BeginCtx[_ble_ctx_ARGVX]=$_ble_ctx_ARGVI +_ble_syntax_bash_command_BeginCtx[_ble_ctx_ARGEX]=$_ble_ctx_ARGEI +_ble_syntax_bash_command_BeginCtx[_ble_ctx_CMDX]=$_ble_ctx_CMDI +_ble_syntax_bash_command_BeginCtx[_ble_ctx_CMDX1]=$_ble_ctx_CMDI +_ble_syntax_bash_command_BeginCtx[_ble_ctx_CMDXT]=$_ble_ctx_CMDI +_ble_syntax_bash_command_BeginCtx[_ble_ctx_CMDXC]=$_ble_ctx_CMDI +_ble_syntax_bash_command_BeginCtx[_ble_ctx_CMDXE]=$_ble_ctx_CMDI +_ble_syntax_bash_command_BeginCtx[_ble_ctx_CMDXD]=$_ble_ctx_CMDI +_ble_syntax_bash_command_BeginCtx[_ble_ctx_CMDXD0]=$_ble_ctx_CMDI +_ble_syntax_bash_command_BeginCtx[_ble_ctx_CMDXV]=$_ble_ctx_CMDI +_ble_syntax_bash_command_BeginCtx[_ble_ctx_FARGX1]=$_ble_ctx_FARGI1 +_ble_syntax_bash_command_BeginCtx[_ble_ctx_SARGX1]=$_ble_ctx_FARGI1 +_ble_syntax_bash_command_BeginCtx[_ble_ctx_FARGX2]=$_ble_ctx_FARGI2 +_ble_syntax_bash_command_BeginCtx[_ble_ctx_FARGX3]=$_ble_ctx_FARGI3 +_ble_syntax_bash_command_BeginCtx[_ble_ctx_CARGX1]=$_ble_ctx_CARGI1 +_ble_syntax_bash_command_BeginCtx[_ble_ctx_CARGX2]=$_ble_ctx_CARGI2 +_ble_syntax_bash_command_BeginCtx[_ble_ctx_CPATX]=$_ble_ctx_CPATI +_ble_syntax_bash_command_BeginCtx[_ble_ctx_CPATX0]=$_ble_ctx_CPATI +_ble_syntax_bash_command_BeginCtx[_ble_ctx_TARGX1]=$_ble_ctx_TARGI1 +_ble_syntax_bash_command_BeginCtx[_ble_ctx_TARGX2]=$_ble_ctx_TARGI2 +_ble_syntax_bash_command_BeginCtx[_ble_ctx_COARGX]=$_ble_ctx_COARGI +_ble_syntax_bash_command_isARGI[_ble_ctx_CMDI]=1 +_ble_syntax_bash_command_isARGI[_ble_ctx_VRHS]=1 +_ble_syntax_bash_command_isARGI[_ble_ctx_ARGI]=1 +_ble_syntax_bash_command_isARGI[_ble_ctx_ARGQ]=1 +_ble_syntax_bash_command_isARGI[_ble_ctx_ARGVI]=1 +_ble_syntax_bash_command_isARGI[_ble_ctx_ARGVR]=1 +_ble_syntax_bash_command_isARGI[_ble_ctx_ARGEI]=1 +_ble_syntax_bash_command_isARGI[_ble_ctx_ARGER]=1 +_ble_syntax_bash_command_isARGI[_ble_ctx_FARGI1]=1 # var +_ble_syntax_bash_command_isARGI[_ble_ctx_FARGI2]=1 # in +_ble_syntax_bash_command_isARGI[_ble_ctx_FARGI3]=1 # args... +_ble_syntax_bash_command_isARGI[_ble_ctx_FARGQ3]=1 # args... (= の後) +_ble_syntax_bash_command_isARGI[_ble_ctx_CARGI1]=1 # value +_ble_syntax_bash_command_isARGI[_ble_ctx_CARGQ1]=1 # value (= の後) +_ble_syntax_bash_command_isARGI[_ble_ctx_CARGI2]=1 # in +_ble_syntax_bash_command_isARGI[_ble_ctx_CPATI]=1 # pattern +_ble_syntax_bash_command_isARGI[_ble_ctx_CPATQ]=1 # pattern +_ble_syntax_bash_command_isARGI[_ble_ctx_TARGI1]=1 # -p +_ble_syntax_bash_command_isARGI[_ble_ctx_TARGI2]=1 # -- +_ble_syntax_bash_command_isARGI[_ble_ctx_COARGI]=1 # var (coproc の後) +function ble/syntax:bash/ctx-command/.check-word-begin { + if ((wbegin<0)); then + local octx + ((octx=ctx, + wtype=octx, + ctx=_ble_syntax_bash_command_BeginCtx[ctx])) + ble/util/assert '((ctx!=0))' "invalid ctx=$octx at the beginning of words" || + ((ctx=wtype=_ble_ctx_ARGI)) + ble/syntax/parse/word-push "$wtype" "$i" + ((octx!=_ble_ctx_ARGX0&&octx!=_ble_ctx_CPATX0)); return "$?" # return unexpectedWbegin + fi + ble/util/assert '((_ble_syntax_bash_command_isARGI[ctx]))' "invalid ctx=$ctx in words" + return 0 +} +function ble/syntax:bash/ctx-command { + if ble/syntax:bash/starts-with-delimiter-or-redirect; then + ble/util/assert ' + ((ctx==_ble_ctx_ARGX||ctx==_ble_ctx_ARGX0||ctx==_ble_ctx_ARGVX||ctx==_ble_ctx_ARGEX|| + ctx==_ble_ctx_FARGX2||ctx==_ble_ctx_FARGX3||ctx==_ble_ctx_COARGX|| + ctx==_ble_ctx_CMDX||ctx==_ble_ctx_CMDX1||ctx==_ble_ctx_CMDXT||ctx==_ble_ctx_CMDXC|| + ctx==_ble_ctx_CMDXE||ctx==_ble_ctx_CMDXD||ctx==_ble_ctx_CMDXD0||ctx==_ble_ctx_CMDXV))' "invalid ctx=$ctx @ i=$i" + ble/util/assert '((wbegin<0&&wtype<0))' "invalid word-context (wtype=$wtype wbegin=$wbegin) on non-word char." + ble/syntax:bash/ctx-command/.check-delimiter-or-redirect; return "$?" + fi + ble/syntax:bash/check-comment && return 0 + local unexpectedWbegin=-1 + ble/syntax:bash/ctx-command/.check-word-begin || ((unexpectedWbegin=i)) + local wtype0=$wtype i0=$i + local flagConsume=0 + if ble/syntax:bash/check-variable-assignment; then + flagConsume=1 + elif local rex='^([^'${_ble_syntax_bash_chars[_ble_ctx_ARGI]}']+|\\.)'; [[ $tail =~ $rex ]]; then + local rematch=$BASH_REMATCH + local attr=$ctx + [[ $BASH_REMATCH == '\'? ]] && attr=$_ble_attr_QESC + ((_ble_syntax_attr[i]=attr,i+=${#rematch})) + flagConsume=1 + elif ble/syntax:bash/check-process-subst; then + flagConsume=1 + elif ble/syntax:bash/check-quotes; then + flagConsume=1 + elif ble/syntax:bash/check-dollar; then + flagConsume=1 + elif ble/syntax:bash/check-glob; then + flagConsume=1 + elif ble/syntax:bash/check-brace-expansion; then + flagConsume=1 + elif ble/syntax:bash/check-tilde-expansion; then + flagConsume=1 + elif ble/syntax:bash/starts-with-histchars; then + ble/syntax:bash/check-history-expansion || + ((_ble_syntax_attr[i]=ctx,i++)) + flagConsume=1 + fi + if ((flagConsume)); then + ble/util/assert '((wtype0>=0))' + if ((ctx==_ble_ctx_FARGI1)); then + local rex='^[a-zA-Z_][a-zA-Z_0-9]*$' attr=$_ble_attr_ERR + if ((i0==wbegin)) && [[ ${text:i0:i-i0} =~ $rex ]]; then + local ret; ble/syntax/highlight/vartype "$BASH_REMATCH"; attr=$ret + fi + ((_ble_syntax_attr[i0]=attr)) + fi + [[ ${_ble_syntax_bash_command_Expect[wtype0]} ]] && + ((_ble_syntax_attr[i0]=_ble_attr_ERR)) + if ((unexpectedWbegin>=0)); then + ble/syntax/parse/touch-updated-attr "$unexpectedWbegin" + ((_ble_syntax_attr[unexpectedWbegin]=_ble_attr_ERR)) + fi + return 0 + else + return 1 + fi +} +function ble/syntax:bash/ctx-command-compound-expect { + ble/util/assert '((ctx==_ble_ctx_FARGX1||ctx==_ble_ctx_SARGX1||ctx==_ble_ctx_CARGX1||ctx==_ble_ctx_FARGX2||ctx==_ble_ctx_CARGX2||ctx==_ble_ctx_COARGX))' + local _ble_syntax_bash_is_command_form_for= + if ble/syntax:bash/starts-with-delimiter-or-redirect; then + if ((ctx==_ble_ctx_FARGX2)) && [[ $tail == [$';\n']* ]]; then + ble/syntax:bash/ctx-command + return "$?" + elif ((ctx==_ble_ctx_FARGX1)) && [[ $tail == '(('* ]]; then + ((ctx=_ble_ctx_CMDX1,_ble_syntax_bash_is_command_form_for=1)) + elif [[ $tail == $'\n'* ]]; then + if ((ctx==_ble_ctx_CARGX2)); then + ((_ble_syntax_attr[i++]=_ble_ctx_ARGX)) + else + ((_ble_syntax_attr[i++]=_ble_attr_ERR,ctx=_ble_ctx_ARGX)) + fi + return 0 + elif [[ $tail =~ ^$_ble_syntax_bash_RexSpaces ]]; then + ((_ble_syntax_attr[i]=ctx,i+=${#BASH_REMATCH})) + return 0 + elif ((ctx!=_ble_ctx_COARGX)); then + local i0=$i + ((ctx=_ble_ctx_ARGX)) + ble/syntax:bash/ctx-command/.check-delimiter-or-redirect || ((i++)) + ((_ble_syntax_attr[i0]=_ble_attr_ERR)) + return 0 + fi + fi + local i0=$i + if ble/syntax:bash/check-comment; then + if ((ctx==_ble_ctx_FARGX1||ctx==_ble_ctx_SARGX1||ctx==_ble_ctx_CARGX1||ctx==_ble_ctx_COARGX)); then + ((_ble_syntax_attr[i0]=_ble_attr_ERR)) + fi + return 0 + fi + ble/syntax:bash/ctx-command +} +function ble/syntax:bash/ctx-command-expect/.match-word { + local word=$1 len=${#1} + if [[ $tail == "$word"* ]]; then + ble/syntax/parse/set-lookahead $((len+1)) + if ((${#tail}==len)) || i=$((i+len)) ble/syntax:bash/check-word-end/is-delimiter; then + return 0 + fi + fi + return 1 +} +function ble/syntax:bash/ctx-command-time-expect { + ble/util/assert '((ctx==_ble_ctx_TARGX1||ctx==_ble_ctx_TARGX2))' + if ble/syntax:bash/starts-with-delimiter-or-redirect; then + ble/util/assert '((wbegin<0&&wtype<0))' + if [[ $tail =~ ^$_ble_syntax_bash_RexSpaces ]]; then + ((_ble_syntax_attr[i]=ctx,i+=${#BASH_REMATCH})) + return 0 + else + ((ctx=_ble_ctx_CMDXT)) + ble/syntax:bash/ctx-command/.check-delimiter-or-redirect; return "$?" + fi + fi + if ((ctx==_ble_ctx_TARGX1)); then + ble/syntax:bash/ctx-command-expect/.match-word '-p' || + ((ctx=_ble_bash>=50100?_ble_ctx_TARGX2:_ble_ctx_CMDXT)) + fi + if ((ctx==_ble_ctx_TARGX2)); then + ble/syntax:bash/ctx-command-expect/.match-word '--' || + ((ctx=_ble_ctx_CMDXT)) + fi + ble/syntax:bash/ctx-command +} +function ble/syntax:bash/ctx-command-case-pattern-expect { + ble/util/assert '((ctx==_ble_ctx_CPATX||ctx==_ble_ctx_CPATX0))' + if ble/syntax:bash/starts-with-delimiter-or-redirect; then + local delimiter=$BASH_REMATCH + if [[ $tail =~ ^$_ble_syntax_bash_RexSpaces ]]; then + ((_ble_syntax_attr[i]=ctx,i+=${#BASH_REMATCH})) + elif [[ $tail == '|'* ]]; then + ((_ble_syntax_attr[i++]=ctx==_ble_ctx_CPATX?_ble_attr_ERR:_ble_attr_GLOB,ctx=_ble_ctx_CPATX)) + elif [[ $tail == ')'* ]]; then + ((_ble_syntax_attr[i++]=ctx==_ble_ctx_CPATX?_ble_attr_ERR:_ble_attr_GLOB,ctx=_ble_ctx_CMDX)) + elif [[ $tail == '('* ]]; then + ble/syntax:bash/ctx-command/.check-delimiter-or-redirect + else + ((_ble_syntax_attr[i]=_ble_attr_ERR,i+=${#delimiter})) + fi + return "$?" + fi + local i0=$i + if ble/syntax:bash/check-comment; then + ((_ble_syntax_attr[i0]=_ble_attr_ERR)) + return 0 + fi + ble/syntax:bash/ctx-command +} +_BLE_SYNTAX_FCTX[_ble_ctx_VALX]=ble/syntax:bash/ctx-values +_BLE_SYNTAX_FCTX[_ble_ctx_VALI]=ble/syntax:bash/ctx-values +_BLE_SYNTAX_FEND[_ble_ctx_VALI]=ble/syntax:bash/ctx-values/check-word-end +_BLE_SYNTAX_FCTX[_ble_ctx_VALR]=ble/syntax:bash/ctx-values +_BLE_SYNTAX_FEND[_ble_ctx_VALR]=ble/syntax:bash/ctx-values/check-word-end +_BLE_SYNTAX_FCTX[_ble_ctx_VALQ]=ble/syntax:bash/ctx-values +_BLE_SYNTAX_FEND[_ble_ctx_VALQ]=ble/syntax:bash/ctx-values/check-word-end +function ble/syntax:bash/ctx-values/enter { + local outer_nparam=$nparam + ble/syntax/parse/nest-push "$_ble_ctx_VALX" + nparam=$outer_nparam +} +function ble/syntax:bash/ctx-values/leave { + local inner_nparam=$nparam + ble/syntax/parse/nest-pop + nparam=$inner_nparam +} +function ble/syntax:bash/ctx-values/check-word-end { + ((wbegin<0)) && return 1 + [[ ${text:i:1} == [!"$_ble_term_IFS;|&<>()"] ]] && return 1 + local wbeg=$wbegin wlen=$((i-wbegin)) wend=$i + local word=${text:wbegin:wlen} + ble/syntax/parse/word-pop + ble/util/assert '((ctx==_ble_ctx_VALI||ctx==_ble_ctx_VALR||ctx==_ble_ctx_VALQ))' 'invalid context' + ((ctx=_ble_ctx_VALX)) + return 0 +} +function ble/syntax:bash/ctx-values { + if ble/syntax:bash/starts-with-delimiter; then + ble/util/assert '((ctx==_ble_ctx_VALX))' "invalid ctx=$ctx @ i=$i" + ble/util/assert '((wbegin<0&&wtype<0))' "invalid word-context (wtype=$wtype wbegin=$wbegin) on non-word char." + if [[ $tail =~ ^$_ble_syntax_bash_RexIFSs ]]; then + local spaces=$BASH_REMATCH + ble/syntax:bash/check-here-document-from "$spaces" && return 0 + ((_ble_syntax_attr[i]=ctx,i+=${#spaces})) + return 0 + elif [[ $tail == ')'* ]]; then + ((_ble_syntax_attr[i++]=_ble_attr_DEL)) + ble/syntax:bash/ctx-values/leave + return 0 + elif [[ $type == ';'* ]]; then + ((_ble_syntax_attr[i++]=_ble_attr_ERR)) + return 0 + else + ((_ble_syntax_attr[i++]=_ble_attr_ERR)) + return 0 + fi + fi + if ble/syntax:bash/check-comment; then + return 0 + fi + if ((wbegin<0)); then + ((ctx=_ble_ctx_VALI)) + ble/syntax/parse/word-push "$ctx" "$i" + fi + ble/util/assert '((ctx==_ble_ctx_VALI||ctx==_ble_ctx_VALR||ctx==_ble_ctx_VALQ))' "invalid context ctx=$ctx" + if ble/syntax:bash/check-variable-assignment; then + return 0 + elif ble/syntax:bash/check-plain-with-escape "[^${_ble_syntax_bash_chars[_ble_ctx_ARGI]}]+"; then + return 0 + elif ble/syntax:bash/check-process-subst; then + return 0 + elif ble/syntax:bash/check-quotes; then + return 0 + elif ble/syntax:bash/check-dollar; then + return 0 + elif ble/syntax:bash/check-glob; then + return 0 + elif ble/syntax:bash/check-brace-expansion; then + return 0 + elif ble/syntax:bash/check-tilde-expansion; then + return 0 + elif ble/syntax:bash/starts-with-histchars; then + ble/syntax:bash/check-history-expansion || + ((_ble_syntax_attr[i]=ctx,i++)) + return 0 + fi + return 1 +} +_BLE_SYNTAX_FCTX[_ble_ctx_CONDX]=ble/syntax:bash/ctx-conditions +_BLE_SYNTAX_FCTX[_ble_ctx_CONDI]=ble/syntax:bash/ctx-conditions +_BLE_SYNTAX_FEND[_ble_ctx_CONDI]=ble/syntax:bash/ctx-conditions/check-word-end +_BLE_SYNTAX_FCTX[_ble_ctx_CONDQ]=ble/syntax:bash/ctx-conditions +_BLE_SYNTAX_FEND[_ble_ctx_CONDQ]=ble/syntax:bash/ctx-conditions/check-word-end +function ble/syntax:bash/ctx-conditions/check-word-end { + ((wbegin<0)) && return 1 + [[ ${text:i:1} == [!"$_ble_term_IFS;|&<>()"] ]] && return 1 + local wbeg=$wbegin wlen=$((i-wbegin)) wend=$i + local word=${text:wbegin:wlen} + ble/syntax/parse/word-pop + ble/util/assert '((ctx==_ble_ctx_CONDI||ctx==_ble_ctx_CONDQ))' 'invalid context' + if [[ $word == ']]' ]]; then + ble/syntax/parse/touch-updated-attr "$wbeg" + ((_ble_syntax_attr[wbeg]=_ble_attr_DEL)) + ble/syntax/parse/nest-pop + else + ((ctx=_ble_ctx_CONDX)) + fi + return 0 +} +function ble/syntax:bash/ctx-conditions { + if ble/syntax:bash/starts-with-delimiter; then + ble/util/assert '((ctx==_ble_ctx_CONDX))' "invalid ctx=$ctx @ i=$i" + ble/util/assert '((wbegin<0&&wtype<0))' "invalid word-context (wtype=$wtype wbegin=$wbegin) on non-word char." + if [[ $tail =~ ^$_ble_syntax_bash_RexIFSs ]]; then + ((_ble_syntax_attr[i]=ctx,i+=${#BASH_REMATCH})) + return 0 + else + ((_ble_syntax_attr[i++]=_ble_ctx_CONDI)) + return 0 + fi + fi + ble/syntax:bash/check-comment && return 0 + if ((wbegin<0)); then + ((ctx=_ble_ctx_CONDI)) + ble/syntax/parse/word-push "$ctx" "$i" + fi + ble/util/assert '((ctx==_ble_ctx_CONDI||ctx==_ble_ctx_CONDQ))' "invalid context ctx=$ctx" + if ble/syntax:bash/check-variable-assignment; then + return 0 + elif ble/syntax:bash/check-plain-with-escape "[^${_ble_syntax_bash_chars[_ble_ctx_ARGI]}]+"; then + return 0 + elif ble/syntax:bash/check-process-subst; then + return 0 + elif ble/syntax:bash/check-quotes; then + return 0 + elif ble/syntax:bash/check-dollar; then + return 0 + elif ble/syntax:bash/check-glob; then + return 0 + elif ble/syntax:bash/check-brace-expansion; then + return 0 + elif ble/syntax:bash/check-tilde-expansion; then + return 0 + elif ble/syntax:bash/starts-with-histchars; then + ble/syntax:bash/check-history-expansion || + ((_ble_syntax_attr[i++]=ctx)) + return 0 + else + ((_ble_syntax_attr[i++]=ctx)) + return 0 + fi + return 1 +} +_BLE_SYNTAX_FCTX[_ble_ctx_RDRF]=ble/syntax:bash/ctx-redirect +_BLE_SYNTAX_FCTX[_ble_ctx_RDRD]=ble/syntax:bash/ctx-redirect +_BLE_SYNTAX_FCTX[_ble_ctx_RDRD2]=ble/syntax:bash/ctx-redirect +_BLE_SYNTAX_FCTX[_ble_ctx_RDRS]=ble/syntax:bash/ctx-redirect +_BLE_SYNTAX_FEND[_ble_ctx_RDRF]=ble/syntax:bash/ctx-redirect/check-word-end +_BLE_SYNTAX_FEND[_ble_ctx_RDRD]=ble/syntax:bash/ctx-redirect/check-word-end +_BLE_SYNTAX_FEND[_ble_ctx_RDRD2]=ble/syntax:bash/ctx-redirect/check-word-end +_BLE_SYNTAX_FEND[_ble_ctx_RDRS]=ble/syntax:bash/ctx-redirect/check-word-end +function ble/syntax:bash/ctx-redirect/check-word-begin { + if ((wbegin<0)); then + ble/syntax/parse/word-push "$ctx" "$i" + ble/syntax/parse/touch-updated-word "$i" #■これは不要では? + fi +} +function ble/syntax:bash/ctx-redirect/check-word-end { + ((wbegin<0)) && return 1 + ble/syntax:bash/check-word-end/is-delimiter || return 1 + ble/syntax/parse/word-pop + ble/syntax/parse/nest-pop + ble/util/assert '((!_ble_syntax_bash_command_isARGI[ctx]))' "invalid ctx=$ctx in words" + return 0 +} +function ble/syntax:bash/ctx-redirect { + if ble/syntax:bash/starts-with-delimiter-or-redirect; then + ((_ble_syntax_attr[i++]=_ble_attr_ERR)) + [[ ${tail:1} =~ ^$_ble_syntax_bash_RexSpaces ]] && + ((_ble_syntax_attr[i]=ctx,i+=${#BASH_REMATCH})) + return 0 + fi + if local i0=$i; ble/syntax:bash/check-comment; then + ((_ble_syntax_attr[i0]=_ble_attr_ERR)) + return 0 + fi + ble/syntax:bash/ctx-redirect/check-word-begin + if ble/syntax:bash/check-plain-with-escape "[^${_ble_syntax_bash_chars[_ble_ctx_ARGI]}]+"; then + return 0 + elif ble/syntax:bash/check-process-subst; then + return 0 + elif ble/syntax:bash/check-quotes; then + return 0 + elif ble/syntax:bash/check-dollar; then + return 0 + elif ble/syntax:bash/check-glob; then + return 0 + elif ble/syntax:bash/check-brace-expansion; then + return 0 + elif ble/syntax:bash/check-tilde-expansion; then + return 0 + elif ble/syntax:bash/starts-with-histchars; then + ble/syntax:bash/check-history-expansion || + ((_ble_syntax_attr[i]=ctx,i++)) + return 0 + fi + return 1 +} +_ble_syntax_bash_heredoc_EscSP='\040' +_ble_syntax_bash_heredoc_EscHT='\011' +_ble_syntax_bash_heredoc_EscLF='\012' +_ble_syntax_bash_heredoc_EscFS='\034' +function ble/syntax:bash/ctx-heredoc-word/initialize { + local ret + ble/util/s2c ' ' + ble/util/sprintf _ble_syntax_bash_heredoc_EscSP '\\%03o' "$ret" + ble/util/s2c $'\t' + ble/util/sprintf _ble_syntax_bash_heredoc_EscHT '\\%03o' "$ret" + ble/util/s2c $'\n' + ble/util/sprintf _ble_syntax_bash_heredoc_EscLF '\\%03o' "$ret" + ble/util/s2c "$_ble_term_FS" + ble/util/sprintf _ble_syntax_bash_heredoc_EscFS '\\%03o' "$ret" +} +ble/syntax:bash/ctx-heredoc-word/initialize +function ble/syntax:bash/ctx-heredoc-word/remove-quotes { + local text=$1 result= + local rex='^[^\$"'\'']+|^\$?["'\'']|^\\.?|^.' + while [[ $text && $text =~ $rex ]]; do + local rematch=$BASH_REMATCH + if [[ $rematch == \" || $rematch == \$\" ]]; then + if rex='^\$?"(([^\"]|\\.)*)(\\?$|")'; [[ $text =~ $rex ]]; then + local str=${BASH_REMATCH[1]} + local a b + b='\`' a='`'; str=${str//"$b"/"$a"} + b='\"' a='"'; str=${str//"$b"/"$a"} # WA #D1751 safe + b='\$' a='$'; str=${str//"$b"/"$a"} + b='\\' a='\'; str=${str//"$b"/"$a"} + result=$result$str + text=${text:${#BASH_REMATCH}} + continue + fi + elif [[ $rematch == \' ]]; then + if rex="^('[^']*)'?"; [[ $text =~ $rex ]]; then + builtin eval "result=\$result${BASH_REMATCH[1]}'" + text=${text:${#BASH_REMATCH}} + continue + fi + elif [[ $rematch == \$\' ]]; then + if rex='^(\$'\''([^\'\'']|\\.)*)('\''|\\?$)'; [[ $text =~ $rex ]]; then + builtin eval "result=\$result${BASH_REMATCH[1]}'" + text=${text:${#BASH_REMATCH}} + continue + fi + elif [[ $rematch == \\* ]]; then + result=$result${rematch:1} + text=${text:${#rematch}} + continue + fi + result=$result$rematch + text=${text:${#rematch}} + done + delimiter=$result$text +} +function ble/syntax:bash/ctx-heredoc-word/escape-delimiter { + local ret=$1 + if [[ $ret == *[\\\'$_ble_term_IFS$_ble_term_FS]* ]]; then + local a b fs=$_ble_term_FS + a=\\ ; b='\'$a; ret=${ret//"$a"/"$b"} + a=\' ; b='\'$a; ret=${ret//"$a"/"$b"} + a=' ' ; b=$_ble_syntax_bash_heredoc_EscSP; ret=${ret//"$a"/"$b"} + a=$'\t'; b=$_ble_syntax_bash_heredoc_EscHT; ret=${ret//"$a"/"$b"} + a=$'\n'; b=$_ble_syntax_bash_heredoc_EscLF; ret=${ret//"$a"/"$b"} + a=$fs ; b=$_ble_syntax_bash_heredoc_EscFS; ret=${ret//"$a"/"$b"} + fi + escaped=$ret +} +function ble/syntax:bash/ctx-heredoc-word/unescape-delimiter { + builtin eval "delimiter=\$'$1'" +} +_BLE_SYNTAX_FCTX[_ble_ctx_RDRH]=ble/syntax:bash/ctx-heredoc-word +_BLE_SYNTAX_FEND[_ble_ctx_RDRH]=ble/syntax:bash/ctx-heredoc-word/check-word-end +_BLE_SYNTAX_FCTX[_ble_ctx_RDRI]=ble/syntax:bash/ctx-heredoc-word +_BLE_SYNTAX_FEND[_ble_ctx_RDRI]=ble/syntax:bash/ctx-heredoc-word/check-word-end +function ble/syntax:bash/ctx-heredoc-word/check-word-end { + ((wbegin<0)) && return 1 + ble/syntax:bash/check-word-end/is-delimiter || return 1 + local octx=$ctx word=${text:wbegin:i-wbegin} + ble/syntax/parse/word-pop + ble/syntax/parse/nest-pop + local I + if ((octx==_ble_ctx_RDRI)); then I=I; else I=R; fi + local Q delimiter + if [[ $word == *[\'\"\\]* ]]; then + Q=Q; ble/syntax:bash/ctx-heredoc-word/remove-quotes "$word" + else + Q=H; delimiter=$word + fi + local escaped; ble/syntax:bash/ctx-heredoc-word/escape-delimiter "$delimiter" + nparam=$nparam$_ble_term_FS@$I$Q$escaped + return 0 +} +function ble/syntax:bash/ctx-heredoc-word { + ble/syntax:bash/ctx-redirect +} +_BLE_SYNTAX_FCTX[_ble_ctx_HERE0]=ble/syntax:bash/ctx-heredoc-content +_BLE_SYNTAX_FCTX[_ble_ctx_HERE1]=ble/syntax:bash/ctx-heredoc-content +function ble/syntax:bash/ctx-heredoc-content { + local indented= quoted= delimiter= + ble/syntax:bash/ctx-heredoc-word/unescape-delimiter "${nparam:2}" + [[ ${nparam::1} == I ]] && indented=1 + [[ ${nparam:1:1} == Q ]] && quoted=1 + local rex ht=$'\t' lf=$'\n' + if ((ctx==_ble_ctx_HERE0)); then + rex="^${indented:+$ht*}"$'([^\n]+\n?|\n)' + [[ $tail =~ $rex ]] || return 1 + local line=${BASH_REMATCH%"$lf"} + local rematch1=${BASH_REMATCH[1]} + if [[ ${rematch1%"$lf"} == "$delimiter" ]]; then + local indent + ((indent=${#BASH_REMATCH}-${#rematch1}, + _ble_syntax_attr[i]=_ble_ctx_HERE0, + _ble_syntax_attr[i+indent]=_ble_ctx_RDRH, + i+=${#line})) + ble/syntax/parse/nest-pop + return 0 + fi + fi + if [[ $quoted ]]; then + ble/util/assert '((ctx==_ble_ctx_HERE0))' + ((_ble_syntax_attr[i]=_ble_ctx_HERE0,i+=${#BASH_REMATCH})) + return 0 + else + ((ctx=_ble_ctx_HERE1)) + if rex='^([^$`\'"$lf"']|\\.)+'"$lf"'?|^'"$lf" && [[ $tail =~ $rex ]]; then + ((_ble_syntax_attr[i]=_ble_ctx_HERE0, + i+=${#BASH_REMATCH})) + [[ $BASH_REMATCH == *"$lf" ]] && ((ctx=_ble_ctx_HERE0)) + return 0 + fi + if ble/syntax:bash/check-dollar; then + return 0 + elif [[ $tail == '`'* ]] && ble/syntax:bash/check-quotes; then + return 0 + else + ((_ble_syntax_attr[i]=_ble_ctx_HERE0,i++)) + return 0 + fi + fi +} +function ble/syntax:bash/is-complete { + local iN=${#_ble_syntax_text} + ((iN>0)) && ((_ble_syntax_attr[iN-1]==_ble_attr_ERR)) && return 1 + local stat=${_ble_syntax_stat[iN]} + if [[ $stat ]]; then + ble/string#split-words stat "$stat" + local nlen=${stat[3]}; ((nlen>=0)) && return 1 + local nparam=${stat[6]}; [[ $nparam == none ]] && nparam= + local rex="$_ble_term_FS@([RI][QH][^$_ble_term_FS]*)(.*$)" + [[ $nparam =~ $rex ]] && return 1 + local ctx=${stat[0]} + ((ctx==_ble_ctx_ARGX||ctx==_ble_ctx_ARGX0||ctx==_ble_ctx_ARGVX||ctx==_ble_ctx_ARGEX|| + ctx==_ble_ctx_CMDX||ctx==_ble_ctx_CMDXT||ctx==_ble_ctx_CMDXE||ctx==_ble_ctx_CMDXV|| + ctx==_ble_ctx_TARGX1||ctx==_ble_ctx_TARGX2)) || return 1 + fi + local attrs ret + IFS= builtin eval 'attrs="::${_ble_syntax_attr[*]/%/::}"' # WA #D1570 checked + ble/string#count-string "$attrs" ":$_ble_attr_KEYWORD_BEGIN:"; local nbeg=$ret + ble/string#count-string "$attrs" ":$_ble_attr_KEYWORD_END:"; local nend=$ret + ((nbeg>nend)) && return 1 + return 0 +} +function ble/syntax:bash/find-end-of-array-index { + local beg=$1 end=$2 + ret= + local inest0=$beg nest0 + [[ ${_ble_syntax_nest[inest0]} ]] || return 1 + local q stat1 nlen1 inest1 r= + for ((q=inest0+1;q=limit)); do + [[ $bleopt_syntax_debug ]] && _ble_syntax_stat_shift[shift2_j+shift]=1 + ble/syntax/parse/shift.stat + ble/syntax/parse/shift.nest + ((shift2_j--)) + done +} +function ble/syntax/parse/shift.impl2/.proc1 { + if ((TE_iend0&&wbegin>end0)) && [[ ${wtype//[0-9]} ]]; then + [[ $bleopt_syntax_debug ]] && _ble_syntax_stat_shift[shift2_j+shift]=1 + ble/syntax/parse/shift.stat + ble/syntax/parse/shift.nest + ((shift2_j=wbegin)) # skip + elif ((tchild>=0)); then + ble/syntax/tree-enumerate-children ble/syntax/parse/shift.impl2/.proc1 + fi +} +function ble/syntax/parse/shift.method1 { + local i j + for ((i=i2,j=j2;i<=iN;i++,j++)); do + local shift2_j=$j + ble/syntax/parse/shift.stat + ((j>0)) && ble/syntax/parse/shift.tree + ((i=end0&&(i1+=shift), + i2=_ble_syntax_dend,i2>=end0&&(i2+=shift), + (i1<0||begiN)&&(i2=iN), + j2=i2-shift)) + if ((flagSeekStat)); then + local lookahead='stat[7]' + local -a stat + while ((i1>0)); do + if [[ ${_ble_syntax_stat[--i1]} ]]; then + ble/string#split-words stat "${_ble_syntax_stat[i1]}" + ((i1+lookahead<=beg)) && break + fi + done + fi + ble/util/assert '((0<=i1&&i1<=beg&&end<=i2&&i2<=iN))' "X2 0 <= $i1 <= $beg <= $end <= $i2 <= $iN" +} +function ble/syntax/parse/check-end { + [[ ${_BLE_SYNTAX_FEND[ctx]} ]] && "${_BLE_SYNTAX_FEND[ctx]}" +} +function ble/syntax/parse { + local text=$1 iN=${#1} + local opts=$2 + local beg=${3:-0} end=${4:-$iN} end0=${5:-0} + ((end==beg&&end0==beg&&_ble_syntax_dbeg<0)) && return 0 + local IFS=$_ble_term_IFS + local shift=$((end-end0)) + ble/util/assert \ + '((0<=beg&&beg<=end&&end<=iN&&beg<=end0))' \ + "X1 0 <= beg:$beg <= end:$end <= iN:$iN, beg:$beg <= end0:$end0 (shift=$shift text=$text)" || + ((beg=0,end=iN)) + local i1 i2 j2 + ble/syntax/parse/determine-parse-range + ble/syntax/vanishing-word/register _ble_syntax_tree 0 "$i1" "$j2" 0 "$i2" + ble/syntax/parse/shift + local ctx wbegin wtype inest tchild tprev nparam ilook + if ((i1>0)) && [[ ${_ble_syntax_stat[i1]} ]]; then + local -a stat + ble/string#split-words stat "${_ble_syntax_stat[i1]}" + local wlen=${stat[1]} nlen=${stat[3]} tclen=${stat[4]} tplen=${stat[5]} + ctx=${stat[0]} + wbegin=$((wlen<0?wlen:i1-wlen)) + wtype=${stat[2]} + inest=$((nlen<0?nlen:i1-nlen)) + tchild=$((tclen<0?tclen:i1-tclen)) + tprev=$((tplen<0?tplen:i1-tplen)) + nparam=${stat[6]}; [[ $nparam == none ]] && nparam= + ilook=$((i1+${stat[7]:-1})) + else + ctx=$_ble_ctx_UNSPECIFIED ##!< 現在の解析の文脈 + ble/syntax:"$_ble_syntax_lang"/initialize-ctx # ctx 初期化 + wbegin=-1 ##!< シェル単語内にいる時、シェル単語の開始位置 + wtype=-1 ##!< シェル単語内にいる時、シェル単語の種類 + inest=-1 ##!< 入れ子の時、親の開始位置 + tchild=-1 + tprev=-1 + nparam= + ilook=1 + fi + local -a _tail_syntax_stat _tail_syntax_tree _tail_syntax_nest _tail_syntax_attr + _tail_syntax_stat=("${_ble_syntax_stat[@]:j2:iN-i2+1}") + _tail_syntax_tree=("${_ble_syntax_tree[@]:j2:iN-i2}") + _tail_syntax_nest=("${_ble_syntax_nest[@]:j2:iN-i2}") + _tail_syntax_attr=("${_ble_syntax_attr[@]:j2:iN-i2}") + ble/array#reserve-prototype "$iN" + _ble_syntax_stat=("${_ble_syntax_stat[@]::i1}" "${_ble_array_prototype[@]:i1:iN-i1}") # 再開用データ + _ble_syntax_tree=("${_ble_syntax_tree[@]::i1}" "${_ble_array_prototype[@]:i1:iN-i1}") # 単語 + _ble_syntax_nest=("${_ble_syntax_nest[@]::i1}" "${_ble_array_prototype[@]:i1:iN-i1}") # 入れ子の親 + _ble_syntax_attr=("${_ble_syntax_attr[@]::i1}" "${_ble_array_prototype[@]:i1:iN-i1}") # 文脈・色とか + ble/syntax:"$_ble_syntax_lang"/initialize-vars + _ble_syntax_text=$text + local i _stat tail + local debug_p1 + for ((i=i1;i=i2)) && [[ ${_tail_syntax_stat[i-i2]} == "$_stat" ]]; then + if ble/syntax/parse/nest-equals "$inest"; then + _ble_syntax_stat=("${_ble_syntax_stat[@]::i}" "${_tail_syntax_stat[@]:i-i2}") + _ble_syntax_tree=("${_ble_syntax_tree[@]::i}" "${_tail_syntax_tree[@]:i-i2}") + _ble_syntax_nest=("${_ble_syntax_nest[@]::i}" "${_tail_syntax_nest[@]:i-i2}") + _ble_syntax_attr=("${_ble_syntax_attr[@]::i}" "${_tail_syntax_attr[@]:i-i2}") + break + fi + fi + _ble_syntax_stat[i]=$_stat + tail=${text:i} + debug_p1=$i + "${_BLE_SYNTAX_FCTX[ctx]}" || ((_ble_syntax_attr[i]=_ble_attr_ERR,i++)) + ble/syntax/parse/check-end + done + builtin unset -v debug_p1 + ble/syntax/vanishing-word/register _tail_syntax_tree $((-i2)) $((i2+1)) "$i" 0 "$i" + ble/syntax/urange#update _ble_syntax_attr_ "$i1" "$i" + (((i>=i2)?( + _ble_syntax_dbeg=_ble_syntax_dend=-1 + ):( + _ble_syntax_dbeg=i,_ble_syntax_dend=i2))) + if ((i>=iN)); then + ((i=iN)) + ble/syntax/parse/generate-stat + _ble_syntax_stat[i]=$_stat + if ((inest>0)); then + ((_ble_syntax_attr[iN-1]=_ble_attr_ERR)) + while ((inest>=0)); do + ((i=inest)) + ble/syntax/parse/nest-pop + ((inest>=i&&(inest=i-1))) + done + fi + fi + ble/util/assert \ + '((${#_ble_syntax_stat[@]}==iN+1))' \ + "unexpected array length #arr=${#_ble_syntax_stat[@]} (expected to be $iN), #proto=${#_ble_array_prototype[@]} should be >= $iN" +} +function ble/syntax/highlight { + local text=$1 lang=${2:-bash} cache_prefix=$3 + local -a _ble_highlight_layer__list=(plain syntax) + local -a vars=() + ble/array#push vars "${_ble_syntax_VARNAMES[@]}" + ble/array#push vars "${_ble_highlight_layer_plain_VARNAMES[@]}" + ble/array#push vars "${_ble_highlight_layer_syntax_VARNAMES[@]}" + local "${vars[@]/%/=}" # WA #D1570 checked + if [[ $cache_prefix ]] && ((${cache_prefix}_INITIALIZED++)); then + ble/util/restore-vars "$cache_prefix" "${vars[@]}" + ble/string#common-prefix "$_ble_syntax_text" "$text" + local beg=${#ret} + ble/string#common-suffix "${_ble_syntax_text:beg}" "${text:beg}" + local end=$((${#text}-${#ret})) end0=$((${#_ble_syntax_text}-${#ret})) + else + ble/syntax/initialize-vars + ble/highlight/layer:plain/initialize-vars + ble/highlight/layer:syntax/initialize-vars + _ble_syntax_lang=$lang + local beg=0 end=${#text} end0=0 + fi + ble/syntax/parse "$text" '' "$beg" "$end" "$end0" + local HIGHLIGHT_BUFF HIGHLIGHT_UMIN HIGHLIGHT_UMAX + ble/highlight/layer/update "$text" '' "$beg" "$end" "$end0" + IFS= builtin eval "ret=\"\${$HIGHLIGHT_BUFF[*]}\"" + [[ $cache_prefix ]] && + ble/util/save-vars "$cache_prefix" "${vars[@]}" + return 0 +} +function ble/syntax/completion-context/.add { + local source=$1 + local comp1=$2 + ble/util/assert '[[ $source && comp1 -ge 0 ]]' + sources[${#sources[*]}]="$source $comp1" +} +function ble/syntax/completion-context/.check/parameter-expansion { + local rex_paramx='^(\$(\{[!#]?)?)([a-zA-Z_][a-zA-Z_0-9]*)?$' + if [[ ${text:istat:index-istat} =~ $rex_paramx ]]; then + local rematch1=${BASH_REMATCH[1]} + local source=variable + if [[ $rematch1 == '${'* ]]; then + source=variable:b # suffix } + elif ((ctx==_ble_ctx_BRACE1||ctx==_ble_ctx_BRACE2)); then + source=variable:n # no suffix + fi + ble/syntax/completion-context/.add "$source" $((istat+${#rematch1})) + fi +} +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CMDI]=inside-command +function ble/syntax/completion-context/.check-prefix/ctx:inside-command { + if ((wlen>=0)); then + ble/syntax/completion-context/.add command "$wbeg" + if [[ ${text:wbeg:index-wbeg} =~ $rex_param ]]; then + ble/syntax/completion-context/.add variable:= "$wbeg" + fi + fi + ble/syntax/completion-context/.check/parameter-expansion +} +_ble_syntax_bash_complete_check_prefix[_ble_ctx_ARGI]='inside-argument argument' +_ble_syntax_bash_complete_check_prefix[_ble_ctx_ARGQ]='inside-argument argument' +_ble_syntax_bash_complete_check_prefix[_ble_ctx_FARGI1]='inside-argument variable:w' +_ble_syntax_bash_complete_check_prefix[_ble_ctx_FARGI3]='inside-argument argument' +_ble_syntax_bash_complete_check_prefix[_ble_ctx_FARGQ3]='inside-argument argument' +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CARGI1]='inside-argument argument' +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CARGQ1]='inside-argument argument' +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CPATI]='inside-argument argument' +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CPATQ]='inside-argument argument' +_ble_syntax_bash_complete_check_prefix[_ble_ctx_COARGI]='inside-argument variable command' +_ble_syntax_bash_complete_check_prefix[_ble_ctx_VALI]='inside-argument sabbrev file' +_ble_syntax_bash_complete_check_prefix[_ble_ctx_VALQ]='inside-argument sabbrev file' +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CONDI]='inside-argument sabbrev file option' +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CONDQ]='inside-argument sabbrev file' +_ble_syntax_bash_complete_check_prefix[_ble_ctx_ARGVI]='inside-argument sabbrev variable:=' +_ble_syntax_bash_complete_check_prefix[_ble_ctx_ARGEI]='inside-argument command:D variable:= file' +function ble/syntax/completion-context/.check-prefix/ctx:inside-argument { + if ((wlen>=0)); then + local source + for source; do + ble/syntax/completion-context/.add "$source" "$wbeg" + if [[ $source != argument ]]; then + local sub=${text:wbeg:index-wbeg} + if [[ $sub == *[=:]* ]]; then + sub=${sub##*[=:]} + ble/syntax/completion-context/.add "$source" $((index-${#sub})) + fi + fi + done + fi + ble/syntax/completion-context/.check/parameter-expansion +} +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CMDX]=next-command +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CMDX1]=next-command +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CMDXT]=next-command +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CMDXV]=next-command +function ble/syntax/completion-context/.check-prefix/.test-redirection { + local word=$1 + [[ $word =~ ^$_ble_syntax_bash_RexRedirect$ ]] || return 1 + ((ctx==_ble_ctx_CMDXC||ctx==_ble_ctx_CMDXD||ctx==_ble_ctx_CMDXD0||ctx==_ble_ctx_FARGX3)) && return 0 + local rematch3=${BASH_REMATCH[3]} + case $rematch3 in + ('>&') + ble/syntax/completion-context/.add fd "$index" + ble/syntax/completion-context/.add file:no-fd "$index" ;; + (*'&') + ble/syntax/completion-context/.add fd "$index" ;; + ('<<'|'<<-') + ble/syntax/completion-context/.add wordlist:EOF:END:HERE "$index" ;; + ('<<<'|*) + ble/syntax/completion-context/.add file "$index" ;; + esac + return 0 +} +function ble/syntax/completion-context/.check-prefix/ctx:next-command { + local word=${text:istat:index-istat} + if ble/syntax:bash/simple-word/is-simple-or-open-simple "$word"; then + ble/syntax/completion-context/.add command "$istat" + if local rex='^[a-zA-Z_][a-zA-Z_0-9]*(\+?=)?$' && [[ $word =~ $rex ]]; then + if [[ $word == *= ]]; then + if ((_ble_bash>=30100)) || [[ $word != *+= ]]; then + ble/syntax/completion-context/.add argument "$index" + fi + else + ble/syntax/completion-context/.add variable:= "$istat" + fi + fi + elif ble/syntax/completion-context/.check-prefix/.test-redirection; then + true + elif [[ $word =~ ^$_ble_syntax_bash_RexSpaces$ ]]; then + shopt -q no_empty_cmd_completion || + ble/syntax/completion-context/.add command "$index" + fi + ble/syntax/completion-context/.check/parameter-expansion +} +_ble_syntax_bash_complete_check_prefix[_ble_ctx_ARGX]=next-argument +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CARGX1]=next-argument +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CPATX]=next-argument +_ble_syntax_bash_complete_check_prefix[_ble_ctx_FARGX3]=next-argument +_ble_syntax_bash_complete_check_prefix[_ble_ctx_COARGX]=next-argument +_ble_syntax_bash_complete_check_prefix[_ble_ctx_ARGVX]=next-argument +_ble_syntax_bash_complete_check_prefix[_ble_ctx_ARGEX]=next-argument +_ble_syntax_bash_complete_check_prefix[_ble_ctx_VALX]=next-argument +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CONDX]=next-argument +_ble_syntax_bash_complete_check_prefix[_ble_ctx_RDRS]=next-argument +function ble/syntax/completion-context/.check-prefix/ctx:next-argument { + local source + if ((ctx==_ble_ctx_ARGX||ctx==_ble_ctx_CARGX1||ctx==_ble_ctx_FARGX3)); then + source=(argument) + elif ((ctx==_ble_ctx_COARGX)); then + source=(command variable) + elif ((ctx==_ble_ctx_ARGVX)); then + source=(sabbrev variable:= option) + elif ((ctx==_ble_ctx_ARGEX)); then + source=(command:D variable:= file) + elif ((ctx==_ble_ctx_CONDX)); then + source=(sabbrev file option) + else + source=(sabbrev file) + fi + local word=${text:istat:index-istat} + if ble/syntax:bash/simple-word/is-simple-or-open-simple "$word"; then + local src + for src in "${source[@]}"; do + ble/syntax/completion-context/.add "$src" "$istat" + done + if [[ ${source[0]} != argument ]]; then + local rex="^([^='\"\$\\{}]|\\.)*=" + if [[ $word =~ $rex ]]; then + word=${word:${#BASH_REMATCH}} + ble/syntax/completion-context/.add rhs $((index-${#word})) + fi + fi + elif ble/syntax/completion-context/.check-prefix/.test-redirection "$word"; then + true + elif [[ $word =~ ^$_ble_syntax_bash_RexSpaces$ ]]; then + local src + for src in "${source[@]}"; do + ble/syntax/completion-context/.add "$src" "$index" + done + fi + ble/syntax/completion-context/.check/parameter-expansion +} +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CMDXC]=next-compound +function ble/syntax/completion-context/.check-prefix/ctx:next-compound { + local rex word=${text:istat:index-istat} + if [[ ${text:istat:index-istat} =~ $rex_param ]]; then + ble/syntax/completion-context/.add wordlist:-r:'for:select:case:if:while:until' "$istat" + elif rex='^[[({]+$'; [[ $word =~ $rex ]]; then + ble/syntax/completion-context/.add wordlist:-r:'(:{:((:[[' "$istat" + fi +} +_ble_syntax_bash_complete_check_prefix[_ble_ctx_FARGX1]="next-identifier variable:w" # _ble_ctx_FARGX1 → (( でなければ 変数名 +_ble_syntax_bash_complete_check_prefix[_ble_ctx_SARGX1]="next-identifier variable:w" +function ble/syntax/completion-context/.check-prefix/ctx:next-identifier { + local source=$1 word=${text:istat:index-istat} + if [[ $word =~ $rex_param ]]; then + ble/syntax/completion-context/.add "$source" "$istat" + elif [[ $word =~ ^$_ble_syntax_bash_RexSpaces$ ]]; then + ble/syntax/completion-context/.add "$source" "$index" + else + ble/syntax/completion-context/.add none "$istat" + fi +} +_ble_syntax_bash_complete_check_prefix[_ble_ctx_ARGX0]="next-word sabbrev" +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CPATX0]="next-word sabbrev" +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CMDXD0]="next-word wordlist:-rs:';:{:do'" +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CMDXD]="next-word wordlist:-rs:'{:do'" +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CMDXE]="next-word wordlist:-rs:'}:fi:done:esac:then:elif:else:do'" +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CARGX2]="next-word wordlist:-rs:'in'" +_ble_syntax_bash_complete_check_prefix[_ble_ctx_CARGI2]="next-word wordlist:-rs:'in'" +_ble_syntax_bash_complete_check_prefix[_ble_ctx_FARGX2]="next-word wordlist:-rs:'in:do'" +_ble_syntax_bash_complete_check_prefix[_ble_ctx_FARGI2]="next-word wordlist:-rs:'in:do'" +function ble/syntax/completion-context/.check-prefix/ctx:next-word { + local source=$1 word=${text:istat:index-istat} rex=$'^[^ \t]*$' + if [[ $word =~ ^$_ble_syntax_bash_RexSpaces$ ]]; then + ble/syntax/completion-context/.add "$source" "$index" + else + ble/syntax/completion-context/.add "$source" "$istat" + fi +} +_ble_syntax_bash_complete_check_prefix[_ble_ctx_TARGX1]=time-argument +_ble_syntax_bash_complete_check_prefix[_ble_ctx_TARGI1]=time-argument +_ble_syntax_bash_complete_check_prefix[_ble_ctx_TARGX2]=time-argument +_ble_syntax_bash_complete_check_prefix[_ble_ctx_TARGI2]=time-argument +function ble/syntax/completion-context/.check-prefix/ctx:time-argument { + ble/syntax/completion-context/.check/parameter-expansion + ble/syntax/completion-context/.add command "$istat" + if ((ctx==_ble_ctx_TARGX1)); then + local rex='^-p?$' words='-p' + ((_ble_bash>=50100)) && + rex='^-[-p]?$' words='-p':'--' + [[ ${text:istat:index-istat} =~ $rex ]] && + ble/syntax/completion-context/.add wordlist:--:"$words" "$istat" + elif ((ctx==_ble_ctx_TARGX2)); then + local rex='^--?$' + [[ ${text:istat:index-istat} =~ $rex ]] && + ble/syntax/completion-context/.add wordlist:--:'--' "$istat" + fi +} +_ble_syntax_bash_complete_check_prefix[_ble_ctx_QUOT]=quote +function ble/syntax/completion-context/.check-prefix/ctx:quote { + ble/syntax/completion-context/.check/parameter-expansion + ble/syntax/completion-context/.check-prefix/ctx:quote/.check-container-word +} +function ble/syntax/completion-context/.check-prefix/ctx:quote/.check-container-word { + local nlen=${stat[3]}; ((nlen>=0)) || return 1 + local inest=$((nlen<0?nlen:istat-nlen)) + local nest; ble/string#split-words nest "${_ble_syntax_nest[inest]}" + [[ ${nest[0]} ]] || return 1 + local wlen2=${nest[1]}; ((wlen2>=0)) || return 1 + local wbeg2=$((wlen2<0?wlen2:inest-wlen2)) + if ble/syntax:bash/simple-word/is-simple-or-open-simple "${text:wbeg2:index-wbeg2}"; then + local wt=${nest[2]} + [[ ${_ble_syntax_bash_command_EndWtype[wt]} ]] && + wt=${_ble_syntax_bash_command_EndWtype[wt]} + if ((wt==_ble_ctx_CMDI)); then + ble/syntax/completion-context/.add command "$wbeg2" + elif ((wt==_ble_ctx_ARGI||wt==_ble_ctx_ARGVI||wt==_ble_ctx_ARGEI||wt==_ble_ctx_FARGI2||wt==_ble_ctx_CARGI2)); then + ble/syntax/completion-context/.add argument "$wbeg2" + elif ((wt==_ble_ctx_CPATI)); then # case pattern の内部 + return + fi + fi +} +_ble_syntax_bash_complete_check_prefix[_ble_ctx_RDRF]=redirection +_ble_syntax_bash_complete_check_prefix[_ble_ctx_RDRD2]=redirection +_ble_syntax_bash_complete_check_prefix[_ble_ctx_RDRD]=redirection +function ble/syntax/completion-context/.check-prefix/ctx:redirection { + ble/syntax/completion-context/.check/parameter-expansion + local p=$((wlen>=0?wbeg:istat)) + if ble/syntax:bash/simple-word/is-simple-or-open-simple "${text:p:index-p}"; then + if ((ctx==_ble_ctx_RDRF)); then + ble/syntax/completion-context/.add file "$p" + elif ((ctx==_ble_ctx_RDRD)); then + ble/syntax/completion-context/.add fd "$p" + elif ((ctx==_ble_ctx_RDRD2)); then + ble/syntax/completion-context/.add fd "$p" + ble/syntax/completion-context/.add file:no-fd "$p" + fi + fi +} +_ble_syntax_bash_complete_check_prefix[_ble_ctx_RDRH]=here +_ble_syntax_bash_complete_check_prefix[_ble_ctx_RDRI]=here +function ble/syntax/completion-context/.check-prefix/ctx:here { + local p=$((wlen>=0?wbeg:istat)) + ble/syntax/completion-context/.add wordlist:EOF:END:HERE "$p" +} +_ble_syntax_bash_complete_check_prefix[_ble_ctx_VRHS]=rhs +_ble_syntax_bash_complete_check_prefix[_ble_ctx_ARGVR]=rhs +_ble_syntax_bash_complete_check_prefix[_ble_ctx_ARGER]=rhs +_ble_syntax_bash_complete_check_prefix[_ble_ctx_VALR]=rhs +function ble/syntax/completion-context/.check-prefix/ctx:rhs { + ble/syntax/completion-context/.check/parameter-expansion + if ((wlen>=0)); then + local p=$wbeg + local rex='^[a-zA-Z0-9_]+(\+?=|\[)' + ((ctx==_ble_ctx_VALR)) && rex='^(\[)' + if [[ ${text:p:index-p} =~ $rex ]]; then + if [[ ${BASH_REMATCH[1]} == '[' ]]; then + local p1=$((wbeg+${#BASH_REMATCH}-1)) + if local ret; ble/syntax:bash/find-end-of-array-index "$p1" "$index"; then + local p2=$ret + case ${_ble_syntax_text:p2:index-p2} in + (']='*) ((p=p2+2)) ;; + (']+='*) ((p=p2+3)) ;; + (']+') + ble/syntax/completion-context/.add wordlist:-rW:'+=' $((p2+1)) + p= ;; + esac + fi + else + ((p+=${#BASH_REMATCH})) + fi + fi + else + local p=$istat + fi + if [[ $p ]] && ble/syntax:bash/simple-word/is-simple-or-open-simple "${text:p:index-p}"; then + ble/syntax/completion-context/.add rhs "$p" + fi +} +_ble_syntax_bash_complete_check_prefix[_ble_ctx_PARAM]=param +function ble/syntax/completion-context/.check-prefix/ctx:param { + local tail=${text:istat:index-istat} + if [[ $tail == : ]]; then + return 0 + elif [[ $tail == '}'* ]]; then + local nlen=${stat[3]} + local inest=$((nlen<0?nlen:istat-nlen)) + ((0<=inest&&inest=0)) || return 1 + local inest=$((istat-nlen)) + ble/syntax/parse/nest-type # ([in] inest; [out] ntype) + if [[ $ntype == [ad]'[' ]]; then + if [[ $tail == ']' ]]; then + ble/syntax/completion-context/.add wordlist:-rW:'=' $((istat+1)) + elif ((_ble_bash>=30100)) && [[ $tail == ']+' ]]; then + ble/syntax/completion-context/.add wordlist:-rW:'+=' $((istat+1)) + elif [[ $tail == ']=' || _ble_bash -ge 30100 && $tail == ']+=' ]]; then + ble/syntax/completion-context/.add rhs "$index" + fi + fi + fi +} +_ble_syntax_bash_complete_check_prefix[_ble_ctx_BRACE1]=brace +_ble_syntax_bash_complete_check_prefix[_ble_ctx_BRACE2]=brace +function ble/syntax/completion-context/.check-prefix/ctx:brace { + local ctx1=$ctx istat1=$istat nlen1=${stat[3]} + ((nlen1>=0)) || return 1 + local inest1=$((istat1-nlen1)) + while :; do + local nest=${_ble_syntax_nest[inest1]} + [[ $nest ]] || return 1 + ble/string#split-words nest "$nest" + ctx1=${nest[0]} + ((ctx1==_ble_ctx_BRACE1||ctx1==_ble_ctx_BRACE2)) || break + inest1=${nest[3]} + ((inest1>=0)) || return 1 + done + for ((istat1=inest1;1;istat1--)); do + ((istat1>=0)) || return 1 + [[ ${_ble_syntax_stat[istat1]} ]] && break + done + local stat1 + ble/string#split-words stat1 "${_ble_syntax_stat[istat1]}" + local wlen=${stat1[1]} + local wbeg=$((wlen>=0?istat1-wlen:istat1)) + ble/syntax/completion-context/.check/parameter-expansion + ble/syntax/completion-context/.add argument "$wbeg" +} +function ble/syntax/completion-context/.search-last-istat { + local index=$1 istat + for ((istat=index;istat>=0;istat--)); do + if [[ ${_ble_syntax_stat[istat]} ]]; then + ret=$istat + return 0 + fi + done + ret= + return 1 +} +function ble/syntax/completion-context/.check-prefix { + local rex_param='^[a-zA-Z_][a-zA-Z_0-9]*$' + local from=${1:-$((index-1))} + local ret + ble/syntax/completion-context/.search-last-istat "$from" || return 1 + local istat=$ret stat + ble/string#split-words stat "${_ble_syntax_stat[istat]}" + [[ ${stat[0]} ]] || return 1 + local ctx=${stat[0]} wlen=${stat[1]} + local wbeg=$((wlen<0?wlen:istat-wlen)) + local name=${_ble_syntax_bash_complete_check_prefix[ctx]} + if [[ $name ]]; then + builtin eval "ble/syntax/completion-context/.check-prefix/ctx:$name" + fi +} +function ble/syntax/completion-context/.check-here { + ((${#sources[*]})) && return 0 + local -a stat + ble/string#split-words stat "${_ble_syntax_stat[index]}" + if [[ ${stat[0]} ]]; then + local ctx=${stat[0]} + if ((ctx==_ble_ctx_CMDX||ctx==_ble_ctx_CMDXV||ctx==_ble_ctx_CMDX1||ctx==_ble_ctx_CMDXT)); then + if ! shopt -q no_empty_cmd_completion; then + ble/syntax/completion-context/.add command "$index" + ble/syntax/completion-context/.add variable:= "$index" + fi + elif ((ctx==_ble_ctx_CMDXC)); then + ble/syntax/completion-context/.add wordlist:-rs:'(:{:((:[[:for:select:case:if:while:until' "$index" + elif ((ctx==_ble_ctx_CMDXE)); then + ble/syntax/completion-context/.add wordlist:-rs:'}:fi:done:esac:then:elif:else:do' "$index" + elif ((ctx==_ble_ctx_CMDXD0)); then + ble/syntax/completion-context/.add wordlist:-rs:';:{:do' "$index" + elif ((ctx==_ble_ctx_CMDXD)); then + ble/syntax/completion-context/.add wordlist:-rs:'{:do' "$index" + elif ((ctx==_ble_ctx_ARGX0||ctx==_ble_ctx_CPATX0)); then + ble/syntax/completion-context/.add sabbrev "$index" + elif ((ctx==_ble_ctx_ARGX||ctx==_ble_ctx_CARGX1||ctx==_ble_ctx_FARGX3)); then + ble/syntax/completion-context/.add argument "$index" + elif ((ctx==_ble_ctx_FARGX1||ctx==_ble_ctx_SARGX1)); then + ble/syntax/completion-context/.add variable:w "$index" + ble/syntax/completion-context/.add sabbrev "$index" + elif ((ctx==_ble_ctx_ARGVX)); then + ble/syntax/completion-context/.add variable:= "$index" + ble/syntax/completion-context/.add option "$index" + ble/syntax/completion-context/.add sabbrev "$index" + elif ((ctx==_ble_ctx_ARGEX)); then + ble/syntax/completion-context/.add variable:= "$index" + ble/syntax/completion-context/.add command:D "$index" + ble/syntax/completion-context/.add file "$index" + elif ((ctx==_ble_ctx_CARGX2)); then + ble/syntax/completion-context/.add wordlist:-rs:'in' "$index" + elif ((ctx==_ble_ctx_FARGX2)); then + ble/syntax/completion-context/.add wordlist:-rs:'in:do' "$index" + elif ((ctx==_ble_ctx_TARGX1)); then + local words='-p' + ((_ble_bash>=50100)) && words='-p':'--' + ble/syntax/completion-context/.add command "$index" + ble/syntax/completion-context/.add wordlist:--:"$words" "$index" + elif ((ctx==_ble_ctx_TARGX2)); then + ble/syntax/completion-context/.add command "$index" + ble/syntax/completion-context/.add wordlist:--:'--' "$index" + elif ((ctx==_ble_ctx_COARGX)); then + ble/syntax/completion-context/.add variable:w "$index" + ble/syntax/completion-context/.add command "$index" + elif ((ctx==_ble_ctx_CONDX)); then + ble/syntax/completion-context/.add sabbrev "$index" + ble/syntax/completion-context/.add option "$index" + ble/syntax/completion-context/.add file "$index" + elif ((ctx==_ble_ctx_CPATI||ctx==_ble_ctx_RDRF||ctx==_ble_ctx_RDRS)); then + ble/syntax/completion-context/.add file "$index" + elif ((ctx==_ble_ctx_RDRD)); then + ble/syntax/completion-context/.add fd "$index" + elif ((ctx==_ble_ctx_RDRD2)); then + ble/syntax/completion-context/.add fd "$index" + ble/syntax/completion-context/.add file:no-fd "$index" + elif ((ctx==_ble_ctx_RDRH||ctx==_ble_ctx_RDRI)); then + ble/syntax/completion-context/.add wordlist:EOF:END:HERE "$index" + elif ((ctx==_ble_ctx_VRHS||ctx==_ble_ctx_ARGVR||ctx==_ble_ctx_ARGER||ctx==_ble_ctx_VALR)); then + ble/syntax/completion-context/.add rhs "$index" + fi + fi +} +function ble/syntax/completion-context/generate { + local text=$1 index=$2 + sources=() + ((index<0&&(index=0))) + ble/syntax/completion-context/.check-prefix + ble/syntax/completion-context/.check-here +} +function ble/syntax:bash/extract-command/.register-word { + local wtxt=${_ble_syntax_text:wbegin:wlen} + if [[ ! $comp_cword ]] && ((wbegin<=EC_pos)); then + if ((EC_pos<=wbegin+wlen)); then + comp_cword=${#comp_words[@]} + comp_point=$((${#comp_line}+wbegin+wlen-EC_pos)) + comp_line="$wtxt$comp_line" + ble/array#push comp_words "$wtxt" + else + comp_cword=${#comp_words[@]} + comp_point=${#comp_line} + comp_line="$wtxt $comp_line" + ble/array#push comp_words "" "$wtxt" + fi + else + comp_line="$wtxt$comp_line" + ble/array#push comp_words "$wtxt" + fi + [[ $EC_opts == *:treeinfo:* ]] && + ble/array#push tree_words "$TE_i:$TE_nofs" +} +function ble/syntax:bash/extract-command/.construct-proc { + if [[ $wtype =~ ^[0-9]+$ ]]; then + if ((wtype==_ble_ctx_CMDI)); then + if ((EC_posnofs0))' "Broken AST: tree-node info missing at $((i0-1))[$nofs0]" || return 1 + local tplen=${node[nofs0+3]} + ((tplen>=0)) || return 1 + local i=$((i0-tplen)) nofs=0 + ret=$i:$nofs + if [[ $opts == *:wvars:* ]]; then + ble/string#split-words node "${_ble_syntax_tree[i-1]}" + ble-assert '((${#node[@]}>nofs))' "Broken AST: tree-node info missing at $((i-1))[$nofs]" || return 1 + wtype=${node[nofs]} + wlen=${node[nofs+1]} + ((wbeg=i-wlen,wend=i)) + wattr=${node[nofs+4]} + fi + return 0 +} +function ble/syntax/tree#next-sibling { + local i0=${1%%:*} nofs0=0 opts=:$2: + [[ $1 == *:* ]] && nofs0=${1#*:} + ((nofs0)) && return 1 + local iN=${#_ble_syntax_text} i nofs node + for ((i=i0+1;i<=iN;i++)); do + [[ ${_ble_syntax_tree[i-1]} ]] || continue + ble/string#split-words node "${_ble_syntax_tree[i-1]}" + nofs=${#node[@]} + while (((nofs-=_ble_syntax_TREE_WIDTH)>=0)); do + if ((i0==i-node[nofs+2])); then + return 1 + elif ((i0==i-node[nofs+3])); then + ret=$i:$nofs + if [[ $opts == *:wvars:* ]]; then + wtype=${node[nofs]} + wlen=${node[nofs+1]} + ((wbeg=i-wlen,wend=i)) + wattr=${node[nofs+4]} + fi + return 0 + fi + done + done + return 1 +} +function ble/syntax:bash/extract-command-by-noderef { + local i=${1%%:*} nofs=0 opts=:$2: + [[ $1 == *:* ]] && nofs=${1#*:} + comp_words=() + tree_words=() + comp_line= + comp_cword=0 + comp_point=0 + local ExprIsArgument='wtype==_ble_ctx_ARGI||wtype==_ble_ctx_ARGVI||wtype==_ble_ctx_ARGEI||wtype==_ble_attr_VAR' + local ret node wtype wlen wbeg wend wattr + ble/string#split-words node "${_ble_syntax_tree[i-1]}" + wtype=${node[nofs]} wlen=${node[nofs+1]} + [[ ! ${wtype//[0-9]} ]] && ((wtype==_ble_ctx_CMDI||ExprIsArgument)) || return 1 + ble/array#push comp_words "${_ble_syntax_text:i-wlen:wlen}" + [[ $opts == *:treeinfo:* ]] && + ble/array#push tree_words "$i:$nofs" + ret=$i:$nofs + while + { [[ ${wtype//[0-9]} ]] || ((wtype!=_ble_ctx_CMDI)); } && + ble/syntax/tree#previous-sibling "$ret" wvars + do + [[ ! ${wtype//[0-9]} ]] || continue + if ((wtype==_ble_ctx_CMDI||ExprIsArgument)); then + ble/array#push comp_words "${_ble_syntax_text:wbeg:wlen}" + [[ $opts == *:treeinfo:* ]] && + ble/array#push tree_words "$ret" + fi + done + ble/array#reverse comp_words + [[ $opts == *:treeinfo:* ]] && + ble/array#reverse tree_words + ((comp_cword=${#comp_words[@]}-1)) + ret=$i:$nofs + while ble/syntax/tree#next-sibling "$ret" wvars; do + [[ ! ${wtype//[0-9]} ]] || continue + ((wtype==_ble_ctx_CMDI)) && break + if ((ExprIsArgument)); then + ble/array#push comp_words "${_ble_syntax_text:wbeg:wlen}" + [[ $opts == *:treeinfo:* ]] && + ble/array#push tree_words "$ret" + fi + done + local IFS=$_ble_term_IFS + comp_line="${comp_words[*]}" + local tmp="${comp_words[*]::comp_cword+1}" + comp_point=${#tmp} +} +_ble_syntax_attr2iface=() +function ble/syntax/attr2iface/color_defface.onload { + function ble/syntax/attr2iface/.define { + ((_ble_syntax_attr2iface[$1]=_ble_faces__$2)) + } + ble/syntax/attr2iface/.define _ble_ctx_ARGX syntax_default + ble/syntax/attr2iface/.define _ble_ctx_ARGX0 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_ARGI syntax_default + ble/syntax/attr2iface/.define _ble_ctx_ARGQ syntax_default + ble/syntax/attr2iface/.define _ble_ctx_ARGVX syntax_default + ble/syntax/attr2iface/.define _ble_ctx_ARGVI syntax_default + ble/syntax/attr2iface/.define _ble_ctx_ARGVR syntax_default + ble/syntax/attr2iface/.define _ble_ctx_ARGEX syntax_default + ble/syntax/attr2iface/.define _ble_ctx_ARGEI syntax_default + ble/syntax/attr2iface/.define _ble_ctx_ARGER syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CMDX syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CMDX1 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CMDXT syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CMDXC syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CMDXE syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CMDXD syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CMDXD0 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CMDXV syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CMDI syntax_command + ble/syntax/attr2iface/.define _ble_ctx_VRHS syntax_default + ble/syntax/attr2iface/.define _ble_ctx_QUOT syntax_quoted + ble/syntax/attr2iface/.define _ble_ctx_EXPR syntax_expr + ble/syntax/attr2iface/.define _ble_attr_ERR syntax_error + ble/syntax/attr2iface/.define _ble_attr_VAR syntax_varname + ble/syntax/attr2iface/.define _ble_attr_QDEL syntax_quotation + ble/syntax/attr2iface/.define _ble_attr_QESC syntax_escape + ble/syntax/attr2iface/.define _ble_attr_DEF syntax_default + ble/syntax/attr2iface/.define _ble_attr_DEL syntax_delimiter + ble/syntax/attr2iface/.define _ble_ctx_PARAM syntax_param_expansion + ble/syntax/attr2iface/.define _ble_ctx_PWORD syntax_default + ble/syntax/attr2iface/.define _ble_ctx_PWORDE syntax_error + ble/syntax/attr2iface/.define _ble_ctx_PWORDR syntax_default + ble/syntax/attr2iface/.define _ble_attr_HISTX syntax_history_expansion + ble/syntax/attr2iface/.define _ble_attr_FUNCDEF syntax_function_name + ble/syntax/attr2iface/.define _ble_ctx_VALX syntax_default + ble/syntax/attr2iface/.define _ble_ctx_VALI syntax_default + ble/syntax/attr2iface/.define _ble_ctx_VALR syntax_default + ble/syntax/attr2iface/.define _ble_ctx_VALQ syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CONDX syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CONDI syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CONDQ syntax_default + ble/syntax/attr2iface/.define _ble_attr_COMMENT syntax_comment + ble/syntax/attr2iface/.define _ble_ctx_CASE syntax_default + ble/syntax/attr2iface/.define _ble_ctx_PATN syntax_default + ble/syntax/attr2iface/.define _ble_attr_GLOB syntax_glob + ble/syntax/attr2iface/.define _ble_ctx_BRAX syntax_default + ble/syntax/attr2iface/.define _ble_attr_BRACE syntax_brace + ble/syntax/attr2iface/.define _ble_ctx_BRACE1 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_BRACE2 syntax_default + ble/syntax/attr2iface/.define _ble_attr_TILDE syntax_tilde + ble/syntax/attr2iface/.define _ble_ctx_SARGX1 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_FARGX1 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_FARGX2 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_FARGX3 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_FARGI1 syntax_varname + ble/syntax/attr2iface/.define _ble_ctx_FARGI2 command_keyword + ble/syntax/attr2iface/.define _ble_ctx_FARGI3 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_FARGQ3 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CARGX1 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CARGX2 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CARGI1 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CARGQ1 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CARGI2 command_keyword + ble/syntax/attr2iface/.define _ble_ctx_CPATX syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CPATI syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CPATQ syntax_default + ble/syntax/attr2iface/.define _ble_ctx_CPATX0 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_TARGX1 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_TARGX2 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_TARGI1 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_TARGI2 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_COARGX syntax_default + ble/syntax/attr2iface/.define _ble_ctx_COARGI syntax_command + ble/syntax/attr2iface/.define _ble_ctx_RDRF syntax_default + ble/syntax/attr2iface/.define _ble_ctx_RDRD syntax_default + ble/syntax/attr2iface/.define _ble_ctx_RDRD2 syntax_default + ble/syntax/attr2iface/.define _ble_ctx_RDRS syntax_default + ble/syntax/attr2iface/.define _ble_ctx_RDRH syntax_document_begin + ble/syntax/attr2iface/.define _ble_ctx_RDRI syntax_document_begin + ble/syntax/attr2iface/.define _ble_ctx_HERE0 syntax_document + ble/syntax/attr2iface/.define _ble_ctx_HERE1 syntax_document + ble/syntax/attr2iface/.define _ble_attr_CMD_BOLD command_builtin_dot + ble/syntax/attr2iface/.define _ble_attr_CMD_BUILTIN command_builtin + ble/syntax/attr2iface/.define _ble_attr_CMD_ALIAS command_alias + ble/syntax/attr2iface/.define _ble_attr_CMD_FUNCTION command_function + ble/syntax/attr2iface/.define _ble_attr_CMD_FILE command_file + ble/syntax/attr2iface/.define _ble_attr_CMD_JOBS command_jobs + ble/syntax/attr2iface/.define _ble_attr_CMD_DIR command_directory + ble/syntax/attr2iface/.define _ble_attr_KEYWORD command_keyword + ble/syntax/attr2iface/.define _ble_attr_KEYWORD_BEGIN command_keyword + ble/syntax/attr2iface/.define _ble_attr_KEYWORD_END command_keyword + ble/syntax/attr2iface/.define _ble_attr_KEYWORD_MID command_keyword + ble/syntax/attr2iface/.define _ble_attr_FILE_DIR filename_directory + ble/syntax/attr2iface/.define _ble_attr_FILE_STICKY filename_directory_sticky + ble/syntax/attr2iface/.define _ble_attr_FILE_LINK filename_link + ble/syntax/attr2iface/.define _ble_attr_FILE_ORPHAN filename_orphan + ble/syntax/attr2iface/.define _ble_attr_FILE_FILE filename_other + ble/syntax/attr2iface/.define _ble_attr_FILE_SETUID filename_setuid + ble/syntax/attr2iface/.define _ble_attr_FILE_SETGID filename_setgid + ble/syntax/attr2iface/.define _ble_attr_FILE_EXEC filename_executable + ble/syntax/attr2iface/.define _ble_attr_FILE_WARN filename_warning + ble/syntax/attr2iface/.define _ble_attr_FILE_FIFO filename_pipe + ble/syntax/attr2iface/.define _ble_attr_FILE_SOCK filename_socket + ble/syntax/attr2iface/.define _ble_attr_FILE_BLK filename_block + ble/syntax/attr2iface/.define _ble_attr_FILE_CHR filename_character + ble/syntax/attr2iface/.define _ble_attr_FILE_URL filename_url + ble/syntax/attr2iface/.define _ble_attr_VAR_UNSET varname_unset + ble/syntax/attr2iface/.define _ble_attr_VAR_EMPTY varname_empty + ble/syntax/attr2iface/.define _ble_attr_VAR_NUMBER varname_number + ble/syntax/attr2iface/.define _ble_attr_VAR_EXPR varname_expr + ble/syntax/attr2iface/.define _ble_attr_VAR_ARRAY varname_array + ble/syntax/attr2iface/.define _ble_attr_VAR_HASH varname_hash + ble/syntax/attr2iface/.define _ble_attr_VAR_READONLY varname_readonly + ble/syntax/attr2iface/.define _ble_attr_VAR_TRANSFORM varname_transform + ble/syntax/attr2iface/.define _ble_attr_VAR_EXPORT varname_export +} +blehook/eval-after-load color_defface ble/syntax/attr2iface/color_defface.onload +function ble/syntax/highlight/cmdtype1 { + type=$1 + local cmd=$2 + case "$type:$cmd" in + (builtin::|builtin:.) + ((type=_ble_attr_CMD_BOLD)) ;; + (builtin:*) + ((type=_ble_attr_CMD_BUILTIN)) ;; + (alias:*) + ((type=_ble_attr_CMD_ALIAS)) ;; + (function:*) + ((type=_ble_attr_CMD_FUNCTION)) ;; + (file:*) + ((type=_ble_attr_CMD_FILE)) ;; + (keyword:*) + ((type=_ble_attr_KEYWORD)) ;; + (*:%*) + ble/util/joblist.check + if jobs -- "$cmd" &>/dev/null; then + ((type=_ble_attr_CMD_JOBS)) + else + ((type=_ble_attr_ERR)) + fi ;; + (*) + if [[ -d $cmd ]] && shopt -q autocd &>/dev/null; then + ((type=_ble_attr_CMD_DIR)) + else + ((type=_ble_attr_ERR)) + fi ;; + esac +} +function ble/syntax/highlight/cmdtype/.jobs { local LC_ALL=C; jobs; } +ble/function#suppress-stderr ble/syntax/highlight/cmdtype/.jobs +function ble/syntax/highlight/cmdtype/.is-job-name { + ble/util/joblist.check + local value=$1 word=$2 + if [[ $value == '%'* ]] && jobs -- "$value" &>/dev/null; then + return 0 + fi + local quote=\'\"\\\` + if [[ ${auto_resume+set} && $word != *["$quote"]* ]]; then + if [[ $auto_resume == exact ]]; then + local jobs job ret + ble/util/assign-array jobs 'ble/syntax/highlight/cmdtype/.jobs' + for job in "${jobs[@]}"; do + ble/string#trim "${job#*' '}" + ble/string#trim "${ret#*' '}" + [[ $value == "$ret" ]] && return 0 + done + return 1 + elif [[ $auto_resume == substring ]]; then + jobs -- "%?$value" &>/dev/null; return "$?" + else + jobs -- "%$value" &>/dev/null; return "$?" + fi + fi + return 1 +} +function ble/syntax/highlight/cmdtype/.impl { + local cmd=$1 _0=$2 + local cmd_type; ble/util/type cmd_type "$cmd" + ble/syntax/highlight/cmdtype1 "$cmd_type" "$cmd" + if [[ $type == "$_ble_attr_CMD_ALIAS" && $cmd != "$_0" ]]; then + type=$( + builtin unalias "$cmd" + ble/util/type cmd_type "$cmd" + ble/syntax/highlight/cmdtype1 "$cmd_type" "$cmd" + printf %s "$type") + elif ble/syntax/highlight/cmdtype/.is-job-name "$cmd" "$_0"; then + ((type=_ble_attr_CMD_JOBS)) + elif [[ $type == "$_ble_attr_KEYWORD" ]]; then + ble/syntax/highlight/cmdtype1 "${cmd_type[1]}" "$cmd" + fi +} +_ble_syntax_highlight_filetype_version=-1 +function ble/syntax/highlight/cmdtype { + local cmd=$1 _0=$2 + if ((_ble_syntax_highlight_filetype_version!=_ble_edit_LINENO)); then + ble/gdict#clear _ble_syntax_highlight_filetype + ((_ble_syntax_highlight_filetype_version=_ble_edit_LINENO)) + fi + if local ret; ble/gdict#get _ble_syntax_highlight_filetype "$_0"; then + type=$ret + return 0 + fi + ble/syntax/highlight/cmdtype/.impl "$cmd" "$_0" + ble/gdict#set _ble_syntax_highlight_filetype "$_0" "$type" +} +function ble/syntax/highlight/filetype { + type= + local file=$1 + if [[ ( $OSTYPE == cygwin || $OSTYPE == msys ) && $file == //* ]]; then + [[ $file == // ]] && ((type=_ble_attr_FILE_DIR)) + [[ $type ]]; return "$?" + fi + if [[ -h $file ]]; then + if [[ -e $file ]]; then + ((type=_ble_attr_FILE_LINK)) + else + ((type=_ble_attr_FILE_ORPHAN)) + fi + elif [[ -e $file ]]; then + if [[ -d $file ]]; then + if [[ -k $file ]]; then + ((type=_ble_attr_FILE_STICKY)) + elif [[ -h ${file%/} ]]; then + ((type=_ble_attr_FILE_LINK)) + else + ((type=_ble_attr_FILE_DIR)) + fi + elif [[ -f $file ]]; then + if [[ -u $file ]]; then + ((type=_ble_attr_FILE_SETUID)) + elif [[ -g $file ]]; then + ((type=_ble_attr_FILE_SETGID)) + elif [[ -x $file ]]; then + ((type=_ble_attr_FILE_EXEC)) + else + ((type=_ble_attr_FILE_FILE)) + fi + elif [[ -c $file ]]; then + ((type=_ble_attr_FILE_CHR)) + elif [[ -p $file ]]; then + ((type=_ble_attr_FILE_FIFO)) + elif [[ -S $file ]]; then + ((type=_ble_attr_FILE_SOCK)) + elif [[ -b $file ]]; then + ((type=_ble_attr_FILE_BLK)) + fi + elif local rex='^https?://[^ ^`"<>\{|}]+$'; [[ $file =~ $rex ]]; then + ((type=_ble_attr_FILE_URL)) + fi + [[ $type ]] +} +function ble/syntax/highlight/ls_colors/.clear { + _ble_syntax_highlight_lscolors=() + ble/gdict#clear _ble_syntax_highlight_lscolors_ext +} +function ble/syntax/highlight/ls_colors/.register-extension { + local key=$1 value=$2 + ble/gdict#set _ble_syntax_highlight_lscolors_ext "$key" "$value" +} +function ble/syntax/highlight/ls_colors/.read-extension { + ble/gdict#get _ble_syntax_highlight_lscolors_ext "$1" +} +function ble/syntax/highlight/ls_colors/.parse { + ble/syntax/highlight/ls_colors/.clear + local fields field + ble/string#split fields : "$1" + for field in "${fields[@]}"; do + [[ $field == *=* ]] || continue + local lhs=${field%%=*} + local ret; ble/color/sgrspec2g "${field#*=}"; local rhs=$ret + case $lhs in + ('di') _ble_syntax_highlight_lscolors[_ble_attr_FILE_DIR]=$rhs ;; + ('st') _ble_syntax_highlight_lscolors[_ble_attr_FILE_STICKY]=$rhs ;; + ('ln') _ble_syntax_highlight_lscolors[_ble_attr_FILE_LINK]=$rhs ;; + ('or') _ble_syntax_highlight_lscolors[_ble_attr_FILE_ORPHAN]=$rhs ;; + ('fi') _ble_syntax_highlight_lscolors[_ble_attr_FILE_FILE]=$rhs ;; + ('su') _ble_syntax_highlight_lscolors[_ble_attr_FILE_SETUID]=$rhs ;; + ('sg') _ble_syntax_highlight_lscolors[_ble_attr_FILE_SETGID]=$rhs ;; + ('ex') _ble_syntax_highlight_lscolors[_ble_attr_FILE_EXEC]=$rhs ;; + ('cd') _ble_syntax_highlight_lscolors[_ble_attr_FILE_CHR]=$rhs ;; + ('pi') _ble_syntax_highlight_lscolors[_ble_attr_FILE_FIFO]=$rhs ;; + ('so') _ble_syntax_highlight_lscolors[_ble_attr_FILE_SOCK]=$rhs ;; + ('bd') _ble_syntax_highlight_lscolors[_ble_attr_FILE_BLK]=$rhs ;; + (\*.*) + ble/syntax/highlight/ls_colors/.register-extension "${lhs:2}" "$rhs" ;; + esac + done +} +function ble/syntax/highlight/ls_colors { + local file=$1 + if ((type==_ble_attr_FILE_FILE)); then + local ext=${file##*/} ret= + while [[ $ext == *.* ]]; do + ext=${ext#*.} + [[ $ext ]] || break + if ble/syntax/highlight/ls_colors/.read-extension "$ext"; then + type=g:$ret + return 0 + fi + done + fi + local g=${_ble_syntax_highlight_lscolors[type]} + if [[ $g ]]; then + type=g:$g + return 0 + fi + return 1 +} +function ble/syntax/highlight/getg-from-filename { + local filename=$1 type= + ble/syntax/highlight/filetype "$filename" + if [[ $bleopt_filename_ls_colors ]]; then + if ble/syntax/highlight/ls_colors "$filename" && [[ $type == g:* ]]; then + local ret; ble/color/face2g filename_ls_colors; g=$ret + ((g|=${type:2})) + return 0 + fi + fi + if [[ $type ]]; then + ble/syntax/attr2g "$type" + else + g= + fi +} +function bleopt/check:filename_ls_colors { + ble/syntax/highlight/ls_colors/.parse "$value" +} +bleopt -I filename_ls_colors +_ble_syntax_progcolor_vars=( + node TE_i TE_nofs wtype wlen wbeg wend wattr) +_ble_syntax_progcolor_wattr_vars=( + wattr_buff wattr_pos wattr_g) +function ble/progcolor/load-word-data { + TE_i=${1%%:*} TE_nofs=${1#*:} + [[ $1 != *:* ]] && TE_nofs=0 + ble/string#split-words node "${_ble_syntax_tree[TE_i-1]}" + wtype=${node[TE_nofs]} + wlen=${node[TE_nofs+1]} + wattr=${node[TE_nofs+4]} + wbeg=$((TE_i-wlen)) + wend=$TE_i +} +function ble/progcolor/set-wattr { + ble/syntax/urange#update color_ "$wbeg" "$wend" + ble/syntax/wrange#update _ble_syntax_word_ "$TE_i" + node[TE_nofs+4]=$1 + local IFS=$_ble_term_IFS + _ble_syntax_tree[TE_i-1]="${node[*]}" +} +function ble/progcolor/eval-word { + local iword=${1:-progcolor_iword} opts=$2 + if [[ ${progcolor_stats[iword]+set} ]]; then + ret=${progcolor_wvals[iword]} + return "${progcolor_stats[iword]}" + fi + local wtxt=${comp_words[iword]} + local simple_flags simple_ibrace + if ! ble/syntax:bash/simple-word/reconstruct-incomplete-word "$wtxt"; then + ret= + progcolor_stats[iword]=2 + progcolor_wvals[iword]= + return 2 + fi + ble/syntax:bash/simple-word/eval "$ret" "$opts"; local ext=$? + ((ext==148)) && return 148 + if ((ext!=0)); then + ret= + progcolor_stats[iword]=1 + progcolor_wvals[iword]= + return 1 + fi + progcolor_stats[iword]=0 + progcolor_wvals[iword]=$ret + return 0 +} +function ble/progcolor/load-cmdspec-opts { + if [[ $progcolor_cmdspec_opts ]]; then + cmdspec_opts=$progcolor_cmdspec_opts + else + ble/cmdspec/opts#load "${comp_words[0]}" + progcolor_cmdspec_opts=${cmdspec_opts:-:} + fi +} +function ble/progcolor/stop-option#init { + rexrej='^--$' rexreq= stopat= + local cmdspec_opts=$1 + if [[ $cmdspec_opts ]]; then + if [[ :$cmdspec_opts: == *:no-options:* ]]; then + stopat=0 + return 1 + elif ble/opts#extract-first-optarg "$cmdspec_opts" stop-options-at && [[ $ret ]]; then + ((stopat=ret)) + return 1 + fi + local ret + if ble/opts#extract-first-optarg "$cmdspec_opts" stop-options-on && [[ $ret ]]; then + rexrej=$ret + elif [[ :$cmdspec_opts: == *:disable-double-hyphen:* ]]; then + rexrej= + fi + if ble/opts#extract-first-optarg "$cmdspec_opts" stop-options-unless && [[ $ret ]]; then + rexreq=$ret + elif [[ :$cmdspec_opts: == *:stop-options-postarg:* ]]; then + rexreq='^-.+' + ble/opts#has "$cmdspec_opts" plus-options && rexreq='^[-+].+' + fi + fi +} +function ble/progcolor/stop-option#test { + [[ $rexrej && $1 =~ $rexrej || $rexreq && ! ( $1 =~ $rexreq ) ]] +} +function ble/progcolor/is-option-context { + if [[ ${progcolor_optctx[1]} ]]; then + ((progcolor_optctx[1]<0?1:(progcolor_iword<=progcolor_optctx[1]))) + return $? + fi + local rexrej rexreq stopat + if [[ ! ${progcolor_optctx[0]} ]]; then + progcolor_optctx[0]=1 + local cmdspec_opts + ble/progcolor/load-cmdspec-opts + ble/progcolor/stop-option#init "$cmdspec_opts" + if [[ ! $rexrej$rexreq ]]; then + progcolor_optctx[1]=${stopat:--1} + ((progcolor_optctx[1]<0?1:(progcolor_iword<=progcolor_optctx[1]))) + return $? + fi + progcolor_optctx[2]=$rexrej + progcolor_optctx[3]=$rexreq + progcolor_optctx[4]=$stopat + else + rexrej=${progcolor_optctx[2]} + rexreq=${progcolor_optctx[3]} + stopat=${progcolor_optctx[4]} + fi + [[ $stopat ]] && ((progcolor_iword>stopat)) && return 1 + local iword + for ((iword=progcolor_optctx[0];iword0)) && ble/array#push wattr_buff "$len:$wattr_g" + wattr_pos=$pos + wattr_g=$g +} +function ble/progcolor/wattr#setattr { + local pos=$1 attr=$2 g + ble/syntax/attr2g "$attr" + ble/progcolor/wattr#setg "$pos" "$g" +} +function ble/progcolor/wattr#finalize { + local wattr + if ((${#wattr_buff[@]})); then + local len=$((wend-wattr_pos)) + ((len>0)) && ble/array#push wattr_buff \$:"$wattr_g" + wattr_pos=$wend + wattr_g=d + IFS=, builtin eval 'wattr="m${wattr_buff[*]}"' + else + wattr=$wattr_g + fi + ble/progcolor/set-wattr "$wattr" +} +function ble/progcolor/highlight-filename/.detect-separated-path { + local word=$1 + ((wtype==_ble_ctx_ARGI||wtype==_ble_ctx_ARGEI||wtype==_ble_ctx_VALI||wtype==_ble_attr_VAR||wtype==_ble_ctx_RDRS)) || return 1 + local detect_opts=url:$highlight_eval_opts + ((wtype==_ble_ctx_RDRS)) && detect_opts=$detect_opts:noglob + [[ $word == '~'* ]] && ((_ble_syntax_attr[p0]!=_ble_attr_TILDE)) && detect_opts=$detect_opts:notilde + ble/syntax:bash/simple-word/detect-separated-path "$word" :, "$detect_opts" +} +function ble/progcolor/highlight-filename/.pathspec.wattr { + local p=$p0 opts=$2 + if [[ :$opts: != *:no-path-color:* ]]; then + local ipath npath=${#path[@]} + for ((ipath=0;ipath' || $redirect_ntype == '>'[\|\&] ) ]]; then + if [[ -e $value || -h $value ]]; then + if [[ -d $value || ! -w $value ]]; then + type=$_ble_attr_ERR + elif [[ ( $redirect_ntype == [\<\&]'>' || $redirect_ntype == '>' || $redirect_ntype == '>&' ) && -f $value ]]; then + if [[ -o noclobber ]]; then + type=$_ble_attr_ERR + else + type=$_ble_attr_FILE_WARN + fi + fi + elif [[ $value == */* && ! -w ${value%/*}/ || $value != */* && ! -w ./ ]]; then + type=$_ble_attr_ERR + fi + elif [[ $redirect_ntype == '<' && ! -r $value ]]; then + type=$_ble_attr_ERR + fi + fi + fi + local g= + if [[ $bleopt_filename_ls_colors ]]; then + if ble/syntax/highlight/ls_colors "$value" && [[ $type == g:* ]]; then + local ret; ble/color/face2g filename_ls_colors; g=$ret + type=g:$((${type:2}|g)) + fi + fi + [[ $type && ! $g ]] && ble/syntax/attr2g "$type" + ble/progcolor/highlight-filename/.pathspec.wattr "${g:-d}" "$highlight_opts" + return 0 +} +function ble/progcolor/highlight-filename/.single.wattr { + local p0=${1%%:*} p1=${1#*:} + local wtxt=${text:p0:p1-p0} + if ((wtype==_ble_ctx_CMDI)) && ble/alias#active "$wtxt"; then + ble/progcolor/wattr#setattr "$p0" "$_ble_attr_CMD_ALIAS" + return 0 + fi + local path_opts=after-sep:$highlight_eval_opts + [[ $wtxt == '~'* ]] && ((_ble_syntax_attr[p0]!=_ble_attr_TILDE)) && path_opts=$path_opts:notilde + ((wtype==_ble_ctx_RDRS||wtype==_ble_attr_VAR||wtype==_ble_ctx_VALI&&wbeg=2)); then + ble/progcolor/wattr#setattr "$p0" "$_ble_attr_ERR" + elif ((wtype==_ble_ctx_CMDI)); then + local attr=${_ble_syntax_attr[wbeg]} + if ((attr!=_ble_attr_KEYWORD&&attr!=_ble_attr_KEYWORD_BEGIN&&attr!=_ble_attr_KEYWORD_END&&attr!=_ble_attr_KEYWORD_MID&&attr!=_ble_attr_DEL)); then + local type=; ble/syntax/highlight/cmdtype "$value" "$wtxt" + if ((type==_ble_attr_CMD_FILE||type==_ble_attr_CMD_FILE||type==_ble_attr_ERR)); then + ble/progcolor/highlight-filename/.pathspec-with-attr.wattr "$type" + elif [[ $type ]]; then + ble/progcolor/wattr#setattr "$p0" "$type" + fi + fi + elif ((wtype==_ble_ctx_RDRD||wtype==_ble_ctx_RDRD2)); then + if local rex='^[0-9]+-?$|^-$'; [[ $value =~ $rex ]]; then + ble/progcolor/wattr#setattr "$p0" "$_ble_attr_DEL" + elif ((wtype==_ble_ctx_RDRD2)); then + ble/progcolor/highlight-filename/.pathspec-by-name.wattr "$value" + else + ble/progcolor/wattr#setattr "$p0" "$_ble_attr_ERR" + fi + elif ((wtype==_ble_ctx_ARGI||wtype==_ble_ctx_ARGEI||wtype==_ble_ctx_VALI||wtype==_ble_attr_VAR||wtype==_ble_ctx_RDRS||wtype==_ble_ctx_RDRF)); then + ble/progcolor/highlight-filename/.pathspec-by-name.wattr "$value" + fi +} +function ble/progcolor/highlight-filename.wattr { + local p0=$1 p1=$2 + if ((p0=2)) || return 1 + local IFS=$_ble_term_IFS + local ins="$*" + comp_line=$ins${comp_line:${#ocmd}} + ((comp_point-=${#ocmd},comp_point<0&&(comp_point=0),comp_point+=${#ins})) + comp_words=("$@" "${comp_words[@]:1}") + ((comp_cword&&(comp_cword+=$#-1))) + ble/array#reserve-prototype $# + tree_words=("${tree_words[0]}" "${_ble_array_prototype[@]::$#-1}" "${tree_words[@]:1}") +} +function ble/progcolor { + local cmd=$1 opts=$2 + local -a progcolor_stats=() + local -a progcolor_wvals=() + local progcolor_cmdspec_opts= + local -a progcolor_optctx=() + local -a alias_args=() + local checked=" " processed= + while :; do + if ble/is-function ble/cmdinfo/cmd:"$cmd"/chroma; then + ble/progcolor/.compline-rewrite-command "$cmd" "${alias_args[@]}" + ble/cmdinfo/cmd:"$cmd"/chroma "$opts" + processed=1 + break + elif [[ $cmd == */?* ]] && ble/is-function ble/cmdinfo/cmd:"${cmd##*/}"/chroma; then + ble/progcolor/.compline-rewrite-command "${cmd##*/}" "${alias_args[@]}" + ble/cmdinfo/cmd:"${cmd##*/}"/chroma "$opts" + processed=1 + break + fi + checked="$checked$cmd " + local ret + ble/alias#expand "$cmd" + ble/string#split-words ret "$ret" + [[ $checked == *" $ret "* ]] && break + cmd=$ret + ((${#ret[@]}>=2)) && + alias_args=("${ret[@]:1}" "${alias_args[@]}") + done + [[ $processed ]] || + ble/progcolor/default + if [[ ${tree_words[0]} ]]; then + local "${_ble_syntax_progcolor_vars[@]/%/=}" # WA #D1570 checked + ble/progcolor/load-word-data "${tree_words[0]}" + [[ $wattr == - ]] && ble/progcolor/word:default + fi +} +function ble/highlight/layer:syntax/touch-range { + ble/syntax/urange#update '' "$@" +} +function ble/highlight/layer:syntax/fill { + local _i _arr=$1 _i1=$2 _i2=$3 _v=$4 + for ((_i=_i1;_i<_i2;_i++)); do + builtin eval "$_arr[_i]=\"\$_v\"" + done +} +_ble_highlight_layer_syntax_VARNAMES=( + _ble_highlight_layer_syntax_buff + _ble_highlight_layer_syntax_active + _ble_highlight_layer_syntax1_table + _ble_highlight_layer_syntax2_table + _ble_highlight_layer_syntax3_list + _ble_highlight_layer_syntax3_table) +function ble/highlight/layer:syntax/initialize-vars { + _ble_highlight_layer_syntax_buff=() + _ble_highlight_layer_syntax1_table=() + _ble_highlight_layer_syntax2_table=() + _ble_highlight_layer_syntax3_list=() + _ble_highlight_layer_syntax3_table=() # errors +} +ble/highlight/layer:syntax/initialize-vars +function ble/highlight/layer:syntax/update-attribute-table { + ble/highlight/layer/update/shift _ble_highlight_layer_syntax1_table + if ((_ble_syntax_attr_umin>=0)); then + ble/highlight/layer:syntax/touch-range _ble_syntax_attr_umin _ble_syntax_attr_umax + local i g=0 + ((_ble_syntax_attr_umin>0)) && + ((g=_ble_highlight_layer_syntax1_table[_ble_syntax_attr_umin-1])) + for ((i=_ble_syntax_attr_umin;i<_ble_syntax_attr_umax;i++)); do + if ((${_ble_syntax_attr[i]})); then + ble/syntax/attr2g "${_ble_syntax_attr[i]}" + fi + _ble_highlight_layer_syntax1_table[i]=$g + done + _ble_syntax_attr_umin=-1 _ble_syntax_attr_umax=-1 + fi +} +function ble/highlight/layer:syntax/word/.update-attributes/.proc { + [[ $wtype =~ ^[0-9]+$ ]] || return 1 + [[ ${node[TE_nofs+4]} == - ]] || return 1 + if ((wtype==_ble_ctx_CMDI||wtype==_ble_ctx_ARGI||wtype==_ble_ctx_ARGVI||wtype==_ble_ctx_ARGEI)); then + local comp_line comp_point comp_words comp_cword tree_words + if ble/syntax:bash/extract-command-by-noderef "$TE_i:$TE_nofs" treeinfo; then + local cmd=${comp_words[0]} + ble/progcolor "$cmd" + return 0 + fi + fi + ble/progcolor/word:default +} +function ble/highlight/layer:syntax/word/.update-attributes { + ((_ble_syntax_word_umin>=0)) || return 1 + if [[ ! $ble_textarea_render_defer_running ]]; then + local _ble_syntax_bash_simple_eval_timeout=$bleopt_highlight_timeout_sync + local _ble_syntax_bash_simple_eval_timeout_carry= + local highlight_eval_opts=cached:single:stopcheck:timeout-carry + else + local _ble_syntax_bash_simple_eval_timeout=$bleopt_highlight_timeout_async + local highlight_eval_opts=cached:single:stopcheck + fi + ble/syntax/tree-enumerate-in-range "$_ble_syntax_word_umin" "$_ble_syntax_word_umax" \ + ble/highlight/layer:syntax/word/.update-attributes/.proc +} +function ble/highlight/layer:syntax/word/.apply-attribute { + local wbeg=$1 wend=$2 wattr=$3 + ((wbegcolor_umax&&(wend=color_umax), + wbegwend&&(j=wend))) + fi + ble/highlight/layer:syntax/word/.apply-attribute "$i" "$j" "$sub_wattr" + (((i=j)=0)) && ble/syntax/tree-enumerate-children "$proc_children" +} +function ble/highlight/layer:syntax/update-word-table { + local color_umin=-1 color_umax=-1 iN=${#_ble_syntax_text} + ble/highlight/layer:syntax/word/.update-attributes + ble/highlight/layer/update/shift _ble_highlight_layer_syntax2_table + ble/syntax/wrange#update _ble_syntax_word_ "$_ble_syntax_vanishing_word_umin" "$_ble_syntax_vanishing_word_umax" + ble/syntax/wrange#update color_ "$_ble_syntax_vanishing_word_umin" "$_ble_syntax_vanishing_word_umax" + _ble_syntax_vanishing_word_umin=-1 _ble_syntax_vanishing_word_umax=-1 + ble/highlight/layer:syntax/word/.apply-attribute 0 "$iN" d # clear word color + local TE_i + for ((TE_i=_ble_syntax_word_umax;TE_i>=_ble_syntax_word_umin;)); do + if ((TE_i>0)) && [[ ${_ble_syntax_tree[TE_i-1]} ]]; then + local -a node + ble/string#split-words node "${_ble_syntax_tree[TE_i-1]}" + local wlen=${node[1]} + local wbeg=$((TE_i-wlen)) wend=$TE_i + if [[ ${node[0]} =~ ^[0-9]+$ ]]; then + local attr=${node[4]} + ble/highlight/layer:syntax/word/.apply-attribute "$wbeg" "$wend" "$attr" + fi + local tclen=${node[2]} + if ((tclen>=0)); then + local tchild=$((TE_i-tclen)) + local tree= TE_nofs=0 proc_children=ble/highlight/layer:syntax/word/.proc-childnode + ble/syntax/tree-enumerate-children "$proc_children" + fi + ((TE_i=wbeg)) + else + ((TE_i--)) + fi + done + ((color_umin>=0)) && ble/highlight/layer:syntax/touch-range "$color_umin" "$color_umax" + _ble_syntax_word_umin=-1 _ble_syntax_word_umax=-1 +} +function ble/highlight/layer:syntax/update-error-table/set { + local i1=$1 i2=$2 g=$3 + if ((i1=DMAX0?(a+=DMAX-DMAX0):(a>=DMIN&&(a=DMIN)), + b>=DMAX0?(b+=DMAX-DMAX0):(b>=DMIN&&(b=DMIN)))) + if ((a0)) && [[ ${_ble_syntax_stat[iN]} ]]; then + local ret; ble/color/face2g syntax_error; local g=$ret + local -a stat + ble/string#split-words stat "${_ble_syntax_stat[iN]}" + local ctx=${stat[0]} nlen=${stat[3]} nparam=${stat[6]} + [[ $nparam == none ]] && nparam= + local i inest + if ((nlen>0)) || [[ $nparam ]]; then + ble/highlight/layer:syntax/update-error-table/set $((iN-1)) "$iN" "$g" + if ((nlen>0)); then + ((inest=iN-nlen)) + while ((inest>=0)); do + local inest2 + for((inest2=inest+1;inest2=i&&(inest=i-1))) + done + fi + fi + if ((ctx==_ble_ctx_CMDX1||ctx==_ble_ctx_CMDXC||ctx==_ble_ctx_FARGX1||ctx==_ble_ctx_SARGX1||ctx==_ble_ctx_FARGX2||ctx==_ble_ctx_CARGX1||ctx==_ble_ctx_CARGX2||ctx==_ble_ctx_COARGX)); then + ble/highlight/layer:syntax/update-error-table/set $((iN-1)) "$iN" "$g" + fi + fi +} +function ble/highlight/layer:syntax/update { + local text=$1 player=$2 + local i iN=${#text} + local umin=-1 umax=-1 + ((DMIN>=0)) && umin=$DMIN umax=$DMAX + if [[ ! $bleopt_highlight_syntax ]]; then + if [[ $_ble_highlight_layer_syntax_active ]]; then + _ble_highlight_layer_syntax_active= + PREV_UMIN=0 PREV_UMAX=${#1} + fi + return + fi + if [[ ! $_ble_highlight_layer_syntax_active ]]; then + _ble_highlight_layer_syntax_active=1 + umin=0 umax=${#text} + fi + if [[ $bleopt_syntax_debug ]]; then + local debug_attr_umin=$_ble_syntax_attr_umin + local debug_attr_uend=$_ble_syntax_attr_umax + fi + ble/cmdspec/initialize # load chroma + ble/highlight/layer:syntax/update-attribute-table + ble/highlight/layer:syntax/update-word-table + ble/highlight/layer:syntax/update-error-table + if ((DMIN>=0)); then + ble/highlight/layer/update/shift _ble_highlight_layer_syntax_buff + if ((DMAX>0)); then + local g sgr ch ret + ble/highlight/layer:syntax/getg "$DMAX" + ble/color/g2sgr "$g"; sgr=$ret + ch=${_ble_highlight_layer_plain_buff[DMAX]} + _ble_highlight_layer_syntax_buff[DMAX]=$sgr$ch + fi + fi + local i j g gprev=0 + if ((umin>0)); then + ble/highlight/layer:syntax/getg $((umin-1)) + gprev=$g + fi + if ((umin>=0)); then + local ret + for ((i=umin;i<=umax;i++)); do + local ch=${_ble_highlight_layer_plain_buff[i]} + ble/highlight/layer:syntax/getg "$i" + [[ $g ]] || ble/highlight/layer/update/getg "$i" + if ((gprev!=g)); then + ble/color/g2sgr "$g" + ch=$ret$ch + ((gprev=g)) + fi + _ble_highlight_layer_syntax_buff[i]=$ch + done + fi + PREV_UMIN=$umin PREV_UMAX=$umax + PREV_BUFF=_ble_highlight_layer_syntax_buff + if [[ $bleopt_syntax_debug ]]; then + local status buff= nl=$'\n' + _ble_syntax_attr_umin=$debug_attr_umin _ble_syntax_attr_umax=$debug_attr_uend ble/syntax/print-status -v status + local -a DRAW_BUFF=() + ble/syntax/print-layer-buffer.draw plain + ble/syntax/print-layer-buffer.draw syntax + ble/syntax/print-layer-buffer.draw disabled + ble/syntax/print-layer-buffer.draw region + ble/syntax/print-layer-buffer.draw overwrite + local ret; ble/canvas/sflush.draw + status=$status$ret + ble/edit/info/show ansi "$status" + fi +} +function ble/highlight/layer:syntax/getg { + [[ ! $bleopt_highlight_syntax ]] && return + local i=$1 + if [[ ${_ble_highlight_layer_syntax3_table[i]} ]]; then + g=${_ble_highlight_layer_syntax3_table[i]} + elif [[ ${_ble_highlight_layer_syntax2_table[i]} ]]; then + g=${_ble_highlight_layer_syntax2_table[i]} + elif [[ ${_ble_highlight_layer_syntax1_table[i]} ]]; then + g=${_ble_highlight_layer_syntax1_table[i]} + fi +} +function ble/highlight/layer:syntax/textarea_render_defer.hook { + ble/syntax/wrange#update _ble_syntax_word_ "$_ble_syntax_word_defer_umin" "$_ble_syntax_word_defer_umax" + _ble_syntax_word_defer_umin=-1 + _ble_syntax_word_defer_umax=-1 +} +blehook textarea_render_defer+=ble/highlight/layer:syntax/textarea_render_defer.hook +function ble/syntax/import { :; } +blehook/invoke syntax_load +ble/function#try ble/textarea#invalidate str +return 0 -- cgit v1.2.3