1

I'm trying to use matchadd to highlight different occurrences of whitespace. However, sometimes it doesn't work for some reason. Here is the code:

  highlight GroupA guibg=lightgreen
  highlight GroupB guifg=white                " For default Vim color scheme
  highlight GroupC guibg=red
  highlight GroupD guibg=gray
  highlight GroupE guibg=blue

  call matchadd("GroupA", "\t", 11)           " Highlight tabs
  call matchadd("GroupB", " ", 12)            " Don't highlight single spaces

" Highlight initial spaces
" call matchadd("GroupC", "^ \+", 13)         " Why it doesn't work?
  call matchadd("GroupC", "^    ", 13)        " Current workaround

" Highlight 2 or more consequal spaces
  call matchadd("GroupD", "\S\zs\s\{2,}", 14) " Why it doesn't work?
                                              " I haven't found any workaround

" Highlight trailing spaces
" call matchadd("GroupE", " \+$", 15)         " Why it doesn't work?
  call matchadd("GroupE", "    $", 15)        " Current workaround

The regular expressions themselves are seems to be correct. If we try to avoid matchadd, everything works. So, here it is, just to show the correct behaviour:

test 1:

highlight GroupA guibg=lightgreen
match GroupA /\t/

test 2:

highlight GroupC guibg=red
highlight GroupD guibg=gray
highlight GroupE guibg=blue

 match GroupC /^ \+/
2match GroupD /\S\zs\s\{2,}/
3match GroupE / \+$/

Test file (>--- is for tab, . is for space):

>---aaaa>---
....bbbb....

foo.bar..baz
  • Try replacing the double quotes with single quotes to surround the regexes you pass to matchadd(). Or try doubling the backslashes. – user938271 Aug 26 '18 at 12:42
  • @user938271 Wow! Both suggestions work! Thank you very much. It would be cool to have detailed explanation posted as answer. – john c. j. Aug 26 '18 at 12:51
  • 1
    Well, it seems I discovered explanation myself: vi.stackexchange.com/questions/9706/… – john c. j. Aug 26 '18 at 13:04
2

Inside double-quoted strings some special characters are automatically replaced (see :h expr-quote). For example, the string "\t", containing the two characters \ and t is automatically transformed into a string containing a single literal tab character.

As a result, any backslash is automatically removed. This is undesirable if your string must be passed to Vim's regex engine. For example, if you want to pass the regex \s\+ to Vim's regex engine via matchadd(), it won't work when using double quotes to surround your string, because \s\+ will be replaced by s+.

The solution is to either use single quotes (see :h expr-') because it will prevent the interpolation, or double the backslashes, so that even after Vim removes a backslash, another one still remains.

Usually it's recommended to use single quotes, unless you really need the double quotes:

Prefer single quoted strings

Double quoted strings are semantically different in vimscript, and you probably don't want them (they break regexes).

Use double quoted strings when you need an escape sequence (such as "\n") or if you know it doesn't matter and you need to embed single quotes.

  • Never thought Google have styleguide for Vimscript! – john c. j. Aug 26 '18 at 13:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.