in reply to Re^2: $. - smarter than you might think
in thread $. - smarter than you might think

heh.. that makes me think about a $SIG{__DIE__} handler which not only says harshly "Can't do method foo in context bar in file quux line 1024" or such, but prints the 3 lines above and below the error as well...
don't talk nonsense at blah.pl line 23. 21 learn('nothing'); 22 sub blah (\[&]) { 23 warn "don't talk nonsense"; > 24 $_[0]->(); 25 } 26 sub learn { 27 my $self->teach(shift); Can't use string ("bar") as a subroutine ref while "strict refs" in us +e at blah.pl line 24.

I discovered this playing with your code, btw. Thanks!

cheers,
--shmem

#!/usr/bin/perl use strict; $SIG{__DIE__} = sub { if(my ($d) = $_[0] =~ /line (\d+)/) { seek DATA,0,0; while(<DATA>) { if($. == $d) { warn '> '.$..' '.$_; } else { warn ' '.$..' '.$_ if ($. > $d - 4) && ($. < $d + 4); } } } }; my $foo = 'bar'; blah($foo); learn('nothing'); sub blah (\[&]) { warn "don't talk nonsense"; $_[0]->(); } sub learn { my $self->teach(shift); warn "got it"; } __END__
hmm.. why does it succeed to compile and run whilst calling blah() with a scalar and not a subref?

_($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                              /\_¯/(q    /
----------------------------  \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

Replies are listed 'Best First'.
Re^4: $. - smarter than you might think
by radiantmatrix (Parson) on Jun 26, 2006 at 15:56 UTC

    Ok, I played with your code and came up with a modification of my own:

    local $SIG{__DIE__} = sub { my ($d) = ( $_[0] =~ /line (\d+)\.$/ ); unless ($d) { print STDERR $_[0]; return; } my $context = 3; #number of context lines seek DATA,0,0; while(<DATA>) { next if $. < ($d-$context); #cycle until context starts warn ($. == $d ? '>' : ' ') #mark line if it contains the error .sprintf('%4d ',$.) #use 4-place line numbers (alignment) .$_; #show code on line last if $. > ($d+$context); #move on once we've finished context } };

    The actual run-time efficiency on long code will be helped by the last if.. line: there's no reason to keep doing I/O once your context has been exhausted.

    The other modifications are largely maintenance-minded:

    1. variable for number of context lines makes it easier to change your mind about context later;
    2. using the (?:) syntax allows me to have all formatting done in one place, making it easier to change the format of printed lines at will;

    I also fixed one potential bug in your regex: you would have matched any 'line \d+' in the string -- I could break your code by die('I had a problem reading the data file at line 12'). You'd see the context of your code around line 12, but the relevant code might be around line 60 or something. The new regex takes the match at the end of the message.

    Updates:

    • 2006-06-26 : trailing paren crept in, removed -- thanks to shmem for noticing

    <radiant.matrix>
    A collection of thoughts and links from the minds of geeks
    The Code that can be seen is not the true Code
    I haven't found a problem yet that can't be solved by a well-placed trebuchet
      Hey, good on ye... it's always nice to see bad hacks smoothened into a reasonable thing.

      radiantmatrix ++ if $self->($points_left).

      But! you have an extra ) on line two of your code ;) And if would get picky, I'd rather write warn +($. == $d ? '>' : ' ') than print STDERR. Flavours :)

      thx & greets,
      --shmem

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s,/,($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e,e && print}