我是编写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;不在脚本上下文中
出了什么问题?
答案 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。但这很麻烦,这里不需要(因为自动加载是正确的解决方案),它也向其他开发人员发送错误的信号(折叠函数不是稳定和可重用的)。