ANSI Terminal Colors, in Brief

!!! Skip to “Basic Terminal Colorization” for the first code example.
!!! Skip to “Teaser: Initialization of ANSI Colors in Perl“ if you already understand the codes and are ready to grab a skeleton Perl script to hack at.
Below are paste-able command examples of how to generate ANSI color codes. That’s all. It’s not the full standard, and there is no advanced terminal manipulation. You can find all that elsewhere. But, this is where I’ll come when I need to remind myself of how this is done, without having to—once again—wade through all those other references (as I had to do to generate these examples).
Other Articles in the Series:
Preliminaries
Note that this should be optional, which means you should be able to skip this. But, it’s here if you need it (or want to explore multi-line commands (which I guess I might have to do a post on).
I won’t do this often on this blog, but these are medium-sized multi-line commands. I’ve done what I can to make sure they’ll work whether you are setup for this or not. It’s just that there are some things that are too small and trivial for writing them as a full script. Apologies if you find this irksome, but I will strive not to over use this.
Below are my .bashrc settings, in case you want to see what working with multi-line commands are like, particularly if you use set -o vi
or are otherwise adept at command-line editing.
.bashrc Settings for Multi-line Editing:
export HISTCONTROL=ignoredups
export HISTIGNORE=$'[ \t]*:&:[fb]g:exit'
export HISTSIZE=2000
export HISTFILESIZE=8000
export PROMPT_COMMAND="history -a"
test -t 1 && export PROMPT_COMMAND='history -a && echo -e "\e]2;${USER}@$(hostname) $(pwd)\a"'
shopt -s cmdhist histappend histreedit histverify lithist
shopt -s interactive_comments
set -o vi
export LC_COLLATE=C
Basic Terminal Colorization
Try This (in Bash):
(
for bg in {40..47} {30..37}; do
cd="\e[${bg}m";
echo -ne $cd;
echo -n " $cd ";
echo -e '\e[00m';
done;
)
Notes
The parenthesis aren’t necessary. The parenthesis in this form is not a technique in common usage. It just keeps the variables local, so that the variables in the code I share don’t happen to pollute your environment. Savvy scripters will not even bother to copy them.
Obligatory Sample Output (Full):
More Complex Colorization
Try This as Well (Again in Bash) and on Different Terminals:
(
for md in {1..9}; do
for bg in {40..47}; do
for fg in {30..37}; do
cd="\e[${bg};${fg};${md}m";
echo -ne $cd;
echo -n "$cd ";
echo -ne '\e[00m';
done;
echo;
done;
done;
)
Notes
This uses three codes for the ANSI colorization: background, foreground, mode. Order doesn’t matter. You could do just background and foreground colors, or whatever, so adjust as needed.
Obligatory Sample Output (Partial, Very Partial):
The Same Colorization with Command-line Perl
Now Try It The Perl Way (again on Different Terminals):
perl -E '
foreach $md (1..9) {
foreach $bg (40..47) {
foreach $fg (30..37) {
$cd = "[${bg};${fg};${md}m";
print "\e$cd";
print "\\e$cd ";
print "\e[00m";
}
say "";
}
}'
Notes
Note the challenges printing the escape code in Perl the same way I did in Bash. It’s a bit different that the echo -n[e]
in bash.
I kept the Perl here very basic on purpose. It’s about ANSI not Perl. The upcoming articles will use fancier Perl (though some people don’t like that, sorry), as it keeps the set code brief (somewhat) so that the focus is on the regular expression.
Obligatory Sample Outp… Oh It Should Be Like The Last One
Teaser: Initialization of ANSI Colors in Perl
These will appear in upcoming posts. The skeleton template that follows should be usable, but does not contain a full regex example.
Tight And Unobtrusive:
# Simple ANSI color code generation
my @nrm = ( "\e[0m", reverse map { "\e[3" . $_ . "m" } (1..7) );
my @clr = map { ( $_, shift @nrm ) } map { "\e[9" . $_ . "m" } (0..7);
Fancier But Not Too Fancy:
# Names of colors--order matching that of ordinal values for ANSI colors
my @colorNames = qw(Black Red Green Yellow Blue Purple Cyan White);
# Generate color codes from names into hash
my %color;
@color{@colorNames} = map { "\e[3" . $_ . "m" } (0..$#colorNames);
@color{map { "bld$_" } @colorNames} = map { "\e[9" . $_ . "m" } (0..$#colorNames);
@color{map { "rvr$_" } @colorNames} = map { "\e[7;3" . $_ . "m" } (0..$#colorNames);
# Explictly organize the sequence of colors by name and hash
my @clr = @color{qw[ bldYellow rvrBlue bldGreen Yellow Blue bldCyan Cyan
rvrWhite Purple bldBlue rvrYellow Red Green bldPurple bldRed
bldWhite White rvrRed rvrGreen rvrPurple rvrCyan ]};
I have fancier, but I think it’s overrated.
Using These Perl Colors
Ahead of the loop (when use strict
and you don’t feel like scattering my
statements all over the place:
Globals, Not to Pollute the Loop Space (an opinion):
# Arrays used in loop
my (@clrs, @hi, @F);
The below code takes an array text strings, @F
, however you happen to have populated it, and prints it as a line with the array elements each in different colors.
Usage on an array that has the chunks to get individual colors:
#Colorize
@clrs = (@clrs, @clr) while scalar(@F) > scalar(@clrs);
@hi = map { $_ . (shift @F || "") } @clrs[0..$#F];
say join("\e[90m | ", @hi), "\e[0m";
The full examples are yet to come. The one that follows below has a relatively blank regex to start with. But, you can populate the array of strings, @F
, any way you want.
A skeleton example (untested):
#!/usr/bin/perl -w
use strict;
use v5.16.3;
# Simple ANSI color code generation
my @nrm = ( "\e[0m", reverse map { "\e[3" . $_ . "m" } (1..7) );
my @clr = map { ( $_, shift @nrm ) } map { "\e[9" . $_ . "m" } (0..7);
# Arrays used in loop
my (@clrs, @hi, @F);
while (<>) {
### Parser for bar-delimite content (in place of regex parser below if desired)
# @F = split /\|/;
# $F[-1] =~ s/\s*[\r\n]+//; # chomp field, O.S. independent
# Regex
@F = m{^ # Anchor to beginning of samples
(.*) # Trailing characters
}x
or say($_, " ---<<{NO MATCH}>>---") and next;
say "undefined" unless defined $F[0]; # Validate
#Colorize
@clrs = (@clrs, @clr) while scalar(@F) > scalar(@clrs);
@hi = map { $_ . (shift @F || "") } @clrs[0..$#F];
say join("\e[90m | ", @hi), "\e[0m";
}
The two lines of color generation and comment can simply be replaced by the fancier color generation example.
Obligatory Sample Outp… See The Links Below
Niceties
I hope the brevity and and the style proved useful. I had little to say about motivation here, because, hey, colors. And, I hope the opening skip ahead comments were useful. A table of contents might have been nice, but I don’t feel strongly about that. Apologies to those who don’t like multi-line commands, though I did make an effort to make it so you can just lift those examples straight into a script (with hopefully a minimum of editing).
Links (Repeated for Convenience):
Enjoy
Subscribe to my newsletter
Read articles from TesserId directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
