From 7638bb031bca4cd5b9d9fd9c846a8783d326140c Mon Sep 17 00:00:00 2001 From: Pragmatic Software Date: Tue, 16 Jun 2015 21:51:09 -0700 Subject: [PATCH] Fix interactive-editing chained commands --- modules/compiler_vm/languages/_default.pm | 770 +++++++++++----------- 1 file changed, 386 insertions(+), 384 deletions(-) diff --git a/modules/compiler_vm/languages/_default.pm b/modules/compiler_vm/languages/_default.pm index 7639bb67..b69c6295 100755 --- a/modules/compiler_vm/languages/_default.pm +++ b/modules/compiler_vm/languages/_default.pm @@ -155,7 +155,7 @@ sub show_output { my $self = shift; my $output = $self->{output}; - unless($self->{got_run} and $self->{copy_code}) { + unless ($self->{got_run} and $self->{copy_code}) { open FILE, ">> log.txt"; print FILE "------------------------------------------------------------------------\n"; print FILE localtime() . "\n"; @@ -164,7 +164,7 @@ sub show_output { close FILE; } - if(exists $self->{options}->{'-paste'} or (defined $self->{got_run} and $self->{got_run} eq "paste")) { + if (exists $self->{options}->{'-paste'} or (defined $self->{got_run} and $self->{got_run} eq 'paste')) { my $cmdline = $self->{cmdline}; $cmdline =~ s/\$sourcefile/$self->{sourcefile}/g; @@ -444,7 +444,7 @@ sub process_cmdline_options { sub process_interactive_edit { my $self = shift; my $code = $self->{code}; - my (@last_code, $save_last_code, $unshift_last_code); + my (@last_code, $unshift_last_code); print " code: [$code]\n" if $self->{debug}; @@ -474,7 +474,6 @@ sub process_interactive_edit { $code = $copy_code; $self->{only_show} = 1; $self->{copy_code} = 1; - $save_last_code = 1; } if($subcode =~ m/^\s*(?:and\s+)?(?:diff|show)\s+(\S+)\s*$/) { @@ -500,425 +499,406 @@ sub process_interactive_edit { exit 0; } - if($subcode =~ m/^\s*(?:and\s+)?diff(?:\s+\S+)?\s*$/i) { - if($#last_code < 1) { - print "$self->{nick}: Not enough recent code to diff.\n" - } else { - use Text::WordDiff; - my $diff = word_diff(\$last_code[1], \$last_code[0], { STYLE => 'Diff' }); - if($diff !~ /(?:|)/) { - $diff = "No difference."; - } else { - $diff =~ s/(.*?)(\s+)<\/del>/$1<\/del>$2/g; - $diff =~ s/(.*?)(\s+)<\/ins>/$1<\/ins>$2/g; - $diff =~ s/((?:(?!).)*)<\/del>\s*((?:(?!).)*)<\/ins>/`replaced $1 with $2`/g; - $diff =~ s/(.*?)<\/del>/`removed $1`/g; - $diff =~ s/(.*?)<\/ins>/`inserted $1`/g; - } + my $prevchange = $last_code[0]; + my @replacements; + my $got_changes = 0; + my $got_sub = 0; + my $got_diff = 0; + my $got_undo = 0; + my $last_keyword; - print "$self->{nick}: $diff\n"; + while($subcode =~ s/^\s*(and)?\s*undo//) { + splice @last_code, 0, 1; + if(not defined $last_code[0]) { + print "$self->{nick}: No more undos remaining.\n"; + exit 0; + } else { + $code = $last_code[0]; + $got_undo = 1; } - exit 0; } - if($subcode =~ m/^\s*(?:and\s+)?(run|paste)\s*$/i) { - $self->{got_run} = lc $1; - if(defined $last_code[0]) { - $code = $last_code[0]; - $self->{only_show} = 0; - } else { - print "$self->{nick}: No recent code to $self->{got_run}.\n"; - exit 0; - } - } else { - my $got_undo = 0; - my $got_sub = 0; + while(1) { + $got_sub = 0; - while($subcode =~ s/^\s*(and)?\s*undo//) { - splice @last_code, 0, 1; - if(not defined $last_code[0]) { - print "$self->{nick}: No more undos remaining.\n"; - exit 0; - } else { - $code = $last_code[0]; - $got_undo = 1; - } - } - - my @replacements; - my $prevchange = $last_code[0]; - my $got_changes = 0; - my $last_keyword; - - while(1) { - $got_sub = 0; - #$got_changes = 0; - - $subcode =~ s/^\s*and\s+'/and $last_keyword '/ if defined $last_keyword; - - if($subcode =~ m/^\s*(and)?\s*remove \s*([^']+)?\s*'/) { - $last_keyword = 'remove'; - my $modifier = 'first'; - - $subcode =~ s/^\s*(and)?\s*//; - $subcode =~ s/remove\s*([^']+)?\s*//i; - $modifier = $1 if defined $1; - $modifier =~ s/\s+$//; - - my ($e, $r) = extract_delimited($subcode, "'"); - - my $text; - - if(defined $e) { - $text = $e; - $text =~ s/^'//; - $text =~ s/'$//; - $subcode = "replace $modifier '$text' with ''$r"; - } else { - print "$self->{nick}: Unbalanced single quotes. Usage: cc remove [all, first, .., tenth, last] 'text' [and ...]\n"; - exit 0; - } - next; - } - - if($subcode =~ s/^\s*(and)?\s*prepend '//) { - $last_keyword = 'prepend'; - $subcode = "'$subcode"; - - my ($e, $r) = extract_delimited($subcode, "'"); - - my $text; - - if(defined $e) { - $text = $e; - $text =~ s/^'//; - $text =~ s/'$//; - $subcode = $r; - - $got_sub = 1; - $got_changes = 1; - - if(not defined $prevchange) { - print "$self->{nick}: No recent code to prepend to.\n"; - exit 0; - } - - $code = $prevchange; - $code =~ s/^/$text /; - $prevchange = $code; - } else { - print "$self->{nick}: Unbalanced single quotes. Usage: cc prepend 'text' [and ...]\n"; - exit 0; - } - next; - } - - if($subcode =~ s/^\s*(and)?\s*append '//) { - $last_keyword = 'append'; - $subcode = "'$subcode"; - - my ($e, $r) = extract_delimited($subcode, "'"); - - my $text; - - if(defined $e) { - $text = $e; - $text =~ s/^'//; - $text =~ s/'$//; - $subcode = $r; - - $got_sub = 1; - $got_changes = 1; - - if(not defined $prevchange) { - print "$self->{nick}: No recent code to append to.\n"; - exit 0; - } - - $code = $prevchange; - $code =~ s/$/ $text/; - $prevchange = $code; - } else { - print "$self->{nick}: Unbalanced single quotes. Usage: cc append 'text' [and ...]\n"; - exit 0; - } - next; - } - - if($subcode =~ m/^\s*(and)?\s*replace\s*([^']+)?\s*'.*'\s*with\s*'.*?'/i) { - $last_keyword = 'replace'; - $got_sub = 1; - my $modifier = 'first'; - - $subcode =~ s/^\s*(and)?\s*//; - $subcode =~ s/replace\s*([^']+)?\s*//i; - $modifier = $1 if defined $1; - $modifier =~ s/\s+$//; - - my ($from, $to); - my ($e, $r) = extract_delimited($subcode, "'"); - - if(defined $e) { - $from = $e; - $from =~ s/^'//; - $from =~ s/'$//; - $from = quotemeta $from; - $from =~ s/\\ / /g; - $subcode = $r; - $subcode =~ s/\s*with\s*//i; - } else { - print "$self->{nick}: Unbalanced single quotes. Usage: cc replace 'from' with 'to' [and ...]\n"; - exit 0; - } - - ($e, $r) = extract_delimited($subcode, "'"); - - if(defined $e) { - $to = $e; - $to =~ s/^'//; - $to =~ s/'$//; - $subcode = $r; - } else { - print "$self->{nick}: Unbalanced single quotes. Usage: cc replace 'from' with 'to' [and replace ... with ... [and ...]]\n"; - exit 0; - } - - given($modifier) { - when($_ eq 'all' ) {} - when($_ eq 'last' ) {} - when($_ eq 'first' ) { $modifier = 1; } - when($_ eq 'second' ) { $modifier = 2; } - when($_ eq 'third' ) { $modifier = 3; } - when($_ eq 'fourth' ) { $modifier = 4; } - when($_ eq 'fifth' ) { $modifier = 5; } - when($_ eq 'sixth' ) { $modifier = 6; } - when($_ eq 'seventh') { $modifier = 7; } - when($_ eq 'eighth' ) { $modifier = 8; } - when($_ eq 'nineth' ) { $modifier = 9; } - when($_ eq 'tenth' ) { $modifier = 10; } - default { print "$self->{nick}: Bad replacement modifier '$modifier'; valid modifiers are 'all', 'first', 'second', ..., 'tenth', 'last'\n"; exit 0; } - } - - my $replacement = {}; - $replacement->{'from'} = $from; - $replacement->{'to'} = $to; - $replacement->{'modifier'} = $modifier; - - push @replacements, $replacement; - next; - } - - if($subcode =~ m/^\s*(and)?\s*s\/.*\//) { - $last_keyword = undef; - $got_sub = 1; - $subcode =~ s/^\s*(and)?\s*s//; - - my ($regex, $to); - my ($e, $r) = extract_delimited($subcode, '/'); - - if(defined $e) { - $regex = $e; - $regex =~ s/^\///; - $regex =~ s/\/$//; - $subcode = "/$r"; - } else { - print "$self->{nick}: Unbalanced slashes. Usage: cc s/regex/substitution/[gi] [and s/.../.../ [and ...]]\n"; - exit 0; - } - - ($e, $r) = extract_delimited($subcode, '/'); - - if(defined $e) { - $to = $e; - $to =~ s/^\///; - $to =~ s/\/$//; - $subcode = $r; - } else { - print "$self->{nick}: Unbalanced slashes. Usage: cc s/regex/substitution/[gi] [and s/.../.../ [and ...]]\n"; - exit 0; - } - - my $suffix; - $suffix = $1 if $subcode =~ s/^([^ ]+)//; - - if(length $suffix and $suffix =~ m/[^gi]/) { - print "$self->{nick}: Bad regex modifier '$suffix'. Only 'i' and 'g' are allowed.\n"; - exit 0; - } - if(defined $prevchange) { - $code = $prevchange; - } else { - print "$self->{nick}: No recent code to change.\n"; - exit 0; - } - - my $ret = eval { - my ($ret, $a, $b, $c, $d, $e, $f, $g, $h, $i, $before, $after); - - if(not length $suffix) { - $ret = $code =~ s|$regex|$to|; - ($a, $b, $c, $d, $e, $f, $g, $h, $i) = ($1, $2, $3, $4, $5, $6, $7, $8, $9); - $before = $`; - $after = $'; - } elsif($suffix =~ /^i$/) { - $ret = $code =~ s|$regex|$to|i; - ($a, $b, $c, $d, $e, $f, $g, $h, $i) = ($1, $2, $3, $4, $5, $6, $7, $8, $9); - $before = $`; - $after = $'; - } elsif($suffix =~ /^g$/) { - $ret = $code =~ s|$regex|$to|g; - ($a, $b, $c, $d, $e, $f, $g, $h, $i) = ($1, $2, $3, $4, $5, $6, $7, $8, $9); - $before = $`; - $after = $'; - } elsif($suffix =~ /^ig$/ or $suffix =~ /^gi$/) { - $ret = $code =~ s|$regex|$to|gi; - ($a, $b, $c, $d, $e, $f, $g, $h, $i) = ($1, $2, $3, $4, $5, $6, $7, $8, $9); - $before = $`; - $after = $'; - } - - if($ret) { - $code =~ s/\$1/$a/g; - $code =~ s/\$2/$b/g; - $code =~ s/\$3/$c/g; - $code =~ s/\$4/$d/g; - $code =~ s/\$5/$e/g; - $code =~ s/\$6/$f/g; - $code =~ s/\$7/$g/g; - $code =~ s/\$8/$h/g; - $code =~ s/\$9/$i/g; - $code =~ s/\$`/$before/g; - $code =~ s/\$'/$after/g; - } - - return $ret; - }; - - if($@) { - my $error = $@; - $error =~ s/ at .* line \d+\.\s*$//; - print "$self->{nick}: $error\n"; - exit 0; - } - - if($ret) { - $got_changes = 1; - } - - $prevchange = $code; - } - - if($got_sub and not $got_changes) { - print "$self->{nick}: No substitutions made.\n"; - exit 0; - } elsif($got_sub and $got_changes) { - next; - } + $subcode =~ s/^\s*and\s+'/and $last_keyword '/ if defined $last_keyword; + if($subcode =~ m/^\s*(?:and\s+)?diff\b/i) { + $got_diff = 1; last; } - if($#replacements > -1) { - use re::engine::RE2 -strict => 1; - @replacements = sort { $a->{'from'} cmp $b->{'from'} or $a->{'modifier'} <=> $b->{'modifier'} } @replacements; + if($subcode =~ m/^\s*(?:and\s+)?(run|paste)\b/i) { + $self->{got_run} = lc $1; + $self->{only_show} = 0; + if ($prevchange) { + $code = $prevchange; + } else { + print "$self->{nick}: No recent code to $self->{got_run}.\n"; + exit 0; + } + } - my ($previous_from, $previous_modifier); + if($subcode =~ m/^\s*(and)?\s*remove \s*([^']+)?\s*'/) { + $last_keyword = 'remove'; + my $modifier = 'first'; - foreach my $replacement (@replacements) { - my $from = $replacement->{'from'}; - my $to = $replacement->{'to'}; - my $modifier = $replacement->{'modifier'}; + $subcode =~ s/^\s*(and)?\s*//; + $subcode =~ s/remove\s*([^']+)?\s*//i; + $modifier = $1 if defined $1; + $modifier =~ s/\s+$//; - if(defined $previous_from) { - if($previous_from eq $from and $previous_modifier =~ /^\d+$/) { - $modifier -= $modifier - $previous_modifier; - } - } + my ($e, $r) = extract_delimited($subcode, "'"); - if(defined $prevchange) { - $code = $prevchange; - } else { - print "$self->{nick}: No recent code to change.\n"; + my $text; + + if(defined $e) { + $text = $e; + $text =~ s/^'//; + $text =~ s/'$//; + $subcode = "replace $modifier '$text' with ''$r"; + } else { + print "$self->{nick}: Unbalanced single quotes. Usage: cc remove [all, first, .., tenth, last] 'text' [and ...]\n"; + exit 0; + } + next; + } + + if($subcode =~ s/^\s*(and)?\s*prepend '//) { + $last_keyword = 'prepend'; + $subcode = "'$subcode"; + + my ($e, $r) = extract_delimited($subcode, "'"); + + my $text; + + if(defined $e) { + $text = $e; + $text =~ s/^'//; + $text =~ s/'$//; + $subcode = $r; + + $got_sub = 1; + $got_changes = 1; + + if(not defined $prevchange) { + print "$self->{nick}: No recent code to prepend to.\n"; exit 0; } - my $ret = eval { - my $got_change; + $code = $prevchange; + $code =~ s/^/$text /; + $prevchange = $code; + } else { + print "$self->{nick}: Unbalanced single quotes. Usage: cc prepend 'text' [and ...]\n"; + exit 0; + } + next; + } - my ($first_char, $last_char, $first_bound, $last_bound); - $first_char = $1 if $from =~ m/^(.)/; - $last_char = $1 if $from =~ m/(.)$/; + if($subcode =~ s/^\s*(and)?\s*append '//) { + $last_keyword = 'append'; + $subcode = "'$subcode"; - if($first_char =~ /\W/) { - $first_bound = '.?'; - } else { - $first_bound = '\b'; - } + my ($e, $r) = extract_delimited($subcode, "'"); - if($last_char =~ /\W/) { - $last_bound = '.?'; - } else { - $last_bound = '\b'; - } + my $text; - if($modifier eq 'all') { - if($code =~ s/($first_bound)$from($last_bound)/$1$to$2/g) { - $got_change = 1; - } - } elsif($modifier eq 'last') { - if($code =~ s/(.*)($first_bound)$from($last_bound)/$1$2$to$3/) { - $got_change = 1; - } - } else { - my $count = 0; - my $unescaped = $from; - $unescaped =~ s/\\//g; - if($code =~ s/($first_bound)$from($last_bound)/if(++$count == $modifier) { "$1$to$2"; } else { "$1$unescaped$2"; }/ge) { - $got_change = 1; - } - } - return $got_change; - }; + if(defined $e) { + $text = $e; + $text =~ s/^'//; + $text =~ s/'$//; + $subcode = $r; - if($@) { - my $error = $@; - $error =~ s/ at .* line \d+\.\s*$//; - print "$self->{nick}: $error\n"; + $got_sub = 1; + $got_changes = 1; + + if(not defined $prevchange) { + print "$self->{nick}: No recent code to append to.\n"; exit 0; } + $code = $prevchange; + $code =~ s/$/ $text/; + $prevchange = $code; + } else { + print "$self->{nick}: Unbalanced single quotes. Usage: cc append 'text' [and ...]\n"; + exit 0; + } + next; + } + + if($subcode =~ m/^\s*(and)?\s*replace\s*([^']+)?\s*'.*'\s*with\s*'.*?'/i) { + $last_keyword = 'replace'; + $got_sub = 1; + my $modifier = 'first'; + + $subcode =~ s/^\s*(and)?\s*//; + $subcode =~ s/replace\s*([^']+)?\s*//i; + $modifier = $1 if defined $1; + $modifier =~ s/\s+$//; + + my ($from, $to); + my ($e, $r) = extract_delimited($subcode, "'"); + + if(defined $e) { + $from = $e; + $from =~ s/^'//; + $from =~ s/'$//; + $from = quotemeta $from; + $from =~ s/\\ / /g; + $subcode = $r; + $subcode =~ s/\s*with\s*//i; + } else { + print "$self->{nick}: Unbalanced single quotes. Usage: cc replace 'from' with 'to' [and ...]\n"; + exit 0; + } + + ($e, $r) = extract_delimited($subcode, "'"); + + if(defined $e) { + $to = $e; + $to =~ s/^'//; + $to =~ s/'$//; + $subcode = $r; + } else { + print "$self->{nick}: Unbalanced single quotes. Usage: cc replace 'from' with 'to' [and replace ... with ... [and ...]]\n"; + exit 0; + } + + given($modifier) { + when($_ eq 'all' ) {} + when($_ eq 'last' ) {} + when($_ eq 'first' ) { $modifier = 1; } + when($_ eq 'second' ) { $modifier = 2; } + when($_ eq 'third' ) { $modifier = 3; } + when($_ eq 'fourth' ) { $modifier = 4; } + when($_ eq 'fifth' ) { $modifier = 5; } + when($_ eq 'sixth' ) { $modifier = 6; } + when($_ eq 'seventh') { $modifier = 7; } + when($_ eq 'eighth' ) { $modifier = 8; } + when($_ eq 'nineth' ) { $modifier = 9; } + when($_ eq 'tenth' ) { $modifier = 10; } + default { print "$self->{nick}: Bad replacement modifier '$modifier'; valid modifiers are 'all', 'first', 'second', ..., 'tenth', 'last'\n"; exit 0; } + } + + my $replacement = {}; + $replacement->{'from'} = $from; + $replacement->{'to'} = $to; + $replacement->{'modifier'} = $modifier; + + push @replacements, $replacement; + next; + } + + if($subcode =~ m/^\s*(and)?\s*s\/.*\//) { + $last_keyword = undef; + $got_sub = 1; + $subcode =~ s/^\s*(and)?\s*s//; + + my ($regex, $to); + my ($e, $r) = extract_delimited($subcode, '/'); + + if(defined $e) { + $regex = $e; + $regex =~ s/^\///; + $regex =~ s/\/$//; + $subcode = "/$r"; + } else { + print "$self->{nick}: Unbalanced slashes. Usage: cc s/regex/substitution/[gi] [and s/.../.../ [and ...]]\n"; + exit 0; + } + + ($e, $r) = extract_delimited($subcode, '/'); + + if(defined $e) { + $to = $e; + $to =~ s/^\///; + $to =~ s/\/$//; + $subcode = $r; + } else { + print "$self->{nick}: Unbalanced slashes. Usage: cc s/regex/substitution/[gi] [and s/.../.../ [and ...]]\n"; + exit 0; + } + + my $suffix; + $suffix = $1 if $subcode =~ s/^([^ ]+)//; + + if(length $suffix and $suffix =~ m/[^gi]/) { + print "$self->{nick}: Bad regex modifier '$suffix'. Only 'i' and 'g' are allowed.\n"; + exit 0; + } + if(defined $prevchange) { + $code = $prevchange; + } else { + print "$self->{nick}: No recent code to change.\n"; + exit 0; + } + + my $ret = eval { + my ($ret, $a, $b, $c, $d, $e, $f, $g, $h, $i, $before, $after); + + if(not length $suffix) { + $ret = $code =~ s|$regex|$to|; + ($a, $b, $c, $d, $e, $f, $g, $h, $i) = ($1, $2, $3, $4, $5, $6, $7, $8, $9); + $before = $`; + $after = $'; + } elsif($suffix =~ /^i$/) { + $ret = $code =~ s|$regex|$to|i; + ($a, $b, $c, $d, $e, $f, $g, $h, $i) = ($1, $2, $3, $4, $5, $6, $7, $8, $9); + $before = $`; + $after = $'; + } elsif($suffix =~ /^g$/) { + $ret = $code =~ s|$regex|$to|g; + ($a, $b, $c, $d, $e, $f, $g, $h, $i) = ($1, $2, $3, $4, $5, $6, $7, $8, $9); + $before = $`; + $after = $'; + } elsif($suffix =~ /^ig$/ or $suffix =~ /^gi$/) { + $ret = $code =~ s|$regex|$to|gi; + ($a, $b, $c, $d, $e, $f, $g, $h, $i) = ($1, $2, $3, $4, $5, $6, $7, $8, $9); + $before = $`; + $after = $'; + } + if($ret) { - $got_sub = 1; - $got_changes = 1; + $code =~ s/\$1/$a/g; + $code =~ s/\$2/$b/g; + $code =~ s/\$3/$c/g; + $code =~ s/\$4/$d/g; + $code =~ s/\$5/$e/g; + $code =~ s/\$6/$f/g; + $code =~ s/\$7/$g/g; + $code =~ s/\$8/$h/g; + $code =~ s/\$9/$i/g; + $code =~ s/\$`/$before/g; + $code =~ s/\$'/$after/g; } - $prevchange = $code; - $previous_from = $from; - $previous_modifier = $modifier; - } + return $ret; + }; - if(not $got_changes) { - print "$self->{nick}: No replacements made.\n"; + if($@) { + my $error = $@; + $error =~ s/ at .* line \d+\.\s*$//; + print "$self->{nick}: $error\n"; exit 0; } + + if ($ret) { + $got_changes = 1; + } + + $prevchange = $code; } - $save_last_code = 1; - - unless($got_undo and not $got_changes) { - $unshift_last_code = 1 unless $copy_code and not $got_changes; + if ($got_sub and not $got_changes) { + print "$self->{nick}: No substitutions made.\n"; + exit 0; + } elsif ($got_sub and $got_changes) { + next; } - if($copy_code and $got_changes) { - $self->{only_show} = 0; + last; + } + + if (@replacements) { + use re::engine::RE2 -strict => 1; + @replacements = sort { $a->{'from'} cmp $b->{'from'} or $a->{'modifier'} <=> $b->{'modifier'} } @replacements; + + my ($previous_from, $previous_modifier); + + foreach my $replacement (@replacements) { + my $from = $replacement->{'from'}; + my $to = $replacement->{'to'}; + my $modifier = $replacement->{'modifier'}; + + if(defined $previous_from) { + if($previous_from eq $from and $previous_modifier =~ /^\d+$/) { + $modifier -= $modifier - $previous_modifier; + } + } + + if(defined $prevchange) { + $code = $prevchange; + } else { + print "$self->{nick}: No recent code to change.\n"; + exit 0; + } + + my $ret = eval { + my $got_change; + + my ($first_char, $last_char, $first_bound, $last_bound); + $first_char = $1 if $from =~ m/^(.)/; + $last_char = $1 if $from =~ m/(.)$/; + + if($first_char =~ /\W/) { + $first_bound = '.?'; + } else { + $first_bound = '\b'; + } + + if($last_char =~ /\W/) { + $last_bound = '.?'; + } else { + $last_bound = '\b'; + } + + if($modifier eq 'all') { + if($code =~ s/($first_bound)$from($last_bound)/$1$to$2/g) { + $got_change = 1; + } + } elsif($modifier eq 'last') { + if($code =~ s/(.*)($first_bound)$from($last_bound)/$1$2$to$3/) { + $got_change = 1; + } + } else { + my $count = 0; + my $unescaped = $from; + $unescaped =~ s/\\//g; + if($code =~ s/($first_bound)$from($last_bound)/if(++$count == $modifier) { "$1$to$2"; } else { "$1$unescaped$2"; }/ge) { + $got_change = 1; + } + } + return $got_change; + }; + + if($@) { + my $error = $@; + $error =~ s/ at .* line \d+\.\s*$//; + print "$self->{nick}: $error\n"; + exit 0; + } + + if($ret) { + $got_sub = 1; + $got_changes = 1; + } + + $prevchange = $code; + $previous_from = $from; + $previous_modifier = $modifier; } - if($got_undo and not $got_changes) { - $self->{only_show} = 1; + if(not $got_changes) { + print "$self->{nick}: No replacements made.\n"; + exit 0; } } - if($save_last_code) { + unless($got_undo and not $got_changes) { + $unshift_last_code = 1 unless $copy_code and not $got_changes; + } + + if ($copy_code and $got_changes) { + $self->{only_show} = 0; + } + + if ($got_undo and not $got_changes) { + $self->{only_show} = 1; + } + + unless (($self->{got_run} or $got_diff) and not $got_changes) { if($unshift_last_code) { unshift @last_code, $code; } @@ -934,6 +914,28 @@ sub process_interactive_edit { close FILE; } + if ($got_diff) { + if($#last_code < 1) { + print "$self->{nick}: Not enough recent code to diff.\n" + } else { + use Text::WordDiff; + my $diff = word_diff(\$last_code[1], \$last_code[0], { STYLE => 'Diff' }); + + if($diff !~ /(?:|)/) { + $diff = "No difference."; + } else { + $diff =~ s/(.*?)(\s+)<\/del>/$1<\/del>$2/g; + $diff =~ s/(.*?)(\s+)<\/ins>/$1<\/ins>$2/g; + $diff =~ s/((?:(?!).)*)<\/del>\s*((?:(?!).)*)<\/ins>/`replaced $1 with $2`/g; + $diff =~ s/(.*?)<\/del>/`removed $1`/g; + $diff =~ s/(.*?)<\/ins>/`inserted $1`/g; + } + + print "$self->{nick}: $diff\n"; + } + exit 0; + } + $self->{code} = $code; }