Perrin Harkins <[EMAIL PROTECTED]> said something to this effect on 10/29/2001:
> > I am writing a web-based template processing service somewhat
> > like Apache::Template, which adds a few configurable behaviors
> > to TT2 to make it act somewhat more like HTML::Mason.  Among
> > these are the ability for providers to search the working
> > directory of a template and all its parent directories, up to a
> > specified root directory, similar to how autohandlers and
> > dhandlers are looked for in mason.
...
> > So in order to do the current-directory-sensitive behavior, I
> > have had to subclass Template::Context, Template::Provider, and
> > Template::Document (Context keeps a stack of Documents that
> > updates in the visit/leave methods, Provider implements the new
> > search logic, Document remembers its location).   I've also had
> > to extend the existing API in incompatible ways, namely
> > reverting visit/leave to an earlier behavior, and passing extra
> > args to Provider::fetch (the latter is compatible -- for now).
> 
> You did all of that just to get TT to climb the directory tree
> when resolving template calls?  Why don't you just vary the
> include path on each request?  TT already knows how to climb
> the include path.

I had the same reaction, although I kept it to myself.  :)  I've
written a mod_perl handler which does this, too; it recreates the
INCLUDE_PATH on each request, based on $r->filename.  The sub I
use to recreate it looks like this:

#------------------------------------------------------------------------
# _inc_path($filename)
#
# This creates a list of directories to be returned to the provider,
# and specifies how provider searches for included files. This hack
# makes the provider walk up the directory hierarchy to find the
# closest occurance of a file to include. This facilitates, for
# example, putting different headers and footers at various places
# along the tree.
#------------------------------------------------------------------------
sub _inc_path ($) {
    my $f = shift;
    my %uniq;
    my @dir;
    local $" = '/';

    #
    # This bit of code returns a reference to a list of directories,
    # sorted in reverse order by length, starting from the directory
    # in which the translated filename lives, and ending with /.
    #
    return [
        sort { length $b <=> length $a } # reverse sorted by length
        grep { ++$uniq{$_} == 1        } # (unique directories only)
        map  { push @dir, $_; "/@dir"; } # a growing list of dirs
             ($f =~ m:([^/]+)/:og)       # gathered from the current
    ];                                   # translated filename
}

It gets called as:

  $INCLUDE_PATH = _inc_path($r->filename);

Simple, strightforward, efficient.  The only limitation is that
it goes all the way to /, which can be gotten around pretty
easily (and is left an an exercise for the reader. ;).

(darren)

-- 
There is a fine line between participation and mockery.


Reply via email to