Set Vim background based on your terminal's background color

Josh Sherman
4 min read
Command-line Interface Vim / Neovim Shell Script

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!

Join the Conversation

Good stuff? Want more?

Weekly emails about technology, development, and sometimes sauerkraut.

100% Fresh, Grade A Content, Never Spam.

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.

Currently Reading

Parasie Eve

Previous Reads

Buy Me a Coffee Become a Sponsor

Related Articles