How to return text to normal color after using the perl module ANSIColor? - perl

I recently found the very fun perl module ANSIColor for changing my text color. Basically, all i need to do to change perl stdout text color is something like...
print color("red")."My sample text\n";
However, after exiting the script, my terminal is now only printing in red as well! Is there some function for return the console to the original color that I can include at the end of my script?
Thanks!

Use colored() instead of color(). This will reset the coloring after the string is printed:
print colored("My sample text\n", "red");

You can try,
print color 'reset';

Term::ANSIColor doc page says that to get back to normal text you should use reset keyword.
print color 'bold blue';
print "This text is bold blue.\n";
print color 'reset';
print "This text is normal.\n";
Also I recommend to look at Constant Interface

Related

Perl: Colouring Term::Readline messages while keeping underline ornament (and potentially others)

I want to use Term::Readline with colourful prompts, something along the lines of: readline("foo" . colored("bar", "red") . "baz")
I found Term::ANSIColor and it looks promising. It does, however, seem to clear all colours or underlining after, i.e. colored("some text", "red").
That is bad because
the prompt generated by readline contains underlining. Sometimes, that is.
I guess colored doesn't know what formatting has been applied before and I wasn't able to find out whether Colorstacks, mentioned in the documentation, will help me. The documentation has only examples which directly print stuff and is -at best- is not well suited for Perl newbies like me.
The problem is that the prompt generated by readline doesn't look consistent, because it is underlined first and after the coloured part, the underlining is gone:
I can read the "ornaments" which seem to be relevant for the underlining to happen, as seen in the following code:
#!/usr/bin/env perl
use Term::ReadLine;
use Term::ANSIColor;
my $term;
sub prompt {
$term = new Term::ReadLine 'colourtest'
unless $term;
print "My ornaments: " . $term->ornaments . "\n";
my $answer = $term->readline(#_);
# readline turns off autoflush, re-enable it
$| = 1;
return $answer;
}
prompt("Underlined " .
colored("followed by colour", "red") .
" then plain");
I guess my question is: Can I make Term::ANSIColor play well together with readline such that colored falls back to the previously applied formatting?

Clear already printed values using perl

I need to clear the printed values in perl console window. For an example,
Note: I am developing this in Windows OS.
use strict;
my $mode;
Initialize();
sub Initialize{
print "Enter 1 or 2";
$mode=<STDIN>;
chomp($mode);
check_mode($mode);
}
sub check_mode{
if(($mode!=1) and ($mode!=2)){
print "invalid selection";
Initialize();
}
else{
print "valid selection";
sleep 5;
}
}
While entering wrong selection, I have called the Initialize function, it is printing again. But, what I want is while calling the function it should delete already printed value in the console window and it should print again. Is it possible?
Please give your valuable suggestions.
While you can use the backspace character code "\b" to erase characters on the current line, that has limitations since when the user hits enter it will print a linefeed and your backspace characters won't carry back up to erase the previous line.
See Win32::Console which should allow you to print your prompt at a fixed location and then later overwrite the wrong selection or you can get input a single character at a time using the InputChar method and suppress the newline...
for specific to window os and linux os
system($^O =~ /win/i ? 'cls' : 'clear');

Coloring a perl die message

I want to change the color of a die message in my perl script. I am currently using Term::ANSIColor to do other color changing in my script. The problem I run into with die messages is once the script dies it cannot reset the color to the terminal default and the terminal prompt is whatever color was last used in my script. In this case it turns it red.
Any idea how I can have the script die but still change the color back?
Here is the code block in question;
#!/usr/bin/perl
use strict;
use warnings;
require Term::ANSIColor;
use Term::ANSIColor;
print "Loading configuration file\n";
# Check if the specified configuration file exists, if not die
if (! -e $config_file_path) {
print color 'red';
die "$config_file_path not found!\n";
print color 'reset';
} else {
print color 'green';
print "$config_file_path loaded\n";
print color 'reset';
}
Update
It works but now I am not able to get rid of the part of the die statment that says what line it happened on.
Loading configuration file
/etc/solignis/config.xml not found!
at discovery.pl line 50.
Normally I just add a line break the die function and that eliminates any of the normal error output from die. Any idea why its doing that?
Update 2
Based on all of your recommendations, I cobbled this together.
print STDERR RED, "$config_file_path not found!";
die RESET, "\n";
It seems to work correctly. Using the constants for Term::ANSIColor1 was a perfect thing I needed to simply things.
die is printing to STDERR while print is going to STDOUT.
print STDERR color 'red';
die "$config_file_path not found!\n";
Note that ... you just died. Your 'reset' isn't going to be printed
You want to concatenate it onto your die:
die color 'red' . "$config_file_path not found!" . color 'reset';
You can also use the constants:
use Term::ANSIColor qw(:constants);
die RED, "THis is death!", RESET, "\n";
EDIT: Sorry - And to get rid of the "where it happened" part, concatenate a \n to the end:
die color 'red' . "$config_file_path not found!" . color 'reset' . "\n";
There's a few ways to do this.
Use Term::ANSIColor's colored function, which seems to automatically add the ANSI reset sequence at the end:
die colored( "$config_file_path not found!\n", 'red' );
Use the constants interface from Term::ANSIColor:
use Term::ANSIColor qw( :constants );
$Term::ANSIColor::AUTORESET = 1;
die RED "$config_file_path not found!\n";
or
die RED, "$config_file_path not found!\n", RESET;
You can also trap $SIG{__DIE__}, or use an END block, with a coderef and reset it after printing its arguments. (These are probably not the greatest ideas, but they would allow you to reset the colors under almost any exit circumstance.)
I’m sure an END{} block in which you reset the terminal back to its blackness is the cleanest solution. That’s what such things are for.
Do NOT screw around with $SIG{__DIE__}, or you will be unhappy. Nobody realizes it gets called even for trapped exceptions!!
You can use the __DIE__ handler:
$SIG{'__DIE__'} = sub {
print color 'reset';
};
From perldoc perlvar:
Due to an implementation glitch, the
$SIG{__DIE__} hook is called even
inside an eval().
Hence, you should probably not use this technique.

How to print BOLD text in here doc in Perl?

I am using the here doc to print usage messages for the user. Is there a way to print specific words BOLD similar to the man pages on unix. I am using this on Unix. Is there a way to use Term::ANSIColor(or some other way?) with the here doc?
1) You can simply include ANSI codes into heredoc:
print <<EOD;
XXXX\033[1;30;40m YYYY\033[1;33;43m ZZZZ\033[0mRESET
EOD
2) Heredoc interpolates the variables, so if you include ANSI colors into a variable, it works.
my $v="xxxxx";
$var = "\nXXXX\033[1;30;40m YYYY\033[1;33;43mZZZZ\033[0mRESET\n";
print <<EOD;
$var
EOD
3) Building on #2, you can generate ANSI codes via Term::ANSIColor's color() method as a string and use the variable containing that string in the heredoc. Sorry, no working example since I don't have ANSIColor installed but should be obvious.
You may want to store a specific ANSI code in some specific variable and put the actual text in heredoc and sprincle ANSI-code variables there.
You can use the #{[expression]} syntax within a heredoc to evaluate arbitrary code. The output of this little program will look OK if your terminal has a dark background and light foreground color:
use Term::ANSIColor;
print <<EOF;
I am using the here doc to print usage messages
for the user. Is there a way to print #{[colored['bright_white'],'specific words']}
BOLD similar to the man pages on unix. I am using
this on Unix. Is there a way to use Term::ANSIColor
(or some other way?) with the here doc?
EOF

How do I toggle printing to STDOUT/STDERR dynamically in Perl?

I'm curious if I can toggle between printing to STDOUT or STDERR based on some value or inline expression (without using an if statement).
print ($someFlag ? STDOUT : STDERR) "hello world!"
Obviously, that syntax doesn't work.
I think this will do what you want:
print {$someFlag ? *STDOUT : *STDERR} "hello world!";
A similar example can be seen in the documentation for print. Use typeglobs so that it will run under use strict.
Another strategy is to define your own printing function that will behave differently, depending on the value of $someFlag.
Do you need to evaluate for each call to print?
If not, would this work for you:
my $redir = $someFlag ? STDOUT : STDERR;
print $redir "hello world!\n";
One mechanism is to 'select' the output descriptor (file channel).
select STDERR;
print ...goes to STDERR...;
select STDOUT;
print ...goes to STDOUT...;
I suspect this is now deprecated, though.
I wrap this sort of thing in a method that returns the appropriate filehandle:
print { $obj->which_handle_do_I_want } "Some message";
You might want to look at how IO::Interactive.
However, if you're doing this for logging, I recommend Log::Log4perl since you can not only change where the output goes, but can send the output to multiple places, set priorities for the message, and a lot more. And, you can change all of that without changing the source.