0

I've discovered the wonder that is colorcolumn but I haven't yet mastered the black art of Vim scripting. If I have :set colorcolumn=80,132 in my .vimrc, how can I a) discover that I have more than one value, and b) access that 2nd value?

I have a line completion function that uses &cc to calculate a padding value:

function! LinePadOut(c)
  exec 'norm A ^['.(&cc - virtcol('$')).'A'.nr2char(a:c)
endfunction
nnoremap <expr> <C-L><C-L> ':call LinePadOut('.getchar().')^M'

This only takes into consideration the "80." How can I get at the "132" or even know it's there? I'd like to write a "long padding" version that uses the 132. (I take no credit for this function. It was someone else's magic that I poked at until it did what I wanted.)

Thanks!

2 Answers 2

3

One strange thing about vimscript is that it automatically converts string to numbers when some operations are applied. For example, if you try this:

if '123foo'
    echo 'hi'
endif

You will get 'hi' as the output, but if you try this:

if 'foo'
    echo 'hi'
endif

You will get nothing.

This happens because the condition of an 'if' sentence has to be an int, so both strings are automatically converted likewise and we get 123 and 0 respectively because the conversion stops at any non digit char.

The value stored in colorcolumn option is a string as stated in the help (see 'colorcolumn'), specifically a comma separate list of values with the type string that contain the column numbers that are highlighted.

Just like 'if' sentence, the minus sign '-' requires numbers to be its operands and strings will be converted (until first non digit) in order to accomplish that. So when you do:

&cc - virtcol('$')

The value of &cc which is originally "80,132" automatically converts to 80 losing the 132 and any other value. If you want to treat all the separated values, I would recommend you to split the contents of colorcolumn with the split() function:

let value_list = split(&cc, ',') " Split values at ,

Then, you can use a for statement to treat all the values. You can also query the length by using the len() function:

for value in value_list
    echo 'The value is: ' . value
endfor

let number_of_values = len(value_list)

for i in range(number_of_values)
    echo 'The value in ' . i . ' position is: ' . value_list[i]
endfor
1

How can I a) discover that I have more than one value, and b) access that 2nd value?

a). By checking if the option contains a comma. I'd do so with a regular expression comparison. See :help =~:

if &cc =~ ','
  echo 'Multiple colorcolumns'
endif

b). By splitting the option's value on the comma(s). See :help split():

for cc in split(&cc, ',')
  echo 'colorcolumn:' cc
endfor

c). To explain why your code ignores the second colorcolumn in your setting, note that &cc is not a Number but in fact a String:

:echo type(&cc) == type("")

(See also :help 'colorcolumn'.)

So when you attempt to subtract from it, it is converted into a Number with the following technique:

Conversion from a String to a Number is done by converting the first digits to a number.

:help Number

Thus, everything after and including the first comma is ignored.

Your Answer

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

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