File Coverage

blib/lib/Term/Choose/LineFold.pm
Criterion Covered Total %
statement 32 120 26.6
branch 1 46 2.1
condition 0 12 0.0
subroutine 9 10 90.0
pod 1 1 100.0
total 43 189 22.7


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