This question is a sequel question of this one. I have the following script that removes capitalized words from vim spell check.
syn match myExCapitalWords +\<\w*[A-Z]\K*\>+ contains=#NoSpell
But it works only if I do syn clear first. But then all other highlighting (e.g. markdown) gets lost. I went through syn list to see what might be causing the conflict, but now I am out of clue.
It looks like you're extending arbitrary syntaxes with your myExCapitalWords group. Whether / in which syntax items that works depends on the underlying syntax. Unfortunately, it is not possible to extend arbitrary syntaxes in a blanket way. That's why you're seeing problems that can only be solved via :syn clear (which gets rid of the underlying syntax).
A syntax contains multiple groups, some of which are usually contained= in others. If you introduce a new syntax, it will only apply to where no other syntax group already matches. You can force your group into others via containedin=TOP or even containedin=ALL, but that overlay may prevent other original groups from matching, and causes strange effects because their own contains= or nextgroup= now don't apply.
So, unfortunately, there's no general solution for this. If you're only interested in a few syntaxes, you can tweak your one-liner to make it cooperate with the underlying syntax (e.g. try containedin={syntaxName}Comment{s}), but there's no generally applicable solution.
Related
Summary
I'm not asking your opinion about the proposed change being good, bad, amazing, or what.
I'm just asking your help to answer this question: does the change I propose for the syntax coloring of the comments break the syntax coloring of something else (keywords, strings, syntax errors, ...)?
The question above is not opinion based, as my change either does break something or it doesn't. That's it.
Original question
I have created the issue #5876 on Vim's GitHub page to propose a change to vim/runtime/syntax/sed.vim, but it has not received much attention, so I'm considering creating a PR for the change.
In fact, I created an issue instead of a PR because I'm not totally confident the change is not disruptive, hence this question.
The issue is with line 20:
syn match sedComment "^\s*#.*$"
because of which only "full line" comments are colored as comments. Using trailing comments following a command (allowed by GNU sed, for instance), stimulates some red background coloring (since it's considered an error by the syntax coloring logic, I guess).
I think it would be reasonable to relax this definition of comments to permit GNU sed-style comments, for the simple reason that the rule is less restrictive.
In this respect, I have noticed that changing that line to
syn match sedComment "\s*#.*$"
i.e. just removing the anchor ^, seems to be enough. I have also tried testing it by putting some # in search and replace strings in a sed script, and it seems fine.
However I don't feel confident with Vim syntax coloring files, so I would like to be sure that regex, as I edited it, is not causing false positives.
To demonstrate why I'm not confident about it, take this single-line sed script
s/aaa/bbb/#ccc
here # is not colored as a comment, and ccc's background is red (like an error?), whereas, just adding a space, give the correct coloring:
s/aaa/bbb/ #ccc
Therefore I think that my edit works (or seems to work) because of precedence rules between the several syntax coloring directives (with respect to this specific example with s/aaa/bbb/#ccc, I think that # just after the closing delimiter of the s command has a meaning in the language, but I don't know; the GNU Sed man page doesn't say anything about it).
Edit
Another example suggested in the comments is the following, the syntax coloring of which is not broken by the proposed change
s/#if !defined(\([^)]*)/#ifndef \1/ # with or without this comment is fine
My research
I have eventually found some time to study :h E410 and now I have an answer.
From there I read that
1. Keyword
[...] It will only match with a complete word [...]
2. Match
This is a match with a single regexp pattern.
3. Region
This starts at a match of the "start" regexp pattern and ends with a match with the
"end" regexp pattern. Any other text can appear in between. A "skip" regexp
pattern can be used to avoid matching the "end" pattern.
Since the line I'm going to change uses the syntax 2.,
point 1. is not relevant,
point 3. is relevant, as in general there can be an overlap between the what syn match and syn region match.
(By the way, I verified that syn region uses a lazy regex, probably \_.\{-} looking at some examples afterwards, to match stuff between the start and end regexp patterns.)
Then from :h :syn-priority
An item that starts in an earlier position has priority over items that start in later positions.
The answer
Therefore, changing
syn match sedComment "^\s*#.*$"
to
syn match sedComment "\s*#.*$"
should not introduce any syntax error, the reason being that if a text matching the above regex is not actually a comment (as is the case for e.g. the command s/#/hash/), then it must be preceded by some non-comment syntax which will be matched by other syn match/syn region groups. Since this match starts before where the group sedComment starts to match, the former has precedence on the latter.
In conclusion, unless something is broken with sed.vim already, the proposed change will not result in a wrong syntax coloring.
Further observations
Actually, there is already something wrong in sed.vim, and my proposed edit does not solve it (I should edit some other line in sed.vim to fix it, but I'm a bit lazy now).
For instance, in the following line, which is illegal because a is not a valid flag, a does not get the Error coloring.
s/x/y/a
My proposed edit does not solve this bug.
For the same reason, since some other syntax rule is eating 1 character after the third delimiter in the substitution command, the GNU-sed-valid comment in the following command is incorrectly colored
s/x/y/#hello
# │└───┴─── colored as Error
# └─ not colored
The coloring would be wrong even for an old version of sed which does not allow trailing comments, as the Error coloring should include the # too.
My proposed edit does not solve this bug either.
One more observation
The change I propose causes single-letter commands to be highlighted as Error if they are followed by a comment
p # this is a comment
│ └─────────────────┴─── colored as Comment (ok)
└────── colored as Error (bad)
This again, is not a worsening, as the current sed.vim colors almost the whole line above as an Error.
One of the vim plugins I use does:
syn keyword rustTodo contained TODO FIXME XXX NB NOTE
Resulting in highlighting NB in comments, which I don't like. Is there a way to either redefine the keywords or remove one from them? Looking at :help syn-keyword makes me think that this is not possible.
If that is the only definition for rustTodo (these are cummulative), you can remove and then redefine it:
syn clear rustTodo
syn keyword rustTodo contained TODO FIXME XXX NOTE
Unfortunately, the granularity for removal of syntax items is limited to whole syntax groups (here : rustTodo); you cannot pick individual keywords unless they also have separate groups (which would result in much more linking of highlight groups and therefore inefficient).
To make this permanent, put it into ~/.vim/after/syntax/rust.vim
If you think that the majority of users doesn't like NB here, please suggest to the author to drop it. Adding it back as a personal customization is easier and more maintainable than removing it...
I had a similar question while importing syntax files from within other syntax files, and came up with a dirty hack.
Instead of loading your syntax file with
syn include #othersyntax syntax/othersyntax.vim
you can use
syn include #othersyntax !sed 's/<NB>//' syntax/othersyntax.vim
Eww. This brings serious platform dependency and security issues, but at least relieves you of the burden to keep the replacement keyword list in sync with upstream.
I want to leave my system's Python syntax highlighting mostly intact, but I have a specific pattern I'd like to highlight for an idiom I use a lot. How can I add additional highlighting instructions on top of the existing highlighting done by vim?
(Apologies if this has already been asked. All the vim syntax highlighting questions I found seemed to involve writing a new syntax highlighting from scratch.)
Put your additional :syntax commands into ~/.vim/after/syntax/python.vim, and they will be automatically executed after the original syntax script.
It's easy to highlight stuff that so far isn't parsed at all.
For elements already parsed / hightlighted, you need to find out by which syntax group (e.g. pythonFunction), and add a containedin=pythonFunction clause to your :syntax commands. Without that, the original matching will obscure yours. To find out which syntax group causes the highlighting. :syn list shows all active groups, but it's easier when you install the SyntaxAttr.vim - Show syntax highlighting attributes of character under cursor plugin.
Introducing highlighting across (larger) elements that have multiple existing syntax groups is difficult, as your match will obscure the original ones, and that may break the entire parsing. You need to carefully examine the existing nested element structure, and try to fit in yours, again via contains= and containedin= clauses. Depending on the actual situation, that can be difficult.
For the actual syntax definitions, see the help starting at :h :syn-keyword. Basically, there are simple keyword definitions, regular expression matches, and regions defined by start and end patterns.
I need to add support for assembler language I'm working with (it is not x86, 68K, or 8051 which are well supported by vim). I looked at the existing syntax files, and here are my questions
1) When does it really make sense to use syn keyword and syn match? My understanding is that the latter supports regex and gives more flexibility. On the other way, looking at /usr/share/vim/vim70/syntax/asmh8300.vim - they define opcodes in both keyword and match, what benefit does it really give?
2) Instructions in my Asm have a common format:
INSTR OP1, OP2 ..; i.e. space delimits the instruction name from operands.
I think for this I'm ok with only defining all Asm commands in 'keyword' since space symbol is by default in 'iskeyword'. Am I right ?
3) The Asm also supports C-style structures, enums and comments. Can I just borrow its syntax definition from c.vim or it won't work and requires some tweaking?
If you have a limited set of identifiers, and if they all consist solely of keyword characters, then :syn keyword is the best choice. You're right in that :syn match provides a superset of functionality. Essentially,
:syn keyword myGroup foobar
is equivalent to
:syn match myGroup "\<foobar\>"
Beware of old versions
The syntax/asmh8300.vim syntax you've referenced is from 2002, it may not be the best example of how to write a syntax file. (For example, it omits the \<...\> around its matches, what looks like a bug to me. And it still has compatibility stuff for Vim 5 / 6 that's not needed any more.)
Also, do you actually use Vim 7.0?! Vim 7.0 is from 2007 and very outdated. It should be possible to install the latest version 7.3; if you can't find a proper package for your distribution (for Windows, check the binaries from the Cream project, it's also not very difficult to compile (e.g. from the Mercurial sources) on Linux.
Borrow other syntax elements
If other syntaxes are embedded in your syntax, and clearly delimited (e.g. like JavaScript inside HTML), you can :syn include it. But if there are just similar constructs, it's best to copy-and-paste them into your syntax (and adapt at least the group names). You need to be careful to catch all contained syntax groups, too; together with syntax clusters, the hierarchy can be quite complex!
More tips
When writing a syntax, you often need to find out which syntax group causes the highlighting. :syn list shows all active groups, but it's easier when you install the SyntaxAttr.vim - Show syntax highlighting attributes of character under cursor plugin.
I try to add some syntax highlighting for javascript to vim, but I keep running into one problem: when characters are already highlighted, they seem to be completely ignored by all other regular expressions.
For example, I tried to add syntax highlighting for the argument list of a function. While creating the right rexex I disabled the syntax highlighting for the function keyword, such that it was easier to see what my regex did. I ended up with the following (working) regex:
syn match javaScriptArguments "[(=\:\s,]function.\{-}(\zs.\{-}\ze)"
However, as soon as I enabled the highlighting for the function keyword again, this line doesn't work anymore. It seems that vim simply excludes everything which is already highlighted, and thus it won't find any matches for the regex above, even though it won't result in characters being highlighted twice.
How can I solve/work around this problem?
Syntax definitions must be contained for them to match inside other syntax items. Find all the gruesome details at :help syn-contains.
In your case, you're relying on a look-before of the "function" keyword via \zs. In my experience, that's bound to cause problems, but may turn out to be unneccessary once you use contained. In general, it is difficult to extend an existing syntax definition without modifying the original script (which I suppose is what you're intending to do). Have a look at :help :syn-containedin and :help :syn-nextgroup.