Like most developers, I prefer dark mode in my terminal and code editor.
🌺 Spring is coming around however, and that means, somewhere between 3 and 4 o’clock in the afternoon, the sun is starting to produce a nasty glare on my monitor making dark mode an unacceptable choice.
I threw some code at this problem and now I can quickly switch between light and dark mode from the command line.
I’m using the well-known Solarized theme, which is especially great in this case because it has a light and dark variant.
I use iTerm2 and I installed the official Solarized dark iTerm2 theme. It actually doesn’t matter that much since I’m running Tmux, which will have its own color handling and is overlaid on your terminal.
In Tmux I’m using two custom themes, a dark one and a light one. Normally I would not recommend customly theming anything unless you really like minutiae. However, there are not a lot of interface elements in Tmux, so you can quickly get a nice result without too much configuration. Just make sure your colors match the Vim theme. You can find the files in my dotfiles repository.
In my tmux.conf file I include the dark theme by default:
One very important line is at the bottom of both my theme files:
setenv -g TMUX_THEME dark
This sets an environment variable containing the current theme, which we’ll get back to in the Vim section.
In Vim I’m using this variation of Solarized which is optimized for terminal Vim.
I’m using these settings to ensure proper color handling:
let g:solarized_termcolors=256 colorscheme solarized8
Switching theme from the command line
I’ve created two bash files,
dark.sh, to switch theme from the command line.
They look like this:
The first line of each file sources the right theme file.
Awesome! Now we can very quickly switch Tmux theme, and the MacOS style will follow suit.
Switching theme is a matter of running
$ sh ~/light.sh
💡 Alternatively, you can put this in a function. I’m using Fish shell, and actually have two Fish functions that call the above
sh command. Having the scripts in separate files worked best for me when integrating with Vim, due to PATH issues.
We’re not done: when starting a new Vim session, it will just use whatever your default
background setting is, probably
To fix this, we’re going to listen to that environment variable we configured above:
function! Chomp(string) return substitute(a:string, '\n\+$', '', '') endfunction let tmuxtheme = split(Chomp(system('tmux show-environment -g TMUX_THEME')), "=") if tmuxtheme == "dark" set background=dark else set background=light end
This bit of code should go in your
.vimrc file. It parses the current
TMUX_THEME environment variable, and switches
Neat! Now new Vim sessions will follow along with our current preference.
Switching theme from Vim
Last but not least, we need a way to toggle the theme from within Vim.
Add the following functions to your
function! Dark() set background=dark silent !sh ~/path/to/dark.sh endfunction function! Light() set background=light silent !sh ~/path/to/light.sh endfunction command! Dark call Dark() command! Light call Light()
You can now call
:Light from within Vim to switch theme, and actually have MacOS and Tmux follow right along.
One point of all this is to stop the jarring effect of switching to a white screen after working in a dark terminal for a while. Luckily a lot of software nowadays contains an option for switching theme automatically when the OS preference changes. Slack and Brave Browser for instance both respect this system setting. This really helps, so make sure to use that option.
Since a lot of my tools these days live in the browser, and websites can actually implement CSS based on the system setting, you might get lucky. It depends on the sites you frequent. DuckDuckGo, Twitter, and this blog will fall in line neatly.
One improvement that I’m still thinking about, is to change the theme in running Vim sessions. I usually work using a dozen Tmux sessions for different projects, containing their own Vim processes. A running Vim process won’t re-evaluate their colorscheme when I change the system setting from elsewhere.
Is there a way to get a list of running Vim commands, and passing a command to them? I don’t know.
Might be a fun trick. On the other hand…