package SimpleTemplate; use strict; use warnings; use vars qw( $VERSION ); $VERSION = '1.00'; my $default; # Holds the default template object when class methods are used. sub new { my $class = shift; my $content = shift || _ST_default_content(); my $self = { '_delims' => [qw/ <% %> /], '_content' => $content, '_listsep' => "\n", }; bless $self, $class; } sub list_separator { my $self = shift; if (! ref $self) { $self = $default = $default || __PACKAGE__->new() } return @_ ? $self->{_listsep} = shift : $self->{_listsep}; } sub delimiters { my $self = shift; if (! ref $self) { $self = $default = $default || __PACKAGE__->new() } $self->{_delims} = shift if @_ == 1; $self->{_delims} = [shift, shift] if @_ == 2; return $self->{_delims}; } sub tags { my $self = shift; if (! ref $self) { $self = $default = $default || __PACKAGE__->new() } my ($L, $R) = @{$self->{_delims}}; my @list = $self->{_content} =~ m/\Q$L\E\s*(.*?)\s*\Q$R\E/gm; return @list; } sub fill { my $self = shift; if (! ref $self) { $self = $default = $default || __PACKAGE__->new() } my $args = shift; my $replace = shift; my ($L, $R) = @{$self->{_delims}}; my $text = $self->{_content}; $text =~ s/\Q$L\E\s*(.*?)\s*\Q$R\E/$self->_expand($1,$args)/egm; $self->{_content} = $text if $replace; return \$text; } # Private Methods sub _expand { my $self = shift; my ($key, $hashr) = @_; my $value = $hashr->{$key}; return '' unless defined $value; for (ref $value) { /CODE/ and do { return $value->() }; /ARRAY/ and do { return join $self->{_listsep}, @$value }; /SCALAR/ and do { return $$value }; /^$/ and do { return $value }; } } # Private class methods sub _ST_default_content { my $FH; my $pkg = caller; no strict 'refs'; # if DATA exists in the calling package use that. if ( exists ${ $pkg . '::' }{DATA} and defined *{${$pkg . '::'}{DATA}}{IO}) { $FH = *{${$pkg . '::'}{DATA}}{IO}; # else if DATA exists in main, use that. } elsif ( exists $main::{DATA} and defined *main::DATA{IO} ){ $FH = *main::DATA{IO}; # else use <> } else { $FH = \*ARGV; } do { undef $/; <$FH> }; } q( My two cents aren't worth a dime. ); __END__ =head1 NAME SimpleTemplate - Perl extension for very simple templates. =head1 SYNOPSIS use SimpleTemplate; my $template = SimpleTemplate->new("Hello, <%World%>!\n"); my $ref = $template->fill({ World => 'PerlMonks' }); print $$ref exit(0); # Also try the bells, whistles, and variations! Like... # Filling placeholders with other thingies! my $textref = $template->fill( { Foo => \$scalar_ref, Bar => \@or_a_list, Baz => \&a_sub_ref, } ); # Default Content! my $template = SimpleTemplate->new(); # Default Content via a class method! SimpleTemplate->fill({ PlaceHolder => 'Your Favorite Value' }); # Change your delimiters! $template->delimiters('[:', ':]'); # Change your list separator! $template->list_separator(':'); # Find the tag names in your Content! my @tags = $template->tags(); =head1 DESCRIPTION This module allows for filling in placeholders in templates. It is meant to exceedingly simple. It does not make it possible for you to actually put code in your templates. If that is what you want, there are many other (less simple) modules that would be a better choice. SimpleTemplate works in two (intermixable) modes. When the provided methods are called as class methods, they operate on a default template object stored in a private class variable. This default template is created the first time any of the methods are called as class methods. It is created by calling the constructor without any arguments. I've found this module to be extreeeeeeeeeeeeeeeeeeeeeeeemely useful. I use it for all manner of things. Here's a hint... just because SimpleTemplate is simple that doesn't mean your use of it has to be. SimpleTemplate can do a lot, especially if you make heavy use of the delimiters() method and the optional argument to fill(). =head1 METHODS =over 8 =item new() The constructor can be called with either a single scalar argument or none at all. When it is called with an argument, the argument is taken to be the template content. When it is called without an argument, the template content is read from a filehandle. If the DATA filehandle is found in the calling package, the template content is read from it. Else if the DATA filehandle is found in main::, the template content is read from there. Otherwise, the template content is read from the ARGV filehandle. =item fill() This method expects a single hashref as an argument. The keys of the hash referred to by the hashref should coincide with the placeholder names and the values should be the data to be substituted (or references to the data.) If a value is found to be a reference, it will be called if it is a code reference, dereferenced and joined with the defined list separator if it is a reference to an array, or dereferenced if it is a reference to a scalar. Note that a reference to a hash isn't handled specially at all. An optional argument can be supplied. If it is a true value, the template object's content will be replaced with the result of filling in its placeholders. This can be useful for recursively filling templates. =item delimiters() This method takes 0, 1, or 2 arguments. When called with at least one argument, it sets the delimiters used to define placeholders in the template. If there is exactly one argument, it is assumed to be a reference to an array containing the left and right delimiters in that order. When called with two arguments, they are assumed to be the left and right delimiters in that order. When called with no arguments no attempt is made to set the delimiters. This method returns a reference to an array containing the left and right delimiters in that order. The default delimiters are '<%' and '%>' but feel free to change them; that's what this method is here for. =item list_separator() This method takes either 0 arguments or exactly one argument. If it is called with an argument, the list separator value is set to that value. It returns the list separator value. By default, the list separator is a newline ("\n"). The list separator is a string which is used to separate the values when a placeholder is filled with an array. =item tags() This method takes no arguments. It returns a list of the placeholder names used in the template. =back =head1 IMPORTANT NOTE Placeholder names must not have leading/trailing whitespace. Whitespace should be avoided in delimiters too. =head1 LIMITATIONS SimpleTemplate reads the whole template into memory. If your templates are huge, it will be a memory hog. This helps to keep SimpleTemplate SIMPLE! =head1 BUGS Yeah, right! As if... Look - this module is just too simple to have bugs. But, if you find any anyway, please let me know at perlmonks.org. =head1 AUTHOR sauoq =head1 SEE ALSO L. =cut