I noticed, that the Template::Stash::Context module as distributed
with Template Toolkit 2.07 don't implements all new virtual variable
methods (like 'match') of the regular Stash module.
To make the new methods also available with Template::Stash::Context,
I tried to merge the differences related to the new methods between
Template::Stash and Template::Stash::Context into
Template::Stash::Context, but I'm not sure if I have covered all
details correct.
Attached is my patch to Template::Stash::Context for review, and I
welcome all comments and corrections.
--
Jens Kl�cker, ets GmbH
Perfection is achieved when there is nothing left to remove, not
when there is nothing left to add.
*** Context.pm.orig Wed Apr 17 16:18:00 2002
--- Context.pm Fri Jun 21 14:08:57 2002
***************
*** 94,97 ****
--- 94,98 ----
'inc' => sub { local $^W = 0; my $item = shift; ++$item },
'dec' => sub { local $^W = 0; my $item = shift; --$item },
+ # import => \&hash_import,
defined $ROOT_OPS ? %$ROOT_OPS : (),
};
***************
*** 100,115 ****
'item' => sub { $_[0] },
'list' => sub { [ $_[0] ] },
! 'hash' => sub { { 0 => $_[0] } },
'length' => sub { length $_[0] },
'defined' => sub { return 1 },
'array' => sub { return [$_[0]] },
'repeat' => sub {
my ($str, $count) = @_;
! $str = '' unless defined $str; $count ||= 1;
return $str x $count;
},
'search' => sub {
my ($str, $pattern) = @_;
- return $str unless defined $str and $pattern;
return $str unless defined $str and defined $pattern;
return $str =~ /$pattern/;
--- 101,117 ----
'item' => sub { $_[0] },
'list' => sub { [ $_[0] ] },
! 'hash' => sub { { value => $_[0] } },
'length' => sub { length $_[0] },
+ 'size' => sub { return 1 },
'defined' => sub { return 1 },
'array' => sub { return [$_[0]] },
'repeat' => sub {
my ($str, $count) = @_;
! $str = '' unless defined $str;
! $count ||= 1;
return $str x $count;
},
'search' => sub {
my ($str, $pattern) = @_;
return $str unless defined $str and defined $pattern;
return $str =~ /$pattern/;
***************
*** 124,127 ****
--- 126,135 ----
return $str;
},
+ 'match' => sub {
+ my ($str, $search) = @_;
+ return $str unless defined $str and defined $search;
+ my @matches = ($str =~ /$search/);
+ return @matches ? \@matches : '';
+ },
'split' => sub {
my ($str, $split, @args) = @_;
***************
*** 139,142 ****
--- 147,151 ----
},
'hash' => sub { $_[0] },
+ 'size' => sub { scalar keys %{$_[0]} },
'keys' => sub { [ keys %{ $_[0] } ] },
'values' => sub { [ values %{ $_[0] } ] },
***************
*** 149,157 ****
keys %$hash ];
},
! 'import' => sub { my ($hash, $imp) = @_;
! $imp = {} unless ref $imp eq 'HASH';
! @$hash{ keys %$imp } = values %$imp;
! return '';
! },
'sort' => sub {
my ($hash) = @_;
--- 158,164 ----
keys %$hash ];
},
! 'exists' => sub { exists $_[0]->{ $_[1] } },
! 'defined' => sub { defined $_[0]->{ $_[1] } },
! 'import' => \&hash_import,
'sort' => sub {
my ($hash) = @_;
***************
*** 180,187 ****
'reverse' => sub { my $list = shift; [ reverse @$list ] },
'array' => sub { return $_[0] },
'join' => sub {
! my ($list, $joint) = @_;
! join(defined $joint ? $joint : ' ',
! map { defined $_ ? $_ : '' } @$list)
},
'sort' => sub {
--- 187,199 ----
'reverse' => sub { my $list = shift; [ reverse @$list ] },
'array' => sub { return $_[0] },
+ 'grep' => sub {
+ my ($list, $pattern) = @_;
+ $pattern ||= '';
+ return [ grep /$pattern/, @$list ];
+ },
'join' => sub {
! my ($list, $joint) = @_;
! join(defined $joint ? $joint : ' ',
! map { defined $_ ? $_ : '' } @$list)
},
'sort' => sub {
***************
*** 191,195 ****
? map { $_->[0] } # for case insensitivity
sort { $a->[1] cmp $b->[1] }
! map { [ $_, lc $_->{ $field } ] }
@$list
: map { $_->[0] }
--- 203,210 ----
? map { $_->[0] } # for case insensitivity
sort { $a->[1] cmp $b->[1] }
! map { [ $_, lc(ref($_) eq 'HASH'
! ? $_->{ $field } :
! UNIVERSAL::can($_, $field)
! ? $_->$field() : $_) ] }
@$list
: map { $_->[0] }
***************
*** 204,208 ****
? map { $_->[0] } # for case insensitivity
sort { $a->[1] <=> $b->[1] }
! map { [ $_, lc $_->{ $field } ] }
@$list
: map { $_->[0] }
--- 219,226 ----
? map { $_->[0] } # for case insensitivity
sort { $a->[1] <=> $b->[1] }
! map { [ $_, lc(ref($_) eq 'HASH'
! ? $_->{ $field } :
! UNIVERSAL::can($_, $field)
! ? $_->$field() : $_) ] }
@$list
: map { $_->[0] }
***************
*** 214,217 ****
--- 232,242 ----
};
+ sub hash_import {
+ my ($hash, $imp) = @_;
+ $imp = {} unless ref $imp eq 'HASH';
+ @$hash{ keys %$imp } = values %$imp;
+ return '';
+ }
+
#========================================================================
***************
*** 502,505 ****
--- 527,531 ----
my ($self, $root, $item, $args, $lvalue, $nextItem) = @_;
my $rootref = ref $root;
+ my $atroot = ($rootref eq __PACKAGE__);
my ($value, @result, $ret, $retVal);
$nextItem ||= "";
***************
*** 526,530 ****
$root = [$root];
}
! if ($rootref eq __PACKAGE__ || $rootref eq 'HASH') {
# if $root is a regular HASH or a Template::Stash kinda HASH (the
--- 552,556 ----
$root = [$root];
}
! if ($atroot || $rootref eq 'HASH') {
# if $root is a regular HASH or a Template::Stash kinda HASH (the
***************
*** 543,550 ****
return $root->{ $item } = { }; ## RETURN
}
! elsif ($value = $HASH_OPS->{ $item }) {
@result = &$value($root, @$args); ## @result
}
! elsif (ref $item eq 'ARRAY') {
# hash slice
return [@$root{@$item}]; ## RETURN
--- 569,578 ----
return $root->{ $item } = { }; ## RETURN
}
! # ugly hack: only allow import vmeth to be called on root stash
! elsif (($value = $HASH_OPS->{ $item })
! && ! $atroot || $item eq 'import') {
@result = &$value($root, @$args); ## @result
}
! elsif ( ref $item eq 'ARRAY' ) {
# hash slice
return [@$root{@$item}]; ## RETURN
***************
*** 582,586 ****
return $retVal if ( $ret ); ## RETURN
}
! elsif (ref $item eq 'ARRAY' ) {
# array slice
return [@$root[@$item]]; ## RETURN
--- 610,614 ----
return $retVal if ( $ret ); ## RETURN
}
! elsif ( ref $item eq 'ARRAY' ) {
# array slice
return [@$root[@$item]]; ## RETURN
***************
*** 605,608 ****
--- 633,643 ----
if ($@) {
+ # temporary hack - required to propogate errors thrown
+ # by views; if $@ is a ref (e.g. Template::Exception
+ # object then we assume it's a real error that needs
+ # real throwing
+
+ die $@ if ref($@) || ($@ !~ /Can't locate object method/);
+
# failed to call object method, so try some fallbacks
if (UNIVERSAL::isa($root, 'HASH')
***************
*** 616,620 ****
@result = &$value($root, @$args);
}
! else {
@result = (undef, $@);
}
--- 651,658 ----
@result = &$value($root, @$args);
}
! elsif ($value = $SCALAR_OPS->{ $item }) {
! @result = &$value($root, @$args);
! }
! elsif ($self->{ _DEBUG }) {
@result = (undef, $@);
}
***************
*** 728,732 ****
elsif (UNIVERSAL::isa($root, 'UNIVERSAL')) {
# try to call the item as a method of an object
! return $root->$item(@$args, $value); ## RETURN
}
else {
--- 766,790 ----
elsif (UNIVERSAL::isa($root, 'UNIVERSAL')) {
# try to call the item as a method of an object
!
! return $root->$item(@$args, $value) ## RETURN
! unless $default && $root->$item();
!
! # 2 issues:
! # - method call should be wrapped in eval { }
! # - fallback on hash methods if object method not found
! #
! # eval { $result = $root->$item(@$args, $value); };
! #
! # if ($@) {
! # die $@ if ref($@) || ($@ !~ /Can't locate object method/);
! #
! # # failed to call object method, so try some fallbacks
! # if (UNIVERSAL::isa($root, 'HASH') && exists $root->{ $item }) {
! # $result = ($root->{ $item } = $value)
! # unless $default && $root->{ $item };
! # }
! # }
! # return $result; ## RETURN
!
}
else {
***************
*** 881,883 ****
=head1 SEE ALSO
! L<Template::Stash|Template::Stash>
\ No newline at end of file
--- 939,941 ----
=head1 SEE ALSO
! L<Template::Stash|Template::Stash>