File Coverage

blib/lib/Sub/HandlesVia/HandlerLibrary/String.pm
Criterion Covered Total %
statement 71 72 98.6
branch 2 2 100.0
condition 2 3 66.6
subroutine 43 44 97.7
pod 21 21 100.0
total 139 142 97.8


line stmt bran cond sub pod time code
1 11     11   855 use 5.008;
  11         40  
2 11     11   63 use strict;
  11         25  
  11         251  
3 11     11   59 use warnings;
  11         21  
  11         690  
4              
5             package Sub::HandlesVia::HandlerLibrary::String;
6              
7             our $AUTHORITY = 'cpan:TOBYINK';
8             our $VERSION = '0.050000';
9              
10 11     11   3815 use Sub::HandlesVia::HandlerLibrary;
  11         37  
  11         547  
11             our @ISA = 'Sub::HandlesVia::HandlerLibrary';
12              
13 11     11   82 use Sub::HandlesVia::Handler qw( handler );
  11         23  
  11         87  
14 11     11   981 use Types::Standard qw( Optional Str CodeRef RegexpRef Int Any Item Defined );
  11         26  
  11         57  
15              
16             our @METHODS = qw(
17             set get inc append prepend chop chomp clear reset
18             length substr replace replace_globally uc lc fc
19             starts_with ends_with contains match cmp eq ne gt lt ge le
20             starts_with_i ends_with_i contains_i match_i cmpi eqi nei gti lti gei lei
21             );
22              
23             my $fold = ( $] >= 5.016 ) ? 'CORE::fc' : 'lc';
24              
25             sub _type_inspector {
26 132     132   322 my ($me, $type) = @_;
27 132 100 66     391 if ($type == Str or $type == Defined) {
28             return {
29 84         6475 trust_mutated => 'always',
30             };
31             }
32 48         22993 return $me->SUPER::_type_inspector($type);
33             }
34              
35             sub set {
36             handler
37             name => 'String:set',
38             args => 1,
39             signature => [Str],
40             template => '« $ARG »',
41             lvalue_template => '$GET = $ARG',
42             usage => '$value',
43             documentation => "Sets the string to a new value.",
44             _examples => sub {
45 1     1   73 my ( $class, $attr, $method ) = @_;
46 1         7 return join "",
47             " my \$object = $class\->new( $attr => 'foo' );\n",
48             " \$object->$method\( 'bar' );\n",
49             " say \$object->$attr; ## ==> 'bar'\n",
50             "\n";
51             },
52 4     4 1 48 }
53              
54             sub get {
55             handler
56             name => 'String:get',
57             args => 0,
58             template => '$GET',
59             documentation => "Gets the current value of the string.",
60             _examples => sub {
61 1     1   71 my ( $class, $attr, $method ) = @_;
62 1         7 return join "",
63             " my \$object = $class\->new( $attr => 'foo' );\n",
64             " say \$object->$method; ## ==> 'foo'\n",
65             "\n";
66             },
67 3     3 1 48 }
68              
69             sub inc {
70 35     35 1 219 handler
71             name => 'String:inc',
72             args => 0,
73             template => '« do { my $shv_tmp = $GET; ++$shv_tmp } »',
74             lvalue_template => '++$GET',
75             additional_validation => 'no incoming values',
76             documentation => "Performs C<< ++ >> on the string.",
77             }
78              
79             sub append {
80             handler
81             name => 'String:append',
82             args => 1,
83             signature => [Str],
84             template => '« $GET . $ARG »',
85             lvalue_template => '$GET .= $ARG',
86             usage => '$tail',
87             documentation => "Appends another string to the end of the current string and updates the attribute.",
88             _examples => sub {
89 1     1   65 my ( $class, $attr, $method ) = @_;
90 1         110 return join "",
91             " my \$object = $class\->new( $attr => 'foo' );\n",
92             " \$object->$method( 'bar' );\n",
93             " say \$object->$attr; ## ==> 'foobar'\n",
94             "\n";
95             },
96 70     70 1 491 }
97              
98             sub prepend {
99             handler
100             args => 1,
101             name => 'String:prepend',
102             signature => [Str],
103             template => '« $ARG . $GET »',
104             usage => '$head',
105             documentation => "Prepends another string to the start of the current string and updates the attribute.",
106             _examples => sub {
107 1     1   65 my ( $class, $attr, $method ) = @_;
108 1         7 return join "",
109             " my \$object = $class\->new( $attr => 'foo' );\n",
110             " \$object->$method( 'bar' );\n",
111             " say \$object->$attr; ## ==> 'barfoo'\n",
112             "\n";
113             },
114 67     67 1 379 }
115              
116             sub replace {
117             handler
118             name => 'String:replace',
119             args => 2,
120             signature => [ Str|RegexpRef, Str|CodeRef ],
121             usage => '$regexp, $replacement',
122             template => sprintf(
123             'my $shv_tmp = $GET; if (%s) { my $shv_callback = $ARG[2]; $shv_tmp =~ s/$ARG[1]/$shv_callback->()/e } else { $shv_tmp =~ s/$ARG[1]/$ARG[2]/ } «$shv_tmp»',
124             CodeRef->inline_check('$ARG[2]'),
125             ),
126             lvalue_template => sprintf(
127             'if (%s) { my $shv_callback = $ARG[2]; $GET =~ s/$ARG[1]/$shv_callback->()/e } else { $GET =~ s/$ARG[1]/$ARG[2]/ } $GET',
128             CodeRef->inline_check('$ARG[2]'),
129             ),
130             documentation => "Replaces the first regexp match within the string with the replacement string.",
131             _examples => sub {
132 1     1   70 my ( $class, $attr, $method ) = @_;
133 1         10 return join "",
134             " my \$object = $class\->new( $attr => 'foo' );\n",
135             " \$object->$method( 'o' => 'a' );\n",
136             " say \$object->$attr; ## ==> 'fao'\n",
137             "\n",
138             " my \$object2 = $class\->new( $attr => 'foo' );\n",
139             " \$object2->$method( qr/O/i => sub { return 'e' } );\n",
140             " say \$object2->$attr; ## ==> 'feo'\n",
141             "\n";
142             },
143 67     67 1 286 }
144              
145             sub replace_globally {
146             handler
147             name => 'String:replace_globally',
148             args => 2,
149             signature => [ Str|RegexpRef, Str|CodeRef ],
150             usage => '$regexp, $replacement',
151             template => sprintf(
152             'my $shv_tmp = $GET; if (%s) { my $shv_callback = $ARG[2]; $shv_tmp =~ s/$ARG[1]/$shv_callback->()/eg } else { $shv_tmp =~ s/$ARG[1]/$ARG[2]/g } «$shv_tmp»',
153             CodeRef->inline_check('$ARG[2]'),
154             ),
155             lvalue_template => sprintf(
156             'if (%s) { my $shv_callback = $ARG[2]; $GET =~ s/$ARG[1]/$shv_callback->()/eg } else { $GET =~ s/$ARG[1]/$ARG[2]/g } $GET',
157             CodeRef->inline_check('$ARG[2]'),
158             ),
159             documentation => "Replaces the all regexp matches within the string with the replacement string.",
160             _examples => sub {
161 1     1   66 my ( $class, $attr, $method ) = @_;
162 1         18 return join "",
163             " my \$object = $class\->new( $attr => 'foo' );\n",
164             " \$object->$method( 'o' => 'a' );\n",
165             " say \$object->$attr; ## ==> 'faa'\n",
166             "\n",
167             " my \$object2 = $class\->new( $attr => 'foo' );\n",
168             " \$object2->$method( qr/O/i => sub { return 'e' } );\n",
169             " say \$object2->$attr; ## ==> 'fee'\n",
170             "\n";
171             },
172 3     3 1 58 }
173              
174             sub match {
175             handler
176             name => 'String:match',
177             args => 1,
178             signature => [ Str|RegexpRef ],
179             usage => '$regexp',
180             template => '$GET =~ /$ARG/',
181             documentation => "Returns true iff the string matches the regexp.",
182             _examples => sub {
183 1     1   64 my ( $class, $attr, $method ) = @_;
184 1         12 return join "",
185             " my \$object = $class\->new( $attr => 'foo' );\n",
186             " if ( \$object->$method\( '^f..\$' ) ) {\n",
187             " say 'matched!';\n",
188             " }\n",
189             "\n";
190             },
191 69     69 1 316 }
192              
193             sub match_i {
194             handler
195             name => 'String:match_i',
196             args => 1,
197             signature => [ Str|RegexpRef ],
198             usage => '$regexp',
199             template => '$GET =~ /$ARG/i',
200             documentation => "Returns true iff the string matches the regexp case-insensitively.",
201             _examples => sub {
202 1     1   73 my ( $class, $attr, $method ) = @_;
203 1         8 return join "",
204             " my \$object = $class\->new( $attr => 'foo' );\n",
205             " if ( \$object->$method\( '^F..\$' ) ) {\n",
206             " say 'matched!';\n",
207             " }\n",
208             "\n";
209             },
210 4     4 1 23 }
211              
212             sub starts_with {
213 4     4 1 24 handler
214             name => 'String:starts_with',
215             args => 1,
216             signature => [ Str ],
217             usage => '$head',
218             template => 'substr($GET, 0, length $ARG) eq $ARG',
219             documentation => "Returns true iff the string starts with C<< \$head >>.",
220             }
221              
222             sub starts_with_i {
223 4     4 1 24 handler
224             name => 'String:starts_with_i',
225             args => 1,
226             signature => [ Str ],
227             usage => '$head',
228             template => sprintf( '%s(substr($GET, 0, length $ARG)) eq %s($ARG)', $fold, $fold ),
229             documentation => "Returns true iff the string starts with C<< \$head >> case-insensitvely.",
230             }
231              
232             sub ends_with {
233 4     4 1 29 handler
234             name => 'String:ends_with',
235             args => 1,
236             signature => [ Str ],
237             usage => '$tail',
238             template => 'substr($GET, -length $ARG) eq $ARG',
239             documentation => "Returns true iff the string ends with C<< \$tail >>.",
240             }
241              
242             sub ends_with_i {
243 4     4 1 28 handler
244             name => 'String:ends_with_i',
245             args => 1,
246             signature => [ Str ],
247             usage => '$tail',
248             template => sprintf( '%s(substr($GET, -length $ARG)) eq %s($ARG)', $fold, $fold ),
249             documentation => "Returns true iff the string ends with C<< \$tail >> case-insensitvely.",
250             }
251              
252             sub contains {
253 4     4 1 35 handler
254             name => 'String:contains',
255             args => 1,
256             signature => [ Str ],
257             usage => '$str',
258             template => 'index($GET, $ARG) != -1',
259             documentation => "Returns true iff the string contains C<< \$str >>.",
260             }
261              
262             sub contains_i {
263 4     4 1 28 handler
264             name => 'String:contains_i',
265             args => 1,
266             signature => [ Str ],
267             usage => '$str',
268             template => sprintf( 'index(%s($GET), %s($ARG)) != -1', $fold, $fold ),
269             documentation => "Returns true iff the string contains C<< \$str >> case-insensitvely.",
270             }
271              
272             sub chop {
273 35     35 1 211 handler
274             name => 'String:chop',
275             args => 0,
276             template => 'my $shv_return = chop(my $shv_tmp = $GET); «$shv_tmp»; $shv_return',
277             lvalue_template => 'chop($GET)',
278             additional_validation => 'no incoming values',
279             documentation => "Like C<chop> from L<perlfunc>.",
280             }
281              
282             sub chomp {
283 35     35 1 215 handler
284             name => 'String:chomp',
285             args => 0,
286             template => 'my $shv_return = chomp(my $shv_tmp = $GET); «$shv_tmp»; $shv_return',
287             lvalue_template => 'chomp($GET)',
288             additional_validation => 'no incoming values',
289             documentation => "Like C<chomp> from L<perlfunc>.",
290             }
291              
292             sub clear {
293             handler
294             name => 'String:clear',
295             args => 0,
296             template => '«q()»',
297             additional_validation => 'no incoming values',
298             documentation => "Sets the string to the empty string.",
299             _examples => sub {
300 1     1   71 my ( $class, $attr, $method ) = @_;
301 1         15 return join "",
302             " my \$object = $class\->new( $attr => 'foo' );\n",
303             " \$object->$method;\n",
304             " say \$object->$attr; ## nothing\n",
305             "\n";
306             },
307 35     35 1 351 }
308              
309             sub reset {
310             handler
311             name => 'String:reset',
312             args => 0,
313             template => '« $DEFAULT »',
314 0     0   0 default_for_reset => sub { 'q()' },
315 3     3 1 27 documentation => 'Resets the attribute to its default value, or an empty string if it has no default.',
316             }
317              
318             sub length {
319             handler
320             name => 'String:length',
321             args => 0,
322             template => 'length($GET)',
323             documentation => "Like C<length> from L<perlfunc>.",
324             _examples => sub {
325 1     1   63 my ( $class, $attr, $method ) = @_;
326 1         7 return join "",
327             " my \$object = $class\->new( $attr => 'foo' );\n",
328             " say \$object->$method; ## ==> 3\n",
329             "\n";
330             },
331 35     35 1 334 }
332              
333             sub substr {
334 131     131 1 682 handler
335             name => 'String:substr',
336             min_args => 1,
337             max_args => 3,
338             signature => [Int, Optional[Int], Optional[Str]],
339             usage => '$start, $length?, $replacement?',
340             template => 'if (#ARG==1) { substr($GET, $ARG[1]) } elsif (#ARG==2) { substr($GET, $ARG[1], $ARG[2]) } elsif (#ARG==3) { my $shv_tmp = $GET; my $shv_return = substr($shv_tmp, $ARG[1], $ARG[2], $ARG[3]); «$shv_tmp»; $shv_return } ',
341             lvalue_template => 'if (#ARG==1) { substr($GET, $ARG[1]) } elsif (#ARG==2) { substr($GET, $ARG[1], $ARG[2]) } elsif (#ARG==3) { substr($GET, $ARG[1], $ARG[2], $ARG[3]) } ',
342             documentation => "Like C<substr> from L<perlfunc>, but is not an lvalue.",
343             }
344              
345             for my $comparison ( qw/ cmp eq ne lt gt le ge / ) {
346 11     11   56971 no strict 'refs';
  11         45  
  11         2188  
347              
348             *$comparison = sub {
349 30     30   218 handler
350             name => "String:$comparison",
351             args => 1,
352             signature => [Str],
353             usage => '$str',
354             template => "\$GET $comparison \$ARG",
355             documentation => "Returns C<< \$object->attr $comparison \$str >>.",
356             };
357              
358             *{ $comparison . 'i' } = sub {
359 28     28   196 handler
360             name => "String:$comparison" . 'i',
361             args => 1,
362             signature => [Str],
363             usage => '$str',
364             template => "$fold(\$GET) $comparison $fold(\$ARG)",
365             documentation => "Returns C<< fc(\$object->attr) $comparison fc(\$str) >>. Uses C<lc> instead of C<fc> in versions of Perl older than 5.16.",
366             };
367             }
368              
369             for my $mutation ( qw/ uc fc lc / ) {
370 11     11   89 no strict 'refs';
  11         38  
  11         1390  
371             my $mutationf = $mutation;
372             if ( $mutationf eq 'fc' ) {
373             $mutationf = $fold;
374             }
375             *$mutation = sub {
376 13     13   145 handler
377             name => "String:$mutation",
378             args => 0,
379             template => "$mutationf(\$GET)",
380             documentation => "Returns C<< $mutation(\$object->attr) >>.",
381             };
382             }
383              
384             1;