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.315 second using v1.01-cache-2.11-cpan-454fe037f31 )