I've been stepping through a lot of code in the Perl debugger recently. The debugger has a bit of a forbidding reputation but it's not too bad once your muscle memory has got the essential commands down.
Once thing that would really help me though would be to have my text editor (TextMate) track the current debugger file and line. Then, when I wanted to see the code around the current location, I could just flip to my editor instead of hunting around with the debugger's code viewing commands.
TextMate registers a handler for the txmt:// URL scheme that can be used to send it to a particular file, line and column (you can read more about that here).
Mac OS has /usr/bin/open which allows an arbitrary URL (or file or application) to be opened from the command line.
The Perl debugger recognises a function watchfunction, defined in ~/.perldb and calls it for every line it executes.
Throwing all those ingredients together gives us TextMate::JumpTo - a module to remotely control TextMate's current location - and this ~/.perldb file which tells the debugger to sync its position with TextMate:
use TextMate::JumpTo qw(jumpto);
sub afterinit {
$trace |= 4; # Enable watchfunction
# Needed to work out where filenames are relative to
chomp( $base_dir = `pwd` );
}
sub watchfunction {
my ( $package, $file, $line ) = @_;
local $trace = 0;
if ( $file =~ /^\(eval\s+\d+\)\[(.+?):(\d+)\]/ ) {
$file = $1;
$line += $2 - 1;
}
$file = File::Spec->rel2abs( $file, $base_dir );
jumpto( file => $file, line => $line, bg => 1 )
if substr( $file, 0, length( $base_dir ) ) eq $base_dir;
}
Now I just debug normally and any time I want to see the code around the current line I switch to the editor and there it is. It's not quite full editor integration but it immediately makes my life a lot easier.
This
o animate=1
to see an animated display of all lines the debugger executes.
use TextMate::JumpTo qw(jumpto);
use File::Spec;
parse_options( "windowSize=30 " );
sub afterinit {
$trace |= 4; # Enable watchfunction
# Needed to work out where filenames are relative to
chomp( $base_dir = `pwd` );
$option{animate} = 0;
push @options, 'animate';
}
sub watchfunction {
my ( $package, $file, $line ) = @_;
return unless $DB::single || $option{animate};
local $trace = 0;
if ( $file =~/^\(eval\s+\d+\)\[(.+?):(\d+)\]/ ) {
$file = $1;
$line += $2 - 1;
}
$file = File::Spec->rel2abs( $file, $base_dir );
jumpto( file => $file, line => $line, bg => 1 );
return 1;
}
N.B.: Users may need to chmod 644 ~/.perldb
to get this working correctly (depending on their default umask).