Configuring Auto Dark Mode

Published Tue Jan 23 2024

For my terminal and editor I appreciate a theme with tasteful palettes for dark and light mode. This is a big reason why I use Rose Pine. Switching between themes isn’t that hard, but automatic switching on day/night schedules has become my preferred way of theming. This was until my plugin for Neovim stopped working! There is not an api for checking the appearance preference of your OS in Neovim. After some thought and lots of Googling I remembered my terminal Wezterm has an appearance api!

(fn get_appearance []
  (if wezterm.gui
    (string.lower (wezterm.gui.get_appearance))
    "dark"
))

Using Fennel of course, I created a small function that uses wezterm.gui.get_apperance. This can return 4 possible values: Light, Dark, LightHighContrast, and DarkHighContrast.

Since this is my personal machine and I don’t use high contrast themes, I can ignore them for now. After getting this value from Wezterm I transform it into lowercase since Neovim background value of “dark” or “light” is lowercased.

This value is inside my Wezterm config though, I need to read it from Neovim. Luckily there’s another Wezterm api that can set environment variables in the window, not so surprisingly named set_environment_variables.

(tset overrides :set_environment_variables {
  :WINDOW_APPEARANCE (get_appearance)
})

I already have a handler for window update events, so all I needed was to add my environment variable to the overrides. Once set, this will be equivalent to export WINDOW_APPEARANCE=dark except using the Wezterm api value.

{
  1 :rose-pine/neovim
  :name "rose-pine"
  :lazy false
  :priority 1000
  :config (fn []
    ((. (require :rose-pine) :setup) { :dark_variant "moon" })
    (vim.cmd "colorscheme rose-pine")
    ;; window_appearance is set in wezterm config
    (let [appearance (os.getenv :WINDOW_APPEARANCE)]
      (when (= appearance nil) (set apppearance "dark"))
      (vim.api.nvim_set_option_value "background" appearance {})
  ))
}

Now I just need to reference this environment variable to set Neovim’s background option. Since I’ve taken care of the casing in Wezterm, the value can be passed straight into vim.api.nvim_set_option_value! I was pleasantly surprised at how simple this ended up being once transitioned from using a plugin. Thank you to f-person on GitHub for making the plugin I was using before auto-dark-mode.nvim.

The complete code for this post can be found in my dotfiles repo