#!/usr/bin/perl -w use strict; use Algorithm::Diff qw(traverse_sequences); use Getopt::Std; my ($old_file, $new_file) = @ARGV[-2,-1]; &useage unless ( $old_file and $new_file and -e $old_file and -e $new_file ); # get options and file contents as array refs our ( $opt_b, $opt_c ); getopts('bc'); my $skip_blanks = $opt_b; my $skip_comments = $opt_c; my $old = get( $old_file, $skip_blanks, $skip_comments ); my $new = get( $new_file, $skip_blanks, $skip_comments ); # print out the colour coded diff - common code is black # code in $old_file but not $new_file is red # code in $new_file but not $old_file is green print "
\n\n"; sub get { my ($file, $skip_blanks, $skip_comments ) = @_; my @file; open F, $file or die "Can't read $file: $!"; while (Color Key:\n"; print "".escapeHTML($old_file)."\n"; print "".escapeHTML($new_file)."
\n"; # this is snippet of code originally written by merlyn exactly as posted. # it is the same as his except he forgot to escape the HTML in his example. # traverse_sequences( $old, $new, { # MATCH => sub { print escapeHTML($old->[shift]) }, # DISCARD_A => sub { print "" . escapeHTML($old->[shift])."" }, # DISCARD_B => sub { print "".escapeHTML($new->[shift,shift])."" }, #}); # this is what I (silently) modified it to to demonstrate # to merlyn that I knew another way to do it and can RTFS # this is the same syntax used in the diff sub in the source traverse_sequences( $old, $new, { MATCH => sub { print escapeHTML($old->[$_[0]]) }, DISCARD_A => sub { print "" . escapeHTML($old->[$_[0]])."" }, DISCARD_B => sub { print "".escapeHTML($new->[$_[1]])."" }, }); print "
tags
# s/( {2,})/" " x length $1/eg;
# make the brower bugfix escapes;
s/\x8b//g;
s/\x9b//g;
# make the PERL MONKS escapes (if desired)
# s/\[/[/g;
# s/\]/]/g;
# change newlines to
if desired - not required with
# s/\n/
\n/g;
return $_;
}
sub useage {
print qq(
Useage $0 -[b,c]
-b skip blank lines
-c skip comment only lines
HTML output to STDOUT
);
exit;
}
####
The arguments to C are the two sequences to
traverse, and a callback which specifies the callback functions, like
this:
traverse_sequences( \@seq1, \@seq2,
{ MATCH => $callback_1,
DISCARD_A => $callback_2,
DISCARD_B => $callback_3,
} );
Callbacks are invoked with at least the indices of the two arrows as
their arguments. They are not expected to return any values. If a
callback is omitted from the table, it is not called.
## ##
sub diff
{
my $a = shift; # array ref
my $b = shift; # array ref
my $retval = [];
my $hunk = [];
my $discard = sub { push( @$hunk, [ '-', $_[ 0 ], $a->[$_[0]] ] ) };
my $add = sub { push( @$hunk, [ '+', $_[ 1 ], $b->[$_[1]] ] ) };
my $match = sub { push( @$retval, $hunk ) if scalar(@$hunk); $hunk = [] };
traverse_sequences( $a, $b,
{ MATCH => $match,
DISCARD_A => $discard,
DISCARD_B => $add
}, @_ );
&$match();
return wantarray ? @$retval : $retval;
}