Puma::ServerPages
|
|
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.
|