Dynamic Vim Themes

Obsessively keeping my Vim and Terminal themes in sync

Dynamic Vim Themes

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
    if !empty($VIM_COLOR)
        colorscheme $VIM_COLOR
        " Prefered default colorscheme
        colorscheme wombat256mod
catch /^Vim\%((\a\+)\)\=:E185/
    " Colorschemes not installed yet
    " This happens when first installing bundles
    colorscheme default


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

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!