September 11, 2009

Simple Template System in Perl

Article about ▸

written by Marek Foss

Simple Template

By now you should know I am a fan of everything simple. I casted an opinion that frameworks, while useful, are overcomplicated and create an unnecessary load on your project, unless it reaches a certain amount of complexity. And one of the most used frameworks, are the template frameworks. Thus, it would be great to have a dead simple template system, that just works. And that’s what I am going to show you today.

Because Perl is my weapon of choice, I’m going to show you my Simple Template System (STS) for that language, but porting it to another one shouldn’t be a problem. The idea is simple, of course, and relies on creating a traditional HTML file, as if creating the general look of the site, and then instead of content, marking it with special string, which we then substitute with whatever we want, using regular expressions.

So you start off with a simple HTML page, for example:

<html>
<head>
    <title>Simple Template System</title>
</head>
<body>
    <div class="menu">
        <!---sidebar--->
    </div>
    <div class="main">
        <!---content--->
    </div>
</body>
</head>

The <!—-sidebar—-> and <!—-content—-> are those special strings for substitution. The purpose of using a HTML comment symbol with an additional hyphen is that first of all, they are invisible if left behind in the code, second – it’s easy to regex them from ordinary comments, and third – they are valid HTML. So now we have a page skeleton, or in other words – a template. It’s time to use it.

For this purpose, we’ll have a simple Perl script that reads the template file, lets call it main.tmp, and substitutes the necessary stuff to display a content-rich site. First we load the template into a variable:

my $tmp = '';
if( open FILE, '<', 'main.tmp' ){
    while( <FILE> ){ $tmp .= $_; }
    close FILE;
}

To walk you through the code, I’ll just say that we first try to open the file in the read-only mode, then we go over all the lines in that file and append them to the $tmp variable, and in the end we close that file.

Then we define content variables and give them some values:

my $sidebar = 'This is a menu';
my $content = 'This is the main content block';

Finally, we put the content in the necessary places using regular expressions, and we print the website:

$tmp =~ s/<!---sidebar--->/$sidebar/;
$tmp =~ s/<!---content--->/$content/;
$tmp =~ s/<!---.*?--->//g;

print CGI::header( -type => 'text/html' );
print $tmp;

The s/ is a regular expression substitution. The first argument is the string to look for, the second argument is the string to put instead of the first one. So we simply look for sidebar and main content placeholders, and substitute it with the actual content. The last regular expression removes all other placeholders that we won’t be using in this case – because this template system is flexible, you can have a lot of place holders, not all need to be used. And what about placeholders within placeholders? Well you could use them, you would just need a more fancy regular expression. I can’t think of a reason to have such a thing, but why not :]

UPDATE: draegtun of transfixedbutnotdead picked up the STS subject in a clever post on how features can kill usability, but had a very good idea of making the initial code slicker by using a hash table and a single regex. So, instead of defining variables separately, we use a hash:

my %vars= {
    sidebar => 'This is a menu',
    content => 'This is the main content block'
}

And instead of separate regular expressions, just a single one:

$tmp =~ s/<!---(.*?)--->/exists $vars{$1} ? $vars{$1} : ''/ge;

The above regex looks for the placeholders, and if the placeholder name matches any of our keys in the hash that contain data to be displayed – we make a substitution. Otherwise, we remove the placeholder from the displayed page.

Conclusions

And there you have it – a Simple Template System that you can setup within minutes just by coding by hand, and quickly create a variable-content websites. Using if statement you could make a page that displays different content basing on which section the user wants to see. Finally, you could have several different template files, changing them according to your needs (for example, front page different then subpages, article pages, etc.)

Please state your opinion and feedback on STS in the comments, I’m interested in what you think about it.


If you liked the article, please spread the word and share it!

  • Share

Comments


draegtun writes:

Sometimes simple is best.

Nice post.  Inspired me to write my own related post! 

http://transfixedbutnotdead.com/2009/09/14/building-a-sts-simple-template-system/

/I3az/


Hartog writes:

I have done this over a gazillion times (be it with $$name$$ or such) and finally came to the conclusion that it isn’t worthwhile to do it over and over and over again. DRY _is_ a powerful statement that needs consideration in a choice to abandon frameworks and go DIY.

And you will inevitably get a need for loops and conditionals even on the simple projects, and putting that logic outside of the template is, imho, bad practice.

There are some pretty useful small & powerful templating systems on CPAN, HTML::Template is the one I’d recommend.


Marek Foss writes:

I was wondering that myself. I think DRY is fine as long as setting it up takes less time than setting up a framework - in the end it’s all about time. On the other hand, you need to consider problems in the future, when the app grows.

However I disagree with your statement that “you will inevitably get a need for loops and conditionals even on the simple projects, and putting that logic outside of the template is, imho, bad practice.”

I think a template is a template, and the logic should always be in the controller, not in the view. Even so, I agree there are some awesome template systems for Perl. Just sometimes it’s way quicker to DIY :)



Leave a comment: (comments may not appear immediately due to page caching)

Name: Email: (not disclosed)

WWW: Remember my details

Notify me of follow-up comments

Feed me:

to feed
  • Subscribe and get the new articles every now and then directly in your reader — I recommend using Google Reader

Facebook:

Connect:

 by Google
Google FriendConnect appears to be down at the moment. Sorry for inconvenience.
Related Posts with Thumbnails