App-sdif
view release on metacpan or search on metacpan
script/cdif view on Meta::CPAN
if ($app->colordump) {
print $color_handler->colormap(
name => '--changeme', option => '--colormap');
exit;
}
sub color {
$color_handler->color(@_);
}
my $prefix_re = do {
if ($app->prefix) {
qr/$app->{prefix_pattern}/;
} else {
"";
}
};
my $DIFF;
my $OLD;
my $NEW;
if ($app->rcs) {
my $rcsfile = shift || usage("No RCS filename\n\n");
$DIFF = "$diff @diffopts @rcsopt $rcsfile|";
} elsif (@ARGV == 2) {
($OLD, $NEW) = splice(@ARGV, 0, 2);
$DIFF = "$diff @diffopts $OLD $NEW |";
} elsif (@ARGV < 2) {
$DIFF = shift || '-';
} else {
usage("Arguments error.\n\n") if @ARGV;
}
warn "DIFF = \"$DIFF\"\n" if $debug{f};
my %func = do {
my $col = $app->color ? 0 : 1;
pairmap { $a => $b->[$col] } (
DELETE => [ sub { color("DELETE", @_) }, \&bd ],
APPEND => [ sub { color("APPEND", @_) }, \&bd ],
OLD => [ sub { color("OCHANGE", @_) }, \&ul ],
NEW => [ sub { color("NCHANGE", @_) }, \&ul ],
UNKNOWN => [ sub { color("UNKNOWN", @_) }, undef ],
);
};
my $w_pattern = do {
if ($app->unit =~ /^char/) {
qr/\X/s;
} else {
my $w = $app->unit eq 'letter' ? '' : '_';
qr{
\p{Han} | \p{InHiragana}+ | \p{InKatakana}+ |
[$w\p{Latin}]+ |
[$w\p{Hang}]+ |
[$w\p{Cyrillic}]+ |
[$w\p{Arabic}]+ |
[$w\p{Thai}]+ |
\d+ |
# (\p{Punct})\g{-1}* |
[\h\r\f]*\n | \s+ | (\X)\g{-1}*
}x;
}
};
##
## Converter/Effector function for visible characters
##
my($converter, $effector);
use Getopt::EX::LabeledParam;
Getopt::EX::LabeledParam
->new(HASH => \%opt_visible)
->load_params (@{$app->visible});
if (my @names = grep $opt_visible{$_}, keys %opt_visible) {
my @chars = map $visible{$_}->[0], @names;
my %hash = map { @$_ } values %visible;
my $re = do { local $" = ''; qr/[\Q@chars\E]/ };
my $sub0 = sub { s/($re)/$hash{$1}/g };
my $sub1 = sub { $_[0] =~ s/($re)/$hash{$1}/gr };
my $sub2 = sub {
my $mark_re = shift;
for (@_) {
$_ // next;
s{^$mark_re\K(?=.*$re)(.*\R?)}{
$sub1->($1);
}mge;
}
};
$converter = $sub2;
if (my $color = $colormap{'VISIBLE'}) {
my $s = ansi_code($color);
my $e = ansi_code($color =~ s/(?=.)/~/gr); # cancel the effect
my $symbols = join('',
map { $visible{$_}->[-1] =~ s/\s+//gr }
@names);
$effector = sub { s/([\Q$symbols\E]+)/${s}${1}${e}/g };
}
}
##
## Temporary files
##
use Command::Run::Tmpfile;
my $T1 = Command::Run::Tmpfile->new;
my $T2 = Command::Run::Tmpfile->new;
##
## Total statistic info
##
my %stat;
@stat{'a', 'd', 'c', 'anl', 'dnl', 'cnl'} = (0, 0, 0, 0, 0, 0);
@stat{'anlb', 'dnlb', 'cnlb'} = (0, 0, 0);
open(DIFF, $DIFF) || die "$DIFF: $!\n";
binmode DIFF, ":encoding(utf8)";
my $stdout = IO::Divert->new;
sub sprintln { map { s/(?<=[^\n])\z/\n/r } @_ }
sub println { print sprintln @_ }
sub print_lxl {
script/cdif view on Meta::CPAN
println $old if $old and $app->show_old;
println $del if $del;
println $new if $new and $app->show_new;
}
#
# diff -c
#
elsif (/^\*\*\* ([\d,]+) \*\*\*\*\r?$/) {
my $left = $1;
print_command($_);
my(@old, @new);
my $oline = range($left);
@old = read_diffc(*DIFF, $oline);
my $new;
if (@old and $old[0] =~ /^--- /) {
$new = shift @old;
@old = ("");
} else {
$new = <DIFF>;
}
my $dline = map { /^-/mg } @old;
if ($new =~ /^--- ([\d,]+) ----$/) {
my $right = $1;
my $nline = range($right);
if (@old == 1 and $old[0] ne "" and $oline - $dline == $nline) {
@new = ("");
} else {
@new = read_diffc(*DIFF, $nline);
}
if ($converter) {
$converter->(qr/[\-\+\!\ ][ \t]/, @old, @new);
}
my $mark_re = qr/![ \t]/;
for my $i (keys @old) {
my $cmark = "! ";
if ($i % 2) {
compare(\$old[$i], \$new[$i], $mark_re) if $app->unit;
}
if ($app->color) {
$old[$i] =~ s{^([\-\!][ \t])(.*)}{
color("OMARK", $1) . color("OTEXT", $2)
}mge;
$new[$i] =~ s{^([\+\!][ \t])(.*)}{
color("NMARK", $1) . color("NTEXT", $2)
}mge;
}
}
}
println @old if $app->show_old;
println $new;
println @new if $app->show_new;
}
#
# diff --combined (generic)
#
elsif (m{^
(?<prefix> $prefix_re)
(?<command>
(?<mark> \@{2,} ) [ ]
(?<lines> (?: [-+]\d+(?:,\d+)? [ ] ){2,} )
\g{mark}
(?s:.*)
)
}x) {
my($prefix, $command, $lines) = @+{qw(prefix command lines)};
my $column = length $+{mark};
my @lines = map {
$_ eq ' ' ? 1 : int $_
} $lines =~ /\d+(?|,(\d+)|( ))/g;
if (@lines != $column) {
print;
next;
}
my($divert, %read_opt);
if ($prefix) {
$read_opt{prefix} = $prefix;
$divert = IO::Divert->new(FINAL => sub { s/^/$prefix/mg });
}
print_command($command);
my @buf = read_unified \%read_opt, *DIFF, @lines;
state @mark_re;
my $mark_re = $mark_re[$column] //= do {
my $mark = '.' x ($column - 1);
qr/$mark/;
};
if ($converter) {
map { $converter->($mark_re, @$_) }
map { $_->lists }
@buf;
}
for my $buf (@buf) {
my @result = compare_unified($column, $buf, $mark_re);
if (@result == 3) {
$app->show_new or splice @result, 2, 1;
$app->show_old or splice @result, 1, 1;
}
println @result;
}
}
#
# conflict marker
#
elsif (/^<<<<<<<\s+(.*)/) {
CONFLICT:
{
my $c1 = $_;
my @old = read_until { /^=======$/ } *DIFF;
my $c2 = pop @old // do {
print $c1, @old;
last;
};
my @new = read_until { /^>>>>>>>\s+(.*)/ } *DIFF;
( run in 1.224 second using v1.01-cache-2.11-cpan-d7a12ab2c7f )