On Friday 27 April 2007 2:54 pm, Paul Seamons wrote:
> I propose adding a DUMP directive.  I've had this in CGI::Ex::Template
> since May of last year.  I have found it almost invaluble.  I am
> willing to write all of the code necessary to have it in TT2.  It
> works something similar to the following:

All done.  Attached is a set of patches that will add DUMP support, 
configuration, pod, and testing.  The patch does not include the resulting 
changes to the Grammar.pm.  If you are applying this patch to your own 2.19
version, you will need to run "cd parser ; ./yc ; cd -" after applying the 
patch to update the Grammar.pm.

As a side note - it was a pretty scary thing to see how TT actually parses 
everything - a one line change to the Parser.yp resulted in a 100k diff for 
Grammar.pm.  I guess that is the nature of yapp, but still - all I can say 
is "wow!"

The DUMP directive implemented here is pretty close to what the thread 
discussed.  The main missing item is that there currently isn't inline 
configuration of the directive - all configuration must happen through the 
DUMP configuration option (outlined in the added POD).  The inline 
configuration was making the DUMP output look poor, and it seemed a little 
ambiguous about what should be a DUMP configuration parameter and what should 
be dumped.  The Data::Dumper module makes you configure everything before 
calling Dump or Dumper - so we do to.  I think this will be handled if we get 
around to adding the CONFIG option that lets you change configuration during 
the playing of the template.

Try it out.  I'm hoping pretty soon that everyone will be taking it for 
granted.  It is a very useful feature.

Paul
diff -r Template-Toolkit-2.19/lib/Template/Context.pm Template-Toolkit-2.19-mine/lib/Template/Context.pm
727a728,796
> # dump
> #
> # Used by the DUMP directive for dumping the contents of
> # one or more variables - or the entire stash.  Configuration
> # of behavior is handled by the DUMP configuration option.
> #------------------------------------------------------------------------
> 
> sub dump {
>     my ($self, $info) = @_;
> 
>     # find configuration overrides
>     my $conf = $self->{'DUMP'};
>     return '' if ! $conf && defined $conf; # DUMP => 0
>     $conf = {} if ref $conf ne 'HASH';
> 
>     my ($file, $line, $name, $args, $EntireStash) = @{ $info }{qw(file line name args EntireStash)};
> 
>     # allow for handler override
>     my $handler = $conf->{'handler'};
>     if (! $handler) {
>         require Data::Dumper;
> 
>         # new object and configure it with keys that it understands
>         my $obj = Data::Dumper->new([]);
>         my $meth;
>         foreach my $prop (keys %$conf) {
>             $obj->$prop($conf->{$prop}) if $prop =~ /^\w+$/ && ($meth = $obj->can($prop));
>         }
> 
>         # add in custom Sortkeys handler that can trim out private variables
>         my $sort = $obj->Sortkeys;
>         $obj->Sortkeys(sub { my $h = shift; [grep {$_ !~ $Template::Stash::PRIVATE} ($sort ? sort keys %$h : keys %$h)] });
> 
>         $handler = sub { $obj->Values([EMAIL PROTECTED]); $obj->Dump }
>     }
> 
>     # play the handler
>     my $out;
>     if (! $EntireStash                      # always play if not EntireStash
>         || $conf->{'EntireStash'}           # explicitly set
>         || ! defined $conf->{'EntireStash'} # default to on
>         ) {
>         $out = $handler->($args);
>     }
>     $out = '' if ! defined $out;
> 
>     # show our variable names
>     $EntireStash ? $out =~ s/\$VAR1/$name/g : $out =~ s/\$VAR1/$name/;
> 
>     # add headers and formatting
>     if ($conf->{'html'}                # explicitly html
>         || (! defined($conf->{'html'}) # or not explicitly no html
>             && $ENV{'REQUEST_METHOD'}  # and looks like a web request
>             )) {
>         if (defined $out) {
>             $out = $self->filter('html')->($out);
>             $out = "<pre>$out</pre>";
>         }
>         $out = "<b>DUMP: File \"$info->{file}\" line $info->{line}</b>$out" if $conf->{'header'} || ! defined $conf->{'header'};
>     } else {
>         $out = "DUMP: File \"$info->{file}\" line $info->{line}\n    $out" if $conf->{'header'} || ! defined $conf->{'header'};
>     }
> 
>     return $out;
> }
> 
> 
> 
> #------------------------------------------------------------------------
854a924,925
>     $self->{ DUMP } = $config->{ DUMP } if defined $config->{ DUMP };
> 
diff -r Template-Toolkit-2.19/lib/Template/Directive.pm Template-Toolkit-2.19-mine/lib/Template/Directive.pm
994a995,1026
> sub dump {
>     my ($class, $args, $_file, $_line, $textref) = @_;
> 
>     # add on named arguments as a final hashref
>     my $named = shift @$args;
>     push @$args, "{\n        " . join(",\n        ", @$named) . ",\n    },\n" if @$named;
> 
>     # prepare arguments to pass to Dumper
>     my $_args = (@$args > 1) ? "[\n    ". join(",\n    ", @$args) .",\n    ]" # treat multiple args as a single arrayref to help name align
>               : (@$args > 0) ? "\n    ".  join(",\n    ", @$args) .",\n    "  # treat single item as a single item
>               : '$stash';                                                     # treat entire stash as one item
> 
>     # find the name of the variables being dumped
>     my $is_entire = ! @$args ? 1 : 0;
>     my $_name = $is_entire ? 'EntireStash' : $$textref;
>     $_name =~ s/^.*?\bDUMP\s*//;
>     s/\'/\\\'/g for $_name, $_file;
> 
>     return <<EOF;
> 
> # DUMP
>     $OUTPUT \$context->dump({
>         file => '$_file',
>         line => $_line,
>         name => '$_name',
>         args => $_args,
>         EntireStash => $is_entire,
>     });
> EOF
> 
> }
> 
diff -r Template-Toolkit-2.19/lib/Template/Manual/Config.pod Template-Toolkit-2.19-mine/lib/Template/Manual/Config.pod
1439a1440,1504
> =item DUMP
> 
> Configures the behavior of the DUMP tag.  May be set to 0, a hashref,
> or another true value.  Default is true.
> 
> If set to 0, all DUMP directives will do nothing.  This is useful if
> you would like to turn off the DUMP directives under some environments.
> 
> IF set to a true value (or undefined) then DUMP directives will operate.
> 
> If set to a hashref, the values of the hash can be used to configure
> the operation of the DUMP directives.  The following are the values
> that can be set in this hash.
> 
> =over 4
> 
> =item EntireStash
> 
> Default 1.  If set to 0, then the DUMP directive will not print the
> entire contents of the stash when a DUMP directive is called without
> arguments.
> 
> =item handler
> 
> Defaults to internal coderef that uses Data::Dumper.  If set to a
> coderef, the DUMP directive will pass the arguments to be dumped and
> expects a string with the dumped data.  This gives complete control
> over the dump process.
> 
> Note 1: The default handler makes sure that values matching the
> private variable regex are not included.  If you install your own handler,
> you will need to take care of these variables if you intend for them
> to not be shown.
> 
> Note 2: If you would like the name of the variable to be dumped, include
> the string '$VAR1' and the DUMP directive will interpolate the value.  For
> example, to dump all output as YAML - you could do the following:
> 
>     DUMP => {
>        handler => sub {
>            require YAML;
>            return "\$VAR1 =\n" . YAML::Dump(shift);
>        },
>     }
> 
> =item header
> 
> Default 1.  Controls whether a header is printed for each DUMP directive.
> The header contains the file and line number the DUMP directive was
> called from.  If set to 0 the headers are disabled.
> 
> =item html
> 
> Defaults to 1 if $ENV{'REQUEST_METHOD'} is set - 0 otherwise.  If set to
> 1, then the output of the DUMP directive is passed to the html filter
> and encased in "pre" tags.  If set to 0 no html encoding takes place.
> 
> =item Sortkeys, Useqq, Ident, Pad, etc
> 
> Any of the Data::Dumper configuration items may be passed.
> 
> =back
> 
> 
> 
diff -r Template-Toolkit-2.19/lib/Template/Manual/Directives.pod Template-Toolkit-2.19-mine/lib/Template/Manual/Directives.pod
2175d2174
<     
2176a2176,2196
> =item DUMP
> 
> DUMP inserts a Data::Dumper printout of the variable or expression.
> If no argument is passed it will dump the entire contents of the
> current variable stash (with private keys removed).
> 
> The output also includes the current file and line number that the
> DUMP directive was called from.
> 
> See the DUMP configuration option for ways to customize and control
> the output available to the DUMP directive.
> 
>     [% DUMP %] # dump entire stash
> 
>     [% DUMP 1 + 2 %] # dump expressions
> 
>     [% DUMP a, b, c %] # dump multiple variables
> 
>     [% DUMP {c => 'C'} %] # dump constructors
> 
>     [% DUMP foo bar => 'baz' %] # dump positional and named arguments
diff -r Template-Toolkit-2.19/lib/Template/Parser.pm Template-Toolkit-2.19-mine/lib/Template/Parser.pm
715a716
>     $self->{ TEXT   } = \$text;
diff -r Template-Toolkit-2.19/parser/Grammar.pm.skel Template-Toolkit-2.19-mine/parser/Grammar.pm.skel
51a52
>         DUMP
diff -r Template-Toolkit-2.19/parser/Parser.yp Template-Toolkit-2.19-mine/parser/Parser.yp
120a121
>         |   DUMP args               { $factory->dump($_[2], $_[0]->{'FILE'}, ${$_[0]->{'LINE'}}, $_[0]->{'TEXT'}) }

Reply via email to