【问题标题】:vim customize c syntax foldingvim 自定义 c 语法折叠
【发布时间】:2014-08-25 21:48:15
【问题描述】:

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)

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

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

问候, 格哈德

【问题讨论】:

    标签: c vim syntax folding


    【解决方案1】:

    这将使您顺利上路。它目前只折叠顶级功能。把这个放在~/.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 中的表达式来确定它应该如何折叠。我所做的只是检查当前后的行是否在第一列中包含{,如果确实如此,我们将折叠级别设置为&gt;1,表示开始级别1的折叠。它结束在行}&lt;1 表示结束第 1 层的折叠。

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

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

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

    【讨论】:

      【解决方案2】:

      正确处理折叠并不是那么简单。

      例如,支持 K&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);,我也不利用出现在折叠区域开头的 cmets :( .

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-23
        • 1970-01-01
        • 2013-02-11
        • 1970-01-01
        • 2010-10-22
        • 2015-11-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多