vim-airline.sh (17173B)
1 # -*- mode: sh; mode: sh-bash -*- 2 # 3 # airline.vim (https://github.com/vim-airline/vim-airline) の模倣実装 4 # 5 # * "g:airline_mode_map" is partially supported 6 # 7 # Unsupported mappings 8 # 9 # 'ic' : 'INSERT COMPL', 10 # 'ix' : 'INSERT COMPL', 11 # 'multi' : 'MULTI' 12 # 't' : 'TERMINAL' 13 # 14 15 ble-import keymap.vi 16 ble-import prompt-git 17 18 bleopt/declare -n vim_airline_theme dark 19 function bleopt/check:vim_airline_theme { 20 local init=ble/lib/vim-airline/theme:"$value"/initialize 21 if ! ble/is-function "$init"; then 22 local ret 23 if ! ble/util/import/search "airline/$value"; then 24 ble/util/print "ble/lib/vim-airline: theme '$value' not found." >&2 25 return 1 26 fi 27 ble/util/import "$ret" 28 ble/is-function "$init" || return 1 29 fi 30 31 "$init" 32 return 0 33 } 34 35 bleopt/declare -v vim_airline_section_a '\e[1m\q{lib/vim-airline/mode}' 36 bleopt/declare -v vim_airline_section_b '\q{lib/vim-airline/gitstatus}' 37 bleopt/declare -v vim_airline_section_c '\w' 38 bleopt/declare -v vim_airline_section_x 'bash' 39 bleopt/declare -v vim_airline_section_y '$_ble_util_locale_encoding[unix]' 40 bleopt/declare -v vim_airline_section_z ' \q{history-percentile} \e[1m!\q{history-index}/\!\e[22m \q{position}' 41 42 bleopt/declare -v vim_airline_left_sep $'\uE0B0' 43 bleopt/declare -v vim_airline_left_alt_sep $'\uE0B1' 44 bleopt/declare -v vim_airline_right_sep $'\uE0B2' 45 bleopt/declare -v vim_airline_right_alt_sep $'\uE0B3' 46 bleopt/declare -v vim_airline_symbol_branch $'\uE0A0' 47 bleopt/declare -v vim_airline_symbol_dirty $'\u26A1' 48 49 function bleopt/check:vim_airline_left_sep { ble/prompt/unit#clear _ble_prompt_status; } 50 function bleopt/check:vim_airline_left_alt_sep { ble/prompt/unit#clear _ble_prompt_status; } 51 function bleopt/check:vim_airline_right_sep { ble/prompt/unit#clear _ble_prompt_status; } 52 function bleopt/check:vim_airline_right_alt_sep { ble/prompt/unit#clear _ble_prompt_status; } 53 54 builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_lib_vim_airline_mode_map_default}" 55 ble/gdict#set _ble_lib_vim_airline_mode_map_default 'i' 'INSERT' 56 ble/gdict#set _ble_lib_vim_airline_mode_map_default 'n' 'NORMAL' 57 ble/gdict#set _ble_lib_vim_airline_mode_map_default 'in' '(INSERT)' 58 ble/gdict#set _ble_lib_vim_airline_mode_map_default 'o' 'OP PENDING' 59 ble/gdict#set _ble_lib_vim_airline_mode_map_default 'R' 'REPLACE' 60 ble/gdict#set _ble_lib_vim_airline_mode_map_default '' 'V REPLACE' 61 ble/gdict#set _ble_lib_vim_airline_mode_map_default 'v' 'VISUAL' 62 ble/gdict#set _ble_lib_vim_airline_mode_map_default 'V' 'V-LINE' 63 ble/gdict#set _ble_lib_vim_airline_mode_map_default '' 'V-BLOCK' 64 ble/gdict#set _ble_lib_vim_airline_mode_map_default 's' 'SELECT' 65 ble/gdict#set _ble_lib_vim_airline_mode_map_default 'S' 'S-LINE' 66 ble/gdict#set _ble_lib_vim_airline_mode_map_default '' 'S-BLOCK' 67 ble/gdict#set _ble_lib_vim_airline_mode_map_default '?' '------' 68 ble/gdict#set _ble_lib_vim_airline_mode_map_default 'c' 'COMMAND' 69 builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_lib_vim_airline_mode_map_atomic}" 70 ble/gdict#set _ble_lib_vim_airline_mode_map_atomic 'i' 'I' 71 ble/gdict#set _ble_lib_vim_airline_mode_map_atomic 'n' 'N' 72 ble/gdict#set _ble_lib_vim_airline_mode_map_atomic 'R' 'R' 73 ble/gdict#set _ble_lib_vim_airline_mode_map_atomic 'v' 'V' 74 ble/gdict#set _ble_lib_vim_airline_mode_map_atomic 'V' 'V-L' 75 ble/gdict#set _ble_lib_vim_airline_mode_map_atomic '' 'V-B' 76 ble/gdict#set _ble_lib_vim_airline_mode_map_atomic 's' 'S' 77 ble/gdict#set _ble_lib_vim_airline_mode_map_atomic 'S' 'S-L' 78 ble/gdict#set _ble_lib_vim_airline_mode_map_atomic '' 'S-B' 79 ble/gdict#set _ble_lib_vim_airline_mode_map_atomic '?' '--' 80 ble/gdict#set _ble_lib_vim_airline_mode_map_atomic 'c' 'C' 81 builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_lib_vim_airline_mode_map}" 82 ble/gdict#cp _ble_lib_vim_airline_mode_map_default _ble_lib_vim_airline_mode_map 83 84 function ble/lib/vim-airline/initialize-faces { 85 # default (taken from dark.vim insert) 86 ble/color/defface vim_airline_a fg=17,bg=45 87 ble/color/defface vim_airline_b fg=231,bg=27 88 ble/color/defface vim_airline_c fg=231,bg=18 89 ble/color/defface vim_airline_error fg=16,bg=88 # fg=#000000,bg=#990000 90 ble/color/defface vim_airline_term fg=158,bg=234 # fg=#9cffd3,bg=#202020 91 ble/color/defface vim_airline_warning fg=16,bg=166 # fg=#000000,bg=#df5f00 92 93 94 # "abc" spezialized for map is by default mirror of "abc" for 95 # general map (except for _replace) 96 local section map 97 for section in a b c error term warning; do 98 for map in _normal _insert _visual _commandline _inactive; do 99 ble/color/defface "vim_airline_$section$map" ref:"vim_airline_$section" 100 done 101 ble/color/defface "vim_airline_${section}_replace" ref:"vim_airline_${section}_insert" 102 done 103 104 # "zyx" is mirror of "abc" by default 105 local map 106 for map in '' _normal _insert _replace _visual _commandline _inactive; do 107 ble/color/defface "vim_airline_x$map" ref:"vim_airline_c$map" 108 ble/color/defface "vim_airline_y$map" ref:"vim_airline_b$map" 109 ble/color/defface "vim_airline_z$map" ref:"vim_airline_a$map" 110 done 111 112 # "modified" is mirror of unmodified by default 113 local name 114 for name in {a,b,c,x,y,z,error,term,warning}{,_normal,_insert,_replace,_visual,_commandline,_inactive}; do 115 ble/color/defface "vim_airline_${name}_modified" ref:"vim_airline_$name" 116 done 117 } 118 ble/lib/vim-airline/initialize-faces 119 120 function ble/lib/vim-airline/convert-theme/.to-color256 { 121 local R=$((16#${1:1:2})) 122 local G=$((16#${1:3:2})) 123 local B=$((16#${1:5:2})) 124 ble/color/convert-rgb24-to-color256 "$R" "$G" "$B" 125 } 126 function ble/lib/vim-airline/convert-theme/.setface { 127 local gspec= 128 local ret 129 ble/lib/vim-airline/convert-theme/.to-color256 "$2"; local fg=$ret 130 ble/lib/vim-airline/convert-theme/.to-color256 "$3"; local bg=$ret 131 printf 'ble/color/setface vim_airline_%-13s %-13s # %s\n' "$1" "fg=$fg,bg=$bg" "fg=$2,bg=$3" 132 } 133 function ble/lib/vim-airline/convert-theme { 134 local file=$1 135 sed -n 's/let s:airline_\([_a-zA-Z0-9]\{1,\}\)[^[:alnum:]]\{1,\}\(\#[0-9a-fA-F]\{6\}\)[^[:alnum:]]\{1,\}\(\#[0-9a-fA-F]\{6\}\).*/\1 \2 \3/p' "$file" | 136 while ble/bash/read face fg bg; do 137 ble/lib/vim-airline/convert-theme/.setface "$face" "$fg" "$bg" 138 done 139 } 140 141 # themes/dark.vim (default) 142 ble/color/setface vim_airline_a_normal fg=17,bg=190 # fg=#00005f,bg=#dfff00 143 ble/color/setface vim_airline_b_normal fg=231,bg=238 # fg=#ffffff,bg=#444444 144 ble/color/setface vim_airline_c_normal fg=158,bg=234 # fg=#9cffd3,bg=#202020 145 ble/color/setface vim_airline_a_insert fg=17,bg=45 # fg=#00005f,bg=#00dfff 146 ble/color/setface vim_airline_b_insert fg=231,bg=27 # fg=#ffffff,bg=#005fff 147 ble/color/setface vim_airline_c_insert fg=231,bg=18 # fg=#ffffff,bg=#000080 148 ble/color/setface vim_airline_a_visual fg=16,bg=214 # fg=#000000,bg=#ffaf00 149 ble/color/setface vim_airline_b_visual fg=16,bg=202 # fg=#000000,bg=#ff5f00 150 ble/color/setface vim_airline_c_visual fg=231,bg=52 # fg=#ffffff,bg=#5f0000 151 ble/color/setface vim_airline_a_inactive fg=239,bg=234 # fg=#4e4e4e,bg=#1c1c1c 152 ble/color/setface vim_airline_b_inactive fg=239,bg=235 # fg=#4e4e4e,bg=#262626 153 ble/color/setface vim_airline_c_inactive fg=239,bg=236 # fg=#4e4e4e,bg=#303030 154 ble/color/setface vim_airline_a_commandline fg=17,bg=40 # fg=#00005f,bg=#00d700 155 ble/color/setface vim_airline_b_commandline fg=231,bg=238 # fg=#ffffff,bg=#444444 156 ble/color/setface vim_airline_c_commandline fg=158,bg=234 # fg=#9cffd3,bg=#202020 157 158 #------------------------------------------------------------------------------ 159 160 # unit:_ble_lib_vim_airline_mode 161 162 _ble_lib_vim_airline_mode_data=() 163 _ble_lib_vim_airline_keymap= 164 _ble_lib_vim_airline_mode= 165 _ble_lib_vim_airline_rawmode= 166 function ble/prompt/unit:_ble_lib_vim_airline_mode/update { 167 local keymap mode m 168 ble/keymap:vi/script/get-vi-keymap 169 ble/keymap:vi/script/get-mode 170 case $mode in 171 (i*) m='insert' ;; 172 ([R]*) m='replace' ;; 173 (*[vVsS]) m='visual' ;; 174 (*c) m='commandline' ;; 175 (*n) m='normal' ;; 176 (*) m='inactive' ;; 177 esac 178 179 ble/prompt/unit/add-hash '$_ble_edit_str' 180 ble/prompt/unit/add-hash '$_ble_history_INDEX' 181 182 local entry 183 ble/history/get-entry "$_ble_history_INDEX" 184 [[ $_ble_edit_str != "$entry" ]] && m=${m}_modified 185 186 ble/prompt/unit/assign _ble_lib_vim_airline_keymap "$keymap" 187 ble/prompt/unit/assign _ble_lib_vim_airline_mode "$m" 188 ble/prompt/unit/assign _ble_lib_vim_airline_rawmode "$mode" 189 [[ $prompt_unit_changed ]] 190 } 191 192 ## unit:_ble_lib_vim_airline_sep_width 193 ## 分割子の幅を計測してキャッシュします。 194 ## @arr _ble_lib_vim_airline_right_sep_width 195 ## @var _ble_lib_vim_airline_right_sep_width[0] (unit内部使用) version 196 ## @var _ble_lib_vim_airline_right_sep_width[1] (unit内部使用) hashref 197 ## @var _ble_lib_vim_airline_right_sep_width[2] (unit内部使用) hash 198 ## @var _ble_lib_vim_airline_right_sep_width[3] 左sepの幅 199 ## @var _ble_lib_vim_airline_right_sep_width[4] 右sepの幅 200 _ble_lib_vim_airline_sep_width_data=() 201 function ble/prompt/unit:_ble_lib_vim_airline_sep_width/update { 202 ble/prompt/unit/add-hash '$bleopt_char_width_version,$bleopt_char_width_mode' 203 ble/prompt/unit/add-hash '$bleopt_emoji_version,$bleopt_emoji_width,$bleopt_emoji_opts' 204 205 local w ret x y g 206 207 ((x=0,y=0,g=0)) 208 LINES=1 COLUMNS=$cols ble/canvas/trace "$bleopt_vim_airline_left_sep" confine 209 ((w=x,x=0,y=0,g=0)) 210 LINES=1 COLUMNS=$cols ble/canvas/trace "$bleopt_vim_airline_left_alt_sep" confine 211 ((w=x>w?x:w)) 212 ble/prompt/unit/add-hash '$bleopt_vim_airline_left_sep' 213 ble/prompt/unit/add-hash '$bleopt_vim_airline_left_alt_sep' 214 ble/prompt/unit/assign '_ble_lib_vim_airline_sep_width_data[3]' "$w" 215 216 ((x=0,y=0,g=0)) 217 LINES=1 COLUMNS=$cols ble/canvas/trace "$bleopt_vim_airline_right_sep" confine 218 ((w=x,x=0,y=0,g=0)) 219 LINES=1 COLUMNS=$cols ble/canvas/trace "$bleopt_vim_airline_right_alt_sep" confine 220 ((w=x>w?x:w)) 221 ble/prompt/unit/add-hash '$bleopt_vim_airline_right_sep' 222 ble/prompt/unit/add-hash '$bleopt_vim_airline_right_alt_sep' 223 ble/prompt/unit/assign '_ble_lib_vim_airline_sep_width_data[4]' "$w" 224 225 [[ $prompt_unit_changed ]] 226 } 227 228 ## @fn ble/prompt/backslash:lib/vim-airline/mode/.resolve rawmode 229 ## @var[out] ret 230 function ble/prompt/backslash:lib/vim-airline/mode/.resolve { 231 local raw=$1 232 if ble/gdict#has _ble_lib_vim_airline_mode_map "$raw"; then 233 ble/gdict#get _ble_lib_vim_airline_mode_map "$raw" 234 else 235 case $raw in 236 (o) ble/prompt/backslash:lib/vim-airline/mode/.resolve "$_ble_lib_vim_airline_rawmode" ;; 237 ([iR]?*) ble/prompt/backslash:lib/vim-airline/mode/.resolve "${raw::1}" ;; 238 (*?[ncvVsS]) ble/prompt/backslash:lib/vim-airline/mode/.resolve "${raw:${#raw}-1}" ;; 239 () ble/prompt/backslash:lib/vim-airline/mode/.resolve R ;; 240 (R) ble/prompt/backslash:lib/vim-airline/mode/.resolve i ;; 241 ([S]) ble/prompt/backslash:lib/vim-airline/mode/.resolve s ;; 242 ([Vs]) ble/prompt/backslash:lib/vim-airline/mode/.resolve v ;; 243 ([ivnc]) 244 ret= 245 case $_ble_lib_vim_airline_rawmode in 246 (i*) ret=$bleopt_keymap_vi_mode_name_insert ;; 247 (R*) ret=$bleopt_keymap_vi_mode_name_replace ;; 248 (*) ret=$bleopt_keymap_vi_mode_name_vreplace ;; 249 esac 250 [[ $_ble_lib_vim_airline_rawmode == [iR]?* ]] && 251 ble/string#tolower "($insert) " 252 253 case $_ble_lib_vim_airline_rawmode in 254 (*n) 255 if [[ ! $ret ]]; then 256 local rex='[[:alnum:]](.*[[:alnum:]])?' 257 [[ $bleopt_keymap_vi_mode_string_nmap =~ $rex ]] 258 ret=${BASH_REMATCH[0]:-NORMAL} 259 fi ;; 260 (*v) ret="${ret}${ret:+ }$bleopt_keymap_vi_mode_name_visual" ;; 261 (*V) ret="${ret}${ret:+ }$bleopt_keymap_vi_mode_name_visual $bleopt_keymap_vi_mode_name_line" ;; 262 (*) ret="${ret}${ret:+ }$bleopt_keymap_vi_mode_name_visual $bleopt_keymap_vi_mode_name_block" ;; 263 (*s) ret="${ret}${ret:+ }$bleopt_keymap_vi_mode_name_select" ;; 264 (*S) ret="${ret}${ret:+ }$bleopt_keymap_vi_mode_name_select $bleopt_keymap_vi_mode_name_line" ;; 265 (*) ret="${ret}${ret:+ }$bleopt_keymap_vi_mode_name_select $bleopt_keymap_vi_mode_name_block" ;; 266 (*c) ret="${ret}${ret:+ }COMMAND" ;; 267 esac 268 [[ $ret ]] || 269 ble/prompt/backslash:lib/vim-airline/mode/.resolve '?' ;; 270 (*) ret='?__' ;; 271 esac 272 fi 273 } 274 function ble/prompt/backslash:lib/vim-airline/mode { 275 local ret 276 if [[ $_ble_lib_vim_airline_keymap == vi_omap ]]; then 277 ble/prompt/backslash:lib/vim-airline/mode/.resolve o 278 else 279 ble/prompt/backslash:lib/vim-airline/mode/.resolve "$_ble_lib_vim_airline_rawmode" 280 fi 281 [[ $ret ]] && ble/prompt/print "$ret" 282 } 283 function ble/prompt/backslash:lib/vim-airline/gitstatus { 284 local "${_ble_contrib_prompt_git_vars[@]/%/=}" # WA #D1570 checked 285 if ble/contrib/prompt-git/initialize; then 286 ble/contrib/prompt-git/update-head-information 287 if [[ $branch ]]; then 288 ble/prompt/print "$bleopt_vim_airline_symbol_branch$branch" 289 elif [[ $hash ]]; then 290 ble/prompt/print "$bleopt_vim_airline_symbol_branch${hash::7}" 291 else 292 ble/prompt/print '$bleopt_vim_airline_symbol_branch???????' 293 fi 294 ble/contrib/prompt-git/is-dirty && 295 ble/prompt/print "$bleopt_vim_airline_symbol_dirty" 296 fi 297 } 298 299 function ble/prompt/unit:{vim-airline-section}/update { 300 local section=$1 301 local ref_ps=bleopt_vim_airline_section_$section 302 local face=vim_airline_${section}_$_ble_lib_vim_airline_mode 303 local prefix=_ble_lib_vim_airline_section_$section 304 305 ble/prompt/unit/add-hash '$_ble_lib_vim_airline_mode_data' 306 ble/prompt/unit/add-hash "\$$ref_ps" 307 local trace_opts=confine:relative:noscrc:face0="$face":ansi:measure-bbox:measure-gbox 308 local prompt_rows=1 prompt_cols=$cols # Note: cols は \q{lib/vim-airline} で設定される 309 ble/prompt/unit:{section}/update "$prefix" "${!ref_ps}" "$trace_opts" 310 } 311 function ble/prompt/unit:_ble_lib_vim_airline_section_a/update { ble/prompt/unit:{vim-airline-section}/update a; } 312 function ble/prompt/unit:_ble_lib_vim_airline_section_b/update { ble/prompt/unit:{vim-airline-section}/update b; } 313 function ble/prompt/unit:_ble_lib_vim_airline_section_c/update { ble/prompt/unit:{vim-airline-section}/update c; } 314 function ble/prompt/unit:_ble_lib_vim_airline_section_x/update { ble/prompt/unit:{vim-airline-section}/update x; } 315 function ble/prompt/unit:_ble_lib_vim_airline_section_y/update { ble/prompt/unit:{vim-airline-section}/update y; } 316 function ble/prompt/unit:_ble_lib_vim_airline_section_z/update { ble/prompt/unit:{vim-airline-section}/update z; } 317 318 function ble/lib/vim-airline/.print-section { 319 local section=$1 320 local ret g0 bg 321 ble/color/face2g "vim_airline_${section}_$_ble_lib_vim_airline_mode"; g0=$ret 322 ble/color/g#compute-bg "$g0"; bg=$ret 323 324 if [[ $prev_g0 ]]; then 325 local sep=bleopt_vim_airline gsep 326 if [[ $prev_section == [ab] ]]; then 327 sep=${sep}_left 328 else 329 sep=${sep}_right 330 fi 331 if [[ $prev_bg == $bg ]]; then 332 sep=${sep}_alt_sep 333 if [[ $prev_section == [ab] ]]; then 334 gsep=$prev_g0 335 else 336 gsep=$g0 337 fi 338 ((gsep&=~_ble_color_gflags_DecorationMask|_ble_color_gflags_Revert|_ble_color_gflags_Invisible)) 339 else 340 sep=${sep}_sep gsep=0 341 if [[ $sep == *_right_sep ]]; then 342 ble/color/g#setfg gsep "$bg" 343 ble/color/g#setbg gsep "$prev_bg" 344 else 345 ble/color/g#setfg gsep "$prev_bg" 346 ble/color/g#setbg gsep "$bg" 347 fi 348 fi 349 ble/color/g2sgr-ansi "$gsep" 350 ble/prompt/print "$ret${!sep}" 351 fi 352 353 local ref_show=_ble_lib_vim_airline_section_${section}_show 354 if [[ ${!ref_show} ]]; then 355 ble/prompt/unit:{section}/get "_ble_lib_vim_airline_section_$section"; local esc=$ret 356 ble/color/g2sgr-ansi "$g0" 357 ble/prompt/print "$ret $esc$ret " 358 fi 359 [[ $section == c ]] && ble/prompt/print $'\r' 360 361 prev_g0=$g0 362 prev_bg=$bg 363 prev_section=$section 364 } 365 366 function ble/prompt/backslash:lib/vim-airline { 367 local "${_ble_contrib_prompt_git_vars[@]/%/=}" # WA #D1570 checked 368 ble/prompt/unit#update _ble_lib_vim_airline_mode 369 370 ble/prompt/unit#update _ble_lib_vim_airline_sep_width 371 local lwsep=${_ble_lib_vim_airline_sep_width_data[3]:-1} 372 local rwsep=${_ble_lib_vim_airline_sep_width_data[4]:-1} 373 374 # Set background color 375 local ret bg=0 376 ble/color/face2g "vim_airline_c_$_ble_lib_vim_airline_mode" 377 ble/color/g#getbg "$ret" 378 ble/color/g#setbg bg "$ret" 379 ble/color/setface prompt_status_line "g:$bg" 380 381 local cols=$COLUMNS; ((_ble_term_xenl||cols--)) 382 local unit rest_cols=$((cols-2*lwsep-3*rwsep)) 383 for unit in _ble_lib_vim_airline_section_{a,c,z,b,y,x}; do 384 ble/prompt/unit#update "$unit" 385 386 local gx1=${unit}_gbox[0]; gx1=${!gx1} 387 local x2=${unit}_bbox[2]; x2=${!x2} 388 local show= 389 [[ $gx1 ]] && ((x2+2<=rest_cols)) && ((show=1,rest_cols-=x2+2)) 390 builtin eval -- "${unit}_show=\$show" 391 done 392 393 local section prev_section= prev_g0= prev_bg= 394 for section in a b c x y z; do 395 ble/lib/vim-airline/.print-section "$section" 396 done 397 } 398 399 bleopt -I vim_airline_@ 400 bleopt keymap_vi_mode_show= 401 bleopt prompt_status_line='\q{lib/vim-airline}' 402 bleopt prompt_status_align=$'justify=\r'