File Coverage

blib/lib/Object/String.pm
Criterion Covered Total %
statement 202 202 100.0
branch 36 36 100.0
condition 9 9 100.0
subroutine 73 73 100.0
pod 64 64 100.0
total 384 384 100.0


line stmt bran cond sub pod time code
1 1     1   17094 use strict;
  1         1  
  1         36  
2 1     1   4 use warnings;
  1         1  
  1         23  
3 1     1   2 use utf8;
  1         6  
  1         5  
4 1     1   24 use v5.10;
  1         2  
  1         35  
5              
6             package Object::String;
7 1     1   7875 use Unicode::Normalize;
  1         2033  
  1         84  
8             our $VERSION = '0.09'; # VERSION
9              
10             # ABSTRACT: A string object for Perl 5
11              
12 1     1   529 use Moo;
  1         13388  
  1         5  
13              
14              
15              
16             has 'string' => ( is => 'ro' );
17              
18              
19 1     1 1 21 sub to_string { shift->string; }
20              
21              
22             sub to_lower {
23 82     82 1 127 my $self = shift;
24 82         168 $self->{string} = lc $self->{string};
25 82         314 return $self;
26             }
27              
28              
29             sub to_lower_first {
30 5     5 1 34 my $self = shift;
31 5         13 $self->{string} = lcfirst $self->{string};
32 5         28 return $self;
33             }
34              
35              
36             sub to_upper {
37 3     3 1 923 my $self = shift;
38 3         8 $self->{string} = uc $self->{string};
39 3         17 return $self;
40             }
41              
42              
43             sub to_upper_first {
44 28     28 1 84 my $self = shift;
45 28         49 $self->{string} = ucfirst $self->{string};
46 28         107 return $self;
47             }
48              
49              
50 26     26 1 311 sub capitalize { shift->to_lower->to_upper_first; }
51              
52              
53 25     25 1 127 sub Object::String::length { return CORE::length shift->string; }
54              
55              
56             sub ensure_left {
57 2     2 1 29 my ($self, $prefix) = @_;
58 2 100       4 $self->{string} = $self->prefix($prefix)->string
59             unless($self->starts_with($prefix));
60 2         9 return $self;
61             }
62              
63              
64             sub ensure_right {
65 2     2 1 29 my ($self, $suffix) = @_;
66 2 100       5 $self->{string} = $self->suffix($suffix)->string
67             unless($self->ends_with($suffix));
68 2         46 return $self;
69             }
70              
71              
72             sub trim_left {
73 30     30 1 112 my $self = shift;
74 30         86 $self->{string} =~ s/^(\s|\t)+//;
75 30         81 return $self;
76             }
77              
78              
79             sub trim_right {
80 29     29 1 82 my $self = shift;
81 29         129 $self->{string} =~ s/(\s|\t)+$//;
82 29         134 return $self;
83             }
84              
85              
86 25     25 1 115 sub trim { shift->trim_left->trim_right; }
87              
88              
89             sub clean {
90 11     11 1 41 my $self = shift;
91 11         88 $self->{string} =~ s/(\s|\t)+/ /g;
92 11         28 return $self->trim;
93             }
94              
95              
96 2     2 1 30 sub collapse_whitespace { shift->clean; }
97              
98              
99             sub repeat {
100 2     2 1 18 my ($self, $n) = @_;
101 2         11 $self->{string} = $self->string x $n;
102 2         10 return $self;
103             }
104              
105              
106 1     1 1 17 sub times { shift->repeat(@_); }
107              
108              
109             sub starts_with {
110 15     15 1 50 my ($self, $str) = @_;
111 15         164 return ($self->string =~ /^$str/);
112             }
113              
114              
115             sub ends_with {
116 9     9 1 37 my ($self, $str) = @_;
117 9         114 return ($self->string =~ /$str$/);
118             }
119              
120              
121             sub contains {
122 4     4 1 31 my ($self, $str) = @_;
123 4         19 return index $self->string, $str;
124             }
125              
126              
127 2     2 1 30 sub include { shift->contains(@_); }
128              
129              
130             sub chomp_left {
131 3     3 1 40 my $self = shift;
132 3 100 100     23 if($self->starts_with(" ") || $self->starts_with("\t")) {
133 2         6 return $self->chop_left;
134             }
135 1         5 return $self;
136             }
137              
138              
139             sub chomp_right {
140 3     3 1 39 my $self = shift;
141 3 100 100     7 if($self->ends_with(" ") || $self->ends_with("\t")) {
142 2         5 return $self->chop_right;
143             }
144 1         5 return $self;
145             }
146              
147              
148             sub chop_left {
149 4     4 1 28 my $self = shift;
150 4         9 $self->{string} = substr $self->{string}, 1, CORE::length $self->{string};
151 4         19 return $self;
152              
153             }
154              
155              
156             sub chop_right {
157 4     4 1 28 my $self = shift;
158 4         7 chop $self->{string};
159 4         20 return $self;
160             }
161              
162              
163 4     4 1 91 sub is_numeric { shift->string =~ /^\d+$/; }
164              
165              
166 4     4 1 77 sub is_alpha { shift->string =~ /^[a-zA-Z]+$/; }
167              
168              
169 4     4 1 77 sub is_alpha_numeric { shift->string =~ /^[a-zA-Z0-9]+$/; }
170              
171              
172             sub is_lower {
173 4     4 1 55 my $self = shift;
174 4         20 return $self->string eq lc $self->string;
175             }
176              
177              
178             sub is_upper {
179 4     4 1 54 my $self = shift;
180 4         20 return $self->string eq uc $self->string;
181             }
182              
183              
184             sub to_boolean {
185 26     26 1 194 my $self = shift;
186 26 100       149 return 1 if $self->string =~ /^(on|yes|true)$/i;
187 16 100       76 return 0 if $self->string =~ /^(off|no|false)$/i;
188 6         21 return;
189             }
190              
191              
192 13     13 1 210 sub to_bool { shift->to_boolean }
193              
194              
195             sub is_empty {
196 6     6 1 87 my $self = shift;
197 6 100 100     52 return 1 if $self->string =~ /\s+/ || $self->string eq '';
198 1         4 return 0;
199             }
200              
201              
202             sub count {
203 1     1 1 16 my ($self, $str) = @_;
204 1         23 return () = $self->string =~ /$str/g;
205             }
206              
207              
208             sub left {
209 3     3 1 91 my ($self, $count) = @_;
210 3 100       11 if($count < 0) {
211 1         5 $self->{string} = substr $self->string, $count, abs($count);
212 1         18 return $self;
213             }
214 2         10 $self->{string} = substr $self->string, 0, $count;
215 2         11 return $self;
216             }
217              
218              
219             sub right {
220 3     3 1 43 my ($self, $count) = @_;
221 3 100       8 if($count < 0) {
222 1         5 $self->{string} = substr $self->string, 0, abs($count);
223 1         5 return $self;
224             }
225 2         7 $self->{string} = substr $self->string, -$count, $count;
226 2         8 return $self;
227             }
228              
229              
230             sub underscore {
231 51     51 1 252 my $self = shift;
232 51         96 $self->{string} =~ tr/ -/_/;
233 51         101 $self->{string} =~ s/::/\//g;
234 51         198 $self->{string} =~ s/^([A-Z])/_$1/;
235 51         177 $self->{string} =~ s/([A-Z]+)([A-Z][a-z])/$1_$2/g;
236 51         245 $self->{string} =~ s/([a-z\d])([A-Z])/$1_$2/g;
237 51         111 return $self->to_lower;
238             }
239              
240              
241 10     10 1 221 sub underscored { shift->underscore; }
242              
243              
244             sub dasherize {
245 13     13 1 221 my $self = shift;
246 13         34 $self->{string} = $self->underscore->string;
247 13         24 $self->{string} =~ tr/_/-/;
248 13         146 return $self;
249             }
250              
251              
252             sub camelize {
253 6     6 1 130 my $self = shift;
254 6         15 my $begins_underscore = $self->underscore->starts_with('_');
255 6         18 $self->{string} = join '', map { ucfirst $_ } split /_/, $self->underscore->string;
  25         58  
256 6         22 $self->{string} = join '::', map { ucfirst $_ } split /\//, $self->string;
  8         22  
257 6 100       38 return ($begins_underscore ? $self : $self->to_lower_first);
258             }
259              
260              
261             sub latinise {
262 4     4 1 25 my $self = shift;
263 4         51 $self->{string} = NFKD($self->string);
264 1     1   2665 $self->{string} =~ s/\p{NonspacingMark}//g;
  1         1  
  1         13  
  4         32  
265 4         16 return $self;
266             }
267              
268              
269             sub escape_html {
270 2     2 1 52 return shift->replace_all('&', '&')
271             ->replace_all('"', '"')
272             ->replace_all("'", ''')
273             ->replace_all('<', '<')
274             ->replace_all('>', '>');
275             }
276              
277              
278             sub unescape_html {
279 2     2 1 48 return shift->replace_all('&', '&')
280             ->replace_all('"', '"')
281             ->replace_all(''', "'")
282             ->replace_all('<', '<')
283             ->replace_all('>', '>');
284             }
285              
286              
287             sub index_left {
288 2     2 1 44 my ($self, $substr, $position) = @_;
289 2 100       15 return index $self->string, $substr, $position if defined $position;
290 1         11 return index $self->string, $substr;
291             }
292              
293              
294             sub index_right {
295 2     2 1 47 my ($self, $substr, $position) = @_;
296 2 100       15 return rindex $self->string, $substr, $position if defined $position;
297 1         12 return rindex $self->string, $substr;
298             }
299              
300              
301             sub replace_all {
302 28     28 1 93 my ($self, $substr1, $substr2) = @_;
303 28         36 $substr1 = quotemeta $substr1;
304 28         329 $self->{string} =~ s/$substr1/$substr2/g;
305 28         118 return $self;
306             }
307              
308              
309             sub humanize {
310             return shift->underscore
311 6     6 1 56 ->replace_all('_', ' ')
312             ->trim
313             ->capitalize;
314             }
315              
316              
317             sub pad_left {
318 4     4 1 59 my ($self, $count, $char) = @_;
319 4 100       11 $char = ' ' unless defined $char;
320 4 100       9 return $self if $count <= $self->length;
321 2         3 $self->{string} = $char x ($count - $self->length) . $self->string;
322 2         11 return $self;
323             }
324              
325              
326             sub pad_right {
327 4     4 1 69 my ($self, $count, $char) = @_;
328 4 100       11 $char = ' ' unless defined $char;
329 4 100       9 return $self if $count <= $self->length;
330 2         8 $self->{string} = $self->string . $char x ($count - $self->length);
331 2         11 return $self;
332             }
333              
334              
335             sub pad {
336 5     5 1 76 my ($self, $count, $char) = @_;
337 5 100       14 $char = ' ' unless defined $char;
338 5 100       9 return $self if $count <= $self->length;
339 3         7 my $count_left = 1 + int(($count - $self->length) / 2);
340 3         6 my $count_right = $count - $self->length - $count_left;
341 3         12 $self->{string} = $char x $count_left . $self->string;
342 3         8 $self->{string} = $self->string . $char x $count_right;
343 3         13 return $self;
344             }
345              
346              
347             sub next {
348 2     2 1 108 my $self = shift;
349 2         5 $self->{string}++;
350 2         10 return $self;
351             }
352              
353              
354             sub slugify {
355             return shift->trim
356             ->humanize
357             ->latinise
358             ->strip_punctuation
359             ->to_lower
360 3     3 1 49 ->dasherize;
361             }
362              
363              
364             sub strip_punctuation {
365 8     8 1 31 my $self = shift;
366 8         30 $self->{string} =~ s/[[:punct:]]//g;
367 8         34 return $self;
368             }
369              
370              
371             sub swapcase {
372 1     1 1 25 my $self = shift;
373 1         4 $self->{string} =~ tr/a-zA-Z/A-Za-z/;
374 1         7 return $self;
375             }
376              
377              
378             sub concat {
379 5     5 1 35 my ($self, @strings) = @_;
380 5         19 $self->{string} = $self->string . join '', @strings;
381 5         32 return $self;
382             }
383              
384              
385 3     3 1 37 sub suffix { shift->concat(@_); }
386              
387              
388             sub prefix {
389 3     3 1 35 my ($self, @strings) = @_;
390 3         13 $self->{string} = join('', @strings) . $self->string;
391 3         13 return $self;
392             }
393              
394              
395             sub reverse {
396 1     1 1 16 my $self = shift;
397 1         7 $self->{string} = join '', reverse split //, $self->string;
398 1         4 return $self;
399             }
400              
401              
402 3     3 1 48 sub count_words { 0 + split /\s/, shift->clean->string; }
403              
404              
405             sub quote_meta {
406 1     1 1 15 my $self = shift;
407 1         5 $self->{string} = quotemeta $self->string;
408 1         5 return $self;
409             }
410              
411              
412             sub rot13 {
413 3     3 1 36 my $self = shift;
414 3         6 $self->{string} =~ tr/A-Za-z/N-ZA-Mn-za-m/;
415 3         14 return $self;
416             }
417              
418              
419 1     1 1 181 sub say { CORE::say shift->string; }
420              
421              
422             sub titleize {
423 4     4 1 110 my $self = shift;
424 4         14 $self->{string} = join ' ', map { str($_)->capitalize->string }
  16         62  
425             split / /,
426             $self->clean
427             ->strip_punctuation
428             ->string;
429 4         25 return $self;
430             }
431              
432              
433 2     2 1 39 sub titlecase { shift->titleize }
434              
435 1     1   17394 no Moo;
  1         3  
  1         6  
436              
437 1     1   176 use base 'Exporter';
  1         1  
  1         188  
438              
439             our @EXPORT = qw {
440             str
441             };
442              
443              
444             sub str {
445 223     223 1 3185 my $string = join ' ', @_;
446              
447 223         5888 return Object::String->new(string => $string);
448             }
449              
450             1;
451              
452             __END__