tags:

views:

57

answers:

2

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

+4  A: 
fun! DoStuff(word)
    exec 'syntax match Error /\<'.a:word.'\>/ contained'
endf
Mykola Golubyev
Awesome, thanks (ps: I edited the answer because I accidentally clicked the "down vote" arrow on my way to the "accept" check, and I couldn't change that to an upvote without editing).
David Wolever
+1  A: 

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!

Al