#!/usr/bin/perl package tt; use Module::Compile -base; use strict; use warnings; use Template; our $VERSION = "0.02"; sub default_tt_config { return ( INTERPOLATE => 0, EVAL_PERL => 1, INCLUDE_PATH => [ @INC ], LOAD_PERL => 1, DEBUG => "undef", ); } sub default_tt_vars { my $class = shift; return ( filter_class => $class, 'package' => undef, file => undef, from_line => undef, to_line => undef, ); } sub pmc_compile { my ( $class, $source, $extra ) = @_; # try to make vars out of the use line my %use_opts = do { ( my $vars = $extra->{use} ) =~ s/^\s*use\s+tt\s*//; eval "$vars"; }; die "error evaluating vars on use line ($extra->{use}): $@" if $@; # try to remove keys that look like TT configuration my %config = ( $class->default_tt_config, map { $_ => delete $use_opts{$_} } grep /^[A-Z_]+$/, keys %use_opts, ); my %vars = ( $class->default_tt_vars, %use_opts, ); my $t = Template->new(\%config) || die Template->error; $t->process( \$source, \%vars, \( my $out ) ) || die $t->error; $out || die $t->error; return $out; } __PACKAGE__; __END__ =pod =head1 NAME tt - Preprocess Perl code with Template Toolkit and Module::Compile. =head1 SYNOPSIS package Foo; # between 'use tt' and 'no tt' the source code will # be process by Template Toolkit. # This example generates source code for accessors. # the specific problem is best solved with L or # L, but the principal remains the same use tt ( fields => [qw/foo bar gorch/] ); [% FOREACH fields IN fields %] sub [% field %] { my $self = shift; $self->{'[% field %]'} = shift if @_; return $self->{'[% field %]'}; } [% END %] no tt; package main; my $obj = Foo->new; $obj->bar("moose"); =head1 DESCRIPTION This module uses Module::Compile to help you generate Perl code without using BEGIN/eval tricks and reducing readability, but without having to repeat yourself either. =head1 BUT SOURCE FILTERS BAD!!!! Yeah, source filters suck (normally) for two reasons, neither of which L suffers from: =over 4 =item 1. They're kinda slow and may introduce fat dependencies for simple code. L fixes this. =item 2. They break down on edge cases. This is true for source filters that try to parse Perl, pretending to implement syntax extensions. Since L doesn't parse the perl code at all but operates on a very dumb string level it meets no edge cases. =back That said, string level preprocessing of source code sucks. However, since Perl doesn't have a convenient AST to write Lisp-style macros and deeper templates (that are aware of Perl's own semantics), this module does fill a niche. =head1 CONFIGURATION To configure L