Re: Mason 2.0 thoughts

"John Siracusa" <[email protected]> Mon, 14 May 2007 09:48:39 -0400
Newsgroups gmane.comp.web.mason.devel
Message-ID <[email protected]>
On 5/13/07, Jonathan Swartz <[email protected]> wrote:
>> A second request:
>>
>>     <% STUFF |myescape %>
>>
>> where a piece of my code gets passed STUFF, either as a string or as a
>> "live" snippet of Perl.  Right now, I have to do:
>>
>>     <% 'STUFF' |myescape %>
>>
>> and the quotes annoy me, as does the need to eval manually.
>
> Ah, so whereas the current escape flag subroutines get passed the
> result of STUFF, you'd like it to pass STUFF as a code reference?

More precisely, I'd like escapes to register their intent in one of
two(-point 1) ways:

1. Give me the result (current behavior)
2. Give me the raw, unparsed string.
   2.1 ...and also put me in the context of the calling comp.

Number 2 is straightforward and allows for interesting custom(ish)
markup in templates.  Here's an example from my current work:

...
<% 'START_FORM' |fm %>

<% 'USERNAME:LABEL' |f %>
<% 'USERNAME:FIELD' |f %>

<% 'PASSWORD:LABEL' |f %>
<% 'PASSWORD:FIELD' |f %><

<% 'LOGIN_BUTTON:FIELD' |f %>

<% 'END_FORM' |fm %>
...

This is my version of a "designer-friendly" syntax for my HTML widget
library.  The single quotes are just noise here; I just want the raw
text which I parse and handle in by own way.

The 2.1 bit gets around the current impossibility (well, "extreme
difficulty," anyway) of having your custom escape code run in the
context of the component package.  For example, if I want to also
accept arbitrary Perl expressions inside my custom syntax, e.g.:

    ...
    <% 'LOGIN_BUTTON:FIELD(size => $size)' |f %>
    ...
    <%init>
    my $size = ...;
    </%init>

I'm in quite a bind since $size is a lexical in a context far, far
away once I get inside my escape code.  To get around this, my code
would have to be compiled into the object file.  So, putting it all
together, this:

    <% 'LOGIN_BUTTON:FIELD(size => $size)' |f %>

becomes this in the template:

    <% LOGIN_BUTTON:FIELD(size => $size) |f %>

which gets compiled down to this in the object file:

    $m->print(MyEscape::handle_whatever(size => $size));

Multiple escapes now have to look something like this:

Template:

    <% LOGIN_BUTTON:FIELD(size => $size) |f,g %>

Object file:

    $m->print(MyOtherEscape::handle_this(
              MyEscape::handle_that(size => $size)));

"Traditional" (type 1) escapes could be inlined in the same way, for uniformity.

Also, speaking of lexicals that are far, far away, getting at %ARGS
(another lexical, IIRC) is painful(/"impossible") from inside escape
routines.  In my web app framework, I save off component args before
calling Mason so I can get at them later, but I only hook in at the
top level.  When a component calls another component, I'm not there to
snag the args.  (AFAIK, there's no easy place to hook in for that.)
So, either %ARGS as a (possibly local()ized) package var, or a new
place to get at the %ARGS passed to the current component would be
nice :)

> Of course, this would be unnecessary (and inefficient) for escape
> flags like |h, so we'd want to do the right thing depending on the
> escape flags.

Inlining is your friend :)  And speaking of efficiency, coalescing
multiple $m->print() calls into fewer calls with multiple args might
buy some speed.  Optimizations like this, in turn, start to beg for
some sort of intermediary form upon which optimization can be done
before the final object file is produced...

-John

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/