App-ccdiff

 view release on metacpan or  search on metacpan

ccdiff  view on Meta::CPAN

		    }
		next;
		}
	    $d1 .= $c;
	    $d2 .= $c;
	    $c =~ s/\S/$chr_eql/g;
	    $x1 .= $c;
	    $x2 .= $c;
	    next;
	    }
	if (@co) {
	    $heu->{old} += scalar @co;
	    $d1 .= $cml.$clr_old;
	    $d1 .= s/\n/$reset\n$clr_old/gr for @co;
	    $d1 .= $reset.$cmr;
	    $x1 .= $_ for map { s/[^\t\r\n]/$cmd/gr } @co;
	    $opt_v and push @h1, map { $opt_U ? charnames::viacode (ord) : unpack "H*"; } @co;
	    }
	if (@cn) {
	    $heu->{new} += scalar @cn;
	    $d2 .= $cml.$clr_new;
	    $d2 .= s/\n/$reset\n$clr_new/gr for @cn;
	    $d2 .= $reset.$cmr;
	    $x2 .= $_ for map { s/[^\t\r\n]/$cma/gr } @cn;
	    $opt_v and push @h2, map { $opt_U ? charnames::viacode (ord) : unpack "H*"; } @cn;
	    }
	}
    $heu->{pct} = ($heu->{old} + $heu->{new}) / (2 * $heu->{same});
    my @d = map { [ split m/(?<=\n)/ => s/\n*\z/\n/r ] } $d1, $d2;
    if ($opt_m) {
	$opt_v > 1 and s/(\S+)/ $1 /g for $x1, $x2;
	s/[ \t]*\n*\z/\n/ for $x1, $x2;
	my @x = map { /\S/ ? [ split m/(?<=\n)/ ] : [] } $x1, $x2;
	foreach my $n (0, 1) {
	    @{$x[$n]} and $d[$n] = [ map {( $d[$n][$_], $x[$n][$_] // "" )} 0 .. (scalar @{$d[$n]} - 1) ];
	    }
	}
    if ($opt_v) {
	$opt_U && $opt_v > 2 and $_ .= sprintf " (U+%06X)", charnames::vianame ($_) for @h1, @h2;
	@h1 and push @{$d[0]}, sprintf " -- ${clr_dbg}verbose$reset : %s\n", join ", " => map { $clr_old.$_.$reset } @h1;
	@h2 and push @{$d[1]}, sprintf " -- ${clr_dbg}verbose$reset : %s\n", join ", " => map { $clr_new.$_.$reset } @h2;
	}
    @d;
    } # subdiff

sub read_rc {
    my $home = $ENV{HOME} || $ENV{USERPROFILE} || $ENV{HOMEPATH};
    foreach my $rcf (
	    "$home/ccdiff.rc",
	    "$home/.ccdiffrc",
	    "$home/.config/ccdiff",
	    ) {
	-s $rcf or next;
	(stat $rcf)[2] & 022 and next;
	open my $fh, "<", $rcf or next;
	while (<$fh>) {
	    my ($k, $v) = (m/^\s*([-\w]+)\s*[:=]\s*(.*\S)/) or next;
	    $rc{ lc $k
	        =~ s{[-_]colou?r$}{}ir
	        =~ s{background}{bg}ir
	        =~ s{^(?:unicode|utf-?8?)$}{utf8}ir
	      } = $v
		=~ s{U\+?([0-9A-Fa-f]{2,7})}{chr hex $1}ger
		=~ s{^(?:no|false)$}{0}ir
		=~ s{^(?:yes|true)$}{-1}ir; # -1 is still true
	    }
	}
    } # read_rc

# Return the known colors from Term::ANSIColor
# Stolen straight from the pm
sub tac_colors {
    my %c256;
    foreach my $r (0 .. 5) {
        foreach my $g (0 .. 5) {
            $c256{lc $_}++ for map {("RGB$r$g$_", "ON_RGB$r$g$_")} 0 .. 5;
	    }
	}
    $c256{lc $_}++ for
      # Basic colors
      qw(
	CLEAR           RESET             BOLD            DARK
	FAINT           ITALIC            UNDERLINE       UNDERSCORE
	BLINK           REVERSE           CONCEALED

	BLACK           RED               GREEN           YELLOW
	BLUE            MAGENTA           CYAN            WHITE
	ON_BLACK        ON_RED            ON_GREEN        ON_YELLOW
	ON_BLUE         ON_MAGENTA        ON_CYAN         ON_WHITE

	BRIGHT_BLACK    BRIGHT_RED        BRIGHT_GREEN    BRIGHT_YELLOW
	BRIGHT_BLUE     BRIGHT_MAGENTA    BRIGHT_CYAN     BRIGHT_WHITE
	ON_BRIGHT_BLACK ON_BRIGHT_RED     ON_BRIGHT_GREEN ON_BRIGHT_YELLOW
	ON_BRIGHT_BLUE  ON_BRIGHT_MAGENTA ON_BRIGHT_CYAN  ON_BRIGHT_WHITE
	),
      # 256 colors
      (map { ("ANSI$_", "ON_ANSI$_") } 0 .. 255),
      (map { ("GREY$_", "ON_GREY$_") } 0 .. 23);

    my $ACV = $Term::ANSIColor::VERSION;
    $ACV < 3.02 and delete @c256{grep m/italic/   => keys %c256};
    $ACV < 4.00 and delete @c256{grep m/rgb|grey/ => keys %c256};
    $ACV < 4.06 and delete @c256{grep m/ansi/     => keys %c256};
    sort keys %c256;
    } # tac_colors

1;

__END__

=encoding utf-8

=head1 NAME

ccdiff - Colored Character diff

=head1 SYNOPSIS

 ccdiff [options] file1|- file2|-
 ccdiff [options] dir1    dir2

ccdiff  view on Meta::CPAN

=item header (-H --header --HC=color --header-color=color)

 header  : 1
 header  : blue_on_white

Defines if a header is displayed above the diff (default is 1), supported
colors are allowed.

If the value is a valid supported color, it will show the header in that
color scheme.  To disable the header set it to C<0> in the RC file or use
C<--no-header> as a command line argument.

=item old-label

=item new-label

Defines the tag(s) in the header for the source file(s)/stream(s).

 App::ccdiff::ccdiff ($left, $right);

 =>

 < *STDIN  Fri Nov  7 10:14:51 2025
 > *STDIN  Fri Nov  7 10:14:51 2025

 App::ccdiff::ccdiff ($left, $right,
    { "old-label" => "OLD", "new-label" => "NEW" });

 =>

 < OLD     Fri Nov  7 10:14:51 2025
 > NEW     Fri Nov  7 10:14:51 2025

=item verbose

 verbose : cyan

Defines the color to be used as color for the verbose tag. The default is
C<cyan>. This color will only be used under C<--verbose>.

The color C<none> is also accepted and disables this color.

Any color accepted by L<Term::ANSIColor> is allowed. Any other color will
result in a warning.

This option may also be specified as

 verbose-color
 verbose_color
 verbose-colour
 verbose_colour

=item utf8 (-U)

 utf8    : yes

Defines whether all I/O is to be interpreted as UTF-8. The default is C<no>.

This option may also be specified as

 unicode
 utf
 utf-8

=item index (-I)

 index   : no

Defines if the position indication for a change chunk is prefixed with an
index number. The default is C<no>. The index is 1-based.

Without this option, the position indication would be like

 5,5c5,5
 19,19d18
 42a42,42

with this option, it would be

 [001] 5,5c5,5
 [002] 19,19d18
 [005] 42a42,42

When this option contains a positive integer, C<ccdiff> will only show the
diff chunk with that index.

=item emacs

 emacs   : no

If this option is yes/true, calling C<ccdiff> with just one single argument,
and that argument being an existing file, the arguments will act as

 $ ccdiff file~ file

if file~ exists.

=item threshold (-t)

 threshold : 2

Defines the number of lines a change block may differ before the fall-back of
horizontal diff to vertical diff.

=item heuristics (-h)

 heuristics : 40

Defines the percentage of character-changes a change block may differ before
the fall-back of horizontal diff to vertical diff. The default is undefined,
meaning no fallback based on heuristics.

=item ellipsis (-e)

 ellipsis : 0

Defines the number of characters to keep on each side of a horizontal-equal
segment. The default is C<0>, meaning to not compress. See also C<chr_eli>.

=item chr_old



( run in 0.527 second using v1.01-cache-2.11-cpan-d7f47b0818f )