Skip to content

Instantly share code, notes, and snippets.

@kristijanhusak
Last active March 6, 2024 18:15
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kristijanhusak/2039c3cca4a574c5521e39b4d0c5ce66 to your computer and use it in GitHub Desktop.
Save kristijanhusak/2039c3cca4a574c5521e39b4d0c5ce66 to your computer and use it in GitHub Desktop.
Toggle between light and dark colorschemes for both neovim and kitty

Requirements:

  • Neovim v0.4+
  • Python 3.4+ and pynvim
  • Kitty
  • Zsh, but would probably work with any shell if configured properly
  • Your favorite dark and light colorschemes

Installation

  1. Add below python script to ~/.config/kitty/ folder. Make sure to make it executable (chmod +x ~/.config/kitty/colors)
  2. Set up your dark/light colorscheme, and where to store kitty colors configuration (line 4 to 9)
  3. Run the script for first time manually to initialize the colors: ~/.config/kitty/colors dark. It will set up the color scheme and print some env vars, ignore it
  4. Add chunk of code from this .zshrc file to your ~/.zshrc
  5. Add chunk of code from this init.vim to your init.vim
  6. Add include to your kitty.conf (Check example below)
  7. Reopen kitty

Usage

  • To set specific background type, do colors light or colors dark
  • To toggle bg type, do colors toggle
  • To reload the current set up configuration, just run colors

How it works

  • Python script starts headless nvim instance and sets the selected colorscheme on it
  • All necessary colors for kitty colorscheme are then parsed from that instance (bg, fg, cursor, selection, terminal color pallete 0 to 15)
  • color_file provided is written with the kitty configuration, alongside with env variables needed for nvim
  • Env variables are returned from script so shell can export them in real time
#!/usr/bin/python3
# Where to store kitty configuration
color_file = '/home/kristijan/.cache/main_colorscheme.conf'
# Hash with dark/light colorschemes, background type => vim colorscheme nane
colorschemes = {
'dark': 'gruvbox',
'light': 'xcodelight',
}
import pynvim
import argparse
import os
import sys
from pathlib import Path
parser = argparse.ArgumentParser()
parser.add_argument('bg', nargs='?', default=None, choices=['dark', 'light', 'toggle'])
args = parser.parse_args()
bg = args.bg
current_bg = os.getenv('NVIM_COLORSCHEME_BG')
def set_env(background):
os.system('kitty @ set-colors --all --configured ' + color_file)
cmd = ['export NVIM_COLORSCHEME_BG=' + background]
cmd += ['export NVIM_COLORSCHEME=' + colorschemes[background]]
return cmd
if Path(color_file).exists():
cfile = open(color_file, 'r')
first_line = cfile.readline().rstrip()
current_bg = first_line.split('=')[1]
elif not bg:
print('You must provide background type argument on first run', file=sys.stderr)
exit()
if not bg:
print(';'.join(set_env(current_bg)))
exit()
if bg == 'toggle':
bg = 'dark' if current_bg == 'light' else 'light'
os.environ['NVIM_COLORSCHEME_BG'] = bg
os.environ['NVIM_COLORSCHEME'] = colorschemes[bg]
nvim = pynvim.attach('child', argv=["/usr/bin/env", "nvim", "--embed", "--headless"])
def get_hl_color(name):
hl_output = nvim.call('execute', 'hi ' + name)
bgcolor = None
fgcolor = None
for item in hl_output.split('\n')[1].split():
if item.startswith('guifg'):
fgcolor = item.split('=')[1]
if item.startswith('guibg'):
bgcolor = item.split('=')[1]
return fgcolor or '', bgcolor or ''
normal_fg, normal_bg = get_hl_color('Normal')
cursor_fg, cursor_bg = get_hl_color('Cursor')
selection_fg, selection_bg = get_hl_color('Visual')
command = [
'env NVIM_COLORSCHEME_BG=' + bg,
'env NVIM_COLORSCHEME=' + colorschemes[bg],
'foreground ' + normal_fg,
'background ' + normal_bg,
'cursor ' + (cursor_bg.startswith('#') and cursor_bg or normal_fg),
'cursor_text_color ' + (cursor_fg.startswith('#') and cursor_fg or 'background'),
'selection_foreground ' + (selection_fg.startswith('#') and selection_fg or 'none'),
'selection_background ' + (selection_bg.startswith('#') and selection_bg or normal_fg)
]
for i in range(0, 16):
command.append('color' + str(i) + ' ' + nvim.eval('g:terminal_color_' + str(i)))
nvim.close()
file = open(color_file, 'w')
file.write('\n'.join(command))
file.close()
cmd = set_env(bg)
is_bg_changed = bg != current_bg
if is_bg_changed:
# Do some additional work if needed
print(';'.join(cmd))
silent! exe 'set background='.$NVIM_COLORSCHEME_BG
silent! exe 'colorscheme '.$NVIM_COLORSCHEME
allow_remote_control yes
# Must match path set in python script for "color_file" variable
include ~/.cache/main_colorscheme.conf
colors() {
color_vars=$(~/.config/kitty/colors $1)
# Eval ensures that proper env variables are loaded in real time
eval ${color_vars}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment