Vim your way in the GUI: Neovide Configuration
What is Neovide
Neovim is a vim-based text editor that lives in the terminal. Neovide is one of the GUI that provides a graphical user interface for Neovim, in the sense that although it still looks like the terminal, it is not, allowing for some graphical improvements.
Smooth scrolling and cursor effects are enticing for me. You can easily track cursor position when jumping around, and it makes various transitions smooth, while keeping all the functionalities and configurations of Neovim.
However, you could miss some terminal features or shortcuts such as changing the font size easily. I also encountered problems with some color schemes in the integrated terminal shell: the fallback colors were not properly defined.
In this post, I use some lua
code to fix those issues in the configuration.
Configuring init.lua
for Neovide
init.lua
(or init.vim
) normally holds the configuration for Neovim, it is
also read by Neovide. In addition, Neovide adds its own setting variables in the
config.
Our first action is to insulate our neovide specific config from the rest of the
init.lua
.
-- init.lua
if vim.fn.exists("g:neovide")==1 then
vim.notify("This notification should only appear on neovide !")
-- your neovide specific config here
-- e.g. set the refresh rate
vim.api.nvim_set_var( "neovide_refresh_rate", 75)
-- more config goes here
-- ...
end
Wrapping the Neovide specific configuration in this if/end
block will not
poison our usual Neovim config.
Check
https://neovide.dev/configuration.html
to examine all the options. I might add that you can leverage the
vim.fn.getenv()
to conditionally set options depending on your shell
variables. For instance, the neovide_refresh_rate
value might be different
across your machines and monitors. You can save that information into a shell
environment variable $MONITOR_RATE
, and access it in init.lua
via
vim.fn.getenv("MONITOR_RATE")
.
A more elaborate alternative is to query the result of a shell command using
Lua’s io.popen()
. I could then for example check if my laptop is unplugged by processing
/sys/class/power_supply
and conditionally adjust the refresh rate to save battery.
Setting the font
I set the font family, weight and size using :
vim.o.guifont = "JetBrainsMono Nerd Font:style=Regular,Regular:h12"
The trailing number represents the font size.
Make text smaller and larger
It would be pleasant to be able to adjust the font size when several windows are opened. At this time, there is a built-in way to do it, so we will come up with our own solution.
In a nutshell, I want to increase/decrease the font size by pressing
Ctrl-equal
/Ctrl-minus
in vim normal and visual modes. This should be
achieved by editing the relevant portion of vim.o.guifont
.
This is the additional configuration code:
-- zoom
vim.keymap.set("", "<C-=>",
function ()
-- find & get current font size
local _, _, font_size = vim.o.guifont:find(".*:h(%d+)$")
font_size = tostring( tonumber(font_size)+1 )
-- update the font size
vim.o.guifont = string.gsub(vim.o.guifont, "%d+$",font_size)
end,
{noremap = true}
)
-- dezoom
vim.keymap.set("", "<C-->",
function ()
-- find & get current font size
local _, _, font_size = vim.o.guifont:find(".*:h(%d+)$")
if tonumber(font_size) > 1 then
font_size = tostring( tonumber(font_size)-1 )
-- update the font size
vim.o.guifont = string.gsub(vim.o.guifont, "%d+$",font_size)
end
end,
{noremap = true}
)
I am basically using Lua patterns methods
to infer the current font size from the string
"JetBrainsMono Nerd Font:style=Regular,Regular:h12"
, i.e. 12
in this case,
and then incrementing/decrementing that number. Both functions are wrapped into
vim.keymap.set
, which is the preferred approach to define custom mapping in
Neovim config.
Fixing bad terminal colors
Many great color schemes available out there don’t properly define terminal
colors. In Neovim proper, the fallback colors are defined by the underlying
terminal program (e.g. the content of alacritty.yaml
for the Alacritty
terminal). Thus, the colors in your Neovim embedded terminal are the same as
your terminal colors. This is why most authors of color schemes don’t have the
incentive to specifically define terminal colors for Neovim.
The adverse effect for Neovide is that the fallback colors in the embedded terminal are not defined. The program Neovide is independent of your terminal and doesn’t know anything about what terminal you are used to, and where to find those color values.
So I have defined some Gruvbox inspired color values.
-- detecting if the terminal colors are defined (the 0-th one at least)
if (vim.fn.exists("g:neovide")==1 and vim.fn.exists("g:terminal_color_0")==0)
vim.api.nvim_set_var( "terminal_color_0" , '#352F2A')
vim.api.nvim_set_var( "terminal_color_1" , '#B65C60')
vim.api.nvim_set_var( "terminal_color_2" , '#78997A')
vim.api.nvim_set_var( "terminal_color_3" , '#EBC06D')
vim.api.nvim_set_var( "terminal_color_4" , '#9AACCE')
vim.api.nvim_set_var( "terminal_color_5" , '#B380B0')
vim.api.nvim_set_var( "terminal_color_6" , '#86A3A3')
vim.api.nvim_set_var( "terminal_color_7" , '#A38D78')
vim.api.nvim_set_var( "terminal_color_8" , '#4D453E')
vim.api.nvim_set_var( "terminal_color_9" , '#F17C64')
vim.api.nvim_set_var( "terminal_color_10" , '#99D59D')
vim.api.nvim_set_var( "terminal_color_11" , '#EBC06D')
vim.api.nvim_set_var( "terminal_color_12" , '#9AACCE')
vim.api.nvim_set_var( "terminal_color_13" , '#CE9BCB')
vim.api.nvim_set_var( "terminal_color_14" , '#88B3B2')
vim.api.nvim_set_var( "terminal_color_15" , '#C1A78E')
end
Make sure that this code gets executed only after
vim.cmd('colorscheme MyColorSchemeName')
is called.
Final Thoughts
When doing quick editing on smaller files, I still use Neovim to stay in the terminal. Neovide is great for wide screens when working on large projects. The default animations are reasonable, and they help keep track of what is going on in your screen.
There are nonetheless a few hiccups in setting the configuration for Neovide. Hopefully this post that has provided some guidance in that regard.