Text-WordDiff
view release on metacpan or search on metacpan
lib/Text/WordDiff.pm view on Meta::CPAN
# Append to the scalar reference.
my $out_ref = $out_handler;
$out_handler = sub { $$out_ref .= shift };
}
elsif ( $type eq 'ARRAY' ) {
# Push each item onto the array.
my $out_ref = $out_handler;
$out_handler = sub { push @$out_ref, shift };
}
elsif ( $type eq 'GLOB' || UNIVERSAL::isa( $out_handler, 'IO::Handle' )) {
# print to the file handle.
my $output_handle = $out_handler;
$out_handler = sub { print $output_handle shift };
}
else {
# D'oh!
croak "Unrecognized output type: $type";
}
# Instantiate the diff object, along with any options.
my $diff = Algorithm::Diff->new(@seqs, delete $opts->{DIFF_OPTS});
# Load the style class and instantiate an instance.
my $style = delete $opts->{STYLE} || 'ANSIColor';
$style = __PACKAGE__ . "::$style" if exists $styles{$style};
eval "require $style" or die $@ unless $style->can('new');
$style = $style->new($opts) if !ref $style;
# Run the diff.
my $hunks = 0;
$out_handler->($style->file_header());
while ($diff->Next) {
$hunks++;
$out_handler->( $style->hunk_header() );
# Output unchanged items.
if (my @same = $diff->Same) {
$out_handler->( $style->same_items(@same) );
}
# Output deleted and inserted items.
else {
if (my @del = $diff->Items(1)) {
$out_handler->( $style->delete_items(@del) );
}
if (my @ins = $diff->Items(2)) {
$out_handler->( $style->insert_items(@ins) );
}
}
$out_handler->( $style->hunk_footer() );
}
$out_handler->( $style->file_footer() );
return defined $output ? $output : $hunks;
}
package Text::WordDiff::Base;
sub new {
my ($class, $opts) = @_;
return bless { %{$opts} } => $class;
}
sub file_header {
my $self = shift;
my $fn1 = $self->filename_a;
my $fn2 = $self->filename_b;
return '' unless defined $fn1 && defined $fn2;
my $p1 = $self->filename_prefix_a;
my $t1 = $self->mtime_a;
my $p2 = $self->filename_prefix_b;
my $t2 = $self->mtime_b;
return "$p1 $fn1" . (defined $t1 ? "\t" . localtime $t1 : '') . "\n"
. "$p2 $fn2" . (defined $t2 ? "\t" . localtime $t2 : '') . "\n"
;
}
sub hunk_header { return '' }
sub same_items { return '' }
sub insert_items { return '' }
sub delete_items { return '' }
sub hunk_footer { return '' }
sub file_footer { return '' }
sub filename_a { return shift->{FILENAME_A} }
sub filename_b { return shift->{FILENAME_B} }
sub mtime_a { return shift->{MTIME_A} }
sub mtime_b { return shift->{MTIME_B} }
sub filename_prefix_a { return shift->{FILENAME_PREFIX_A} }
sub filename_prefix_b { return shift->{FILENAME_PREFIX_B} }
1;
__END__
##############################################################################
=head1 Name
Text::WordDiff - Track changes between documents
=head1 Synopsis
use Text::WordDiff;
my $diff = word_diff 'file1.txt', 'file2.txt', { STYLE => 'HTML' };
my $diff = word_diff \$string1, \$string2, { STYLE => 'ANSIColor' };
my $diff = word_diff \*FH1, \*FH2; \%options;
my $diff = word_diff \&reader1, \&reader2;
my $diff = word_diff \@records1, \@records2;
# May also mix input types:
my $diff = word_diff \@records1, 'file_B.txt';
=head1 Description
This module is a variation on the lovely L<Text::Diff|Text::Diff> module.
Rather than generating traditional line-oriented diffs, however, it generates
word-oriented diffs. This can be useful for tracking changes in narrative
documents or documents with very long lines. To diff source code, one is still
( run in 0.336 second using v1.01-cache-2.11-cpan-ec4f86ec37b )