File Coverage

blib/lib/Term/ANSIColorx/AutoFilterFH.pm
Criterion Covered Total %
statement 96 118 81.3
branch 26 42 61.9
condition n/a
subroutine 14 15 93.3
pod 0 3 0.0
total 136 178 76.4


line stmt bran cond sub pod time code
1              
2             package Term::ANSIColorx::AutoFilterFH;
3              
4 3     3   4986 use Carp;
  3         11  
  3         144  
5 3     3   1172 use Symbol;
  3         2007  
  3         157  
6 3     3   2651 use Tie::Handle;
  3         5101  
  3         65  
7 3     3   17 use base 'Tie::StdHandle';
  3         5  
  3         269  
8 3     3   17 use base 'Exporter';
  3         6  
  3         192  
9 3     3   537 use Term::ANSIColor qw(color colorvalid);
  3         8386  
  3         1033  
10              
11             sub import {
12 3     3   16 my @__;
13 3 100       41 my $color_package = Term::ANSIColorx::ColorNicknames->can("import")
14             ? "Term::ANSIColorx::ColorNicknames"
15             : "Term::ANSIColor";
16              
17 3         8 for(@_) {
18 6 50       16 if( m/\Acolor.?package\s*=\s*(\S+)\z/ ) {
19 0         0 $color_package = $1
20              
21             } else {
22 6         11 push @__, $_
23             }
24             }
25              
26             # Exporter warns when we re-export color and colorvalid with a different prototype
27 3     4   16 local $SIG{__WARN__} = sub {}; # and there's really no good way to disable it
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   19 eval qq{ use $color_package qw(color colorvalid); 1 }
  3         5  
  3         114  
  3         204  
32             or die $@;
33              
34 3         3790 __PACKAGE__->export_to_level(1, @__);
35             }
36              
37 3     3   429 use common::sense;
  3         16  
  3         13  
38              
39             our $VERSION = '2.7193';
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   391 my $this = shift;
52              
53 4         14 for my $pfft (keys %pf2t) {
54 5 50       21 if( $pf2t{$pfft} == $this ) {
55 0         0 delete $pf2t{$pfft};
56 0         0 last;
57             }
58             }
59              
60 4         8 delete $orig{$this};
61 4         8 delete $pats{$this};
62 4         277 delete $trun{$this};
63             }
64             # }}}
65             # set_truncate {{{
66             sub set_truncate {
67 2     2 0 10 my $pfft = shift;
68 2         4 my $that = int shift;
69 2         5 my $this = $pf2t{$pfft};
70              
71 2 50       6 return delete $trun{$this} unless $that > 0;
72              
73 2         17 $trun{$this} = $that;
74             }
75             # }}}
76             # PRINT {{{
77             sub PRINT {
78 3     3   24 my $this = shift;
79 3         7 my @them = @_;
80              
81             # FIXME: this is totally unreadable code
82              
83 3         8 for my $it (@them) {
84 3         6 my @colors;
85              
86             # for each pattern, set an applicable icolor index for each character
87             # in @colors
88 3         5 for my $p ( @{$pats{$this}} ) {
  3         9  
89 4         64 while( $it =~ m/($p->[0])/g ) {
90 52         141 my @character_list = ( $-[1] .. $+[1]-1 );
91              
92 52 50       134 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         265 $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         30 for my $i ( reverse 0 .. $#colors ) {
121 326 100       510 if( (my $n = $colors[$i]) != $l ) {
122 102         187 substr $it, $i+1, 0, $RESET . "$icolors[$l]";
123 102         144 $l = $n;
124             }
125             }
126              
127             # lastly, change the color of the first character if there is one
128 3 100       21 substr $it, 0, 0, $icolors[$colors[0]] if $colors[0];
129             }
130              
131 3 100       13 if( my $trun = $trun{$this} ) {
132             # TODO This assumes all PRINT()s are *lines*, and they're clearly not.
133              
134 2         3 local $";
135 2         13 my $line = "@them";
136 2 50       13 (substr $line, $trun) = "\n" if length $line > $trun+1;
137 2         5 print {$orig{$this}} $line;
  2         16  
138              
139 2         9 return;
140             }
141              
142 1         2 print {$orig{$this}} @them;
  1         7  
143             }
144             # }}}
145             # filtered_handle {{{
146             sub filtered_handle {
147 5     5 0 4747 my ($fh, @patterns) = @_;
148 5 50       22 croak "filtered_handle(globref, \@patterns)" unless ref($fh) eq "GLOB";
149              
150 5         13 @icolors = ("");
151 5         16 $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       120 $RESET .= "\e[m" if $RESET eq "\e[0m";
156              
157 5         8 my @pats;
158 5         20 while( (my ($pat,$color) = splice @patterns, 0, 2) ) {
159 8 50       20 croak "\@patterns should contain an even number of items" unless defined $color;
160              
161 8 50       18 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       22 unless( ref($pat) eq "Regexp" ) {
168 3         7 $pat = eval {qr($pat)};
  3         37  
169 3 50       12 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       21 croak "color \"$color\" unknown" unless colorvalid($color);
176 7         95 $color = color($color);
177              
178 7         127 my ($l) = grep {$color eq $icolors[$_]} 0 .. $#icolors;
  9         22  
179              
180 7 100       16 unless($l) {
181 6         12 push @icolors, $color;
182 6         9 $l = $#icolors;
183             }
184              
185 7         32 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         13 my $pfft = bless gensym();
191 4 50       54 my $this = tie *{$pfft}, __PACKAGE__ or die $!;
  4         47  
192              
193 4         59 $pf2t{$pfft} = $this;
194 4         11 $orig{$this} = $fh;
195 4         8 $pats{$this} = \@pats;
196              
197 4         11 $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__