Integrating TextMate with the Perl debugger

brian_d_foy on 2008-01-19T18:36:00

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.


Here's a better .perldb

AndyArmstrong on 2008-01-19T18:14:10

This .perldb adds an option called 'animate' that controls TextMate synchronisation. Normally TextMate will only sync on lines that the debugger displayes. Turn animate on

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;
}

Awesome!

yDNA Barak on 2008-01-20T04:23:59

This is just hella cool. Thanks, Andy!

N.B.: Users may need to chmod 644 ~/.perldb to get this working correctly (depending on their default umask).