File Coverage

blib/lib/Term/ANSIColorx/AutoFilterFH.pm
Criterion Covered Total %
statement 97 119 81.5
branch 26 42 61.9
condition n/a
subroutine 14 15 93.3
pod 0 3 0.0
total 137 179 76.5


line stmt bran cond sub pod time code
1              
2             package Term::ANSIColorx::AutoFilterFH;
3              
4 3     3   3985 use Carp;
  3         3  
  3         135  
5 3     3   1155 use Symbol;
  3         1788  
  3         164  
6 3     3   1211 use Tie::Handle;
  3         3653  
  3         50  
7 3     3   12 use base 'Tie::StdHandle';
  3         3  
  3         223  
8 3     3   21 use base 'Exporter';
  3         4  
  3         120  
9 3     3   459 use Term::ANSIColor qw(color colorvalid);
  3         4872  
  3         709  
10              
11             sub import {
12 3     3   14 my @__;
13 3 100       28 my $color_package = Term::ANSIColorx::ColorNicknames->can("import")
14             ? "Term::ANSIColorx::ColorNicknames"
15             : "Term::ANSIColor";
16              
17 3         4 for(@_) {
18 6 50       11 if( m/\Acolor.?package\s*=\s*(\S+)\z/ ) {
19 0         0 $color_package = $1
20              
21             } else {
22 6         8 push @__, $_
23             }
24             }
25              
26             # Exporter warns when we re-export color and colorvalid with a different prototype
27 3     4   15 local $SIG{__WARN__} = sub {}; # and there's really no good way to disable it
  4         72  
28             # so we just disable the warning signal for a sec
29              
30             #arn qq{ use $color_package qw(color colorvalid); 1 };
31 3 50   3   11 eval qq{ use $color_package qw(color colorvalid); 1 }
  3         3  
  3         80  
  3         198  
32             or die $@;
33              
34 3         3204 __PACKAGE__->export_to_level(1, @__);
35             }
36              
37 3     3   466 use common::sense;
  3         28  
  3         10  
38              
39             our $VERSION = '2.7191_2';
40             our @EXPORT_OK = qw(filtered_handle);
41              
42             my %pf2t;
43             my %orig;
44             my %pats;
45             my %trun;
46              
47             my (@icolors, $RESET);
48              
49             # DESTROY {{{
50             sub DESTROY {
51 4     4   621 my $this = shift;
52              
53 4         11 for my $pfft (keys %pf2t) {
54 5 50       24 if( $pf2t{$pfft} == $this ) {
55 0         0 delete $pf2t{$pfft};
56 0         0 last;
57             }
58             }
59              
60 4         6 delete $orig{$this};
61 4         7 delete $pats{$this};
62 4         63 delete $trun{$this};
63             }
64             # }}}
65             # set_truncate {{{
66             sub set_truncate {
67 2     2 0 7 my $pfft = shift;
68 2         3 my $that = int shift;
69 2         3 my $this = $pf2t{$pfft};
70              
71 2 50       9 return delete $trun{$this} unless $that > 0;
72              
73 2         8 $trun{$this} = $that;
74             }
75             # }}}
76             # PRINT {{{
77             sub PRINT {
78 3     3   14 my $this = shift;
79 3         6 my @them = @_;
80              
81             # FIXME: this is totally unreadable code
82              
83 3         4 for my $it (@them) {
84 3         3 my @colors;
85              
86             # for each pattern, set an applicable icolor index for each character
87             # in @colors
88 3         3 for my $p ( @{$pats{$this}} ) {
  3         7  
89 4         62 while( $it =~ m/($p->[0])/g ) {
90 52         102 my @character_list = ( $-[1] .. $+[1]-1 );
91              
92 52 50       70 if( $icolors[$p->[1]] eq "_hashed_" ) {
93 0         0 my $dyn = dynamic_colors($1);
94              
95             # This is evil to debug
96             # … data dump can help …
97             #
98             # use Data::Dump qw(dump);
99             # warn dump({
100             # character_list => \@character_list,
101             # match => $1,
102             # icolors => \@icolors,
103             # dyn => $dyn,
104             # p => \$p,
105             # });
106              
107 0         0 my $pos = 0;
108 0         0 $colors[$_] = $dyn->[$pos++] for @character_list;
109             }
110              
111             else {
112 52         248 $colors[$_] = $p->[1] for @character_list;
113             }
114             }
115             }
116              
117             # in reverse order, change the color for each character iff
118             # it's not already the same; reset before change (is the reset overkill??)
119 3         6 my $l = 0;
120 3         18 for my $i ( reverse 0 .. $#colors ) {
121 326 100       381 if( (my $n = $colors[$i]) != $l ) {
122 102         115 substr $it, $i+1, 0, $RESET . "$icolors[$l]";
123 102         76 $l = $n;
124             }
125             }
126              
127             # lastly, change the color of the first character if there is one
128 3 100       19 substr $it, 0, 0, $icolors[$colors[0]] if $colors[0];
129             }
130              
131 3 100       12 if( my $trun = $trun{$this} ) {
132             # TODO This assumes all PRINT()s are *lines*, and they're clearly not.
133              
134 2         2 local $";
135 2         7 my $line = "@them";
136 2 50       11 (substr $line, $trun) = "\n" if length $line > $trun+1;
137 2         4 print {$orig{$this}} $line;
  2         7  
138              
139 2         6 return;
140             }
141              
142 1         1 print {$orig{$this}} @them;
  1         4  
143             }
144             # }}}
145             # filtered_handle {{{
146             sub filtered_handle {
147 5     5 0 6205 my ($fh, @patterns) = @_;
148 5 50       44 croak "filtered_handle(globref, \@patterns)" unless ref($fh) eq "GLOB";
149              
150 5         9 @icolors = ("");
151 5         14 $RESET = color("reset");
152              
153             # dunno about others, but my term doesn't reset background right
154             # with '0m'; needs pure 'm'
155 5 50       87 $RESET .= "\e[m" if $RESET eq "\e[0m";
156              
157 5         6 my @pats;
158 5         16 while( (my ($pat,$color) = splice @patterns, 0, 2) ) {
159 8 50       13 croak "\@patterns should contain an even number of items" unless defined $color;
160              
161 8 50       11 if( $color eq "_hashed_" ) {
162 0         0 push @icolors, '_hashed_';
163 0         0 push @pats, [ $pat, $#icolors ];
164 0         0 next;
165             }
166              
167 8 100       17 unless( ref($pat) eq "Regexp" ) {
168 3         3 $pat = eval {qr($pat)};
  3         32  
169 3 50       7 croak "RE \"$_\" doesn't compile well: $@" unless $pat;
170             }
171              
172             # die unless all the elements of @uc are all caps exports of
173             # Term::ANSIColor
174              
175 8 100       18 croak "color \"$color\" unknown" unless colorvalid($color);
176 7         74 $color = color($color);
177              
178 7         74 my ($l) = grep {$color eq $icolors[$_]} 0 .. $#icolors;
  9         16  
179              
180 7 100       13 unless($l) {
181 6         6 push @icolors, $color;
182 6         5 $l = $#icolors;
183             }
184              
185 7         30 push @pats, [ $pat => $l ];
186             }
187              
188             # NOTE: This is called pfft because I'd like to get rid of it.
189             # it doesn't seem like I should need it and it irritates me.
190 4         14 my $pfft = bless gensym();
191 4 50       39 my $this = tie *{$pfft}, __PACKAGE__ or die $!;
  4         46  
192              
193 4         46 $pf2t{$pfft} = $this;
194 4         7 $orig{$this} = $fh;
195 4         6 $pats{$this} = \@pats;
196              
197 4         9 $pfft;
198             }
199             # }}}
200              
201             # {{{ DYNAMIC_COLOR_MATCH_HACK:
202             DYNAMIC_COLOR_MATCH_HACK: {
203             my %dynamic_color_match_hash;
204             my @dynamic_color_list = (map {color($_)} (
205             "green", "bold green",
206             "cyan", "bold cyan",
207             "magenta", "bold magenta",
208             "bold blue",
209             "yellow", "bold yellow",
210             ));
211              
212             sub dynamic_colors {
213 0     0 0   my $match = shift;
214 0           my $list = $dynamic_color_match_hash{$match};
215              
216 0 0         return $list if $list;
217              
218 0           my @color = map {$dynamic_color_list[rand @dynamic_color_list]} 1 .. length($match);
  0            
219              
220 0           for my $color (@color) {
221 0           my ($l) = grep {$color eq $icolors[$_]} 0 .. $#icolors;
  0            
222              
223 0 0         unless($l) {
224 0           push @icolors, $color;
225 0           $l = $#icolors;
226             }
227              
228 0           $color = $l;
229             }
230              
231 0           return $dynamic_color_match_hash{$match} = \@color;
232             }
233             }
234              
235             # }}}
236              
237             "true";
238              
239             __END__