回答您的问题:call()
手册中的原型为call({func}, {arglist} [, {dict}])
; 该{arglist}
参数必须是名副其实的列表对象,而不是参数列表。也就是说,您必须这样编写:
let @x = call(a:functionToExecute, [GetSelectedText()])
这假定a:functionToExecute
是Funcref(请参阅:help Funcref
)或函数的名称(例如,字符串,例如'Type1ProcessString'
)。
现在,这是一项强大的功能,可为Vim提供类似LISP的质量,但您可能很少像上面那样使用它。如果a:functionToExecute
是字符串,即函数的名称,则可以执行以下操作:
function! Wrapper(functionToExecute)
" ...
let s:processing = function(a:functionToExecute)
let @x = s:processing(GetSelectedText())
" ...
endfunction
然后使用函数名称调用包装器:
call Wrapper('Type1ProcessString')
另一方面,如果a:functionToExecute
是Funcref,则可以直接调用它:
function! Wrapper(functionToExecute)
" ...
let @x = a:functionToExecute(GetSelectedText())
" ...
endfunction
但是您需要这样调用包装器:
call Wrapper(function('Type1ProcessString'))
您可以使用来检查功能是否存在exists('*name')
。这使得以下小技巧成为可能:
let s:width = function(exists('*strwidth') ? 'strwidth' : 'strlen')
例如,strwidth()
如果Vim足够新,可以使用内置函数,然后回退到strlen()
其他函数(我并不是说这样的回退是有意义的;我只是说可以做到)。:)
使用字典函数(请参阅:help Dictionary-function
参考资料),您可以定义类似于类的东西:
let g:MyClass = {}
function! g:MyClass.New(...)
let newObj = copy(self)
if a:0 && type(a:1) == type({})
let newObj._attributes = deepcopy(a:1)
endif
if exists('*MyClassProcess')
let newObj._process = function('MyClassProcess')
else
let newObj._process = function('s:_process_default')
endif
return newObj
endfunction
function! g:MyClass.getFoo() dict
return get(get(self, '_attributes', {}), 'foo')
endfunction
function! g:MyClass.setFoo(val) dict
if !has_key(self, '_attributes')
let self._attributes = {}
endif
let self._attributes['foo'] = a:val
endfunction
function! g:MyClass.process() dict
call self._process()
endfunction
function! s:_process_default()
echomsg 'nothing to see here, define MyClassProcess() to make me interesting'
endfunction
然后,您将实例化这样的对象:
let little_object = g:MyClass.New({'foo': 'bar'})
并调用其方法:
call little_object.setFoo('baz')
echomsg little_object.getFoo()
call little_object.process()
您还可以具有类属性和方法:
let g:MyClass.__meaning_of_life = 42
function g:MyClass.GetMeaningOfLife()
return get(g:MyClass, '__meaning_of_life')
endfunction
(请注意,dict
此处不需要)。
编辑: 子类化是这样的:
let g:MySubclass = copy(g:MyClass)
call extend(g:MySubclass, subclass_attributes)
这里的微妙之处是使用copy()
代替deepcopy()
。这样做的原因是能够通过引用访问父类的属性。这是可以实现的,但是它非常脆弱,正确处理绝非易事。另一个潜在的问题是此类子类is-a
与合并has-a
。由于这个原因,类属性通常并不值得。
好的,这应该足以让您思考。
回到您的原始代码段,有两个可以改进的细节:
- 您无需
normal gvd
删除旧选择,normal "xp
即使您不先杀死它也将替换它
- 使用
call setreg('x', [lines], type)
代替let @x = [lines]
。这将显式设置寄存器的类型x
。否则,您将依赖于x
已经具有正确的类型(即,字符,行或块)。
dict
关键字。这适用于您的“类方法”。请参阅:h numbered-function
。