Syntax highlighting within a string - vim

To add a python syntax rule I will do something like this:
"Highlight the word self -- self.new, self
syn match pythonSelf /\<self\>/
:hi pythonSelf guifg=#5f9ba9
However, I would like to highlight any all-caps words and if they are ONLY in a python string. So for example, in the following image:
Line 15 should not have the ALTER word highlighted, but the words between lines 20-21 should be highlighted. Would it be possible to add something like:
syn match sqlKeyword /[A-Z]\+/
But only if it's contained within a python string?

You can try:
syn match sqlKeyword /[A-Z]\+/ containedin=pythonString contained
If you want to match all-caps words only, you might want to improve your pattern like this: /\<[A-Z]\+\>/.

Related

Vim: Line Following Syntax Match is also a Syntax Match

I would like to highlight lines matching this regex RED:
syn match RedLine "^\*\*\* .* \*\*\*\n"
Then I'd like to highlight the following line BLUE no matter what text it contains.
I tried using \zs to match the following line's pattern like this:
syn match BlueLine "^\*\*\* .* \*\*\*\n\zs.*"
But that doesn't work (my understanding is that the read position has passed the portion of the match before \zs already).
So I tried the "look behind" atom like this:
syn match BlueLine "\(^\*\*\* .* \*\*\*\n\)\#50<=.*"
But that was way too slow even with the 50 byte limit.
How can I always match an entire line whenever the previous line matches a certain pattern?
e.g.
*** this line's RED since it's surrounded by pairs of 3 stars ***
this line's always BLUE because of the preceding line
You actually don't need to re-parse the first line to capture the second, following line (which indeed is highly inefficient). Vim has :help :syn-nextgroup, which directs the parser to continue parsing with preference to the specified group. The skipnl keyword skips over the newline in between. As you indiscriminately want to highlight the entire next line, a simple .* pattern will do. The only important detail for that rule is the contained keyword, so that this rule only matches triggered by the nextgroup=, but never on its own (which would color the entire buffer blue).
syn match RedLine "^\*\*\* .* \*\*\*$" skipnl nextgroup=BlueLine
syn match BlueLine ".*" contained

vim syntax - How to highlight a match inside a region

I'm writing a vim syntax highlighting script to determine if a global param is in uppercase only. If its not - I want to highlight it.
The problem is that the global params is in a specific part in the page.
The code looks something like this:
***VARS***
${VAR1}
${var2}
***OTHERS***
${var3}
So I want that all the variables under VARS which contains lowercase to be highlighted - in my example, only ${var2} should be highlighted.
I tried to do this:
syn match global_var_match "\${.*[a-z][^}]+}" contained
syn region global_variables start="\(\*\*\*VARS\*\*\*\)\#<=" end="\(\*\*\* OTHERS\*\*\*\)\#=" contains=global_var_match
hi link global_variables ErrorMsg
But then also ${VAR1} and ${var2} is highlighted.
One problem is the simple typo in:
hi link global_variables ErrorMsg
This should be
hi link global_var_match ErrorMsg
I.e. the bad match, not the containing region. However, with this change, variables containing lower case are still matched under ***OTHERS***.
That issue is caused by a spurious space you have in your match for ***OTHERS***.
I also chhanged your global_var_match regex. I have it as:
syn match global_var_match "\${[^}]*[a-z][^}]*}" contained
This behaves very well for me in test cases like
${VAR} blah ${VAr} ${vAR}
and others: only the vars containing lower case are flagged. Still investigating why the region is incorrect.
Here is what I have:
syn match global_var_match "\${[^}]*[a-z][^}]*}" contained
syn region global_variables start="\(\*\*\*VARS\*\*\*\)\#<=" end="\(\*\*\*OTHERS
\*\*\*\)\#=" contains=global_var_match
hi link global_var_match ErrorMsg

How can I use syntax match with literal `*` correctly?

Consider the following vim syntax rules, which I am using to change the color of words surrounded by *.
syntax match boldme /\*.\{-1,}\*/
highlight boldme ctermfg=Red
For some reason, this rule only works if the word is at the beginning of a line, *hello* is red in the first line below but not the second line.
*hello* works
Another word and *hello* does not work.
How can I make syn match work in the middle of a line for the scenario above?
Update: This problem appears to be specific to using the literal * character as part of the match. The following match works fine for using _ instead.
syntax match boldme /_.\+_/
Thus the question is really, how do I force vim to treat a literal * character correctly in syn match?
try this:
syntax match boldme /\*.\+\*/
Update
I don't know how did you do the test, see this gif animation with vim -u NONE:

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.

Sub-match syntax highlighting in 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".

Resources