sample.adapter.bash (12801B)
1 # ble/contrib/layer/sample.adapter.bash (C) 2015, akinomyoga 2 # 3 # The first implementation of ``syntax highlighting'' in ble.sh. 4 # 5 # This file contains a historical implementation of syntax highlighting in 6 # ble.sh. The initial interface was different from the current one (see the 7 # functions ble/syntax-highlight+*). When the new interface is introduced in 8 # commit ec3f3661b (2015-02-23), the `adapter` layer was implemented to bridge 9 # the older implementation of highlighter and the new layer interface. This 10 # served the first implementation of syntax highlighting and later replaced by 11 # a serious implementation based on a real shell parser (ble-syntax.sh, 12 # currently src/core-syntax.sh). After a long time since it was superceded, 13 # the layer definition was moved from the main file `ble-color.sh` to the 14 # archive `archive/layer/adapter.sh` in commit afdcc1598 (2017-03-05 #D0386). 15 # Now, let us move the file to the `contrib` repository and preserve it as a 16 # historical implementation of ``syntax highlighting'' and an illustration of 17 # implementing a layer. 18 # 19 # To try this layer, you can set the following values to the array 20 # `_ble_highlight_layer_list`: 21 # 22 # ```bash 23 # ble-import layer/sample.adapter 24 # _ble_highlight_layer_list=(plain adapter) 25 # ``` 26 # 27 # It should be noted that the behavior related the selected regions seems buggy 28 # within the current layer model. 29 30 ## 31 ## レイヤー ble/highlight/layer:adapter 32 ## 33 ## 古い枠組みに依る色つけのアダプターを 34 ## レイヤーの実装のサンプルとして此処に残す。 35 ## 使う場合は例えば以下の様にする。 36 ## 37 ## _ble_highlight_layer_list=(plain adapter) 38 ## 39 ## 40 41 bleopt/declare -v syntax_highlight_mode default 42 43 _ble_region_highlight_table=() 44 45 ## 古い実装からの adapter 46 _ble_highlight_layer_adapter_buff=() 47 _ble_highlight_layer_adapter_table=() 48 function ble/highlight/layer:adapter/update { 49 local text=$1 player=$2 50 51 # update g table 52 local LAYER_UMIN LAYER_UMAX 53 local -a _ble_region_highlight_table 54 ble/highlight/layer/update/shift _ble_region_highlight_table _ble_highlight_layer_adapter_table 55 if [[ $bleopt_syntax_highlight_mode ]]; then 56 # LAYER_UMIN を設定しない highlight_mode の場合はそのまま。 57 # LAYER_UMIN を設定する highlight_mode の場合は参照せずに上書きされる。 58 LAYER_UMIN=0 LAYER_UMAX=$iN 59 "ble/syntax-highlight+$bleopt_syntax_highlight_mode" "$text" 60 else 61 LAYER_UMIN=$iN LAYER_UMAX=0 62 fi 63 _ble_highlight_layer_adapter_table=("${_ble_region_highlight_table[@]}") 64 65 # 描画文字を更新する範囲 [i1,i2] 66 # text[i2] (更新範囲の次の文字) の SGR に影響を与えない為、 67 # 実際の更新は text[i2] に対しても行う。 68 ((PREV_UMIN>=0&&LAYER_UMIN>PREV_UMIN&&(LAYER_UMIN=PREV_UMIN), 69 PREV_UMAX>=0&&LAYER_UMAX<PREV_UMAX&&(LAYER_UMAX=PREV_UMAX))) 70 local i1=$LAYER_UMIN i2=$LAYER_UMAX 71 ((i2>=iN&&(i2=iN-1))) 72 73 # update char buffer 74 ble/highlight/layer/update/shift _ble_highlight_layer_adapter_buff 75 local i g gprev=0 ctx=0 ret 76 ((i1>0)) && { ble/highlight/layer/getg "$((i1-1))"; gprev=$g; } 77 # ble/edit/info/show text "layer:adapter u = $i1-$i2" 78 for ((i=i1;i<=i2;i++)); do 79 local ch 80 if [[ ${_ble_region_highlight_table[i]} ]]; then 81 ch=${_ble_highlight_layer_plain_buff[i]} 82 ((g=_ble_region_highlight_table[i])) 83 if ((ctx!=0||g!=gprev)); then 84 ((ctx=0,gprev=g)) 85 ble/color/g2sgr "$g" 86 ch=$ret$ch 87 fi 88 else 89 builtin eval "ch=\${$PREV_BUFF[i]}" 90 if ((ctx!=1)); then 91 ((ctx=1,gprev=-1)) 92 ble/highlight/layer/update/getg 93 ble/color/g2sgr "$g" 94 ch=$ret$ch 95 fi 96 fi 97 98 _ble_highlight_layer_adapter_buff[i]=$ch 99 done 100 101 PREV_BUFF=_ble_highlight_layer_adapter_buff 102 if ((LAYER_UMIN<LAYER_UMAX)); then 103 ((PREV_UMIN=LAYER_UMIN,PREV_UMAX=LAYER_UMAX)) 104 else 105 ((PREV_UMIN=-1,PREV_UMAX=-1)) 106 fi 107 } 108 function ble/highlight/layer:adapter/getg { 109 # 描画属性がない時は _ble_region_highlight_table[i] 110 # には空文字列が入っているのでOK 111 g=${_ble_highlight_layer_adapter_table[$1]} 112 } 113 114 115 #------------------------------------------------------------------------------ 116 117 ## @fn _ble_region_highlight_table; ble/syntax-highlight/append triplets ; _ble_region_highlight_table 118 function ble/syntax-highlight/append { 119 while (($#)); do 120 local -a triplet 121 triplet=($1) 122 local ret; ble/color/gspec2g "${triplet[2]}"; local g=$ret 123 local i=${triplet[0]} iN=${triplet[1]} 124 for ((;i<iN;i++)); do 125 _ble_region_highlight_table[$i]=$g 126 done 127 shift 128 done 129 } 130 131 function ble/syntax-highlight+region { 132 if [[ $_ble_edit_mark_active ]]; then 133 if ((_ble_edit_mark>_ble_edit_ind)); then 134 ble/syntax-highlight/append "$_ble_edit_ind $_ble_edit_mark bg=60,fg=white" 135 elif ((_ble_edit_mark<_ble_edit_ind)); then 136 ble/syntax-highlight/append "$_ble_edit_mark $_ble_edit_ind bg=60,fg=white" 137 fi 138 fi 139 } 140 141 function ble/syntax-highlight+test { 142 local text=$1 143 local i iN=${#text} w 144 local mode=cmd 145 for ((i=0;i<iN;)); do 146 local tail=${text:i} rex 147 if [[ $mode == cmd ]]; then 148 if rex='^[_a-zA-Z][_a-zA-Z0-9]*=' && [[ $tail =~ $rex ]]; then 149 # 変数への代入 150 local var=${tail%%=*} 151 ble/syntax-highlight/append "$i $((i+${#var})) fg=orange" 152 ((i+=${#var}+1)) 153 154 mode=rhs 155 elif rex='^[_a-zA-Z][_a-zA-Z0-9]*\[[^]]+\]=' && [[ $tail =~ $rex ]]; then 156 # 配列変数への代入 157 local var="${tail%%\[*}" 158 ble/syntax-highlight/append "$i $((i+${#var})) fg=orange" 159 ((i+=${#var}+1)) 160 161 local tmp="${tail%%\]=*}" 162 local ind="${tmp#*\[}" 163 ble/syntax-highlight/append "$i $((i+${#ind})) fg=green" 164 ((i+=${#var}+1)) 165 166 mode=rhs 167 elif rex='^[^ "'\'']+([ ]|$)' && [[ $tail =~ $rex ]]; then 168 local cmd="${tail%%[ ]*}" cmd_type 169 ble/util/type cmd_type "$cmd" 170 case $cmd_type:$cmd in 171 builtin:*) 172 ble/syntax-highlight/append "$i $((i+${#cmd})) fg=red" ;; 173 alias:*) 174 ble/syntax-highlight/append "$i $((i+${#cmd})) fg=teal" ;; 175 function:*) 176 ble/syntax-highlight/append "$i $((i+${#cmd})) fg=navy" ;; 177 file:*) 178 ble/syntax-highlight/append "$i $((i+${#cmd})) fg=green" ;; 179 keyword:*) 180 ble/syntax-highlight/append "$i $((i+${#cmd})) fg=blue" ;; 181 *) 182 ble/syntax-highlight/append "$i $((i+${#cmd})) bg=224" ;; 183 esac 184 ((i+=${#cmd})) 185 mode=arg 186 else 187 ((i++)) 188 fi 189 else 190 ((i++)) 191 fi 192 done 193 194 ble/syntax-highlight+region "$@" 195 196 # ble/syntax-highlight/append "${#text1} $((${#text1}+1)) standout" 197 } 198 199 function ble/syntax-highlight+default/type { 200 type=$1 201 local cmd=$2 202 case $type:$cmd in 203 (builtin::|builtin:.) 204 # 見にくいので太字にする 205 type=builtin_bold ;; 206 (builtin:*) 207 type=builtin ;; 208 (alias:*) 209 type=alias ;; 210 (function:*) 211 type=function ;; 212 (file:*) 213 type=file ;; 214 (keyword:*) 215 type=keyword ;; 216 (*:%*) 217 # jobs 218 ble/util/joblist.check 219 if jobs "$cmd" &>/dev/null; then 220 type=jobs 221 else 222 type=error 223 fi ;; 224 (*) 225 type=error ;; 226 esac 227 } 228 229 function ble/syntax-highlight+default { 230 local rex IFS=$_ble_term_IFS 231 local text=$1 232 local i iN=${#text} w 233 local mode=cmd 234 for ((i=0;i<iN;)); do 235 local tail=${text:i} 236 if [[ $mode == cmd ]]; then 237 if rex='^([_a-zA-Z][_a-zA-Z0-9]*)\+?=' && [[ $tail =~ $rex ]]; then 238 # for bash-3.1 ${#arr[n]} bug 239 local rematch1="${BASH_REMATCH[1]}" 240 241 # local var="${BASH_REMATCH[0]::-1}" 242 ble/syntax-highlight/append "$i $((i+$rematch1)) fg=orange" 243 ((i+=${#BASH_REMATCH})) 244 mode=rhs 245 continue 246 elif rex='^([^'"$IFS"'|&;()<>'\''"\]|\\.)+' && [[ $tail =~ $rex ]]; then 247 # ■ time'hello' 等の場合に time だけが切り出されてしまう 248 249 local word=${BASH_REMATCH[0]} 250 builtin eval "local cmd=${word}" 251 252 # この部分の判定で fork を沢山する \if 等に対しては 4fork+2exec になる。 253 # ■キャッシュ(accept-line 時に clear)するなどした方が良いかもしれない。 254 local type; ble/util/type type "$cmd" 255 ble/syntax-highlight+default/type "$type" "$cmd" # -> type 256 if [[ $type = alias && $cmd != "$word" ]]; then 257 # alias を \ で無効化している場合 258 # → unalias して再度 check (2fork) 259 type=$( 260 builtin unalias "$cmd" 261 ble/util/type type "$cmd" 262 ble/syntax-highlight+default/type "$type" "$cmd" # -> type 263 ble/util/put "$type") 264 elif [[ "$type" = keyword && "$cmd" != "$word" ]]; then 265 # keyword (time do if function else elif fi の類) を \ で無効化している場合 266 # →file, function, builtin, jobs のどれかになる。以下 3fork+2exec 267 ble/util/joblist.check 268 if [[ ! ${cmd##%*} ]] && jobs "$cmd" &>/dev/null; then 269 # %() { :; } として 関数を定義できるが jobs の方が優先される。 270 # (% という名の関数を呼び出す方法はない?) 271 # でも % で始まる物が keyword になる事はそもそも無いような。 272 type=jobs 273 elif ble/is-function "$cmd"; then 274 type=function 275 elif enable -p | ble/bin/grep -q -F -x "enable $cmd" &>/dev/null; then 276 type=builtin 277 elif which "$cmd" &>/dev/null; then 278 type=file 279 else 280 type=error 281 fi 282 fi 283 284 case $type in 285 (file) 286 ble/syntax-highlight/append "$i $((i+${#word})) fg=green" ;; 287 (alias) 288 ble/syntax-highlight/append "$i $((i+${#word})) fg=teal" ;; 289 (function) 290 ble/syntax-highlight/append "$i $((i+${#word})) fg=navy" ;; 291 (builtin) 292 ble/syntax-highlight/append "$i $((i+${#word})) fg=red" ;; 293 (builtin_bold) 294 ble/syntax-highlight/append "$i $((i+${#word})) fg=red,bold" ;; 295 (keyword) 296 ble/syntax-highlight/append "$i $((i+${#word})) fg=blue" ;; 297 (jobs) 298 ble/syntax-highlight/append "$i $((i+1)) fg=red" ;; 299 (error|*) 300 ble/syntax-highlight/append "$i $((i+${#word})) bg=224" ;; 301 esac 302 303 ((i+=${#BASH_REMATCH})) 304 if rex='^keyword:([!{]|time|do|if|then|else|while|until)$|^builtin:eval$' && [[ $type:$cmd =~ $rex ]]; then 305 mode=cmd 306 else 307 mode=arg 308 fi 309 310 continue 311 fi 312 elif [[ $mode == arg ]]; then 313 if rex='^([^"$'"$IFS"'|&;()<>'\''"`\]|\\.)+' && [[ $tail =~ $rex ]]; then 314 # ■ time'hello' 等の場合に time だけが切り出されてしまう 315 local arg=${BASH_REMATCH[0]} 316 317 local file=$arg 318 [[ ( $file == '~' || $file = '~/'* ) && ! ( -e $file || -h $file ) ]] && file=$HOME${file:1} 319 if [[ -d $file ]]; then 320 ble/syntax-highlight/append "$i $((i+${#arg})) fg=navy,underline" 321 elif [[ -h $file ]]; then 322 ble/syntax-highlight/append "$i $((i+${#arg})) fg=teal,underline" 323 elif [[ -x $file ]]; then 324 ble/syntax-highlight/append "$i $((i+${#arg})) fg=green,underline" 325 elif [[ -f $file ]]; then 326 ble/syntax-highlight/append "$i $((i+${#arg})) underline" 327 fi 328 329 ((i+=${#arg})) 330 continue 331 fi 332 fi 333 334 # /^'([^'])*'|^\$'([^\']|\\.)*'|^`([^\`]|\\.)*`|^\\./ 335 if rex='^'\''([^'\''])*'\''|^\$'\''([^\'\'']|\\.)*'\''|^`([^\`]|\\.)*`|^\\.' && [[ $tail =~ $rex ]]; then 336 ble/syntax-highlight/append "$i $((i+${#BASH_REMATCH})) fg=green" 337 ((i+=${#BASH_REMATCH})) 338 mode=arg_ 339 continue 340 elif rex='^['"$IFS"']+' && [[ $tail =~ $rex ]]; then 341 ((i+=${#BASH_REMATCH})) 342 local spaces=${BASH_REMATCH[0]} 343 if [[ $spaces =~ $'\n' ]]; then 344 mode=cmd 345 else 346 [[ $mode = arg_ ]] && mode=arg 347 fi 348 continue 349 elif rex='^;;?|^;;&$|^&&?|^\|\|?' && [[ $tail =~ $rex ]]; then 350 if [[ $mode = cmd ]]; then 351 ble/syntax-highlight/append "$i $((i+${#BASH_REMATCH})) bg=224" 352 fi 353 ((i+=${#BASH_REMATCH})) 354 mode=cmd 355 continue 356 elif rex='^(&?>>?|<>?|[<>]&)' && [[ $tail =~ $rex ]]; then 357 ble/syntax-highlight/append "$i $((i+${#BASH_REMATCH})) bold" 358 ((i+=${#BASH_REMATCH})) 359 mode=arg 360 continue 361 elif rex='^(' && [[ $tail =~ $rex ]]; then 362 ((i+=${#BASH_REMATCH})) 363 mode=cmd 364 continue 365 fi 366 # 他 "...", ${}, $... arg と共通 367 368 ((i++)) 369 # a[]=... の引数は、${} や "" を考慮に入れるだけでなく [] の数を数える。 370 done 371 372 ble/syntax-highlight+region "$@" 373 }