views:

255

answers:

2

First, I'll show the specific problem I'm having, but I think the problem can be generalized.

I'm working with a language that has explicit parenthesis syntax (like Lisp), but has keywords that are only reserved against the left paren. Example:

(key key)

the former is a reserved word, but the latter is a reference to the variable named "key"

Unfortunately, I find highlighting the left paren annoying, so I end up using

syn keyword classification key

instead of

syn keyword classification (key

but the former triggers on the variable uses as well.

I'd take a hack to get around my problem, but I'd be more interested in a general method to highlight just a subset of a given match.

A: 

There does appear to be some capability for layered highlighting, as seen here: http://stackoverflow.com/questions/773554/highlighting-matches-in-vim-over-an-inverted-pattern
which gives ex commands

:match myBaseHighlight /foo/
:2match myGroup /./

I haven't been able to get anything like that to work in my syntax files, though. I tried something like:

syn match Keyword "(key"
syn match Normal "("

The highlighting goes to Normal or Keyword over the whole bit depending on what gets picked up first (altered by arrangement in the file)

Vim soundly rejected using "2match" as a keyword after "syn".

Chad Wellington
`2match` is simply a variant of the `match` command, with a lower priority. It's completely unrelated to `syn match`. `:match` and related commands/functions are used to highlight a pattern in the current window, regardless of buffer. Until Vim 7, there was only the `match` command. In Vim 7, it gained `2match` and `3match`. Patch 7.1.040 added the `clearmatches()`, `getmatches()`, `matchadd()`, `matchdelete()`, and `setmatches()` functions which allow for essentially unlimited match patterns.
jamessan
+3  A: 

Using syn keyword alone for this situation doesn't work right because you want your highlighting to be more aware of the surrounding syntax. A combination of syn region, syn match, and syn keyword works well.

hi link lispFuncs Function
hi link lispFunc Identifier
hi link sExpr Statement

syn keyword lispFuncs key foo bar contained containedin=lispFunc
syn match lispFunc "(\@<=\w\+" contained containedin=sExpr contains=lispFuncs
syn region sExpr matchgroup=Special start="(" end=")" contains=sExpr,lispFuncs

The above will only highlight key, foo, and bar using the Function highlight group, only if they're also matched by lispFunc.

If there are any words other than key, foo, and bar which come after a (, they will be highlighted using the Identifier highlight group. This allows you to distinguish between standard function names and user-created ones.

The ( and ) will be highlighted using the Special highlight group, and anything inside the () past the first word will be highlighted using the Statement highlight group.

jamessan