Set Vim background based on your terminal’s background color

I’ve been spending more time at the pool lately (sorry, not sorry) and I’ve
found myself manually switching between a light and a dark gnome-terminal
theme.

This was all well and good, but my .vimrc includes set background=dark so
regardless of which theme I’m using in the terminal, vim has a dark
background.

Searched a far and wide on the interwebs and I couldn’t find a decent solution.
Most of the tips were outdated and relied on deprecated technologies (e.g.
gconf) and everything else just wasn’t quite enough to run inside of vim.

Determined, I set out to write a solution that would tell vim the current
background color and then use said value to dynamically set the background color
to either light or dark.

Just for reference, I use the Solarized color scheme and toggle between the
light and dark versions.

As mentioned, I also use gnome-terminal so YMMV on other terminals.

The star of the show is an app called xtermcontrol that can return the
background color of your terminal. The problem is, once you’re inside of vim,
you can’t use the command because it can’t figure out what your terminal is.

I read that you could simply run an escape code to return the value so
xtermcontrol isn’t necessarily a hard dependency. With that, I couldn’t make
heads or tails on how to pull that off, so I am relying on xtermcontrol.

Before I get into the code, let me give you a high level overview of what I’m
doing.

First, I created a vim function that serves as an alias to vim.

The alias runs xtermcontrol --get-bg which gets the background color and then
uses said value to pass vim a --cmd argument to set a theme value.

Inside of .vimrc I check that theme exists and if it’s set to light. If it
is, run set background=light otherwise fallback to the dark theme.

One gotcha I noticed is that when I run git commit I always end up with a dark
background in vim. Assumption is it’s because git is running vim
differently and it’s completely bypassing my alias function.

Simply put, it wasn’t a big enough deal for me to get it fixed.

Feel free to send me a PR if you know how to get shit working 😉

So now you know the gist of what I was trying to accomplish, and here’s the
code:

.zshrc

I use zsh but this outta work well in bash and I make zero claims about
whether or not this would work in fish or any other shells.

Depending on your theme’s background color, you will need to adjust
rgb:0000/2b2b/3636 to be whatever your dark theme’s background color is.

You can get that value by running xtermcontrol --get-bg.

function vim {
  BACKGROUND=$(xtermcontrol --get-bg)

  if [[ "$BACKGROUND" == "rgb:0000/2b2b/3636" ]] then
    env vim --cmd "let theme = 'dark'" $@
  else
    env vim --cmd "let theme = 'light'" $@
  fi
}

.vimrc

In the aforementioned alias, I pass a --cmd that sets the theme value that
we can interrogate inside of the .vimrc:

if exists('theme') && theme == 'light'
  set background=light
else
  set background=dark
endif

Worked well enough for me. Next time I’m at the pool and I switch to Solarized
light in the terminal, vim should adjust accordingly.

Probably should figure out how to switch my terminal profile with a command
instead of that pesky right-click, going to profiles and then selecting my
theme.

Better still, wonder if I could tap into the ambient light sensor and do this
all automagically O_O

Happy hacking folks, and remember that I keep all of my dotfiles out on
GitHub*
ready for some serious forking!

  • For now at least, we’ll see how this Microsoft acquisition goes 😉
Josh Sherman - The Man, The Myth, The Avatar

About Josh

Husband. Father. Pug dad. Musician. Founder of Holiday API, Head of Engineering and Emoji Specialist at Mailshake, and author of the best damn Lorem Ipsum Library for PHP.


If you found this article helpful, please consider buying me a coffee.