sistema_progs

Programas para customizar o meu entorno de traballo nos meus equipos persoais
Log | Files | Refs

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 }