2

我在编写时使用 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: ? follow nothing”错误。

任何想法都会非常受欢迎!

4

1 回答 1

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 文件的用例,我认为这是一个安全的假设。它不能很好地处理表中的表。如果你需要,你将不得不稍微调整一下。

于 2012-09-23T13:08:36.033 回答