在vim中调用脚本本地函数发出错误?

时间:2017-09-19 11:31:08

标签: vim centos7

我是编写vim插件和vimscripting的新学习者,并尝试使用以下自定义函数自定义我的插件来折叠我的代码文件。

setlocal foldmethod=indent
setlocal foldmethod=expr
setlocal foldexpr=<SID>FoldFunction(v:lnum)

function! s:GetNextNonBlankLine(lnum)
    let numlines = line('$')
    let current = a:lnum + 1

    while current <= numlines
        if getline(current) =~? '\v\S'
            return current
        endif

        let current += 1
    endwhile

    return -2
endfunction

function! s:FindIndentLevel(lnum)
    return indent(a:lnum) / &shiftwidth
endfunction

function! s:FoldFunction(lnum)
    if getline(a:lnum) =~? '\v^\s*$'
        return '-1'
    endif
    let this_indent = <SID>FindIndentLevel(a:lnum)
    let next_indent = <SID>FindIndentLevel(<SID>GetNextNonBlankLine(a:lnum))

    if next_indent == this_indent
        return this_indent
    elseif next_indent < this_indent
        return this_indent
    elseif next_indent > this_indent
        return '>' . next_indent
    endif
endfunction

如果我删除脚本本地前缀(s :)然后它工作正常但许多人建议将其转换为脚本本地函数,因为不了解全局函数范围。

所以我重写了它,但它给出了以下错误:

  

E81:使用&lt; SID&gt;不在脚本上下文中

出了什么问题?

1 个答案:

答案 0 :(得分:2)

是的,可以更好地避免全局功能,特别是如果您将插件分发给其他人。在您当地的Vim设置中,可能可以避免名称冲突,但您永远不会了解其他人。

不幸的是,Vim只在映射和命令中自动处理脚本本地函数(即<SID>前缀),而不是分配给选项(如此处的'foldexpr')。这是Vim的缺点。

一个简单的解决方法是使用自动加载脚本。也就是说,将:function定义移动到(例如)~/.vim/autoload/FoldUtil.vim,并重命名该函数:

function! FoldUtil#FoldFunction(...)

然后,在你的脚本中,你就是这样:

setlocal foldmethod=indent
setlocal foldmethod=expr
setlocal foldexpr=FoldUtil#FoldFunction(v:lnum)

通过这种方式,您还可以获得自动加载的所有其他好处:大型脚本仅获取一次;你只执行上述3个命令来启用新的折叠方法。

请注意,您可以导出脚本的ID;然后,您可以手动将ID转换为<SNR>NNN_代表的<SID>。这将允许保持函数script-local。但这很麻烦,这里不需要(因为自动加载是正确的解决方案),它也向其他开发人员发送错误的信号(折叠函数不是稳定和可重用的)。