I wrote a vim syntax file. I notice that all keywords except those beginning with a colon (:) are being highlighted. Is there any way to escape colons in Vim?
Here's a section of the file:
syn keyword actionLabel :action nextgroup=actionName skipwhite
syn keyword problemLabels :goal :init :domain
syn keyword advLabels :types
syn keyword pondLabels :observe
hi def link actionLabel Statement
hi def link problemLabels Statement
hi def link advLabels Statement
hi def link pondLabels Statement
From :h :syn-define about keywords...
It can only contain keyword characters, according to the
'iskeyword' option. It cannot contain other syntax items. It will
only match with a complete word (there are no keyword characters
before or after the match). The keyword "if" would match in
"if(a=b)", but not in "ifdef x", because "(" is not a keyword
character and "d" is.
That means you'll have to modify iskeyword for your file type to include the colon character (ascii 58). Starting from the vi default, we can support any alphabetic character, number, underscore, or colon:
set iskeyword="#,48-58,_"
The best solution seems to be not using the keyword option, but using the matches option instead.
syn match pddlLabel ':[a-zA-Z0-9]\+'
hi def link pddlLabel Statement
Related
I have following syntax file:
syn match TaskName /^\[.*\]/
syn match TaskType /^\[.*\]\s*\zs[a-z]*/
syn match TaskDescription /^\[.*\]\s*[a-z]*\s\+\zs.*/
hi def link TaskName Title
hi def link TaskType Todo
hi def link TaskDescription Comment
and the context is:
Task Type Command
[file-run] local no description
why only [file-run] is matched?
If I type /^\[.*\]\s*\zs[a-z]* in normal mode, local will be matched.
The reason it is not matching is that :syn match does not try and
evaluate text it has already matched. So, it cannot match against the text already matched by :syn match TaskName.
Additionally, there's a lot that could be improved upon your patterns, notably:
You have a lot of pattern atoms that will match the empty string.
This makes pattern matching slow, as patterns like [a-z]* will match
everywhere (this pattern in particular is even pointed out as an example of
a pattern to avoid in the help documentation for :syn-pattern). In most
cases it is better to match 1 or more matches with \+ than 0 or
more matches with *.
You can make all of your patterns more brief and more clear using other
arguments of :syn match.
I would suggest leveraging the power of the nextgroup argument in combination
with the skipwhite argument of :syn match:
nextgroup allows you to tell
Vim to try and match the groups specified after this match.
The skipwhite argument allows you to skip over tabs and spaces when
trying to match the next group with nextgroup.
Keeping these in mind, you could rewrite your patterns to look like:
syn match TaskName /^\[.\+\]/ nextgroup=TaskType skipwhite
syn match TaskType /[a-z]\+/ nextgroup=TaskDescription skipwhite
syn match TaskDescription /\w\+\(\s\+\w\+\)*/
In order to do this, I've also edited your TaskDescription match to be “a word,
followed by 0 or more words separated by whitespace".
You can see that utilizing nextgroup and skipwhite makes each syntax match
more brief, in addition to making the contents of each group more clear.
Relevant :help queries:
:h :syn-match
:h :syn-pattern
:h :syn-nextgroup
:h :syn-skipwhite
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:
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.
I am attempting to write a syntax file for Vim.
One of the lines of code reads
syn match constant "\**\*"
while one of many other lines reads
syn keyword aiOperators up-build
The code for highlighting is the following:
hi constant gui=bold
hi aiOperators guifg=green
However, the result of the above is that only the following is highlighted:
The asterisks of every constant, but not the characters between them.
Characters up until the first hyphen of aiOperators.
What seems to be the issue?
The regular expression for your constant specifies a literal asterisk, zero or more times, followed by a literal asterisk. If you intend to match characters delimited by asterisks, you need something like \*\w\+\*: a literal asterisk, followed by one or more word characters, followed by a literal asterisk.
The :syn keyword only works for keyword characters; by default, the hyphen is not included, so the match stops there. If, for your filetype, the hyphen belongs to the set of keyword characters, use
:setlocal iskeyword+=-
This should not be placed into the syntax file itself, but into ~/.vim/ftplugin/myfiletype.vim. Otherwise, use :syn match.
Starting with vim and love that it highlights todo comments. Around here, however we use a custom keyword (first initial last initial todo: abTODO) so it's easy to grep for todos that apply to a specific person.
I'd love to add mine as a keyword that vi picks up and highlights along with todo, fixme and xxx.
In vim, how do I highlight TODO: and FIXME:? seems to apply, but using the following does not work:
syn match myTodo contained "abTODO"
hi def link myTodo Todo
UPDATE
In my .vimrc I have the following 3 lines (as suggested):
syntax enable
syn match myTodo "\<\l\{2\}TODO\>"
hi def link myTodo Todo
That is a lowercase L, not 1. However abTODO is still not being highlighted at all.
Try this match:
syn match myTodo "\<\l\{2\}TODO\>"
Explanation:
\< matches the beginning of a word
\l\{2\} matches precisely two lowercase letters
TODO\> matches the string TODO at the end of the word
Your highlight command is fine at it is. I don't think the contained option is necessary here.