Sub-match syntax highlighting in Vim - vim

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.

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.

There does appear to be some capability for layered highlighting, as seen here: 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".

Related

Custom Vim syntax highlighting only works for some keywords

I'm writing a custom syntax highlighting file for a proprietary language I have to use a lot. I have written a full file but it seems to only use 3 colors. All punctuation is one color, some of the keywords I have specified are another color, and everything else is a third color.
The odd thing is, I removed every match and every redefinition (hi def link) from the file and the highlighting doesn't seem to have changed at all. In fact, I tried adding some other keyword mappings to try to see where it's breaking, but it seems only certain lines are being evaluated for the highlighting. For instance, this line ends up highlighting the proper text:
syn keyword clangImport IMPORT
However, this line (below) doesn't and is a different color despite not even providing any specific highlighting instructions:
syn keyword clangGroupAttributes ?? GN GA GV GL GP GR PV PN SI CN
Why would it only evaluate certain lines of the syn keyword mapping?
Additionally, none of my regex matching worked at all despite using something as simple as "\d\+".

vim regex & highlight syntax: find a match and ignore sub-match in it

I am trying to write a syntax highlighter in VIM. How do you highlight a match within another match?
To find each match, I created two syn match lines, which work where the matches are separate.
syn match celString "^xpath=.\{-};" -> matches "xpath=.........;"
syn match celComment "\${.\{-}}" -> matches "${LIB_METADATA};"
The first line is pink for the xpath string and blue for the ${..} string.
The second line is pink for the xpath string, but the ${..} contained inside that string is ignored.
I've tried to change the order of the syn match lines, but that doesn't have any effect.
I'd appreciate your ideas.
By default, Vim only applies the syntax groups to text that hasn't yet been assigned a syntax. To specify that one group can contain other groups, use the contains=... attribute:
:syn match celString "^xpath=.\{-};" contains=celComment
The order of definition shouldn't matter here. See :help :syn-contains for more information.

highlight sub-match in vim

I'm trying to figure out how to highlight a specific portion of a match in vim.
Given the following example rule (taken from the coffeescript syntax file source):
syn match coffeeExtendedOp /\%(\S\s*\)\#<=[+\-*/%&|\^=!<>?.]\+\|[-=]>\|--\|++\|:/ display
This regular expression matches various coffeescript operators. The operators are highlighted (in my vimrc) like this:
hi Operator guifg=#ff0000
For example, since coffeeExtendedOp is linked to coffeeOperator which is linked to Operator, in the above source file. This all works, but I'm wondering how to specifically highlight the ++ operator matched in the above syn match with a different color, say blue, within my vimrc (that is, without altering the original source file above). I'm simply wondering if this is possible.
EDIT: I think the rules are placed under a cluster, so perhaps that's why it's not affecting anything. Is there a way to access the rule within the cluster?
EDIT: Question was clarified.
Solution:
syn match plusplus /++/ contained containedin=coffeeExtendedOp display
hi plusplus guifg=#0000ff
The problem now is that this only works when I run them as commands in vim, but not when I put it in my vimrc file. Any ideas? Could it be that the stuff is hidden behind the cluster? But then why is it visible in vim through a command? I tried including the syntax file but it didn't seem to have any effect.
Looking at the coffee.vim you linked to it seems like the dot belongs to the coffeeDotAccess syntax item. So you can highlight it just by doing this:
:hi coffeeDotAccess ctermfg=blue
I'm going to guess a bit at what you need. (I don't speak Coffeescript and your sample regex is way too complicated for me to start reading at the moment).
Transparent syntax items
You could have a look at transparent syntax rules: (http://vimdoc.sourceforge.net/htmldoc/usr_44.html)
In a C language file you would like to highlight the () text after a "while"
differently from the () text after a "for". In both of these there can be
nested () items, which should be highlighted in the same way. You must make
sure the () highlighting stops at the matching ). This is one way to do this:
:syntax region cWhile matchgroup=cWhile start=/while\s*(/ end=/)/
\ contains=cCondNest
:syntax region cFor matchgroup=cFor start=/for\s*(/ end=/)/
\ contains=cCondNest
:syntax region cCondNest start=/(/ end=/)/ contained transparent
Partial matches in regex
If you really just meant highlighting submatches, have a look at the the
\zs start match
\ze end match
In short,
:match Error /foo\zsbar\zered/
would highlight only 'bar' in 'foobarred'

LaTeX section highlighting in vim

In LaTeX, a section looks like:
\section{Section Title}
I would like to highlight such sections, or section titles. I tried to put the following in ~/.vim/bundle/latexrc/after/syntax/tex.vim:
syn match texSectioning "\\section\>" skipwhite nextgroup=texSectioningTitle
syn region texSectioningTitle contained matchgroup=Delimiter start='{' end='}' contains=#texSectioningGroup
syn cluster texSectioningGroup contains=texMatcher,texComment,texDelimiter
(Note that this kind of syntax is not handled by the default tex.vim syntax file. It only defines "section zones", which are pretty much worthless for me.)
I then define the following in my color scheme:
hi texSectioning gui=bold guifg=red
And nothing happens; that is, section titles do not appear in red in my LaTeX code (even after I reloaded the file completely).
I am totally confused as to how vim's syntax work, and how to debug it.
Edit
Some more information: it sometimes works and sometimes not. Completely unpredictable. What could be the problem? Pathogen? Something else? I'm completely puzzled.
You have defined the new syntax items texSectioning, texSectioningTitle and texSectioningGroup, but you have not linked them to a highlighting group, so Vim doesn't know how to display them. Try adding these lines:
hi def link texSectioning Statement
hi def link texSectioningTitle String
hi def link texSectioningGroup Comment
The Statement, String and Comment colourings are defining by the colourscheme you are using. These are just examples: you can replace them with any group defined in the colourscheme file.
Here is the answer: the tex.vim divides the text in zones, in which the syntax must be explicitly allowed. The key element is that command:
syn cluster texChapterGroup contains=#texSectioningGroup
This says to vim that inside a texChapterGroup, the syntax cluster texSectioningGroup is allowed. The next thing to do is simply to define that cluster as usual.
Another detail is that the region texSectioningTitle must be contained, otherwise it will match arbitrary pairs of {} in LaTeX.
So a complete solution goes like this:
syn match texSectioningCommand '\\section\>' skipwhite nextgroup=texSectioningTitle contains=#texSectioningGroup
syn region texSectioningTitle start='{' end='}' contained
syn cluster texSectioningGroup contains=texSectioningCommand
syn cluster texChapterGroup contains=#texSectioningGroup
Edit Here is why the behaviour was apparently unpredictable: vim does not read the entire file to figure out the syntax. So in a big enough chapter, my section syntax would work because vim did not go far enough to see it was in a chapter zone.
Just to update the information to highlight section easily. Using containedin means that all the other syntax matches contains this new syntax match. Then just define the color you want.
syn match texSectioningCommand '\\section\>' containedin=ALLBUT,texComment
hi texSectioningCommand guifg=#ec5f67 ctermfg=203
Alternatively, a simple new syntax match could be added to the texFoldGroup in order to be evaluated inside the the block document.
syn match texSectioningCommand '\\section\>'
syn cluster texFoldGroup add=texSectioningCommand
hi texSectioningCommand guifg=#ec5f67 ctermfg=203

Vim syntax files ... trying to understand "contains"

I'm trying to patch up a new vim syntax file for some custom format I'm using. Most of it I can understand, but the keyword "contains" is giving me trouble.
Is there anyone here who could give me an explanation of what it does (I've read the help -> didn't quite get it) in a way as if he were explaining it to a tree.
In general, you can only have one syntax highlighting method in one place. Therefore, to use C-like syntaxes as an example, if you define a region to start on an opening brace '{' and end on a closing brace '}', the syntax highlighting for that region will be the same.
contains= allows you to configure other syntax highlighting groups to be contained within an outer group. To follow the previous example, you may want int to be highlighted even when it is in the outer region. You could then have something like:
syn keyword Keyword int
syn region BraceBlock start='{' end='}' contains=Keyword
It is quite common to need to add items later to the list of contained keywords. There are a few ways of doing this. Firstly, you can use contains=ALL or contains=ALLBUT,Error to allow anything to be in a region. Secondly, you can use containedin to push something into the contains of another region:
syn region BraceBlock start='{' end='}'
syn keyword Keyword int containedin=BraceBlock
Thirdly, you can define anything that is "contained" as valid in this group:
syn region BraceBlock start='{' end='}' contains=CONTAINED
syn keyword Keyword int contained
Finally, you can use clusters, which make it quite easy to decide what goes where:
syn region BraceBlock start='{' end='}' contains=#MyCluster
syn keyword Keyword int
syn cluster MyCluster contains=Keyword
syn keyword Conditional if else
syn cluster MyCluster add=Conditional
" Now conditionals and keywords can appear in a BraceBlock
Without knowing exactly what you want to understand, I'm not sure what else to say - what are you trying to achieve and what is causing you problems?

Resources