Toggling background color in kitty and vim (yob)

shell
vim
Author

Arumoy Shome

Published

January 19, 2024

Abstract

yob is a tiny shell script which toggles between a light and dark colorscheme in Kitty, my terminal of choice.

yob is a shell script that I wrote to toggle between a light and dark colorscheme in Kitty, my terminal of choice. Some additional configuration also allow me to sync the vim colorscheme to that of kitty. This is a much simpler version of this script by Greg Hurrell.

The name is inspired by the vim-unimpaired package for vim. The package adds keybindings prefixed with the yo* that toggle various vim settings. The b in yob stands for “background”.

Here is the script in its entirety as of 2024-01-19. You can also find the latest version in my dotfiles repository.

yob
#!/usr/bin/env bash

LIGHT_THEME="colors/gruvbox-light.conf"
DARK_THEME="colors/gruvbox-dark.conf"
LOCATION="$HOME/.local/share/yob"
VIM_BG_FILE="$LOCATION/background"

__init() {
  [[ ! -d "$LOCATION" ]] && mkdir -p "$LOCATION"
  [[ ! -e "$VIM_BG_FILE" ]] && touch "$VIM_BG_FILE"
}

__update() {
  (
  cd "$HOME/.config/kitty"
  if [[ "$1" == "light" ]]; then
    ln -sf "$LIGHT_THEME" current-theme.conf
    echo "light" >"$VIM_BG_FILE"
  else
    ln -sf "$DARK_THEME" current-theme.conf
    echo "dark" >"$VIM_BG_FILE"
  fi
  )

  kitten @ set-colors --all --configured "$HOME/.config/kitty/current-theme.conf"
}

__toggle() {
  local CURRENT_BG
  CURRENT_BG="$(head -n 1 "$VIM_BG_FILE")"
  if [[ "$CURRENT_BG" =~ "light" ]]; then
    __update "dark"
  else
    __update "light"
  fi
}

main() {
  if [[ ! "$TERM" =~ "kitty" ]]; then
    echo "yob: not running kitty, doing nothing."
    exit 1
  fi

  if [[ ! -e "$VIM_BG_FILE" ]]; then
    __init
    __update "dark"
    exit 0
  fi

  __toggle
}

main "$@"
1
Some initial setup. Here we define the location of the light and dark colorscheme files for kitty (I choose to save them in the kitty config directory and check it into git so that they are available wherever I clone my dotfiles repo). We also store additional data for yob in ~/.local/share/yob/background as per XDG best practices for unix systems.
2
Here we create a symbolic link between the colorscheme file and current-theme.conf. The current-theme.conf file is picked up by kitty next time it starts. Finally, we set the theme for the existing kitty sessions using kitty @ set-colors.
3
This function toggles between the light and dark themes based on information in ~/.local/share/yob/background.

Choosing a colorscheme with light and dark variant

After many experiments with various colorschemes in different lighting conditions, I picked Gruvbox as my theme of choice. There are several reasons for this decision:

  • The colorscheme has been around for a little over 10 years and is very stable (very few changes since 2018 as per the commits chart on github).
  • Both light and dark variants of the theme are legible in various lighting conditions.
  • Due to its popularity, the theme is available in Kitty and Vim 9 out-of-the-box.

Preserving kitty colors across sessions

To preserve the colorscheme across kitty sessions, yob symlinks the colorsheme files to current-theme.conf in kitty’s config directory. The following line ensures that kitty sources the right colorscheme next time kitty starts.

~/.config/kitty/kitty.conf
include current-theme.conf

Syncing vim colors with kitty

The aru#set_background() function reads the first line of ~/.local/share/yob/background using the built-in readfile function in vim (see :help readfile) and updates the background.

.vim/autoload/aru.vim
function! aru#set_background() abort
  let config_file = expand('~/.local/share/yob/background')
  if filereadable(config_file)
    let bg = readfile(config_file, '', 1)[0]
  endif

  execute 'set background=' .. bg
endfunction

If we run yob from another shell, the colors in existing vim sessions does not update. To account for this I introduce an autocommand that is fired every time vim is started and when it gets focus.

.vimrc
set termguicolors
color retrobox

function! AruAutoBackground() abort
  augroup AruAutoBackground
    autocmd!
    autocmd FocusGained,VimEnter * call aru#set_background()
  augroup END
endfunction
call AruAutoBackground()
Back to top