Customizing highlighting of individual Neovim windows

Caleb Taylor
3 min readJul 1, 2018

--

In 2017, Neovim released the winhighlight feature. It gave users the ability to perform “window-local highlights”. There were talks of using it in tandem with the upcoming (hopefully) floating windows feature. But how can you use it now?

Disclaimer: Thanks to Niall Burkley, I have realized that you should only use guifg and guibg if you have termguicolors enabled in Neovim. If not, then you should be using ctermfg and ctermbg for color changes.

See :h 'termguicolors' for more details.

Highlighting Active/Inactive Windows

One of the most obvious benefits of per-window highlighting is the ability to distinguish between active and inactive windows.

Example of dimming background of inactive windows

This used to be done via plugins like blueyed/vim-diminactive that were built on a hack using &cursorcolumn. Now, the basic functionality of changing the background color of inactive windows is now done easily in Neovim:

Dimming inactive windows with winhighlight

The process is pretty straight forward:
1. Create an auto-command group to call a function when a new window is entered.
2. Create your new local highlights in that function to customize windows.

Note the use of the Normal and NormalNC highlight groups. According to the documentation, the Normal highlight group affects “normal text” and the NormalNC highlight group affects “normal text in non-current windows”.

This allows us to set the highlight group of the active window to the ActiveWindow highlight group, and inactive windows to the InactiveWindow . The syntax for winhighlight is to define a comma-delimited set of highlight groups in the format {Highlight_Group_To_Replace}:{Highlight_Group_To_Use_Instead} .

I found that using something like this hex color tool allows you to darken/lighten your colorscheme’s background color by a few percent to achieve a good “inactive” background color.

Targeting Specific Window Types

Another useful feature is the ability to target specific types of windows. My personal setup is very minimal. I started with the Oceanic-Next colorscheme and removed the background from several highlight groups. This resulted in a very clean, minimal interface.

The default UI.

However, I had an issue. When I tried to invoke auto-complete, I had a hard time distinguishing between the editor window and the preview window.

Example of preview window with function signature blending into code

Before winhighlight this was a difficult task. Preview windows had the same background as your normal window, and if your status line didn’t have a different background color, everything ran together. Fortunately, this can also be fixed with winhighlight :

Targeting preview window with winhighlight

That’s all it takes. Just by checking the &previewwindow variable, we can specifically target the preview window. I replaced the Normal highlight group with the MarkdownError group because it suited my needs: only a subtle background difference. I could’ve created another custom highlight group, but this one worked just fine.

In case you’ve never messed with highlighting groups, you can see all the predefined highlight groups by running the command:

:so $VIMRUNTIME/syntax/hitest.vim

The end result is a subtle background change for the preview window that keeps the desired minimal UI, while still offering a clear distinction between the main window and the preview window.

Subtle background change for preview window for better UI

You can also target the Neovim terminal window. If you use the feature and want to customize anything about the highlighting groups, you can do it by checking the &buftype variable:

Applying custom highlighting for the terminal in Neovim

That about wraps it up. I hope the was a useful intro into the winhighlight feature. Let me know if I missed anything or if there are any other good examples of window-local highlights.

--

--

Caleb Taylor
Caleb Taylor

Written by Caleb Taylor

Sr. Engineering Manager @ PlayStation

Responses (1)