vim自定义c语法折叠

时间:2014-08-25 21:48:16

标签: c vim syntax folding

Vim支持基于语法的C代码折叠,效果很好。 但是,函数名称不是折叠的一部分,只是{和}之间的部分。

给出了这个示例代码:

static inline bool uFuzzyCompare(double p1, double p2)
{
    return (uAbs(p1 - p2) <= 0.000000000001 * uMin(uAbs(p1), uAbs(p2)));
}

static inline bool uFuzzyComparef(float p1, float p2)
{
    return (uAbsf(p1 - p2) <= 0.00001f * uMinf(uAbsf(p1), uAbsf(p2)));
}

static inline bool uFuzzyIsNull(double d)
{
    return uAbs(d) <= 0.000000000001;
}

static inline bool uFuzzyIsNullf(float f)
{
    return uAbs(f) <= 0.00001f;
}

这看起来像这样:

static inline bool uFuzzyCompare(double p1, double p2)
+--  3 lines: {----------------------------------------------------------------------------------------------------------------------------------------------------------------

static inline bool uFuzzyComparef(float p1, float p2)
+--  3 lines: {----------------------------------------------------------------------------------------------------------------------------------------------------------------

static inline bool uFuzzyIsNull(double d)
+--  3 lines: {----------------------------------------------------------------------------------------------------------------------------------------------------------------

static inline bool uFuzzyIsNullf(float f)
+--  3 lines: {----------------------------------------------------------------------------------------------------------------------------------------------------------------

我更喜欢这个:

+-- uFuzzyCompare(...) (5 lines)
+-- uFuzzyComparef(...) (5 lines)
+-- uFuzzyIsNull(...) (5 lines)
+-- uFuzzyIsNullf(...) (5 lines)

这意味着将函数声明包含在fold和空行中,并将函数名称显示为折叠文本。

这有可能吗? 也许使用foldmethod表达式,但我不知道在不编写完整的C语法分析器的情况下创建此表达式的好方法。 所以使用语法解析器是最好的,但我找不到任何配置选项。

的问候, 格哈德

2 个答案:

答案 0 :(得分:3)

这将帮助您顺利前进。它目前只折叠顶级功能。把它放在~/.vim/ftplugin/c.vim

function! CFold()
    if getline(v:lnum - 1)[0] ==# '}'
        return '<1'
    elseif getline(v:lnum + 1)[0] ==# '{'
        return '>1'
    endif
    return '='
endfunction

function! CFoldText()
    let line = getline(v:foldstart)
    let sub = substitute(line, '.*\<\(\w\+\)(.*).*', '\1(...)', 'g')
    return '+-- ' . sub . ' (' . (v:foldend - v:foldstart + 1) . ' lines)'
endfunction

setlocal foldmethod=expr
setlocal foldexpr=CFold()
setlocal foldtext=CFoldText()
setlocal fillchars-=fold:-

示例文本的输出

+-- uFuzzyCompare(...) (5 lines)
+-- uFuzzyComparef(...) (5 lines)
+-- uFuzzyIsNull(...) (5 lines)
+-- uFuzzyIsNullf(...) (5 lines)

这是如何运作的。当你将foldmethod设置为expr时,vim使用foldexpr中的表达式来确定它应该如何折叠。我正在做的就是检查第一列中当前后面的行是否包含{,如果是,我们将折叠级别设置为>1,表示开始第1级的折叠。在}行结束。 <1表示结束了1级的折叠。

要设置折叠文本,我们只需提取函数并用...替换参数(对于参数为多行的行,这可能会中断)。然后我们返回一个格式很好的字符串。 v:foldstartv:foldend是设置的变量,表示折叠开始和结束的哪一行。

从fillchars中删除fold:-会删除折叠文本后的破折号。

相关帮助页面:h 'foldmethod':h foldexpr:h foldtext:h 'fillchars'

答案 1 :(得分:0)

正确处理折叠并非易事。

例如,支持K&amp; R缩进样式需要一些工作。

if (a_or_b) {
    if (foo) {
       a1();
    } else if (bar) {
       a2();
    } else {
       a3();
    }
} else {
   b();
}

智能地/好地折叠像do {...} while(cond);这样的东西使事情变得更加复杂(因为我们需要支持嵌套的上下文)

do
{
   act();
   do {
      a2();
   } 
   while (inner);
} 
while(outer)
;

无论如何,我已经开发出一个在合理的时间内尽力而为的解决方案:VimFold4C - 但是我还不支持do { ... } while(cond);,也没有利用在开头出现的评论折叠区:(。