4

The colorcolumn works well when there are no wrapped lines. set colorcolumn=80:

Vim colorcolumn

However, when there are long lines that are wrapped, the colorcolumn breaks into multiple pieces:

Vim colorcolumn on wrapped lines

Is there a way to make it such that the colorcolumn will always be a single unbroken line?

1 Answer 1

4

The colorcolumn setting accepts multiple values, for example set colorcolumn=30,60 will highlight column 30 and 60.

We can use this to display a single unbroken line for wrapped lines; for example for a 130-column line on a 40 column wide display you would use set colorcolumn=30,70,110 to highlight the first three columns.

You can set this automatically with a little command:

command! -nargs=1 WrappedCC let &colorcolumn = join(map(range(10), {i -> &columns * i + <args>}), ',')

This uses &columns to get the screen width, and adds the first ten colour columns at the correct place.


You can also hook in to OptionSet autocommand to automatically do this whenever colorcolumn is set, so you don't need a new command; you can just use set cc=80 instead of WrappedCC 80. You can still use set cc= to clear the highlight, or set cc=80,120 to only set those two columns.

fun s:wrapped_cc()
    let &colorcolumn = join(map(range(10), {i -> &columns * i + str2nr(&cc)}), ',')
endfun

augroup wrappedcc
    autocmd!
    autocmd OptionSet  colorcolumn  if &cc != '' && &cc !~ ','       | call s:wrapped_cc() | endif
    autocmd VimEnter   *            if &cc != '' && &cc !~ ','       | call s:wrapped_cc() | endif
    autocmd VimResized *            if len(matchlist(&cc, ',')) >= 4 | call s:wrapped_cc() | endif
augroup end

This also needs to hook in to the VimEnter because OptionSet isn't triggered on startup; otherwise set colorcolumn=80 from your vimrc won't work; since the VimEnter is triggered after reading all the vimrc you can put the set colorcolumn= anywhere in your vimrc (it doesn't need to be after the autocmd).

Also need to hook in to the VimResized to re-calculate the column positions because they need to be adjusted after the window is resized. This assumes that anything with more than four columns is a "wrapped column".

5
  • 1
    Note: just noticed this will break set cc=+1 to set the colour column relative to the text width. I'll leave this answer as-is for now; I'll fix it later. Jan 30, 2021 at 7:45
  • Martin, thanks a lot for updating the answer. Just in case, there is still one issue here - the columns don't match if there is set number.
    – john c. j.
    Aug 14, 2022 at 20:14
  • It seems it should be i -> (&columns - &numberwidth) instead of i -> &columns to fix this.
    – john c. j.
    Aug 14, 2022 at 20:36
  • 2
    Right @johnc.j., although that will break if you don't have any numbers enabled. Also if you have any placed signs that needs to be subtracted. Getting the actual "editable" window width seems somewhat non-trivial 🤔 Aug 14, 2022 at 22:23
  • I have just discovered that to make this function work properly, colorcolumn must be set with absolute value: set columns=100 textwidth=78 colorcolumn=79 or by using let: let &colorcolumn = &textwidth + 1. If you use set with relative number, the function won't work properly (set colorcolumn=+1 " the function will work wrong).
    – john c. j.
    Aug 24, 2022 at 11:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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