File Coverage

blib/lib/Object/String.pm
Criterion Covered Total %
statement 212 212 100.0
branch 38 38 100.0
condition 9 9 100.0
subroutine 78 78 100.0
pod 67 67 100.0
total 404 404 100.0


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