Subject: | Allow a max WIDTH for Table diffs |
The attached patch implements a WIDTH option for Text::Diff::Table
in order to limit the total table width to a given number of characters
(e.g. the terminal width). Please feel free to review and/or adapt this
patch according to your style, I'd be happy to see the feature in a new
release of Text-Diff.
Cheers,
Marek
diff -ruN Text-Diff-0.35/MANIFEST Text-Diff-0.35p1/MANIFEST
--- Text-Diff-0.35/MANIFEST 2002-07-14 14:52:16.000000000 +0200
+++ Text-Diff-0.35p1/MANIFEST 2005-09-05 09:31:56.813815000 +0200
@@ -10,3 +10,4 @@
t/keygen.t
t/outputs.t
t/table.t
+t/table_w.t
diff -ruN Text-Diff-0.35/lib/Text/Diff/Table.pm Text-Diff-0.35p1/lib/Text/Diff/Table.pm
--- Text-Diff-0.35/lib/Text/Diff/Table.pm 2002-08-27 19:57:58.000000000 +0200
+++ Text-Diff-0.35p1/lib/Text/Diff/Table.pm 2005-09-05 09:45:49.753744000 +0200
@@ -2,13 +2,13 @@
=head1 NAME
- Text::Diff::Table - Text::Diff plugin to generate "table" format output
+Text::Diff::Table - Text::Diff plugin to generate "table" format output
=head1 SYNOPSIS
use Text::Diff;
- diff \@a, $b { STYLE => "Table" };
+ diff \@a, $b, { STYLE => "Table" };
=head1 DESCRIPTION
@@ -71,7 +71,7 @@
@ISA = qw( Text::Diff::Base Exporter );
@EXPORT_OK = qw( expand_tabs );
-$VERSION = 1.2;
+$VERSION = 1.3;
use strict;
use Carp;
@@ -346,25 +346,94 @@
if defined $cols->[$i] && length $cols->[$i] > $w[$i];
}
}
+ my $WIDTH = $options->{WIDTH};
- my %fmts = $four_column_mode
- ? (
+ my %fmts;
+ if($four_column_mode) {
+ if($WIDTH) {
+ # scale it - in 0 and 2 we have the numbers, 1 and 3 are the lines
+ # we need 10 chars for separators and whitespace
+ my $lw = $WIDTH - 7 - $w[0] -$w[2];
+ my $ls = $w[1] + $w[3];
+ $w[1] = int($w[1]*$lw/$ls);
+ $w[3] = int($w[3]*$lw/$ls);
+ %fmts = (
+ "=" => "| %$w[0]s|%-$w[1]s| %$w[2]s|%-$w[3]s|\n",
+ "A" => "* %$w[0]s|%-$w[1]s* %$w[2]s|%-$w[3]s|\n",
+ "B" => "| %$w[0]s|%-$w[1]s* %$w[2]s|%-$w[3]s*\n",
+ "*" => "* %$w[0]s|%-$w[1]s* %$w[2]s|%-$w[3]s*\n",
+ );
+ } else {
+ %fmts = (
"=" => "| %$w[0]s|%-$w[1]s | %$w[2]s|%-$w[3]s |\n",
"A" => "* %$w[0]s|%-$w[1]s * %$w[2]s|%-$w[3]s |\n",
"B" => "| %$w[0]s|%-$w[1]s * %$w[2]s|%-$w[3]s *\n",
"*" => "* %$w[0]s|%-$w[1]s * %$w[2]s|%-$w[3]s *\n",
- )
- : (
+ );
+ }
+ } else { # three-column mode
+ if($WIDTH) {
+ # scale it - in 0 we have the numbers, 1 and 2 are the lines
+ # we need 9 chars for separators and whitespace
+ my $lw = $WIDTH - 5 - $w[0];
+ my $ls = $w[1] + $w[2];
+ $w[1] = int($w[1]*$lw/$ls);
+ $w[2] = int($w[2]*$lw/$ls);
+ %fmts = (
+ "=" => "| %$w[0]s|%-$w[1]s|%-$w[2]s|\n",
+ "A" => "* %$w[0]s|%-$w[1]s|%-$w[2]s|\n",
+ "B" => "| %$w[0]s|%-$w[1]s|%-$w[2]s*\n",
+ "*" => "* %$w[0]s|%-$w[1]s|%-$w[2]s*\n",
+ );
+ } else {
+ %fmts = (
"=" => "| %$w[0]s|%-$w[1]s |%-$w[2]s |\n",
"A" => "* %$w[0]s|%-$w[1]s |%-$w[2]s |\n",
"B" => "| %$w[0]s|%-$w[1]s |%-$w[2]s *\n",
"*" => "* %$w[0]s|%-$w[1]s |%-$w[2]s *\n",
- );
+ );
+ }
+ }
$fmts{bar} = sprintf $fmts{"="}, "", "", "", "" ;
$fmts{bar} =~ s/\S/+/g;
$fmts{bar} =~ s/ /-/g;
- return join( "",
+ my $ret;
+ if($WIDTH) {
+ if($four_column_mode) {
+ $ret = join( "",
+ map {
+ sprintf( $fmts{$_->[-1]},
+ $_->[0],
+ defined $_->[1] && length($_->[1]) > $w[1] ? substr($_->[1],0,$w[1]-1).">" : $_->[1],
+ $_->[2],
+ defined $_->[3] && length($_->[3]) > $w[3] ? substr($_->[3],0,$w[3]-1).">" : $_->[3]
+ )
+ } (
+ ["bar"],
+ @heading_lines,
+ @heading_lines ? ["bar"] : (),
+ @{$self->{ELTS}},
+ )
+ );
+ } else { # three-column mode
+ $ret = join( "",
+ map {
+ sprintf( $fmts{$_->[-1]},
+ $_->[0],
+ defined $_->[1] && length($_->[1]) > $w[1] ? substr($_->[1],0,$w[1]-1).">" : $_->[1],
+ defined $_->[2] && length($_->[2]) > $w[2] ? substr($_->[2],0,$w[2]-1).">" : $_->[2]
+ )
+ } (
+ ["bar"],
+ @heading_lines,
+ @heading_lines ? ["bar"] : (),
+ @{$self->{ELTS}},
+ )
+ );
+ }
+ } else { # no WIDTH specified
+ $ret = join( "",
map {
sprintf( $fmts{$_->[-1]}, @$_ )
} (
@@ -373,11 +442,24 @@
@heading_lines ? ["bar"] : (),
@{$self->{ELTS}},
),
- );
-
+ );
+ }
@{$self->{ELTS}} = [];
+ return $ret;
}
+=head1 OPTIONS
+
+The table diff allows to speficy a C<WIDTH> option:
+
+ $d = diff($a, $b, { STYLE => 'Table', WIDTH => 80 });
+
+The resulting table will not exceed the given width. Please note that
+approx. 5 characters are required for the table layout, and another
+2-6 for the line numbers. The line column widths are distributed
+according to the ratio of the longest line in each column. If a line
+is longer than the column width, the last character is C<E<gt>> to
+indicate that the line continues.
=head1 LIMITATIONS
diff -ruN Text-Diff-0.35/t/general.t Text-Diff-0.35p1/t/general.t
--- Text-Diff-0.35/t/general.t 2001-12-16 13:42:15.000000000 +0100
+++ Text-Diff-0.35p1/t/general.t 2005-09-05 08:21:58.442755000 +0200
@@ -126,8 +126,8 @@
warn "# diff options: $diff_opts\n" ;
warn "# my options: $Diff_opts\n" ;
## Merge the outputs using A::D
- my @E = split /^/g, $expect ;
- my @G = split /^/g, $output ;
+ my @E = split /^/m, $expect ;
+ my @G = split /^/m, $output ;
my $w = length "Expected" ;
for ( @E, @G ) {
s/\n/\\n/g ;
diff -ruN Text-Diff-0.35/t/table_w.t Text-Diff-0.35p1/t/table_w.t
--- Text-Diff-0.35/t/table_w.t 1970-01-01 01:00:00.000000000 +0100
+++ Text-Diff-0.35p1/t/table_w.t 2005-09-05 09:31:21.226898000 +0200
@@ -0,0 +1,101 @@
+#!/usr/local/bin/perl -w
+
+use strict ;
+use Test ;
+use Text::Diff ;
+
+sub t($$$$) {
+ my ( $a, $b, $wid, $exp ) = @_;
+ my $d = diff \$a, \$b, { STYLE => "Table", WIDTH => $wid };
+
+ ## Older Test.pms don't support ok( $foo, qr// );
+ if($d eq $exp) {
+ ok(1);
+ } else {
+ warn "\nGot:\n$d\nExpected:\n$exp\n";
+ ok(0);
+ }
+}
+
+my $t1 = <<"EOT";
+This is
+some text
+that has a line which is quite longer than the other lines.
+EOT
+my $t2 = <<"EOT";
+This is
+some text
+that has another line which is quite longer than the other lines.
+EOT
+
+my $u1 = <<'EOT';
+# we iterate over all *.c files
+for c in *.c do
+ # first we print the file name
+ echo $c
+ # calculate the base name
+ b=`basename $c .c`
+ # compile it
+ gcc -o $b.o -c $c
+done
+EOT
+
+my $u2 = <<'EOT';
+for c in *.c do
+ # calculate the base name
+ b=`basename $c .c`
+ # compile it and print success message
+ gcc -o $b.o -c $c && echo "$c compiled OK"
+done
+EOT
+
+my @tests = (
+ sub { t $t1, $t2, 0, <<"EOT"
++--+-------------------------------------------------------------+-------------------------------------------------------------------+
+| 1|This is |This is |
+| 2|some text |some text |
+* 3|that has a line which is quite longer than the other lines. |that has another line which is quite longer than the other lines. *
++--+-------------------------------------------------------------+-------------------------------------------------------------------+
+EOT
+ },
+ sub { t $t1, $t2, 40, <<"EOT"
++--+----------------+-----------------+
+| 1|This is |This is |
+| 2|some text |some text |
+* 3|that has a line>|that has another>*
++--+----------------+-----------------+
+EOT
+ },
+ sub { t $u1, $u2, 0, <<'EOT'
++--+----------------------------------+--+----------------------------------------------+
+* 1|# we iterate over all *.c files * | |
+| 2|for c in *.c do | 1|for c in *.c do |
+* 3| # first we print the file name * | |
+* 4| echo $c * | |
+| 5| # calculate the base name | 2| # calculate the base name |
+| 6| b=`basename $c .c` | 3| b=`basename $c .c` |
+* 7| # compile it * 4| # compile it and print success message *
+* 8| gcc -o $b.o -c $c * 5| gcc -o $b.o -c $c && echo "$c compiled OK" *
+| 9|done | 6|done |
++--+----------------------------------+--+----------------------------------------------+
+EOT
+ },
+ sub { t $u1, $u2, 60, <<'EOT'
++--+---------------------+--+-----------------------------+
+* 1|# we iterate over al>* | |
+| 2|for c in *.c do | 1|for c in *.c do |
+* 3| # first we print t>* | |
+* 4| echo $c * | |
+| 5| # calculate the ba>| 2| # calculate the base name |
+| 6| b=`basename $c .c` | 3| b=`basename $c .c` |
+* 7| # compile it * 4| # compile it and print suc>*
+* 8| gcc -o $b.o -c $c * 5| gcc -o $b.o -c $c && echo >*
+| 9|done | 6|done |
++--+---------------------+--+-----------------------------+
+EOT
+ }
+) ;
+
+plan tests => scalar @tests ;
+
+$_->() for @tests ;