Question

I have a custom config that involves the following syntax:

  • key=value
  • $(var) represents a variable

The $(var) part can appear in both key and value, i.e. message="hello $(FirsName) $(LastName)". The value part must be surrounded by double quote " if it contains space characters.

I want to match key, value and $(var) and highlight them separately in vim.

Here is what in my vim syntax file:

syn match configValue "\(\S\+=\)\@<=\"[^\"]*\"\|\(\S\+=\)\@<=\S\+"
syn match configKey "^\s*[a-zA-Z0-9_.]\+\(\s*=\)\@="
syn match configVar "\$(.*)"

The code successfully matches configValue and configKey, but not configVar if it is within key=value. This is ruled by the syntax match priority (h:syn-priority):

  1. When multiple Match or Region items start in the same position, the item defined last has priority.
  2. A Keyword has priority over Match and Region items.
  3. An item that starts in an earlier position has priority over items that start in later positions.

Rule 3 gives the other two matches higher priority than that of configVar.

My problem is that, how to match the three patterns separately, with configVar having the highest priority?

Était-ce utile?

La solution

To have configVar match inside configValue, you have to contain it; this is done via the contained (leave this off if the var can also match anywhere, not just inside key=value) and contains=... attributes:

syn match configValue "\(\S\+=\)\@<=\"[^\"]*\"\|\(\S\+=\)\@<=\S\+" contains=configVar
syn match configVar "\$([^)]*)" contained

Note that I've changed the pattern for configVar to avoid matching $(foo) and $(bar) as one element.


You said that configVar can also appear in configKey, but for that, the range of allowed characters needs to include $(), too. Then, the containment works just as well:

syn match configKey "^\s*[a-zA-Z0-9_.$()]\+\(\s*=\)\@=" contains=configVar
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top