Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight

Term::ANSIColor is awesome, but.. (need help)

by mascip (Pilgrim)
on Mar 30, 2014 at 13:17 UTC ( #1080285=perlquestion: print w/replies, xml ) Need Help??
mascip has asked for the wisdom of the Perl Monks concerning the following question:

Hi there :-)

I've just used Term::ANSIColor in an app for the first time, and found it really awesome. I didn't have to change anything at all in my code: I just declared the colors on some variables.

my $name = colored('Jon', 'red');
and almost all the rest worked as if nothing had been changed, but now my terminal outputs are much more readable.

My problem starts when some commands do string comparison:

do_something() if $name eq 'Jon';
This breaks because $name is not just Jon now, it's red Jon.

One workaraound is to use colorstrip():

do_something() if colorstrip($name) eq 'Jon';
That works, but it means I have to make this change everywhere in the code, which is a pain. Especially when these variables get sent to various objects who do all the hard work.

Is there any way to make this work? Some way of saying: "You're being compared? Wait, I'll colorstrip you first".

If that was included in the Term::ANSIColor module, that would be even better. That's why I just wrote to the module author, to come and read this message.

Any idea how to take advantage of Perl's flexibility and perform this trick?

Replies are listed 'Best First'.
Re: Ter::ANSIColor is awesome, but.. (need help)
by Corion (Pope) on Mar 30, 2014 at 13:32 UTC

    Separate the program logic and the output.

    Within your program, always keep $name eq 'Jon', and have a routine, output_name(), which does

    print colored($name,'red');

    or a function visual_name, which returns the value, ready for printing as name:

    sub visual_name { my( $name )= @_; colored( $name, 'red' ); };

      Thank you Corion.
      That makes sense, but it doesn't exactly solve my problem. I don't want to make this change in every part of the code where I'm displaying something.

      I guess, most of my print statements are in the same file in fact, apart from exceptions. (Edit: In fact I just realized that I would really like these exceptions to be colourized...)

      I'll try this tomorrow. But I'm still wondering if there is a better way...

        The starting point of my reasoning is:

        There is only one place where I declare the variables that I want to colorize. If I could colorize them then and nowhere else, that would be much simpler.

Re: Term::ANSIColor is awesome, but.. (need help) (overload and override)
by tye (Sage) on Mar 30, 2014 at 19:24 UTC

    Change the module to produce objects with stringification overloaded to return the original string (w/o color escapes). Override the output functions you use (like 'print'), to do something like:

    sub ... { local( $Term::ANSIColor::InOutput ) = 1; return CORE::...( @_ ); }

    and have the stringification include the color escapes if $InOutput is true.

    - tye        

      I had the very same idea but I was thinking of using a global variable. A class variable - or a class attribute - is much better. Thank you!

      And a good thing is that it should also work for exceptions, if I also create a die_color() function.

      1. If I implement this, is it worth sharing it on CPAN?

      2. Is it "bad practice"?

      3. Is there a better way?

      I really like the idea of a string declared with a color, but who behaves just like a normal string in the program. Only the display is colored.

        I would really like to hear people's feedback: Is this String::Colored module a good / bad idea ?

        Additional idea given by a Monger:

        local *CORE::GLOBAL::print = \&String::Colored::sing;
        That's if I want to not need to change anything in my current code, while adding colors. Any warnings against the dangers of this trick would be very welcome :-)

Re: Term::ANSIColor is awesome, but.. (need help)
by Discipulus (Monsignor) on Mar 31, 2014 at 07:22 UTC
    Hello, in the case you choice to separate completely the coloring logic you can use this useful script. You'll find a nice implementation.


    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.

      It also ended on CPAN, as cet.

      Because my aim is String variables with a color, I think I'll go for Term::ANSIColor::colored(). Thanks for sharing this module :-)

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1080285]
Approved by hdb
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (4)
As of 2018-05-25 11:20 GMT
Find Nodes?
    Voting Booth?