How to have a Vim multiline syntax highlight clause? - vim

I'm trying to write the syntax highlight module for a tiny text format that includes three different kinds of list elements (starting with -, o and x respectively), and I'd like to highlight entries based on their kind. For single lines it's easy, I just use a syn match myGroup /^\s\+- .\+/ and I'm done.
Problem is, I've been trying to do it so that the next lines without a list marker keep the same colour as the starting list item line, to no success. I've been trying to do it with syntax regions, but I can't seem to understand how they work.
To be more precise, this is the output I'm trying to reach:
If any change is needed in the file format so that it is easier/possible, I have liberty to change it.
Any clue of how can I get it?

You can try something along these lines
syntax region Minus_Region start=/^\s\+-/ end=/;/
hi Minus_Region guifg='Yellow'
syntax region O_Region start=/^\s\+o/ end=/;/
hi O_Region guifg='Green'
syntax region X_Region start=/^\s\+x/ end=/;/
hi X_Region guifg='Gray'
You define region by its start and its end (in this case ;), no matter how many lines are involved.
For more information, see help
:h syn-region
If you want to finish the regions without having a end marking character (in this case ;), you could do it using the match-end (me) option on the end argument of the regions, and having the regions end on the next region-start marker. Example:
syntax region Minus_Region start=/^\s\+- / end=/^\s\+[-ox] /me=s-1
syntax region O_Region start=/^\s\+o / end=/^\s\+[-ox] /me=s-1
syntax region X_Region start=/^\s\+x / end=/^\s\+[-ox] /me=s-1
The me=s-1 part means "The real match ends at one character to the left of the start position of the pattern match".

Related

Syntax highlight start and end of transparent regions in Vim

I am writing a syntax highlight file for a language (that didn't already have one) in Vim.
An analogous problem to the one I'm stuck on would be highlighting lists in Python: I want the elements of the list to highlight normally, assuming they are types the language allow to be in such a list, while the list's structure (i.e. [ , ] should highlight in its own colour.
Currently I use
syn region myList start='\[' end=']' transparent contains=myList,myDelimiter,myNumber,myString
syn match myDelimiter ',' contained
myList contains itself to allow nested lists (hence legal extra ] end markers) without breaking the region. However, since it is transparent (to allow highlighting of other legal groups (myNumber and myString in this example)), the [ start and ] end brackets remain without highlighting.
The myDelimiter group can be considered a workaround to at least highlight the commas (though it's rather pointless without the rest of the structure, i.e. the start [ and end ]). Adding the [ and ] to the myDelimiter pattern like this:
syn match myDelimiter ',\|\[\|]' contained
breaks the myList region and makes it activate on unrelated parts of the file (outside of any list, thus breaking other syntax highlights for elements not allowed in a list. I think the problem is that the end isn't considered an end anymore, but a delimiter within a big array spanning to the last array in the file).
I tried adding matchgroup=myList to syn region myList ... (and ensured it had a corresponding hi myList ctermfg=red entry in my colorscheme), but it changed nothing.
Is there a way to fix this?
You need to add matchgroup=myListContainer to your region definition and after that you can highlight this new group:
:hi myListContainer guifg=red
You can use for your matchgroup any other group name, but I think that it shouldn't be the same as the primary group you're linking to.
Please take a look at the example here.

Syntax Highlighting with Fine Granularity

Is there a way to assign an individual character, as identified by a height and depth index, to a highlight group? Every match feature I have come across uses a regex pattern as input.
The reason I ask is because I am making a syntax coloring plugin that will make text an increasingly lighter shade of gray with increasing parenthesis depth. If vim has no such feature and another algorithm makes character-by-character highlighting unnecessary, please point me to it!
Vim has a whole set of special regular expression atoms that can specify buffer positions.
For lines, \%23l matches only in line 23. You can also use \%>23l for all lines starting from 23, and concatenate two of those with < and > to specify ranges.
For columns, there are the corresponding \%23c and \%23v. The former uses byte indices (what Vim somewhat confusingly calls "columns"), as returned by functions like col() and getpos(), the latter screen widths (from virtcol()).
By combining those atoms, you can select arbitrary blocks of text, and highlight them, e.g. with :call matchadd(...). See :help /\%l for details on the atoms.
For your plugin implementation, you may be able to get some ideas from the vim js context coloring plugin, which highlights JavaScript code according to its scope.

Multi-line Highlight in Vim

I am currently writing a plugin in Vim that needs to highlight arbitrary lines in a file
at the same time.
My approach so far has been implementing match with the line number to highlight it, but the problem is that I would need to add | for every other line in a file and append that information and then call it every time the window gets redrawn.
There is another problem with match in my case, and that is that a line that may not have any whitespace would not look highlighted (match only highlights existing text/whitespace).
So even if I had match rewrite the window and highlighting all the lines I need, from a user's perspective this wouldn't be to useful if the highlighting doesn't show anything if there is no whitespace/text.
Can I get any suggestions in how to effectively show/display/highlight (I'm open to different implementations to solve my problem) arbitrary lines in a file at the same time regardless of amount of text or whitespace?
Edit: My main request is to be able to highlight lines by line number not by regex
matching. So any solution should need to be flexible enough to accept a Line number to match.
Edit: signs is the answer to my problem, and I found this tutorial the best way to grasp and implement what I needed: http://htmlpreview.github.io/?https://github.com/runpaint/vim-recipes/blob/master/text/07_navigation/12_bookmarking_lines_with_visible_markers.html
I would use region rather than match. Here is part of my manuscript syntax file that highlights speech:
:syntax region msSpeech start=/"/ end=/"\|\n\n/
:highlight msSpeech guifg=#000088
It starts with a double quote and ends with another double quote or the end of the paragraph. It will highlight multiple lines if need be.

Full width background color highlighting of codeblock in Vim

I have Vim documents that have codeblock regions that use 'syntax include' regions to have different syntax highlighting from the main document. For example, I have a syntax region named 'pyregion' defined that I use when I input Python code. The pyregion areas of the document are then highlighted using setup in Python's syntax file, while the area outside the region uses the syntax file of the main document.
I want to have the entire background in the Python region be shaded a different color to distinguish it from the non-Python areas of the document. I can get part of the way there by entering a background for the entire python region:
:highlight pyregion guibg=#555555
But the command above changes the background only for areas that have text characters on them, not for entire background of the region, which seems still to be governed like rest of document by the background color defined for the 'Normal' group. This is okay -- it does draw attention to the region, but it has a blotchy look because only the code characters themselves have different background, not the entire band of the region across the screen.
Is there some way to get a uniform band of a different background color across the whole region, not just portion of region where there are characters?
There's related question and answer in following link, but so far as I can tell that answer also changes background only where there is text:
Highlight Code Block Backgrounds with Vim
Thanks for any help.
I don't believe that this is possible without a ridiculous bodge (see below). If you try this:
:match Error /\%3l/
It highlights what Vim considers to be the whole of line 3. The highlighting only extends to the the end of the characters. This makes me suspect that there will be no way to highlight non-existent characters.
Stop reading now.
Purely as an exercise in the ridiculous, you could of course append a massive number of spaces to the end of every line and then remove them when you save. This would be daft, but it's the only thing I can think of.
" Add spaces to the end of every line (you could also do
" this selectively for lines that don't already have lots
" of spaces and you could do it on reading a file or whatever)
:exe '%s/$/' . repeat(' ', 1000) . '/'
" Automatically remove spaces at the end of every line when saving
:autocmd BufWritePre %s/ *$//
" Make 'A' append at the end of the non-space characters on the line
:nmap A / *$<CR>i
" Make '$' go to the end of the non-space characters on the line
:nmap $ /.\? *$<CR>
Disclaimer: don't do this.
Yes, you can do this using the sign command.
http://vimdoc.sourceforge.net/htmldoc/sign.html
sign define 1 linehl=Error
sign place 1 name=er1 line=1 file=file.txt
Will highlight the first line of file.txt all the way to the edge of the terminal.

Vim: need help with a tiny script code to highlight

I need a script code to highlight "[Capítulo" and "]" and everything between them. Thank you.
I want it to work everytime I open , for example, a .txt file. Just like code highlighting.
Here's an easy way to do it:
in vim, make sure syntax highlighting is on with :syn on
run the command :highlight to get a listing of all the highlight group names, and samples of what they look like. The Error group looks like it stands out well in my colorscheme, so I'll use that in my example (but you can use any of the other names, like Todo or Search)
:syntax match Error /\[Capítulo[^\]]*\]/
This pattern will keep you from greedily matching the largest chunk. Even though other people are suggesting you use the regular expression /\[Capítulo.*\]/ - it's probably not what you want, because it will match everything in between if there are two or more such patterns on a line.
For example /\[Capítulo.*\]/ will match this entire line:
[Capítulo foo] these words should not be highlighted [Capítulo bar]
The same example but with /\[Capítulo[^\]]*\]/ will only match stuff inside []:
[Capítulo foo] these words should not be highlighted [Capítulo bar]
With regular expressions, it's a common trick to make a group that matches everything but the character that you want to end your match, instead of using the .* which will match as many characters as it can. In this case, we make the group [^\]]* - which says "match everything except ]."
If this works the way you want it to, add the syntax match line without the ":" to your .vimrc
A regular expression is what you're looking for:
Type / to enter in "search mode" and type:
\[Capítulo.*\]/

Resources