あなたの質問に答えるために:call()
マニュアルののプロトタイプはcall({func}, {arglist} [, {dict}])
です。{arglist}
引数は、引数のリストではなく、文字通りListオブジェクトである必要があります。つまり、次のように記述する必要があります。
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
です。このため、通常、クラス属性は実際に苦労する価値はありません。
さて、これはあなたに思考のためのいくつかの食べ物を与えるのに十分でなければなりません。
最初のコードスニペットに戻ると、改善の余地がある2つの詳細があります。
normal gvd
古い選択を削除する必要normal "xp
はなく、最初に削除しなくても置き換えられます
- の
call setreg('x', [lines], type)
代わりに使用してくださいlet @x = [lines]
。これにより、レジスタのタイプが明示的に設定されx
ます。それ以外の場合は、x
すでに正しいタイプ(つまり、文字単位、行単位、またはブロック単位)に依存しています。
dict
キーワードは必要ありません。これは「クラスメソッド」に適用されます。を参照してください:h numbered-function
。