Vim: define syntax rules within functions?
I'd like to dynamically create syntax rules inside a function. For example, something like:
fun! DoStuff(word)
syntax match Error 开发者_运维百科'\<'.word.'\>' contained
... other stuff ...
endf
But, apparently* that doesn't work. So… How can I do it?
*: Vim script is still voodoo, as far as I'm concerned
fun! DoStuff(word)
exec 'syntax match Error /\<'.a:word.'\>/ contained'
endf
The reason you've been having problems isn't that syn match
can't be used in a function, it's that when it's used in the way you've described, it is entered literally. I'm not sure what the details are of the implementation, but I'd expect it to treat the pattern as \<
(delimited by quotation marks) and then it would have some unrecognised strings at the end. It won't treat the .
as a concatenation operator. Therefore, what you have to do (as Mykola Golubyev correctly pointed out), you have to create the command as one long string:
'syntax match Error /\<' . a:word . '\>/ contained'
which, if the argument is foobar gives:
'syntax match Error /\<foobar\>/ contained'
and then you have to use exec
to actually run that command.
An aside (but quite an important one in my opinion)...
If you're simply adding \<
and \>
around the word, use syn keyword
instead: the \<
and \>
are implied and the matcher is much faster (which can make a difference to the responsiveness of vim if you have a lot of keywords).
You could simply use a command in that case (although this wouldn't work if you're trying to do something more complicated):
:command! -nargs=1 DoStuff syn keyword Error <args> contained
:DoStuff MyKeyword
If you need to use a function:
function! DoStuff(word)
exec 'syntax keyword Error ' . a:word . ' contained'
endfunction
For more information, there are some useful documents here:
:help :syn-keyword
:help :syn-match
:help :command
:help :command-nargs
:help :function
:help :exec
As a really random aside, a little known vim fact is that you can fractionally shorten the match command as exec
automatically adds spaces between arguments, so:
exec 'syntax keyword Error ' . a:word . ' contained'
becomes
exec 'syntax keyword Error' a:word 'contained'
... but it's probably more readable the first way!
精彩评论