line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# -*- mode: cperl; cperl-indent-level: 2 -*-
|
2
|
|
|
|
|
|
|
#
|
3
|
|
|
|
|
|
|
# This module is copyright 1998 Mark-Jason Dominus.
|
4
|
|
|
|
|
|
|
# (mjd-perl-interpolation@plover.com)
|
5
|
|
|
|
|
|
|
# and 2002-2009 Jenda Krynicky
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
package Interpolation;
|
8
|
4
|
|
|
4
|
|
89668
|
use vars '$VERSION';
|
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
244
|
|
9
|
|
|
|
|
|
|
$VERSION = '0.74';
|
10
|
4
|
|
|
4
|
|
21
|
use strict 'vars';
|
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
114
|
|
11
|
4
|
|
|
4
|
|
18
|
use warnings;
|
|
4
|
|
|
|
|
12
|
|
|
4
|
|
|
|
|
115
|
|
12
|
4
|
|
|
4
|
|
19
|
no warnings 'uninitialized'; # I don't want to be forced to use "if (defined $foo and $foo)
|
|
4
|
|
|
|
|
21
|
|
|
4
|
|
|
|
|
132
|
|
13
|
|
|
|
|
|
|
|
14
|
4
|
|
|
4
|
|
19
|
use Carp;
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
6996
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
%Interpolation::builtin = (
|
17
|
|
|
|
|
|
|
null => sub { $_[0] },
|
18
|
|
|
|
|
|
|
'eval' => sub { $_[0] },
|
19
|
|
|
|
|
|
|
identity => sub { $_[0] },
|
20
|
|
|
|
|
|
|
ucwords =>
|
21
|
|
|
|
|
|
|
sub {
|
22
|
|
|
|
|
|
|
my $s = lc shift;
|
23
|
|
|
|
|
|
|
$s =~ s/\b(\w)/\u$1/g;
|
24
|
|
|
|
|
|
|
$s
|
25
|
|
|
|
|
|
|
},
|
26
|
|
|
|
|
|
|
commify =>
|
27
|
|
|
|
|
|
|
sub {
|
28
|
|
|
|
|
|
|
local $_ = sprintf("%.2f", shift());
|
29
|
|
|
|
|
|
|
1 while s/^(-?\d+)(\d{3})/$1,$2/;
|
30
|
|
|
|
|
|
|
$_;
|
31
|
|
|
|
|
|
|
},
|
32
|
|
|
|
|
|
|
'reverse' =>
|
33
|
|
|
|
|
|
|
sub { reverse $_[0] },
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# Idea for funky sprintf trick thanks to Ken Fox
|
36
|
|
|
|
|
|
|
'sprintf' =>
|
37
|
|
|
|
|
|
|
sub {
|
38
|
|
|
|
|
|
|
my %fakehash;
|
39
|
|
|
|
|
|
|
my $format = shift;
|
40
|
|
|
|
|
|
|
tie %fakehash, Interpolation,
|
41
|
|
|
|
|
|
|
sub { sprintf($format, split /$;/o,$_[0])};
|
42
|
|
|
|
|
|
|
\%fakehash;
|
43
|
|
|
|
|
|
|
},
|
44
|
|
|
|
|
|
|
'sprintf1' =>
|
45
|
|
|
|
|
|
|
sub {
|
46
|
|
|
|
|
|
|
my ($fmt, @args) = split(/$;/o, shift());
|
47
|
|
|
|
|
|
|
sprintf($fmt, @args);
|
48
|
|
|
|
|
|
|
},
|
49
|
|
|
|
|
|
|
'sprintfx' => sub {sprintf shift(), @_},
|
50
|
|
|
|
|
|
|
'sqlescape' => sub {$_ = $_[0]; s/'/''/g; "'".$_},
|
51
|
|
|
|
|
|
|
'htmlescape' => sub {HTML::Entities::encode($_[0], '^\r\n\t !\#\$%\"\'-;=?-~')},
|
52
|
|
|
|
|
|
|
'tagescape' => sub {HTML::Entities::encode($_[0], '^\r\n\t !\#\$%\(-;=?-~')},
|
53
|
|
|
|
|
|
|
'jsescape' => sub {my $s = $_[0];$s =~ s/(['"])/\\$1/g;HTML::Entities::encode($s, '^\r\n\t !\#\$%\(-;=?-~')},
|
54
|
|
|
|
|
|
|
'round' => sub {
|
55
|
|
|
|
|
|
|
my ($number, $scale);
|
56
|
|
|
|
|
|
|
if (defined $_[1]) {
|
57
|
|
|
|
|
|
|
($number, $scale) = @_;
|
58
|
|
|
|
|
|
|
} else {
|
59
|
|
|
|
|
|
|
($number, $scale) = split /$;/o, $_[0];
|
60
|
|
|
|
|
|
|
}
|
61
|
|
|
|
|
|
|
$scale = 1 unless $scale;
|
62
|
|
|
|
|
|
|
return POSIX::floor(($number / $scale) + 0.5) * $scale;
|
63
|
|
|
|
|
|
|
}
|
64
|
|
|
|
|
|
|
);
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
%Interpolation::needmodules = (
|
67
|
|
|
|
|
|
|
'htmlescape' => 'use HTML::Entities;',
|
68
|
|
|
|
|
|
|
'tagescape' => 'use HTML::Entities;',
|
69
|
|
|
|
|
|
|
'jsescape' => 'use HTML::Entities;',
|
70
|
|
|
|
|
|
|
'round' => 'use POSIX;',
|
71
|
|
|
|
|
|
|
);
|
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
my %is_scalar;
|
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub import {
|
76
|
27
|
|
|
27
|
|
217450
|
my $caller_pack = caller;
|
77
|
27
|
|
|
|
|
51
|
shift; # the "Interpolation"
|
78
|
|
|
|
|
|
|
# print STDERR "exporter args: (@_); caller pack: $caller_pack\n";
|
79
|
27
|
50
|
|
|
|
122
|
if (@_ % 2) {
|
80
|
0
|
|
|
|
|
0
|
croak "Argument list in `use Interpolation' must be list of pairs; aborting";
|
81
|
|
|
|
|
|
|
}
|
82
|
27
|
|
|
|
|
84
|
while (@_) {
|
83
|
23
|
|
|
|
|
47
|
my $hashname = shift;
|
84
|
23
|
|
|
|
|
41
|
my $function = shift;
|
85
|
23
|
|
|
|
|
29
|
my $type;
|
86
|
|
|
|
|
|
|
|
87
|
23
|
50
|
|
|
|
72
|
$function = $hashname unless $function;
|
88
|
|
|
|
|
|
|
|
89
|
23
|
100
|
|
|
|
113
|
if ($hashname =~ /^(.+):([\$\@\*\\]*->[\$\@])$/) {
|
90
|
|
|
|
|
|
|
# there is a type specification !
|
91
|
9
|
|
|
|
|
21
|
$type = $2;
|
92
|
9
|
|
|
|
|
16
|
$hashname = $1;
|
93
|
9
|
100
|
|
|
|
28
|
if ($type eq '->$') {
|
94
|
1
|
|
|
|
|
4
|
$is_scalar{$caller_pack . '::' . $hashname} = undef;
|
95
|
1
|
|
|
|
|
1
|
my $fakescalar;
|
96
|
1
|
|
|
|
|
4
|
tie $fakescalar, 'Interpolation::Scalar', $function;
|
97
|
1
|
|
|
|
|
2
|
*{$caller_pack . '::' . $hashname} = \$fakescalar;
|
|
1
|
|
|
|
|
4
|
|
98
|
1
|
|
|
|
|
4
|
next;
|
99
|
|
|
|
|
|
|
}
|
100
|
|
|
|
|
|
|
} else {
|
101
|
14
|
|
|
|
|
27
|
$type = '$->$';
|
102
|
|
|
|
|
|
|
}
|
103
|
|
|
|
|
|
|
|
104
|
22
|
|
|
|
|
32
|
my %fakehash;
|
105
|
22
|
|
|
|
|
240
|
tie %fakehash, 'Interpolation', $type, $function;
|
106
|
22
|
|
|
|
|
39
|
*{$caller_pack . '::' . $hashname} = \%fakehash;
|
|
22
|
|
|
|
|
143
|
|
107
|
|
|
|
|
|
|
}
|
108
|
27
|
|
|
|
|
4795
|
return 1
|
109
|
|
|
|
|
|
|
}
|
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
sub TIEHASH {
|
112
|
35
|
|
|
35
|
|
14923
|
shift;
|
113
|
35
|
|
|
|
|
70
|
my $function = pop();
|
114
|
35
|
|
|
|
|
67
|
my $type = shift();
|
115
|
35
|
|
|
|
|
52
|
my $my_pack;
|
116
|
|
|
|
|
|
|
|
117
|
35
|
100
|
100
|
|
|
408
|
if ($type eq '' or $type eq '$->$') {
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
118
|
22
|
|
|
|
|
46
|
$my_pack = 'Interpolation::base'
|
119
|
|
|
|
|
|
|
} elsif ($type eq '$->@') {
|
120
|
4
|
|
|
|
|
11
|
$my_pack = 'Interpolation::S2A';
|
121
|
|
|
|
|
|
|
} elsif ($type eq '@->$') {
|
122
|
2
|
|
|
|
|
5
|
$my_pack = 'Interpolation::A2S';
|
123
|
|
|
|
|
|
|
} elsif ($type eq '@->@') {
|
124
|
2
|
|
|
|
|
5
|
$my_pack = 'Interpolation::A2A';
|
125
|
|
|
|
|
|
|
} else {
|
126
|
5
|
|
|
|
|
13
|
$my_pack = 'Interpolation::general';
|
127
|
|
|
|
|
|
|
}
|
128
|
|
|
|
|
|
|
|
129
|
35
|
100
|
|
|
|
97
|
if (ref $function) {
|
130
|
20
|
50
|
|
|
|
78
|
croak "'use Interpolation' needs a reference to a subroutine or a builtin name!" unless ref $function eq 'CODE';
|
131
|
|
|
|
|
|
|
} else {
|
132
|
15
|
|
|
|
|
36
|
my $lc_function = lc $function;
|
133
|
15
|
|
|
|
|
15
|
my $lc_hashname;
|
134
|
15
|
50
|
|
|
|
44
|
if (exists $Interpolation::builtin{$lc_function}) {
|
135
|
15
|
100
|
|
|
|
51
|
if (exists $Interpolation::needmodules{$lc_function}) {
|
136
|
3
|
|
|
1
|
|
264
|
eval $Interpolation::needmodules{$lc_function};
|
|
1
|
|
|
1
|
|
10
|
|
|
1
|
|
|
1
|
|
1
|
|
|
1
|
|
|
|
|
63
|
|
|
1
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
42
|
|
|
1
|
|
|
|
|
7
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
36
|
|
137
|
3
|
50
|
|
|
|
9
|
croak $@ if $@;
|
138
|
3
|
|
|
|
|
8
|
delete $Interpolation::needmodules{$lc_function}
|
139
|
|
|
|
|
|
|
}
|
140
|
15
|
|
|
|
|
36
|
$function = $Interpolation::builtin{$lc_function};
|
141
|
|
|
|
|
|
|
} else {
|
142
|
0
|
|
|
|
|
0
|
croak "Unknown builtin $function!\n";
|
143
|
|
|
|
|
|
|
}
|
144
|
|
|
|
|
|
|
}
|
145
|
|
|
|
|
|
|
|
146
|
35
|
|
|
|
|
200
|
$my_pack->TIEHASH($function, $type);
|
147
|
|
|
|
|
|
|
}
|
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
sub unimport {
|
150
|
4
|
|
|
4
|
|
27
|
no warnings 'untie';
|
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
1919
|
|
151
|
1
|
|
|
1
|
|
3
|
my $caller_pack = caller;
|
152
|
1
|
|
|
|
|
2
|
my $my_pack = shift;
|
153
|
1
|
|
|
|
|
5
|
while (@_) {
|
154
|
1
|
|
|
|
|
3
|
my $varname = shift;
|
155
|
1
|
50
|
|
|
|
6
|
if (!exists $is_scalar{$caller_pack . '::' . $varname}) {
|
156
|
1
|
|
|
|
|
2
|
my $oldvar = *{$caller_pack . '::' . $varname}{HASH};
|
|
1
|
|
|
|
|
5
|
|
157
|
1
|
|
|
|
|
2
|
my %fakehash;
|
158
|
1
|
|
|
|
|
2
|
*{$caller_pack . '::' . $varname} = \%fakehash;
|
|
1
|
|
|
|
|
3
|
|
159
|
1
|
|
|
|
|
5
|
untie %$oldvar;
|
160
|
|
|
|
|
|
|
} else {
|
161
|
0
|
|
|
|
|
0
|
my $oldvar = *{$caller_pack . '::' . $varname}{SCALAR};
|
|
0
|
|
|
|
|
0
|
|
162
|
0
|
|
|
|
|
0
|
my $fakescalar;
|
163
|
0
|
|
|
|
|
0
|
*{$caller_pack . '::' . $varname} = \$fakescalar;
|
|
0
|
|
|
|
|
0
|
|
164
|
0
|
|
|
|
|
0
|
untie $$oldvar;
|
165
|
0
|
|
|
|
|
0
|
delete $is_scalar{$caller_pack . '::' . $varname};
|
166
|
|
|
|
|
|
|
}
|
167
|
|
|
|
|
|
|
}
|
168
|
|
|
|
|
|
|
}
|
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
package Interpolation::base;
|
171
|
4
|
|
|
4
|
|
24
|
use Carp;
|
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
2597
|
|
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
sub TIEHASH {
|
174
|
30
|
|
|
30
|
|
61
|
my $pack = shift;
|
175
|
30
|
|
|
|
|
54
|
my $cref = shift;
|
176
|
30
|
50
|
|
|
|
113
|
unless (ref $cref) { # Convert symbolic name to function ref
|
177
|
0
|
0
|
|
|
|
0
|
croak "Unknown builtin function `$cref'; aborting"
|
178
|
|
|
|
|
|
|
unless exists $Interpolation::builtin{lc $cref};
|
179
|
|
|
|
|
|
|
|
180
|
0
|
0
|
|
|
|
0
|
eval $Interpolation::needmodules{lc $cref}
|
181
|
|
|
|
|
|
|
if (exists $Interpolation::needmodules{lc $cref});
|
182
|
0
|
0
|
|
|
|
0
|
croak $@ if $@;
|
183
|
|
|
|
|
|
|
|
184
|
0
|
|
|
|
|
0
|
$cref = $Interpolation::builtin{lc $cref};
|
185
|
|
|
|
|
|
|
}
|
186
|
30
|
|
|
|
|
304
|
bless $cref => $pack; # That's it? Yup!
|
187
|
|
|
|
|
|
|
}
|
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
# This is where the magic is.
|
190
|
|
|
|
|
|
|
sub FETCH {
|
191
|
75
|
|
|
75
|
|
23126
|
&{$_[0]}($_[1]); # For pre-5.004_04 compatibility
|
|
75
|
|
|
|
|
378
|
|
192
|
|
|
|
|
|
|
#$_[0]->($_[1]); # Line of the day?
|
193
|
|
|
|
|
|
|
}
|
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
sub cut_it_out {
|
196
|
0
|
|
|
0
|
|
0
|
my $object = shift;
|
197
|
0
|
|
|
|
|
0
|
my $caller = (caller(1))[3];
|
198
|
0
|
|
|
|
|
0
|
croak "Not allowed to use $caller on an Interpolation variable; aborting";
|
199
|
|
|
|
|
|
|
}
|
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub STORE {
|
202
|
2
|
|
|
2
|
|
2521
|
&{$_[0]}($_[1], $_[2]); # For pre-5.004_04 compatibility
|
|
2
|
|
|
|
|
12
|
|
203
|
|
|
|
|
|
|
#$_[0]->($_[1]); # Line of the day?
|
204
|
|
|
|
|
|
|
}
|
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
*DELETE = \&cut_it_out;
|
207
|
|
|
|
|
|
|
*CLEAR = \&cut_it_out;
|
208
|
|
|
|
|
|
|
*EXISTS = \&cut_it_out;
|
209
|
|
|
|
|
|
|
*FIRSTKEY = \&cut_it_out;
|
210
|
|
|
|
|
|
|
*NEXTKEY = \&cut_it_out;
|
211
|
|
|
|
|
|
|
|
212
|
22
|
|
|
22
|
|
5569
|
sub UNTIE {};
|
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
package Interpolation::S2A;
|
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
@Interpolation::S2A::ISA = ('Interpolation::base');
|
217
|
|
|
|
|
|
|
sub FETCH {
|
218
|
12
|
|
|
12
|
|
17157
|
join $", &{$_[0]}($_[1]);
|
|
12
|
|
|
|
|
49
|
|
219
|
|
|
|
|
|
|
}
|
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
sub STORE {
|
222
|
2
|
50
|
|
2
|
|
2497
|
if (defined wantarray) {
|
223
|
2
|
|
|
|
|
9
|
join $", &{$_[0]}($_[1], $_[2]);
|
|
2
|
|
|
|
|
13
|
|
224
|
|
|
|
|
|
|
} else {
|
225
|
0
|
|
|
|
|
0
|
&{$_[0]}($_[1], $_[2]);
|
|
0
|
|
|
|
|
0
|
|
226
|
|
|
|
|
|
|
}
|
227
|
|
|
|
|
|
|
}
|
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
package Interpolation::A2A;
|
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
@Interpolation::A2A::ISA = ('Interpolation::base');
|
232
|
|
|
|
|
|
|
sub FETCH {
|
233
|
4
|
|
|
4
|
|
1027
|
join $", &{$_[0]}(split /$;/o,$_[1]);
|
|
4
|
|
|
|
|
21
|
|
234
|
|
|
|
|
|
|
}
|
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
package Interpolation::A2S;
|
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
@Interpolation::A2S::ISA = ('Interpolation::base');
|
239
|
|
|
|
|
|
|
sub FETCH {
|
240
|
6
|
|
|
6
|
|
3388
|
&{$_[0]}(split /$;/o,$_[1]);
|
|
6
|
|
|
|
|
32
|
|
241
|
|
|
|
|
|
|
}
|
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
package Interpolation::general;
|
244
|
4
|
|
|
4
|
|
29
|
use Carp;
|
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
4393
|
|
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
@Interpolation::general::ISA = ('Interpolation::base');
|
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
sub TIEHASH {
|
249
|
5
|
|
|
5
|
|
11
|
my $pack = shift;
|
250
|
5
|
|
|
|
|
12
|
my $cref = shift;
|
251
|
5
|
|
|
|
|
11
|
my $type = shift;
|
252
|
5
|
|
|
|
|
12
|
my $self = [];
|
253
|
5
|
50
|
|
|
|
22
|
unless (ref $cref) {
|
254
|
0
|
0
|
|
|
|
0
|
croak "Unknown builtin function `$cref'; aborting"
|
255
|
|
|
|
|
|
|
unless exists $Interpolation::builtin{$cref};
|
256
|
0
|
|
|
|
|
0
|
$cref = $Interpolation::builtin{$cref};
|
257
|
|
|
|
|
|
|
}
|
258
|
5
|
|
|
|
|
18
|
$self->[0] = reverse $type;
|
259
|
5
|
|
|
|
|
11
|
$self->[1] = $cref;
|
260
|
5
|
|
|
|
|
34
|
bless $self => $pack; # That's it? Yup!
|
261
|
|
|
|
|
|
|
}
|
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
sub FETCH {
|
264
|
19
|
|
|
19
|
|
11260
|
my $self = shift;
|
265
|
19
|
|
|
|
|
56
|
my $type = $self->[0];
|
266
|
19
|
|
|
|
|
44
|
my $par1type = chop ($type);
|
267
|
19
|
|
|
|
|
25
|
my (@param,$par1subtype);
|
268
|
19
|
100
|
66
|
|
|
126
|
if (($par1type eq '\\') and (($par1subtype = chop($type)) eq '@')) {
|
|
|
50
|
|
|
|
|
|
269
|
6
|
|
|
|
|
64
|
$param[0] = [split /$;/o, $_[0]]
|
270
|
|
|
|
|
|
|
} elsif ($par1type eq '@') {
|
271
|
0
|
|
|
|
|
0
|
@param = split /$;/o, $_[0]
|
272
|
|
|
|
|
|
|
} else {
|
273
|
13
|
|
|
|
|
40
|
$param[0] = $_[0]
|
274
|
|
|
|
|
|
|
}
|
275
|
19
|
50
|
66
|
|
|
204
|
if ($type =~ /^(.)>-$/ or ($type =~ /\*$/ and $_[0] eq $; and (undef @param or 1))) {
|
|
|
|
0
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
276
|
0
|
|
|
|
|
0
|
my $code = $self->[1];
|
277
|
0
|
0
|
|
|
|
0
|
if ($1 eq '$') {
|
278
|
0
|
|
|
|
|
0
|
&{$code}(@param);
|
|
0
|
|
|
|
|
0
|
|
279
|
|
|
|
|
|
|
} else {
|
280
|
0
|
|
|
|
|
0
|
join $", &{$code}(@param);
|
|
0
|
|
|
|
|
0
|
|
281
|
|
|
|
|
|
|
}
|
282
|
|
|
|
|
|
|
} else {
|
283
|
19
|
100
|
|
|
|
2383
|
if ($type =~ /\*$/) {$type .= $par1subtype.$par1type}; ##??>
|
|
14
|
|
|
|
|
36
|
|
284
|
19
|
|
|
|
|
27
|
my %fakehash;
|
285
|
19
|
|
|
|
|
129
|
tie %fakehash, Interpolation::internal, [$type, $self->[1], @param];
|
286
|
19
|
|
|
|
|
354
|
bless \%fakehash, Interpolation::internal;
|
287
|
|
|
|
|
|
|
}
|
288
|
|
|
|
|
|
|
}
|
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
package Interpolation::internal;
|
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
@Interpolation::internal::ISA = ('Interpolation::base');
|
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
sub TIEHASH {
|
295
|
47
|
|
|
47
|
|
80
|
my ($pack, $self) = @_;
|
296
|
47
|
|
|
|
|
237
|
bless $self => $pack; # That's it? Yup!
|
297
|
|
|
|
|
|
|
}
|
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
sub FETCH {
|
300
|
30
|
|
|
30
|
|
47
|
my $self = $_[0];
|
301
|
30
|
|
|
|
|
70
|
my $par1type = chop ($self->[0]);
|
302
|
30
|
|
|
|
|
35
|
my (@param,$par1subtype);
|
303
|
30
|
100
|
66
|
|
|
159
|
if ($par1type eq '\\' and (($par1subtype = chop($self->[0])) eq '@')) {
|
|
|
50
|
33
|
|
|
|
|
304
|
6
|
|
|
|
|
42
|
$param[0] = [split /$;/o, $_[1]]
|
305
|
|
|
|
|
|
|
} elsif ($par1type eq '@' and $self->[0] !~ /\*$/) {
|
306
|
0
|
|
|
|
|
0
|
@param = split /$;/o, $_[1]
|
307
|
|
|
|
|
|
|
} else {
|
308
|
24
|
|
|
|
|
60
|
$param[0] = $_[1]
|
309
|
|
|
|
|
|
|
}
|
310
|
30
|
|
|
|
|
65
|
push @$self, @param;
|
311
|
30
|
100
|
66
|
|
|
588
|
if ($self->[0] =~ /^(.)>-$/ or ($self->[0] =~ /\*$/ and $_[1] eq $; and pop @$self)) {
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
312
|
2
|
|
|
|
|
4
|
shift @$self;
|
313
|
2
|
|
|
|
|
6
|
my $code = shift @$self;
|
314
|
2
|
50
|
|
|
|
12
|
if ($1 eq '$') {
|
315
|
0
|
|
|
|
|
0
|
&{$code}(@$self);
|
|
0
|
|
|
|
|
0
|
|
316
|
|
|
|
|
|
|
} else {
|
317
|
2
|
|
|
|
|
4
|
join $", &{$code}(@$self);
|
|
2
|
|
|
|
|
9
|
|
318
|
|
|
|
|
|
|
}
|
319
|
|
|
|
|
|
|
} else {
|
320
|
28
|
|
|
|
|
38
|
my %fakehash;
|
321
|
28
|
50
|
|
|
|
104
|
if ($self->[0] =~ /\*$/) {$self->[0] .= $par1subtype.$par1type}; ##??>
|
|
28
|
|
|
|
|
68
|
|
322
|
28
|
|
|
|
|
84
|
tie %fakehash, Interpolation::internal, $self;
|
323
|
28
|
|
|
|
|
163
|
bless \%fakehash, Interpolation::internal;
|
324
|
|
|
|
|
|
|
}
|
325
|
|
|
|
|
|
|
}
|
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
use overload '""' => sub {
|
328
|
17
|
|
|
17
|
|
27
|
my $self = tied(%{$_[0]});
|
|
17
|
|
|
|
|
47
|
|
329
|
17
|
|
|
|
|
106
|
my ($type, $code, @param) = @$self;
|
330
|
17
|
50
|
|
|
|
76
|
if ($type =~ /^\$/) {
|
331
|
17
|
|
|
|
|
27
|
&{$code}(@param);
|
|
17
|
|
|
|
|
62
|
|
332
|
|
|
|
|
|
|
} else {
|
333
|
0
|
|
|
|
|
0
|
join $", &{$code}(@param);
|
|
0
|
|
|
|
|
0
|
|
334
|
|
|
|
|
|
|
}
|
335
|
4
|
|
|
4
|
|
6823
|
};
|
|
4
|
|
|
|
|
4044
|
|
|
4
|
|
|
|
|
38
|
|
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
package Interpolation::Scalar;
|
338
|
|
|
|
|
|
|
|
339
|
4
|
|
|
4
|
|
4203
|
use Tie::Scalar;
|
|
4
|
|
|
|
|
2310
|
|
|
4
|
|
|
|
|
110
|
|
340
|
4
|
|
|
4
|
|
24
|
use Carp;
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
1071
|
|
341
|
|
|
|
|
|
|
our @ISA=(Tie::Scalar);
|
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
sub TIESCALAR {
|
344
|
1
|
|
|
1
|
|
1
|
my $pack = shift;
|
345
|
1
|
|
|
|
|
2
|
my $cref = shift;
|
346
|
1
|
50
|
|
|
|
3
|
unless (ref $cref) { # symbolic names not supported
|
347
|
0
|
|
|
|
|
0
|
croak "Builtins not supported for type (void)->\$";
|
348
|
|
|
|
|
|
|
}
|
349
|
1
|
|
|
|
|
4
|
bless $cref => $pack; # That's it? Yup!
|
350
|
|
|
|
|
|
|
}
|
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
sub FETCH {
|
353
|
5
|
|
|
5
|
|
2033
|
&{$_[0]}(); # For pre-5.004_04 compatibility
|
|
5
|
|
|
|
|
22
|
|
354
|
|
|
|
|
|
|
#$_[0]->($_[1]); # Line of the day?
|
355
|
|
|
|
|
|
|
}
|
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
sub STORE {
|
358
|
1
|
|
|
1
|
|
419
|
&{$_[0]}($_[1]); # For pre-5.004_04 compatibility
|
|
1
|
|
|
|
|
4
|
|
359
|
|
|
|
|
|
|
#$_[0]->($_[1]); # Line of the day?
|
360
|
|
|
|
|
|
|
}
|
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
1;
|
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
=head1 NAME
|
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
Interpolation - Arbitrary string interpolation semantics (using tie())
|
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
Version 0.74
|
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
Originaly by Mark-Jason Dominus (mjd-perl-interpolation@plover.com)
|
372
|
|
|
|
|
|
|
Since version 0.66 maintained by Jenda@Krynicky.cz
|
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
use Interpolation name => \&function, ...;
|
377
|
|
|
|
|
|
|
print "la la la la $name{blah blah blah}";
|
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
# This is like doing:
|
380
|
|
|
|
|
|
|
$VAR = &function(blah blah blah);
|
381
|
|
|
|
|
|
|
print "la la la la $VAR";
|
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
Beginners always want to write this:
|
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
print "The sum of three and four is: 3+4";
|
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
And they want the C<3+4> part to be evaluated, so that it prints
|
390
|
|
|
|
|
|
|
this:
|
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
The sum of three and four is: 7
|
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
Of course, it's a double-quoted string, so it's not evaluated. The
|
395
|
|
|
|
|
|
|
only things that are evaluated in double-quoted strings are variable
|
396
|
|
|
|
|
|
|
references.
|
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
There are solutions to this, but most of them are ugly. This module
|
399
|
|
|
|
|
|
|
is less ugly. Well .... this module IS ugly, but only inside. Your code may end up being nice.
|
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
The module also lets you define arbitrary interpolation semantics.
|
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
For example, you can say
|
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
use Interpolation money => \&commify_with_dollar_sign,
|
406
|
|
|
|
|
|
|
E => 'eval',
|
407
|
|
|
|
|
|
|
placename => 'ucwords',
|
408
|
|
|
|
|
|
|
;
|
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
And then you can write these:
|
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
print "3 + 4 = $E{3+4}";
|
413
|
|
|
|
|
|
|
# Prints ``3 + 4 = 7''
|
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
$SALARY = 57500;
|
416
|
|
|
|
|
|
|
print "The salary is $money{$SALARY}";
|
417
|
|
|
|
|
|
|
# Prints ``The salary is $57,500.00''
|
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
$PLACE1 = 'SAN BERNADINO HIGH SCHOOL';
|
420
|
|
|
|
|
|
|
$PLACE2 = 'n.y. state';
|
421
|
|
|
|
|
|
|
print "$placename{$PLACE1} is not near $placename{$PLACE2}";
|
422
|
|
|
|
|
|
|
# Prints ``San Bernadino High School is not near N.Y. State";
|
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
=head1 DETAILS
|
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
The arguments to the C |
427
|
|
|
|
|
|
|
the pair is C<($n, $f)>, then C<$n> will be the name for the semantics
|
428
|
|
|
|
|
|
|
provided by C<$f>. C<$f> must either be a reference to a function
|
429
|
|
|
|
|
|
|
that you supply, or it can be the name of one of the built-in
|
430
|
|
|
|
|
|
|
formatting functions provided by this package. C will
|
431
|
|
|
|
|
|
|
take over the C<%n> hash or C<$n> scalar in your package, and tie it so that acessing
|
432
|
|
|
|
|
|
|
C<$n{X}> calls C and yields its return value.
|
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
If for some reason you want to, you can add new semantics at run time
|
435
|
|
|
|
|
|
|
by using
|
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
import Interpolation name => function, ...
|
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
You can remove them again with
|
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
unimport Interpolation 'name', ...
|
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
Interpolators created by the import() or use statements are always PACKAGE variables, not lexicals!
|
444
|
|
|
|
|
|
|
If you want a lexical interpolator you can create it like this:
|
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
my %name;
|
447
|
|
|
|
|
|
|
tie %name, 'Interpolation', sub { ...
|
448
|
|
|
|
|
|
|
or
|
449
|
|
|
|
|
|
|
my %name;
|
450
|
|
|
|
|
|
|
tie %name, 'Interpolation', '$$->$', sub { ...
|
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
=head2 Built-ins
|
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
C provides a few useful built-in formatting functions;
|
456
|
|
|
|
|
|
|
you can refer to these by name in the C |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
eval - Evaluate the argument
|
459
|
|
|
|
|
|
|
null - Same as eval
|
460
|
|
|
|
|
|
|
identity - Also the same as eval
|
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
ucwords - Capitalize Input String Like This
|
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
commify - 1428571 => 1,428,571.00
|
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
reverse - reverse string
|
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
sprintf - makes "$S{'%.2f %03d'}{37.5,42}" turn into "37.50 042"
|
469
|
|
|
|
|
|
|
use Interpolation S => 'sprintf';
|
470
|
|
|
|
|
|
|
print "$S{'%.2f %03d'}{37.5, 42}\n";
|
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
sprintf1 - makes "$S{'%.2f %03d', 37.5,42}" turn into "37.50 042".
|
473
|
|
|
|
|
|
|
use Interpolation S => 'sprintf1';
|
474
|
|
|
|
|
|
|
print "$S{'%.2f %03d', 37.5, 42}\n";
|
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
sprintfX - makes "$S{'%.2f %03d'}{37.5}{42}" turn into "37.50 042".
|
477
|
|
|
|
|
|
|
use Interpolation 'S:$$*->$' => 'sprintfX';
|
478
|
|
|
|
|
|
|
print "$S{'%.2f %03d'}{37.5}{42}\n";
|
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
sqlescape - escapes single quotes for use in SQL queries
|
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
round - rounds the number
|
483
|
|
|
|
|
|
|
use Interpolation round => 'round'; print "The sum is: $round{$sum, 0.01}\n";
|
484
|
|
|
|
|
|
|
use Interpolation 'round:$$->$' => 'round'; print "The sum is: $round{$sum}{0.01}\n";
|
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
htmlescape - escapes characters special to HTML
|
487
|
|
|
|
|
|
|
"$htmlescape{$text}
|
488
|
|
|
|
|
|
|
tagescape - escapes characters special to HTML plus double and single quotes
|
489
|
|
|
|
|
|
|
qq{}
|
490
|
|
|
|
|
|
|
jsescape - escapes the text to be used in JavaScript
|
491
|
|
|
|
|
|
|
qq{}
|
492
|
|
|
|
|
|
|
(the last three require module HTML::Entities)
|
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
=head1 ADVANCED
|
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
It is posible to pass multiple (or no) arguments to your function.
|
497
|
|
|
|
|
|
|
There are two alternate syntaxes:
|
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
$interpolator{param1,param2}
|
500
|
|
|
|
|
|
|
$interpolator{param1}{param2}
|
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
The first syntax will pass both arguments in $_[0] joined by $;, so you have to split them:
|
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
use Interpolation add => sub{@_ = split /$;/o, $_[0]; $_[0] + $_[1]};
|
505
|
|
|
|
|
|
|
print "3 + 4 = $add{3,4}\n";
|
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
The other syntax (used for example by builtin 'sprintf') requires quite some magic,
|
508
|
|
|
|
|
|
|
so you probably wouldn't want to be forced to write it yourself.
|
509
|
|
|
|
|
|
|
(See the source of this module if you want to know how strange is the code. )
|
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
The other problem is, that your interpolator might want to return an array.
|
512
|
|
|
|
|
|
|
In that case you would anticipate to get all the items joined by $",
|
513
|
|
|
|
|
|
|
but instead you would get only the last item. You have to join the list yourself:
|
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
use Interpolation foo => sub {join $", &bar($_[0])};
|
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
To make your life easier this module provides a way to specify the "type" of the interpolator
|
518
|
|
|
|
|
|
|
and then does the necessary splits, joins or magic itself.
|
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
The syntax is:
|
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
use Interpolation 'name:input->output' => sub { ...
|
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
where the input is a list of '$'s, '@'s and '\@'s and the output is either '$' or '@'.
|
525
|
|
|
|
|
|
|
The '$' means that the parameter/output should be left intact, while '@'
|
526
|
|
|
|
|
|
|
forces a split/join on the parameter/output. Each character in the input list
|
527
|
|
|
|
|
|
|
specifies the type of one brace in the call.
|
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
In addition you may add an asterisk
|
530
|
|
|
|
|
|
|
to the end of the input type specification. This will allow for an arbitrary long
|
531
|
|
|
|
|
|
|
list of parameters. Their type will be the last specified.
|
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
In previous version you had to "close" the interpolator call by $;.
|
534
|
|
|
|
|
|
|
That is you would write something like "xxx $foo{par1}{par2}...{parn}{$;} xxx".
|
535
|
|
|
|
|
|
|
While this is still suported it is NOT required anymore.
|
536
|
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
The default type is $->$.
|
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
Ex.:
|
540
|
|
|
|
|
|
|
'foo:$->$' - pass the argument to function directly and evaluate it in scalar context
|
541
|
|
|
|
|
|
|
$foo{param}
|
542
|
|
|
|
|
|
|
'foo:$->@' - pass the argument to function directly, evaluate it in list context and join
|
543
|
|
|
|
|
|
|
the result by $" (by default space)
|
544
|
|
|
|
|
|
|
$foo{param}
|
545
|
|
|
|
|
|
|
'foo:@->$' - split the first parameter by $; and pass the resulting list to the function,
|
546
|
|
|
|
|
|
|
evaluate in scalar context
|
547
|
|
|
|
|
|
|
$foo{param1,param2,...}
|
548
|
|
|
|
|
|
|
'foo:@->@' - split the first parameter by $; and pass the resulting list to the function,
|
549
|
|
|
|
|
|
|
evaluate in list context and join
|
550
|
|
|
|
|
|
|
$foo{param1,param2,...}
|
551
|
|
|
|
|
|
|
'foo:$$->$' - ask for two parameters enclosed in braces
|
552
|
|
|
|
|
|
|
$foo{param1}{param2}
|
553
|
|
|
|
|
|
|
'foo:$@->$' - ask for two parameters enclosed in braces and split the second one
|
554
|
|
|
|
|
|
|
the list you get from the split will be added to @_ flatlist
|
555
|
|
|
|
|
|
|
$foo{paramA}{paramB1,paramB2,...}
|
556
|
|
|
|
|
|
|
'foo:$\@->$' - ask for two parameters enclosed in braces and split the second one
|
557
|
|
|
|
|
|
|
the list you get from the split will be passed as a reference to an array
|
558
|
|
|
|
|
|
|
$foo{paramA}{paramB1,paramB2,...}
|
559
|
|
|
|
|
|
|
'foo:$*->$ - ask for arbitrary number of scalar parameters
|
560
|
|
|
|
|
|
|
$foo{par1}{par2}{par3}{$;}
|
561
|
|
|
|
|
|
|
'foo:->$ - no parameters. This creates a tied scalar.
|
562
|
|
|
|
|
|
|
$foo
|
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
'foo:@->$' => &bar IS EQUAL TO 'foo' => sub {&bar(split /$;/o, $_[0])}
|
566
|
|
|
|
|
|
|
'foo:$->@' => &bar IS EQUAL TO 'foo' => sub {join $", &bar($_[0])}
|
567
|
|
|
|
|
|
|
'foo:@->@' => &bar IS EQUAL TO 'foo' => sub {join $", &bar(split /$;/o, $_[0])}
|
568
|
|
|
|
|
|
|
'foo:\@->$' => &bar IS EQUAL TO 'foo' => sub {&bar([split /$;/o, $_[0] ])}
|
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
The builtin function sprintf could be implemented as:
|
571
|
|
|
|
|
|
|
'sprintf:$@->$' => sub {sprintf shift,@_}
|
572
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
Since version 0.69 it is possible to assign to interpolators of type '$->$', '$->@' and '->$'.
|
574
|
|
|
|
|
|
|
The assigned value will be passed to the function you specified as the last parameter:
|
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
use Interpolation 'count:->$' => sub {if (@_) {$count = $_[0]} else {$count++}};
|
577
|
|
|
|
|
|
|
# print "Current count is $count\n";
|
578
|
|
|
|
|
|
|
use Interpolation 'count:$->$' => sub {
|
579
|
|
|
|
|
|
|
if (@_ == 2) {
|
580
|
|
|
|
|
|
|
$count{$_[0]} = $_[1]
|
581
|
|
|
|
|
|
|
} else {
|
582
|
|
|
|
|
|
|
$count{$_[0]}++
|
583
|
|
|
|
|
|
|
}
|
584
|
|
|
|
|
|
|
};
|
585
|
|
|
|
|
|
|
# print "Current count of A is $count{A}\n";
|
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
=head1 Cool examples
|
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
=over 2
|
592
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
=item SQL
|
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
use Interpolation "'" => sub {$_ = $_[0]; s/'/''/g; "'".$_};
|
596
|
|
|
|
|
|
|
...
|
597
|
|
|
|
|
|
|
$db->Sql("SELECT * FROM People WHERE LastName = $'{$lastname}'");
|
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
When passing strings to SQL you have to escape the apostrophes
|
600
|
|
|
|
|
|
|
(and maybe some other characters) this crazy hack allows you do it quite easily.
|
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
Instead of "... = '$variable'" you write "... = $'{$variable}'" et voila ;-)
|
603
|
|
|
|
|
|
|
You may of course use this syntax for whatever string escaping you like.
|
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
=item IF
|
606
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
use Interpolation 'IF:$*->$' => sub {$_[0] ? $_[1] : $_[2]};
|
608
|
|
|
|
|
|
|
#or
|
609
|
|
|
|
|
|
|
use Interpolation '?:$*->$' => sub {$_[0] ? $_[1] : $_[2]};
|
610
|
|
|
|
|
|
|
#...
|
611
|
|
|
|
|
|
|
print <<"*END*"
|
612
|
|
|
|
|
|
|
Blah blah blah
|
613
|
|
|
|
|
|
|
There was $count $IF{$count > 1}{jobs}{job}.
|
614
|
|
|
|
|
|
|
There was $count $?{$count > 1}{jobs}{job}.
|
615
|
|
|
|
|
|
|
There was $count job$?{$count > 1}{s}.
|
616
|
|
|
|
|
|
|
*END*
|
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
=back
|
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
=head1 Warnings
|
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
It's easy to forget that the index to a C<$hash{...}> is an arbitrary
|
623
|
|
|
|
|
|
|
expression, unless it looks like an identifier. There are two gotchas here.
|
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
=over 4
|
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
=item Trap 1.
|
628
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
print "$X{localtime}";
|
630
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
Here the C formatter is used to format the literal string
|
632
|
|
|
|
|
|
|
C; the C built-in function is not invoked. If
|
633
|
|
|
|
|
|
|
you really want the current time, use one of these:
|
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
print "$X{+localtime}";
|
636
|
|
|
|
|
|
|
print "$X{localtime()}";
|
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
=item Trap 2.
|
639
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
print "$X{What ho?}";
|
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
This won't compile---you get `search pattern not terminated'. Why?
|
643
|
|
|
|
|
|
|
Because Perl sees the C> and interprets it as the beginning of a
|
644
|
|
|
|
|
|
|
pattern match operator, similar to C>. (Ah, you forgot that C>
|
645
|
|
|
|
|
|
|
could be a pattern match delimiter even without a leading C, didn't
|
646
|
|
|
|
|
|
|
you?) You really need
|
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
print "$X{'What ho?'}";
|
649
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
=back
|
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
The rule is simple: That thing in the braces that looks like a hash
|
653
|
|
|
|
|
|
|
key really is a hash key, and so you need to put it in quotes under
|
654
|
|
|
|
|
|
|
the same circumstances that you need to put any other hash key in
|
655
|
|
|
|
|
|
|
quotes. You probably wouldn't expect this to work either:
|
656
|
|
|
|
|
|
|
|
657
|
|
|
|
|
|
|
$V = $X{What ho?};
|
658
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
=head1 Author
|
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
=begin text
|
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
Originaly, Mark-Jason Dominus (C), Plover Systems co.
|
665
|
|
|
|
|
|
|
http://www.plover.com/~mjd/perl/Interpolation
|
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
Now maintained by, C .
|
668
|
|
|
|
|
|
|
http://Jenda.Krynicky.cz/#Interpolation
|
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
=end text
|
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
=begin man
|
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
Originaly, Mark-Jason Dominus (C), Plover Systems co.
|
675
|
|
|
|
|
|
|
http://www.plover.com/~mjd/perl/Interpolation
|
676
|
|
|
|
|
|
|
|
677
|
|
|
|
|
|
|
Now maintained by, C .
|
678
|
|
|
|
|
|
|
http://Jenda.Krynicky.cz/#Interpolation
|
679
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
=end man
|
681
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
=begin html
|
683
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
Originaly, Mark-Jason Dominus (mjd-perl-interpolation@plover.com), Plover Systems co.
|
685
|
|
|
|
|
|
|
http://www.plover.com/~mjd/perl/Interpolation
|
686
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
Now maintained by, Jenda Krynicky.
|
688
|
|
|
|
|
|
|
http://Jenda.Krynicky.cz/#Interpolation
|
689
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
=end html
|
691
|
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
=cut
|
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
|