by Joel Tari

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.