File Coverage

blib/lib/Text/Colorizer.pm
Criterion Covered Total %
statement 63 123 51.2
branch 7 30 23.3
condition 12 27 44.4
subroutine 13 24 54.1
pod 10 10 100.0
total 105 214 49.0


line stmt bran cond sub pod time code
1              
2             package Text::Colorizer ;
3              
4 2     2   41217 use strict;
  2         3  
  2         42  
5 2     2   8 use warnings ;
  2         2  
  2         34  
6 2     2   4 use Carp ;
  2         5  
  2         175  
7              
8             BEGIN
9             {
10              
11 2         13 use Sub::Exporter -setup =>
12             {
13             exports => [ qw() ],
14             groups =>
15             {
16             all => [ qw() ],
17             }
18 2     2   869 };
  2         16332  
19            
20 2     2   527 use vars qw ($VERSION);
  2         3  
  2         60  
21 2     2   30 $VERSION = '0.01_01';
22             }
23              
24             #-------------------------------------------------------------------------------
25              
26 2     2   884 use English qw( -no_match_vars ) ;
  2         5674  
  2         8  
27              
28 2     2   1316 use Readonly ;
  2         5259  
  2         103  
29             Readonly my $EMPTY_STRING => q{} ;
30              
31 2     2   51 use Carp qw(carp croak confess) ;
  2         2  
  2         79  
32 2     2   1020 use Term::ANSIColor qw(colored) ;
  2         8004  
  2         2722  
33              
34             #-------------------------------------------------------------------------------
35              
36             =head1 NAME
37              
38             Text::Colorizer - Create colored text from text and color descrition. An ANSI to HTML tranformation is provided
39              
40             =head1 SYNOPSIS
41              
42             my $c= Text::Colorizer->new
43             (
44             NAME => '' ,
45             INTERACTION =>
46             {
47             INFO => sub {print @_},
48             WARN => \&Carp::carp,
49             DIE => \&Carp::confess,
50             }
51            
52             FORMAT => 'HTML' | 'ANSI' |'ASCII',
53              
54             DEFAULT_COLOR => 'bright_white on_black',
55             COLOR => 'cycle'| 'bw',
56             COLORS =>
57             {
58             ASCII => [],
59             ANSI => ['white', 'bright_green', 'bright_yellow','bright_cyan', 'bright_red' ],
60             HTML => ['white', 'bright_green', 'bright_yellow','bright_cyan', 'bright_red' ],
61             },
62            
63             COLOR_NAMES - A hash reference
64              
65             COLOR_NAMES =>
66             {
67             HTML =>
68             {
69             white => "color:#888;",
70             black => "color:#000;",
71             ...
72             }
73             ANSI => ...
74             ASCII => ...
75             }
76             ) ;
77              
78             # or
79            
80             my $c= Text::Colorizer->new() ;
81            
82             my $colored_text = $c->color
83             (
84             'red on_black' => 'string',
85             $color => [... many strings..],
86             'user_defined_color_name' => 'string'
87             ) ;
88              
89             =head1 DESCRIPTION
90              
91             This module defined methods to produce colored html from ANSI color description. The generated code use I
 tags.  
92             The generated HTML can be embeded in your pod documentation.
93              
94             =head1 DOCUMENTATION
95              
96             Valid colors:
97            
98             black red green yellow blue magenta cyan white
99            
100             bright_black bright_red bright_green bright_yellow
101             bright_blue bright_magenta bright_cyan bright_white
102              
103             on_black on_red on_green on yellow
104             on_blue on_magenta on_cyan on_white
105            
106             on_bright_black on_bright_red on_bright_green on_bright_yellow
107             on_bright_blue on_bright_magenta on_bright_cyan on_bright_white
108              
109             Todo: insert a color chart in this document.
110              
111             Todo: allow user to add her own generator
112             =head2 Default background color
113              
114             #todo:
115              
116             =head1 SUBROUTINES/METHODS
117              
118             =cut
119              
120              
121             #-------------------------------------------------------------------------------
122              
123             Readonly my $NEW_ARGUMENTS => [qw(NAME INTERACTION VERBOSE JOIN JOIN_FLAT FORMAT DEFAULT_COLOR COLOR RANDOM_COLORS COLORS)] ;
124              
125             sub new
126             {
127              
128             =head2 new(NAMED_ARGUMENTS)
129              
130             Create a Text::Colorizer object.
131              
132             my $c= Text::Colorizer->new() ;
133              
134             I - a list of pairs - Option => Value
135              
136             =over 2
137              
138             =item * NAME - String - Name of the Data::HexDump::Range object, set to 'Anonymous' by default
139              
140             =item * INTERACTION - Hash reference - Set of subs that are used to display information to the user
141              
142             Useful if you use Data::HexDump::Range in an application without terminal.
143              
144             =item * VERBOSE - Boolean - Display information about the creation of the object. Default is I
145              
146             =item * JOIN - String - string used to join colored elements. Default is an empty string.
147              
148             =item * JOIN_FLAT - String - string used to join colored elements passed in array references. Default is an empty string.
149              
150             =item * FORMAT - String - format of the dump string generated by Data::HexDump::Range.
151              
152             Default is B which allows for colors. Other formats are 'ASCII' and 'HTML'.
153              
154             =item * DEFAULT_COLOR -
155              
156             =item * COLOR - String 'bw' or 'cycle'.
157              
158             Ranges for which no color has been defined, in 'ANSI' or 'HTML' format mode, will be rendered in
159             black and white or with a color picked from a cyclic color list. Default is 'bw'.
160              
161             =item * RANDOM_COLORS - Hash reference -
162              
163             COLORS =>
164             {
165             ASCII => [],
166             ANSI => ['white', 'bright_green', 'bright_yellow','bright_cyan', 'bright_red' ],
167             HTML => ['white', 'bright_green', 'bright_yellow','bright_cyan', 'bright_red' ],
168             },
169            
170             =item * COLOR_NAMES - A hash reference
171              
172             COLOR_NAMES =>
173             {
174             HTML =>
175             ...
176            
177             } ;
178              
179             =back
180              
181             I - Text::Colorizer
182              
183             I - Dies if the color description are not valid
184              
185             =cut
186              
187 3     3 1 1672 my ($invocant, @setup_data) = @_ ;
188              
189 3   100     12 my $class = ref($invocant) || $invocant ;
190 3 100       24 confess 'Invalid constructor call!' unless defined $class ;
191              
192 2         2 my $object = {} ;
193              
194 2         5 my ($package, $file_name, $line) = caller() ;
195 2         28 bless $object, $class ;
196              
197 2         4 $object->Setup($package, $file_name, $line, @setup_data) ;
198              
199 2         4 return($object) ;
200             }
201              
202             #-------------------------------------------------------------------------------
203              
204             sub Setup
205             {
206              
207             =head2 Setup
208              
209             Helper sub called by new. This is a private sub.
210              
211             =cut
212              
213 2     2 1 3 my ($self, $package, $file_name, $line, @setup_data) = @_ ;
214              
215 2 50       5 if (@setup_data % 2)
216             {
217 0         0 croak "Invalid number of argument '$file_name, $line'!" ;
218             }
219              
220 2         3 my %valid_argument = map {$_ => 1} @{$NEW_ARGUMENTS} ;
  20         34  
  2         7  
221              
222 2   50 0   17 $self->{INTERACTION}{INFO} ||= sub {print @_} ;
  0         0  
223 2   50     7 $self->{INTERACTION}{WARN} ||= \&Carp::carp ;
224 2   50     6 $self->{INTERACTION}{DIE} ||= \&Carp::croak ;
225 2         3 $self->{NAME} = 'Anonymous';
226 2         2 $self->{FILE} = $file_name ;
227 2         3 $self->{LINE} = $line ;
228              
229 2         5 $self->CheckOptionNames(\%valid_argument, @setup_data) ;
230              
231 2         81 %{$self} =
  2         9  
232             (
233             NAME => 'Anonymous',
234             FILE => $file_name,
235             LINE => $line,
236            
237             JOIN => $EMPTY_STRING,
238             JOIN_FLAT => $EMPTY_STRING,
239            
240             FORMAT => 'ANSI',
241             COLOR => 'cycle',
242            
243             DEFAULT_COLOR => '',
244            
245             RANDOM_COLORS =>
246             {
247             ASCII => [],
248             ANSI => ['white', 'bright_green', 'bright_yellow','bright_cyan', 'bright_red' ],
249             HTML => ['white', 'bright_green', 'bright_yellow','bright_cyan', 'bright_red' ],
250             },
251            
252             COLORS =>
253             {
254             ANSI =>
255             {
256             # you can defined aliases too
257             # alarm => 'bright_red on_bright_yellwo',
258             reset => 'reset',
259            
260             white => 'white',
261             black => 'black',
262             green => 'green',
263             yellow => 'yellow',
264             cyan => 'cyan',
265             red => 'red',
266             blue => 'blue',
267             magenta => 'magenta',
268            
269             bright_white => 'bright_white',
270             bright_black => 'bright_black',
271             bright_green => 'bright_green',
272             bright_yellow => 'bright_yellow',
273             bright_cyan => 'bright_cyan',
274             bright_red => 'bright_red',
275             bright_blue => 'bright_blue',
276             bright_magenta => 'bright_magenta',
277            
278             on_white => 'on_white',
279             on_black => 'on_black',
280             on_green => 'on_green',
281             on_yellow => 'on_yellow',
282             on_cyan => 'on_cyan',
283             on_red => 'on_red',
284             on_blue => 'on_blue',
285             on_magenta => 'on_magenta',
286            
287             on_bright_white => 'on_bright_white',
288             on_bright_black => 'on_bright_black',
289             on_bright_green => 'on_bright_green',
290             on_bright_yellow => 'on_bright_yellow',
291             on_bright_cyan => 'on_bright_cyan',
292             on_bright_red => 'on_bright_red',
293             on_bright_blue => 'on_bright_blue',
294             on_bright_magenta => 'on_bright_magenta',
295             },
296            
297             HTML =>
298             {
299             # any attribute you can put in a span
300             reset => '',
301            
302             white => 'color:#888; ',
303             black => 'color:#000; ',
304             green => 'color:#080; ',
305             yellow => 'color:#880; ',
306             cyan => 'color:#088; ',
307             red => 'color:#800; ',
308             blue => 'color:#008; ',
309             magenta => 'color:#880; ',
310            
311             bright_white => 'color:#fff; ',
312             bright_black => 'color:#000; ',
313             bright_green => 'color:#0f0; ',
314             bright_yellow => 'color:#ff0; ',
315             bright_cyan => 'color:#0ff; ',
316             bright_red => 'color:#f00; ',
317             bright_blue => 'color:#00f; ',
318             bright_magenta => 'color:#ff0; ',
319              
320             on_white => 'background-color:#888; ',
321             on_black => 'background-color:#000; ',
322             on_green => 'background-color:#080; ',
323             on_yellow => 'background-color:#880; ',
324             on_cyan => 'background-color:#088; ',
325             on_red => 'background-color:#800; ',
326             on_blue => 'background-color:#008; ',
327             on_magenta => 'background-color:#880; ',
328            
329             on_bright_white => 'background-color:#fff; ',
330             on_bright_black => 'background-color:#000; ',
331             on_bright_green => 'background-color:#0f0; ',
332             on_bright_yellow => 'background-color:#ff0; ',
333             on_bright_cyan => 'background-color:#0ff; ',
334             on_bright_red => 'background-color:#f00; ',
335             on_bright_blue => 'background-color:#00f; ',
336             on_bright_magenta => 'background-color:#ff0; ',
337             },
338             },
339              
340             @setup_data,
341             ) ;
342              
343 2         34 my $location = "$self->{FILE}:$self->{LINE}" ;
344              
345 2   50 0   10 $self->{INTERACTION}{INFO} ||= sub {print @_} ;
  0         0  
346 2   50     10 $self->{INTERACTION}{WARN} ||= \&Carp::carp ;
347 2   50     9 $self->{INTERACTION}{DIE} ||= \&Carp::confess ;
348              
349 2 50       4 if($self->{VERBOSE})
350             {
351 0         0 $self->{INTERACTION}{INFO}('Creating ' . ref($self) . " '$self->{NAME}' at $location.\n") ;
352             }
353              
354 2         3 return(1) ;
355             }
356              
357             #-------------------------------------------------------------------------------
358              
359             sub CheckOptionNames
360             {
361              
362             =head2 CheckOptionNames
363              
364             Verifies the named options passed to the members of this class. Calls B<{INTERACTION}{DIE}> in case
365             of error. This shall not be used directly.
366              
367             =cut
368              
369 2     2 1 2 my ($self, $valid_options, @options) = @_ ;
370              
371 2 50       5 if (@options % 2)
372             {
373 0         0 $self->{INTERACTION}{DIE}->('Invalid number of argument!') ;
374             }
375              
376 2 50       5 if('HASH' eq ref $valid_options)
    0          
377             {
378             # OK
379             }
380             elsif('ARRAY' eq ref $valid_options)
381             {
382 0         0 $valid_options = map{$_ => 1} @{$valid_options} ;
  0         0  
  0         0  
383             }
384             else
385             {
386 0         0 $self->{INTERACTION}{DIE}->("Invalid argument '$valid_options'!") ;
387             }
388              
389 2         3 my %options = @options ;
390              
391 2         4 for my $option_name (keys %options)
392             {
393 0 0       0 unless(exists $valid_options->{$option_name})
394             {
395 0         0 $self->{INTERACTION}{DIE}->("$self->{NAME}: Invalid Option '$option_name' at '$self->{FILE}:$self->{LINE}'!") ;
396             }
397             }
398              
399 2 50 33     16 if
      33        
      33        
400             (
401             (defined $options{FILE} && ! defined $options{LINE})
402             || (!defined $options{FILE} && defined $options{LINE})
403             )
404             {
405 0         0 $self->{INTERACTION}{DIE}->("$self->{NAME}: Incomplete option FILE::LINE!") ;
406             }
407              
408 2         2 return(1) ;
409             }
410              
411             #-------------------------------------------------------------------------------
412              
413             sub get_colors
414             {
415              
416             =head2 get_colors( )
417              
418             Returns the colors defined in the object
419              
420             my $colors = $c->get_colors( ) ;
421              
422             I - None
423              
424             I - A hash reference
425              
426             I - None
427              
428             =cut
429              
430 0     0 1   my ($self) = @_ ;
431              
432 0           return $self->{COLORS} ;
433             }
434              
435             #-------------------------------------------------------------------------------
436              
437             sub set_colors()
438             {
439              
440             =head2 set_colors(\%colors)
441              
442             Copies
443              
444             my %colors =
445             {
446             HTML =>
447             {
448             white => "style='color:#888;'",
449             black => "style='color:#000;'",
450             ...
451             bright_white => "style='color:#fff;'",
452             bright_black => "style='color:#000;'",
453             bright_green => "style='color:#0f0;'",
454             ...
455             }
456             },
457            
458             $c->set_color(\%colors) ;
459              
460             I
461              
462             =over 2
463              
464             =item * \%colors - A hash reference
465              
466             =back
467              
468             I - Nothing
469              
470             I - dies if the color definitions are invalid
471              
472             =cut
473              
474 0     0 1   my ($self, $colors) = @_ ;
475              
476 0           $self->{COLORS} = $colors ;
477              
478 0           return ;
479             }
480              
481             #-------------------------------------------------------------------------------
482              
483             sub flatten
484             {
485            
486             =head2 [P] flatten($scalar || \@array)
487              
488             Transforms array references to a flat list
489              
490             I -
491              
492             =over 2
493              
494             =item * $scalar -
495              
496             =back
497              
498             I - a lsit of scalars
499              
500             =cut
501              
502             map
503             {
504 0     0 1   my $description = $_ ;
  0            
505            
506 0 0         if(ref($description) eq 'ARRAY')
507             {
508 0           flatten(@{$description}) ;
  0            
509             }
510             else
511             {
512 0           $description
513             }
514             } @_
515             }
516              
517             #-------------------------------------------------------------------------------
518              
519             sub color
520             {
521              
522             =head2 $c->color($color_name, $text, $color_name, \@many_text_strings, ...) ;
523              
524             Returns colored text. according to the object setting. Default is HTML color coded.
525              
526             my $colored_text = $c->color
527             (
528             'red on_black' => 'string',
529             $color => [... many strings..]
530             'user_defined_color_name' => 'string'
531             ) ;
532            
533             I - A list of colors and text pairs
534              
535             =over 2
536              
537             =item * $color -
538              
539             =item * $text -
540              
541             =back
542              
543             I - A single string
544              
545             I - Dies if the color is invalid
546              
547             =cut
548              
549 0     0 1   my ($self) = shift @_ ;
550              
551 0           my ($header, $footer, $colorizer) = ('', '') ;
552              
553 0           for ($self->{FORMAT})
554             {
555             /ASCII/ and do
556 0 0         {
557             #todo flatten and return
558 0           return 'ASCII has no colors!' ;
559             } ;
560            
561             /ANSI/ and do
562 0 0         {
563 0 0 0 0     $colorizer = sub { my ($text, $color) = @_ ; (defined $color && $color ne '') ? colored($text, $color) : $text ; } ;
  0            
  0            
564            
565 0           last ;
566             } ;
567            
568             /HTML/ and do
569 0 0         {
570 0           $header = qq~
\n~ ; 
571 0     0     $colorizer = sub { my ($text, $color) = @_ ; "" . $text . "" ;} ;
  0            
  0            
572 0           $footer .= "\n\n" ;
573            
574 0           last ;
575             } ;
576            
577 0           $self->{INTERACTION}{DIE}("Error: Invalid format '$self->{FORMAT}'.\n");
578             }
579              
580 0 0         $self->{INTERACTION}{DIE}("Error: number of elements in argument list'.\n") if @_ % 2 ;
581              
582 0           my @formated ;
583              
584 0           while(@_)
585             {
586 0           my ($color_tag, $text) = (shift, shift) ;
587 0           my $colors = '' ;
588            
589 0           for my $color_tag_component (split /\s+/, $color_tag)
590             {
591 0           $color_tag_component =~ s/\s+//g ;
592            
593 0           my $color = $self->{COLORS}{$self->{FORMAT}}{$color_tag_component} ;
594            
595 0 0         $self->{INTERACTION}{DIE}("Error: Invalid color componenent '$self->{FORMAT}::$color_tag_component'.\n") unless defined $color ;
596            
597 0           $colors .= ' ' . $color ;
598             }
599            
600 0           push @formated, join $self->{JOIN_FLAT}, map {$colorizer->($_, $colors)} flatten($text) ;
  0            
601             }
602              
603 0           return $header . join($self->{JOIN}, @formated) . $footer ;
604             }
605              
606             #-------------------------------------------------------------------------------
607              
608             sub color_all
609             {
610              
611             =head2 color_all($color, $string, \@many_text_strings, ...)
612              
613             Uses a single color to colorize all the strings
614              
615             my $colored_text = $c->color_all($color, $string, \@many_text_strings, ...) ;
616              
617             I
618              
619             =over 2
620              
621             =item * $xxx -
622              
623             =back
624              
625             I - Nothing
626              
627             I
628              
629             =cut
630              
631 0     0 1   my ($self, $color) = (shift @_, shift @_) ;
632              
633             #todo: verify colors
634              
635 0           return $self->color(map{$color, $_} @_) ;
  0            
636             }
637              
638             #-------------------------------------------------------------------------------
639              
640             sub color_with
641             {
642              
643             =head2 color_with(\%color_definitions, 'color' => 'text', $color => \@many_text_strings, ...) ;
644              
645             Colors a text, temporarely overridding the colors defined in the object.
646              
647             my %colors =
648             {
649             HTML =>
650             {
651             white => "style='color:#888;'",
652             black => "style='color:#000;'",
653             ...
654             bright_white => "style='color:#fff;'",
655             bright_black => "style='color:#000;'",
656             bright_green => "style='color:#0f0;'",
657             ...
658             }
659             },
660            
661             my $colored_text = $c->color
662             (
663             'red on_black' => 'string',
664             'blue on_yellow' => [... many strings..]
665             'user_defined_color_name' => 'string'
666             ) ;
667              
668             I
669              
670             =over 2
671              
672             =item * $ -
673              
674             =item * $color -
675              
676             =item * $xxx -
677              
678             =back
679              
680             I - Nothing
681              
682             I - Dies if any argument is invalid
683              
684             =cut
685              
686 0     0 1   my ($self, $colors) = (shift @_, shift @_) ;
687              
688 0           local $self->{COLORS} = $colors ;
689 0           return $self->color(@_) ;
690             }
691              
692             #-------------------------------------------------------------------------------
693              
694             sub color_all_with
695       0 1   {
696              
697             =head2 color_all_with($temporary_colors, $color, $text | \@many_text_string, ...) ;
698              
699             Uses a single color to colorize all the strings, using a temporary color definition
700              
701             my $temporary_colors =
702             {
703             HTML =>
704             {
705             white => "style='color:#888;'",
706             black => "style='color:#000;'",
707             ...
708             bright_white => "style='color:#fff;'",
709             bright_black => "style='color:#000;'",
710             bright_green => "style='color:#0f0;'",
711             ...
712             }
713             },
714            
715             my $colored_text = $c->color_all_with($temporary_colors, $color, 'string', [... many strings..], ...) ;
716              
717             I
718              
719             =over 2
720              
721             =item * $xxx -
722              
723             =back
724              
725             I - A colorized string
726              
727             I Dies if invalid input is received
728              
729             =cut
730              
731             }
732              
733             #-------------------------------------------------------------------------------
734              
735             1 ;
736              
737             =head1 BUGS AND LIMITATIONS
738              
739             None so far.
740              
741             =head1 AUTHOR
742              
743             Nadim ibn hamouda el Khemir
744             CPAN ID: NKH
745             mailto: nadim@cpan.org
746              
747             =head1 COPYRIGHT & LICENSE
748              
749             Copyright 2010 Nadim Khemir.
750              
751             This program is free software; you can redistribute it and/or
752             modify it under the terms of either:
753              
754             =over 4
755              
756             =item * the GNU General Public License as published by the Free
757             Software Foundation; either version 1, or (at your option) any
758             later version, or
759              
760             =item * the Artistic License version 2.0.
761              
762             =back
763              
764             =head1 SUPPORT
765              
766             You can find documentation for this module with the perldoc command.
767              
768             perldoc Text::Colorizer
769              
770             You can also look for information at:
771              
772             =over 4
773              
774             =item * AnnoCPAN: Annotated CPAN documentation
775              
776             L
777              
778             =item * RT: CPAN's request tracker
779              
780             Please report any bugs or feature requests to L .
781              
782             We will be notified, and then you'll automatically be notified of progress on
783             your bug as we make changes.
784              
785             =item * Search CPAN
786              
787             L
788              
789             =back
790              
791             =head1 SEE ALSO
792              
793             L
794              
795             =cut