File Coverage

blib/lib/Term/Choose/LineFold.pm
Criterion Covered Total %
statement 33 116 28.4
branch 1 44 2.2
condition 0 7 0.0
subroutine 9 10 90.0
pod 1 1 100.0
total 44 178 24.7


line stmt bran cond sub pod time code
1             package Term::Choose::LineFold;
2              
3 3     3   23 use warnings;
  3         6  
  3         225  
4 3     3   21 use strict;
  3         5  
  3         79  
5 3     3   36 use 5.10.1;
  3         12  
6              
7             our $VERSION = '1.781';
8              
9 3     3   22 use Exporter qw( import );
  3         4  
  3         224  
10              
11             our @EXPORT_OK = qw( char_width print_columns cut_to_printwidth adjust_to_printwidth line_fold );
12              
13 3     3   18 use Carp qw( croak );
  3         23  
  3         194  
14              
15 3     3   32 use Term::Choose::Constants qw( PH SGR_ES EXTRA_W );
  3         32  
  3         216  
16 3     3   1675 use Term::Choose::Screen qw( get_term_size );
  3         32  
  3         942  
17              
18             BEGIN {
19 3     3   11 my $module;
20             eval {
21 3         2446 require Term::Choose::LineFold::XS;
22 3         2714 Term::Choose::LineFold::XS->VERSION( 0.001 );
23 3         11 $module = 'Term::Choose::LineFold::XS';
24 3         27 1;
25 3 50       11 } or do {
26 0         0 require Term::Choose::LineFold::PP;
27 0         0 $module = 'Term::Choose::LineFold::PP';
28             };
29 3     3   42 no strict qw( refs );
  3         7  
  3         443  
30 3         10 for my $func ( qw( char_width print_columns cut_to_printwidth adjust_to_printwidth ) ) {
31 12         19 *{"Term::Choose::LineFold::$func"} = \&{"${module}::$func"};
  12         5677  
  12         40  
32             }
33             }
34             #BEGIN {
35             # my $module;
36             # eval {
37             # require Term::Choose::LineFold::XS;
38             # Term::Choose::LineFold::XS->VERSION( 0.001 );
39             # $module = 'Term::Choose::LineFold::XS';
40             # 1;
41             # } or do {
42             # require Term::Choose::LineFold::PP;
43             # $module = 'Term::Choose::LineFold::PP';
44             # };
45             # *Term::Choose::LineFold::char_width = \&{"${module}::char_width"};
46             # *Term::Choose::LineFold::print_columns = \&{"${module}::print_columns"};
47             # *Term::Choose::LineFold::cut_to_printwidth = \&{"${module}::cut_to_printwidth"};
48             # *Term::Choose::LineFold::adjust_to_printwidth = \&{"${module}::adjust_to_printwidth"};
49             #}
50              
51              
52             sub line_fold {
53 0     0 1   my ( $str, $opt ) = @_; # copy $str
54 0 0         if ( ! length $str ) {
55 0           return $str;
56             }
57 0   0       $opt //= {};
58 0   0       $opt->{join} //= 1;
59 0 0         if ( ! defined $opt->{width} ) {
    0          
60 0           my ( $term_width, undef ) = get_term_size();
61 0           $opt->{width} = $term_width + EXTRA_W;
62             }
63             elsif ( $opt->{width} !~ /^[1-9][0-9]*\z/ ) {
64 0           croak "Option 'width': '$opt->{width}' is not an Integer 1 or greater!";
65             }
66 0           my $max_tab_width = int( $opt->{width} / 2 );
67 0           for ( $opt->{init_tab}, $opt->{subseq_tab} ) {
68 0 0         if ( length ) {
69 0 0         if ( /^[0-9]+\z/ ) {
70 0           $_ = ' ' x $_;
71             }
72             else {
73 0           s/\t/ /g;
74 0           s/\v+/\ \ /g; ##
75 0           s/[\p{Cc}\p{Noncharacter_Code_Point}\p{Cs}]//g;
76             }
77 0 0         if ( length > $max_tab_width ) {
78 0           $_ = cut_to_printwidth( $_, $max_tab_width );
79             }
80             }
81             else {
82 0           $_ = '';
83             }
84             }
85 0           my @color;
86 0 0         if ( $opt->{color} ) {
87 0           $str =~ s/${\PH}//g;
  0            
88 0 0         $str =~ s/(${\SGR_ES})/push( @color, $1 ) && ${\PH}/ge;
  0            
  0            
  0            
89             }
90 0 0 0       if ( $opt->{binary_filter} && substr( $str, 0, 100 ) =~ /[\x00-\x08\x0B-\x0C\x0E-\x1F]/ ) {
91             #$str = $self->{binary_filter} == 2 ? sprintf("%v02X", $_[0]) =~ tr/./ /r : 'BNRY'; # perl 5.14
92 0 0         if ( $opt->{binary_filter} == 2 ) {
93 0           ( $str = sprintf( "%v02X", $_[0] ) ) =~ tr/./ /; # use unmodified string
94             }
95             else {
96 0           $str = 'BNRY';
97             }
98             }
99 0           $str =~ s/\t/ /g;
100 0           $str =~ s/[^\v\P{Cc}]//g; # remove control chars but keep vertical spaces
101 0           $str =~ s/[\p{Noncharacter_Code_Point}\p{Cs}]//g;
102 0           my @paragraphs;
103              
104 0           for my $row ( split /\R/, $str, -1 ) { # -1 to keep trailing empty fields
105 0           my @lines;
106 0           $row =~ s/\s+\z//;
107 0           my @words = split( /(?<=\S)(?=\s)/, $row );
108 0           my $line = $opt->{init_tab};
109              
110 0           for my $i ( 0 .. $#words ) {
111 0 0         if ( print_columns( $line . $words[$i] ) <= $opt->{width} ) {
112 0           $line .= $words[$i];
113             }
114             else {
115 0           my $tmp;
116 0 0         if ( $i == 0 ) {
117 0           $tmp = $opt->{init_tab} . $words[$i];
118             }
119             else {
120 0           push( @lines, $line );
121 0           $words[$i] =~ s/^\s+//;
122 0           $tmp = $opt->{subseq_tab} . $words[$i];
123             }
124 0           ( $line, my $remainder ) = cut_to_printwidth( $tmp, $opt->{width} );
125 0           while ( length $remainder ) {
126 0           push( @lines, $line );
127 0           $tmp = $opt->{subseq_tab} . $remainder;
128 0           ( $line, $remainder ) = cut_to_printwidth( $tmp, $opt->{width} );
129             }
130             }
131 0 0         if ( $i == $#words ) {
132 0           push( @lines, $line );
133             }
134             }
135 0 0         if ( $opt->{join} ) {
136 0           push( @paragraphs, join( "\n", @lines ) );
137             }
138             else {
139 0 0         if ( @lines ) {
140 0           push( @paragraphs, @lines );
141             }
142             else {
143 0           push( @paragraphs, '' );
144             }
145             }
146             }
147 0 0         if ( @color ) {
148 0           my $last_color;
149 0           for my $paragraph ( @paragraphs ) {
150 0 0         if ( ! $opt->{join} ) {
151 0 0         if ( $last_color ) {
152 0           $paragraph = $last_color . $paragraph;
153             }
154 0           my $count = () = $paragraph =~ /${\PH}/g;
  0            
155 0 0         if ( $count ) {
156 0           $last_color = $color[$count - 1];
157             }
158             }
159 0           $paragraph =~ s/${\PH}/shift @color/ge;
  0            
  0            
160 0 0         if ( ! @color ) {
161 0           last;
162             }
163             }
164 0           $paragraphs[-1] .= "\e[0m";
165             }
166 0 0         if ( $opt->{join} ) {
167 0           return join( "\n", @paragraphs );
168             }
169             else {
170 0           return @paragraphs;
171             }
172             }
173              
174              
175              
176             1;
177              
178             __END__