File Coverage

blib/lib/Data/Text.pm
Criterion Covered Total %
statement 93 101 92.0
branch 32 34 94.1
condition 6 9 66.6
subroutine 16 17 94.1
pod 10 10 100.0
total 157 171 91.8


line stmt bran cond sub pod time code
1             package Data::Text;
2              
3 4     4   399692 use warnings;
  4         36  
  4         108  
4 4     4   19 use strict;
  4         5  
  4         57  
5 4     4   14 use Carp;
  4         8  
  4         155  
6 4     4   1524 use String::Clean;
  4         50203  
  4         101  
7 4     4   1613 use String::Util;
  4         11632  
  4         339  
8              
9             =head1 NAME
10              
11             Data::Text - Class to handle text in an OO way
12              
13             =head1 VERSION
14              
15             Version 0.10
16              
17             =cut
18              
19             our $VERSION = '0.10';
20              
21             use overload (
22             '==' => \&equal,
23             '!=' => \¬_equal,
24             '""' => \&as_string,
25 0     0   0 bool => sub { 1 },
26 4         33 fallback => 1 # So that boolean tests don't cause as_string to be called
27 4     4   25 );
  4         6  
28              
29             =head1 SYNOPSIS
30              
31             Handle text in an OO way.
32              
33             use Data::Text;
34              
35             my $d = Data::Text->new("Hello, World!\n");
36              
37             print $d->as_string();
38              
39             =head1 SUBROUTINES/METHODS
40              
41             =head2 new
42              
43             Creates a Data::Text object.
44              
45             The optional parameter 'text' contains a string, or object, to initialise the object with.
46              
47             =cut
48              
49             sub new {
50 21     21 1 2727 my $proto = shift;
51 21   66     82 my $class = ref($proto) || $proto;
52              
53             # Use Data::Text->new(), not Data::Text::new()
54 21 100       39 if(!defined($class)) {
55 1         16 Carp::carp(__PACKAGE__, ': use ->new() not ::new() to instantiate');
56 1         204 return;
57             }
58              
59 20 100       39 if(scalar(@_)) {
60 6         10 my $self = bless { }, $class;
61              
62 6         14 return $self->set(@_);
63             }
64              
65 14         31 return bless { }, $class;
66             }
67              
68             =head2 set
69              
70             Sets the object to contain the given text.
71              
72             The argument can be a reference to an array of strings, or an object.
73             If called with an object, the message as_string() is sent to it for its contents.
74              
75             $d->set({ text => "Hello, World!\n" });
76             $d->set(text => [ 'Hello, ', 'World!', "\n" ]);
77              
78             =cut
79              
80             sub set {
81 9     9 1 575 my $self = shift;
82              
83 9         11 my %params;
84 9 50       32 if(ref($_[0]) eq 'HASH') {
    100          
85 0         0 %params = %{$_[0]};
  0         0  
86             } elsif(scalar(@_) % 2 == 0) {
87 3         6 %params = @_;
88             } else {
89 6         11 $params{'text'} = shift;
90             }
91              
92 9 100       26 if(!defined($params{'text'})) {
93 1         7 Carp::carp(__PACKAGE__, ': no text given');
94 1         268 return;
95             }
96              
97 8 100       16 if(ref($params{'text'})) {
98             # Allow the text to be a reference to a list of strings
99 2 100       5 if(ref($params{'text'}) eq 'ARRAY') {
100 1 50       4 if(scalar(@{$params{'text'}}) == 0) {
  1         4  
101 1         3 Carp::carp(__PACKAGE__, ': no text given');
102 1         261 return;
103             }
104 0         0 delete $self->{'text'};
105 0         0 foreach my $text(@{$params{'text'}}) {
  0         0  
106 0         0 $self = $self->append($text);
107             }
108 0         0 return $self;
109             }
110 1         3 $self->{'text'} = $params{'text'}->as_string();
111             } else {
112 6         30 $self->{'text'} = $params{'text'};
113             }
114              
115 7         17 return $self;
116             }
117              
118              
119             =head2 append
120              
121             Adds data given in "text" to the end of the object.
122             Contains a simple sanity test for consecutive punctuation.
123             I expect I'll improve that.
124              
125             Successive calls to append() can be daisy chained.
126              
127             $d->set('Hello ')->append("World!\n");
128              
129             The argument can be a reference to an array of strings, or an object.
130             If called with an object, the message as_string() is sent to it for its contents.
131              
132             =cut
133              
134             sub append {
135 18     18 1 3082 my $self = shift;
136              
137 18         23 my %params;
138 18 100       44 if(ref($_[0]) eq 'HASH') {
    100          
139 1         2 %params = %{$_[0]};
  1         4  
140             } elsif(scalar(@_) % 2 == 0) {
141 3         7 %params = @_;
142             } else {
143 14         23 $params{'text'} = shift;
144             }
145              
146 18 100       31 if(!defined($params{'text'})) {
147 2         6 Carp::carp(__PACKAGE__, ': no text given');
148 2         517 return;
149             }
150              
151 16 100       27 if(ref($params{'text'})) {
152             # Allow the text to be a reference to a list of strings
153 3 100       10 if(ref($params{'text'}) eq 'ARRAY') {
154 2 100       3 if(scalar(@{$params{'text'}}) == 0) {
  2         7  
155 1         4 Carp::carp(__PACKAGE__, ': no text given');
156 1         241 return;
157             }
158 1         3 foreach my $text(@{$params{'text'}}) {
  1         3  
159 3         8 $self = $self->append($text);
160             }
161 1         11 return $self;
162             }
163 1         8 $params{'text'} = $params{'text'}->as_string();
164             }
165              
166             # FIXME: handle ending with an abbreviation
167              
168 14 100 100     56 if($self->{'text'} && ($self->{'text'} =~ /[\.\,;]\s*$/)) {
169 5 100       12 if($params{'text'} =~ /^\s*[\.\,;]/) {
170             Carp::carp(__PACKAGE__,
171             # die(__PACKAGE__,
172             ": attempt to add consecutive punctuation\n\tCurrent = '",
173             $self->{'text'},
174             "'\n\tAppend = '",
175 4         14 $params{'text'},
176             '"',
177             );
178 4         1319 return;
179             }
180             }
181 10         19 $self->{'text'} .= $params{'text'};
182              
183 10         21 return $self;
184             }
185              
186             =head2 equal
187              
188             Are two texts the same?
189              
190             my $t1 = Data::Text->new('word');
191             my $t2 = Data::Text->new('word');
192             print ($t1 == $t2), "\n"; # Prints 1
193              
194             =cut
195              
196             sub equal {
197 3     3 1 381 my $self = shift;
198 3         5 my $other = shift;
199              
200 3         7 return $self->as_string() eq $other->as_string();
201             }
202              
203             =head2 not_equal
204              
205             Are two texts different?
206              
207             my $t1 = Data::Text->new('xyzzy');
208             my $t2 = Data::Text->new('plugh');
209             print ($t1 != $t2), "\n"; # Prints 1
210              
211             =cut
212              
213             sub not_equal {
214 3     3 1 6 my $self = shift;
215 3         4 my $other = shift;
216              
217 3         4 return $self->as_string() ne $other->as_string();
218             }
219              
220             =head2 as_string
221              
222             Returns the text as a string.
223              
224             =cut
225              
226             sub as_string {
227 26     26 1 1380 my $self = shift;
228              
229 26         110 return $self->{'text'};
230             }
231              
232             =head2 length
233              
234             Returns the length of the text.
235              
236             =cut
237              
238             sub length {
239 2     2 1 4 my $self = shift;
240              
241 2 100       6 if(!defined($self->{'text'})) {
242 1         4 return 0;
243             }
244              
245 1         5 return length($self->{'text'});
246             }
247              
248             =head2 trim
249              
250             Removes leading and trailing spaces from the text.
251              
252             =cut
253              
254             sub trim {
255 1     1 1 2 my $self = shift;
256              
257 1         7 $self->{'text'} = String::Util::trim($self->{'text'});
258              
259 1         25 return $self;
260             }
261              
262             =head2 rtrim
263              
264             Removes trailing spaces from the text.
265              
266             =cut
267              
268             sub rtrim {
269 1     1 1 2 my $self = shift;
270              
271 1         4 $self->{'text'} = String::Util::rtrim($self->{'text'});
272              
273 1         15 return $self;
274             }
275              
276             =head2 replace
277              
278             Replaces words.
279              
280             use Data::Text;
281              
282             my $dt = Data::Text->new();
283             $dt->append('Hello World');
284             $dt->replace({ 'Hello' => 'Goodbye dear' });
285             print $dt->as_string(), "\n"; # Outputs "Goodbye dear world"
286              
287             =cut
288              
289             sub replace {
290 1     1 1 3 my $self = shift;
291              
292 1   33     9 $self->{'clean'} ||= String::Clean->new();
293 1         21 $self->{'text'} = $self->{'clean'}->replace(shift, $self->{'text'}, shift);
294              
295 1         83 return $self;
296             }
297              
298             =head1 AUTHOR
299              
300             Nigel Horne, C<< >>
301              
302             =head1 BUGS
303              
304             =head1 SEE ALSO
305              
306             L, L
307              
308             =head1 SUPPORT
309              
310             You can find documentation for this module with the perldoc command.
311              
312             perldoc Data::Text
313              
314             You can also look for information at:
315              
316             =over 4
317              
318             =item * MetaCPAN
319              
320             L
321              
322             =item * RT: CPAN's request tracker
323              
324             L
325              
326             =item * CPANTS
327              
328             L
329              
330             =item * CPAN Testers' Matrix
331              
332             L
333              
334             =item * CPAN Ratings
335              
336             L
337              
338             =item * CPAN Testers Dependencies
339              
340             L
341              
342             =back
343              
344             =head1 LICENSE AND COPYRIGHT
345              
346             Copyright 2021-2022 Nigel Horne.
347              
348             This program is released under the following licence: GPL2
349              
350             =cut
351              
352             1;