Subject: | Patch: custom color names via environment variable |
Hi Russ,
Attached is a patch for your consideration which adds support for
user-defined color mappings, such as 'alert=red' or 'gray=bright_black'.
With these color mappings, the functions color(), colored() and
colorvalid() will also understand 'alert' and 'gray' as colors.
The custom colors are spceified with an environment variable like so:
TERM_ANSICOLOR_CUSTOM_COLORS="alert=red,gray=bright_black"
The impetus for this patch comes from the perl module Data::Printer, and
the Solarized color scheme (http://ethanschoonover.com/solarized).
I'd like to be able to create a Data::Printer config which uses the
Solarized color names themselves.
eg. hash => "orange on_base02" vs hash => "bright_red on_black"
I'm pretty bad at designing color schemes anyway, and adding a layer of
color name indirection makes it doubly difficult.
With this patch I can set up a mapping for the Solarized color names and
anything which uses Term::ANSIColor automatically just works with them.
How does this sound to you?
Steve
Subject: | custom-colors.patch |
diff --git a/ANSIColor.pm b/ANSIColor.pm
index 9e3530e..5db5530 100644
--- a/ANSIColor.pm
+++ b/ANSIColor.pm
@@ -90,6 +90,11 @@ for (reverse sort keys %ATTRIBUTES) {
$ATTRIBUTES_R{$ATTRIBUTES{$_}} = $_;
}
+# Add custom color names if required.
+if (exists($ENV{TERM_ANSICOLOR_CUSTOM_COLORS})) {
+ _add_custom_colors($ENV{TERM_ANSICOLOR_CUSTOM_COLORS});
+}
+
##############################################################################
# Implementation (constant form)
##############################################################################
@@ -272,6 +277,29 @@ sub colorvalid {
return 1;
}
+# Parse a comma-separated line of custom color definitions, each of the
+# form: newname=oldname
+sub _add_custom_colors {
+ my ($str) = @_;
+ $str =~ s/\s+//g; # trim out all whitespace
+ for my $defn (split(/,/, $str)) {
+ my ($new, $old) = split(/=/, $defn, 2);
+ if (!$new || !$old) {
+ warn "Bad color mapping \"$defn\"";
+ }
+ elsif (! exists $ATTRIBUTES{$old}) {
+ warn "Unknown color mapping \"$old\"";
+ }
+ else {
+ $ATTRIBUTES{$new} = $ATTRIBUTES{$old};
+
+ # Could also do the the reverse mapping, but this may break
+ # client code which expects specific strings to be returned
+ # from uncolor.
+ }
+ }
+}
+
##############################################################################
# Module return value and documentation
##############################################################################
@@ -633,6 +661,33 @@ platforms that don't support ANSI escape sequences.
For it to have its proper effect, this environment variable must be set
before any color constants are used in the program.
+=item TERM_ANSICOLOR_CUSTOM_COLORS
+
+This environment variable allows the user to specify custom color names
+that will be understood by color(), colored() and colorvalid(). The custom
+color names are simply aliases for existing color names.
+
+The format is:
+
+ TERM_ANSICOLOR_CUSTOM_COLORS="newcolor1=oldcolor1,newcolor2=oldcolor2"
+
+Whitespace is ignored.
+
+For example the L<Solarized|http://ethanschoonover.com/solarized> colors can
+be mapped with:
+
+ TERM_ANSICOLOR_CUSTOM_COLORS="\
+ base00=bright_yellow, on_base00=on_bright_yellow,\
+ base01=bright_green, on_base01=on_bright_green, \
+ base02=black, on_base02=on_black, \
+ base03=bright_black, on_base03=on_bright_black, \
+ base0=bright_blue, on_base0=on_bright_blue, \
+ base1=bright_cyan, on_base1=on_bright_cyan, \
+ base2=white, on_base2=on_white, \
+ base3=bright_white, on_base3=on_bright_white, \
+ orange=bright_red, on_orange=on_bright_red, \
+ violet=bright_magenta,on_violet=on_bright_magenta"
+
=back
=head1 RESTRICTIONS
diff --git a/MANIFEST b/MANIFEST
index 65ba31f..bca9351 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -4,6 +4,7 @@ Makefile.PL
MANIFEST
README
t/basic.t
+t/custom.t
t/eval.t
t/pod-spelling.t
t/pod.t
diff --git a/t/basic.t b/t/basic.t
index 7f6bfff..235b29e 100755
--- a/t/basic.t
+++ b/t/basic.t
@@ -13,6 +13,7 @@ use Test::More tests => 54;
BEGIN {
delete $ENV{ANSI_COLORS_DISABLED};
+ delete $ENV{TERM_ANSICOLOR_CUSTOM_COLORS};
use_ok ('Term::ANSIColor',
qw/:pushpop color colored uncolor colorstrip colorvalid/);
}
diff --git a/t/custom.t b/t/custom.t
new file mode 100644
index 0000000..1c1a048
--- /dev/null
+++ b/t/custom.t
@@ -0,0 +1,65 @@
+#!/usr/bin/perl -Tw
+#
+# t/config.t -- testing the custom user colors functionality
+#
+use strict;
+use Test::More tests => 23;
+
+my @expected_warnings;
+my @unexpected_warnings;
+
+BEGIN {
+ $ENV{TERM_ANSICOLOR_CUSTOM_COLORS} = join(',',
+ ' custom_black = black',
+ 'custom_red= red',
+ 'custom_green =green ',
+ 'custom_blue=blue',
+ 'custom_unknown=unknown',
+ '=no_new',
+ 'no_old=',
+ 'no_equals',
+ );
+ delete $ENV{ANSI_COLORS_DISABLED};
+
+ # Test::Warn instead maybe?
+ local $SIG{__WARN__} = sub {
+ my ($msg) = @_;
+ if ($msg =~ /(?:Bad|Unknown) color mapping/) {
+ push(@expected_warnings, $msg);
+ }
+ else {
+ warn $msg;
+ push(@unexpected_warnings, $msg);
+ }
+ };
+
+ use_ok 'Term::ANSIColor',
+ qw/color colored uncolor colorvalid/;
+}
+
+# Check that the appropriate warnings got issued
+ok(grep(/Unknown color mapping "unknown"/, @expected_warnings),
+ 'Got unknown old color warning');
+for my $bad (qw( =no_new no_old= no_equals )) {
+ ok(grep(/Bad color mapping "$bad"/, @expected_warnings),
+ "Got warning for \"$bad\"");
+}
+is(scalar @unexpected_warnings, 0, "No unexpected warnings");
+
+
+# Check the custom colors all get assigned. They use various spacing formats
+# and should all parse correctly.
+for my $original (qw( black red green blue )) {
+ my $custom = 'custom_' . $original;
+ ok (colorvalid ($custom), "$custom is valid()");
+ is (color ($custom), color ($original),
+ "custom $custom matches $original with color()");
+ is (colored ('test', $custom), colored ('test', $original),
+ "custom $custom matches $original with colored()");
+ is ((uncolor(color($custom)))[0], $original,
+ "uncolor works for $custom back to $original");
+}
+
+
+# custom_unknown is mapped to an unknown color and should not appear
+ok(! colorvalid('custom_unknown'), 'unknown color mapping fails');
diff --git a/t/eval.t b/t/eval.t
index 394368e..08e6186 100755
--- a/t/eval.t
+++ b/t/eval.t
@@ -12,6 +12,7 @@ use Test::More tests => 5;
BEGIN {
delete $ENV{ANSI_COLORS_DISABLED};
+ delete $ENV{TERM_ANSICOLOR_CUSTOM_COLORS};
use_ok ('Term::ANSIColor', qw/:constants/);
}
diff --git a/t/stringify.t b/t/stringify.t
index a8eb448..56cc03f 100755
--- a/t/stringify.t
+++ b/t/stringify.t
@@ -20,6 +20,7 @@ use Test::More tests => 6;
BEGIN {
delete $ENV{ANSI_COLORS_DISABLED};
+ delete $ENV{TERM_ANSICOLOR_CUSTOM_COLORS};
use_ok ('Term::ANSIColor',
qw/:pushpop color colored uncolor colorstrip colorvalid/);
}