Dynamic Vim Themes
Obsessively keeping my Vim and Terminal themes in sync
As a software developer, I often spend time in my computer terminal. And, as a nerd, I primarily use the Vim or Neovim text editors for all my coding. I've obsessively configured both of these such that I can migrate my exact configuration between machines with ease and feel right at home.
These days terminal windows are not limited to "hacker mode" with green text on black backgrounds, but much wider spectrum of colors and pleasing themes. The experience becomes a little less pleasing when you launch your editor and the whole thing changes! This lead me to some handy Vim configuration to allow my terminal to tell it what theme to use and some handy shell scripts to determine what terminal theme I'm using.
First, Vim! This part's actually really simple. In my massive directory of Vim settings, I've got this snippet:
" Color Schemes {{
" Set theme based on $VIM_COLOR variable
try
if !empty($VIM_COLOR)
colorscheme $VIM_COLOR
else
" Prefered default colorscheme
colorscheme wombat256mod
endif
catch /^Vim\%((\a\+)\)\=:E185/
" Colorschemes not installed yet
" This happens when first installing bundles
colorscheme default
endtry
It's actually very simple. It just checks for an environment variable from the terminal I launched it and attempts to use that as the colorscheme. There's a little bit of logic for the default value and a fall-back if the colorscheme hasn't bee installed yet, but it's really quite simple. It allows you to add export VIM_COLOR=mytheme
in your .bash_profile and Vim will pick it up.
In order to make sure that variable matches my terminal theme, I must set it somewhere dynamically. This is where it gets a little tricky.
The easy way
On Ubuntu, or anywhere I can't do auto detection, I edit each terminal profile and set a custom command for the shell. There I can use env
to set the variable. For example env VIM_COLOR=wombat256mod fish
or env VIM_COLOR=solarized bash
. That will start my desired shell with a particular colorscheme set to match.
This works almost universally and is very simple to set up. So I decided to try something more elaborate.
The hard way
On macOS I've been using a script I wrote that returns a colorscheme for me based on a terminal's colors. It's easy enough to get these values on macOS with a few lines.
On iTerm you can use $ITERM_PROFILE
and you're done. If I'm using Apple Terminal, the following Apple Script will let me know what my window profile name is by locating the current window and grabbing it's settings.
# Returns terminal profile for Apple Terminal
osascript <<EOD
set current_tty to "$(tty)"
tell application "Terminal"
repeat with win in windows
repeat with the_tab in tabs of win
set tab_settings to the current settings of the_tab
if current_tty is equal to the tty of the_tab then
return the name of tab_settings
end if
end repeat
end repeat
end tell
EOD
Putting it all together, I have this script called in my shell configuration to set the $VIM_COLOR
variable on both bash and fish.
And that's it!