Add "rainbow" plugin for colored parentheses
dblume

dblume commited on 2024-05-26 14:29:28
Showing 12 changed files, with 978 additions and 4 deletions.


Chose https://github.com/luochen1990/rainbow because it's
correct, small, configurable and fast.

Rejected the older https://github.com/krischik/vim-rainbow
because it "broke" formatting with strings, Ex., something like
"set (", val, ")".

I'm certain I'll be updating .vimrc and init.vim with better
colors soon.
... ...
@@ -429,11 +429,11 @@ let g:rooter_patterns = ['.git', 'Makefile', 'builds/']
429 429
 let g:rooter_cd_cmd = 'lcd'
430 430
 let g:rooter_manual_only = 1
431 431
 
432
+" 'Rainbow Parentheses Improved' https://github.com/luochen1990/rainbow/
433
+let g:rainbow_conf = { 'ctermfgs': ['lightblue', 'yellow', 'green', 'cyan', 'lightmagenta'] }
434
+let g:rainbow_active = 1 "set to 0 if you want to enable it later via :RainbowToggle
435
+
432 436
 " See https://wiki.dlma.com/neovim#cscope
433 437
 lua << EOF
434 438
   require('cscope_maps').setup()
435 439
 EOF
436
-
437
-" In some environments, Vim starts in replace mode:
438
-" https://superuser.com/questions/1284561/why-is-vim-starting-in-replace-mode
439
-" set t_u7=
... ...
@@ -0,0 +1,190 @@
1
+Rainbow Parentheses Improved 
2
+===
3
+>	help you read complex code by showing diff level of parentheses in diff color !!
4
+
5
+Description [(这里有中文版)](https://github.com/luochen1990/rainbow/blob/master/README_zh.md)
6
+---------------------------------------------------------------------------------------------------
7
+
8
+As everyone knows, the most complex codes were composed of a mass of different kinds of parentheses (typically: lisp).
9
+This plugin will help you read these codes by showing different levels of parentheses in different colors.
10
+You can also find this plugin in **[www.vim.org](http://www.vim.org/scripts/script.php?script_id=4176)**.
11
+
12
+#### lisp
13
+![lisp](https://raw.githubusercontent.com/luochen1990/rainbow/demo/lisp.png)
14
+#### html
15
+![html](https://raw.githubusercontent.com/luochen1990/rainbow/demo/html.png)
16
+#### [more](https://github.com/luochen1990/rainbow/blob/demo/more.md)
17
+
18
+### What is improved ?
19
+
20
+- no limit of parentheses levels.
21
+- separately edit guifgs and ctermfgs (the colors used for highlighting).
22
+- now you can design your own parentheses  such as 'begin' and 'end'.
23
+- you can also configure anything separately for different types of files.
24
+- now you can even decide to let some operators (like + - * / , ==) highlighted with the parentheses together.
25
+- dot separated combined filetype support (`:h ft`).
26
+- json style configuration used, more understandable and readable, easier for advanced configuration.
27
+- the code is shorter and easier to read now.
28
+- smoother and faster.
29
+- the Chinese document is added.
30
+
31
+### Referenced:
32
+- http://www.vim.org/scripts/script.php?script_id=1561 (Martin Krischik)
33
+- http://www.vim.org/scripts/script.php?script_id=3772 (kien)
34
+
35
+Install
36
+-------
37
+
38
+#### install via Plug:
39
+
40
+```vim
41
+Plug 'luochen1990/rainbow'
42
+let g:rainbow_active = 1 "set to 0 if you want to enable it later via :RainbowToggle
43
+```
44
+
45
+#### install manually:
46
+
47
+- first, execute the following commands (for windows users, use `~/vimfiles` instead of `~/.vim`)
48
+
49
+	```sh
50
+	git clone https://github.com/luochen1990/rainbow.git
51
+	cd rainbow
52
+	mkdir -p ~/.vim/plugin ~/.vim/autoload
53
+	cp plugin/* ~/.vim/plugin
54
+	cp autoload/* ~/.vim/autoload
55
+	```
56
+
57
+- second, add the follow sentences to your `.vimrc` or `_vimrc` :
58
+
59
+	```vim
60
+	let g:rainbow_active = 1 "set to 0 if you want to enable it later via :RainbowToggle
61
+	```
62
+
63
+- third, restart your vim and enjoy coding.
64
+
65
+Configure
66
+---------
67
+
68
+There is an example for advanced configuration, add it to your vimrc and edit it as you wish (just keep the format).
69
+
70
+Note: you can remove these lines safely since they are all included by the [source code](https://github.com/luochen1990/rainbow/blob/master/autoload/rainbow_main.vim)).
71
+
72
+```vim
73
+let g:rainbow_conf = {
74
+\	'guifgs': ['royalblue3', 'darkorange3', 'seagreen3', 'firebrick'],
75
+\	'ctermfgs': ['lightblue', 'lightyellow', 'lightcyan', 'lightmagenta'],
76
+\	'guis': [''],
77
+\	'cterms': [''],
78
+\	'operators': '_,_',
79
+\	'parentheses': ['start=/(/ end=/)/ fold', 'start=/\[/ end=/\]/ fold', 'start=/{/ end=/}/ fold'],
80
+\	'separately': {
81
+\		'*': {},
82
+\		'markdown': {
83
+\			'parentheses_options': 'containedin=markdownCode contained', "enable rainbow for code blocks only
84
+\		},
85
+\		'lisp': {
86
+\			'guifgs': ['royalblue3', 'darkorange3', 'seagreen3', 'firebrick', 'darkorchid3'], "lisp needs more colors for parentheses :)
87
+\		},
88
+\		'haskell': {
89
+\			'parentheses': ['start=/(/ end=/)/ fold', 'start=/\[/ end=/\]/ fold', 'start=/\v\{\ze[^-]/ end=/}/ fold'], "the haskell lang pragmas should be excluded
90
+\		},
91
+\		'vim': {
92
+\			'parentheses_options': 'containedin=vimFuncBody', "enable rainbow inside vim function body
93
+\		},
94
+\		'perl': {
95
+\			'syn_name_prefix': 'perlBlockFoldRainbow', "solve the [perl indent-depending-on-syntax problem](https://github.com/luochen1990/rainbow/issues/20)
96
+\		},
97
+\		'stylus': {
98
+\			'parentheses': ['start=/{/ end=/}/ fold contains=@colorableGroup'], "[vim css color](https://github.com/ap/vim-css-color) compatibility
99
+\		},
100
+\		'css': 0, "disable this plugin for css files
101
+\		'nerdtree': 0, "rainbow is conflicting with NERDTree, creating extra parentheses
102
+\	}
103
+\}
104
+```
105
+
106
+- 'guifgs': a list of `guifg` (`:h highlight-guifg`), i.e. colors for gui interface, will be used in order
107
+- 'guis': a list of `gui` (`:h highlight-gui`), will be used in order
108
+- 'ctermfgs': a list of `ctermfg` (`:h highlight-ctermfg`)
109
+- 'cterms': a list of `cterm` (`:h highlight-cterm`)
110
+- 'operators': describe the operators you want to highlight (note: be careful about special characters which needs escaping, you can find more examples [here](https://github.com/luochen1990/rainbow/issues/3), and you can also read the [vim help about syn-pattern](http://vimdoc.sourceforge.net/htmldoc/syntax.html#:syn-pattern)). note that this option will be overwritten by the `step` part of `parentheses`.
111
+- 'parentheses': a list of parentheses definitions, a parentheses definition contains parts like `start=/(/`, `step=/,/`, `stop=/)/`, `fold`, `contained`, `containedin=someSynNames`, `contains=@Spell`, see `:h syntax` for more details. notice that the `step` part is defined by this plugin so it is not described by the official vim doc.
112
+- 'parentheses_options': parentheses options shared between different parentheses, things like `containedin=xxxFuncBody`, `contains=@Spell` (or 'contains=@NoSpell') often appears here. this option is often used to solve [3rd-party-plugin-compatibility]() problems.
113
+- 'separately': configure for specific filetypes (decided by &ft), key `*` for filetypes without separate configuration, value `0` means disable rainbow only for this type of files, value `"default"` means keep the default shim for this filetype (notice: the default shim config will change between plugin version).
114
+- 'syn_name_prefix': add a prefix to name of the syntax definition, this option is often used to solve [3rd-party-plugin-compatibility]() problems.
115
+- 'after': execute some vim commands after the rainbow syntax rules is defined. it is often used like `['syn clear xxx']` to solve [3rd-party-plugin-compatibility]() problems.
116
+- keep a field empty to use the default setting.
117
+
118
+To get more advanced config examples, try to search throught this [tag](https://github.com/luochen1990/rainbow/issues?utf8=%E2%9C%93&q=label%3A%22config+reference%22+).
119
+
120
+User Command
121
+------------
122
+
123
+- **:RainbowToggle**		--you can use it to toggle this plugin.
124
+
125
+3rd Party Plugin Compatibility
126
+------------------------------
127
+
128
+You should notice that this plugin is very special, Vim plugins is expected to provide syntax definitions vertically, i.e. one filetype, one syntax definition set:
129
+
130
+```
131
+----------------------------------------------------
132
+|      cpp       |      java       |    python     |
133
+|                |                 |               |
134
+| syn cppKeyword | syn javaKeyword | syn pyKeyword |
135
+| syn cppFunc    | syn javaFunc    | syn pyLambda  |
136
+| syn cppParen   | syn javaParen   | syn pyParen   |
137
+| ...            | ...             | ...           |
138
+----------------------------------------------------
139
+```
140
+
141
+But this plugin provide syntax definitions horizontally, i.e. parentheses syntax for all filetypes:
142
+
143
+```
144
+----------------------------------------------------
145
+|      cpp       |      java       |    python     |
146
+|                |                 |               |
147
+| syn cppKeyword | syn javaKeyword | syn pyKeyword |
148
+| syn cppFunc    | syn javaFunc    | syn pyLambda  |
149
+| ...            | ...             | ...           |
150
+----------------------------------------------------
151
+|                     rainbow                      |
152
+|                                                  |
153
+| syn cppRainbow   syn javaRainbow   syn pyRainbow |
154
+----------------------------------------------------
155
+```
156
+
157
+You can notice that, to provide rainbow parentheses, this plugin have to define it's own syntax rules, and these rules will overwrite the parentheses syntax provided by the filetype plugin.
158
+
159
+It works well at most of the time, but in some special cases, when the parentheses syntax rule is depended somewhere else (e.g. indent, spell checking, nested syntax rules), the things depend on the original syntax rules will be broken.
160
+
161
+This plugin has provide some mechanisms to solve the compatibility problems, and have provided default configurations to solve compatibility problems with the default vim syntax files.
162
+
163
+But if this plugin is conflicted with some other plugins, you will probably have to solve them by yourself. First, you can search on [this issue tag](https://github.com/luochen1990/rainbow/issues?utf8=%E2%9C%93&q=label%3A%22confliction+with+other+third-party+syntax+plugins%22+) to find whether there is somebody else had the same problem and solved it. Second, you can read the following content about troubleshooting.
164
+
165
+Troubleshooting
166
+---------------
167
+
168
+- rainbow doesn't work at all: find out the current parentheses syntax name, and use the `after` mechanism to clear these syntax.
169
+- rainbow doesn't work inside some structure: find out the syntax region name, and use the `parentheses_options` mechanism like `'containedin=xxx'`.
170
+- spell checking doesn't work inside parentheses: use the `parentheses_options` mechanism like `'contains=@Spell'`.
171
+- spell checking works inside parentheses but you don't want it: use the `parentheses_options` mechanism like `'contains=@NoSpell'`.
172
+- indent not works correctly: check the indent script you are using and search `synID` inside it to find which syntax name prefix it depends on, and use the `syn_name_prefix` mechanism to solve it.
173
+
174
+The following keymappings will help you to check the syntax name and definitions under the cursor, add them to your vimrc and restart vim:
175
+
176
+```vim
177
+nnoremap <f1> :echo synIDattr(synID(line('.'), col('.'), 0), 'name')<cr>
178
+nnoremap <f2> :echo ("hi<" . synIDattr(synID(line("."),col("."),1),"name") . '> trans<'
179
+\ . synIDattr(synID(line("."),col("."),0),"name") . "> lo<"
180
+\ . synIDattr(synIDtrans(synID(line("."),col("."),1)),"name") . ">")<cr>
181
+nnoremap <f3> :echo map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')<cr>
182
+nnoremap <f4> :exec 'syn list '.synIDattr(synID(line('.'), col('.'), 0), 'name')<cr>
183
+```
184
+
185
+Move your cursor to a parentheses and press the keys to use them.
186
+
187
+------------------------------------------------------------------
188
+**Rate this script if you like it, and I'll appreciate it and improve this plugin for you because of your support!
189
+
190
+Just go to [this page](http://www.vim.org/scripts/script.php?script_id=4176) and choose `Life Changing` and click `rate`**
... ...
@@ -0,0 +1,128 @@
1
+" Copyright 2013 LuoChen (luochen1990@gmail.com). Licensed under the Apache License 2.0.
2
+
3
+if exists('s:loaded') | finish | endif | let s:loaded = 1
4
+
5
+fun s:trim(s)
6
+	return substitute(a:s, '\v^\s*(.{-})\s*$', '\1', '')
7
+endfun
8
+
9
+fun s:concat(strs)
10
+	return join(filter(a:strs, "v:val !~ '^[ ]*$'"), ',')
11
+endfun
12
+
13
+fun s:resolve_parenthesis_with(init_state, p)
14
+	let [paren, contained, containedin, contains_prefix, contains, op] = a:init_state
15
+	let p = (type(a:p) == type([])) ? ((len(a:p) == 3) ? printf('start=#%s# step=%s end=#%s#', a:p[0], op, a:p[-1]) : printf('start=#%s# end=#%s#', a:p[0], a:p[-1])) : a:p "NOTE: preprocess the old style parentheses config
16
+
17
+	let ls = split(p, '\v%(%(start|step|end)\=(.)%(\1@!.)*\1[^ ]*|\w+%(\=[^ ]*)?) ?\zs', 0)
18
+	for s in ls
19
+		let [k, v] = [matchstr(s, '^[^=]\+\ze\(=\|$\)'), matchstr(s, '^[^=]\+=\zs.*')]
20
+		if k == 'step'
21
+			let op = s:trim(v)
22
+		elseif k == 'contains_prefix'
23
+			let contains_prefix = s:trim(v)
24
+		elseif k == 'contains'
25
+			let contains = s:concat([contains, s:trim(v)])
26
+		elseif k == 'containedin'
27
+			let containedin = s:concat([containedin, s:trim(v)])
28
+		elseif k == 'contained'
29
+			let contained = 1
30
+		else
31
+			let paren .= s
32
+		endif
33
+	endfor
34
+	let rst = [paren, contained, containedin, contains_prefix, contains, op]
35
+	"echom json_encode(rst)
36
+	return rst
37
+endfun
38
+
39
+fun s:resolve_parenthesis_from_config(config)
40
+	return s:resolve_parenthesis_with(['', 0, '', a:config.contains_prefix, '', a:config.operators], a:config.parentheses_options)
41
+endfun
42
+
43
+fun s:synID(prefix, group, lv, id)
44
+	return a:prefix.'_lv'.a:lv.'_'.a:group.a:id
45
+endfun
46
+
47
+fun s:synGroupID(prefix, group, lv)
48
+	return a:prefix.a:group.'_lv'.a:lv
49
+endfun
50
+
51
+fun rainbow#syn(config)
52
+	let conf = a:config
53
+	let prefix = conf.syn_name_prefix
54
+	let cycle = conf.cycle
55
+
56
+	let glob_paran_opts = s:resolve_parenthesis_from_config(conf)
57
+	let b:rainbow_loaded = cycle
58
+	for id in range(len(conf.parentheses))
59
+		let [paren, contained, containedin, contains_prefix, contains, op] = s:resolve_parenthesis_with(glob_paran_opts, conf.parentheses[id])
60
+		for lv in range(cycle)
61
+			let lv2 = ((lv + cycle - 1) % cycle)
62
+			let [rid, pid, gid2] = [s:synID(prefix, 'r', lv, id), s:synID(prefix, 'p', lv, id), s:synGroupID(prefix, 'Regions', lv2)]
63
+
64
+			if len(op) > 2
65
+				exe 'syn match '.s:synID(prefix, 'o', lv, id).' '.op.' containedin='.s:synID(prefix, 'r', lv, id).' contained'
66
+			endif
67
+
68
+			let real_contained = (lv == 0)? (contained? 'contained ' : '') : 'contained '
69
+			let real_containedin = (lv == 0)? s:concat([containedin, '@'.gid2]) : '@'.gid2
70
+			let real_contains = s:concat([contains_prefix, contains])
71
+			exe 'syn region '.rid.' matchgroup='.pid.' '.real_contained.'containedin='.real_containedin.' contains='.real_contains.' '.paren
72
+		endfor
73
+	endfor
74
+	for lv in range(cycle)
75
+		exe 'syn cluster '.s:synGroupID(prefix, 'Regions', lv).' contains='.join(map(range(len(conf.parentheses)), 's:synID(prefix, "r", lv, v:val)'), ',')
76
+		exe 'syn cluster '.s:synGroupID(prefix, 'Parentheses', lv).' contains='.join(map(range(len(conf.parentheses)), 's:synID(prefix, "p", lv, v:val)'), ',')
77
+		exe 'syn cluster '.s:synGroupID(prefix, 'Operators', lv).' contains='.join(map(range(len(conf.parentheses)), 's:synID(prefix, "o", lv, v:val)'), ',')
78
+	endfor
79
+	exe 'syn cluster '.prefix.'Regions contains='.join(map(range(cycle), '"@".s:synGroupID(prefix, "Regions", v:val)'), ',')
80
+	exe 'syn cluster '.prefix.'Parentheses contains='.join(map(range(cycle), '"@".s:synGroupID(prefix, "Parentheses", v:val)'), ',')
81
+	exe 'syn cluster '.prefix.'Operators contains='.join(map(range(cycle), '"@".s:synGroupID(prefix, "Operators", v:val)'), ',')
82
+	if has_key(conf, 'after') | for cmd in conf.after | exe cmd | endfor | endif
83
+endfun
84
+
85
+fun rainbow#syn_clear(config)
86
+	let conf = a:config
87
+	let prefix = conf.syn_name_prefix
88
+
89
+	for id in range(len(conf.parentheses))
90
+		for lv in range(conf.cycle)
91
+			let [rid, oid] = [s:synID(prefix, 'r', lv, id), s:synID(prefix, 'o', lv, id)]
92
+			exe 'syn clear '.rid
93
+			exe 'syn clear '.oid
94
+		endfor
95
+	endfor
96
+endfun
97
+
98
+fun rainbow#hi(config)
99
+	let conf = a:config
100
+	let prefix = conf.syn_name_prefix
101
+
102
+	for id in range(len(conf.parentheses))
103
+		for lv in range(conf.cycle)
104
+			let [pid, oid] = [s:synID(prefix, 'p', lv, id), s:synID(prefix, 'o', lv, id)]
105
+			let ctermfg = conf.ctermfgs[lv % len(conf.ctermfgs)]
106
+			let guifg = conf.guifgs[lv % len(conf.guifgs)]
107
+			let cterm = conf.cterms[lv % len(conf.cterms)]
108
+			let gui = conf.guis[lv % len(conf.guis)]
109
+			let hi_style = 'ctermfg='.ctermfg.' guifg='.guifg.(len(cterm) > 0 ? ' cterm='.cterm : '').(len(gui) > 0 ? ' gui='.gui : '')
110
+			exe 'hi '.pid.' '.hi_style
111
+			exe 'hi '.oid.' '.hi_style
112
+		endfor
113
+	endfor
114
+endfun
115
+
116
+fun rainbow#hi_clear(config)
117
+	let conf = a:config
118
+	let prefix = conf.syn_name_prefix
119
+
120
+	for id in range(len(conf.parentheses))
121
+		for lv in range(conf.cycle)
122
+			let [pid, oid] = [s:synID(prefix, 'p', lv, id), s:synID(prefix, 'o', lv, id)]
123
+			exe 'hi clear '.pid
124
+			exe 'hi clear '.oid
125
+		endfor
126
+	endfor
127
+endfun
128
+
... ...
@@ -0,0 +1,136 @@
1
+" Copyright 2013 LuoChen (luochen1990@gmail.com). Licensed under the Apache License 2.0.
2
+
3
+let s:rainbow_conf = {
4
+\	'guifgs': ['royalblue3', 'darkorange3', 'seagreen3', 'firebrick'],
5
+\	'ctermfgs': ['lightblue', 'lightyellow', 'lightcyan', 'lightmagenta'],
6
+\	'guis': [''],
7
+\	'cterms': [''],
8
+\	'operators': '_,_',
9
+\	'contains_prefix': 'TOP',
10
+\	'parentheses_options': '',
11
+\	'parentheses': ['start=/(/ end=/)/ fold', 'start=/\[/ end=/\]/ fold', 'start=/{/ end=/}/ fold'],
12
+\	'separately': {
13
+\		'*': {},
14
+\		'markdown': {
15
+\			'parentheses_options': 'containedin=markdownCode contained',
16
+\		},
17
+\		'lisp': {
18
+\			'guifgs': ['royalblue3', 'darkorange3', 'seagreen3', 'firebrick', 'darkorchid3'],
19
+\		},
20
+\		'haskell': {
21
+\			'parentheses': ['start=/(/ end=/)/ fold', 'start=/\[/ end=/\]/ fold', 'start=/\v\{\ze[^-]/ end=/}/ fold'],
22
+\		},
23
+\		'ocaml': {
24
+\			'parentheses': ['start=/(\ze[^*]/ end=/)/ fold', 'start=/\[/ end=/\]/ fold', 'start=/\[|/ end=/|\]/ fold', 'start=/{/ end=/}/ fold'],
25
+\		},
26
+\		'tex': {
27
+\			'parentheses_options': 'containedin=texDocZone',
28
+\			'parentheses': ['start=/(/ end=/)/', 'start=/\[/ end=/\]/'],
29
+\		},
30
+\		'vim': {
31
+\			'parentheses_options': 'containedin=vimFuncBody,vimExecute',
32
+\			'parentheses': ['start=/(/ end=/)/', 'start=/\[/ end=/\]/', 'start=/{/ end=/}/ fold'],
33
+\		},
34
+\		'xml': {
35
+\			'syn_name_prefix': 'xmlRainbow',
36
+\			'parentheses': ['start=/\v\<\z([-_:a-zA-Z0-9]+)(\s+[-_:a-zA-Z0-9]+(\=("[^"]*"|'."'".'[^'."'".']*'."'".'))?)*\>/ end=#</\z1># fold'],
37
+\		},
38
+\		'xhtml': {
39
+\			'parentheses': ['start=/\v\<\z([-_:a-zA-Z0-9]+)(\s+[-_:a-zA-Z0-9]+(\=("[^"]*"|'."'".'[^'."'".']*'."'".'))?)*\>/ end=#</\z1># fold'],
40
+\		},
41
+\		'html': {
42
+\			'parentheses': ['start=/\v\<((script|style|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'],
43
+\		},
44
+\		'lua': {
45
+\			'parentheses': ["start=/(/ end=/)/", "start=/{/ end=/}/", "start=/\\v\\[\\ze($|[^[])/ end=/\\]/"],
46
+\		},
47
+\		'perl': {
48
+\			'syn_name_prefix': 'perlBlockFoldRainbow',
49
+\		},
50
+\		'php': {
51
+\			'syn_name_prefix': 'phpBlockRainbow',
52
+\			'contains_prefix': '',
53
+\			'parentheses': ['start=/(/ end=/)/ containedin=@htmlPreproc contains=@phpClTop', 'start=/\[/ end=/\]/ containedin=@htmlPreproc contains=@phpClTop', 'start=/{/ end=/}/ containedin=@htmlPreproc contains=@phpClTop', '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 contains_prefix=TOP'],
54
+\		},
55
+\		'stylus': {
56
+\			'parentheses': ['start=/{/ end=/}/ fold contains=@colorableGroup'],
57
+\		},
58
+\		'css': 0,
59
+\		'sh': 0,
60
+\		'vimwiki': 0,
61
+\	}
62
+\}
63
+
64
+fun s:eq(x, y)
65
+	return type(a:x) == type(a:y) && a:x == a:y
66
+endfun
67
+
68
+fun s:gcd(a, b)
69
+	let [a, b, t] = [a:a, a:b, 0]
70
+	while b != 0
71
+		let t = b
72
+		let b = a % b
73
+		let a = t
74
+	endwhile
75
+	return a
76
+endfun
77
+
78
+fun s:lcm(a, b)
79
+	return (a:a / s:gcd(a:a, a:b)) * a:b
80
+endfun
81
+
82
+fun rainbow_main#gen_config(ft)
83
+	let g = exists('g:rainbow_conf')? g:rainbow_conf : {}
84
+	"echom 'g:rainbow_conf:' string(g)
85
+	let s = get(g, 'separately', {})
86
+	"echom 'g:rainbow_conf.separately:' string(s)
87
+	let dft_conf = extend(copy(s:rainbow_conf), g) | unlet dft_conf.separately
88
+	"echom 'default config options:' string(dft_conf)
89
+	let dx_conf = s:rainbow_conf.separately['*']
90
+	"echom 'default star config:' string(dx_conf)
91
+	let ds_conf = get(s:rainbow_conf.separately, a:ft, dx_conf)
92
+	"echom 'default separately config:' string(ds_conf)
93
+	let ux_conf = get(s, '*', ds_conf)
94
+	"echom 'user star config:' string(ux_conf)
95
+	let us_conf = get(s, a:ft, ux_conf)
96
+	"echom 'user separately config:' string(us_conf)
97
+	let af_conf = (s:eq(us_conf, 'default') ? ds_conf : us_conf)
98
+	"echom 'almost finally config:' string(af_conf)
99
+	if s:eq(af_conf, 0)
100
+		return 0
101
+	else
102
+		let conf = extend(extend({'syn_name_prefix': substitute(a:ft, '\v\A+(\a)', '\u\1', 'g').'Rainbow'}, dft_conf), af_conf)
103
+		let conf.cycle = (has('gui_running') || (has('termguicolors') && &termguicolors)) ? s:lcm(len(conf.guifgs), len(conf.guis)) : s:lcm(len(conf.ctermfgs), len(conf.cterms))
104
+		return conf
105
+	endif
106
+endfun
107
+
108
+fun rainbow_main#gen_configs(ft)
109
+	return filter(map(split(a:ft, '\v\.'), 'rainbow_main#gen_config(v:val)'), 'type(v:val) == type({})')
110
+endfun
111
+
112
+fun rainbow_main#load()
113
+	let b:rainbow_confs = rainbow_main#gen_configs(&filetype)
114
+	for conf in b:rainbow_confs
115
+		call rainbow#syn(conf)
116
+		call rainbow#hi(conf)
117
+	endfor
118
+endfun
119
+
120
+fun rainbow_main#clear()
121
+	if !exists('b:rainbow_confs') | return | endif
122
+	for conf in b:rainbow_confs
123
+		call rainbow#hi_clear(conf)
124
+		call rainbow#syn_clear(conf)
125
+	endfor
126
+	unlet b:rainbow_confs
127
+endfun
128
+
129
+fun rainbow_main#toggle()
130
+	if exists('b:rainbow_confs')
131
+		call rainbow_main#clear()
132
+	else
133
+		call rainbow_main#load()
134
+	endif
135
+endfun
136
+
... ...
@@ -0,0 +1,18 @@
1
+Rainbow Parentheses Improved                                     *rainbow*
2
+==========================================================================
3
+
4
+Commands:                                               *rainbow-commands*
5
+--------------------------------------------------------------------------
6
+
7
+*RainbowToggle*     ---  toggle this plugin on/off
8
+*RainbowToggleOn*   ---  toggle this plugin on
9
+*RainbowToggleOff*  ---  toggle this plugin off
10
+
11
+Configurations:                                           *rainbow-config*
12
+--------------------------------------------------------------------------
13
+
14
+*g:rainbow_active*  ---  1 to auto enable this plugin
15
+                         0 to enable it later via :RainbowToggle
16
+*g:rainbow_conf*    ---  https://github.com/luochen1990/rainbow#configure
17
+
18
+vim:tw=78:ts=8:ft=help:norl:
... ...
@@ -0,0 +1,12 @@
1
+" Copyright 2013 LuoChen (luochen1990@gmail.com). Licensed under the Apache License 2.0.
2
+
3
+if exists('s:loaded') || !(exists('g:rainbow_active') || exists('g:rainbow_conf')) | finish | endif | let s:loaded = 1
4
+
5
+command! RainbowToggle call rainbow_main#toggle()
6
+command! RainbowToggleOn call rainbow_main#load()
7
+command! RainbowToggleOff call rainbow_main#clear()
8
+
9
+if (exists('g:rainbow_active') && g:rainbow_active)
10
+	auto syntax * call rainbow_main#load()
11
+	auto colorscheme * call rainbow_main#load()
12
+endif
... ...
@@ -0,0 +1,190 @@
1
+Rainbow Parentheses Improved 
2
+===
3
+>	help you read complex code by showing diff level of parentheses in diff color !!
4
+
5
+Description [(这里有中文版)](https://github.com/luochen1990/rainbow/blob/master/README_zh.md)
6
+---------------------------------------------------------------------------------------------------
7
+
8
+As everyone knows, the most complex codes were composed of a mass of different kinds of parentheses (typically: lisp).
9
+This plugin will help you read these codes by showing different levels of parentheses in different colors.
10
+You can also find this plugin in **[www.vim.org](http://www.vim.org/scripts/script.php?script_id=4176)**.
11
+
12
+#### lisp
13
+![lisp](https://raw.githubusercontent.com/luochen1990/rainbow/demo/lisp.png)
14
+#### html
15
+![html](https://raw.githubusercontent.com/luochen1990/rainbow/demo/html.png)
16
+#### [more](https://github.com/luochen1990/rainbow/blob/demo/more.md)
17
+
18
+### What is improved ?
19
+
20
+- no limit of parentheses levels.
21
+- separately edit guifgs and ctermfgs (the colors used for highlighting).
22
+- now you can design your own parentheses  such as 'begin' and 'end'.
23
+- you can also configure anything separately for different types of files.
24
+- now you can even decide to let some operators (like + - * / , ==) highlighted with the parentheses together.
25
+- dot separated combined filetype support (`:h ft`).
26
+- json style configuration used, more understandable and readable, easier for advanced configuration.
27
+- the code is shorter and easier to read now.
28
+- smoother and faster.
29
+- the Chinese document is added.
30
+
31
+### Referenced:
32
+- http://www.vim.org/scripts/script.php?script_id=1561 (Martin Krischik)
33
+- http://www.vim.org/scripts/script.php?script_id=3772 (kien)
34
+
35
+Install
36
+-------
37
+
38
+#### install via Plug:
39
+
40
+```vim
41
+Plug 'luochen1990/rainbow'
42
+let g:rainbow_active = 1 "set to 0 if you want to enable it later via :RainbowToggle
43
+```
44
+
45
+#### install manually:
46
+
47
+- first, execute the following commands (for windows users, use `~/vimfiles` instead of `~/.vim`)
48
+
49
+	```sh
50
+	git clone https://github.com/luochen1990/rainbow.git
51
+	cd rainbow
52
+	mkdir -p ~/.vim/plugin ~/.vim/autoload
53
+	cp plugin/* ~/.vim/plugin
54
+	cp autoload/* ~/.vim/autoload
55
+	```
56
+
57
+- second, add the follow sentences to your `.vimrc` or `_vimrc` :
58
+
59
+	```vim
60
+	let g:rainbow_active = 1 "set to 0 if you want to enable it later via :RainbowToggle
61
+	```
62
+
63
+- third, restart your vim and enjoy coding.
64
+
65
+Configure
66
+---------
67
+
68
+There is an example for advanced configuration, add it to your vimrc and edit it as you wish (just keep the format).
69
+
70
+Note: you can remove these lines safely since they are all included by the [source code](https://github.com/luochen1990/rainbow/blob/master/autoload/rainbow_main.vim)).
71
+
72
+```vim
73
+let g:rainbow_conf = {
74
+\	'guifgs': ['royalblue3', 'darkorange3', 'seagreen3', 'firebrick'],
75
+\	'ctermfgs': ['lightblue', 'lightyellow', 'lightcyan', 'lightmagenta'],
76
+\	'guis': [''],
77
+\	'cterms': [''],
78
+\	'operators': '_,_',
79
+\	'parentheses': ['start=/(/ end=/)/ fold', 'start=/\[/ end=/\]/ fold', 'start=/{/ end=/}/ fold'],
80
+\	'separately': {
81
+\		'*': {},
82
+\		'markdown': {
83
+\			'parentheses_options': 'containedin=markdownCode contained', "enable rainbow for code blocks only
84
+\		},
85
+\		'lisp': {
86
+\			'guifgs': ['royalblue3', 'darkorange3', 'seagreen3', 'firebrick', 'darkorchid3'], "lisp needs more colors for parentheses :)
87
+\		},
88
+\		'haskell': {
89
+\			'parentheses': ['start=/(/ end=/)/ fold', 'start=/\[/ end=/\]/ fold', 'start=/\v\{\ze[^-]/ end=/}/ fold'], "the haskell lang pragmas should be excluded
90
+\		},
91
+\		'vim': {
92
+\			'parentheses_options': 'containedin=vimFuncBody', "enable rainbow inside vim function body
93
+\		},
94
+\		'perl': {
95
+\			'syn_name_prefix': 'perlBlockFoldRainbow', "solve the [perl indent-depending-on-syntax problem](https://github.com/luochen1990/rainbow/issues/20)
96
+\		},
97
+\		'stylus': {
98
+\			'parentheses': ['start=/{/ end=/}/ fold contains=@colorableGroup'], "[vim css color](https://github.com/ap/vim-css-color) compatibility
99
+\		},
100
+\		'css': 0, "disable this plugin for css files
101
+\		'nerdtree': 0, "rainbow is conflicting with NERDTree, creating extra parentheses
102
+\	}
103
+\}
104
+```
105
+
106
+- 'guifgs': a list of `guifg` (`:h highlight-guifg`), i.e. colors for gui interface, will be used in order
107
+- 'guis': a list of `gui` (`:h highlight-gui`), will be used in order
108
+- 'ctermfgs': a list of `ctermfg` (`:h highlight-ctermfg`)
109
+- 'cterms': a list of `cterm` (`:h highlight-cterm`)
110
+- 'operators': describe the operators you want to highlight (note: be careful about special characters which needs escaping, you can find more examples [here](https://github.com/luochen1990/rainbow/issues/3), and you can also read the [vim help about syn-pattern](http://vimdoc.sourceforge.net/htmldoc/syntax.html#:syn-pattern)). note that this option will be overwritten by the `step` part of `parentheses`.
111
+- 'parentheses': a list of parentheses definitions, a parentheses definition contains parts like `start=/(/`, `step=/,/`, `stop=/)/`, `fold`, `contained`, `containedin=someSynNames`, `contains=@Spell`, see `:h syntax` for more details. notice that the `step` part is defined by this plugin so it is not described by the official vim doc.
112
+- 'parentheses_options': parentheses options shared between different parentheses, things like `containedin=xxxFuncBody`, `contains=@Spell` (or 'contains=@NoSpell') often appears here. this option is often used to solve [3rd-party-plugin-compatibility]() problems.
113
+- 'separately': configure for specific filetypes (decided by &ft), key `*` for filetypes without separate configuration, value `0` means disable rainbow only for this type of files, value `"default"` means keep the default shim for this filetype (notice: the default shim config will change between plugin version).
114
+- 'syn_name_prefix': add a prefix to name of the syntax definition, this option is often used to solve [3rd-party-plugin-compatibility]() problems.
115
+- 'after': execute some vim commands after the rainbow syntax rules is defined. it is often used like `['syn clear xxx']` to solve [3rd-party-plugin-compatibility]() problems.
116
+- keep a field empty to use the default setting.
117
+
118
+To get more advanced config examples, try to search throught this [tag](https://github.com/luochen1990/rainbow/issues?utf8=%E2%9C%93&q=label%3A%22config+reference%22+).
119
+
120
+User Command
121
+------------
122
+
123
+- **:RainbowToggle**		--you can use it to toggle this plugin.
124
+
125
+3rd Party Plugin Compatibility
126
+------------------------------
127
+
128
+You should notice that this plugin is very special, Vim plugins is expected to provide syntax definitions vertically, i.e. one filetype, one syntax definition set:
129
+
130
+```
131
+----------------------------------------------------
132
+|      cpp       |      java       |    python     |
133
+|                |                 |               |
134
+| syn cppKeyword | syn javaKeyword | syn pyKeyword |
135
+| syn cppFunc    | syn javaFunc    | syn pyLambda  |
136
+| syn cppParen   | syn javaParen   | syn pyParen   |
137
+| ...            | ...             | ...           |
138
+----------------------------------------------------
139
+```
140
+
141
+But this plugin provide syntax definitions horizontally, i.e. parentheses syntax for all filetypes:
142
+
143
+```
144
+----------------------------------------------------
145
+|      cpp       |      java       |    python     |
146
+|                |                 |               |
147
+| syn cppKeyword | syn javaKeyword | syn pyKeyword |
148
+| syn cppFunc    | syn javaFunc    | syn pyLambda  |
149
+| ...            | ...             | ...           |
150
+----------------------------------------------------
151
+|                     rainbow                      |
152
+|                                                  |
153
+| syn cppRainbow   syn javaRainbow   syn pyRainbow |
154
+----------------------------------------------------
155
+```
156
+
157
+You can notice that, to provide rainbow parentheses, this plugin have to define it's own syntax rules, and these rules will overwrite the parentheses syntax provided by the filetype plugin.
158
+
159
+It works well at most of the time, but in some special cases, when the parentheses syntax rule is depended somewhere else (e.g. indent, spell checking, nested syntax rules), the things depend on the original syntax rules will be broken.
160
+
161
+This plugin has provide some mechanisms to solve the compatibility problems, and have provided default configurations to solve compatibility problems with the default vim syntax files.
162
+
163
+But if this plugin is conflicted with some other plugins, you will probably have to solve them by yourself. First, you can search on [this issue tag](https://github.com/luochen1990/rainbow/issues?utf8=%E2%9C%93&q=label%3A%22confliction+with+other+third-party+syntax+plugins%22+) to find whether there is somebody else had the same problem and solved it. Second, you can read the following content about troubleshooting.
164
+
165
+Troubleshooting
166
+---------------
167
+
168
+- rainbow doesn't work at all: find out the current parentheses syntax name, and use the `after` mechanism to clear these syntax.
169
+- rainbow doesn't work inside some structure: find out the syntax region name, and use the `parentheses_options` mechanism like `'containedin=xxx'`.
170
+- spell checking doesn't work inside parentheses: use the `parentheses_options` mechanism like `'contains=@Spell'`.
171
+- spell checking works inside parentheses but you don't want it: use the `parentheses_options` mechanism like `'contains=@NoSpell'`.
172
+- indent not works correctly: check the indent script you are using and search `synID` inside it to find which syntax name prefix it depends on, and use the `syn_name_prefix` mechanism to solve it.
173
+
174
+The following keymappings will help you to check the syntax name and definitions under the cursor, add them to your vimrc and restart vim:
175
+
176
+```vim
177
+nnoremap <f1> :echo synIDattr(synID(line('.'), col('.'), 0), 'name')<cr>
178
+nnoremap <f2> :echo ("hi<" . synIDattr(synID(line("."),col("."),1),"name") . '> trans<'
179
+\ . synIDattr(synID(line("."),col("."),0),"name") . "> lo<"
180
+\ . synIDattr(synIDtrans(synID(line("."),col("."),1)),"name") . ">")<cr>
181
+nnoremap <f3> :echo map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')<cr>
182
+nnoremap <f4> :exec 'syn list '.synIDattr(synID(line('.'), col('.'), 0), 'name')<cr>
183
+```
184
+
185
+Move your cursor to a parentheses and press the keys to use them.
186
+
187
+------------------------------------------------------------------
188
+**Rate this script if you like it, and I'll appreciate it and improve this plugin for you because of your support!
189
+
190
+Just go to [this page](http://www.vim.org/scripts/script.php?script_id=4176) and choose `Life Changing` and click `rate`**
... ...
@@ -0,0 +1,128 @@
1
+" Copyright 2013 LuoChen (luochen1990@gmail.com). Licensed under the Apache License 2.0.
2
+
3
+if exists('s:loaded') | finish | endif | let s:loaded = 1
4
+
5
+fun s:trim(s)
6
+	return substitute(a:s, '\v^\s*(.{-})\s*$', '\1', '')
7
+endfun
8
+
9
+fun s:concat(strs)
10
+	return join(filter(a:strs, "v:val !~ '^[ ]*$'"), ',')
11
+endfun
12
+
13
+fun s:resolve_parenthesis_with(init_state, p)
14
+	let [paren, contained, containedin, contains_prefix, contains, op] = a:init_state
15
+	let p = (type(a:p) == type([])) ? ((len(a:p) == 3) ? printf('start=#%s# step=%s end=#%s#', a:p[0], op, a:p[-1]) : printf('start=#%s# end=#%s#', a:p[0], a:p[-1])) : a:p "NOTE: preprocess the old style parentheses config
16
+
17
+	let ls = split(p, '\v%(%(start|step|end)\=(.)%(\1@!.)*\1[^ ]*|\w+%(\=[^ ]*)?) ?\zs', 0)
18
+	for s in ls
19
+		let [k, v] = [matchstr(s, '^[^=]\+\ze\(=\|$\)'), matchstr(s, '^[^=]\+=\zs.*')]
20
+		if k == 'step'
21
+			let op = s:trim(v)
22
+		elseif k == 'contains_prefix'
23
+			let contains_prefix = s:trim(v)
24
+		elseif k == 'contains'
25
+			let contains = s:concat([contains, s:trim(v)])
26
+		elseif k == 'containedin'
27
+			let containedin = s:concat([containedin, s:trim(v)])
28
+		elseif k == 'contained'
29
+			let contained = 1
30
+		else
31
+			let paren .= s
32
+		endif
33
+	endfor
34
+	let rst = [paren, contained, containedin, contains_prefix, contains, op]
35
+	"echom json_encode(rst)
36
+	return rst
37
+endfun
38
+
39
+fun s:resolve_parenthesis_from_config(config)
40
+	return s:resolve_parenthesis_with(['', 0, '', a:config.contains_prefix, '', a:config.operators], a:config.parentheses_options)
41
+endfun
42
+
43
+fun s:synID(prefix, group, lv, id)
44
+	return a:prefix.'_lv'.a:lv.'_'.a:group.a:id
45
+endfun
46
+
47
+fun s:synGroupID(prefix, group, lv)
48
+	return a:prefix.a:group.'_lv'.a:lv
49
+endfun
50
+
51
+fun rainbow#syn(config)
52
+	let conf = a:config
53
+	let prefix = conf.syn_name_prefix
54
+	let cycle = conf.cycle
55
+
56
+	let glob_paran_opts = s:resolve_parenthesis_from_config(conf)
57
+	let b:rainbow_loaded = cycle
58
+	for id in range(len(conf.parentheses))
59
+		let [paren, contained, containedin, contains_prefix, contains, op] = s:resolve_parenthesis_with(glob_paran_opts, conf.parentheses[id])
60
+		for lv in range(cycle)
61
+			let lv2 = ((lv + cycle - 1) % cycle)
62
+			let [rid, pid, gid2] = [s:synID(prefix, 'r', lv, id), s:synID(prefix, 'p', lv, id), s:synGroupID(prefix, 'Regions', lv2)]
63
+
64
+			if len(op) > 2
65
+				exe 'syn match '.s:synID(prefix, 'o', lv, id).' '.op.' containedin='.s:synID(prefix, 'r', lv, id).' contained'
66
+			endif
67
+
68
+			let real_contained = (lv == 0)? (contained? 'contained ' : '') : 'contained '
69
+			let real_containedin = (lv == 0)? s:concat([containedin, '@'.gid2]) : '@'.gid2
70
+			let real_contains = s:concat([contains_prefix, contains])
71
+			exe 'syn region '.rid.' matchgroup='.pid.' '.real_contained.'containedin='.real_containedin.' contains='.real_contains.' '.paren
72
+		endfor
73
+	endfor
74
+	for lv in range(cycle)
75
+		exe 'syn cluster '.s:synGroupID(prefix, 'Regions', lv).' contains='.join(map(range(len(conf.parentheses)), 's:synID(prefix, "r", lv, v:val)'), ',')
76
+		exe 'syn cluster '.s:synGroupID(prefix, 'Parentheses', lv).' contains='.join(map(range(len(conf.parentheses)), 's:synID(prefix, "p", lv, v:val)'), ',')
77
+		exe 'syn cluster '.s:synGroupID(prefix, 'Operators', lv).' contains='.join(map(range(len(conf.parentheses)), 's:synID(prefix, "o", lv, v:val)'), ',')
78
+	endfor
79
+	exe 'syn cluster '.prefix.'Regions contains='.join(map(range(cycle), '"@".s:synGroupID(prefix, "Regions", v:val)'), ',')
80
+	exe 'syn cluster '.prefix.'Parentheses contains='.join(map(range(cycle), '"@".s:synGroupID(prefix, "Parentheses", v:val)'), ',')
81
+	exe 'syn cluster '.prefix.'Operators contains='.join(map(range(cycle), '"@".s:synGroupID(prefix, "Operators", v:val)'), ',')
82
+	if has_key(conf, 'after') | for cmd in conf.after | exe cmd | endfor | endif
83
+endfun
84
+
85
+fun rainbow#syn_clear(config)
86
+	let conf = a:config
87
+	let prefix = conf.syn_name_prefix
88
+
89
+	for id in range(len(conf.parentheses))
90
+		for lv in range(conf.cycle)
91
+			let [rid, oid] = [s:synID(prefix, 'r', lv, id), s:synID(prefix, 'o', lv, id)]
92
+			exe 'syn clear '.rid
93
+			exe 'syn clear '.oid
94
+		endfor
95
+	endfor
96
+endfun
97
+
98
+fun rainbow#hi(config)
99
+	let conf = a:config
100
+	let prefix = conf.syn_name_prefix
101
+
102
+	for id in range(len(conf.parentheses))
103
+		for lv in range(conf.cycle)
104
+			let [pid, oid] = [s:synID(prefix, 'p', lv, id), s:synID(prefix, 'o', lv, id)]
105
+			let ctermfg = conf.ctermfgs[lv % len(conf.ctermfgs)]
106
+			let guifg = conf.guifgs[lv % len(conf.guifgs)]
107
+			let cterm = conf.cterms[lv % len(conf.cterms)]
108
+			let gui = conf.guis[lv % len(conf.guis)]
109
+			let hi_style = 'ctermfg='.ctermfg.' guifg='.guifg.(len(cterm) > 0 ? ' cterm='.cterm : '').(len(gui) > 0 ? ' gui='.gui : '')
110
+			exe 'hi '.pid.' '.hi_style
111
+			exe 'hi '.oid.' '.hi_style
112
+		endfor
113
+	endfor
114
+endfun
115
+
116
+fun rainbow#hi_clear(config)
117
+	let conf = a:config
118
+	let prefix = conf.syn_name_prefix
119
+
120
+	for id in range(len(conf.parentheses))
121
+		for lv in range(conf.cycle)
122
+			let [pid, oid] = [s:synID(prefix, 'p', lv, id), s:synID(prefix, 'o', lv, id)]
123
+			exe 'hi clear '.pid
124
+			exe 'hi clear '.oid
125
+		endfor
126
+	endfor
127
+endfun
128
+
... ...
@@ -0,0 +1,136 @@
1
+" Copyright 2013 LuoChen (luochen1990@gmail.com). Licensed under the Apache License 2.0.
2
+
3
+let s:rainbow_conf = {
4
+\	'guifgs': ['royalblue3', 'darkorange3', 'seagreen3', 'firebrick'],
5
+\	'ctermfgs': ['lightblue', 'lightyellow', 'lightcyan', 'lightmagenta'],
6
+\	'guis': [''],
7
+\	'cterms': [''],
8
+\	'operators': '_,_',
9
+\	'contains_prefix': 'TOP',
10
+\	'parentheses_options': '',
11
+\	'parentheses': ['start=/(/ end=/)/ fold', 'start=/\[/ end=/\]/ fold', 'start=/{/ end=/}/ fold'],
12
+\	'separately': {
13
+\		'*': {},
14
+\		'markdown': {
15
+\			'parentheses_options': 'containedin=markdownCode contained',
16
+\		},
17
+\		'lisp': {
18
+\			'guifgs': ['royalblue3', 'darkorange3', 'seagreen3', 'firebrick', 'darkorchid3'],
19
+\		},
20
+\		'haskell': {
21
+\			'parentheses': ['start=/(/ end=/)/ fold', 'start=/\[/ end=/\]/ fold', 'start=/\v\{\ze[^-]/ end=/}/ fold'],
22
+\		},
23
+\		'ocaml': {
24
+\			'parentheses': ['start=/(\ze[^*]/ end=/)/ fold', 'start=/\[/ end=/\]/ fold', 'start=/\[|/ end=/|\]/ fold', 'start=/{/ end=/}/ fold'],
25
+\		},
26
+\		'tex': {
27
+\			'parentheses_options': 'containedin=texDocZone',
28
+\			'parentheses': ['start=/(/ end=/)/', 'start=/\[/ end=/\]/'],
29
+\		},
30
+\		'vim': {
31
+\			'parentheses_options': 'containedin=vimFuncBody,vimExecute',
32
+\			'parentheses': ['start=/(/ end=/)/', 'start=/\[/ end=/\]/', 'start=/{/ end=/}/ fold'],
33
+\		},
34
+\		'xml': {
35
+\			'syn_name_prefix': 'xmlRainbow',
36
+\			'parentheses': ['start=/\v\<\z([-_:a-zA-Z0-9]+)(\s+[-_:a-zA-Z0-9]+(\=("[^"]*"|'."'".'[^'."'".']*'."'".'))?)*\>/ end=#</\z1># fold'],
37
+\		},
38
+\		'xhtml': {
39
+\			'parentheses': ['start=/\v\<\z([-_:a-zA-Z0-9]+)(\s+[-_:a-zA-Z0-9]+(\=("[^"]*"|'."'".'[^'."'".']*'."'".'))?)*\>/ end=#</\z1># fold'],
40
+\		},
41
+\		'html': {
42
+\			'parentheses': ['start=/\v\<((script|style|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'],
43
+\		},
44
+\		'lua': {
45
+\			'parentheses': ["start=/(/ end=/)/", "start=/{/ end=/}/", "start=/\\v\\[\\ze($|[^[])/ end=/\\]/"],
46
+\		},
47
+\		'perl': {
48
+\			'syn_name_prefix': 'perlBlockFoldRainbow',
49
+\		},
50
+\		'php': {
51
+\			'syn_name_prefix': 'phpBlockRainbow',
52
+\			'contains_prefix': '',
53
+\			'parentheses': ['start=/(/ end=/)/ containedin=@htmlPreproc contains=@phpClTop', 'start=/\[/ end=/\]/ containedin=@htmlPreproc contains=@phpClTop', 'start=/{/ end=/}/ containedin=@htmlPreproc contains=@phpClTop', '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 contains_prefix=TOP'],
54
+\		},
55
+\		'stylus': {
56
+\			'parentheses': ['start=/{/ end=/}/ fold contains=@colorableGroup'],
57
+\		},
58
+\		'css': 0,
59
+\		'sh': 0,
60
+\		'vimwiki': 0,
61
+\	}
62
+\}
63
+
64
+fun s:eq(x, y)
65
+	return type(a:x) == type(a:y) && a:x == a:y
66
+endfun
67
+
68
+fun s:gcd(a, b)
69
+	let [a, b, t] = [a:a, a:b, 0]
70
+	while b != 0
71
+		let t = b
72
+		let b = a % b
73
+		let a = t
74
+	endwhile
75
+	return a
76
+endfun
77
+
78
+fun s:lcm(a, b)
79
+	return (a:a / s:gcd(a:a, a:b)) * a:b
80
+endfun
81
+
82
+fun rainbow_main#gen_config(ft)
83
+	let g = exists('g:rainbow_conf')? g:rainbow_conf : {}
84
+	"echom 'g:rainbow_conf:' string(g)
85
+	let s = get(g, 'separately', {})
86
+	"echom 'g:rainbow_conf.separately:' string(s)
87
+	let dft_conf = extend(copy(s:rainbow_conf), g) | unlet dft_conf.separately
88
+	"echom 'default config options:' string(dft_conf)
89
+	let dx_conf = s:rainbow_conf.separately['*']
90
+	"echom 'default star config:' string(dx_conf)
91
+	let ds_conf = get(s:rainbow_conf.separately, a:ft, dx_conf)
92
+	"echom 'default separately config:' string(ds_conf)
93
+	let ux_conf = get(s, '*', ds_conf)
94
+	"echom 'user star config:' string(ux_conf)
95
+	let us_conf = get(s, a:ft, ux_conf)
96
+	"echom 'user separately config:' string(us_conf)
97
+	let af_conf = (s:eq(us_conf, 'default') ? ds_conf : us_conf)
98
+	"echom 'almost finally config:' string(af_conf)
99
+	if s:eq(af_conf, 0)
100
+		return 0
101
+	else
102
+		let conf = extend(extend({'syn_name_prefix': substitute(a:ft, '\v\A+(\a)', '\u\1', 'g').'Rainbow'}, dft_conf), af_conf)
103
+		let conf.cycle = (has('gui_running') || (has('termguicolors') && &termguicolors)) ? s:lcm(len(conf.guifgs), len(conf.guis)) : s:lcm(len(conf.ctermfgs), len(conf.cterms))
104
+		return conf
105
+	endif
106
+endfun
107
+
108
+fun rainbow_main#gen_configs(ft)
109
+	return filter(map(split(a:ft, '\v\.'), 'rainbow_main#gen_config(v:val)'), 'type(v:val) == type({})')
110
+endfun
111
+
112
+fun rainbow_main#load()
113
+	let b:rainbow_confs = rainbow_main#gen_configs(&filetype)
114
+	for conf in b:rainbow_confs
115
+		call rainbow#syn(conf)
116
+		call rainbow#hi(conf)
117
+	endfor
118
+endfun
119
+
120
+fun rainbow_main#clear()
121
+	if !exists('b:rainbow_confs') | return | endif
122
+	for conf in b:rainbow_confs
123
+		call rainbow#hi_clear(conf)
124
+		call rainbow#syn_clear(conf)
125
+	endfor
126
+	unlet b:rainbow_confs
127
+endfun
128
+
129
+fun rainbow_main#toggle()
130
+	if exists('b:rainbow_confs')
131
+		call rainbow_main#clear()
132
+	else
133
+		call rainbow_main#load()
134
+	endif
135
+endfun
136
+
... ...
@@ -0,0 +1,18 @@
1
+Rainbow Parentheses Improved                                     *rainbow*
2
+==========================================================================
3
+
4
+Commands:                                               *rainbow-commands*
5
+--------------------------------------------------------------------------
6
+
7
+*RainbowToggle*     ---  toggle this plugin on/off
8
+*RainbowToggleOn*   ---  toggle this plugin on
9
+*RainbowToggleOff*  ---  toggle this plugin off
10
+
11
+Configurations:                                           *rainbow-config*
12
+--------------------------------------------------------------------------
13
+
14
+*g:rainbow_active*  ---  1 to auto enable this plugin
15
+                         0 to enable it later via :RainbowToggle
16
+*g:rainbow_conf*    ---  https://github.com/luochen1990/rainbow#configure
17
+
18
+vim:tw=78:ts=8:ft=help:norl:
... ...
@@ -0,0 +1,12 @@
1
+" Copyright 2013 LuoChen (luochen1990@gmail.com). Licensed under the Apache License 2.0.
2
+
3
+if exists('s:loaded') || !(exists('g:rainbow_active') || exists('g:rainbow_conf')) | finish | endif | let s:loaded = 1
4
+
5
+command! RainbowToggle call rainbow_main#toggle()
6
+command! RainbowToggleOn call rainbow_main#load()
7
+command! RainbowToggleOff call rainbow_main#clear()
8
+
9
+if (exists('g:rainbow_active') && g:rainbow_active)
10
+	auto syntax * call rainbow_main#load()
11
+	auto colorscheme * call rainbow_main#load()
12
+endif
... ...
@@ -453,6 +453,12 @@ let g:rooter_patterns = ['.git', 'Makefile', 'builds/']
453 453
 let g:rooter_cd_cmd = 'lcd'
454 454
 let g:rooter_manual_only = 1
455 455
 
456
+" https://github.com/luochen1990/rainbow/
457
+let g:rainbow_conf = {
458
+\	'ctermfgs': ['lightblue', 'yellow', 'green', 'cyan', 'lightmagenta']
459
+\}
460
+let g:rainbow_active = 1 "set to 0 if you want to enable it later via :RainbowToggle
461
+
456 462
 " In some environments, Vim starts in replace mode:
457 463
 " https://superuser.com/questions/1284561/why-is-vim-starting-in-replace-mode
458 464
 " set t_u7=
459 465