How to create a syntax rule that can be contained anywhere? - vim

The following snippet from my .vimrc highlights superfluous whitespace at line ends in a shade of gray:
autocmd Syntax * syntax match MySpace /\s\+$/
autocmd ColorScheme * highlight MySpace ctermbg=238
But this does not work when this whitespace is already matched by a syntax group. For example, trailing whitespace in various types of comments is not marked.
The manual talks about the contains=ALL option for syntax groups, but there seems to be no analogous containedin=ALL. Can I emulate it in any way? The only method I could come up would be to list all relevant syntax groups in the containedin= option of MySpace, and that's clearly tedious and not at all elegant.

Don't know how to do this with Syntax, but you can use the listchars options to highlight trailing spaces.
From my .vimrc:
" List chars
set listchars="" " Reset the listchars
set listchars+=tab:\|\ " show tabs as "|"
set listchars+=nbsp:· " show non-breaking spaces as "·"
set listchars+=trail:· " show trailing spaces as "·"
set listchars+=precedes:«
set listchars+=extends:»

You should use the :match command (or matchadd()), as described in the Vim Tips Wiki article about this particular topic.
If you like a ready-to-use solution for this, you can also try out my ShowTrailingWhitespace plugin, or one of the alternatives listed on the plugin page.

Related

Render boundary space in Vim (just like VSCode)

I am pretty noob at Vim still, pardon my ignorance
"Boundary" whitespace is any whitespace except single spaces between words, paraphrasing from VSCode docs:
I want to mimic this same behavior in Vim (ideally with no plugins).
An example of how this feature looks in VSCode:
There aren't many resources that I found on this topic. There is Render space if it have multi space in Vim, which addresses this exact same feature (previous example image shown is from that question), but the provided solution does not work exactly as expected.
This is an example of how boundary whitespaces look after trying out that stackoverflow solution:
While the '·' character is shown when there are 2 or more spaces in a row, which is desired, they are also shown highlighted, which is not what I expected
Moreover, if I place the cursor on a line that contains consecutive spaces, they disappear (or are highlighted into invisibility, whatever is happening that renders them invisible)
Excuse my newbie comments in my .vimrc; the rest of the file is commented out
This is another example, in VSCode, of the desired behavior:
Am I missing something from that previous question? Is the highlighting of whitespaces normal or a different issue on its own? Thanks in advance!
The feature you are looking for can be enabled with :help 'list' and customized with :help 'listchars':
The result above can be obtained by adding the following lines to your vimrc:
set list
set listchars=eol:↵,lead:·
If your color scheme makes those characters too visible, you can override its NonText and SpecialKey highlight groups (mentioned in :help 'listchars') to make them more bearable. For example:
augroup MyColors
autocmd!
autocmd ColorScheme * hi NonText ctermfg=235 | hi SpecialKey ctermfg=235
augroup END
colorscheme foobar
Note that listchars was more limited at the time the linked question was answered so, while it was more or less valid at the time, it is no longer necessary to use the conceal feature for this.

Turn off highlighting a certain pattern in vim

In vim, I am editing a file of filetype "markdown", but which contains latex math expressions such as $x_i$. Vim's syntax highlighting for markdown thinks the pattern *_* (letter-underscore-letter) is an error, and highlights the underscore in such patterns bright red. I would like to turn this off by adding a line to my .vimrc:
autocmd BufEnter *.Rmd "Dear vim, please don't highlight the pattern *_*"
What is the appropriate command to do that? Is it possible at all to do that in .vimrc, without editing a syntax file?
Note: I want to keep the markdown syntax highlighting in general, only turn off that particular feature.
If you want to remove _ from the markdown error pattern, you can redefine it. In my case I want to turn off error notifications of underscores in a word as I put a lot of URLs in my documents.
There's a line that defines the error pattern inside syntax/markdown.vim file
" Original error pattern
syn match markdownError "\w\#<=_\w\#="
Remove the _ from the pattern and add that to ~/.vim/after/syntax/markdown.vim.
" New error pattern without the underscore
syn match markdownError "\w\#<=\w\#="
You have to modify the Markdown syntax for that. One way would be to remove the parsing of the error:
:syn clear markdownError
But that would cause the other syntax rules to start an italic section on that _ char. Better just clear the error highlighting with:
:hi link markdownError Normal
To maintain the general error highlighting, but only define exceptions for the special $x_i$ string, define an overriding syntax group; luckily, this is easy because no existing syntax is there:
:syn match markdownIgnore "\$x_i\$"
(Adapt the regular expression to match all possible math expressions.)
This needs to be put into ~/.vim/after/syntax/markdown.vim to be executed after the original syntax script.

How can I make vim show spaces?

I'm currently trying to switch from gedit to vim. I try to make vim look similar to gedit:
Especially, I would like to show spaces with dots.
I currently have:
There are some differences, but it looks quite similar (this is my current .vimrc file). But I don't get those dots for spaces.
How can I make vim show spaces?
I found some answers (like this one) that seem to suggest to replace spaces by a special visible character and then replace it back. I don't want to do this every time. I want to be able to open vim and see those spaces.
Show non-space whitespace with
set list
Additionally show spaces as . with
set lcs+=space:·
Turn it off with
set nolist
There are times when I absolutely need to see which whitespaces are tabs and which are true space characters, as well as when spaces appear at the end of a line.
When I'm using vim, I use:
:set list
(which I can turn off with :set nolist)
With :set list, literal spaces show up as spaces, tabs show up as ^I, and the end-of-line shows up as a bright-pink $. (So any blank space you see to the left of the pink $ you'll know is a true space character, and the blank spaces to the right of it is just the "nothing" between the end-of-line and the right side of the editor.)
It's ugly, but it works well.
I don't recommend using it all the time -- just those times when it is crucial to see where literal spaces and literal tab characters exist.
While you can't do exactly what you want here, if your reasoning is like mine, you're wanting to see those spaces because it helps verify proper indentation (do I have 2 spaces there, or is it 3?). For Vim >= 7.3, you can use the indentLine plugin to add a marker at each indentation. It's awesome.
To install if you're using Pathogen:
cd ~/.vim/bundle
git clone https://github.com/Yggdroot/indentLine
It may be worth using undercurl to do the job.
hi WhiteSpaces gui=undercurl guifg=LightGray
match WhiteSpaces / \+/
or you can put this in your .vimrc
autocmd ColorScheme * highlight WhiteSpaces gui=undercurl guifg=LightGray | match WhiteSpaces / \+/
Show leading spaces (indent spaces) using the above mentioned plugin indentLine.
If you use Vundle as plugin manager you can add Plugin 'Yggdroot/indentLine' to your .vimrc and then run vim +PluginInstall +qall to install the plugin.
Add the following two lines to your .vimrc to show leading spaces as ·.
let g:indentLine_leadingSpaceChar='·'
let g:indentLine_leadingSpaceEnabled='1'
Using the answers of J-L and Cedric Simon. Edit ~/.vimrc and add:
set lcs+=space:·
nmap <F2> :set invlist<CR>
imap <F2> <ESC>:set invlist<CR>a
and when you work with vim just pres F2
Vim has been providing the 'listchars' option to show Tab vs. Space, and space characters in critical places, i.e. trailing at the end of lines. In previous versions (when the question was written), it did not offer a modification for all spaces: a blank square is a space, period. Other answers provided some workarounds, though.
In current Vim versions, there are many space-related options; cp. :help 'listchars' for details.
You can get the effect seen in your screenshot; persist by putting that command into your ~/.vimrc:
:set list listchars+=space:. listchars-=eol:$
You don't need to install any plugin to this:
set listchars=tab:\|\
"set listchars=tab:\┊\
"set listchars=tab:\┆\
"set listchars=tab:\¦\
set list

Alternate indentation display in Vim

I came across this question:
https://softwareengineering.stackexchange.com/questions/87077/how-can-a-code-editor-effectively-hint-at-code-nesting-level-without-using-inde
and thought that Vim might be able to do something similar as well with a plugin.
I believe the indentation level could be indicated with the a sign (icon in GUI, text with highlighting in term). The piece I'm not sure about is displaying the lines without indentation. Does anyone know, is it possible and/or how you would do it?
This question is not whether or not displaying indentation levels in this manner is desirable; but how to accomplish it in Vim.
You could use the conceal feature that is new in 7.3.
Here is a function that does roughly what the article is describing (for spaces; accounting for tabs instead would be a fairly trivial addition):
function! IndentationHeatMap()
set conceallevel=1
for i in range(1,9)
let indentation = repeat(" ", &sts * i)
exe 'syntax match NonText "^' . indentation . '" conceal cchar=' . i
endfor
endfunction
A solution closer to what you are requesting might use conceal to hide all leading whitespace with
syntax match NonText "^\s\+" conceal
and then use signs to provide the indicators based on custom calculations.
Note: NonText in these syntax commands is an arbitrary highlight group.
Take a look at these plugins: Indent Guides and IndentHL
Both have screenshots.

Showing trailing spaces in vim

I've set the following options in .vimrc
set listchars=tab:▸\ ,trail:·
set list
And expected to see dots in those places where spaces are used for tabulation in the code (I use spaces, not tabs).
However, the result is different:
Could you please recommend how to reach the desired result? Thanks!
You should check this link. I'm using the match command solution :
:highlight ExtraWhitespace ctermbg=red guibg=red
:match ExtraWhitespace /\s\+$/
This page also provides list based solutions which I haven't personally tried.
The vim-better-whitespace plugin incorporates many tips from the Vim Wiki page referenced in #icecrime's answer. It also has some nifty configuration options.
I installed pathogen.vim just to use this plugin and am happy with my life, all things considered.
And expected to see dots in those places where spaces are used for tabulation in the code (I use spaces, not tabs)
Actually this is the other way round, tab option is used to display a character when a tab character is inserted (\t) instead of spaces.
And trail is use to show trailing spaces at the end of lines.
You seem to have single empty line with trailing spaces, and dots are correctly displayed.
If you are only using spaces tab option is not used or displayed.
To highlight trailing whitespace characters:
:set hlsearch, then
/\s\+$
A more programmatic way to do this is via function matchadd():
hi TrailingWhitespace ctermbg=red guibg=red
call matchadd("TrailingWhitespace", '\v\s+$')
The 2nd paramter to matchadd() is the pattern we want to match. Here, we use single quote to avoid having to escape speical characters like backslashes etc, see also literal-string.
Based on the link posted by icecrime, I find this works quite well...
" Be clever about highlighting trailing whitespace (don't highlight it if we are
" in 'insert' mode and the cursor is at the end of the line). Also (regardless
" of 'insert' mode), highlight any tabs that immediately follow space(s).
" EOLWS and EOLWSInsert are colour group names; the latter being toned-down to
" make editing in 'insert' mode easier on the eye
autocmd InsertEnter * match EOLWS // | match EOLWSInsert /\s\+\%#\#<!$\| \+\ze\t/
autocmd InsertLeave * match EOLWSInsert // | match EOLWS /\s\+$\| \+\ze\t/
autocmd WinEnter,BufWinEnter,WinNew * match EOLWS /\s\+$\| \+\ze\t/
" Disable syntax-specific trailing space error handling because it conflicts
" with the above, mostly because the syntax highlighting doesn't take account of
" whether 'insert' mode is active or not. There are other '*_no_trail_space_error'
" settings - refer to syntax files in $VIMRUNTIME/syntax/
let c_no_trail_space_error = 1
let java_no_trail_space_error = 1
Also, make sure the 'Error' highlight group is NOT defined as inverse video - if it is, it conflicts on strange ways with the above
And expected to see dots in those places where spaces are used for tabulation in the code
Vim has 3 options for displaying spaces with listchars:
space show all spaces with the specified character.
lead Shows leading spaces, i.e. spaces at the starting of the line. I think this is what you want.
trail Shows trailing spaces, i.e. spaces at the end of the line.
There is also multispace but that is irrelevant to your problem.

Resources