File Coverage

blib/lib/Text/Wrapper.pm
Criterion Covered Total %
statement 68 72 94.4
branch 18 28 64.2
condition 5 6 83.3
subroutine 9 9 100.0
pod 2 3 66.6
total 102 118 86.4


line stmt bran cond sub pod time code
1             #---------------------------------------------------------------------
2             package Text::Wrapper;
3             #
4             # Copyright 1998 Christopher J. Madsen
5             #
6             # Author: Christopher J. Madsen
7             # Created: 06 Mar 1998
8             #
9             # This program is free software; you can redistribute it and/or modify
10             # it under the same terms as Perl itself.
11             #
12             # This program is distributed in the hope that it will be useful,
13             # but WITHOUT ANY WARRANTY; without even the implied warranty of
14             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the
15             # GNU General Public License or the Artistic License for more details.
16             #
17             # ABSTRACT: Word wrap text by breaking long lines
18             #---------------------------------------------------------------------
19              
20 3     3   73889 use 5.008;
  3         12  
  3         121  
21 3     3   68 use strict;
  3         9  
  3         240  
22 3     3   16 use warnings;
  3         5  
  3         102  
23              
24 3     3   15 use Carp qw(croak);
  3         6  
  3         3773  
25              
26             #=====================================================================
27             # Package Global Variables:
28              
29             our $VERSION = '1.05';
30             # This file is part of Text-Wrapper 1.05 (January 18, 2014)
31             our $AUTOLOAD;
32              
33             #=====================================================================
34             # Methods:
35             #---------------------------------------------------------------------
36             # Provide methods for getting/setting fields:
37              
38             sub AUTOLOAD
39             {
40 15     15   20 my $self = $_[0];
41 15 50       48 my $type = ref($self) or croak("$self is not an object");
42 15         19 my $name = $AUTOLOAD;
43 15         27 $name =~ s/.*://; # strip fully-qualified portion
44 15         19 my $field = $name;
45 15         55 $field =~ s/_([a-z])/\u$1/g; # squash underlines into mixed case
46 15 50       44 unless (exists $self->{$field}) {
47             # Ignore special methods like DESTROY:
48 0 0       0 return undef if $name =~ /^[A-Z]+$/;
49 0         0 croak("Can't locate object method \"$name\" via package \"$type\"");
50             }
51 15 50       111 return $self->{$field} = $_[1] if $#_;
52 0         0 $self->{$field};
53             } # end AUTOLOAD
54              
55             #---------------------------------------------------------------------
56             sub new
57             {
58 11 50   11 0 17259 croak "Missing parameter" unless (scalar @_ % 2) == 1;
59              
60 11         51 my ($class, %param) = @_;
61              
62 11         153 my $self = bless {
63             'bodyStart' => '',
64             'columns' => 70,
65             'parStart' => '',
66             }, $class;
67              
68 11 100       72 $self->wrap_after(
69             exists $param{wrap_after} ? delete $param{wrap_after} : '-'
70             );
71              
72 11         17 my $value;
73 11         46 while (($AUTOLOAD, $value) = each %param) {
74 15 50       25 defined eval { &AUTOLOAD($self, $value) }
  15         38  
75             or croak("Unknown parameter `$AUTOLOAD'");
76             }
77              
78 11         42 $self;
79             } # end new
80              
81             sub wrap_after
82             {
83 11     11 1 19 my $self = shift;
84              
85 11 50       38 if (@_) {
86 11         59 $self->{_wrapRE} = $self->_build_wrap_re(
87             $self->{wrapAfter} = shift
88             );
89             }
90              
91 11         100 $self->{wrapAfter};
92             } # end wrap_after
93              
94             #---------------------------------------------------------------------
95             our %_wrap_re_cache;
96             our $hWS = ' \t\r\x{2000}-\x{200B}';
97              
98             sub _build_wrap_re
99             {
100 11     11   21 my ($self, $chars) = @_;
101 11 50       33 $chars = '' unless defined $chars;
102              
103 11   66     60 return $_wrap_re_cache{$chars} ||= do {
104 4 100       12 if (length $chars) {
105 3         16 $chars =~ s/(.)/ sprintf '\x{%X}', ord $1 /seg;
  5         22  
106              
107 3         663 qr(
108             [$hWS]*
109             (?: [^$chars$hWS\n]+ |
110             [$chars]+ [^$chars$hWS\n]* )
111             [$chars]*
112             )x;
113             } else {
114 1         187 qr( [$hWS]* [^$hWS\n]+ )x;
115             }
116             };
117             } # end _build_wrap_re
118              
119             #---------------------------------------------------------------------
120             sub wrap
121             {
122 11     11 1 78 my $self = shift;
123 11         21 my $width = $self->{'columns'};
124 11         18 my $text = $self->{'parStart'};
125 11         18 my $length = length $text;
126 11         14 my $lineStart = $length;
127 11         17 my $parStart = $text;
128 11         12 my $parStartLen = $length;
129 11         24 my $continue = "\n" . $self->{'bodyStart'};
130 11         22 my $contLen = length $self->{'bodyStart'};
131 11         15 my $re = $self->{_wrapRE};
132              
133 11         36 pos($_[0]) = 0; # Make sure we start at the beginning
134 11         20 for (;;) {
135 2013 100       7015 if ($_[0] =~ m/\G[$hWS]*(\n+)/ogc) {
136 25         63 $text .= $1 . $parStart;
137 25         36 $lineStart = $length = $parStartLen;
138             } else {
139 1988 100       12021 $_[0] =~ m/\G($re)/g or last;
140 1977         3248 my $word = $1;
141             again:
142 2800 100 100     9018 if (($length + length $word <= $width) or ($length == $lineStart)) {
143 1977         2274 $length += length $word;
144 1977         3626 $text .= $word;
145             } else {
146 823         1951 $text .= $continue;
147 823         1469 $lineStart = $length = $contLen;
148 823         2175 $word =~ s/^[$hWS]+//o;
149 823         3586 goto again;
150             }
151             }
152             } # end forever
153 11 50       45 if ($length != $lineStart) { $text .= "\n" }
  0         0  
154 11         405 else { $text =~ s/(?:\Q$continue\E|\n\Q$parStart\E)\Z/\n/ }
155              
156 11         78 $text;
157             } # end wrap
158              
159             #=====================================================================
160             # Package Return Value:
161              
162             1;
163              
164             __END__