我在 Vim 中有一个插件,我不喜欢其中单个函数的行为。但是,打开拉取请求并不是一个案例,而更像是一个扩展。
我知道,一旦新定义出现在前一个定义之后,就可以通过使用 bang 作为后缀来覆盖函数。但是,如果此方法的作用域为插件中的脚本,我该怎么做呢?
我无法在_Vim_s帮助中找到提示,也无法通过请求搜索引擎找到提示。任何知道这个话题的人,至少如果他可以说这根本不可能的话。
举个小例子:
plugin/autoload/plugin.vim
...
function! s:foo() {
// behavior I would like to adjust
}
...
~/.vimrc
function! foo() {
// the "correct" behavior
}
感谢您的任何帮助!
实际上这是可能的。但正如@romainl所说,您最好向插件维护者建议您的补丁或要求更改点。
关于如何。
首先,您需要确定此自动加载插件的脚本编号。假设:scriptname
说它是 210。为了自动执行此操作,我的库插件中有一个lh#askvim#scriptid()
函数来完成这项工作 - 请参阅答案末尾的当前定义。
然后,要覆盖 s:foo()
函数,您需要为
function! <SNR>210_Foo()
new definition
endfunction
(我刚刚用 vim 8.0-1157 测试过它(
IOW,我们可以覆盖脚本本地函数。但是,我还没有找到如何在不引用其s:
字典的情况下直接覆盖脚本局部变量。我们可以将 setter/getter 函数注入到特定变量或返回本地s:
字典的函数中。
lh#askvim#scriptid()
当前定义如下
" Function: lh#askvim#execute(command) {{{3
" @since Version 4.0.0
if exists('*execute')
function! lh#askvim#execute(command) abort
return split(execute(a:command), "n")
endfunction
else
function! lh#askvim#execute(command) abort
return s:beware_running_through_client_server ? [] : split(lh#askvim#exe(a:command), "n")
endfunction
endif
" Function: lh#askvim#scriptnames() {{{3
function! lh#askvim#scriptnames() abort
let scripts = lh#askvim#execute('scriptnames')
let s:scripts = map(copy(scripts), 'split(v:val, "\v:=\s+")')
call lh#list#map_on(s:scripts, 1, 'fnamemodify(v:val, ":p")')
return s:scripts
endfunction
" Function: lh#askvim#scriptid(name) {{{3
function! lh#askvim#scriptid(name, ...) abort
let last_change = get(a:, 1, 0)
if last_change || !exists('s:scripts')
call lh#askvim#scriptnames()
endif
let matches = filter(copy(s:scripts), 'v:val[1] =~ a:name')
if len(matches) > 1
throw "Too many scripts match `".a:name."`: ".string(matches)
elseif empty(matches)
if last_change
throw "No script match `".a:name."`"
else
return lh#askvim#scriptid(a:name, 1)
endif
endif
return matches[0][0]
endfunction
这是不可能的。
s:foo()
的作用域为其所属的脚本(请参阅:help s:
(,因此无法从其他任何位置访问它。
- 分叉它。
- 对叉子进行所需的更改。
- 使用您的叉子而不是原始叉子。
- 请考虑提交拉取请求。