Better dump output in debugger

I was reading Steve Haryanto's blog post about filtering Data::Dump output and immediately installed Data::Dump. If you use the debugger as often as I do, I recommend you install that module along with DB::Pluggable. That's when the delightful magic starts.

In my $HOME directory, I have a .perldb file which now looks similar to this:

#!/usr/bin/env perl

# Using this is causing the debugger to hang :(
#  - module: BreakOnTestNumber

unless ( $ENV{NOPERLDB} ) {
  eval "use DB::Pluggable; use YAML;";
  die "$0 Can't load db plugin handler: $@" if $@;

  $DB::PluginHandler = DB::Pluggable->new( config => YAML::Load(<<'END') );
global:
  log:
    level: error

plugins:
  - module: Dumper
  - module: StackTraceAsHTML
  - module: TypeAhead
    config:
      type:
        - '{l'
        - '$DB::deep = 10000'
        - 'c'
        - 'use Data::Dump "dumpf"'
        - '*::f = sub { print dumpf(shift, sub { my ($ctx, $oref) = @_; return unless $ctx->class eq "DateTime"; {dump=>qq([$oref])} } ) }'
END

  $DB::PluginHandler->run;
}

Note my very strange TypeAhead configuration. The '{l' tells the perl dubugger to output several lines of context before every debugger prompt (see the extensive debugger commands).

The $DB::deep line merely tells the debugger to allow up to 10,000 levels on the call stack before getting all fussy on me (the default is 100).

The 'c' automatically 'c'ontinues to the breakpoint (in vim, I can set a breakpoint and run the debugger automatically to that line).

It's the next two lines which I love, though:

      - 'use Data::Dump "dumpf"'
      - '*::f = sub { print dumpf(shift, sub { my ($ctx, $oref) = @_; return unless $ctx->class eq "DateTime"; {dump=>qq([$oref])} } ) }'

Those use the new Data::Dump filter and if I have a DateTime object anywhere in a deep data structure, it gets stringified (I may decide to do this with dbic objects, too). Thus, if I have the following data structure:

{ this => 'that', array => [1,2,DateTime->now,3] }

I could do this:

  DB<11> x $result
0  HASH(0xd7f6fd0)
   'array' => ARRAY(0xd8220e0)
      0  1
      1  2
      2  DateTime=HASH(0xd821368)
         'formatter' => undef
         'local_c' => HASH(0xd80fae0)
            'day' => 11
            'day_of_quarter' => 72
            'day_of_week' => 5
            'day_of_year' => 162
            'hour' => 11
            'minute' => 12
            'month' => 6
            'quarter' => 2
            'second' => 29
            'year' => 2010
         'local_rd_days' => 733934
         'local_rd_secs' => 40349
         'locale' => DateTime::Locale::en_US=HASH(0x9810b18)
            'default_date_format_length' => 'medium'
            'default_time_format_length' => 'medium'
            'en_complete_name' => 'English United States'
            'en_language' => 'English'
            'en_territory' => 'United States'
            'id' => 'en_US'
            'native_complete_name' => 'English United States'
            'native_language' => 'English'
            'native_territory' => 'United States'
         'offset_modifier' => 0
         'rd_nanosecs' => 0
         'tz' => DateTime::TimeZone::UTC=HASH(0xd81fce0)
            'name' => 'UTC'
         'utc_rd_days' => 733934
         'utc_rd_secs' => 40349
         'utc_year' => 2011
      3  3
   'this' => 'that'

But I prefer, now, to do this:

  DB<13> ::f $result
{ array => [1, 2, [2010-06-11T11:12:29], 3], this => "that" }

Which do you want to debug?

Note: this requires the recently released Data::Dump 1.16.

Leave a comment

About Ovid

user-pic Have Perl; Will Travel. Freelance Perl/Testing/Agile consultant. Photo by http://www.circle23.com/. Warning: that site is not safe for work. The photographer is a good friend of mine, though, and it's appropriate to credit his work.