[Templates] patches for some better diagnostics
Mark D. Anderson
mda@discerning.com
Fri, 10 Oct 2003 16:12:24 -0700
ok, it isn't pretty, but i've beaten TT into spitting out context
information for undef errors, as well as spitting out trace information
to the console.
First off, an unrelated patch to ttree to give better startup
failure handling:
my $template = Template->new($ttopts);
+ use Data::Dumper;
+ print STDERR "Template->new returned false value with options: ", Dumper($ttopts) unless $template;
+ die "Template::ERROR is: $Template::ERROR" unless $template;
We add debug_format support to ttree:
'template_debug|debug=s',
+ 'template_debug_format|debug_format=s',
At the top of Template/Context.pm, we introduce a new global $LAST_LINE
and we trap die:
!use vars qw( $VERSION $DEBUG $AUTOLOAD $DEBUG_FORMAT);
+use vars qw( $VERSION $DEBUG $AUTOLOAD $DEBUG_FORMAT $LAST_LINE);
use base qw( Template::Base );
use Template::Base;
use Template::Config;
use Template::Constants;
use Template::Exception;
$VERSION = sprintf("%d.%02d", q$Revision: 2.81 $ =~ /(\d+)\.(\d+)/);
$DEBUG_FORMAT = "\n## \$file line \$line : [% \$text %] ##\n";
+$LAST_LINE = undef;
+
+$SIG{__DIE__} = sub {
+ die @_ if !$LAST_LINE || $_[0] =~ m/At /;
+ die 'At ', $LAST_LINE->{file}, ':', $LAST_LINE->{line}, ' token |', $LAST_LINE->{text}, '|: ', @_;
+};
Then later in Template/Context.pm in the function debugging we:
- always set $LAST_LINE
- make sure that there isn't a two-character "\n" in the format string
- support for a "stdout:" prefix found in the value of DEBUG_FORMAT,
to print immediately instead of returning the value (and fouling up the template).
(You'll need to diff yourself; sorry)
sub debugging {
my $self = shift;
my $hash = ref $_[-1] eq 'HASH' ? pop : { };
$LAST_LINE = $hash;
my @args = @_;
# print "*** debug(@args)\n";
if (@args) {
if ($args[0] =~ /^on|1$/i) {
$self->{ DEBUG_DIRS } = 1;
shift(@args);
}
elsif ($args[0] =~ /^off|0$/i) {
$self->{ DEBUG_DIRS } = 0;
shift(@args);
}
}
if (@args) {
if ($args[0] =~ /^msg$/i) {
return unless $self->{ DEBUG_DIRS };
my $format = $self->{ DEBUG_FORMAT };
# interpolate EOL in format
$format =~ s/\\n/\n/g;
$format = $DEBUG_FORMAT unless defined $format;
$format =~ s/\$(\w+)/$hash->{ $1 }/ge;
if ($format =~ m/stdout:(.*)/s) {
print STDOUT $1;
return '';
}
return $format;
}
elsif ($args[0] =~ /^format$/i) {
$self->{ DEBUG_FORMAT } = $args[1];
}
# else ignore
}
return '';
}
Ok, now the coup de grace...
If my ttree rc file has:
template_debug = undef,dirs
template_debug_format = stdout:DEBUG: $file:$line : |$text|\n
Then it will spit out lines to the console as it executes, like:
...
DEBUG: header.inc:100 : IF (level == 1)
DEBUG: header.inc:101 : IF (item.relurl)
DEBUG: header.inc:101 : downdir
...
And when/if there is an undef error you'll get a line like:
! undef error - At header.inc:17 token |foobar|: foobar is undefined
If you want just the context tracking in undef errors without the debug output,
then set:
template_debug = undef,dirs
template_debug_format = stdout:
-mda