views:

80

answers:

3

I'm currently using the following code to output text in green to the terminal:

printf("%c[1;32mHello, world!\n", 27);

However, I want more shades of green. What's the easiest way to accomplish this?

A: 

This may help you:

http://en.wikipedia.org/wiki/ANSI_escape_code

You can only really get 2 different shades of each colour. Try replacing the 1 with a 2 to get dark green.

Mike Weller
This isn't always true. Many terminals allow you to define any shade of colour you like for each colour code using the `initc` terminfo capability.
Charles Bailey
+2  A: 

How you do this depends on your terminal. You may should be able to query a termcap or terminfo database to find out how.

This is easiest to demonstrate with some tput commands.

E.g. on my current terminal:

tput initc 2 500 900 100
tput setaf 2

Defines colour 2 to be a shade of green (the parameters are RGB values between 0 and 1000) and switches the foreground to this colour.

To see the character sequence needed in a C program for your given terminal you can display the capabilities with infocmp.

E.g. (for my terminal)

$ infocmp -1 | grep initc
        initc=\E]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x,
$ infocmp -1 | grep setaf
        setaf=\E[38;5;%p1%dm,

The % paramter formatting is a bit (OK very) painful to parse but is documented in the infocmp man page. Translating this to printf format string isn't too hard.

Charles Bailey
+2  A: 

You can use the 256colors2.pl script on Rob Meerman's site to make sure that your terminal handles 256 colors correctly. Then choose the right combination of RGB values to give you the right shade of green.

Based on his script, it looks like the color numbers are essentially an offset of a base 6 color scheme:

COLOR = r*6^2 + g*6 + b) + 16

And for the foreground color we need to use:

\x1b[38;5;${COLORNUM}m

And again based on his script, here's a (perl) loop that displays the letter O in the desired color:

# now the color values
for ($green = 0; $green < 6; $green++) {
    for ($red = 0; $red < 6; $red++) {
        for ($blue = 0; $blue < 6; $blue++) {
            $color = 16 + ($red * 36) + ($green * 6) + $blue;
            print "\\x1b[38;5;${color}m :\x1b[38;5;${color}m O\x1b[0m ";
            print "\n" if ($blue == 2 || $blue == 5);
        }
    }
    print "\n";
}

And here's a sample of its output:

Screenshot showing color value samples

NOTE: Charles seems to quite a bit more about how it actually works and what you'll need to do to verify that the the shell supports the required capabilities. My information is based strictly on observation and testing with a shell known to support 256 colors (konsole).

Kaleb Pederson