Hans Dieter Pearcey
2008-01-16 16:12:04 UTC
Attached is a patch that makes | in substitutions more powerful. This isn't
finished; it does work, and all but two of the existing tests pass with it, but
the implementation feels a bit fragile and there's no documentation.
There are two major changes.
The first is that there can be multiple |s in a substitution, and each can have
arguments (which can be arbitrary Perl). I called these 'filters', even though
that's kind of an overloaded word now (so I'm open to suggestions).
The second is that instead of evaluating the LHS of a substitution immediately,
it's wrapped in sub { } and passed to the filters that way; this gives more
control to the filters, because evaluation is delayed.
Some examples will probably be clearer:
<% $object->expensive_method(\%args) | cache(expires_in => "10m") | h %>
(there's a test that demonstrates that in t/10-cache.t)
<% $biller->calculate_amount | format('$%5.2f') %>
The old escape_flags and apply_escapes are now implemented in terms of filters.
They keep working anywhere in the filter pipeline; the only special casing done
for them is that escape flags are parsed specially when they're the last filter
entry, so that this keeps working:
<% $foo | h, u %>
But this would also work:
<% $foo | h | u | cache %>
I also did some refactoring of cache_self -- '| cache(...)' uses the same
arguments as cache_self, and I didn't want to reinvent the wheel. See
HTML::Mason::Request::_cache_access (the name sucks). We probably want
something like this independent of the rest of the patch; it makes writing
cache_self analogues much easier.
Because LHS evaluation is delayed, I had to do some ugly things to make sure
that globals referred to on the LHS were still around at $m->print time,
especially $_ and @_.
One thing I can't fix is that wantarray becomes useless in <% %> (it will
always be true). It used to reflect the calling context of exec().
Look at HTML::Mason::Filters for how cache() and format() are written. In
particular, the latter is written pretty much exactly how an 'escape' used to
be.
Things I have not yet done, but consider necessary or very useful for this
being 'finished':
* cache() should autogenerate a unique cache key per <% %> (and maybe even
per-filter, per-substitution), so that it's trivial to stick '| cache' onto
existing substitutions
* more real-world useful filters
* documentation and tests, obviously
If all goes well, I would next move on to something like this:
<%| cache %>
A bunch of text here, including <% $more->stuff %>
with maybe some <& /component/calls &>
you know, lots of text, that would be annoying to put inside a
<% $substitution %>
</%>
(but let's paint that bikeshed after we're done with this one)
hdp.
finished; it does work, and all but two of the existing tests pass with it, but
the implementation feels a bit fragile and there's no documentation.
There are two major changes.
The first is that there can be multiple |s in a substitution, and each can have
arguments (which can be arbitrary Perl). I called these 'filters', even though
that's kind of an overloaded word now (so I'm open to suggestions).
The second is that instead of evaluating the LHS of a substitution immediately,
it's wrapped in sub { } and passed to the filters that way; this gives more
control to the filters, because evaluation is delayed.
Some examples will probably be clearer:
<% $object->expensive_method(\%args) | cache(expires_in => "10m") | h %>
(there's a test that demonstrates that in t/10-cache.t)
<% $biller->calculate_amount | format('$%5.2f') %>
The old escape_flags and apply_escapes are now implemented in terms of filters.
They keep working anywhere in the filter pipeline; the only special casing done
for them is that escape flags are parsed specially when they're the last filter
entry, so that this keeps working:
<% $foo | h, u %>
But this would also work:
<% $foo | h | u | cache %>
I also did some refactoring of cache_self -- '| cache(...)' uses the same
arguments as cache_self, and I didn't want to reinvent the wheel. See
HTML::Mason::Request::_cache_access (the name sucks). We probably want
something like this independent of the rest of the patch; it makes writing
cache_self analogues much easier.
Because LHS evaluation is delayed, I had to do some ugly things to make sure
that globals referred to on the LHS were still around at $m->print time,
especially $_ and @_.
One thing I can't fix is that wantarray becomes useless in <% %> (it will
always be true). It used to reflect the calling context of exec().
Look at HTML::Mason::Filters for how cache() and format() are written. In
particular, the latter is written pretty much exactly how an 'escape' used to
be.
Things I have not yet done, but consider necessary or very useful for this
being 'finished':
* cache() should autogenerate a unique cache key per <% %> (and maybe even
per-filter, per-substitution), so that it's trivial to stick '| cache' onto
existing substitutions
* more real-world useful filters
* documentation and tests, obviously
If all goes well, I would next move on to something like this:
<%| cache %>
A bunch of text here, including <% $more->stuff %>
with maybe some <& /component/calls &>
you know, lots of text, that would be annoying to put inside a
<% $substitution %>
</%>
(but let's paint that bikeshed after we're done with this one)
hdp.