File Coverage

blib/lib/String/Substitution.pm
Criterion Covered Total %
statement 38 38 100.0
branch 10 10 100.0
condition 2 3 66.6
subroutine 14 14 100.0
pod 8 8 100.0
total 72 73 98.6


line stmt bran cond sub pod time code
1             # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
2             #
3             # This file is part of String-Substitution
4             #
5             # This software is copyright (c) 2010 by Randy Stauner.
6             #
7             # This is free software; you can redistribute it and/or modify it under
8             # the same terms as the Perl 5 programming language system itself.
9             #
10 2     2   11836 use strict;
  2         3  
  2         57  
11 2     2   4 use warnings;
  2         3  
  2         80  
12              
13             package String::Substitution;
14             # git description: v1.001-5-gd591202
15              
16             our $AUTHORITY = 'cpan:RWSTAUNER';
17             # ABSTRACT: Simple runtime string substitution functions
18             $String::Substitution::VERSION = '1.002';
19 2     2   775 use Sub::Exporter 0.982;
  2         13688  
  2         8  
20             {
21             my $exports = {
22             exports => [qw(interpolate_match_vars last_match_vars)],
23             groups => {}
24             };
25             my @funcs = qw(sub gsub);
26             foreach my $suffix ( qw(copy modify context) ){
27             push(@{ $exports->{exports} }, map { "${_}_${suffix}" } @funcs);
28             $exports->{groups}->{$suffix} = [
29             map { ("${_}_${suffix}" => { -as => $_ }) } @funcs
30             ];
31             }
32             Sub::Exporter::setup_exporter($exports);
33             }
34              
35              
36             sub gsub_copy {
37 174     174 1 62419 my ($string, $pattern, $replacement) = @_;
38 174         1412 $string =~ s/$pattern/
39 166         448 _replacement_sub($replacement)->(last_match_vars());/ge;
40 174         1086 return $string;
41             }
42              
43              
44             sub gsub_modify {
45 174     174 1 59642 my ( undef, $pattern, $replacement ) = @_;
46 174         1386 return $_[0] =~ s/$pattern/
47 166         340 _replacement_sub($replacement)->(last_match_vars());/ge;
48             }
49              
50              
51             sub gsub_context {
52             return defined wantarray
53 174 100   174 1 178941 ? gsub_copy(@_)
54             : gsub_modify(@_);
55             }
56              
57              
58             sub interpolate_match_vars {
59 528     528 1 820 my ($replacement, @matched) = @_;
60 528         616 my $string = $replacement;
61             # Handling backslash-escapes and variable interpolations
62             # in the same substitution (alternation) keeps track of the position
63             # in the string so that we don't have to count backslashes.
64 528         1688 $string =~
65             s/
66             (?:
67             \\(.) # grab escaped characters (including $)
68             |
69             (?:
70             \$\{([1-9]\d*)\} # match "${1}" (not unrelated '${0}')
71             |
72             \$ ([1-9]\d*) # match "$1" (not unrelated '$0')
73             )
74             )
75             /
76 840 100 66     3942 defined $1
77             ? $1 # if something was escaped drop the \\
78             : $matched[$2 || $3]; # else use braced or unbraced number
79             # ($2 will never contain '0')
80             /xge;
81 528         2155 return $string;
82             }
83              
84              
85             sub last_match_vars {
86 2     2   674 no strict 'refs'; ## no critic
  2         4  
  2         347  
87             return (
88             # fake $& with a substr to avoid performance penalty (see perlvar)
89             #(@_ ? substr($_[0], $-[0], $+[0] - $-[0]) : undef),
90             undef,
91             # $1, $2 ..
92 664 100   664 1 1742 map { defined($$_) ? $$_ : '' } ( 1 .. $#- )
  840         4158  
93             );
94             }
95              
96             # Return a sub that will get matched vars array passed to it
97              
98             sub _replacement_sub {
99 664     664   665 my ($rep) = @_;
100             # if $rep is not a sub, assume it's a string to be interpolated
101             ref $rep
102             ? $rep
103 664 100   528   2671 : sub { interpolate_match_vars($rep, @_); };
  528         882  
104             }
105              
106              
107             sub sub_copy {
108 196     196 1 3783 my ($string, $pattern, $replacement) = @_;
109 196         1312 $string =~ s/$pattern/
110 166         313 _replacement_sub($replacement)->(last_match_vars());/e;
111 196         1098 return $string;
112             }
113              
114              
115             sub sub_modify {
116 196     196 1 66938 my ( undef, $pattern, $replacement ) = @_;
117 196         1483 return $_[0] =~ s/$pattern/
118 166         299 _replacement_sub($replacement)->(last_match_vars());/e;
119             }
120              
121              
122             sub sub_context {
123             return defined wantarray
124 196 100   196 1 130380 ? sub_copy(@_)
125             : sub_modify(@_);
126             }
127              
128             1;
129              
130             __END__