Improving Perl debugger variable output

TL;DR: Drop my .perldb file in your home directory for a much nicer debugger experience.

The kindest thing I can say about the built-in Perl debugger is that it doesn't drink even though it's old enough to. Using it is painful but there are many things you can do to make it nicer. Heck, I even had syntax highlighting working once.

One of my major pet peeves with the debugger has been how it dumps variable data. Have you ever used it and typed "x $dbic_object" or "r" to return from a method and gotten hundreds of lines of near useless output spewing across the screen? To make matters worse, it takes a long time to dump all of that, making the slow debugger even slower than normal. It's very frustrating. Here's how to fix it.

When running the debugger, Perl loads a script named perl5db.pl and internally, when it needs to dump some variables to the terminal, it runs some code which looks like this (edited for clarity):

# If main::dumpValue isn't here, get it.
do 'dumpvar.pl' || die $@
    unless defined &main::dumpValue;

# must detect sigpipe failures  - not catching
# then will cause the debugger to die.
eval { main::dumpValue(@vars); };

# The die doesn't need to include the $@, because
# it will automatically get propagated for us.
if ($@) {
    die unless $@ =~ /dumpvar print failed/;
}

If you read that carefully, you'll realize that if there's a dumpValue() function in main::, that's what the debugger will use to dump out your variables. The old dumpvar.pl code was written back when 5.001 was still around and fortunately shoves things in the dumpvar package, but we still have dumpValue() littering main::.

However, we can make life much easier with this. By creating your own .perldb file in your home directory (I have a fully documented example here), you can add this to it:

# use a different package in case you need to
# define other helper functions here
package My::Debugger;

use Data::Printer sort_keys => 1, colored => 1;

# this is usually set by dumpvars.pl (called from the debugger). But if it's
# already defined, the debugger uses our version
sub ::dumpValue {
    my ( $value, $maxdepth ) = @_;
    p $value;
}

With that, you'll get nice, clean Data::Printer output (or whatever you want to put in there).

2 Comments

Thanks for sharing this!

I have adopted your .perldb, and I like it a lot. With a one line change it also works in an Emacs perldb session (yes, I'm guilty of not only using the debugger, but also Emacs):

haj@hajdesktop:~/devel/tools$ diff -U0 /tmp/.perldb home/.perldb
--- /tmp/.perldb        2019-02-25 19:07:03.128088404 +0100
+++ home/.perldb        2019-02-25 19:06:56.752902812 +0100
@@ -113 +113 @@
-      unless $DB::already_curly_curly_v++;
+      unless $ENV{INSIDE_EMACS} || $DB::already_curly_curly_v++;

Emacs shows the current source in a window, which collides with the 'v' command - but also makes it unneccessary.

Leave a comment

About Ovid

user-pic Freelance Perl/Testing/Agile consultant and trainer. See http://www.allaroundtheworld.fr/ for our services. If you have a problem with Perl, we will solve it for you. And don't forget to buy my book! http://www.amazon.com/Beginning-Perl-Curtis-Poe/dp/1118013840/