Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW

'rgb_palette' - Term::ANSIColor Helper

by kcott (Archbishop)
on Aug 15, 2022 at 07:37 UTC ( #11146145=CUFP: print w/replies, xml ) Need Help??

G'day All,

I've been playing around with Term::ANSIColor recently. I found the named colours to be very limited. The rgbRGB format provides additional colours but the codes are not particularly intuitive. Then I found rNNNgNNNbNNN; at first, I thought I'd need a different terminal but it turns out that it works just fine on my xterm.

I'm quite familiar with the hex notation #rrggbb, but less so with the decimal equivalents; so I wrote myself a helper program: rgb_palette. I thought I'd share; but there are a few things you'd probably want to know up-front.

  • Obviously, you'll need a true color (aka direct-color) terminal.
  • Change the shebang line if it doesn't fit your setup.
  • Install IO::Prompter.
  • The code, as is, has "use v5.36;". You can downgrade this but, if you do, deal with the subroutine signatures (either turn off experimental warnings or rewrite the two short subroutines, e.g. "sub fg ($r, $g, $b) { ..." --> "sub fg { my ($r, $g, $b) = @_; ..."). Also, add in whatever pragmata you're no longer getting for free.
  • I use a black background. You may need to fiddle with some of the text colours if you use something else.
  • I initially had the hex values on each of the coloured swatches in either black or white. I found this distracting; change the commented code in fg() if you want to put it back that way. As it stands, the foreground and background colours are the same making the text invisible but the swatch colour more prominent. I just double-click on a swatch; middle-click to paste; then "Enter" to get the rNNNgNNNbNNN conversion.
  • I've aimed to get a lot of colours without needing a giant screen. You'll need 100 columns and scrolling will almost certainly be necessary. You can also type in your own hex codes if you want: the output shows a swatch of the input value as well as the rNNNgNNNbNNN code.

Alright, that's enough blathering, here's the code:

#!/usr/bin/env perl use v5.36; use IO::Prompter [ -style => 'bold blue', -echostyle => 'bold magenta', ]; use Term::ANSIColor 5.00; my @nums_under_255 = qw{0 26 51 77 102 127 153 179 204 230 243}; say ''; for my $r (@nums_under_255, 255) { for my $g (@nums_under_255, 255) { print ' '; for my $b (@nums_under_255) { print colored(text("r${r}g${g}b${b}"), join(' on_', fg($r, + $g, $b), "r${r}g${g}b${b}")); } say colored(text("r${r}g${g}b255"), join(' on_', fg($r, $g, 25 +5), "r${r}g${g}b255")); } } say ''; my $rgb; while (1) { $rgb = prompt 'Convert hex to decimal rgb (or just hit "Enter" to +quit): ', -return => ''; # Fix for MSWin -- see +?id=118255 $rgb =~ s/\R\z//; unless (length $rgb) { say ''; last; } if ($rgb =~ /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/) +{ my $ansi_rgb = sprintf 'r%dg%db%d', map hex, $1, $2, $3; print colored(' --> [', 'bold white'); print colored(' ' x 8, "$ansi_rgb on_$ansi_rgb"); print colored('] --> ', 'bold white'); say colored($ansi_rgb, 'bold cyan'); } else { say colored("\nERROR: '", 'r255g0b0 on_r51g51b51'), colored($rgb, 'r255g255b0 on_r51g51b51'), colored( "' is invalid. Six hexadecimal characters are expected +; such as in the table above.", 'r255g0b0 on_r51g51b51' ); } } sub fg ($r, $g, $b) { #return $r + 2 * $g + $b > 204 ? 'black' : 'white'; return "r${r}g${g}b${b}"; } sub text ($str) { return sprintf ' %02x%02x%02x ', $str =~ /^r(\d+)g(\d+)b(\d+)$/; }


Updates: Some people encountered problems, so I've made changes.

  • Term::ANSIColor introduced support for 24-bit colour in v5.00 (see Changes). I wasn't aware of this. I've changed "use Term::ANSIColor;" to "use Term::ANSIColor 5.00;". Thanks ++pryrt for reporting this.
  • For MSWin users, there's a bug in IO::Prompter. Again, thanks ++pryrt for reporting this. As a workaround, I've added:
    # Fix for MSWin -- see +?id=118255 $rgb =~ s/\R\z//;
  • Also for MSWin users, there's been some discussion, in a number of responses, about whether the module Win32::Console::ANSI, or the registry setting VirtualTerminalLevel, is required for this code to work. Not being in a position to test this, I can't comment further.

— Ken

Replies are listed 'Best First'.
Re: 'rgb_palette' - Term::ANSIColor Helper
by roho (Chancellor) on Aug 16, 2022 at 05:10 UTC
    Thanks Ken! This will be very useful. For those running Perl on MS Windows, I found I also need the following additional module to display colors:

    use Win32::Console::ANSI;

    "It's not how hard you work, it's how much you get done."

      G'day roho,

      Your welcome; I'm glad you'll find this useful.

      Thanks for adding the MSWin info — that's appreciated.

      — Ken

        Hello and thanks kcott,

        on strawberry 5.26 I have modified your program first lines as..

        use strict; use warnings; use feature qw (say signatures); no warnings qw(experimental::signatures); # use Win32::Console::ANSI; # nothing change if loaded or not

        but I still receive the error Invalid attribute name r0g0b0 at line 23. which is the line

        print colored(text("r${r}g${g}b${b}"), join(' on_', fg($r, $g, $b), "r${r}g${g}b${b}"));

        I also changed the TERM env var from dumb to not dumb (used to work) but still receiving the same error.


        There are no rules, there are no thumbs..
        Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: 'rgb_palette' - Term::ANSIColor Helper
by Tux (Canon) on Aug 17, 2022 at 08:57 UTC

    You might be interested in my xclorsel a Tk GUI to available X11 colors.

    Not changed since 2007-05-08, so maybe apt for modernisation.

    In relation: I have dis_colors to show the current setting for you ANSI-compliant terminal (xterm) related to colors. That makes it easier to choose the combination to select for your messages. This tool could do with an extension to show what to use from Term::ANSIColor, though that would make the display rather wide.

    Note w.r.t. rgb_palette: I use light background and usually discard every tool that uses a black/dark background by default and has no easy/intuitive option to switch to light background. This excludes currently many IDE's as they default to dark background and their option(s) to switch to light background are not implemented well as obviously their developers do not use it. My own tools all default to something "nice" (YMMV) on a light background but when useful, a simple option or rc setting is supported for those that prefer a dark background.

    It took me a bit to remember, but in the xterm source distributions come with color-tests in the vttests subfolder that show something similar to your rgb_palette.

    EDIT: ExtUtils::MakeMaker is CORE and also comes with a prompt function, so you don't require an extra non-core dependancy.

    Enjoy, Have FUN! H.Merijn

      G'day Tux,

      ++ Thanks for this wealth of information. I played with everything but don't have time to go into it all, in any great depth, right now (it's late evening here): some funtime ahead for the weekend.

      • xcolorsel — I had to change the shebang, but otherwise it worked out of the box; I like how you've displayed the full colour and the individual RGB components; I liked the second two dropdown lists ("/in name" & "/similar") which I see as being quite useful.
      • dis_colors — That's handy to get the codes and gives an immediate visualisation of foreground & background combinations. Term::ANSIColor provides a variety of ways to specify colours (strings, constants & arrayrefs); I don't have an answer to how you might lay out the display to include them.
      • vttests — I downloaded which was the latest. There are about 60 scripts in vttests/; I didn't see anything that looked like "color-tests"; I poked around in quite a few but didn't find the functionality you mentioned (i.e. "similar to your rgb_palette"). Could you provide specific filenames?
      • ExtUtils::MakeMaker::prompt() — I was aware of this but thanks for mentioning it anyway (you weren't to know and it's possibly useful for others). I do like the feature-rich IO::Prompter module; the menus are perhaps my favourite bit.

      At the outset, I'll say that I pretty much agree with what you said regarding light & dark backgrounds. In addition, I'm cognisant of accessibility issues (colour blindness, contrast, and so on).

      At the start of this thread, I said that I didn't find the rgbRGB codes intuitive. Initially, this script simply printed a 6x6x6 grid of those codes and the colours they represented. At that point, it was just a quick-and-dirty piece of code to help me with that.

      I then found the rNNNgNNNbNNN codes and realised, somewhat surprisedly, that I could use them. The script progressed from there, through multiple iterations, to what you see above. It was only after completion that I thought, "Others might find this useful; I should share".

      For your, and indeed anyone else's, light background, I think you may just need to make some very minimal changes: for instance, white to black (2 instances; 3 if you've changed fg()) and cyan to green (1 instance). Alternatively, you could use "on_black" for all of the text; although, I think that might end up looking a little messy. If you do make such changes, I'd appreciate feedback on your choices.

      — Ken

        Could you provide specific filenames?

        I should have mentioned,, and

        Regarding prompting, I find that perlfaq is missing some basics. There is a tiny part on how to read passwords and that is all.

        I had 2255 modules installed on my laptop and IO::Prompter was not one of them (now it is), so I think that proves it is not widely used.

        Enjoy, Have FUN! H.Merijn
        Hello kcott,

        > I do like the feature-rich IO::Prompter module; the menus are perhaps my favourite bit.

        well.. I dont know how to be kind about this, but I have a radical different opinion.

        Given anyone is free to choose their tool I find very irritating to spot a nice perl module ( IO::Prompter ) with this statement in the docomentation:

        Several features of this module are known to have problems under Windo +ws. If using that platform, you may have more success (and less distr +ess) by trying IO::Prompt::Tiny, IO::Prompt::Simple, or IO::Prompt::H +ooked first.

        Well.. it is kind to inform me, but consider this situation:

        Hey my friend! For sure I can lend you my wonderful supercar: it is very safe and fast but if you are not tall exactly 183 cm and 90 Kg the car probably will only go 40Km/h and the car can skid when cornering if your feet are not exactly 10 sized.

        :( thanks, better I'll take the bus..

        My busses are:

        use Term::Readline; $ENV{PERL_RL} = "Perl"; my $term = Term::ReadLine->new('sweet_ol_bus'); $term->Attribs->{completion_function} = sub { my $txt = shift; return grep { /^$txt/i } sort keys %$my_list_of +_autocompletion; }; my $in; while ( defined ( $in = $term->readline( 'my_prompt>' ) ) ) { chomp ($in); ... }

        More kind for IO::Prompter should be to have 00_OStest.t stating BAIL_OUT() if $^O eq "MSWin32" and instead I see all tests passing with only, ironically being an interactive module, t/styles.t ....................... skipped: Skipping interactive tests under Windows while all other interactive tests are ok:

        All tests successful. Files=38, Tests=163, 53 wallclock secs ( 0.09 usr + 0.09 sys = 0.19 +CPU) Result: PASS

        So please, consider it carefully before adopting a module if you plan to share your code widely. This is not criticism about you nor your code kcott, absolutely.

        You will see me at the next Perl conference selling t-shirts with: Strawberry setups matter and Say NO to OSsism

        </rant> :)


        There are no rules, there are no thumbs..
        Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: CUFP [id://11146145]
Approved by marto
Front-paged by marto
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (1)
As of 2023-06-04 20:46 GMT
Find Nodes?
    Voting Booth?
    How often do you go to conferences?

    Results (22 votes). Check out past polls.