xterm background color

From Noah.org
Revision as of 06:22, 21 May 2010 by Root (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search


How do you get the background and foreground color of an xterm window?

Why do I care? Well, I care because I want some way to automatically set the 'background' option in Vim. Sometimes my terminal is black on white; sometimes it is light on dark. I use the same .vimrc everywhere. I have <F3> mapped to toggle 'background'. That has helped keep me from going insane, but I have always wanted some way for Vim to just figure out if my background is darker than my text, or if my text is darker than the background.

This works... mostly. It probably won't work over a remote SSH connection ;-) This might also be considered pretty far off into the deep end, but I think the basic idea is sound. First, I dump a few lines of octal from a common binary to make sure the terminal is filled with a good sampling of text. Then I get an X Window dump image of the current window and get a histogram of all the colors sorted by the most frequent color first. Then I grab the top two values out of the luminosity column and compare them. I figure the most common color is the background and the second most common color is text. I have to have Image Magick and PNM-Tools installed. I was almost able to do it without Image Magick, but the `xwdtopnm` command would fail on some windows because it thought the images from `xwd` were sometimes over 24 bits per pixel.

If you don't have all the tools installed then just run this on Ubuntu or Debian:

apt-get -q -y install netpbm imagemagick

Anyway, I'm ashamed to say how long I spent figuring this out (2 or 3 hours, probably).

Save the following script to a file named `background` somewhere in your path. Then invoke Vim as vim -c "set background=$(background)". Finally, to show it worked run this Vim command: :echo &background.

#!/bin/sh

# I turned off the octal dump since it mostly works without it
## od /usr/bin/ld | head -n 40 \
## && \
## I also found that it was handy to ignore total blackness, so 
## I added the 'grep -v' line.

   set $(echo \
         $(xwd -icmap -id $WINDOWID -silent | \
           convert - pnm:- | \
           ppmhist -nohead | \
           grep -v -E -e "^[[:space:]]*0[[:space:]]*0[[:space:]]*0" | \
           head -n 2 | \
           awk '{print $4 }' \
          ) \
        ) \
&& if [ $1 -gt $2 ]; then echo "light"; else echo "dark"; fi