Light/Dark Toggle for Neovim, Fish, and Kitty

Several months ago @elijahmanor posted a great little tech tip on switching themes in Kitty terminal. I had already built a version of this for Kitty and ZSH, but never updated it for Fish. He and I were talking afterward on how cool it would be to have Kitty, Neovim, and Fish all follow the same theme… which I eventually implemented but never documented.

The light/dark mode toggle consists of:

  • an environment variable to track the light/dark toggle
  • a Neovim theme that supports light and dark
  • a complementary light/dark theme for Kitty.
  • Fish functions to switch the themes.

Let’s dive in!

First: You need to tell Kitty to accept commands from other scripts:

allow_remote_control yes

(kitty.conf)

A key part of my implementation was switching to Zenbones as a Neovim theme. Years ago my friend Ben showed me his low-contrast, simple editor theme. He argued that not having the colors caused him to actually read the text rather than jump his eyes from keyword to keyword. I liked the idea, but never found a theme I liked more than my beloved Gruvbox.

light theme

I have been on Zenbones for four months now and really love it. It also conveniently ships with theme files for iTerm, Kitty, and other tools. This means that all I had to write were the fish functions!

function dark -d "Set dark theme"
  set -xU theme "dark"
  kitty @ set-colors -a "~/.local/share/nvim/site/pack/paqs/start/zenbones.nvim/extras/kitty/zenbones_dark.conf"
end

(dark.fish)

All it does is set the env variable and tell Kitty to use the Kitty theme provided by Zenbones. There is an equivalent light function. I honestly have no clue why set -xU works here… it just does. When you run the function in any session, it exports and changes in every session and pane of Tmux. 🤷

Last Neovim’s init.lua needs to listen to our new environment variable:

if os.getenv('theme') == 'light' then
  vim.o.background = 'light'
end

(init.lua)

That’s it! It’s not smart enough to go update the light/dark status for all the Neovim sessions already open, but thanks to vim-unimpaired that’s just a yob1 away.


  1. If you use vim-unimpaired, yob toggles :set background=dark/light 


🔖