1package Template::Alloy::VMethod; 2 3=head1 NAME 4 5Template::Alloy::VMethod - VMethod role. 6 7=cut 8 9use strict; 10use warnings; 11use Template::Alloy; 12use base qw(Exporter); 13our @EXPORT_OK = qw(define_vmethod 14 $ITEM_OPS $ITEM_METHODS 15 $SCALAR_OPS 16 $LIST_OPS $LIST_METHODS 17 $HASH_OPS 18 $FILTER_OPS 19 $VOBJS); 20 21sub new { die "This class is a role for use by packages such as Template::Alloy" } 22 23###----------------------------------------------------------------### 24 25our ($JSON, $JSONP); 26sub json { $JSON ||= do { require JSON; JSON->new->utf8->allow_nonref->allow_unknown->allow_blessed->convert_blessed->canonical } } 27sub jsonp { $JSONP ||= do { require JSON; JSON->new->utf8->allow_nonref->allow_unknown->allow_blessed->convert_blessed->canonical->pretty } } 28 29our $SCALAR_OPS = our $ITEM_OPS = { 30 '0' => sub { $_[0] }, 31 abs => sub { no warnings; abs shift }, 32 atan2 => sub { no warnings; atan2($_[0], $_[1]) }, 33 chunk => \&vmethod_chunk, 34 collapse => sub { local $_ = $_[0]; s/^\s+//; s/\s+$//; s/\s+/ /g; $_ }, 35 cos => sub { no warnings; cos $_[0] }, 36 defined => sub { defined $_[0] ? 1 : '' }, 37 dquote => sub { local $_ = $_[0]; return if ! $_; s/([\"\\])/\\$1/g; s/\n/\\n/g; $_ }, 38 exp => sub { no warnings; exp $_[0] }, 39 fmt => \&vmethod_fmt_scalar, 40 'format' => \&vmethod_format, 41 hash => sub { {value => $_[0]} }, 42 hex => sub { no warnings; hex $_[0] }, 43 html => sub { local $_ = $_[0]; return $_ if ! $_; s/&/&/g; s/</</g; s/>/>/g; s/\"/"/g; $_ }, 44 indent => \&vmethod_indent, 45 int => sub { no warnings; int $_[0] }, 46 item => sub { $_[0] }, 47 js => sub { local $_ = $_[0]; return if ! $_; s/\n/\\n/g; s/\r/\\r/g; s/(?<!\\)([\"\'])/\\$1/g; $_ }, 48 json => sub { return json()->encode($_[0]) if ! $_[1]; my $j = jsonp()->encode($_[0]); chomp $j; $j }, 49 lc => sub { lc $_[0] }, 50 lcfirst => sub { lcfirst $_[0] }, 51 length => sub { defined($_[0]) ? length($_[0]) : 0 }, 52 list => sub { [$_[0]] }, 53 log => sub { no warnings; log $_[0] }, 54 lower => sub { lc $_[0] }, 55 match => \&vmethod_match, 56 new => sub { defined $_[0] ? $_[0] : '' }, 57 none => sub { $_[0] }, 58 null => sub { '' }, 59 oct => sub { no warnings; oct $_[0] }, 60 print => sub { no warnings; "@_" }, 61 rand => sub { no warnings; rand shift }, 62 remove => sub { vmethod_replace(shift, shift, '', 1) }, 63 repeat => \&vmethod_repeat, 64 replace => \&vmethod_replace, 65 'return' => \&vmethod_return, 66 search => sub { my ($str, $pat) = @_; return $str if ! defined $str || ! defined $pat; return $str =~ /$pat/ }, 67 sin => sub { no warnings; sin $_[0] }, 68 size => sub { 1 }, 69 split => \&vmethod_split, 70 sprintf => sub { no warnings; my $pat = shift; sprintf($pat, @_) }, 71 sqrt => sub { no warnings; sqrt $_[0] }, 72 squote => sub { local $_ = $_[0]; return if ! $_; s/([\'\\])/\\$1/g; $_ }, 73 srand => sub { no warnings; srand $_[0]; '' }, 74 stderr => sub { print STDERR $_[0]; '' }, 75 substr => \&vmethod_substr, 76 trim => sub { local $_ = $_[0]; s/^\s+//; s/\s+$//; $_ }, 77 uc => sub { uc $_[0] }, 78 ucfirst => sub { ucfirst $_[0] }, 79 upper => sub { uc $_[0] }, 80 uri => \&vmethod_uri, 81 url => \&vmethod_url, 82 xml => sub { local $_ = $_[0]; s/&/&/g; s/</</g; s/>/>/g; s/\"/"/g; s/\'/'/g; $_ }, 83}; 84 85our $ITEM_METHODS = { 86 eval => \&Template::Alloy::item_method_eval, 87 evaltt => \&Template::Alloy::item_method_eval, 88 file => \&item_method_redirect, 89 redirect => \&item_method_redirect, 90 block_exists => sub { defined($_[1]) && UNIVERSAL::isa($_[0], 'HASH') && $_[0]->{'BLOCKS'} && exists($_[0]->{'BLOCKS'}->{$_[1]}) || 0 }, 91}; 92 93our $FILTER_OPS = {}; # generally - non-dynamic filters belong in scalar ops 94 95our $LIST_OPS = { 96 defined => sub { return 1 if @_ == 1; defined $_[0]->[ defined($_[1]) ? $_[1] : 0 ] }, 97 first => sub { my ($ref, $i) = @_; return $ref->[0] if ! $i; return [@{$ref}[0 .. $i - 1]]}, 98 fmt => \&vmethod_fmt_list, 99 grep => sub { no warnings; my ($ref, $pat) = @_; UNIVERSAL::isa($pat, 'CODE') ? [grep {$pat->($_)} @$ref] : [grep {/$pat/} @$ref] }, 100 hash => sub { no warnings; my $list = shift; return {@$list} if ! @_; my $i = shift || 0; return {map {$i++ => $_} @$list} }, 101 import => sub { my $ref = shift; push @$ref, grep {defined} map {ref eq 'ARRAY' ? @$_ : undef} @_; '' }, 102 item => sub { $_[0]->[ $_[1] || 0 ] }, 103 join => sub { my ($ref, $join) = @_; $join = ' ' if ! defined $join; no warnings; return join $join, @$ref }, 104 json => sub { return json()->encode($_[0]) if ! $_[1]; my $j = jsonp()->encode($_[0]); chomp $j; $j }, 105 last => sub { my ($ref, $i) = @_; return $ref->[-1] if ! $i; return [@{$ref}[-$i .. -1]]}, 106 list => sub { $_[0] }, 107 map => sub { no warnings; my ($ref, $code) = @_; UNIVERSAL::isa($code, 'CODE') ? [map {$code->($_)} @$ref] : [map {$code} @$ref] }, 108 max => sub { no warnings; $#{ $_[0] } }, 109 merge => sub { my $ref = shift; return [ @$ref, grep {defined} map {ref eq 'ARRAY' ? @$_ : undef} @_ ] }, 110 new => sub { no warnings; return [@_] }, 111 null => sub { '' }, 112 nsort => \&vmethod_nsort, 113 pick => \&vmethod_pick, 114 pop => sub { pop @{ $_[0] } }, 115 push => sub { my $ref = shift; push @$ref, @_; return '' }, 116 'return' => \&vmethod_return, 117 reverse => sub { [ reverse @{ $_[0] } ] }, 118 shift => sub { shift @{ $_[0] } }, 119 size => sub { no warnings; scalar @{ $_[0] } }, 120 slice => sub { my ($ref, $a, $b) = @_; $a ||= 0; $b = $#$ref if ! defined $b; return [@{$ref}[$a .. $b]] }, 121 sort => \&vmethod_sort, 122 splice => \&vmethod_splice, 123 unique => sub { my %u; return [ grep { ! $u{$_}++ } @{ $_[0] } ] }, 124 unshift => sub { my $ref = shift; unshift @$ref, @_; return '' }, 125}; 126 127our $LIST_METHODS = { 128}; 129 130our $HASH_OPS = { 131 defined => sub { return 1 if @_ == 1; defined $_[0]->{ defined($_[1]) ? $_[1] : '' } }, 132 delete => sub { my $h = shift; delete @{ $h }{map {defined($_) ? $_ : ''} @_}; '' }, 133 each => sub { [%{ $_[0] }] }, 134 exists => sub { exists $_[0]->{ defined($_[1]) ? $_[1] : '' } }, 135 fmt => \&vmethod_fmt_hash, 136 hash => sub { $_[0] }, 137 import => sub { my ($a, $b) = @_; @{$a}{keys %$b} = values %$b if ref($b) eq 'HASH'; '' }, 138 item => sub { my ($h, $k) = @_; $k = '' if ! defined $k; $Template::Alloy::QR_PRIVATE && $k =~ $Template::Alloy::QR_PRIVATE ? undef : $h->{$k} }, 139 items => sub { [ %{ $_[0] } ] }, 140 json => sub { return json()->encode($_[0]) if ! $_[1]; my $j = jsonp()->encode($_[0]); chomp $j; $j }, 141 keys => sub { [keys %{ $_[0] }] }, 142 list => \&vmethod_list_hash, 143 new => sub { no warnings; return (@_ == 1 && ref $_[-1] eq 'HASH') ? $_[-1] : {@_} }, 144 null => sub { '' }, 145 nsort => sub { my $ref = shift; [sort { $ref->{$a} <=> $ref->{$b}} keys %$ref] }, 146 pairs => sub { [map { {key => $_, value => $_[0]->{$_}} } sort keys %{ $_[0] } ] }, 147 'return' => \&vmethod_return, 148 size => sub { scalar keys %{ $_[0] } }, 149 sort => sub { my $ref = shift; [sort {lc $ref->{$a} cmp lc $ref->{$b}} keys %$ref] }, 150 values => sub { [values %{ $_[0] }] }, 151}; 152 153our $VOBJS = { 154 Text => $SCALAR_OPS, 155 List => $LIST_OPS, 156 Hash => $HASH_OPS, 157}; 158foreach (values %$VOBJS) { 159 $_->{'Text'} = $_->{'fmt'}; 160 $_->{'Hash'} = $_->{'hash'}; 161 $_->{'List'} = $_->{'list'}; 162} 163 164###----------------------------------------------------------------### 165### long virtual methods or filters 166### many of these vmethods have used code from Template/Stash.pm to 167### assure conformance with the TT spec. 168 169sub define_vmethod { 170 my ($self, $type, $name, $sub) = @_; 171 if ( $type =~ /scalar|item|text/i) { $SCALAR_OPS->{$name} = $sub } 172 elsif ($type =~ /array|list/i ) { $LIST_OPS->{ $name} = $sub } 173 elsif ($type =~ /hash/i ) { $HASH_OPS->{ $name} = $sub } 174 elsif ($type =~ /filter/i ) { $FILTER_OPS->{$name} = $sub } 175 else { die "Invalid type vmethod type $type" } 176 return 1; 177} 178 179sub vmethod_fmt_scalar { 180 my $str = shift; $str = '' if ! defined $str; 181 my $pat = shift; $pat = '%s' if ! defined $pat; 182 no warnings; 183 return @_ ? sprintf($pat, $_[0], $str) 184 : sprintf($pat, $str); 185} 186 187sub vmethod_fmt_list { 188 my $ref = shift || return ''; 189 my $pat = shift; $pat = '%s' if ! defined $pat; 190 my $sep = shift; $sep = ' ' if ! defined $sep; 191 no warnings; 192 return @_ ? join($sep, map {sprintf $pat, $_[0], $_} @$ref) 193 : join($sep, map {sprintf $pat, $_} @$ref); 194} 195 196sub vmethod_fmt_hash { 197 my $ref = shift || return ''; 198 my $pat = shift; $pat = "%s\t%s" if ! defined $pat; 199 my $sep = shift; $sep = "\n" if ! defined $sep; 200 no warnings; 201 return ! @_ ? join($sep, map {sprintf $pat, $_, $ref->{$_}} sort keys %$ref) 202 : @_ == 1 ? join($sep, map {sprintf $pat, $_[0], $_, $ref->{$_}} sort keys %$ref) # don't get to pick - it applies to the key 203 : join($sep, map {sprintf $pat, $_[0], $_, $_[1], $ref->{$_}} sort keys %$ref); 204} 205 206sub vmethod_chunk { 207 my $str = shift; 208 my $size = shift || 1; 209 my @list; 210 if ($size < 0) { # chunk from the opposite end 211 $str = reverse $str; 212 $size = -$size; 213 unshift(@list, scalar reverse $1) while $str =~ /( .{$size} | .+ )/xg; 214 } else { 215 push(@list, $1) while $str =~ /( .{$size} | .+ )/xg; 216 } 217 return \@list; 218} 219 220sub vmethod_indent { 221 my $str = shift; $str = '' if ! defined $str; 222 my $pre = shift; $pre = 4 if ! defined $pre; 223 $pre = ' ' x $pre if $pre =~ /^\d+$/; 224 $str =~ s/^/$pre/mg; 225 return $str; 226} 227 228sub vmethod_format { 229 my $str = shift; $str = '' if ! defined $str; 230 my $pat = shift; $pat = '%s' if ! defined $pat; 231 if (@_) { 232 return join "\n", map{ sprintf $pat, $_[0], $_ } split(/\n/, $str); 233 } else { 234 return join "\n", map{ sprintf $pat, $_ } split(/\n/, $str); 235 } 236} 237 238sub vmethod_list_hash { 239 my ($hash, $what) = @_; 240 $what = 'pairs' if ! $what || $what !~ /^(keys|values|each|pairs)$/; 241 return $HASH_OPS->{$what}->($hash); 242} 243 244 245sub vmethod_match { 246 my ($str, $pat, $global) = @_; 247 return [] if ! defined $str || ! defined $pat; 248 my @res = $global ? ($str =~ /$pat/g) : ($str =~ /$pat/); 249 return @res ? \@res : ''; 250} 251 252sub vmethod_nsort { 253 my ($list, $field) = @_; 254 return defined($field) 255 ? [map {$_->[0]} sort {$a->[1] <=> $b->[1]} map {[$_, (ref $_ eq 'HASH' ? $_->{$field} 256 : UNIVERSAL::can($_, $field) ? $_->$field() 257 : $_)]} @$list ] 258 : [sort {$a <=> $b} @$list]; 259} 260 261sub vmethod_pick { 262 my $ref = shift; 263 no warnings; 264 my $n = int(shift); 265 $n = 1 if $n < 1; 266 my @ind = map { $ref->[ rand @$ref ] } 1 .. $n; 267 return $n == 1 ? $ind[0] : \@ind; 268} 269 270sub vmethod_repeat { 271 my ($str, $n, $join) = @_; 272 return '' if ! defined $str || ! length $str; 273 $n = 1 if ! defined($n) || ! length $n; 274 $join = '' if ! defined $join; 275 return join $join, ($str) x $n; 276} 277 278### This method is a combination of my submissions along 279### with work from Andy Wardley, Sergey Martynoff, Nik Clayton, and Josh Rosenbaum 280sub vmethod_replace { 281 my ($text, $pattern, $replace, $global) = @_; 282 $text = '' unless defined $text; 283 $pattern = '' unless defined $pattern; 284 $replace = '' unless defined $replace; 285 $global = 1 unless defined $global; 286 my $expand = sub { 287 my ($chunk, $start, $end) = @_; 288 $chunk =~ s{ \\(\\|\$) | \$ (\d+) }{ 289 $1 ? $1 290 : ($2 > $#$start || $2 == 0) ? '' 291 : substr($text, $start->[$2], $end->[$2] - $start->[$2]); 292 }exg; 293 $chunk; 294 }; 295 if ($global) { 296 $text =~ s{$pattern}{ $expand->($replace, [@-], [@+]) }eg; 297 } else { 298 $text =~ s{$pattern}{ $expand->($replace, [@-], [@+]) }e; 299 } 300 return $text; 301} 302 303sub vmethod_return { 304 my $obj = shift; 305 Template::Alloy->throw('return', {return_val => $obj}); 306} 307 308sub vmethod_sort { 309 my ($list, $field) = @_; 310 if (! defined $field) { 311 return [map {$_->[0]} sort {$a->[1] cmp $b->[1]} map {[$_, lc $_]} @$list ]; # case insensitive 312 } elsif (UNIVERSAL::isa($field, 'CODE')) { 313 return [sort {int($field->($a, $b))} @$list]; 314 } else { 315 return [map {$_->[0]} sort {$a->[1] cmp $b->[1]} map {[$_, lc(ref $_ eq 'HASH' ? $_->{$field} 316 : UNIVERSAL::can($_, $field) ? $_->$field() 317 : $_)]} @$list ]; 318 } 319} 320 321sub vmethod_splice { 322 my ($ref, $i, $len, @replace) = @_; 323 @replace = @{ $replace[0] } if @replace == 1 && ref $replace[0] eq 'ARRAY'; 324 if (defined $len) { 325 return [splice @$ref, $i || 0, $len, @replace]; 326 } elsif (defined $i) { 327 return [splice @$ref, $i]; 328 } else { 329 return [splice @$ref]; 330 } 331} 332 333sub vmethod_split { 334 my ($str, $pat, $lim) = @_; 335 $str = '' if ! defined $str; 336 if (defined $lim) { return defined $pat ? [split $pat, $str, $lim] : [split ' ', $str, $lim] } 337 else { return defined $pat ? [split $pat, $str ] : [split ' ', $str ] } 338} 339 340sub vmethod_substr { 341 my ($str, $i, $len, $replace) = @_; 342 $i ||= 0; 343 return '' if ! defined $str; 344 return substr($str, $i) if ! defined $len; 345 return substr($str, $i, $len) if ! defined $replace; 346 substr($str, $i, $len, $replace); 347 return $str; 348} 349 350sub vmethod_uri { 351 my $str = shift; 352 return '' if ! defined $str; 353 utf8::upgrade($str) if defined &utf8::upgrade; 354 $str =~ s/([^A-Za-z0-9\-_.!~*\'()])/sprintf('%%%02X', ord($1))/eg; 355 return $str; 356} 357 358sub vmethod_url { 359 my $str = shift; 360 return '' if ! defined $str; 361 utf8::upgrade($str) if defined &utf8::upgrade; 362 $str =~ s/([^;\/?:@&=+\$,A-Za-z0-9\-_.!~*\'()])/sprintf('%%%02X', ord($1))/eg; 363 return $str; 364} 365 366sub item_method_redirect { 367 my ($t, $text, $file, $options) = @_; 368 my $path = $t->{'OUTPUT_PATH'} || $t->throw('redirect', 'OUTPUT_PATH is not set'); 369 $t->throw('redirect', 'Invalid filename - cannot include "/../"') 370 if $file =~ m{(^|/)\.\./}; 371 372 if (! -d $path) { 373 require File::Path; 374 File::Path::mkpath($path) || $t->throw('redirect', "Couldn't mkpath \"$path\": $!"); 375 } 376 open (my $fh, '>', "$path/$file") || $t->throw('redirect', "Couldn't open \"$file\": $!"); 377 if (my $bm = (! $options) ? 0 : ref($options) ? $options->{'binmode'} : $options) { 378 if (+$bm == 1) { binmode $fh } 379 else { binmode $fh, $bm} 380 } 381 print $fh $text; 382 return ''; 383} 384 385###----------------------------------------------------------------### 386 3871; 388 389__END__ 390 391=head1 DESCRIPTION 392 393The Template::Alloy::VMethod role provides all of the extra vmethods, 394filters, and virtual objects that add to the base feature set of 395Template::Alloy. Most of the vmethods listed here are similar to 396those provided by Template::Toolkit. We will try to keep 397Template::Alloy's in sync. Template::Alloy also provides several 398extra methods that are needed for HTML::Template::Expr support. 399 400=head1 ROLE METHODS 401 402=over 4 403 404=item define_vmethod 405 406Defines a vmethod. See L<Template::Alloy> for more details. 407 408=item C<vmethod_*> 409 410Methods by these names implement virtual methods that are more complex 411than oneliners. These methods are not exposed via the role. 412 413=item C<filter_*> 414 415Methods by these names implement filters that are more complex than 416one liners. These methods are not exposed via the role. 417 418=back 419 420=head1 VIRTUAL METHOD LIST 421 422The following is the list of builtin virtual methods and filters that 423can be called on each type of data. 424 425In Template::Alloy, the "|" operator can be used to call virtual 426methods just the same way that the "." operator can. The main 427difference between the two is that on access to hashrefs or objects, 428the "|" means to always call the virtual method or filter rather than 429looking in the hashref for a key by that name, or trying to call that 430method on the object. This is similar to how TT3 will function. 431 432Virtual methods are also made available via Virtual Objects which 433are discussed in a later section. 434 435=head2 SCALAR VIRTUAL METHODS AND FILTERS 436 437The following is the list of builtin virtual methods and filters that 438can be called on scalar data types. In Alloy and TT3, filters and 439virtual methods are more closely related than in TT2. In general 440anywhere a virtual method can be used a filter can be used also - and 441likewise all scalar virtual methods can be used as filters. 442 443In addition to the filters listed below, Alloy will automatically load 444Template::Filters and use them if Template::Toolkit is installed. 445 446In addition to the scalar virtual methods, any scalar will be 447automatically converted to a single item list if a list virtual method 448is called on it. 449 450Scalar virtual methods are also available through the "Text" virtual 451object (except for true filters such as eval and redirect). 452 453All scalar virtual methods are available as top level functions as well. 454This is not true of TT2. In Template::Alloy the following are equivalent: 455 456 [% "abc".length %] 457 [% length("abc") %] 458 459You may set VMETHOD_FUNCTIONS to 0 to disable this behavior. 460 461=over 4 462 463=item '0' 464 465 [% item = 'foo' %][% item.0 %] Returns foo. 466 467Allows for scalars to mask as arrays (scalars already will, but this 468allows for more direct access). 469 470Not available in TT. 471 472=item abs 473 474 [% -1.abs %] Returns the absolute value 475 476=item atan2 477 478 [% pi = 4 * 1.atan2(1) %] 479 480Returns the arctangent. The item itself represents Y, the passed argument represents X. 481 482Not available in TT - available in HTML::Template::Expr. 483 484=item chunk 485 486 [% item.chunk(60).join("\n") %] Split string up into a list of chunks of text 60 chars wide. 487 488=item collapse 489 490 [% item.collapse %] Strip leading and trailing whitespace and collapse all other space to one space. 491 492=item cos 493 494 [% item.cos %] Returns the cosine of the item. 495 496Not available in TT - available in HTML::Template::Expr. 497 498=item defined 499 500 [% item.defined %] Always true - because the undef sub translates all undefs to ''. 501 502=item eval 503 504 [% item.eval %] 505 506Process the string as though it was a template. This will start the 507parsing engine and will use the same configuration as the current 508process. Alloy is several times faster at doing this than TT is and 509is considered acceptable. 510 511This is a filter and is not available via the Text virtual object. 512 513Template::Alloy has attempted to make the compile process painless and 514fast. By default an MD5 sum of evaled is taken and used to cache the 515AST. This behavior can be disabled using the CACHE_STR_REFS 516configuration item. 517 518Template::Alloy also allows for named parameters to be passed to the 519eval filter. 520 521 [% '[% 1 + 2 %]'.eval %] 522 523 [% '${ 1 + 2 }'.eval(interpolate => 1) %] 524 525 [% "#get( 1 + 2)"|eval(syntax => 'velocity') %] 526 527 [% '<TMPL_VAR EXPR="1 + 2">'.eval(syntax => 'hte') %] 528 529 [% '<TMPL_VAR EXPR="1 + 2">'.eval(syntax => 'hte') %] 530 531=item evaltt 532 533 Same as the eval filter. 534 535=item exp 536 537 [% 1.exp %] Something like 2.71828182845905 538 539Returns "e" to the power of the item. 540 541=item file 542 543 Same as the redirect filter. 544 545=item fmt 546 547 [% item.fmt('%d') %] 548 [% item.fmt('%6s') %] 549 [% item.fmt('%*s', 6) %] 550 551Similar to format. Returns a string formatted with the passed 552pattern. Default pattern is %s. Opposite from of the sprintf 553vmethod. 554 555=item format 556 557 [% item.format('%d') %] 558 [% item.format('%6s') %] 559 [% item.format('%*s', 6) %] 560 561Print the string out in the specified format. It is similar to the 562"fmt" virtual method, except that the item is split on newline and 563each line is processed separately. 564 565=item hash 566 567 [% item.hash %] Returns a one item hash with a key of "value" and a value of the item. 568 569 570=item hex 571 572 [% "FF".hex %] 573 574Returns the decimal value of the passed hex numbers. Note that you 575may also just use [% 0xFF %]. 576 577Not available in TT - available in HTML::Template::Expr. 578 579=item html 580 581 [% item.html %] Performs a very basic html encoding (swaps out &, <, > and " with the corresponding html entities) 582 Previously it also encoded the ' but this behavior did not match TT2's behavior. Use .xml to obtain that behavior. 583 584=item indent 585 586 [% item.indent(3) %] Indent by that number of spaces if an integer is passed (default is 4). 587 588 [% item.indent("Foo: ") %] Add the string "Foo: " to the beginning of every line. 589 590=item int 591 592 [% item.int %] Return the integer portion of the value (0 if none). 593 594=item json 595 596 [% item.json %] Returns a JSON encoded representation. 597 [% item.json(1) %] Returns a pretty JSON encoded representation. 598 599=item lc 600 601Same as the lower vmethod. Returns the lowercased version of the item. 602 603=item lcfirst 604 605 [% item.lcfirst %] Lowercase the leading letter. 606 607=item length 608 609 [% item.length %] Return the length of the string. 610 611=item list 612 613 [% item.list %] Returns a list (arrayref) with a single value of the item. 614 615=item log 616 617 [% 8.exp.log %] Equal to 8. 618 619Returns the natural log base "e" of the item. 620 621Not available in TT - available in HTML::Template::Expr. 622 623=item lower 624 625 [% item.lower %] Return the string lowercased. 626 627=item match 628 629 [% item.match("(\w+) (\w+)") %] Return a list of items matching the pattern. 630 631 [% item.match("(\w+) (\w+)", 1) %] Same as before - but match globally. 632 633In Template::Alloy and TT3 you can use regular expressions notation as well. 634 635 [% item.match( /(\w+) (\w+)/ ) %] Same as before. 636 637 [% item.match( m{(\w+) (\w+)} ) %] Same as before. 638 639Note that you can't use the 'g' regex modifier - you must pass the second 640argument to turn on global match. 641 642=item none 643 644Returns the item without modification. This was added as a compliment case 645when the AUTO_FILTER configuration is specified. Note that it must be 646called as a filter to bypass the application of the AUTO_FILTER. 647 648 [% item | none %] Returns the item without modification. 649 650=item null 651 652 [% item.null %] Return nothing. 653 654If the item contains a coderef it will still be executed, but the result would 655be ignored. 656 657=item oct 658 659 [% "377".oct %] 660 661Returns the decimal value of the octal string. On recent versions of perl you 662may also pass numbers starting with 0x which will be interpreted as hexadecimal, 663and starting with 0b which will be interpreted as binary. 664 665Not available in TT - available in HTML::Template::Expr. 666 667=item rand 668 669 [% item = 10; item.rand %] Returns a number greater or equal to 0 but less than 10. 670 [% 1.rand %] 671 672Note: This filter is not available as of TT2.15. 673 674=item remove 675 676 [% item.remove("\s+") %] Same as replace - but is global and replaces with nothing. 677 678=item redirect 679 680 [% item.redirect("output_file.html") %] 681 682Writes the contents out to the specified file. The filename must be 683relative to the OUTPUT_PATH configuration variable and the OUTPUT_PATH 684variable must be set. 685 686This is a filter and is not available via the Text virtual object. 687 688=item repeat 689 690 [% item.repeat(3) %] Repeat the item 3 times 691 692 [% item.repeat(3, ' | ') %] Repeat the item 3 times separated with ' | ' 693 694=item replace 695 696 [% item.replace("\s+", " ") %] Globally replace all space with 697 698 [% item.replace("foo", "bar", 0) %] Replace only the first instance of foo with bar. 699 700 [% item.replace("(\w+)", "($1)") %] Surround all words with parenthesis. 701 702In Template::Alloy and TT3 you may also use normal regular expression notation. 703 704 [% item.replace(/(\w+)/, "($1)") %] Same as before. 705 706Note that you can't use the 'g' regex modifier - global match is on by default. 707You must pass the third argument of false to turn off global match. 708 709=item return 710 711Returns the item from the inner most block, macro, or file. Similar to the 712RETURN directive. 713 714 [% item.return %] 715 [% RETURN item %] 716 717=item search 718 719 [% item.search("(\w+)") %] Tests if the given pattern is in the string. 720 721In Template::Alloy and TT3 you may also use normal regular expression notation. 722 723 [% item.search(/(\w+)/) %] Same as before. 724 725=item sin 726 727 [% item.sin %] Returns the sine of the item. 728 729=item size 730 731 [% item.size %] Always returns 1. 732 733=item split 734 735 [% item.split %] Returns an arrayref from the item split on " " 736 737 [% item.split("\s+") %] Returns an arrayref from the item split on /\s+/ 738 739 [% item.split("\s+", 3) %] Returns an arrayref from the item split on /\s+/ splitting until 3 elements are found. 740 741In Template::Alloy and TT3 you may also use normal regular expression notation. 742 743 [% item.split( /\s+/, 3 ) %] Same as before. 744 745=item sprintf 746 747 [% item = "%d %d" %] 748 [% item.sprintf(7, 8) %] 749 750Uses the pattern stored in self, and passes it to sprintf with the passed arguments. 751Opposite from the fmt vmethod. 752 753=item sqrt 754 755 [% item.sqrt %] 756 757Returns the square root of the number. 758 759=item srand 760 761Calls the perl srand function to set the internal random seed. This 762will affect future calls to the rand vmethod. 763 764=item stderr 765 766 [% item.stderr %] Print the item to the current STDERR handle. 767 768=item substr 769 770 [% item.substr(i) %] Returns a substring of item starting at i and going to the end of the string. 771 772 [% item.substr(i, n) %] Returns a substring of item starting at i and going n characters. 773 774=item trim 775 776 [% item.trim %] Strips leading and trailing whitespace. 777 778=item uc 779 780Same as the upper command. Returns uppercased string. 781 782=item ucfirst 783 784 [% item.ucfirst %] Uppercase the leading letter. 785 786=item upper 787 788 [% item.upper %] Return the string uppercased. 789 790=item uri 791 792 [% item.uri %] Perform a very basic URI encoding. 793 794=item url 795 796 [% item.url %] Perform a URI encoding - but some characters such 797 as : and / are left intact. 798 799=item xml 800 801 [% item.xml %] Performs a very basic xml encoding (swaps out &, <, >, ' and " with the corresponding xml entities) 802 803=back 804 805=head2 LIST VIRTUAL METHODS 806 807The following methods can be called on an arrayref type data 808structures (scalar types will automatically promote to a single 809element list and call these methods if needed): 810 811Additionally, list virtual methods can be accessed via the List 812Virtual Object. 813 814=over 4 815 816=item fmt 817 818 [% mylist.fmt('%s', ', ') %] 819 [% mylist.fmt('%6s', ', ') %] 820 [% mylist.fmt('%*s', ', ', 6) %] 821 822Passed a pattern and an string to join on. Returns a string of the 823values of the list formatted with the passed pattern and joined with 824the passed string. Default pattern is %s and the default join string 825is a space. 826 827=item first 828 829 [% mylist.first(3) %] Returns a list of the first 3 items in the list. 830 831=item grep 832 833 [% mylist.grep("^\w+\.\w+$") %] Returns a list of all items matching the pattern. 834 835In Template::Alloy and TT3 you may also use normal regular expression notation. 836 837 [% mylist.grep(/^\w+\.\w+$/) %] Same as before. 838 839 [% mylist.grep(->(a){ a.foo.bar } 840 841=item hash 842 843 [% mylist.hash %] Returns a hashref with the array indexes as keys and the values as values. 844 845=item join 846 847 [% mylist.join %] Joins on space. 848 [% mylist.join(", ") Joins on the passed argument. 849 850=item json 851 852 [% mylist.json %] Returns a JSON encoded representation. 853 [% mylist.json(1) %] Returns a pretty JSON encoded representation. 854 855=item last 856 857 [% mylist.last(3) %] Returns a list of the last 3 items in the list. 858 859=item list 860 861 [% mylist.list %] Returns a reference to the list. 862 863=item map (Not in TT2) 864 865 [% mylist.map(->{ this.upper }) %] Returns a list with the macro played on each item. 866 [% mylist.map(->(a){ a.upper }) %] Same thing 867 868The RETURN directive or return list, item, and hash vmethods allow for 869returning more interesting items. 870 871 [% [1..3].map(->(a){ [1..a].return }) %] 872 873=item max 874 875 [% mylist.max %] Returns the last item in the array. 876 877=item merge 878 879 [% mylist.merge(list2) %] Returns a new list with all defined items from list2 added. 880 881=item nsort 882 883 [% mylist.nsort %] Returns the numerically sorted items of the list. If the items are 884 hashrefs, a key containing the field to sort on can be passed. 885 886=item pop 887 888 [% mylist.pop %] Removes and returns the last element from the arrayref (the stash is modified). 889 890=item push 891 892 [% mylist.push(23) %] Adds an element to the end of the arrayref (the stash is modified). 893 894=item pick 895 896 [% mylist.pick %] Returns a random item from the list. 897 [% ['a' .. 'z'].pick %] 898 899An additional numeric argument is how many items to return. 900 901 [% ['a' .. 'z'].pick(8).join('') %] 902 903Note: This filter is not available as of TT2.15. 904 905=item return 906 907Returns the list from the inner most block, macro, or file. Similar to the 908RETURN directive. 909 910 [% mylist.return %] 911 [% RETURN mylist %] 912 913=item reverse 914 915 [% mylist.reverse %] Returns the list in reverse order. 916 917=item shift 918 919 [% mylist.shift %] Removes and returns the first element of the arrayref (the stash is modified). 920 921=item size 922 923 [% mylist.size %] Returns the number of elements in the array. 924 925=item slice 926 927 [% mylist.slice(i, n) %] Returns a list from the arrayref beginning at index i and continuing for n items. 928 929=item sort 930 931 [% mylist.sort %] Returns the alphabetically sorted items of the list. If the items are 932 hashrefs, a key containing the field to sort on can be passed. 933 934=item splice 935 936 [% mylist.splice(i, n) %] Removes items from array beginning at i and continuing for n items. 937 938 [% mylist.splice(i, n, list2) %] Same as before, but replaces removed items with the items 939 from list2. 940 941=item unique 942 943 [% mylist.unique %] Return a list of the unique items in the array. 944 945=item unshift 946 947 [% mylist.unshift(23) %] Adds an item to the beginning of the arrayref. 948 949=back 950 951=head2 HASH VIRTUAL METHODS 952 953The following methods can be called on hash type data structures: 954 955Additionally, list virtual methods can be accessed via the Hash 956Virtual Object. 957 958=over 4 959 960=item fmt 961 962 [% myhash.fmt('%s => %s', "\n") %] 963 [% myhash.fmt('%4s => %5s', "\n") %] 964 [% myhash.fmt('%*s => %*s', "\n", 4, 5) %] 965 966Passed a pattern and an string to join on. Returns a string of the 967key/value pairs of the hash formatted with the passed pattern and 968joined with the passed string. Default pattern is "%s\t%s" and the 969default join string is a newline. 970 971=item defined 972 973 [% myhash.defined('a') %] Checks if a is defined in the hash. 974 975=item delete 976 977 [% myhash.delete('a') %] Deletes the item from the hash. 978 979Unlink Perl the value is not returned. Multiple values may be passed 980and represent the keys to be deleted. 981 982=item each 983 984 [% myhash.each.join(", ") %] Turns the contents of the hash into a list - subject 985 to change as TT is changing the operations of each and list. 986 987=item exists 988 989 [% myhash.exists('a') %] Checks if a is in the hash. 990 991=item hash 992 993 [% myhash.hash %] Returns a reference to the hash. 994 995=item import 996 997 [% myhash.import(hash2) %] Overlays the keys of hash2 over the keys of myhash. 998 999=item item 1000 1001 [% myhash.item(key) %] Returns the hashes value for that key. 1002 1003=item items 1004 1005 [% myhash.items %] Returns a list of the key and values (flattened hash) 1006 1007=item json 1008 1009 [% myhash.json %] Returns a JSON encoded representation. 1010 [% myhash.json(1) %] Returns a pretty JSON encoded representation. 1011 1012=item keys 1013 1014 [% myhash.keys.join(', ') %] Returns an arrayref of the keys of the hash. 1015 1016=item list 1017 1018 [% myhash.list %] Returns an arrayref with the hash as a single value (subject to change). 1019 1020=item pairs 1021 1022 [% myhash.pairs %] Returns an arrayref of hashrefs where each hash contains {key => $key, value => $value} 1023 for each value of the hash. 1024 1025=item nsort 1026 1027 [% myhash.nsort.join(", ") %] Returns a list of keys numerically sorted by the values. 1028 1029=item return 1030 1031Returns the hash from the inner most block, macro, or file. Similar to the 1032RETURN directive. 1033 1034 [% myhash.return %] 1035 [% RETURN myhash %] 1036 1037=item size 1038 1039 [% myhash.size %] Returns the number of key/value pairs in the hash. 1040 1041=item sort 1042 1043 [% myhash.sort.join(", ") Returns a list of keys alphabetically sorted by the values. 1044 1045=item values 1046 1047 [% myhash.values.join(', ') %] Returns an arrayref of the values of the hash. 1048 1049=back 1050 1051=head1 VIRTUAL OBJECTS 1052 1053TT3 has a concept of Text, List, and Hash virtual objects which 1054provide direct access to the scalar, list, and hash virtual methods. 1055In the TT3 engine this will allow for more concise generated code. 1056Because Alloy does not generated perl code to be executed later, Alloy 1057provides for these virtual objects but does so as more of a namespace 1058(using the methods does not provide a speed optimization in your 1059template - just may help clarify things). 1060 1061 [% a = "foo"; a.length %] => 3 1062 1063 [% a = "foo"; Text.length(a) %] => 3 1064 1065 [% a = Text.new("foo"); a.length %] => 3 1066 1067 1068 [% a = [1 .. 30]; a.size %] => 30 1069 1070 [% a = [1 .. 30]; List.size(a) %] => 30 1071 1072 [% a = List.new(1 .. 30); a.size %] => 30 1073 1074 1075 [% a = {a => 1, b => 2}; a.size %] => 2 1076 1077 [% a = {a => 1, b => 2}; Hash.size(a) %] => 2 1078 1079 [% a = Hash.new({a => 1, b => 2}); a.size %] => 2 1080 1081 [% a = Hash.new(a => 1, b => 2); a.size %] => 2 1082 1083 [% a = Hash.new(a = 1, b = 2); a.size %] => 2 1084 1085 [% a = Hash.new('a', 1, 'b', 2); a.size %] => 2 1086 1087One limitation is that if you pass a key named "Text", 1088"List", or "Hash" in your variable stash - the corresponding 1089virtual object will be hidden. 1090 1091Additionally, you can use all of the Virtual object methods with 1092the pipe operator. 1093 1094 [% {a => 1, b => 2} 1095 | Hash.keys 1096 | List.join(", ") %] => a, b 1097 1098Again, there aren't any speed optimizations to using the virtual 1099objects in Alloy, but it can help clarify the intent in some cases. 1100 1101Note: these aren't really objects. All of the "virtual objects" are 1102references to the $SCALAR_OPS, $LIST_OPS, and $HASH_OPS hashes 1103found in the $VOBJS hash of Template::Alloy. 1104 1105=head1 AUTHOR 1106 1107Paul Seamons <paul@seamons.com> 1108 1109=head1 LICENSE 1110 1111This module may be distributed under the same terms as Perl itself. 1112 1113=cut 1114