App-sdif
view release on metacpan or search on metacpan
script/sdif view on Meta::CPAN
=> sub { $_->boundary = $_[1] ? 'word' : '' } ;
has '+cdifopts'
=> sub { push @cdifopts, shellwords $_[1] } ;
has '+ignore_case'
=> sub { push @{$app->diffopts}, '-i'; push @cdifopts, '-i' } ;
has '+ignore_space_change'
=> sub { push @{$app->diffopts}, '-b'; push @cdifopts, '-w' } ;
has '+ignore_all_space'
=> sub { push @{$app->diffopts}, '-w'; push @cdifopts, '-w' } ;
has '+ignore_blank_lines'
=> sub { push @{$app->diffopts}, '-B' } ;
has '+c' => sub { push @{$app->diffopts}, '-c' } ;
has '+u' => sub { push @{$app->diffopts}, '-u' } ;
has '+context' => sub { push @{$app->diffopts}, '-C' . $_[1] } ;
has '+unified' => sub { push @{$app->diffopts}, '-U' . $_[1] } ;
has nocolor => 'no-color' , action => sub { $app->color = 'never' } ;
has nocdif => 'no-cdif' , action => sub { $app->cdif = undef } ;
has mecab => '!' , action => sub { $app->unit = $_[1] ? 'mecab' : undef } ;
has '+ambiguous' => sub {
if ($_[1] =~ /^(?:wide|full)/) {
$Text::VisualWidth::PP::EastAsian = 1;
Text::ANSI::Fold->configure(ambiguous => 'wide');
}
} ;
has '+help' => sub { usage() } ;
has '+version' => sub { print "$version\n"; exit 0 } ;
has '+man' => sub { pod2usage {-verbose => 2} } ;
} no Getopt::EX::Hashed;
$app = Getopt::EX::Hashed->new() or die;
my @SAVEDARGV = @ARGV;
use Getopt::EX::Long qw(:DEFAULT Configure ExConfigure);
ExConfigure BASECLASS => [ "App::sdif", "Getopt::EX" ];
Configure "bundling";
$app->getopt or usage({status => 1});
warn "\@ARGV = (@SAVEDARGV)\n" if $app->debug;
$App::sdif::Util::NO_WARNINGS = $app->lenience;
use Text::VisualWidth::PP qw(vwidth);
use Text::ANSI::Fold qw(ansi_fold :constants); {
Text::ANSI::Fold->configure(padding => 1,
expand => 1,
tabstop => $app->tabstop);
}
$app->visible->{ht} //= 1 if $app->tabstyle;
if ($app->visible->{ht}) {
Text::ANSI::Fold->configure(
tabstyle => $app->tabstyle,
map { $_->[0] => unicode($_->[1]) }
grep { $_->[1] }
[ tabhead => $app->tabhead ],
[ tabspace => $app->tabspace ],
);
}
sub unicode {
my $char = shift or return undef;
if ($char =~ /^\X$/) {
$char;
} else {
eval qq["\\N{$char}"] or die "$!";
}
}
if ($app->margin > 0) {
if ($app->runin and $app->margin < $app->runin) {
die "margin must be >= runin\n";
}
Text::ANSI::Fold->configure(
linebreak => LINEBREAK_ALL,
margin => $app->margin,
runin => $app->runin // $app->margin,
runout => $app->runout // $app->margin,
);
}
my %colormap = do {
my $col = $app->{256} ? 0 : 1;
pairmap { $a => (ref $b eq 'ARRAY') ? $b->[$col] : $b } (
UNKNOWN => "" ,
OCOMMAND => [ "555/010" , "GS" ],
NCOMMAND => [ "555/010" , "GS" ],
MCOMMAND => [ "555/010" , "GS" ],
OFILE => [ "551/010D" , "GDS" ],
NFILE => [ "551/010D" , "GDS" ],
MFILE => [ "551/010D" , "GDS" ],
OMARK => [ "010/444" , "G/W" ],
NMARK => [ "010/444" , "G/W" ],
MMARK => [ "010/444" , "G/W" ],
UMARK => "" ,
OLINE => [ "220" , "Y" ],
NLINE => [ "220" , "Y" ],
MLINE => [ "220" , "Y" ],
ULINE => "" ,
OTEXT => [ "K/454" , "G" ],
NTEXT => [ "K/454" , "G" ],
MTEXT => [ "K/454" , "G" ],
UTEXT => "" ,
NOTICE => "R" ,
);
};
use Getopt::EX::Colormap;
$Getopt::EX::Colormap::NO_RESET_EL = 1;
use constant SGR_RESET => "\e[m";
my $color_handler = Getopt::EX::Colormap
->new(HASH => \%colormap)
->load_params(@{$app->colormap});
$colormap{OUMARK} ||= $colormap{UMARK} || $colormap{OMARK};
$colormap{NUMARK} ||= $colormap{UMARK} || $colormap{NMARK};
$colormap{OULINE} ||= $colormap{ULINE} || $colormap{OLINE};
$colormap{NULINE} ||= $colormap{ULINE} || $colormap{NLINE};
for (
[ $app->unknowncolor => q/UNKNOWN/ ],
script/sdif view on Meta::CPAN
=back
=item B<-->[B<no->]B<prefix>
Understand prefix for diff output including B<git> B<--graph> option.
True by default.
=item B<--prefix-pattern>=I<pattern>
Specify prefix pattern in regex. Default pattern is:
(?:\| )*(?: )?
This pattern matches B<git> graph style and whitespace indented diff
output.
=item B<-->[B<no->]B<lenience>
Suppress warning message for unexpected input from diff command. True
by default.
=item B<--limit> I<key>=I<value>
Set resource limits. Available keys are:
=over 4
=item B<line>=I<#>
Limit the number of lines displayed for add/delete sections. When a
diff section contains only additions or only deletions and the number
of lines exceeds this value, only the first I<#> lines are shown and
the rest are omitted with a message indicating the number of omitted
lines. This is useful for suppressing long diffs caused by large file
additions or deletions, for example when browsing C<git log -p>
output.
=item B<length>=I<#>
Truncate lines longer than I<#> characters before display processing.
Default is 10000. Extremely long lines, such as SVG data with
embedded base64 images, can make display processing very slow. Set to
0 to disable this limit.
=back
=item B<--visible> I<charname>=[0,1]
=item B<--tabhead>=I<char>
=item B<--tabspace>=I<char>
Visualize characters. Currently only C<ht> (horizontal tab) is
supported. Each horizontal tab character is converted to B<tabhead>
and following B<tabspace> characters. They can be specified by
B<--tabhead> and B<--tabspace> option.
$ sdif --visible ht=1 --tabhead=T --tabspace=.
If the option value is longer than single character, it is evaluated
as unicode name.
$ sdif --visible ht=1 \
--tabhead="MEDIUM SHADE" \
--tabspace="LIGHT SHADE"
See L<https://www.unicode.org/charts/charindex.html> for Unicode
names.
B<cdif> shows non-space control characters visible by default. See
L<cdif/--visible>.
=item B<--tabstyle>=[C<space>,C<dot>,C<symbol>,C<shade>,C<bar>,C<dash>...]
=item B<--ts>=...
Option B<--tabstyle> (or B<--ts>) allow to set B<--tabhead> and
B<--tabspace> characters at once according to the given style name.
Select from C<space>, C<dot>, C<symbol>, C<shade>, C<bar>, C<dash> and
others. See L<Text::ANSI::Fold/tabstyle> for available styles.
Multiple styles can be mixed up like C<symbol,space>. In this case,
tabhead and tabspace are taken from C<symbol> and C<space> style
respectively.
Setting tabstyle implies C<ht> being visible. If you want to set
tabstyle by default, but don't want to make tab visible always,
disable it explicitly.
option default --tabstyle=symbol,space --visible ht=0
Then you can enable it at the time of execution.
$ sdif --visible ht=1
=item B<--tabstop>=I<n>
Specify tab stop. Default is 8.
=item B<--colormap>=I<colormap>, B<--cm>=I<colormap>
Basic I<colormap> format is :
FIELD=COLOR
where the FIELD is one from these :
OLD NEW MERGED UNCHANGED
--------- --------- --------- ---------
OCOMMAND NCOMMAND MCOMMAND : Command line
OFILE NFILE MFILE : File name
OMARK NMARK MMARK UMARK : Mark
OLINE NLINE MLINE ULINE : Line number
OTEXT NTEXT MTEXT UTEXT : Text
If UMARK and/or ULINE is empty, OMARK/NMARK and/or OLINE/NLINE are
used instead.
You can make multiple fields same color joining them by = :
FIELD1=FIELD2=...=COLOR
Also wildcard can be used for field name :
*CHANGE=BDw
Multiple fields can be specified by repeating options
script/sdif view on Meta::CPAN
--light
--green
--cmy
--mono
--dark
--dark-green
--dark-cmy
--dark-mono
=head1 ENVIRONMENT
Environment variable B<SDIFOPTS> is used to set default options.
=head1 AUTHOR
=over
=item Kazumasa Utashiro
=item L<https://github.com/kaz-utashiro/sdif-tools>
=back
=head1 LICENSE
Copyright 1992-2026 Kazumasa Utashiro
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=head1 SEE ALSO
L<cdif(1)>, L<watchdiff(1)>
L<Getopt::EX::Colormap>
L<Getopt::EX::termcolor>
L<App::sdif::colors>
L<https://taku910.github.io/mecab/>
L<App::ansicolumn>
L<App::Greple::xlate>
=cut
# LocalWords: perldoc colormap autocolor termcolor onword cdifopts
# LocalWords: mecab CJK diffopts colortable Unicode OCOMMAND cdif
# LocalWords: NCOMMAND OFILE MCOMMAND NFILE MFILE OMARK NMARK MMARK
# LocalWords: UMARK OLINE NLINE MLINE ULINE OTEXT NTEXT MTEXT UTEXT
# LocalWords: Cyan RGB SDIFOPTS Kazumasa Utashiro watchdiff sdif
# LocalWords: sdiff diff sdifrc CMY cmy macOS iTerm XTerm runin
# LocalWords: runout regex lenience tabhead tabspace unicode cyan
# LocalWords: tabstyle tabstop perl
( run in 2.753 seconds using v1.01-cache-2.11-cpan-cdf2f3d4e48 )