From ae0ef43377aad7d7e2e3c0ab7da80759263cad34 Mon Sep 17 00:00:00 2001 From: Virginia Senioria <91khr@users.noreply.github.com> Date: Sat, 4 Dec 2021 19:01:34 +0800 Subject: [PATCH 1/3] style: trim space in parenthesis keys to avoid 'contained' duplicate and wrapped the long line --- autoload/rainbow.vim | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/autoload/rainbow.vim b/autoload/rainbow.vim index 10551c5..47198d8 100644 --- a/autoload/rainbow.vim +++ b/autoload/rainbow.vim @@ -12,19 +12,23 @@ endfun fun s:resolve_parenthesis_with(init_state, p) let [paren, contained, containedin, contains_prefix, contains, op] = a:init_state - 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 + 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 let ls = split(p, '\v%(%(start|step|end)\=(.)%(\1@!.)*\1[^ ]*|\w+%(\=[^ ]*)?) ?\zs', 0) for s in ls - let [k, v] = [matchstr(s, '^[^=]\+\ze\(=\|$\)'), matchstr(s, '^[^=]\+=\zs.*')] + let [k, v] = [s:trim(matchstr(s, '^[^=]\+\ze\(=\|$\)')), s:trim(matchstr(s, '^[^=]\+=\zs.*'))] if k == 'step' - let op = s:trim(v) + let op = v elseif k == 'contains_prefix' - let contains_prefix = s:trim(v) + let contains_prefix = v elseif k == 'contains' - let contains = s:concat([contains, s:trim(v)]) + let contains = s:concat([contains, v]) elseif k == 'containedin' - let containedin = s:concat([containedin, s:trim(v)]) + let containedin = s:concat([containedin, v]) elseif k == 'contained' let contained = 1 else From 1f384f73df0b3a0611c270209a70ac37720a6a2c Mon Sep 17 00:00:00 2001 From: Virginia Senioria <91khr@users.noreply.github.com> Date: Sat, 4 Dec 2021 19:05:22 +0800 Subject: [PATCH 2/3] feature: bundle the parentheses into clusters and add shortcut for them in the parentheses config and fix the warning when contains_prefix is empty --- autoload/rainbow.vim | 62 ++++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/autoload/rainbow.vim b/autoload/rainbow.vim index 47198d8..f8fc002 100644 --- a/autoload/rainbow.vim +++ b/autoload/rainbow.vim @@ -11,7 +11,7 @@ fun s:concat(strs) endfun fun s:resolve_parenthesis_with(init_state, p) - let [paren, contained, containedin, contains_prefix, contains, op] = a:init_state + let [paren, contained, containedin, contains_prefix, contains, op, cluster] = a:init_state let p = (type(a:p) == type([])) ? \ ((len(a:p) == 3) ? \ printf('start=#%s# step=%s end=#%s#', a:p[0], op, a:p[-1]) : @@ -31,25 +31,27 @@ fun s:resolve_parenthesis_with(init_state, p) let containedin = s:concat([containedin, v]) elseif k == 'contained' let contained = 1 + elseif k == 'cluster' + let cluster = s:concat([cluster, v]) else let paren .= s endif endfor - let rst = [paren, contained, containedin, contains_prefix, contains, op] + let rst = [paren, contained, containedin, contains_prefix, contains, op, cluster] "echom json_encode(rst) return rst endfun fun s:resolve_parenthesis_from_config(config) - return s:resolve_parenthesis_with(['', 0, '', a:config.contains_prefix, '', a:config.operators], a:config.parentheses_options) + return s:resolve_parenthesis_with(['', 0, '', a:config.contains_prefix, '', a:config.operators, ''], a:config.parentheses_options) endfun fun s:synID(prefix, group, lv, id) return a:prefix.'_lv'.a:lv.'_'.a:group.a:id endfun -fun s:synGroupID(prefix, group, lv) - return a:prefix.a:group.'_lv'.a:lv +fun s:synGroupID(prefix, group, lv, cluster) + return a:prefix.a:group.'_lv'.a:lv.'_'.a:cluster endfun fun rainbow#syn(config) @@ -59,31 +61,53 @@ fun rainbow#syn(config) let glob_paran_opts = s:resolve_parenthesis_from_config(conf) let b:rainbow_loaded = cycle + let cluster_list = {} for id in range(len(conf.parentheses)) - let [paren, contained, containedin, contains_prefix, contains, op] = s:resolve_parenthesis_with(glob_paran_opts, conf.parentheses[id]) + let [paren, contained, containedin, contains_prefix, contains, op, cluster] = s:resolve_parenthesis_with(glob_paran_opts, conf.parentheses[id]) + + let cluster = split(cluster, ',') ?? ['default'] + for k in cluster + let cluster_list[k] = get(cluster_list, k, [])->add(id) + endfor + let containedin_items = split(containedin, ',') + let upcluster = filter(copy(containedin_items), 'v:val =~ "#.*"')->map('v:val[1:]') ?? cluster + let containedin = filter(containedin_items, 'v:val !~ "#.*"')->join(',') + let contains_items = (contains_prefix != '' ? [contains_prefix] : []) + split(contains, ',') + for lv in range(cycle) - let lv2 = ((lv + cycle - 1) % cycle) - let [rid, pid, gid2] = [s:synID(prefix, 'r', lv, id), s:synID(prefix, 'p', lv, id), s:synGroupID(prefix, 'Regions', lv2)] + let uplv = ((lv + cycle - 1) % cycle) + let [rid, pid, upid] = [s:synID(prefix, 'r', lv, id), s:synID(prefix, 'p', lv, id), + \ mapnew(upcluster, '"@".s:synGroupID(prefix, "Regions", uplv, v:val)')->join(',')] if len(op) > 2 exe 'syn match '.s:synID(prefix, 'o', lv, id).' '.op.' containedin='.s:synID(prefix, 'r', lv, id).' contained' endif let real_contained = (lv == 0)? (contained? 'contained ' : '') : 'contained ' - let real_containedin = (lv == 0)? s:concat([containedin, '@'.gid2]) : '@'.gid2 - let real_contains = s:concat([contains_prefix, contains]) - exe 'syn region '.rid.' matchgroup='.pid.' '.real_contained.'containedin='.real_containedin.' contains='.real_contains.' '.paren + let real_containedin = (lv == 0)? s:concat([containedin, upid]) : upid + let real_contains = mapnew(contains_items, + \ 'v:val =~ "#.*" ? "@".s:synGroupID(prefix, "Regions", uplv, v:val[1:]) : v:val') + \ ->flatten()->join(',') + let real_contains = real_contains != '' ? ' contains='.real_contains : '' + exe 'syn region '.rid.' matchgroup='.pid.' '.real_contained.'containedin='.real_containedin.real_contains.' '.paren endfor endfor - for lv in range(cycle) - exe 'syn cluster '.s:synGroupID(prefix, 'Regions', lv).' contains='.join(map(range(len(conf.parentheses)), 's:synID(prefix, "r", lv, v:val)'), ',') - exe 'syn cluster '.s:synGroupID(prefix, 'Parentheses', lv).' contains='.join(map(range(len(conf.parentheses)), 's:synID(prefix, "p", lv, v:val)'), ',') - exe 'syn cluster '.s:synGroupID(prefix, 'Operators', lv).' contains='.join(map(range(len(conf.parentheses)), 's:synID(prefix, "o", lv, v:val)'), ',') + + for [kind, abbr] in [['Regions', 'r'], ['Parentheses', 'p'], ['Operators', 'o']] + for [cluster, ids] in items(cluster_list) + for lv in range(cycle) + exe 'syn cluster '.s:synGroupID(prefix, kind, lv, cluster).' contains='. + \ mapnew(ids, 's:synID(prefix, abbr, lv, v:val)')->join(',') + endfor + exe 'syn cluster '.prefix.kind.'_'.cluster.' contains='. + \ map(range(cycle), '"@".s:synGroupID(prefix, kind, v:val, cluster)')->join(',') + endfor + exe 'syn cluster '.prefix.kind.' contains='.map(keys(cluster_list), 'prefix.kind."_".v:val')->join(',') + endfor + + for cmd in conf->get('after', []) + exe cmd endfor - exe 'syn cluster '.prefix.'Regions contains='.join(map(range(cycle), '"@".s:synGroupID(prefix, "Regions", v:val)'), ',') - exe 'syn cluster '.prefix.'Parentheses contains='.join(map(range(cycle), '"@".s:synGroupID(prefix, "Parentheses", v:val)'), ',') - exe 'syn cluster '.prefix.'Operators contains='.join(map(range(cycle), '"@".s:synGroupID(prefix, "Operators", v:val)'), ',') - if has_key(conf, 'after') | for cmd in conf.after | exe cmd | endfor | endif endfun fun rainbow#syn_clear(config) From e03be4f2b6ac4b02ce4e807ac7f3286ce8c1a713 Mon Sep 17 00:00:00 2001 From: Virginia Senioria <91khr@users.noreply.github.com> Date: Mon, 27 Dec 2021 10:17:47 +0800 Subject: [PATCH 3/3] doc: the cluster feature trimmed some trailing spaces documented some commands --- README.md | 18 +++++++++++++----- README_zh.md | 12 +++++++++--- doc/rainbow.txt | 2 ++ 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 19ef974..974355d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Rainbow Parentheses Improved +Rainbow Parentheses Improved === > help you read complex code by showing diff level of parentheses in diff color !! @@ -107,7 +107,7 @@ let g:rainbow_conf = { - 'ctermfgs': a list of `ctermfg` (`:h highlight-ctermfg`) - 'cterms': a list of `cterm` (`:h highlight-cterm`) - '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`. -- '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. +- 'parentheses': a list of parentheses definitions, see [syntax-for-parentheses-definition](). - '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. - '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). - 'syn_name_prefix': add a prefix to name of the syntax definition, this option is often used to solve [3rd-party-plugin-compatibility]() problems. @@ -116,10 +116,18 @@ let g:rainbow_conf = { 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+). +#### Syntax for `parentheses` definition + +A parentheses definition defines a kind of parentheses and contains parts like `start=/(/`, `step=/,/`, `stop=/)/`, `fold`, `contained`, `containedin=someSynNames`, `contains=@Spell`, and `cluster=someNames`, see `:h syntax` for more details for parts except `step` and `cluster`. The content of `step` is a regex matching the operators within the parentheses that should be highlighted; `cluster` is a comma-separated list (just like `containein`) specifying the parenthesis clusters the kind of parentheses, whose default value is `default`, and `default` can also be explicitly specified in the `cluster` list. + +Parenthesis clusters can be referred to in `contains` and `containedin` with the form `#name`, thus the nesting parentheses would be highlighted strictly according to their nesting levels. If you want to use top-level highlight for some parentheses, specify the syntax cluster names rainbow generated for the parentheses clusters instead. + User Command ------------ -- **:RainbowToggle** --you can use it to toggle this plugin. +- **:RainbowToggle** -- you can use it to toggle this plugin on and off. +- **:RainbowToggleOn** -- turn this plugin on. +- **:RainbowToggleOff** -- turn this plugin off 3rd Party Plugin Compatibility ------------------------------ @@ -184,6 +192,6 @@ nnoremap :exec 'syn list '.synIDattr(synID(line('.'), col('.'), 0), 'name') Move your cursor to a parentheses and press the keys to use them. ------------------------------------------------------------------ -**Rate this script if you like it, and I'll appreciate it and improve this plugin for you because of your support! +**Rate this script if you like it, and I'll appreciate it and improve this plugin for you because of your support!** -Just go to [this page](http://www.vim.org/scripts/script.php?script_id=4176) and choose `Life Changing` and click `rate`** +**Just go to [this page](http://www.vim.org/scripts/script.php?script_id=4176) and choose `Life Changing` and click `rate`** diff --git a/README_zh.md b/README_zh.md index a5c7d86..45a4655 100644 --- a/README_zh.md +++ b/README_zh.md @@ -17,7 +17,7 @@ - 更快速和流畅的体验。 - 简短,高质量,并且易读的源代码。 -- 现在的版本将不再限制括号的嵌套层数。 +- 现在的版本将不再限制括号的嵌套层数。 - 现在你可以分别自定义图形界面下和终端上所使用的各种括号颜色。 - 现在你可以自定义括号的形式,不过在这之前你最好了解vim脚本的正则表达式。 - 现在你甚至可以为不同类型的文件设定不同的配置。 @@ -26,7 +26,7 @@ - 现在采用json风格的配置文件,更加可读,更易于进行高级配置。 - 最后但并非不重要的一点是,如你所见,现在增加了中文说明。 -### 以下是本插件所参考的旧版本: +### 以下是本插件所参考的旧版本: - http://www.vim.org/scripts/script.php?script_id=1561 (Martin Krischik) - http://www.vim.org/scripts/script.php?script_id=3772 (kien) @@ -94,10 +94,16 @@ let g:rainbow_active = 1 "0 if you want to enable it later via :RainbowToggle - 'ctermfgs': 一个`ctermfg`的列表 (`:h highlight-ctermfg`), 即终端下的括号颜色 - 'cterms': 一个`cterm`的列表 (`:h highlight-cterm`) - 'operators': 描述你希望哪些运算符跟着与它同级的括号一起高亮(注意:留意需要转义的特殊字符,更多样例见[这里](https://github.com/luochen1990/rainbow/issues/3), 你也可以读[vim帮助 :syn-pattern](http://vimdoc.sourceforge.net/htmldoc/syntax.html#:syn-pattern)) -- 'parentheses': 一个关于括号定义的列表, 每一个括号的定义包含形如以下的部分: `start=/(/`, `step=/,/`, `stop=/)/`, `fold`, `contained`, `containedin=someSynNames`, `contains=@Spell`. 各个部分具体含义可参考 `:h syntax`, 其中 `step` 为本插件的扩展定义, 表示括号中间需要高亮的运算符. +- 'parentheses': 一个关于括号定义的列表, 其中的每个项目描述了一种括号, 具体的语法见[parentheses的语法]() - 'separately': 针对文件类型(由&ft决定)作不同的配置,未被单独设置的文件类型使用`*`下的配置,值为`0`表示仅对该类型禁用插件,值为`"default"`表示使用针对该类型的默认兼容配置 (注意, 默认兼容配置可能随着该插件版本的更新而改变, 如果你不希望它改变, 那么你应该将它拷贝一份放到你的vimrc文件里). - 省略某个字段以使用默认设置 +#### `parentheses`的语法 + +每一种括号的定义包含形如以下的部分: `start=/(/`, `step=/,/`, `stop=/)/`, `fold`, `contained`, `containedin=someSynNames`, `contains=@Spell`, `cluster=someNames`. 其中, `start`, `stop`, `fold`, `contained`, `containedin` 和 `contains` 的具体含义可参考 `:h syntax`; `step` 和 `cluster` 为本插件的扩展定义. `step` 是一个正则, 匹配括号中间需要高亮的运算符. `cluster` 是一个用逗号分隔的列表 (和 `containedin` 类似), 指定了这种括号所属的括号组, 默认的括号组名称为 `default`, 也可以将它显式放在括号组名称的列表中. + +在 `contains` 和 `containein` 中可以用 `#name` 的形式引用一个括号组, 这样相互嵌套的括号就会严格按照嵌套层次来高亮. 如果想要在某种或者某组括号里使用顶层的高亮, 可以使用为括号组生成的语法元素的名字. + ------------------------------------------------------------------- **最后,如果你喜欢这个插件,给它一个评价,我会心存感激,并且因为你的肯定继续改进这个插件!(从[该页面](http://www.vim.org/scripts/script.php?script_id=4176)下方,选择`Life Changing`选项,然后点击`rate`)** diff --git a/doc/rainbow.txt b/doc/rainbow.txt index 3b14327..cb8b166 100644 --- a/doc/rainbow.txt +++ b/doc/rainbow.txt @@ -1,6 +1,8 @@ Rainbow Parentheses Improved *rainbow* ========================================================================== +Detailed document is in the README. + Commands: *rainbow-commands* --------------------------------------------------------------------------