use Term::ReadKey;
use Term::ANSIColor qw(:constants);
use Getopt::Std;
local( $opt_p, $opt_P );
getopts( "p:P:" );
$light_pattern = $opt_p || "";
$heavy_pattern = $opt_P || "\\b";
$infile = "enum.h";
open( DATA, $infile ) || die "can't open $infile: $!\n";
$category = "";
while( <DATA> )
{
chop;
s s s/#.*//;
next unless /\S/; next unless /\w/;
if ( m/^enum\s+(\S+)/ )
{
$category = $1;
$data{ $category }{ i } = 0;
}
else
{
s/,//;
( $term, undef, $i ) = split;
$string = $term;
if ( defined $i && $i =~ m/^\d+$/ )
{
$data{ $category }{ i } = $i;
}
else
{
$i = $data{ $category }{ i };
}
$data{ $category }{ array }{ $i } = $string;
$data{ $category }{ i }++;
}
}
$let = "0";
foreach $cat ( sort keys %data )
{
$letters{ $let } = $cat;
$let++;
$let = "A" if $let eq "10";
$let = "a" if $let eq "AA";
}
@sort_lets = sort keys %letters;
foreach $let ( @sort_lets )
{
push @key, "$let - $letters{ $let }";
}
$klen = 0;
foreach $k ( @key )
{
$lk = length $k;
$klen = $lk if $lk > $klen;
}
$klen += 1;
$klen = 20 if $klen > 20;
@bkey = @key;
foreach $k ( @bkey )
{
if ( length $k < $klen )
{
$k .= " " x ($klen - length $k);
}
else
{
$k = substr( $k, 0, $klen - 1 );
$k .= " ";
}
}
$ntpl = int 80/$klen;
while ( @bkey )
{
push @kd, join "", @bkey[0..$ntpl-1], "\n";
splice @bkey, 0, $ntpl;
}
foreach $file ( @ARGV )
{
open IN, $file or die "can't open $file: $!\n";
@buff = <IN>;
$numlines = @buff;
@save_buff = @buff;
@lines_changed = ();
LINE:
for( $line = 0; $line < $numlines; $line++ )
{
if ( $light_pattern && $buff[ $line ] !~ m/$light_pattern/io )
{
next LINE;
}
$target = $buff[ $line ];
%poslist = ();
while ( $target =~ m/$heavy_pattern(\d+)\b/go )
{
$number = $1;
$pos = pos( $target ) - length $number;
$pre = $`;
next if $pre =~ m#//#;
next if $pre =~ m#[\-+*/%] ?$#;
next if $number eq "0" && $pre =~ m/you ?\[ ?$/;
next if $number eq "1" && $pre =~ m/\D-$/;
$poslist{ $pos } = $number;
}
$longer = 0;
foreach $pos ( sort { $a <=> $b } keys %poslist )
{
$number = $poslist{ $pos };
$nl = length $number;
print "\n";
print YELLOW, @buff[ $line-8..$line-1];
print GREEN, substr( $target, 0, $pos+$longer );
print CYAN, substr( $target, $pos+$longer, $nl );
print GREEN, substr( $target, $pos+$longer+$nl );
print YELLOW, @buff[ $line+1..$line+8];
print "\n";
print RESET;
print @kd;
print "\n";
print GREEN, "$file ", BLUE, "$line ", YELLOW, "replace? ";
print RESET;
if ( ! $do_all )
{
ReadMode('cbreak');
$ans = ReadKey(0);
ReadMode('normal');
print $ans;
}
else
{
$ans = $do_all;
}
if ( defined $letters{ $ans } )
{
print "\n";
$list = $letters{ $ans };
$rep = $data{$list}{array}{ $number };
if ( $rep )
{
substr( $target, $pos+$longer, $nl ) = $rep;
$longer += length( $rep );
$longer -= $nl;
print RED, $target;
print RESET;
push @lines_changed, $line;
}
else
{
print BLINK, RED, "###### trouble! ######\n";
print RESET;
}
}
elsif ( $ans eq "#" )
{
$more = <STDIN>;
print $more;
chop $more;
$cmd = substr $more, 0, 1;
if ( $cmd eq "u" )
{
print "\n";
if ( @lines_changed )
{
$line_changed = pop @lines_changed;
$buff[ $line_changed ] = $save_buff[ $line_changed ];
$line = $line_changed;
redo LINE;
}
else
{
redo;
}
}
elsif ( $cmd eq "l" )
{
$newline = substr $more, 1;
$newline += 0;
$line = $newline if $newline;
redo LINE;
}
elsif ( $cmd eq "s" )
{
$saving = 1;
last LINE;
}
elsif ( $cmd eq "a" )
{
$do_all = substr $more, 1;
print "Really answer with $do_all? ";
$yn = <STDIN>;
if ( $yn !~ m/^yes$/ )
{
$do_all = "";
}
redo;
}
elsif ( $cmd eq "q" )
{
exit;
}
}
else
{
if ( $ans =~ m/\S/ )
{
redo;
}
}
}
$buff[ $line ] = $target;
}
close IN;
if ( @lines_changed )
{
$bak = "$file.bak";
if ( rename( $file, $bak ) )
{
$outfile = $file;
}
else
{
$outfile = "Z$file";
print "***** printing changes to $outfile *****\n";
}
open OUT, "> $outfile" or die "can't open $outfile: $!\n";
print OUT @buff;
close OUT;
}
exit if $saving;
}