Puma::ServerPages
S y n t a x
SourceForge.net Logo

IN-LINE PERL
Puma::ServerPages gives you the ability to place Perl in-line with HTML. This is not some stripped down subset of Perl that I created myself, but rather it is 100% pure Perl that is compiled by Larry Wall's Perl compiler with nothing removed.
How did I manage to do that? Well, those of you familiar with Apache::ASP will be able to see that I took a few queues from there. The key is that the parser converts the Perl/HTML page you create and converts it all into a big string of pure Perl code which is then exec'd in by Perl itself with the output going to the web browser. Pretty simple huh?
So here's our first lesson, including Perl in your HTML.
Most *SP languages use the <% ... %> syntax to place blocks of code in-line into the HTML. I didn't. I much prefer the syntax <: ... />. It's much more XML like and given that XML is quickly becoming a standard that pervades most every computing system that's out there, I thought I'd concede defeat.
Many *SP languages use <%= %> to do a direct print to the output screen. Puma uses a similar <:= ... /> notation, but I have found that I rarely ever use it because Puma can do in-line variable interpolation (described a little later in this chapter).
Anyhow, here's an example:
   <html><head>
      <title>Puma::ServerPages Example</title>
   </head><body>
      <:
         my $ii;
         for ($ii = 0; $ii < 5; $ii++) {
      />
         This is a Puma::ServerPages example, part
            <:= $ii + 1 />
         <br>
      <: } />
   </body></html>
As you can likely figure out, this will display the line, "This is a Puma::ServerPages example" on the browser five times with "part 1" through, "part 5" added to the end of each line. It's not an exciting example, but it's a start. It's kinda ugly too, but we can fix that in later examples.
THE PRINT() FUNCTION
Have you ever gotten sick of the $Response->Write(...) crap that most *SP languages do? Way too much typing for too little results! Why couldn't they just make it so that you could use a print() function instead? Well ... I did!
I looked at the logic behind the idea of the $Response->Write(...) statement, and it just didn't make sense. Perl's CGI had it right all along: a single object to do all the work of the Response and Request and make the STDOUT be the output buffer. That's exactly what happens in Puma::ServerPages. All you have to do is print() to STDOUT and the output magically goes to the browser.
Try this (I'll be leaving the html, head and body tags from now on):
   <:
      my $ii;
      for ($ii = 0; $ii < 5; $ii++) {
         print 'This is a Puma::ServerPages example, part '. $ii + 1
         .'<br>';
      }
   />
This example is the same as the previous one except that it uses the print statement instead. You can see that things are getting prettier already.
So what about buffering? Don't we want the output buffered so we can control it better? Of course! The output of the print statements doesn't actually get sent directly to the browser. Instead, it's captured by using the Puma::Util::Buffer package and can be manipulated fully before shipping it out.
VARIABLE INTERPOLATION
Perl has the ability to interpolate variables in-line with strings such that
   my $name = "Ingmar";
   print "Hello, I'm $name from Ikea!";
would be the same as
   print "Hello, I'm Ingmar from Ikea!";
Puma can do the same. Consider the modified example from above:
   <: for (my $ii = 1; $ii <= 5; $ii++) { />
      This is a Puma::ServerPages example, part $ii<br>
   <: } />
Once again, this example will send the same output to the browser as the rest. Unfortunately, we're back to the ugly notation of <: } />. We'll fix that next.
WRAPPERS FOR PERL CONTROL STATEMENTS
This next part is a bit weird. I'm still not sure about the whole thing.
I was getting rather tired of the <: if (condition) { /> ... <: } /> notation that is common to most *SP languages and thought it was rather ugly. To make it prettier, I decided to wrap Perl's control statements in tags. I'm not sure if it's prettier or more functional, but here it is anyhow:
   <:for (my $ii = 1; $ii <= 5; $ii++) />
      This is a Puma::ServerPages example, part $ii<br>
   </:>
This is the final iteration of this example and that's about as clean as it's gonna get. Perl's for() statement is more or less exactly the same as before except that there is no space between the colon and the word, "for" and there is no opening curly brace at the end. The <: } /> is replaced with </:>.
This same syntax applies to the following Perl control statements:
   <:for () /></:>
   <:foreach () /></:>
   <:if () /><:elsif () /><:else /></:>
   <:unless () /></:>
   <:while () /><:continue /></:>
SPECIAL STATEMENTS
Puma::ServerPages wraps up a number of other Perl statements in the :use tag. Consider the following:
   <:use
      lib="/path/to/perl"
      module="PSP::Module"
      prefix="pspmodule"
      foo="Foey"
      bar=`$barbar`
   />
generates this code:
   use lib '/path/to/perl';
   use PSP::Module;
   my $pspmodule = new PSP::Module(
      foo => 'Foey',
      bar => $barbar,
      Server => $server
   );
The :use tag has three reserved parameters: lib, module and prefix. The lib and module parameters may be used independently, but the prefix parameter requires that the module parameter exist.
If the lib parameter exists, it generates the, "use lib" line. Likewise, the module parameter causes the, "use modulename" line to appear. The prefix parameter creates a new object according to the values of the prefix and module parameters. Any remaining parameters in the :use tag are added to the object constructor as named parameters.
There are two other things to notice in this example. The first is the back-quotes around the $barbar parameter. The backquotes causes the value passed to be evaluated rather than quotes when the page is interpreted.
The second thing to note is the, "Server" parameter passed to the constructor. Puma::ServerPages always passes the $server object to object to the constructor because it is the only hook that the new object has back to the parsing/processing system. Careful attention has been paid to how this is implemented to assure that no circular references (and potential memory leaks) are created in the process.
The other feature that Puma::ServerPages has built into it is the :include tag. This tag replaces the standard Apache include system and eliminates the (rather high) cost of invoking it.
The include tag is formatted as follows:
   <:include file="filename.ext" foo="bar" />
The file= parameter tells the handler which file to include. Any additional parameters are passed to the included file in a hash called $include; thereby $include->{foo} = 'bar' would be set at the beginning of the included file.
There are a few additional parameters that can be passed to thes :include tag that define where to build the filepath for the included file, but I'm too lazy to cover that now. Perhaps in the next revision of the document.