Around a month ago I switched to using Vim full-time. I've already been using Vim for all of my command-line editing, but now I've enabled Vim emulation in all of the other editors I use (namely those coming from JetBrains).
To keep my Vim skills versatile, my Vim configuration uses vanilla key mappings. That said, I've still made a lot of quality-of-life adjustments to the config, including colour scheme tweaks. One of such tweaks is changing the style of the active pane to make it more obvious - which is also the focus of this article.
Getting it to work
There are several steps needed to get the whole thing working. Jump to the end of this article if you want to see the final code.
For the sake of this article, I will use red for my colour column (from here on I will call it just "column"). To make screenshots more compact I will use values
40. Let's assume I start off with this
" Make cc red highlight ColorColumn ctermbg=Red " Set global cc default to 20 set colorcolumn=20 " Set cc in Markdown files to 40 autocmd FileType markdown setlocal colorcolumn=40
Now, if I open files
config.ini (left pane) and
text.md (right pane) I will get this:
Note that the column in the left pane is draw at position
20, and in the right column and position
We want the column to only appear in the active window. Here's the result we want to get:
Naive solution (doesn't work)
A naive solution, that uses only
autocmd, could look like this:
augroup BgHighlight autocmd! autocmd WinEnter * set colorcolumn=40 autocmd WinLeave * set colorcolumn=0 augroup END
This will indeed only show the colour column in the active window, but there is one drawback - the position at which it is drawn is always
40. This defeats the purpose of using different colour column settings for different file types. We can do better!
Instead of using one-liners with
autocmd Win<Enter/Leave>, let's define some functions:
function! OnWinEnter() " We will put some code here soon endfunction function! OnWinLeave() " We will put some code here soon endfunction augroup BgHighlight autocmd! autocmd WinEnter * call OnWinEnter() autocmd WinLeave * call OnWinLeave() augroup END
By now, you have probably guessed what we will do: We will hide the colour column in
OnWinLeave() and reveal it in
OnWinEnter(). Doing this is pretty straight-forward, but there are some things we have to consider.
We will "remember" the initial
colorcolumn setting of a window using a window-scoped variable. Window-scoped variables are created by prefixing their names with
w: (check out Vim variable scoping for more info). To remember the value, we'll need to execute the
let w:initial_cc=&colorcolumn command at some point.
The question is, where do we put it? There's a catch: If we put it inside
OnWinEnter(), we'll actually remember the
colorcolumn of the window that we're leaving. This makes the logic somewhat complicated, so, instead, we're gonna put it inside
OnWinLeave(). We're also gonna add some code to hide the colour column (since the window we're leaving will become inactive):
function! OnWinLeave() " Define w:initial_cc if it isn't already defined if !exists('w:initial_cc') let w:initial_cc=&colorcolumn endif " Hide colour column let &colorcolumn = 0 endfunction
w:initial_cc holds the
colorcolumn value of the window to whose scope it belongs. All we have left to do is use this value in
function! OnWinEnter() " Use w:initial_cc if it's defined " (default value will be used otherwise) if exists('w:initial_cc') let &colorcolumn = w:initial_cc endif endfunction
And we're done! Putting everything into our Vim config we'll get the desired behaviour. I know that some of my explanations lack detail - there are just too many small things to explain here. If you want to understand why (and how) this works, try implementing it yourself.
Below you can see the full Vimscript snippet that you can put into your
.vimrc.json. Note that this technique can be applied to other Vim parameters too - go make something cool with it!