package Sledge::Plugin::DebugScreen;
use strict;
use warnings;
our $VERSION = '0.07';
use Template;
use Devel::StackTrace;
use IO::File;
{
package Sledge::Exception::StackTrace;
sub print_context {
my $self = shift;
my($file, $linenum) = ($self->file, $self->line);
my $code;
if (-f $file) {
my $start = $linenum - 3;
my $end = $linenum + 3;
$start = $start < 1 ? 1 : $start;
if (my $fh = IO::File->new($file, 'r')) {
my $cur_line = 0;
while (my $line = <$fh>) {
++$cur_line;
last if $cur_line > $end;
next if $cur_line < $start;
my @tag = $cur_line == $linenum ? qw( ) : ('', '');
$code .= sprintf(
'%s%5d: %s%s',
$tag[0], $cur_line, $self->_html_escape($line), $tag[1],
);
}
}
}
return $code;
}
sub _html_escape {
my ($self, $str) = @_;
$str =~ s/&/&/g;
$str =~ s/</g;
$str =~ s/>/>/g;
$str =~ s/"/"/g;
return $str;
}
}
our $TEMPLATE = q{
Error in [% title | html %]
[% title | html %]
[% pages.current_url | html %]
[% desc | html %]
StackTrace
| Package |
Line |
File |
[% FOR s IN stacktrace -%]
| [% s.pkg | html %] |
[% s.line | html %] |
[% s.file | html %] |
[% s.print_context %] |
[%- END %]
};
sub import {
my $self = shift;
my $pkg = caller;
no strict 'refs';
{
my $super = $pkg->can('dispatch');
*{"$pkg\::dispatch"} = sub {
my $self = shift;
local $SIG{__DIE__} = sub {
$self->{__stacktrace} = [map {Sledge::Exception::StackTrace->new(
file => $_->filename, line => $_->line, pkg => $_->package,
)} Devel::StackTrace->new->frames ];
die @_; # rethrow
};
$self->$super(@_);
};
}
*{"$pkg\::handle_exception"} = \&_handle_exception;
}
sub _handle_exception {
my ($self, $E) = @_;
return if $self->finished;
if ($self->debug_level) {
warn $E;
my $vars = {
title => ref $self || $self,
desc => "$E",
pages => $self,
};
if (ref $E and $E->can('stacktrace')) {
$vars->{stacktrace} = $E->stacktrace;
} else {
$vars->{stacktrace} = $self->{__stacktrace};
shift @{$vars->{stacktrace}};
}
my $tmpl = Template->new;
my $output;
$tmpl->process(\$TEMPLATE, $vars, \$output);
$self->r->content_type('text/html');
$self->set_content_length(length $output);
$self->r->status($self->SERVER_ERROR);
$self->send_http_header;
$self->r->print($output);
$self->finished(1);
} else {
die $E;
}
}
1;
__END__
=head1 NAME
Sledge::Plugin::DebugScreen - show the debug screen if crashed
=head1 SYNOPSIS
package Your::Pages;
use Sledge::Plugin::DebugScreen;
sub debug_level {
return $ENV{'DEBUG_MODE'} ? 1 : 0;
}
=head1 DESCRIPTION
This plugin shows the debug screen if crashed, like Catalyst.
The debug screen is only showing debug mode.
Screen image: L
=head1 AUTHOR
MATSUNO Tokuhiro
Koichi Taniguchi
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=head1 THANKS TO
Jiro Nishiguchi.
=head1 TODO
more tests.
=head1 DEPENDENCIES
L, L, L
=head1 SEE ALSO
L
=cut