Skip Menu |

This queue is for tickets about the Term-ANSIColor CPAN distribution.

Report information
The Basics
Id: 121974
Status: resolved
Priority: 0/
Queue: Term-ANSIColor

People
Owner: RRA [...] cpan.org
Requestors: a.schwarz_dev [...] dntw.de
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: 5.00



Subject: colored doesn't reliably reset the color on STDERR
Date: Sat, 3 Jun 2017 13:00:27 +0200
To: bug-Term-ANSIColor [...] rt.cpan.org
From: Andreas Schwarz <a.schwarz_dev [...] dntw.de>
Subject: colored doesn't reliably reset the color on STDERR
To: bug-Term-ANSIColor [...] rt.cpan.org
From: Andreas Schwarz <a.schwarz_dev [...] dntw.de>
Term::ANSIcolor colored If you print a colored String on STDOUT and want to print normal text on STDERR in the next line, this text will be colored too (but not if you send normal text to STDOUT before, also not if you send initial colored text to STDERR). This also happens if you're using subroutines for printing. I've tested this issue on following perl versions: 5.20.2-3+deb8u6 from debian jessie repository This is perl 5, version 20, subversion 2 (v5.20.2) built for x86_64-linux-gnu-thread-multi 5.24.1-2 from debian stretch repository This is perl 5, version 24, subversion 1 (v5.24.1) built for x86_64-linux-gnu-thread-multi 5.26.0 from source build on debian jessie This is perl 5, version 26, subversion 0 (v5.26.0) built for x86_64-linux 5.27.0 from source build on debian jessie This is perl 5, version 27, subversion 0 (v5.27.0) built for x86_64-linux demonstration code ------------------------------------------------------------- #!/usr/bin/perl use Term::ANSIColor; print STDOUT "normal STDOUT text\n"; print STDERR "normal STDERR text\n"; # start with STDERR (all fine) ---------------------------- print STDERR colored("red STDERR text\n", 'red'); print STDERR "should normal STDERR text\n"; print STDOUT "should normal STDOUT text\n"; # change the order print STDERR colored("red STDERR text\n", 'red'); print STDOUT "should normal STDOUT text\n"; print STDERR "should normal STDERR text\n"; # start with STDOUT --------------------------------------- print STDOUT colored("red STDOUT text\n", 'red'); print STDERR "should normal STDERR text\n"; # but isn't print STDOUT "should normal STDOUT text\n"; # change the order print STDOUT colored("red STDOUT text\n", 'red'); print STDOUT "should normal STDOUT text\n"; print STDERR "should normal STDERR text\n"; # now it is -------------------------------------------------------------------------------- best regards Andreas Schwarz
Download demo.png
image/png 52.6k

Message body is not shown because sender requested not to inline it.

Download signature.asc
application/pgp-signature 819b

Message body not shown because it is not plain text.

Subject: Re: [rt.cpan.org #121974] colored doesn't reliably reset the color on STDERR
Date: Sat, 03 Jun 2017 12:47:28 -0700
To: "Andreas Schwarz via RT" <bug-Term-ANSIColor [...] rt.cpan.org>
From: Russ Allbery <rra [...] cpan.org>
This was an *excellent* bug report. Thank you for the effort you put into it! "Andreas Schwarz via RT" <bug-Term-ANSIColor@rt.cpan.org> writes: Show quoted text
> If you print a colored String on STDOUT and want to print normal text on > STDERR in the next line, this text will be colored too (but not if you > send normal text to STDOUT before, also not if you send initial colored > text to STDERR).
If you either enable autoflush on STDOUT ($| = 1) or set $Term::ANSIColor::EACHLINE to "\n", that will resolve this problem. This is sort of explained in the manual page, but doesn't explicitly mention interleaving STDOUT and STDERR or line buffering and should. I'll update the documentation before closing this out. But what's happening is the same thing described here: Normally, colored() just puts attribute codes at the beginning and end of the string, but if you set $Term::ANSIColor::EACHLINE to some string, that string will be considered the line delimiter and the attribute will be set at the beginning of each line of the passed string and reset at the end of each line. This is often desirable if the output contains newlines and you're using background colors, since a background color that persists across a newline is often interpreted by the terminal as providing the default background color for the next line. Programs like pagers can also be confused by attributes that span lines. Normally you'll want to set $Term::ANSIColor::EACHLINE to "\n" to use this feature. This line: Show quoted text
> print STDOUT colored("red STDOUT text\n", 'red');
is actually printing the string: "\e[31mred STDOUT text\n\e[0m" STDOUT is line-buffered by default when connected to a terminal, which means that output is flushed after each newline. Perl therefore (via stdio) prints out: "\e[31mred STDOUT text\n" and then buffers "\e[0m" because it hasn't seen another newline. Therefore, this: Show quoted text
> print STDERR "should normal STDERR text\n"; # but isn't
is displayed in red. You then print the rest of a line to STDOUT: Show quoted text
> print STDOUT "should normal STDOUT text\n";
which flushes the buffer and resets the color. The reason why this works as expected in your next example is that you print another line to STDOUT first, which flushes the pending output and resets the color properly. Show quoted text
> # change the order > print STDOUT colored("red STDOUT text\n", 'red'); > print STDOUT "should normal STDOUT text\n"; > print STDERR "should normal STDERR text\n"; # now it is
You don't see the same phenomenon with STDERR because STDERR is *not* line-buffered by default; by default, it's unbuffered, and Perl flushes the output after every bit of output. In general, I recommend setting autoflush on STDOUT at the start of any program that might mix STDOUT and STDERR output, since the line buffering can cause other weird problems and intermixed output. The only drawback is that it makes I/O much less efficient if you have a lot of STDOUT output and partial lines, but most programs that do this sort of mixing aren't performance-sensitive. -- #!/usr/bin/perl -- Russ Allbery, Just Another Perl Hacker $^=q;@!>~|{>krw>yn{u<$$<[~||<Juukn{=,<S~|}<Jwx}qn{<Yn{u<Qjltn{ > 0gFzD gD, 00Fz, 0,,( 0hF 0g)F/=, 0> "L$/GEIFewe{,$/ 0C$~> "@=,m,|,(e 0.), 01,pnn,y{ rw} >;,$0=q,$,,($_=$^)=~y,$/ C-~><@=\n\r,-~$:-u/ #y,d,s,(\$.),$1,gee,print
I've documented this gotcha in the POD in the 5.00 release.