File Coverage

blib/lib/Object/String.pm
Criterion Covered Total %
statement 214 214 100.0
branch 38 38 100.0
condition 9 9 100.0
subroutine 76 76 100.0
pod 66 66 100.0
total 403 403 100.0


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