Horizontal Split Separators in Vim
Making default Vim look better
I’ve been playing around with Vim, it as an IDE for a while. So far I’m very happy with it. Sure it has a few problems. And sure, it’s not as stable as something like Intellij Idea. However, it makes up for it by offering extreme customizability and comfort.
I find that Vim’s simplicity shines in comparison with its competitors, the big, complex IDEs. Those often feel overwhelming and crowded, whereas Vim is minimal but similarly powerful (well, except for Kotlin development). Don’t get me wrong, having your editor directly run in your terminal has its benefits, but it also means that users are quite limited when tweaking its appearance.
In this post, I will explain how I configured my editor to display clean lines, instead of status bars all over the place.
Neovim’s default look
Vim’s default split separators look like this by default:
As we can see, each window has its own status line bellow, which seems quite unnecessary. It is worth noting, that Vim provides the option fillchars
to specify different characters used for the UI. The following piece of code changes the look of vertical separators. It makes everything look so much cleaner:
(vim.opt.fillchars:append "vert:│")
Horizontal separators
Great! so… Where is the problem you might ask:
Vim doesn’t have a concept of horizontal separators, it’s the status bar that marks the end of a window. This means that most users have to live with a bunch of bars all over the place, displaying information that is often irrelevant.
This is something I personally don’t like, having a status bar per split, only clutters the interface. Thus I had to figure out a way of clearing my screen of all those annoying things.
The first thought that went through my head was that I could replace the status bar with a horizontal straight line. Luckily for me, I was already using Feline. Feline, is a very flexible status bar plugin for Neovim. It is particularly interesting how it is configured, that is, by defining a set of providers that display isolated bits of information.
We can simply define a provider that fills the status bar with the character ─
. We should take the width of our current split window so that the characters don’t overflow:
(defn inactive-separator-provider []
(string.rep "─" (vim.api.nvim_win_get_width 0)))
We probably still want to display the status bar for the window which is focused. Feline has a specific setting to configure its appearance for inactive windows. Its called components.inactive
and we can use it to establish which bars should be filled with dashes.
(tset components.inactive 1
[{:provider inactive-separator-provider
:hl {:bg "NONE" :fg horiz-separator-color}}])
Finally, we must also override the background and foreground colors so that they look the same way the vertical separators do:
(feline.setup
{:default_hl
{:inactive
{:fg horiz-separator-color
:bg "NONE"}}
:components components})
Polishing the interface further
There’s still one thing that bothered me though, windows at the bottom of the screen don’t really need a separator below them. I actually tried two different approaches to solve this. The first one was checking the position of the window relative to the rest, by using its coordinates. It turned out to be a not-so-good idea, as it causes problems when we resize our terminal. The way I ended up going with was to use the winnr
function to determine which windows where located at the bottom.
The function works as it follows:
winnr([{arg}]) The result is a Number, which is the number of the current
window. The top window has number 1.
The optional argument {arg} supports the following values:
...
{N}j the number of the Nth window below the
current window (where CTRL-W_j goes to).
...
If there isn’t any window next, the function will return the id of the current one, this way, we can add a check in our inactive-separator-provider
:
(defn inactive-separator-provider []
(if (not= (vim.fn.winnr) (vim.fn.winnr :j))
(string.rep "─" (vim.api.nvim_win_get_width 0))
""))
The resulting UI something like this:
Other options I’d like to try
There are still a few things that I haven’t gotten around to try:
Having the best of both worlds, a separator and a status line at the same time. (It proved to be quite complicated since Vim doesn’t support multi-line status bars).
Another interesting option could be having a global status line for all windows, this might be feasible to implement by using floating windows, although it sounds very hacky.
Anyway, hope this helped, have a good day!