rainbow.vim (7330B)
1 "============================================================================== 2 "Script Title: rainbow parentheses improved 3 "Script Version: 3.4.1 4 "Author: luochen1990 5 "Last Edited: 2017/04/21 6 "Simple Configuration: 7 " first, put "rainbow.vim"(this file) to dir vimfiles/plugin or vim73/plugin 8 " second, add the follow sentences to your .vimrc or _vimrc : 9 " let g:rainbow_active = 1 10 " third, restart your vim and enjoy coding. 11 "Advanced Configuration: 12 " an advanced configuration allows you to define what parentheses to use 13 " for each type of file . you can also determine the colors of your 14 " parentheses by this way (read file vim73/rgb.txt for all named colors). 15 " READ THE SOURCE FILE FROM LINE 25 TO LINE 50 FOR EXAMPLE. 16 "User Command: 17 " :RainbowToggle --you can use it to toggle this plugin. 18 "============================================================================== 19 20 if exists('s:loaded') || !(exists('g:rainbow_active') || exists('g:rainbow_conf')) 21 finish 22 endif 23 let s:loaded = 1 24 25 let s:rainbow_conf = { 26 \ 'guifgs': ['royalblue3', 'darkorange3', 'seagreen3', 'firebrick'], 27 \ 'ctermfgs': ['lightblue', 'lightyellow', 'lightcyan', 'lightmagenta'], 28 \ 'operators': '_,_', 29 \ 'parentheses': ['start=/(/ end=/)/ fold', 'start=/\[/ end=/\]/ fold', 'start=/{/ end=/}/ fold'], 30 \ 'separately': { 31 \ '*': {}, 32 \ 'lisp': { 33 \ 'guifgs': ['royalblue3', 'darkorange3', 'seagreen3', 'firebrick', 'darkorchid3'], 34 \ }, 35 \ 'tex': { 36 \ 'parentheses': ['start=/(/ end=/)/', 'start=/\[/ end=/\]/'], 37 \ }, 38 \ 'vim': { 39 \ 'parentheses': ['start=/(/ end=/)/', 'start=/\[/ end=/\]/', 'start=/{/ end=/}/ fold', 'start=/(/ end=/)/ containedin=vimFuncBody', 'start=/\[/ end=/\]/ containedin=vimFuncBody', 'start=/{/ end=/}/ fold containedin=vimFuncBody'], 40 \ }, 41 \ 'xml': { 42 \ 'parentheses': ['start=/\v\<\z([-_:a-zA-Z0-9]+)(\s+[-_:a-zA-Z0-9]+(\=("[^"]*"|'."'".'[^'."'".']*'."'".'))?)*\>/ end=#</\z1># fold'], 43 \ }, 44 \ 'xhtml': { 45 \ 'parentheses': ['start=/\v\<\z([-_:a-zA-Z0-9]+)(\s+[-_:a-zA-Z0-9]+(\=("[^"]*"|'."'".'[^'."'".']*'."'".'))?)*\>/ end=#</\z1># fold'], 46 \ }, 47 \ 'html': { 48 \ 'parentheses': ['start=/\v\<((area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)[ >])@!\z([-_:a-zA-Z0-9]+)(\s+[-_:a-zA-Z0-9]+(\=("[^"]*"|'."'".'[^'."'".']*'."'".'|[^ '."'".'"><=`]*))?)*\>/ end=#</\z1># fold'], 49 \ }, 50 \ 'php': { 51 \ 'parentheses': ['start=/\v\<((area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)[ >])@!\z([-_:a-zA-Z0-9]+)(\s+[-_:a-zA-Z0-9]+(\=("[^"]*"|'."'".'[^'."'".']*'."'".'|[^ '."'".'"><=`]*))?)*\>/ end=#</\z1># fold', 'start=/(/ end=/)/ containedin=@htmlPreproc contains=@phpClTop', 'start=/\[/ end=/\]/ containedin=@htmlPreproc contains=@phpClTop', 'start=/{/ end=/}/ containedin=@htmlPreproc contains=@phpClTop'], 52 \ }, 53 \ 'css': 0, 54 \ 'sh': { 55 \ 'parentheses': [['\(^\|\s\)\S*()\s*{\?\($\|\s\)','_^{_','}'], ['\(^\|\s\)if\($\|\s\)','_\(^\|\s\)\(then\|else\|elif\)\($\|\s\)_','\(^\|\s\)fi\($\|\s\)'], ['\(^\|\s\)for\($\|\s\)','_\(^\|\s\)\(do\|in\)\($\|\s\)_','\(^\|\s\)done\($\|\s\)'], ['\(^\|\s\)while\($\|\s\)','_\(^\|\s\)\(do\)\($\|\s\)_','\(^\|\s\)done\($\|\s\)'], ['\(^\|\s\)case\($\|\s\)','_\(^\|\s\)\(\S*)\|in\|;;\)\($\|\s\)_','\(^\|\s\)esac\($\|\s\)']], 56 \ }, 57 \ } 58 \} 59 60 func s:resolve_parenthesis(p) 61 let ls = split(a:p, '\v%(%(start|step|end)\=(.)%(\1@!.)*\1[^ ]*|\w+%(\=[^ ]*)?) ?\zs', 0) 62 let [paren, containedin, contains, op] = ['', '', 'TOP', ''] 63 for s in ls 64 let [k, v] = [matchstr(s, '^[^=]\+\ze='), matchstr(s, '^[^=]\+=\zs.*')] 65 if k == 'step' 66 let op = v 67 elseif k == 'contains' 68 let contains = v 69 elseif k == 'containedin' 70 let containedin = v 71 else 72 let paren .= s 73 endif 74 endfor 75 return [paren, containedin, contains, op] 76 endfunc 77 78 func rainbow#load() 79 let conf = b:rainbow_conf 80 let maxlvl = has('gui_running')? len(conf.guifgs) : len(conf.ctermfgs) 81 for i in range(len(conf.parentheses)) 82 let p = conf.parentheses[i] 83 if type(p) == type([]) 84 let op = len(p)==3? p[1] : has_key(conf, 'operators')? conf.operators : '' 85 let conf.parentheses[i] = op != ''? printf('start=#%s# step=%s end=#%s#', p[0], op, p[-1]) : printf('start=#%s# end=#%s#', p[0], p[-1]) 86 endif 87 endfor 88 let def_rg = 'syn region %s matchgroup=%s containedin=%s contains=%s %s' 89 let def_op = 'syn match %s %s containedin=%s contained' 90 91 call rainbow#clear() 92 let b:rainbow_loaded = maxlvl 93 for parenthesis_args in conf.parentheses 94 let [paren, containedin, contains, op] = s:resolve_parenthesis(parenthesis_args) 95 if op == '' |let op = conf.operators |endif 96 for lvl in range(maxlvl) 97 if op != '' |exe printf(def_op, 'rainbow_o'.lvl, op, 'rainbow_r'.lvl) |endif 98 if lvl == 0 99 if containedin == '' 100 exe printf(def_rg, 'rainbow_r0', 'rainbow_p0', 'rainbow_r'.(maxlvl - 1), contains, paren) 101 endif 102 else 103 exe printf(def_rg, 'rainbow_r'.lvl, 'rainbow_p'.lvl.(' contained'), 'rainbow_r'.((lvl + maxlvl - 1) % maxlvl), contains, paren) 104 endif 105 endfor 106 if containedin != '' 107 exe printf(def_rg, 'rainbow_r0', 'rainbow_p0 contained', containedin.',rainbow_r'.(maxlvl - 1), contains, paren) 108 endif 109 endfor 110 exe 'syn cluster RainbowRegions contains='.join(map(range(maxlvl), '"rainbow_r".v:val'),',') 111 exe 'syn cluster RainbowParentheses contains='.join(map(range(maxlvl), '"rainbow_p".v:val'),',') 112 exe 'syn cluster RainbowOperators contains='.join(map(range(maxlvl), '"rainbow_o".v:val'),',') 113 114 call rainbow#show() 115 endfunc 116 117 func rainbow#clear() 118 call rainbow#hide() 119 if exists('b:rainbow_loaded') 120 for each in range(b:rainbow_loaded) 121 exe 'syn clear rainbow_r'.each 122 exe 'syn clear rainbow_o'.each 123 endfor 124 unlet b:rainbow_loaded 125 endif 126 endfunc 127 128 func rainbow#show() 129 if exists('b:rainbow_loaded') 130 let b:rainbow_visible = 1 131 for id in range(b:rainbow_loaded) 132 let ctermfg = b:rainbow_conf.ctermfgs[id % len(b:rainbow_conf.ctermfgs)] 133 let guifg = b:rainbow_conf.guifgs[id % len(b:rainbow_conf.guifgs)] 134 exe 'hi rainbow_p'.id.' ctermfg='.ctermfg.' guifg='.guifg 135 exe 'hi rainbow_o'.id.' ctermfg='.ctermfg.' guifg='.guifg 136 endfor 137 endif 138 endfunc 139 140 func rainbow#hide() 141 if exists('b:rainbow_visible') 142 for each in range(b:rainbow_loaded) 143 exe 'hi clear rainbow_p'.each 144 exe 'hi clear rainbow_o'.each 145 endfor 146 unlet b:rainbow_visible 147 endif 148 endfunc 149 150 func rainbow#toggle() 151 if exists('b:rainbow_loaded') 152 call rainbow#clear() 153 else 154 if exists('b:rainbow_conf') 155 call rainbow#load() 156 else 157 call rainbow#hook() 158 endif 159 endif 160 endfunc 161 162 func rainbow#hook() 163 let g_conf = extend(copy(s:rainbow_conf), exists('g:rainbow_conf')? g:rainbow_conf : {}) |unlet g_conf.separately 164 if exists('g:rainbow_conf.separately') && has_key(g:rainbow_conf.separately, '*') 165 let separately = copy(g:rainbow_conf.separately) 166 else 167 let separately = extend(copy(s:rainbow_conf.separately), exists('g:rainbow_conf.separately')? g:rainbow_conf.separately : {}) 168 endif 169 let b_conf = has_key(separately, &ft)? separately[&ft] : separately['*'] 170 if type(b_conf) == type({}) 171 let b:rainbow_conf = extend(g_conf, b_conf) 172 call rainbow#load() 173 endif 174 endfunc 175 176 command! RainbowToggle call rainbow#toggle() 177 command! RainbowToggleOn call rainbow#hook() 178 command! RainbowToggleOff call rainbow#clear() 179 180 if (exists('g:rainbow_active') && g:rainbow_active) 181 auto syntax * call rainbow#hook() 182 auto colorscheme * call rainbow#show() 183 endif