在Vim中折叠正则表达式

时间:2012-09-23 11:10:31

标签: regex vim

我在写作时使用Pandoc,并在html代码中粘贴更复杂的表格。这可能会使文件看起来不整洁,我想使用Vim的foldexpr使用正则表达式折叠这些表元素。这个正则表达式:

<table\b[^>]*>(?:(?=([^<]+))\1|<(?!table\b[^>]*>))*?</table>

用于突出Sublime Text和BBEdit中的表格代码,但我似乎无法让它在Vim中工作(非常多我的选择编辑器)。

看着“Vim Scripting the Hardway”,我希望写一个这样的简单函数:

setlocal foldmethod = expr setlocal foldexpr = GetTableFold(v:lnum)

function! GetTableFold(lnum)
    if getline(a:lnum) =~? '\v<table\b[^>]*>(?:(?=([^<]+))\1|<(?!table\b[^>]*>))*?  </table>
    return '-1'
endif
return '0'
endfunction

为了隐藏我的文件中的表格元素,但它不起作用。当我尝试在Vim中进行简单搜索正则表达式时,我也得到一个“E64:?无所事事”错误。

非常欢迎任何想法!

1 个答案:

答案 0 :(得分:3)

你在做这件事的方式上遇到了一些问题。首先,你的正则表达式存在语法问题(Ingo指出)。另外,我认为你不太明白vim如何计算折叠水平。 Vim为文件中的每一行调用一次“GetTableFold”函数。然后返回该特定行的折叠级别。因为您没有除行号以外的上下文,所以您不能将该行与跨越多行的正则表达式匹配。相反,您必须手动计算您的线是否落在此范围内。

我有一段时间没有写过任何vimscript,所以这可能有点儿麻烦,但似乎在我试过的几个简单案例中起作用。至少它应该为你提供一个从哪里开始的基础。

function GetTableFold(lnum)
    let n = a:lnum
    while n > 0
        let currline = getline(n)
        let prevline = getline(n-1)
        if currline =~ '\v\<table\>|\<\/table\>'
            return '1'
        elseif currline =~ '\v^\s*$'
            " special case for blank lines
            return '-1'
        elseif prevline =~ '\v\<\/table\>'
            " special case for the line after </table>
            return '0'
        endif
        let n -= 1
    endwhile
    return '0'
endfunction

set foldmethod=expr
set foldexpr=GetTableFold(v:lnum)

这会产生一些讨厌的(合理的?)假设,例如你永远不会在同一行上有<table></table>。鉴于您只在Pandoc文件中放置复杂表的用例,我认为这是一个安全的假设。它不能很好地处理表中的表。如果你需要,你必须稍微调整一下。

相关问题