├── Talk
├── zws1
├── zws2
├── Umv2.png
├── Umuv2.png
├── hc0
├── hc1
├── 5c5a.uchar
├── e0
├── m0
├── README.lt
├── t0
├── t1
├── ccdiff1
├── m1.csv
├── export.csv
├── m0.csv
├── member.csv
├── README
├── termcap
└── termcap-blue
├── sandbox
├── 30a4cd45-1
├── 30a4cd45-2
├── pm1221078-2
├── pm1221078-1
├── TEST_A.txt
├── TEST_B.txt
├── genxml.pl
├── genMETA.pl
├── test1.xml
├── test2.xml
└── genMETA.pm
├── .aspell.local.pws
├── .whitesource
├── xt
├── 50_manifest.t
├── 10_perm.t
├── 02_pod.t
├── 00_perlversion.t
└── 20_kwalitee.t
├── MANIFEST
├── Files
├── 01_1.txt
├── 01_2.txt
└── git-ccdiff
├── MANIFEST.SKIP
├── .gitignore
├── .releaserc
├── 2lib
├── cpanfile
├── .travis.yml
├── META.yml
├── CONTRIBUTING.md
├── META.json
├── Makefile.PL
├── ChangeLog
├── t
└── 01-no-color.t
├── README.md
├── doc
├── README.md
├── make-doc.pl
├── ccdiff.md
├── ccdiff.man
└── ccdiff.3
└── LICENSE
/Talk/zws1:
--------------------------------------------------------------------------------
1 | A BCDE Fg
2 |
--------------------------------------------------------------------------------
/Talk/zws2:
--------------------------------------------------------------------------------
1 | A BcdEFg
2 |
--------------------------------------------------------------------------------
/sandbox/30a4cd45-1:
--------------------------------------------------------------------------------
1 | A
2 | B
3 |
4 | F
5 | G
6 |
--------------------------------------------------------------------------------
/sandbox/30a4cd45-2:
--------------------------------------------------------------------------------
1 | A
2 | B
3 | C
4 | D
5 | E
6 | F
7 | G
8 |
--------------------------------------------------------------------------------
/Talk/Umv2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tux/App-ccdiff/master/Talk/Umv2.png
--------------------------------------------------------------------------------
/Talk/Umuv2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tux/App-ccdiff/master/Talk/Umuv2.png
--------------------------------------------------------------------------------
/.aspell.local.pws:
--------------------------------------------------------------------------------
1 | personal_ws-1.1 en 7
2 | ascii
3 | bg
4 | ccdiff
5 | idx
6 | NYI
7 | utf
8 | WIP
9 |
--------------------------------------------------------------------------------
/sandbox/pm1221078-2:
--------------------------------------------------------------------------------
1 |
2 | foo-test.work.se
3 |
4 |
--------------------------------------------------------------------------------
/sandbox/pm1221078-1:
--------------------------------------------------------------------------------
1 |
2 | foo.work.se
3 | splat.work.se
4 |
5 |
--------------------------------------------------------------------------------
/.whitesource:
--------------------------------------------------------------------------------
1 | {
2 | "generalSettings": {
3 | "shouldScanRepo": true
4 | },
5 | "checkRunSettings": {
6 | "vulnerableCheckRunConclusionLevel": "failure"
7 | }
8 | }
--------------------------------------------------------------------------------
/xt/50_manifest.t:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | use strict;
4 | use warnings;
5 | use Test::More;
6 |
7 | eval "use Test::DistManifest";
8 | plan skip_all => "Test::DistManifest required for testing MANIFEST" if $@;
9 | manifest_ok ();
10 | done_testing;
11 |
--------------------------------------------------------------------------------
/MANIFEST:
--------------------------------------------------------------------------------
1 | ccdiff
2 | ChangeLog
3 | CONTRIBUTING.md
4 | cpanfile
5 | Files/01_1.txt
6 | Files/01_2.txt
7 | Files/git-ccdiff
8 | lib/App/ccdiff.pm
9 | LICENSE
10 | Makefile.PL
11 | MANIFEST
12 | META.json
13 | META.yml
14 | README.md
15 | t/01-no-color.t
16 |
--------------------------------------------------------------------------------
/xt/10_perm.t:
--------------------------------------------------------------------------------
1 | eval "use Test::PAUSE::Permissions";
2 |
3 | if ($@ || $] < 5.018) {
4 | print "1..0 # No perl permission check for old releases\n";
5 | exit 0;
6 | }
7 |
8 | BEGIN { $ENV{RELEASE_TESTING} = 1; }
9 |
10 | all_permissions_ok ("HMBRAND");
11 |
--------------------------------------------------------------------------------
/Talk/hc0:
--------------------------------------------------------------------------------
1 | #: src/common/textevents.h:13
2 | msgid "%C22*%O$tCannot join %C22$1 %O(%C20You are banned%O)."
3 | msgstr "%C22*%O$tΑδυναμία εισαγωγής %C22$1 %O(%C20Είστε μπλοκαρισμένος%Ο)."
4 |
5 | #: src/common/textevents.h:19
6 | msgid "%C29*%O$tCapabilities acknowledged: %C29$2%O"
7 |
--------------------------------------------------------------------------------
/Talk/hc1:
--------------------------------------------------------------------------------
1 | #: src/common/textevents.h:13
2 | msgid "%C22*%O$tCannot join %C22$1 %O(%C20You are banned%O)."
3 | msgstr "%C22*%O$tΑδυναμία εισαγωγής %C22$1 %O(%C20Είστε μπλοκαρισμένος%O)."
4 |
5 | #: src/common/textevents.h:19
6 | msgid "%C29*%O$tCapabilities acknowledged: %C29$2%O"
7 |
--------------------------------------------------------------------------------
/Files/01_1.txt:
--------------------------------------------------------------------------------
1 | Lorem ipsum dolor sit amet, graecis pertinax at ius,
2 | id vix cibo omittantur, et impetus offendit convenire
3 | usu. Ad duo posse theophrastus, vim in accumsan
4 | efficiantur, sed in congue decore. Ex nullam iudicabit
5 | vim. Quo ad modo dolores. Duo ne iuvaret contentiones,
6 | vim ut mollis scripta.
7 |
--------------------------------------------------------------------------------
/Files/01_2.txt:
--------------------------------------------------------------------------------
1 | Lorem ipsum dolor sit amet, graecis pertinax at ius,
2 | id vix cibo omittantur, et impetus offendit convenire
3 | usu. Ad duo posse theophrastus. Vim in accumsan
4 | efficiantur, sed in congue decore. Ex nullam iudicabit
5 | vim. Quo ad modo dolores. Duo ne iuvaret contentiones,
6 | vim ut mollis scripta.
7 |
--------------------------------------------------------------------------------
/Talk/5c5a.uchar:
--------------------------------------------------------------------------------
1 | $ uchar -v ς%Ο
2 | ς U003c2 \N{GREEK SMALL LETTER FINAL SIGMA}
3 | % U00025 \N{PERCENT SIGN}
4 | Ο U0039f \N{GREEK CAPITAL LETTER OMICRON}
5 |
6 | $ uchar -v ς%O
7 | ς U003c2 \N{GREEK SMALL LETTER FINAL SIGMA}
8 | % U00025 \N{PERCENT SIGN}
9 | O U0004f \N{LATIN CAPITAL LETTER O}
10 |
11 |
--------------------------------------------------------------------------------
/MANIFEST.SKIP:
--------------------------------------------------------------------------------
1 | ^\.aspell.local.pws
2 | ^\.git.*
3 | ^\.whitesource
4 | ^2lib
5 | ^blib
6 | ^doc
7 | ^sandbox
8 | ^Talk
9 | [gbx]z$
10 | MANIFEST.SKIP
11 | ^Makefile$
12 | ^pm_to
13 | ^MYMETA
14 | ^\.releaserc
15 | ^\.travis.yml
16 | ^xt/
17 | \.tmp$
18 | ^\.test_info\.
19 |
20 | # These are TODO
21 | ^foo.$
22 | Files/01_[34].txt
23 |
--------------------------------------------------------------------------------
/xt/02_pod.t:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | use Test::More;
4 |
5 | eval "use Test::Pod::Links";
6 | plan skip_all => "Test::Pod::Links required for testing POD Links" if $@;
7 | eval {
8 | no warnings "redefine";
9 | no warnings "once";
10 | *Test::XTFiles::all_files = sub { "ccdiff"; };
11 | };
12 | Test::Pod::Links->new->all_pod_files_ok;
13 |
--------------------------------------------------------------------------------
/Talk/e0:
--------------------------------------------------------------------------------
1 | S
2 | a
3 | t
4 |
5 | D
6 | e
7 | c
8 |
9 | 1
10 | 8
11 |
12 | 0
13 | 7
14 | :
15 | 0
16 | 8
17 | :
18 | 3
19 | 3
20 |
21 | 1
22 | 9
23 | 9
24 | 8
25 | ,
26 | I
27 | .
28 | O
29 | .
30 | D
31 | .
32 | U
33 | .
34 | ,
35 | ,
36 | 7
37 | 5
38 | 6
39 | 1
40 | 9
41 | 4
42 | 4
43 | 3
44 | 3
45 | ,
46 | 1
47 | 4
48 | 4
49 | 2
50 | 5
51 | 3
52 | 9
53 |
54 |
--------------------------------------------------------------------------------
/Talk/m0:
--------------------------------------------------------------------------------
1 | S
2 | a
3 | t
4 |
5 | D
6 | e
7 | c
8 |
9 | 1
10 | 8
11 |
12 | 0
13 | 7
14 | :
15 | 0
16 | 0
17 | :
18 | 3
19 | 3
20 |
21 | 1
22 | 9
23 | 9
24 | 3
25 | ,
26 | I
27 | .
28 | O
29 | .
30 | D
31 | .
32 | U
33 | .
34 | ,
35 | ,
36 | 7
37 | 5
38 | 6
39 | 1
40 | 9
41 | 4
42 | 4
43 | 3
44 | 3
45 | ,
46 | 1
47 | 4
48 | 4
49 | 2
50 | 5
51 | 3
52 | 9
53 |
54 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | blib
2 | cover_db
3 | Makefile
4 | MYMETA.yml
5 | MYMETA.json
6 | pm_to_blib
7 | *.tar.gz
8 | *.tbz
9 | *.tgz
10 | *.txz
11 | *.old
12 | *.gcov
13 | *.gcda
14 | *.gcno
15 | .perlcriticrc
16 | lib/App/ccdiff.pm
17 | App-cc*
18 | xx*
19 | valgrind.log
20 | pod2htm*
21 | nytprof*
22 | tmp/*
23 | sandbox/cover_db*
24 | Talk/*.mp4
25 | Talk/*.jpg
26 | Talk/diff-so-fancy*
27 | *-git
28 |
--------------------------------------------------------------------------------
/xt/00_perlversion.t:
--------------------------------------------------------------------------------
1 | #!/pro/bin/perl
2 |
3 | use strict;
4 | use warnings;
5 |
6 | eval "use Test::More 0.93";
7 | eval "use Test::MinimumVersion";
8 | if ($@) {
9 | print "1..0 # Test::MinimumVersion required for compatability tests\n";
10 | exit 0;
11 | }
12 |
13 | all_minimum_version_ok ("5.014.000", { paths => [
14 | "ccdiff", glob ("t/*"), glob ("xt/*"), glob ("*.PL"),
15 | ]});
16 |
17 | done_testing ();
18 |
--------------------------------------------------------------------------------
/Talk/README.lt:
--------------------------------------------------------------------------------
1 | 0. Configuration
2 |
3 | cat ~/.config/ccdiff
4 |
5 | 1. Manual
6 |
7 | ccdiff --help
8 | ccdiff --man
9 | ccdiff --info
10 |
11 | 2. Verbosity
12 |
13 | ccdiff hc?
14 | ccdiff hc? -v
15 |
16 | 3. Indices
17 |
18 | ccdiff m* -I
19 | ccdiff m* -I1
20 | ccdiff m* -I1 -v
21 |
22 | 4. List colors
23 |
24 | ccdiff --list-colors
25 | dis_colors
26 |
27 | 5. Availability
28 |
29 | cpan App::ccdiff
30 |
--------------------------------------------------------------------------------
/.releaserc:
--------------------------------------------------------------------------------
1 | cpan_user HMBRAND
2 | automated_testing 1
3 | skip_kwalitee 1
4 | skip_manifest 1
5 | skip_prereqs 1
6 | skip_dist 1
7 | allow_glob_in_perls 1
8 | perls /pro/bin/perl\
9 | :/usr/bin/perl\
10 | :/media/Tux/perls/bin/perl5.1[468]*\
11 | :/media/Tux/perls/bin/perl5.[234][02468]*\
12 | :/media/Tux/perls/bin/perl5.41*\
13 | :/media/Tux/perls/bin/tperl5.1[468]*\
14 | :/media/Tux/perls/bin/tperl5.[234][02468]*\
15 | :/media/Tux/perls/bin/tperl5.41*
16 |
--------------------------------------------------------------------------------
/2lib:
--------------------------------------------------------------------------------
1 | #!/pro/bin/perl
2 |
3 | use 5.012001;
4 | use warnings;
5 |
6 | open my $fh, "<", "ccdiff";
7 | my $src = do { local $/; <$fh> };
8 | close $fh;
9 |
10 | my ($vsn) = ($src =~ m/^(our .VERSION\s*=.*)/m);
11 | $vsn =~ s/ - [0-9]{8}//;
12 |
13 | mkdir "lib";
14 | mkdir "lib/App";
15 | open $fh, ">", "lib/App/ccdiff.pm";
16 | #say $fh "package App::ccdiff;\n\n$vsn\n\nuse strict;\nuse warnings\n\n1;\n\n",
17 | # $src =~ s{.*(?=__END__\n)}{}sr;
18 | print $fh $src;
19 | close $fh;
20 |
--------------------------------------------------------------------------------
/sandbox/TEST_A.txt:
--------------------------------------------------------------------------------
1 | ||2.0|A|1|2009-08-16T16:30:00|1|2009|ingreso|Una sola exhibición|350.00|5.25|397.25|ISP900909Q88|Industrias del Sur Poniente, S.A. de C.V.|Alvaro Obregón|37|3|Col. Roma Norte|México|Cuauhtémoc|Distrito Federal|México|06700|Pino Suarez|23|Centro|Monterrey|Monterrey|Nuevo Léon|México|95460|CAUR390312S87|Rosa María Calderón Uriegas|Topochico|52|Jardines del Valle|Monterrey|Monterrey|Nuevo León|México|95465|10|Caja|Vasos decorados|20.00|200|1|pieza|Charola metálica|150.00|150|IVA|15.00|52.50||
--------------------------------------------------------------------------------
/sandbox/TEST_B.txt:
--------------------------------------------------------------------------------
1 | ||2.0|A|1|2009-08-16T16:30:00|1|2009|ingreso|Una sola exhibición|350.00|5.25|397.25|ISP900909Q88|Industrias del Sur Poniente, S.A. de C.V.|Alvaro Obregón|37|3|Col. Roma Norte|México|Cuauhtémoc|Distrito Federal|México|06700|Pino Suarez|23|Centro|Monterrey|Monterrey|Nuevo Léon|México|95460|CAUR390312S87|Rosa María Calderón Uriegas|Topochico|52|Jardines del Valle|Monterrey|Monterrey|Nuevo León|México|95465|10|Caja|Vasos decorados|20.00|200|1|pieza|Charola metálica|150.00|150|IVA|15.00|52.50||
--------------------------------------------------------------------------------
/sandbox/genxml.pl:
--------------------------------------------------------------------------------
1 | #!/pro/bin/perl
2 |
3 | use 5.016003;
4 | use warnings;
5 |
6 | my $n = 0;
7 | my @chr = map { chr } 0x20, 0x23, 0x2b, 0x30..0x3b, 0x3f..0x5a, 0x5e..0x6a;
8 | my $x = qq{\nccdiff};
9 | $x .= join "" => map { qq{}.$chr[int rand @chr]."" } 0..600;
10 | $x .= qq{};
11 |
12 | open my $fh, ">", "test1.xml";
13 | say $fh $x;
14 | close $fh;
15 | open $fh, ">", "test2.xml";
16 | say $fh $x =~ s/"569">\K./!/r;
17 | close $fh;
18 |
--------------------------------------------------------------------------------
/cpanfile:
--------------------------------------------------------------------------------
1 | requires "Algorithm::Diff" => "1.1901";
2 | requires "Getopt::Long";
3 | requires "List::Util";
4 | requires "Term::ANSIColor";
5 | requires "charnames";
6 |
7 | recommends "Algorithm::Diff" => "1.201";
8 | recommends "Algorithm::Diff::XS" => "0.04";
9 |
10 | on "configure" => sub {
11 | requires "ExtUtils::MakeMaker";
12 |
13 | recommends "ExtUtils::MakeMaker" => "7.22";
14 |
15 | suggests "ExtUtils::MakeMaker" => "7.72";
16 | };
17 |
18 | on "build" => sub {
19 | requires "Config";
20 | };
21 |
22 | on "test" => sub {
23 | requires "Capture::Tiny";
24 | requires "Test::More";
25 |
26 | recommends "Capture::Tiny" => "0.24";
27 |
28 | suggests "Capture::Tiny" => "0.50";
29 | };
30 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: perl
2 | os:
3 | - linux
4 | dist: trusty
5 | perl:
6 | - "5.30"
7 | - "5.28"
8 | - "5.26"
9 | - "5.26-shrplib"
10 | - "5.24"
11 | - "5.22"
12 | - "5.20"
13 | - "5.18"
14 | - "5.16"
15 | - "5.14"
16 | env:
17 | global:
18 | - AUTOMATED_TESTING=1
19 | install:
20 | - cpanm --quiet --installdeps --with-all-features --notest . || true
21 | - cpanm --quiet Getopt::Long || true
22 | - cpanm --quiet Term::ANSIColor || true
23 | - cpanm --quiet Test::More || true
24 | - cpanm --quiet Algorithm::Diff || true
25 | - cpanm --quiet Capture::Tiny || true
26 | - perl ./2lib
27 | notifications:
28 | irc:
29 | channels:
30 | - "irc.perl.org#csv"
31 | on_success: always
32 | on_failure: always
33 |
--------------------------------------------------------------------------------
/Files/git-ccdiff:
--------------------------------------------------------------------------------
1 | #!/pro/bin/perl
2 |
3 | # With this file as git-ccdiff in your $PATH
4 | #
5 | # git config --global diff.tool ccdiff
6 | # git config --global difftool.prompt false
7 | # git config --global difftool.ccdiff.cmd 'ccdiff --utf-8 -u -r $LOCAL $REMOTE'
8 | # git difftool 5c5a~..5c5a
9 | # ->
10 | # git ccdiff 5c5a
11 |
12 | use 5.014002;
13 | use warnings;
14 |
15 | my @opt;
16 |
17 | my @git = qw( git difftool );
18 | for (@ARGV) {
19 | if (m/^-/) { # an option
20 | push @opt => $_;
21 | }
22 | elsif (-f) { # a file
23 | push @git => $_;
24 | }
25 | elsif (m/^[0-9a-fA-F]{4,32}$/) { # a commit
26 | push @git => "$_~1..$_";
27 | }
28 | else {
29 | push @git => $_;
30 | }
31 | }
32 |
33 | #use Data::Peek;
34 | #DDumper \@ARGV;
35 |
36 | @opt and $ENV{CCDIFF_OPTIONS} = join " " => @opt;
37 | system @git;
38 |
--------------------------------------------------------------------------------
/Talk/t0:
--------------------------------------------------------------------------------
1 |
2 | :
3 | V
4 | a
5 | =
6 | \
7 | E
8 | [
9 | 0
10 | m
11 | :
12 | V
13 | c
14 | =
15 | \
16 | E
17 | [
18 | 0
19 | ;
20 | 3
21 | 3
22 | m
23 | :
24 | V
25 | e
26 | =
27 | \
28 | E
29 | [
30 | 0
31 | ;
32 | 4
33 | m
34 | :
35 | V
36 | g
37 | =
38 | \
39 | E
40 | [
41 | 0
42 | ;
43 | 4
44 | ;
45 | 3
46 | 6
47 | m
48 | :
49 | \
50 |
51 |
52 | :
53 | V
54 | i
55 | =
56 | \
57 | E
58 | [
59 | 0
60 | ;
61 | 3
62 | 7
63 | ;
64 | 4
65 | 1
66 | m
67 | :
68 | V
69 | k
70 | =
71 | \
72 | E
73 | [
74 | 0
75 | ;
76 | 1
77 | ;
78 | 3
79 | 3
80 | ;
81 | 4
82 | 1
83 | m
84 | :
85 | V
86 | o
87 | =
88 | \
89 | E
90 | [
91 | 0
92 | ;
93 | 1
94 | ;
95 | 3
96 | 6
97 | ;
98 | 4
99 | 1
100 | ;
101 | 4
102 | m
103 | :
104 | c
105 | Q
106 | =
107 | \
108 | E
109 | ?
110 | 2
111 | 5
112 | I
113 | :
114 |
115 |
--------------------------------------------------------------------------------
/Talk/t1:
--------------------------------------------------------------------------------
1 |
2 | :
3 | V
4 | a
5 | =
6 | \
7 | E
8 | [
9 | 0
10 | m
11 | :
12 | V
13 | c
14 | =
15 | \
16 | E
17 | [
18 | 0
19 | ;
20 | 3
21 | 6
22 | m
23 | :
24 | V
25 | e
26 | =
27 | \
28 | E
29 | [
30 | 0
31 | ;
32 | 4
33 | m
34 | :
35 | V
36 | g
37 | =
38 | \
39 | E
40 | [
41 | 0
42 | ;
43 | 4
44 | ;
45 | 3
46 | 6
47 | m
48 | :
49 | \
50 |
51 |
52 | :
53 | V
54 | i
55 | =
56 | \
57 | E
58 | [
59 | 0
60 | ;
61 | 3
62 | 7
63 | ;
64 | 4
65 | 4
66 | m
67 | :
68 | V
69 | k
70 | =
71 | \
72 | E
73 | [
74 | 0
75 | ;
76 | 1
77 | ;
78 | 3
79 | 7
80 | ;
81 | 4
82 | 4
83 | m
84 | :
85 | V
86 | o
87 | =
88 | \
89 | E
90 | [
91 | 0
92 | ;
93 | 1
94 | ;
95 | 3
96 | 6
97 | ;
98 | 4
99 | 4
100 | ;
101 | 4
102 | m
103 | :
104 | c
105 | Q
106 | =
107 | \
108 | E
109 | ?
110 | 2
111 | 5
112 | I
113 | :
114 |
115 |
--------------------------------------------------------------------------------
/xt/20_kwalitee.t:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | use strict;
4 | use warnings;
5 | use Test::More;
6 |
7 | BEGIN { $ENV{AUTHOR_TESTING} = 1; }
8 | eval "use Test::Kwalitee qw( kwalitee_ok );";
9 | if ($@) {
10 | print "1..0 # Test::Kwalitee required for this test\n";
11 | exit 0;
12 | }
13 |
14 | kwalitee_ok (qw(
15 | -has_meta_yml
16 | -metayml_conforms_spec_current
17 | -metayml_conforms_to_known_spec
18 | -metayml_declares_perl_version
19 | -metayml_has_license
20 | -metayml_has_provides
21 | -metayml_is_parsable
22 | -no_symlinks
23 | ));
24 |
25 | my @experimental = qw(
26 | no_stdin_for_prompting
27 | prereq_matches_use
28 | has_test_pod
29 | has_test_pod_coverage
30 | use_warnings
31 |
32 | build_prereq_matches_use
33 | easily_repackageable
34 | easily_repackageable_by_debian
35 | easily_repackageable_by_fedora
36 | fits_fedora_license
37 | has_license_in_source_file
38 | has_version_in_each_file
39 | has_version_in_each_file
40 | uses_test_nowarnings
41 | );
42 |
43 | done_testing ();
44 |
--------------------------------------------------------------------------------
/META.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: App-ccdiff
3 | version: '0.33'
4 | abstract: Colored Character Diff
5 | license: artistic_2
6 | author:
7 | - H.Merijn Brand
8 | generated_by: Author, CPAN::Meta::Converter version 2.150010
9 | dynamic_config: 1
10 | provides:
11 | App::ccdiff:
12 | file: lib/App/ccdiff.pm
13 | version: '0.33'
14 | configure_requires:
15 | ExtUtils::MakeMaker: 0
16 | build_requires:
17 | Config: 0
18 | requires:
19 | Algorithm::Diff: '1.1901'
20 | Capture::Tiny: 0
21 | Getopt::Long: 0
22 | List::Util: 0
23 | Term::ANSIColor: 0
24 | Test::More: 0
25 | charnames: 0
26 | perl: '5.014000'
27 | recommends:
28 | Algorithm::Diff: '1.201'
29 | Algorithm::Diff::XS: '0.04'
30 | Capture::Tiny: '0.24'
31 | resources:
32 | license: http://dev.perl.org/licenses/
33 | homepage: https://metacpan.org/pod/App::ccdiff
34 | repository: https://github.com/Tux/App-ccdiff
35 | bugtracker: https://github.com/Tux/App-ccdiff/issues
36 | IRC: irc://irc.perl.org/#csv
37 | meta-spec:
38 | version: '1.4'
39 | url: http://module-build.sourceforge.net/META-spec-v1.4.html
40 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # General
2 |
3 | I am always open to improvements and suggestions.
4 | Use [issues](https://github.com/Tux/App-ccdiff/issues)
5 |
6 | # Style
7 |
8 | I will never accept pull request that do not strictly conform to my
9 | style, however you might hate it. You can read the reasoning behind
10 | my [preferences](http://tux.nl/style.html).
11 |
12 | I really do not care about mixed spaces and tabs in (leading) whitespace
13 |
14 | Perl::Tidy will help getting the code in shape, but as all software, it
15 | is not perfect. You can find my preferences for these in
16 | [.perltidy](https://github.com/Tux/Release-Checklist/blob/master/.perltidyrc) and
17 | [.perlcritic](https://github.com/Tux/Release-Checklist/blob/master/.perlcriticrc).
18 |
19 | # Mail
20 |
21 | Please, please, please, do *NOT* use HTML mail.
22 | [Plain text](https://useplaintext.email)
23 | [without](http://www.goldmark.org/jeff/stupid-disclaimers/)
24 | [disclaimers](https://www.economist.com/business/2011/04/07/spare-us-the-e-mail-yada-yada)
25 | will do fine!
26 |
27 | # Requirements
28 |
29 | The minimum version required to use this module is stated in
30 | [Makefile.PL](./Makefile.PL)
31 |
--------------------------------------------------------------------------------
/Talk/ccdiff1:
--------------------------------------------------------------------------------
1 | #!/pro/bin/perl
2 |
3 | use 5.018002;
4 | use warnings;
5 |
6 | use Algorithm::Diff;
7 | use Term::ANSIColor qw(:constants color);
8 |
9 | # Color initialization
10 | my %clr = map { $_ => color ($_) } map { $_, "on_$_" }
11 | qw( red green blue black white cyan magenta yellow );
12 | my $reset = RESET;
13 | my $clr_old = $clr{red} . $clr{"on_white"};
14 | my $clr_new = $clr{green} . $clr{"on_white"};
15 |
16 | binmode STDOUT, ":encoding(utf-8)";
17 |
18 | my $f1 = shift or die;
19 | my $f2 = shift // "-";
20 |
21 | my @d1 = $f1 eq "-" ? <> : do {
22 | open my $fh, "<", $f1 or die "$f1: $!\n";
23 | <$fh>;
24 | };
25 | my @d2 = $f2 eq "-" ? <> : do {
26 | open my $fh, "<", $f2 or die "$f2: $!\n";
27 | <$fh>;
28 | };
29 |
30 | my $diff = Algorithm::Diff->new (\@d1, \@d2);
31 | $diff->Base (1);
32 |
33 | my ($N, @s) = (0, 0);
34 | while ($diff->Next) {
35 | $N++;
36 | $diff->Same and next;
37 | my $sep = "";
38 | my @d = map {[ $diff->Items ($_) ]} 1, 2;
39 | if (!@{$d[1]}) {
40 | printf "%d,%dd%d\n", $diff->Get (qw( Min1 Max1 Max2 ));
41 | $_ = $clr_old . (s/$/$reset/r) for @{$d[0]}
42 | }
43 | elsif (!@{$d[0]}) {
44 | printf "%da%d,%d\n", $diff->Get (qw( Max1 Min2 Max2 ));
45 | $_ = $clr_new . (s/$/$reset/r) for @{$d[1]}
46 | }
47 | else {
48 | $sep = "---\n";
49 | printf "%d,%dc%d,%d\n", $diff->Get (qw( Min1 Max1 Min2 Max2 ));
50 | @d = subdiff (@d);
51 | }
52 | print "< $_" for @{$d[0]};
53 | print $sep;
54 | print "> $_" for @{$d[1]};
55 | }
56 |
57 | sub subdiff {
58 | my $d = Algorithm::Diff->new (map { [ map { split m// } @$_ ] } @_);
59 | my ($d1, $d2) = ("", "");
60 | while ($d->Next) {
61 | my @c = map {[ $d->Items ($_) ]} 1, 2;
62 | if ($d->Same) {
63 | $d1 .= $_ for @{$c[0]};
64 | $d2 .= $_ for @{$c[1]};
65 | next;
66 | }
67 | if (@{$c[0]}) {
68 | $d1 .= $clr_old;
69 | $d1 .= $_ for @{$c[0]};
70 | $d1 .= $reset;
71 | }
72 | if (@{$c[1]}) {
73 | $d2 .= $clr_new;
74 | $d2 .= $_ for @{$c[1]};
75 | $d2 .= $reset;
76 | }
77 | }
78 | return map { [ split m/(?<=\n)/ => $_ ] } $d1, $d2;
79 | } # subdiff
80 |
--------------------------------------------------------------------------------
/Talk/m1.csv:
--------------------------------------------------------------------------------
1 | Date,Initials,Voorv,Stamp,ID
2 | Fri Jun 17 11:24:15 2016,C.T.A.Y.,van,1466155455,1182114
3 | Sat Jul 15 18:59:06 1995,G.E.Y.D.,,805827546,1210847
4 | Tue Sep 6 05:43:59 2005,B.O.Q.S.,,1125978239,1943341
5 | Sat Dec 18 07:08:33 1998,I.O.D.U.,,756194433,1442539
6 | Mon Feb 23 10:37:02 2004,R.X.K.S.,van,1077529022,1654127
7 | Thu Jan 15 16:45:16 1970,G.M.M.S.,de,1266316,1029954
8 | Sat Sep 29 20:16:24 1973,U.K.X.P.,aan,118178184,1956059
9 | Mon Jun 11 22:20:48 1984,B.C.W.R.,aan,455833248,1106137
10 | Sat Feb 1 15:02:01 1986,K.C.T.E.,,507650521,1984362
11 | Mon Dec 23 09:05:39 2002,B.I.D.P.,,1040630739,1255867
12 | Sat Jul 3 09:56:00 1999,N.M.Z.Z.,,930988560,1710800
13 | Thu Feb 19 21:38:49 1981,E.X.V.Q.,,351463129,1303398
14 | Thu Jul 13 17:17:09 2000,W.I.G.X.,de,963501429,1461767
15 | Fri Nov 24 11:51:24 2017,U.A.F.C.,,1511520684,1696330
16 | Sat May 14 17:07:32 2005,P.R.U.T.,,1116083252,1315219
17 | Sun Jul 2 08:47:37 1972,B.F.C.X.,,78911257,1944875
18 | Sun Jan 28 15:35:24 1979,Q.J.K.R.,,286382124,1349438
19 | Tue Dec 13 04:02:56 2016,L.J.Y.H.,,1481598176,1893043
20 | Mon Aug 29 04:52:59 2016,R.O.N.C.,,1472439179,1572631
21 | Fri Jan 9 22:31:14 2009,I.U.I.Y.,der,1231536674,1395326
22 | Wed Dec 1 06:18:15 1976,X.T.H.Q.,van,218265495,1013827
23 | Tue Nov 1 09:09:07 2011,V.O.X.F.,,1320134947,1462133
24 | Tue Sep 26 12:49:03 1972,I.H.V.J.,,86356143,1131633
25 | Wed Nov 2 23:44:51 1988,A.T.C.U.,,594513891,1048363
26 | Wed Oct 4 22:30:04 2017,J.I.M.E.,van,1507149004,1781037
27 | Tue Jun 26 11:54:05 1979,F.R.Q.G.,,299238845,1142185
28 | Wed Apr 29 18:33:28 1970,B.U.X.F.,,10258408,1168580
29 | Sun Jul 24 11:09:51 2011,S.W.L.R.,,1311498591,1189509
30 | Thu Dec 4 05:05:04 2014,B.G.Q.D.,,1417665904,1735680
31 | Wed Jan 30 08:40:14 2008,D.H.G.M.,,1201678814,1231464
32 | Sat Feb 19 13:08:22 2011,K.D.L.X.,,1298117302,1637663
33 | Wed May 14 20:43:38 2003,I.S.G.D.,,1052937818,1109472
34 | Tue Jul 22 15:36:22 1975,E.S.S.A.,,175271782,1025423
35 | Wed Mar 7 15:27:32 2001,E.G.D.G.,der,983975252,1801987
36 | Thu Jul 16 17:56:13 2009,R.U.Z.Z.,,1247759773,1049592
37 | Tue Oct 20 18:47:47 1981,S.J.D.X.,der,372448067,1533354
38 | Sun Nov 11 06:22:50 1973,P.D.G.H.,der,121843370,1120326
39 | Mon Jan 18 12:20:07 2010,M.X.G.O.,,1263813607,1133280
40 | Wed Oct 15 00:55:43 1975,U.T.O.Z.,De,182562943,1326411
41 | Fri Jul 8 11:11:14 2016,R.B.E.Y.,,1467969074,1235436
42 | Mon Dec 12 01:38:51 1977,M.R.E.U.,,250735131,1628799
43 |
--------------------------------------------------------------------------------
/Talk/export.csv:
--------------------------------------------------------------------------------
1 | Date,Initials,Voorv,Stamp,ID
2 | Fri Jun 17 11:24:15 2016,C.T.A.Y.,van,1466155455,1182114
3 | Sat Jul 15 18:59:06 1995,G.E.Y.D.,,805827546,1210847
4 | Tue Sep 6 05:43:59 2005,B.O.Q.S.,,1125978239,1943341
5 | Sat Dec 18 07:08:33 1998,I.O.D.U.,,756194433,1442539
6 | Mon Feb 23 10:37:02 2004,R.X.K.S.,van,1077529022,1654127
7 | Thu Jan 15 16:45:16 1970,G.M.M.S.,de,1266316,1029954
8 | Sat Sep 29 20:16:24 1973,U.K.X.P.,aan,118178184,1956059
9 | Mon Jun 11 22:20:48 1984,B.C.W.R.,aan,455833248,1106137
10 | Sat Feb 1 15:02:01 1986,K.C.T.E.,,507650521,1984362
11 | Mon Dec 23 09:05:39 2002,B.I.D.P.,,1040630739,1255867
12 | Sat Jul 3 09:56:00 1999,N.M.Z.Z.,,930988560,1710800
13 | Thu Feb 19 21:38:49 1981,E.X.V.Q.,,351463129,1303398
14 | Thu Jul 13 17:17:09 2000,W.I.G.X.,de,963501429,1461767
15 | Fri Nov 24 11:51:24 2017,U.A.F.C.,,1511520684,1696330
16 | Sat May 14 17:07:32 2005,P.R.U.T.,,1116083252,1315219
17 | Sun Jul 2 08:47:37 1972,B.F.C.X.,,78911257,1944875
18 | Sun Jan 28 15:35:24 1979,Q.J.K.R.,,286382124,1349438
19 | Tue Dec 13 04:02:56 2016,L.J.Y.H.,,1481598176,1893043
20 | Mon Aug 29 04:52:59 2016,R.O.N.C.,,1472439179,1572631
21 | Fri Jan 9 22:31:14 2009,I.U.I.Y.,der,1231536674,1395326
22 | Wed Dec 1 06:18:15 1976,X.T.H.Q.,van,218265495,1013827
23 | Tue Nov 1 09:09:07 2011,V.O.X.F.,,1320134947,1462133
24 | Tue Sep 26 12:49:03 1972,I.H.V.J.,,86356143,1131633
25 | Wed Nov 2 23:44:51 1988,A.T.C.U.,,594513891,1048363
26 | Wed Oct 4 22:30:04 2017,J.I.M.E.,van,1507149004,1781037
27 | Tue Jun 26 11:54:05 1979,F.R.Q.G.,,299238845,1142185
28 | Wed Apr 29 18:33:28 1970,B.U.X.F.,,10258408,1168580
29 | Sun Jul 24 11:09:51 2011,S.W.L.R.,,1311498591,1189509
30 | Thu Dec 4 05:05:04 2014,B.G.Q.D.,,1417665904,1735680
31 | Wed Jan 30 08:40:14 2008,D.H.G.M.,,1201678814,1231464
32 | Sat Feb 19 13:08:22 2011,K.D.L.X.,,1298117302,1637663
33 | Wed May 14 20:43:38 2003,I.S.G.D.,,1052937818,1109472
34 | Tue Jul 22 15:36:22 1975,E.S.S.A.,,175271782,1025423
35 | Wed Mar 7 15:27:32 2001,E.G.D.G.,der,983975252,1801987
36 | Thu Jul 16 17:56:13 2009,R.U.Z.Z.,,1247759773,1049592
37 | Tue Oct 20 18:47:47 1981,S.J.D.X.,der,372448067,1533354
38 | Sun Nov 11 06:22:50 1973,P.D.G.H.,der,121843370,1120326
39 | Mon Jan 18 12:20:07 2010,M.X.G.O.,,1263813607,1133280
40 | Wed Oct 15 00:55:43 1975,U.T.O.Z.,De,182562943,1326411
41 | Fri Jul 8 11:11:14 2016,R.B.E.Y.,,1467969074,1235436
42 | Mon Dec 12 01:38:51 1977,M.R.E.U.,,250735131,1628799
43 |
--------------------------------------------------------------------------------
/Talk/m0.csv:
--------------------------------------------------------------------------------
1 | Date,Initials,Voorv,Stamp,ID
2 | Fri Jun 17 11:24:15 2016,C.T.A.Y.,van,1466155455,1182114
3 | Sat Jul 15 18:59:06 1995,G.E.Y.D.,,805827546,1210847
4 | Tue Sep 6 05:43:59 2005,B.O.Q.S.,,1125978239,1943341
5 | Sat Dec 18 07:00:33 1993,I.O.D.U.,,756194433,1442539
6 | Mon Feb 23 10:37:02 2004,R.X.K.S.,van,1077529022,1654127
7 | Thu Jan 15 16:45:16 1970,G.M.M.S.,de,1266316,1029954
8 | Sat Sep 29 20:16:24 1973,U.K.X.P.,aan,118178184,1956059
9 | Mon Jun 11 22:20:48 1984,B.C.W.R.,aan,455833248,1106137
10 | Sat Feb 1 15:02:01 1986,K.C.T.E.,,507650521,1984362
11 | Mon Dec 23 09:05:39 2002,B.I.D.P.,,1040630739,1255867
12 | Sat Jul 3 09:56:00 1999,N.M.Z.Z.,,930988560,1710800
13 | Thu Feb 19 21:38:49 1981,E.X.V.Q.,,351463129,1303398
14 | Thu Jul 13 17:17:09 2000,W.I.G.X.,de,963501429,1461767
15 | Fri Nov 24 11:51:24 2017,U.A.F.C.,,1511520684,1696330
16 | Sat May 14 17:07:32 2005,P.R.U.T.,,1116083252,1315219
17 | Sun Jul 2 08:47:37 1972,B.F.C.X.,,78911257,1944875
18 | Sun Jan 28 15:35:24 1979,Q.J.K.R.,,286382124,1349438
19 | Mon Dec 12 01:38:51 1977,M.R.E.U.,,250735131,1628799
20 | Tue Dec 13 04:02:56 2016,L.J.Y.H.,,1481598176,1893043
21 | Mon Aug 29 04:52:59 2016,R.O.N.C.,,1472439179,1572631
22 | Fri Jan 9 22:31:14 2009,I.U.I.Y.,der,1231536674,1395326
23 | Wed Dec 1 06:18:15 1976,X.T.H.Q.,van,218265495,1013827
24 | Tue Nov 1 09:09:07 2011,V.O.X.F.,,1320134947,1462133
25 | Tue Sep 26 12:49:03 1972,I.H.V.J.,,86356143,1131633
26 | Wed Nov 2 23:44:51 1988,A.T.C.U.,,594513891,1048363
27 | Wed Oct 4 22:30:04 2017,J.I.M.E.,van,1507149004,1781037
28 | Tue Jun 26 11:54:05 1979,F.R.Q.G.,,299238845,1142185
29 | Wed Apr 29 18:33:28 1970,B.U.X.F.,,10258408,1168580
30 | Sun Jul 24 11:09:51 2011,S.W.L.R.,,1311498591,1189509
31 | Thu Dec 4 05:05:04 2014,B.G.Q.D.,,1417665904,1735680
32 | Wed Jan 30 08:40:14 2008,D.H.G.M.,,1201678814,1231464
33 | Sat Feb 19 13:08:22 2011,K.D.L.X.,,1298117302,1637663
34 | Wed May 14 20:43:38 2003,I.S.G.D.,,1052937818,1109472
35 | Tue Jul 22 15:36:22 1975,E.S.S.A.,,175271782,1025423
36 | Wed Mar 7 15:27:32 2001,E.G.D.G.,der,983975252,1801987
37 | Thu Jul 16 17:56:13 2009,R.U.Z.Z.,,1247759773,1049592
38 | Tue Oct 20 18:47:47 1981,S.J.D.X.,der,372448067,1533354
39 | Sun Nov 11 06:22:50 1973,P.D.G.H.,der,121843370,1120326
40 | Mon Jan 18 12:20:07 2010,M.X.G.O.,,1263813607,1133280
41 | Wed Oct 15 00:55:43 1975,U.T.O.Z.,de,182562943,1326411
42 | Fri Jul 8 11:11:14 2016,R.B.E.Y.,,1467969074,1235436
43 |
--------------------------------------------------------------------------------
/Talk/member.csv:
--------------------------------------------------------------------------------
1 | Date,Initials,Voorv,Stamp,ID
2 | Fri Jun 17 11:24:15 2016,C.T.A.Y.,van,1466155455,1182114
3 | Sat Jul 15 18:59:06 1995,G.E.Y.D.,,805827546,1210847
4 | Tue Sep 6 05:43:59 2005,B.O.Q.S.,,1125978239,1943341
5 | Sat Dec 18 07:00:33 1993,I.O.D.U.,,756194433,1442539
6 | Mon Feb 23 10:37:02 2004,R.X.K.S.,van,1077529022,1654127
7 | Thu Jan 15 16:45:16 1970,G.M.M.S.,de,1266316,1029954
8 | Sat Sep 29 20:16:24 1973,U.K.X.P.,aan,118178184,1956059
9 | Mon Jun 11 22:20:48 1984,B.C.W.R.,aan,455833248,1106137
10 | Sat Feb 1 15:02:01 1986,K.C.T.E.,,507650521,1984362
11 | Mon Dec 23 09:05:39 2002,B.I.D.P.,,1040630739,1255867
12 | Sat Jul 3 09:56:00 1999,N.M.Z.Z.,,930988560,1710800
13 | Thu Feb 19 21:38:49 1981,E.X.V.Q.,,351463129,1303398
14 | Thu Jul 13 17:17:09 2000,W.I.G.X.,de,963501429,1461767
15 | Fri Nov 24 11:51:24 2017,U.A.F.C.,,1511520684,1696330
16 | Sat May 14 17:07:32 2005,P.R.U.T.,,1116083252,1315219
17 | Sun Jul 2 08:47:37 1972,B.F.C.X.,,78911257,1944875
18 | Sun Jan 28 15:35:24 1979,Q.J.K.R.,,286382124,1349438
19 | Mon Dec 12 01:38:51 1977,M.R.E.U.,,250735131,1628799
20 | Tue Dec 13 04:02:56 2016,L.J.Y.H.,,1481598176,1893043
21 | Mon Aug 29 04:52:59 2016,R.O.N.C.,,1472439179,1572631
22 | Fri Jan 9 22:31:14 2009,I.U.I.Y.,der,1231536674,1395326
23 | Wed Dec 1 06:18:15 1976,X.T.H.Q.,van,218265495,1013827
24 | Tue Nov 1 09:09:07 2011,V.O.X.F.,,1320134947,1462133
25 | Tue Sep 26 12:49:03 1972,I.H.V.J.,,86356143,1131633
26 | Wed Nov 2 23:44:51 1988,A.T.C.U.,,594513891,1048363
27 | Wed Oct 4 22:30:04 2017,J.I.M.E.,van,1507149004,1781037
28 | Tue Jun 26 11:54:05 1979,F.R.Q.G.,,299238845,1142185
29 | Wed Apr 29 18:33:28 1970,B.U.X.F.,,10258408,1168580
30 | Sun Jul 24 11:09:51 2011,S.W.L.R.,,1311498591,1189509
31 | Thu Dec 4 05:05:04 2014,B.G.Q.D.,,1417665904,1735680
32 | Wed Jan 30 08:40:14 2008,D.H.G.M.,,1201678814,1231464
33 | Sat Feb 19 13:08:22 2011,K.D.L.X.,,1298117302,1637663
34 | Wed May 14 20:43:38 2003,I.S.G.D.,,1052937818,1109472
35 | Tue Jul 22 15:36:22 1975,E.S.S.A.,,175271782,1025423
36 | Wed Mar 7 15:27:32 2001,E.G.D.G.,der,983975252,1801987
37 | Thu Jul 16 17:56:13 2009,R.U.Z.Z.,,1247759773,1049592
38 | Tue Oct 20 18:47:47 1981,S.J.D.X.,der,372448067,1533354
39 | Sun Nov 11 06:22:50 1973,P.D.G.H.,der,121843370,1120326
40 | Mon Jan 18 12:20:07 2010,M.X.G.O.,,1263813607,1133280
41 | Wed Oct 15 00:55:43 1975,U.T.O.Z.,de,182562943,1326411
42 | Fri Jul 8 11:11:14 2016,R.B.E.Y.,,1467969074,1235436
43 |
--------------------------------------------------------------------------------
/META.json:
--------------------------------------------------------------------------------
1 | { "name" : "App-ccdiff",
2 | "version" : "0.33",
3 | "abstract" : "Colored Character Diff",
4 | "license" : [
5 | "artistic_2"
6 | ],
7 | "author" : [
8 | "H.Merijn Brand "
9 | ],
10 | "generated_by" : "Author",
11 | "dynamic_config" : 1,
12 | "release_status" : "stable",
13 | "provides" : {
14 | "App::ccdiff" : {
15 | "file" : "lib/App/ccdiff.pm",
16 | "version" : "0.33"
17 | }
18 | },
19 | "prereqs" : {
20 | "configure" : {
21 | "requires" : {
22 | "ExtUtils::MakeMaker" : "0"
23 | },
24 | "recommends" : {
25 | "ExtUtils::MakeMaker" : "7.22"
26 | },
27 | "suggests" : {
28 | "ExtUtils::MakeMaker" : "7.70"
29 | }
30 | },
31 | "build" : {
32 | "requires" : {
33 | "Config" : "0"
34 | }
35 | },
36 | "test" : {
37 | "requires" : {
38 | "Test::More" : "0",
39 | "Capture::Tiny" : "0"
40 | },
41 | "recommends" : {
42 | "Capture::Tiny" : "0.24"
43 | },
44 | "suggests" : {
45 | "Capture::Tiny" : "0.48"
46 | }
47 | },
48 | "runtime" : {
49 | "requires" : {
50 | "perl" : "5.014000",
51 | "charnames" : "0",
52 | "Getopt::Long" : "0",
53 | "Algorithm::Diff" : "1.1901",
54 | "Term::ANSIColor" : "0",
55 | "List::Util" : "0"
56 | },
57 | "recommends" : {
58 | "Algorithm::Diff::XS" : "0.04",
59 | "Algorithm::Diff" : "1.201"
60 | }
61 | }
62 | },
63 | "resources" : {
64 | "x_IRC" : "irc://irc.perl.org/#csv",
65 | "bugtracker" : {
66 | "web" : "https://github.com/Tux/App-ccdiff/issues"
67 | },
68 | "repository" : {
69 | "type" : "git",
70 | "web" : "https://github.com/Tux/App-ccdiff",
71 | "url" : "https://github.com/Tux/App-ccdiff"
72 | },
73 | "license" : [
74 | "http://dev.perl.org/licenses/"
75 | ],
76 | "homepage" : "https://metacpan.org/pod/App::ccdiff"
77 | },
78 | "meta-spec" : {
79 | "version" : 2,
80 | "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec"
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/sandbox/genMETA.pl:
--------------------------------------------------------------------------------
1 | #!/pro/bin/perl
2 |
3 | use 5.012002;
4 | use warnings;
5 |
6 | our $VERSION = "2.00 - 2020-12-23";
7 | our $CMD = $0 =~ s{.*/}{}r;
8 |
9 | sub usage {
10 | my $err = shift and select STDERR;
11 | say "usage: $CMD [--check || --yaml || --json]";
12 | exit $err;
13 | } # usage
14 |
15 | use Getopt::Long qw(:config bundling nopermute);
16 | GetOptions (
17 | "help|?" => sub { usage (0) },
18 | "V|version" => sub { say "$CMD [$VERSION]"; exit 0; },
19 |
20 | "c|check!" => \ my $check,
21 | "y|yaml!" => \ my $opt_y,
22 | "j|json!" => \ my $opt_j,
23 |
24 | "v|verbose:1" => \(my $opt_v = 0),
25 | ) or die "usage: $0 [--check]\n";
26 |
27 | use lib "sandbox";
28 | use genMETA;
29 | my $meta = genMETA->new (
30 | from => "ccdiff",
31 | verbose => $opt_v,
32 | );
33 |
34 | $meta->from_data ();
35 | $meta->gen_cpanfile ();
36 |
37 | if ($check) {
38 | $meta->check_encoding ();
39 | $meta->check_required ();
40 | $meta->check_minimum ();
41 | $meta->done_testing ();
42 | }
43 | elsif ($opt_y) {
44 | $meta->print_yaml ();
45 | }
46 | elsif ($opt_j) {
47 | $meta->print_json ();
48 | }
49 | else {
50 | $meta->fix_meta ();
51 | }
52 |
53 | __END__
54 | --- #YAML:1.0
55 | name: App-ccdiff
56 | version: VERSION
57 | abstract: Colored Character Diff
58 | license: artistic_2
59 | author:
60 | - H.Merijn Brand
61 | generated_by: Author
62 | distribution_type: module
63 | provides:
64 | App::ccdiff:
65 | file: lib/App/ccdiff.pm
66 | version: VERSION
67 | requires:
68 | perl: 5.014000
69 | charnames: 0
70 | Algorithm::Diff: 1.1901
71 | Term::ANSIColor: 0
72 | Getopt::Long: 0
73 | List::Util: 0
74 | recommends:
75 | Algorithm::Diff::XS: 0.04
76 | Algorithm::Diff: 1.201
77 | configure_requires:
78 | ExtUtils::MakeMaker: 0
79 | configure_recommends:
80 | ExtUtils::MakeMaker: 7.22
81 | configure_suggests:
82 | ExtUtils::MakeMaker: 7.72
83 | build_requires:
84 | Config: 0
85 | test_requires:
86 | Test::More: 0
87 | Capture::Tiny: 0
88 | test_recommends:
89 | Capture::Tiny: 0.24
90 | test_suggests:
91 | Capture::Tiny: 0.50
92 | resources:
93 | license: http://dev.perl.org/licenses/
94 | homepage: https://metacpan.org/pod/App::ccdiff
95 | repository: https://github.com/Tux/App-ccdiff
96 | bugtracker: https://github.com/Tux/App-ccdiff/issues
97 | IRC: irc://irc.perl.org/#csv
98 | meta-spec:
99 | version: 1.4
100 | url: http://module-build.sourceforge.net/META-spec-v1.4.html
101 |
--------------------------------------------------------------------------------
/Makefile.PL:
--------------------------------------------------------------------------------
1 | use 5.014000;
2 | use warnings;
3 |
4 | use ExtUtils::MakeMaker;
5 |
6 | my $VERSION;
7 | open my $fh, "<", "ccdiff";
8 | while (<$fh>) {
9 | m/VERSION\s*=\s*["']?([0-9.]+)/ or next;
10 | $VERSION = $1;
11 | last;
12 | }
13 | close $fh;
14 |
15 | my %wmf = (
16 | NAME => "App::ccdiff",
17 | DISTNAME => "App-ccdiff",
18 | ABSTRACT => "Colored Character Diff",
19 | AUTHOR => "H.Merijn Brand",
20 | EXE_FILES => [ "ccdiff" ],
21 | VERSION => $VERSION,
22 | MIN_PERL_VERSION => "5.014000",
23 | PREREQ_PM => {
24 | charnames => 0,
25 | "Algorithm::Diff" => "1.1901",
26 | "List::Util" => 0,
27 | "Term::ANSIColor" => 0,
28 | "Getopt::Long" => 0,
29 | },
30 | CONFIGURE_REQUIRES => {
31 | "ExtUtils::MakeMaker" => 0,
32 | },
33 | TEST_REQUIRES => {
34 | "Test::More" => 0,
35 | "Capture::Tiny" => 0,
36 | },
37 | LICENSE => "artistic_2",
38 | macro => { TARFLAGS => "--format=ustar -c -v -f", },
39 |
40 | META_MERGE => {
41 | "meta-spec" => { version => 2 },
42 | licence => "artistic_2",
43 | resources => {
44 | type => "git",
45 | url => "git://github.com/Tux/App-ccdiff.git",
46 | web => "https://github.com/Tux/App-ccdiff",
47 | IRC => "irc://irc.perl.org/#csv",
48 | },
49 | provides => {
50 | "App::ccdiff" => {
51 | file => "ccdiff",
52 | version => $VERSION,
53 | },
54 | },
55 | },
56 | );
57 |
58 | eval { ExtUtils::MakeMaker->VERSION (6.63_03) } or
59 | delete $wmf{TEST_REQUIRES};
60 |
61 | my $rv = WriteMakefile (%wmf);
62 |
63 | package MY;
64 |
65 | sub postamble {
66 | my @mpm = (-d ".git" && -x "2lib")
67 | ? ( '','lib/App/ccdiff.pm: ccdiff',
68 | ' perl ./2lib',
69 | '',
70 | 'all:: lib/App/ccdiff.pm doc spellcheck cpanfile',
71 | )
72 | : ();
73 | -d "xt" && ($ENV{AUTOMATED_TESTING} || 0) != 1 and
74 | push @mpm =>
75 | '',
76 | 'test ::',
77 | ' -@env TEST_FILES="xt/*.t" make -e test_dynamic';
78 | join "\n" =>
79 | 'cpanfile:',
80 | ' perl sandbox/genMETA.pl',
81 | '',
82 | 'spellcheck:',
83 | ' pod-spell-check --aspell --ispell ccdiff',
84 | '',
85 | 'checkmeta: spellcheck',
86 | ' perl sandbox/genMETA.pl -c',
87 | '',
88 | 'fixmeta: distmeta',
89 | ' perl sandbox/genMETA.pl',
90 | '',
91 | 'tgzdist: lib/App/ccdiff.pm doc checkmeta fixmeta $(DISTVNAME).tar.gz distcheck',
92 | ' -@mv -f $(DISTVNAME).tar.gz $(DISTVNAME).tgz',
93 | ' -@cpants_lint.pl $(DISTVNAME).tgz',
94 | ' -@rm -f Debian_CPANTS.txt',
95 | '',
96 | 'doc docs: doc/ccdiff.md doc/ccdiff.html doc/ccdiff.man doc/README.md',
97 | ' perl doc/make-doc.pl',
98 | 'doc/ccdiff.man: doc/ccdiff.3',
99 | ' nroff2man < $? > $@',
100 | 'doc/README.md: README.md',
101 | ' cp -p $? $@',
102 | @mpm;
103 | } # postamble
104 |
105 | 1;
106 |
--------------------------------------------------------------------------------
/Talk/README:
--------------------------------------------------------------------------------
1 | - show termcap
2 | - show termcap-blue
3 |
4 | diff C
5 | diff --color C
6 | colordiff
7 |
8 | vimdiff C
9 | git diff C
10 |
11 | git -c color.diff.new='bold reverse green' \
12 | -c color.diff.old='bold reverse red' \
13 | diff --no-index -U0 --no-color \
14 | --word-diff=color --word-diff-regex=. \
15 |
16 |
17 | xdiff Python, PHP, .......
18 |
19 | mgdiff C X11
20 | diffuse Python
21 | bcompare C X11 Free?
22 | kompare C X11 KDE
23 | xxdiff C X11
24 | meld Python
25 | kdiff3 C X11 Qt
26 | tkdiff Tcl/Tk
27 |
28 | # To be checked ...
29 | araxis - Windows, should work under wine
30 | bc
31 | bc3
32 | codecompare
33 | deltawalker
34 | diff-so-fancy - https://github.com/so-fancy/diff-so-fancy
35 | diffmerge
36 | ecmerge
37 | emerge
38 | examdiff
39 | guiffy
40 | gvimdiff
41 | gvimdiff2
42 | gvimdiff3
43 | klondiff - https://github.com/pierstitus/klondiff (python)
44 | opendiff
45 | p4merge
46 | vimdiff2
47 | vimdiff3
48 | winmerge
49 |
50 | ccdiff Perl
51 |
52 | ccdiff termcap termcap-blue
53 |
54 | xterm -bg gray10 -fg gray90 &
55 |
56 | # Colors (on two xterms: one normal and one with bg black)
57 | ccdiff -r term*
58 | ccdiff --pink term*
59 | ccdiff -r --pink term*
60 | ccdiff --no-color term*
61 | ccdiff --no-color --fancy term*
62 | ccdiff -r --no-color --fancy term*
63 | ccdiff -r --old=blue term*
64 | ccdiff -r --new=blue term*
65 | ccdiff --bg=black term*
66 |
67 | ccdiff -u term*
68 | ccdiff -u0 term*
69 |
70 | - show member.csv
71 | - show export.csv
72 |
73 | ccdiff member.csv export.csv
74 | ccdiff -r member.csv export.csv
75 | ccdiff -r member.csv export.csv -w
76 | ccdiff -r member.csv export.csv -i
77 | ccdiff -r member.csv export.csv -w -i
78 |
79 | ccdiff -r term*
80 | ccdiff -r -B term*
81 |
82 | cd3 hexchat-git
83 | git show 5c5a
84 |
85 | git config --global diff.tool ccdiff
86 | git config --global difftool.prompt false
87 | git config --global difftool.ccdiff.cmd 'ccdiff --utf-8 -u -r $LOCAL $REMOTE'
88 | git difftool 5c5a~..5c5a
89 | cat ~/bin/git-ccdiff
90 | git ccdiff 5c5a
91 | cat 5c5a.uchar
92 |
93 | 290 modules on CPAN with Diff
94 | Some depend on Text::Diff
95 | Many depend (indirectly) on Algorithm::Diff
96 |
97 | man Algorithm::Diff
98 |
99 | show ccdiff1
100 | show ccdiff
101 |
102 | show m0
103 | show e0
104 |
105 | explain horizontal to vertical again
106 |
107 | Text::Diff integration. Neil?
108 | Ignore whitespace options:
109 | -Z, --ignore-trailing-space ignore white space at line end
110 | -b, --ignore-space-change ignore changes in the amount of white space
111 | -w, --ignore-all-space ignore all white space
112 | -E, --ignore-tab-expansion ignore changes due to tab expansion
113 |
114 | Future?
115 | -B, --ignore-blank-lines ignore changes where lines are all blank
116 |
--------------------------------------------------------------------------------
/ChangeLog:
--------------------------------------------------------------------------------
1 | 0.35 - 2025-11-07
2 | * Add old-label and new-label
3 |
4 | 0.34 - 2025-01-02
5 | * Add iwbZusePP config for failing -i/-w/-b/-Z on Algorithm::Diff::XS
6 | * It is 2024 and 2025
7 |
8 | 0.33 - 2023-11-07
9 | * New version declarations based on CVE warnings
10 | * Allow selecting PP diff when XS fails
11 | * Doc fixes for groff-1.24
12 | * Recursive ccdiff on two folders
13 |
14 | 0.32 - 2023-01-05
15 | * Add ref to diff-so-fancy
16 | * README & Documentation fixes (pr#21 .. pr#23, Ryan Schmidt)
17 | * git-ccdiff: not all arguments are sha's (`git ccdiff .`, issue#25)
18 | * It is 2023
19 |
20 | 0.31 - 2022-01-01
21 | * It is 2021 - no changes in 2021
22 | * It is 2022
23 |
24 | 0.30 - 2020-12-23
25 | * Add --swap/-s
26 | * Fix META issue for bugtracker
27 |
28 | 0.29 - 2020-09-16
29 | * Fix Changes
30 | * Default changed by $ENV{CLICOLOR} - see https://bixense.com/clicolors/
31 | * It's 2020
32 | * Fallback to Pod::Text if nroff not available for --man
33 | * Support header colors and header for non-u
34 | * Refuse to diff character and block devices
35 | * Warn that --recurse and folders are not yet supported
36 | * Prefer Algorithm::Diff::XS if installed (raf)
37 | * Support arrarefs for when used as module
38 |
39 | 0.28 - 2019-09-02
40 | * Add cpanfile
41 |
42 | 0.27 - 2019-01-15
43 | * Requires Algorithm::Diff 1.1901
44 | * Default no-color to $ENV{NO_COLOR} - see https://no-color.org
45 | * Happy 2019
46 | * Make sure file arg - only reads STDIN
47 |
48 | 0.26 - 2018-10-14
49 | * Update git-ccdiff
50 | * Docs for git
51 | * Include git-ccdiff as file
52 | * $HOME for Windows users
53 | * Add option to skip header
54 | * Add tests
55 | * Add --settings
56 | * Add repo and provides to META
57 |
58 | 0.25 - 2018-09-07
59 | * Use CORE module for --info
60 | * Show codepoints under -v3 (issue#14)
61 | * Add --no-colors
62 | * Reverse/invert debug color too under -r if possible
63 | * Add --ellipsis / -e
64 | * Allow used character indicators in RC
65 |
66 | 0.24 - 2018-08-26
67 | * Filter colors on Term::ANSIColor version
68 | * Add heuristics
69 |
70 | 0.23 - 2018-08-23
71 | * Add color "none" to disable a color
72 | * Try to prevent unsupported colors
73 | * Also color line-change-indicators (-, +, <, and >) (issue#8)
74 | * Add threshold for horizontal diff (issue#9)
75 | * Remove one leading space for unified diffs
76 | * Add git integration to integrated docs (issue#10)
77 | * Add all Term::ANSIColor colors as known
78 | * Fix color leakage in multiline changes
79 |
80 | 0.22 - 2018-08-21
81 | * Fix issue tracker (issue#6, jwilk)
82 | * Require perl-5.14.0 because of syntax used
83 | * More docs about markers
84 | * Add doc warning about large datasets
85 | * Support emacs users with new config setting
86 | * Fix license issues (gregoa, issue#2)
87 |
88 | 0.21 - 2018-08-19
89 | * Add characterchange-marker on verbose level 2 and up
90 | * Fancy is default, ascii is optional
91 | * Colors are not optional, markers are
92 | * Fix markers for spaces
93 | * Fix doc typo (issue#4)
94 |
95 | 0.20 - 2018-08-16
96 | * Start inline documentation
97 | * Support configuration
98 | * Add -I/--index
99 | * Add --verbose meaning
100 | * Add --list-colors
101 |
102 | 0.10 - 2018-08-15
103 | * Allow bold variants for colors
104 | * Start of -B implementation
105 |
106 | 0.09 - 2018-08-10
107 | * Header for unified diff
108 |
109 | 0.08 - 2018-08-02
110 | * Implement -b
111 | * Implement -Z
112 | * Implement -i
113 |
114 | 0.07 - 2018-07-30
115 | * Add --utf8
116 | * Add git integration example
117 |
118 | 0.06 - 2018-07-20
119 | * Reset colors before newlines
120 | * Add --utf-8
121 | * Add git integration example
122 |
123 | 0.05 - 2018-07-09
124 | * Add unified diff (-u, -u0)
125 | * Complete the usage message
126 |
127 | 0.04 - 2018-07-06
128 | * Put it all in git and on github
129 |
130 | 0.03 - 2018-07-06
131 | * Add color options (--pink, --reverse, --old=C, --new=C, --bg=C)
132 | * Add Unicode indicators (--fancy)
133 |
134 | 0.02 - 2018-05-15
135 | * Add --no-color
136 |
137 | 0.01 - 2018-05-14
138 | * Initial version
139 |
--------------------------------------------------------------------------------
/t/01-no-color.t:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env perl
2 |
3 | use 5.014000;
4 | use warnings;
5 |
6 | use Test::More;
7 | use Capture::Tiny "capture";
8 |
9 | binmode STDOUT, ":encoding(utf-8)";
10 | binmode STDERR, ":encoding(utf-8)";
11 | binmode DATA, ":encoding(utf-8)";
12 |
13 | # localtime will differ on other machines
14 | my %stamp = map { s{^Files/}{}r => "$_ ".localtime ((stat)[9]) } glob "Files/*";
15 |
16 | local $/ = "** EOT **\n";
17 | while () {
18 | chomp;
19 | my ($dsc, $f1, $f2, $opt, $exp) = split m/\n/, $_, 5;
20 | $exp =~ s/STAMP:1/$stamp{$f1}/g;
21 | $exp =~ s/STAMP:2/$stamp{$f2}/g;
22 | #diag "Description: $dsc";
23 | #diag "Options: $opt";
24 | my @cmd = ($^X, "ccdiff", "--utf-8", "--no-color", "Files/$f1", "Files/$f2");
25 | $opt and push @cmd, split m/ / => $opt;
26 | #diag "@cmd";
27 | my ($out, $err, $exit) = capture { system @cmd; };
28 | is ($out, $exp, $dsc);
29 | is ($err, "", "No error");
30 | is ($exit, 0, "Success");
31 | }
32 |
33 | done_testing;
34 |
35 | __END__
36 | No options
37 | 01_1.txt
38 | 01_2.txt
39 |
40 | < STAMP:1
41 | > STAMP:2
42 | 3,3c3,3
43 | < usu. Ad duo posse theophrastus, vim in accumsan
44 | ---
45 | > usu. Ad duo posse theophrastus. Vim in accumsan
46 | ** EOT **
47 | Unified with header
48 | 01_1.txt
49 | 01_2.txt
50 | -u0
51 | --- STAMP:1
52 | +++ STAMP:2
53 | 3,3c3,3
54 | -usu. Ad duo posse theophrastus, vim in accumsan
55 | +usu. Ad duo posse theophrastus. Vim in accumsan
56 | ** EOT **
57 | No header
58 | 01_1.txt
59 | 01_2.txt
60 | --no-header
61 | 3,3c3,3
62 | < usu. Ad duo posse theophrastus, vim in accumsan
63 | ---
64 | > usu. Ad duo posse theophrastus. Vim in accumsan
65 | ** EOT **
66 | Unified with header
67 | 01_1.txt
68 | 01_2.txt
69 | -u0
70 | --- STAMP:1
71 | +++ STAMP:2
72 | 3,3c3,3
73 | -usu. Ad duo posse theophrastus, vim in accumsan
74 | +usu. Ad duo posse theophrastus. Vim in accumsan
75 | ** EOT **
76 | Unified without header
77 | 01_1.txt
78 | 01_2.txt
79 | -u0 --no-header
80 | 3,3c3,3
81 | -usu. Ad duo posse theophrastus, vim in accumsan
82 | +usu. Ad duo posse theophrastus. Vim in accumsan
83 | ** EOT **
84 | Unified with ascii markers
85 | 01_1.txt
86 | 01_2.txt
87 | -mau0 --no-header
88 | 3,3c3,3
89 | -usu. Ad duo posse theophrastus, vim in accumsan
90 | - ^ ^
91 | +usu. Ad duo posse theophrastus. Vim in accumsan
92 | + ^ ^
93 | ** EOT **
94 | Unified with unicode markers
95 | 01_1.txt
96 | 01_2.txt
97 | -mu0 --no-header
98 | 3,3c3,3
99 | -usu. Ad duo posse theophrastus, vim in accumsan
100 | - ▼ ▼
101 | +usu. Ad duo posse theophrastus. Vim in accumsan
102 | + ▲ ▲
103 | ** EOT **
104 | Unified with ascii markers and context
105 | 01_1.txt
106 | 01_2.txt
107 | -mau1
108 | --- STAMP:1
109 | +++ STAMP:2
110 | 3,3c3,3
111 | id vix cibo omittantur, et impetus offendit convenire
112 | -usu. Ad duo posse theophrastus, vim in accumsan
113 | - ^ ^
114 | +usu. Ad duo posse theophrastus. Vim in accumsan
115 | + ^ ^
116 | efficiantur, sed in congue decore. Ex nullam iudicabit
117 | ** EOT **
118 | Unified with ascii verbose 1
119 | 01_1.txt
120 | 01_2.txt
121 | -au0 -v1 --no-header
122 | 3,3c3,3
123 | -usu. Ad duo posse theophrastus, vim in accumsan
124 | - -- verbose : COMMA, LATIN SMALL LETTER V
125 | +usu. Ad duo posse theophrastus. Vim in accumsan
126 | + -- verbose : FULL STOP, LATIN CAPITAL LETTER V
127 | ** EOT **
128 | Unified with unicode verbose 1
129 | 01_1.txt
130 | 01_2.txt
131 | -u0 -v1 --no-header
132 | 3,3c3,3
133 | -usu. Ad duo posse theophrastus, vim in accumsan
134 | - -- verbose : COMMA, LATIN SMALL LETTER V
135 | +usu. Ad duo posse theophrastus. Vim in accumsan
136 | + -- verbose : FULL STOP, LATIN CAPITAL LETTER V
137 | ** EOT **
138 | Unified with ascii verbose 2
139 | 01_1.txt
140 | 01_2.txt
141 | -au0 -v2 --no-header
142 | 3,3c3,3
143 | -usu. Ad duo posse theophrastus>,< >v.< >V
60 | ```
61 | An alternative for integration with git is `diff-so-fancy`
62 |
63 | ## ASCII
64 |
65 | * `vimdiff`
66 |
67 | ## GUI
68 |
69 | Please never use the `xdiff` command (if available at all), because it is
70 | included in many distributions and/or packages and they all work different
71 | or not at all. Some at not intended to be invoked from the command line.
72 |
73 | The list is in increasing clarity of the tool being able to show *minor*
74 | changes in lines visually outstanding:
75 |
76 | * `mgdiff` (C, X11)
77 |
78 | * `diffuse` (Python)
79 |
80 | * `bcompare` (C, X11, not freeware/opensource)
81 |
82 | * `kompare` (C, X11, KDE)
83 |
84 | * `xxdiff` (C, X11)
85 |
86 | * `meld` (Python)
87 |
88 | * `kdiff3` (C, X11, Qt)
89 |
90 | * `tkdiff` (Tcl/Tk)
91 |
92 | ## Other (not checked yet)
93 |
94 | Reasons for not checking include Windows and emacs.
95 |
96 | * araxis
97 | * bc
98 | * bc3
99 | * codecompare
100 | * deltaworker
101 | * diffmerge
102 | * ecmerge
103 | * emerge
104 | * examdiff
105 | * guiffy
106 | * gvimdiff2
107 | * gvimdiff3
108 | * opendiff
109 | * p4merge
110 | * winmerge
111 |
112 | # Dependencies
113 |
114 | This tool will run on recent perl distributions that have
115 | [Algorithm::Diff](https://metacpan.org/pod/Algorithm::Diff)
116 | installed. The modules
117 | [Term::ANSIColor](https://metacpan.org/pod/Term::ANSIColor)
118 | and [Getopt::Long](https://metacpan.org/pod/Getopt::Long)
119 | that are also used are part of the perl CORE distribution
120 | since at least version 5.6.0.
121 | ```
122 | suse# zypper in perl-Algorithm-Diff
123 |
124 | centos# yum install -y perl-Algorithm-Diff
125 |
126 | other# cpan Algorithm::Diff
127 | ```
128 | # Git integration
129 |
130 | You can use ccdiff to show diffs in git. It may work like this:
131 | ```
132 | $ git config --global diff.tool ccdiff
133 | $ git config --global difftool.prompt false
134 | $ git config --global difftool.ccdiff.cmd 'ccdiff --utf-8 -u -r $LOCAL $REMOTE'
135 | $ git difftool SHA~..SHA
136 | $ wget https://github.com/Tux/App-ccdiff/raw/master/Files/git-ccdiff \
137 | -O ~/bin/git-ccdiff
138 | $ perl -pi -e 's{/pro/bin/perl}{/usr/bin/env perl}' ~/bin/git-ccdiff
139 | $ chmod 755 ~/bin/git-ccdiff
140 | $ git ccdiff SHA
141 | ```
142 |
143 | Of course you can use `curl` instead of `wget` and you can choose your own
144 | (fixed) path to `perl` instead of using `/usr/bin/env`.
145 |
146 | ## LIMITATIONS
147 |
148 | There is no provision (yet) for coping with double-width characters.
149 |
150 | Large datasets may consume all available memory, causing the diff to fail.
151 |
152 | Not all that can be set from the configuration files can be overruled by
153 | command-line options.
154 |
155 | ## LICENSE
156 |
157 | The Artistic License 2.0
158 |
159 | Copyright (c) 2018-2025 H.Merijn Brand
160 |
--------------------------------------------------------------------------------
/doc/README.md:
--------------------------------------------------------------------------------
1 | # App-ccdiff
2 |
3 | A colored diff that also colors inside changed lines
4 |
5 | # Synopsis
6 | ```
7 | usage: ccdiff [options] file1 [file2]
8 | ccdiff --help | --man | --info
9 | file1 or file2 can be - (but not both)
10 | ```
11 | # Description
12 |
13 | All command-line tools that show the difference between two files fall
14 | short in showing minor changes visually usefully. This tool tries to give
15 | the look and feel of `diff --color` or `colordiff`, but extending the
16 | display of colored output from red for deleted lines and green for added
17 | lines to red for deleted characters and green for added characters within
18 | the changed lines.
19 |
20 | The tool has options to choose your own favorite color combinations, as
21 | long as they are supported by
22 | [Term::ANSIColor](https://metacpan.org/pod/Term::ANSIColor).
23 |
24 | If you want no colors but indicators below the removed/added characters
25 | in the output, which is very useful if you want to email the output, the
26 | option `--no-color` adds those indicators. With the `--fancy` option you
27 | will get Unicode characters.
28 |
29 | # Installation
30 |
31 | Change the first line of `ccdiff` to start your favorite perl interpreter
32 | and then move the file to a folder in your `$PATH`, or install from CPAN:
33 | ```
34 | $ cpan App::ccdiff
35 | ```
36 |
37 | # Alternatives
38 |
39 | ## Command line / CLI
40 |
41 | * `diff`
42 |
43 | * `diff --color`
44 |
45 | * [`colordiff`](https://www.colordiff.org/)
46 |
47 | * [`klondiff`](https://github.com/pierstitus/klondiff)
48 |
49 | * [`diff-so-fancy`](https://github.com/so-fancy/diff-so-fancy)
50 |
51 | * `git`
52 |
53 | This however requires a long command:
54 | ```
55 | $ git -c color.diff.new='bold reverse green' \
56 | -c color.diff.old='bold reverse red' \
57 | diff --no-index -U0 --no-color \
58 | --word-diff=color --word-diff-regex=. \
59 |
60 | ```
61 | An alternative for integration with git is `diff-so-fancy`
62 |
63 | ## ASCII
64 |
65 | * `vimdiff`
66 |
67 | ## GUI
68 |
69 | Please never use the `xdiff` command (if available at all), because it is
70 | included in many distributions and/or packages and they all work different
71 | or not at all. Some at not intended to be invoked from the command line.
72 |
73 | The list is in increasing clarity of the tool being able to show *minor*
74 | changes in lines visually outstanding:
75 |
76 | * `mgdiff` (C, X11)
77 |
78 | * `diffuse` (Python)
79 |
80 | * `bcompare` (C, X11, not freeware/opensource)
81 |
82 | * `kompare` (C, X11, KDE)
83 |
84 | * `xxdiff` (C, X11)
85 |
86 | * `meld` (Python)
87 |
88 | * `kdiff3` (C, X11, Qt)
89 |
90 | * `tkdiff` (Tcl/Tk)
91 |
92 | ## Other (not checked yet)
93 |
94 | Reasons for not checking include Windows and emacs.
95 |
96 | * araxis
97 | * bc
98 | * bc3
99 | * codecompare
100 | * deltaworker
101 | * diffmerge
102 | * ecmerge
103 | * emerge
104 | * examdiff
105 | * guiffy
106 | * gvimdiff2
107 | * gvimdiff3
108 | * opendiff
109 | * p4merge
110 | * winmerge
111 |
112 | # Dependencies
113 |
114 | This tool will run on recent perl distributions that have
115 | [Algorithm::Diff](https://metacpan.org/pod/Algorithm::Diff)
116 | installed. The modules
117 | [Term::ANSIColor](https://metacpan.org/pod/Term::ANSIColor)
118 | and [Getopt::Long](https://metacpan.org/pod/Getopt::Long)
119 | that are also used are part of the perl CORE distribution
120 | since at least version 5.6.0.
121 | ```
122 | suse# zypper in perl-Algorithm-Diff
123 |
124 | centos# yum install -y perl-Algorithm-Diff
125 |
126 | other# cpan Algorithm::Diff
127 | ```
128 | # Git integration
129 |
130 | You can use ccdiff to show diffs in git. It may work like this:
131 | ```
132 | $ git config --global diff.tool ccdiff
133 | $ git config --global difftool.prompt false
134 | $ git config --global difftool.ccdiff.cmd 'ccdiff --utf-8 -u -r $LOCAL $REMOTE'
135 | $ git difftool SHA~..SHA
136 | $ wget https://github.com/Tux/App-ccdiff/raw/master/Files/git-ccdiff \
137 | -O ~/bin/git-ccdiff
138 | $ perl -pi -e 's{/pro/bin/perl}{/usr/bin/env perl}' ~/bin/git-ccdiff
139 | $ chmod 755 ~/bin/git-ccdiff
140 | $ git ccdiff SHA
141 | ```
142 |
143 | Of course you can use `curl` instead of `wget` and you can choose your own
144 | (fixed) path to `perl` instead of using `/usr/bin/env`.
145 |
146 | ## LIMITATIONS
147 |
148 | There is no provision (yet) for coping with double-width characters.
149 |
150 | Large datasets may consume all available memory, causing the diff to fail.
151 |
152 | Not all that can be set from the configuration files can be overruled by
153 | command-line options.
154 |
155 | ## LICENSE
156 |
157 | The Artistic License 2.0
158 |
159 | Copyright (c) 2018-2025 H.Merijn Brand
160 |
--------------------------------------------------------------------------------
/Talk/termcap:
--------------------------------------------------------------------------------
1 | # xterm nxterm, xterm-color
2 | # wy60
3 | # vt320
4 | # vt220
5 |
6 | # Xterm (nxterm-color)
7 | #
8 | # No defs (yet) for: bt, ei, ko, vb, sa, mh, mk, mp, Va .. Vp,
9 | # ws, we, re, nm,
10 | # Status line: :ds=\E[?E:fs=\E[?F:ts=\E[?E\E[?%i%dT:
11 | # (De-)Init: :ks=\E[?1h\E=:ke=\E[?1l\E>:
12 | # :is=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l:
13 | # :rs=\E[r\E<\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l:
14 | # :ti=\E7\E[?47h:
15 | # :te=\E[2J\E[?47l\E8:
16 | v6|xterm|xterm Reflection X terminal emulator:\
17 | :bs:mi:pt:es:hs:xn:km:LC:MT:\
18 | :co#80:li#25:sg#0:ug#0:wg#0:yg#1:rg#0:\
19 | :bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:\
20 | :cm=\E[%i%d;%dH:cr=\r:ta=\t:\
21 | :le=\b:nd=\E[C:up=\E[A:do=\E[B:\
22 | :LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:DO=\E[%dB:\
23 | :ic=\E[@:dc=\E[P:al=\E[L:dl=\E[M:\
24 | :IC=\E[%d@:DC=\E[%dP:AL=\E[%dL:DL=\E[%dM:\
25 | :gb=l:gk=q:gc=k:\
26 | :gf=l:gn=w:gg=k:\
27 | :gm=t:gi=n:gl=u:gj=x:\
28 | :ge=m:go=v:gh=j:\
29 | :ga=m:gs=\E(0:gx=\E(B:gd=j:\
30 | :ho=\E[1;1H:\
31 | :k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~:\
32 | :k5=\E[15~:k6=\E[17~:k7=\E[18~:k8=\E[19~:\
33 | :k9=\E[20~:ka=\E[21~:F1=\E[23~:F2=\E[24~:\
34 | :kb=\177:kl=\E[D:ku=\E[A:kd=\E[B:kr=\E[C:\
35 | :kD=\177:kI=\E[2~:kN=\E[6~:kP=\E[5~:\
36 | :nl=\n:sf=\n:sr=\EM:\
37 | :mb=@:md=\E[1m:me=\E[0m:mr=\E[7m:\
38 | :ks=\E[?1l\E>\E[?7h:ke=\E?1l:\
39 | :so=\E[0;7m:se=\E[0m:ue=\E[24m:us=\E[4m:\
40 | :Va=\E[0m:Vc=\E[0;33m:Ve=\E[0;4m:Vg=\E[0;4;36m:\
41 | :Vi=\E[0;37;41m:Vk=\E[0;1;33;41m:Vo=\E[0;1;36;41;4m:cQ=\E?25I:
42 | # :sa=\E[%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;m:\
43 | # :vi=\E[?25I:ve=\E[?25h:vs=\E[?25h:\
44 | # :cs=\E[%i%d;%dr:ct=\E[3g:st=\EH:
45 |
46 | v3|vt320|dec vt320 8-bits emulatie:\
47 | :ul:bs:co#80:li#24:\
48 | :cl=\2332J\233;H:cm=\233%i%2;%2H:ti=\233;H:\
49 | :nd=\233C:bc=\233D:up=\233A:do=\233B:\
50 | :ce=\233K:cd=\233J:dl=\2331M:al=\2331L:\
51 | :so=\2337m:se=\23327m:us=\2334m:ue=\23324m:\
52 | :gb=\340:gk=\361:gc=\340:\
53 | :gf=\354:gn=\367:gg=\353:\
54 | :gm=\364:gi=\356:gl=\365:gj=\370:\
55 | :ge=\355:go=\366:gh=\352:\
56 | :ga=\340:gs=:gx=:gd=\340:\
57 | :FE=\2331~:kI=\2332~:kD=\2333~:\
58 | :FF=\2334~:kN=\2335~:kP=\2336~:\
59 | :ku=\1cu:kl=\1cl:kd=\1cd:kr=\1cr:i2=\33(B\33)0\33~:\
60 | :k1=\1.1:k2=\1.2:k3=\1.3:k4=\1.4:k5=\1.5:\
61 | :k6=\1.6:k7=\1.7:k8=\1.8:k9=\1.9:ka=\1.A:\
62 | :Va=\2330m:Vb=\2330;5m:Vc=\2330;1m:Vd=\2330;1;5m:Ve=\2330;4m:\
63 | :Vf=\2330;4;5m:Vg=\2330;1;4m:Vh=\2330;1;4;5m:Vi=\2330;7m:Vj=\2330;5;7m:\
64 | :Vk=\2330;1;7m:Vl=\2330;1;5;7m:Vm=\2330;4;7m:Vn=\2330;4;5;7m:\
65 | :Vo=\2330;1;4;7m:Vp=\2331;4;5;7m:
66 |
67 | W6|wy60|wy60pc|wy60xdb|wyse:\
68 | :am:bs:bw:mi:pt:\
69 | :co#80:li#25:sg#0:ug#0:wg#0:yg#1:rg#0:\
70 | :al=\EE:bl=^G:bt=\EI:cd=\Ey:ce=\Et:cl=\E*:\
71 | :cm=\E=%+ %+ :cr=^M:dc=\EW:dl=\ER:do=^J:\
72 | :ei=\Er:\
73 | :gb=\EcE\053\EcD:gk=\315:gc=\EcE\054\EcD:\
74 | :gf=\311:gn=\313:gg=\273:\
75 | :gm=\314:gi=\316:gl=\271:gj=\272:\
76 | :ge=\310:go=\312:gh=\274:\
77 | :ga=\EcE\113\EcD:gs=:gx=:gd=\EcE\114\EcD:\
78 | :ho=^^:im=\Eq:is=:\
79 | :k0=^A0\r:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:\
80 | :k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:\
81 | :ka=^AI\r:F1=^AJ\r:F2=^AK\r:F3=^AL\r:F4=^AM\r:\
82 | :F5=^AN\r:F6=^AO\r:kb=^H:kl=^H:kd=^J:kr=^L:ku=^K:\
83 | :ko=dc,al,dl,cl,bt,ce,cd,im,ei,ic:\
84 | :le=^H:mb=\EG2:me=\E(\EG0:mh=\EGp:mk=\EG1:mp=\E):\
85 | :mr=\EG4:nd=^L:nl=\n:se=\EG0:so=\EG4:ta=^I:\
86 | :ue=\EG0:up=^K:us=\EG8:\
87 | :vb=\E\^1\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\E\^0:\
88 | :Va=\EG0:Vb=\EG2:Vc=\EGp:Ve=\EG8:Vo=\EG|:Vg=\EGx:\
89 | :ws=\EGp:we=\EG0:re=\EG0:nm=\EG0:Vi=\EG4:Vk=\EGt:\
90 | :sa=\EG%'0'%?%p5%t%'\100'%+%;%?%p2%t%'\010'%+%;%?%p3%t%'\004'%+%;%?%p4%t%'\002'%+%;%?%p7%t%'\001'%+%;%c:
91 | # :sa=\EG%{48}%?%p5%t%{64}%+%;%?%p2%t%{8}%+%;%?%p3%t%{4}%+%;%?%p4%t%{2}%+%;%?%p7%t%{1}%+%;%c:
92 | #W7|wy60pc|wyse:\
93 | # :F3=^Ab\r:F4=^Ac\r:F5=^Ad\r:F6=^Ae\r:\
94 | # :tc=wy60:
95 | # :rv=\EG<:nm=\EG0:Vh=\EGz:Vd=\EGr:Vf=\EG\: kr=\377:\
96 | # :Vj=\EG6:Vl=\EGv:Vm=\EG<:Vn=\EG>:rw=\EG|:Vp=\EG~:\
97 | # :v1=\EGt:v2=\EG0:v3=\EGx:v4=\EG0:v5=\EG|:v6=\EG0:\
98 | # :ga=\EHq:gb=\EHr:gc=\EHs:gd=\EHu:ge=\EHq:gf=\EHr:\
99 | # :gg=\EHs:gh=\EHu:gi=\EHx:gj=\EHv:gk=\EHz:\
100 | # :gl=\EHy:gm=\EHt:gn=\EHp:go=\EH]:
101 | # :gb=\332:gc=\277:\
102 | # :ga=\300:gd=\331:\
103 | W8|wyse6043|wy6043:\
104 | :co#132:li#43:cm=\Ea%i%dR%dC:tc=wy60:
105 | Wn|wyse60|wy24:\
106 | :co#80:li#24:kr=^L:tc=wy60:
107 |
108 | W5|wyse50|wy50:\
109 | :is=:\
110 | :li#25:co#80:am:bs:bs:ul:mi:bw:\
111 | :cr=^M:do=^J:nl=\n:bl=^G:\
112 | :le=^H:bt=\EI:cd=\Ey:ce=\Et:cl=\E*:cm=\E=%+ %+ :\
113 | :so=\EG4:se=\EG0:sg#1:\
114 | :us=\EG8:ue=\EG0:ug#2:\
115 | :me=\E(\EG0:mb=\EG2:mp=\E):mh=\EGp:mr=\EG4:mk=\EG1:\
116 | :dc=\EW:dl=\ER:al=\EE:ei=\Er:ho=^^:im=\Eq:\
117 | :kb=^H:kl=^H:ko=ic,dc,al,dl,cl,bt,ce,cd,im,ei:\
118 | :ku=^K:nd=^L:ta=^I:bt=\EI:up=^K:do=^J:\
119 | :k0=^A0\r:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
120 | :k7=^AF\r:k8=^AG\r:k9=^AH\r:ka=^AI\r:F1=^AJ\r:F2=^AK\r:\
121 | :F3=^AL\r:F4=^AM\r:F5=^AN\r:F6=^AO\r:\
122 | :gs=\EH^B:gx=\EH^C:\
123 | :ga=1:gb=2:gc=3:gd=5:ge=q:gf=r:gg=s:gh=u:gi=x:gj=v:gk=z:\
124 | :gl=y:gm=t:gn=p:go=]:
125 |
126 | v2|xterms|dtterms|xterm terminal emulator (small)(X window system):\
127 | :co#80:li#24:tc=xterm:
128 |
129 | du|dumb:co#80:os:am:
130 |
131 | d0|vt220|vt100|vt100-am|vt100|dec vt100:\
132 | :Va=\E[m:\
133 | :Vb=\E[m\E[5m:\
134 | :Vc=\E[m\E[2m:\
135 | :Vd=\E[m\E[2;5m:\
136 | :Ve=\E[m\E[4m:\
137 | :Vf=\E[m\E[4;5m:\
138 | :Vg=\E[m\E[2;4m:\
139 | :Vh=\E[m\E[2;4;5m:\
140 | :Vi=\E[m\E[7m:\
141 | :Vj=\E[m\E[5;7m:\
142 | :Vk=\E[m\E[2;7m:\
143 | :Vl=\E[m\E[2;5;7m:\
144 | :Vm=\E[m\E[4;7m:\
145 | :Vn=\E[m\E[4;5;7m:\
146 | :Vo=\E[m\E[2;4;7m:\
147 | :Vp=\E[m\E[2;4;5;7m:\
148 | :cr=^M:do=^J:nl=^J:bl=^G:co#80:li#24:cl=50\E[;H\E[2J:\
149 | :so=\E[7m:\
150 | :se=\E[m\E[1m:\
151 | :us=\E[4m:\
152 | :ue=\E[m\E[1m:\
153 | :ws=\E[m:\
154 | :we=\E[1m:\
155 | :ys=\E[5m:\
156 | :ye=\E[m\E[1m:\
157 | :rv=\E[m\E[1;7;4m:\
158 | :rl=\E[m\E[7m:\
159 | :rw=\E[m\E[7;4m:\
160 | :nm=\E[m\E[1m:\
161 | :le=^H:bs:am:cm=5\E[%i%d;%dH:up=2\E[A:\
162 | :ce=\E[K:cd=50\E[J:\
163 | :md=2\E[1m:mr=2\E[7m:mb=2\E[5m:me=2\E[m:is=\E[1m;24r\E[24;1H:\
164 | :rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:ks=\E[?1h\E=:ke=\E[?1l\E>:\
165 | :rf=/usr/lib/tabset/vt100:ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\
166 | :ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:ta=^I:pt:sr=5\EM:vt#3:xn:\
167 | :gs=\E(0:gx=\E(B:ga=m:gb=l:gc=k:gd=j:ge=m:gf=l:gg=k:gh=j:\
168 | :gi=n:gj=x:gk=q:gl=u:gm=t:gn=w:go=v:\
169 | :sc=\E7:rc=\E8:cs=\E[%i%d;%dr:
170 |
--------------------------------------------------------------------------------
/Talk/termcap-blue:
--------------------------------------------------------------------------------
1 | # xterm nxterm, xterm-color
2 | # wy60
3 | # vt320
4 | # vt220
5 |
6 | # Xterm (nxterm-color)
7 | #
8 | # No defs (yet) for: bt, ei, ko, vb, sa, mh, mk, mp, Va .. Vp,
9 | # ws, we, re, nm,
10 | # Status line: :ds=\E[?E:fs=\E[?F:ts=\E[?E\E[?%i%dT:
11 | # (De-)Init: :ks=\E[?1h\E=:ke=\E[?1l\E>:
12 | # :is=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l:
13 | # :rs=\E[r\E<\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l:
14 | # :ti=\E7\E[?47h:
15 | # :te=\E[2J\E[?47l\E8:
16 | v6|xterm|xterm Reflection X terminal emulator:\
17 | :bs:mi:pt:es:hs:xn:km:LC:MT:\
18 | :co#80:li#25:sg#0:ug#0:wg#0:yg#1:rg#0:\
19 | :bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:\
20 | :cm=\E[%i%d;%dH:cr=\r:ta=\t:\
21 | :le=\b:nd=\E[C:up=\E[A:do=\E[B:\
22 | :LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:DO=\E[%dB:\
23 | :ic=\E[@:dc=\E[P:al=\E[L:dl=\E[M:\
24 | :IC=\E[%d@:DC=\E[%dP:AL=\E[%dL:DL=\E[%dM:\
25 | :gb=l:gk=q:gc=k:\
26 | :gf=l:gn=w:gg=k:\
27 | :gm=t:gi=n:gl=u:gj=x:\
28 | :ge=m:go=v:gh=j:\
29 | :ga=m:gs=\E(0:gx=\E(B:gd=j:\
30 | :ho=\E[1;1H:\
31 | :k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~:\
32 | :k5=\E[15~:k6=\E[17~:k7=\E[18~:k8=\E[19~:\
33 | :k9=\E[20~:ka=\E[21~:F1=\E[23~:F2=\E[24~:\
34 | :kb=\177:kl=\E[D:ku=\E[A:kd=\E[B:kr=\E[C:\
35 | :kD=\177:kI=\E[2~:kN=\E[6~:kP=\E[5~:\
36 | :nl=\n:sf=\n:sr=\EM:\
37 | :mb=@:md=\E[1m:me=\E[0m:mr=\E[7m:\
38 | :ks=\E[?1l\E>\E[?7h:ke=\E?1l:\
39 | :so=\E[0;7m:se=\E[0m:ue=\E[24m:us=\E[4m:\
40 | :Va=\E[0m:Vc=\E[0;36m:Ve=\E[0;4m:Vg=\E[0;4;36m:\
41 | :Vi=\E[0;37;44m:Vk=\E[0;1;37;44m:Vo=\E[0;1;36;44;4m:cQ=\E?25I:
42 | # :sa=\E[%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;m:\
43 | # :vi=\E[?25I:ve=\E[?25h:vs=\E[?25h:\
44 | # :cs=\E[%i%d;%dr:ct=\E[3g:st=\EH:
45 |
46 | v3|vt320|dec vt320 8-bits emulatie:\
47 | :ul:bs:co#80:li#24:\
48 | :cl=\2332J\233;H:cm=\233%i%2;%2H:ti=\233;H:\
49 | :nd=\233C:bc=\233D:up=\233A:do=\233B:\
50 | :ce=\233K:cd=\233J:dl=\2331M:al=\2331L:\
51 | :so=\2337m:se=\23327m:us=\2334m:ue=\23324m:\
52 | :gb=\340:gk=\361:gc=\340:\
53 | :gf=\354:gn=\367:gg=\353:\
54 | :gm=\364:gi=\356:gl=\365:gj=\370:\
55 | :ge=\355:go=\366:gh=\352:\
56 | :ga=\340:gs=:gx=:gd=\340:\
57 | :FE=\2331~:kI=\2332~:kD=\2333~:\
58 | :FF=\2334~:kN=\2335~:kP=\2336~:\
59 | :ku=\1cu:kl=\1cl:kd=\1cd:kr=\1cr:i2=\33(B\33)0\33~:\
60 | :k1=\1.1:k2=\1.2:k3=\1.3:k4=\1.4:k5=\1.5:\
61 | :k6=\1.6:k7=\1.7:k8=\1.8:k9=\1.9:ka=\1.A:\
62 | :Va=\2330m:Vb=\2330;5m:Vc=\2330;1m:Vd=\2330;1;5m:Ve=\2330;4m:\
63 | :Vf=\2330;4;5m:Vg=\2330;1;4m:Vh=\2330;1;4;5m:Vi=\2330;7m:Vj=\2330;5;7m:\
64 | :Vk=\2330;1;7m:Vl=\2330;1;5;7m:Vm=\2330;4;7m:Vn=\2330;4;5;7m:\
65 | :Vo=\2330;1;4;7m:Vp=\2331;4;5;7m:
66 |
67 | W6|wy60|wy60pc|wy60xdb|wyse:\
68 | :am:bs:bw:mi:pt:\
69 | :co#80:li#25:sg#0:ug#0:wg#0:yg#1:rg#0:\
70 | :al=\EE:bl=^G:bt=\EI:cd=\Ey:ce=\Et:cl=\E*:\
71 | :cm=\E=%+ %+ :cr=^M:dc=\EW:dl=\ER:do=^J:\
72 | :ei=\Er:\
73 | :gb=\EcE\053\EcD:gk=\315:gc=\EcE\054\EcD:\
74 | :gf=\311:gn=\313:gg=\273:\
75 | :gm=\314:gi=\316:gl=\271:gj=\272:\
76 | :ge=\310:go=\312:gh=\274:\
77 | :ga=\EcE\113\EcD:gs=:gx=:gd=\EcE\114\EcD:\
78 | :ho=^^:im=\Eq:is=:\
79 | :k0=^A0\r:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:\
80 | :k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:\
81 | :ka=^AI\r:F1=^AJ\r:F2=^AK\r:F3=^AL\r:F4=^AM\r:\
82 | :F5=^AN\r:F6=^AO\r:kb=^H:kl=^H:kd=^J:kr=^L:ku=^K:\
83 | :ko=dc,al,dl,cl,bt,ce,cd,im,ei,ic:\
84 | :le=^H:mb=\EG2:me=\E(\EG0:mh=\EGp:mk=\EG1:mp=\E):\
85 | :mr=\EG4:nd=^L:nl=\n:se=\EG0:so=\EG4:ta=^I:\
86 | :ue=\EG0:up=^K:us=\EG8:\
87 | :vb=\E\^1\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\E\^0:\
88 | :Va=\EG0:Vb=\EG2:Vc=\EGp:Ve=\EG8:Vo=\EG|:Vg=\EGx:\
89 | :ws=\EGp:we=\EG0:re=\EG0:nm=\EG0:Vi=\EG4:Vk=\EGt:\
90 | :sa=\EG%'0'%?%p5%t%'\100'%+%;%?%p2%t%'\010'%+%;%?%p3%t%'\004'%+%;%?%p4%t%'\002'%+%;%?%p7%t%'\001'%+%;%c:
91 | # :sa=\EG%{48}%?%p5%t%{64}%+%;%?%p2%t%{8}%+%;%?%p3%t%{4}%+%;%?%p4%t%{2}%+%;%?%p7%t%{1}%+%;%c:
92 | #W7|wy60pc|wyse:\
93 | # :F3=^Ab\r:F4=^Ac\r:F5=^Ad\r:F6=^Ae\r:\
94 | # :tc=wy60:
95 | # :rv=\EG<:nm=\EG0:Vh=\EGz:Vd=\EGr:Vf=\EG\: kr=\377:\
96 | # :Vj=\EG6:Vl=\EGv:Vm=\EG<:Vn=\EG>:rw=\EG|:Vp=\EG~:\
97 | # :v1=\EGt:v2=\EG0:v3=\EGx:v4=\EG0:v5=\EG|:v6=\EG0:\
98 | # :ga=\EHq:gb=\EHr:gc=\EHs:gd=\EHu:ge=\EHq:gf=\EHr:\
99 | # :gg=\EHs:gh=\EHu:gi=\EHx:gj=\EHv:gk=\EHz:\
100 | # :gl=\EHy:gm=\EHt:gn=\EHp:go=\EH]:
101 | # :gb=\332:gc=\277:\
102 | # :ga=\300:gd=\331:\
103 | W8|wyse6043|wy6043:\
104 | :co#132:li#43:cm=\Ea%i%dR%dC:tc=wy60:
105 | Wn|wyse60|wy24:\
106 | :co#80:li#24:kr=^L:tc=wy60:
107 |
108 | W5|wyse50|wy50:\
109 | :is=:\
110 | :li#25:co#80:am:bs:bs:ul:mi:bw:\
111 | :cr=^M:do=^J:nl=\n:bl=^G:\
112 | :le=^H:bt=\EI:cd=\Ey:ce=\Et:cl=\E*:cm=\E=%+ %+ :\
113 | :so=\EG4:se=\EG0:sg#1:\
114 | :us=\EG8:ue=\EG0:ug#2:\
115 | :me=\E(\EG0:mb=\EG2:mp=\E):mh=\EGp:mr=\EG4:mk=\EG1:\
116 | :dc=\EW:dl=\ER:al=\EE:ei=\Er:ho=^^:im=\Eq:\
117 | :kb=^H:kl=^H:ko=ic,dc,al,dl,cl,bt,ce,cd,im,ei:\
118 | :ku=^K:nd=^L:ta=^I:bt=\EI:up=^K:do=^J:\
119 | :k0=^A0\r:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
120 | :k7=^AF\r:k8=^AG\r:k9=^AH\r:ka=^AI\r:F1=^AJ\r:F2=^AK\r:\
121 | :F3=^AL\r:F4=^AM\r:F5=^AN\r:F6=^AO\r:\
122 | :gs=\EH^B:gx=\EH^C:\
123 | :ga=1:gb=2:gc=3:gd=5:ge=q:gf=r:gg=s:gh=u:gi=x:gj=v:gk=z:\
124 | :gl=y:gm=t:gn=p:go=]:
125 |
126 | v2|xterms|dtterms|xterm terminal emulator (small)(X window system):\
127 | :co#80:li#24:tc=xterm:
128 |
129 | du|dumb:co#80:os:am:
130 |
131 | d0|vt220|vt100|vt100-am|vt100|dec vt100:\
132 | :Va=\E[m:\
133 | :Vb=\E[m\E[5m:\
134 | :Vc=\E[m\E[2m:\
135 | :Vd=\E[m\E[2;5m:\
136 | :Ve=\E[m\E[4m:\
137 | :Vf=\E[m\E[4;5m:\
138 | :Vg=\E[m\E[2;4m:\
139 | :Vh=\E[m\E[2;4;5m:\
140 | :Vi=\E[m\E[7m:\
141 | :Vj=\E[m\E[5;7m:\
142 | :Vk=\E[m\E[2;7m:\
143 | :Vl=\E[m\E[2;5;7m:\
144 | :Vm=\E[m\E[4;7m:\
145 | :Vn=\E[m\E[4;5;7m:\
146 | :Vo=\E[m\E[2;4;7m:\
147 | :Vp=\E[m\E[2;4;5;7m:\
148 | :cr=^M:do=^J:nl=^J:bl=^G:co#80:li#24:cl=50\E[;H\E[2J:\
149 | :so=\E[7m:\
150 | :se=\E[m\E[1m:\
151 | :us=\E[4m:\
152 | :ue=\E[m\E[1m:\
153 | :ws=\E[m:\
154 | :we=\E[1m:\
155 | :ys=\E[5m:\
156 | :ye=\E[m\E[1m:\
157 | :rv=\E[m\E[1;7;4m:\
158 | :rl=\E[m\E[7m:\
159 | :rw=\E[m\E[7;4m:\
160 | :nm=\E[m\E[1m:\
161 | :le=^H:bs:am:cm=5\E[%i%d;%dH:up=2\E[A:\
162 | :ce=\E[K:cd=50\E[J:\
163 | :md=2\E[1m:mr=2\E[7m:mb=2\E[5m:me=2\E[m:is=\E[1m;24r\E[24;1H:\
164 | :rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:ks=\E[?1h\E=:ke=\E[?1l\E>:\
165 | :rf=/usr/lib/tabset/vt100:ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\
166 | :ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:ta=^I:pt:sr=5\EM:vt#3:xn:\
167 | :gs=\E(0:gx=\E(B:ga=m:gb=l:gc=k:gd=j:ge=m:gf=l:gg=k:gh=j:\
168 | :gi=n:gj=x:gk=q:gl=u:gm=t:gn=w:go=v:\
169 | :sc=\E7:rc=\E8:cs=\E[%i%d;%dr:
170 |
--------------------------------------------------------------------------------
/doc/make-doc.pl:
--------------------------------------------------------------------------------
1 | #!/pro/bin/perl
2 |
3 | use 5.038002;
4 | use warnings;
5 |
6 | our $VERSION = "0.05 - 20250116";
7 | our $CMD = $0 =~ s{.*/}{}r;
8 |
9 | sub usage {
10 | my $err = shift and select STDERR;
11 | say "usage: $CMD [-v[#]] [--pod]";
12 | exit $err;
13 | } # usage
14 |
15 | use Cwd;
16 | use Pod::Text;
17 | use File::Find;
18 | use List::Util qw( first );
19 | use Encode qw( encode decode );
20 | use Getopt::Long qw(:config bundling);
21 | GetOptions (
22 | "help|?" => sub { usage (0); },
23 | "V|version" => sub { say "$CMD [$VERSION]"; exit 0; },
24 |
25 | "p|pod!" => \ my $pod,
26 |
27 | "v|verbose:1" => \(my $opt_v = 0),
28 | ) or usage (1);
29 |
30 | -d "doc" or mkdir "doc", 0775;
31 |
32 | my @pm; # Do *NOT* scan t/
33 | -d "lib" and find (sub { m/\.pm$/ and push @pm => $File::Find::name }, "lib");
34 | @pm or @pm = sort glob "*.pm";
35 | if (@pm == 0 and open my $fh, "<", "Makefile.PL") {
36 | my @mpl = <$fh>;
37 | close $fh;
38 | if (my @vf = grep m/\bVERSION_FROM\s*=>\s*(.*)/) {
39 | push @pm => $vf[0] =~ s/["']//gr;
40 | last;
41 | }
42 | if (my @ef = grep m/\bEXE_FILES\s*=>\s*\[(.*)\]/) {
43 | push @pm => eval qq{($1)};
44 | last;
45 | }
46 | }
47 |
48 | push @pm => @ARGV;
49 | @pm = sort grep { ! -l $_ } @pm;
50 | @pm or die "No documentation source files found\n";
51 |
52 | if ($opt_v) {
53 | say "Using these sources for static documentation:";
54 | say " $_" for @pm;
55 | }
56 |
57 | sub dext {
58 | my ($pm, $ext) = @_;
59 | my $fn = $pm =~ s{^lib/}{}r
60 | =~ s{^(?:App|scripts|examples)/}{}r
61 | =~ s{/}{-}gr
62 | =~ s{(?:\.pm)?$}{.$ext}r # examples, scripts
63 | =~ s{^(?=CSV_XS\.)}{Text-}r
64 | =~ s{^(?=Peek\.)} {Data-}r
65 | =~ s{^(?=Read\.)} {Spreadsheet-}r
66 | =~ s{^(SpeedTest)} {\L$1}ri
67 | =~ s{^}{doc/}r;
68 | getcwd =~ m/Config-Perl/ and
69 | $fn =~ s{doc/\K}{Config-Perl-};
70 | $fn;
71 | } # dext
72 |
73 | my %enc;
74 | my %pod;
75 | { # Check if file had pod at all
76 | foreach my $pm (@pm) {
77 | open my $fh, ">", \$pod{$pm};
78 | Pod::Text->new->parse_from_file ($pm, $fh);
79 | close $fh;
80 |
81 | $pod && $pod{$pm} and link $pm => dext ($pm, "pod");
82 | }
83 | }
84 |
85 | eval { require Pod::Checker; };
86 | if ($@) {
87 | warn "Cannot convert pod to markdown: $@\n";
88 | }
89 | else {
90 | my $fail = 0;
91 | my %ignore_empty = (
92 | "lib/DBI/ProfileData.pm" => 7,
93 | "Peek.pm" => 4,
94 | "Read.pm" => 5,
95 | );
96 | foreach my $pm (@pm) {
97 | open my $eh, ">", \my $err;
98 | my $pc = Pod::Checker->new ();
99 | my $ok = $pc->parse_from_file ($pm, $eh);
100 | close $eh;
101 | $enc{$pm} = $pc->{encoding};
102 | $err && $err =~ m/\S/ or next;
103 | # Ignore warnings here on empty previous paragraphs as it
104 | # uses =head2 for all possible invocation alternatives
105 | if (my $ni = $ignore_empty{$pm}) {
106 | my $pat = qr{ WARNING: empty section };
107 | my @err = split m/\n+/ => $err;
108 | my @wrn = grep m/$pat/ => @err;
109 | @wrn == $ni and $err = join "\n" => grep !m/$pat/ => @err;
110 | $err =~ m/\S/ or next;
111 | }
112 | say $pm;
113 | say $err;
114 | $err =~ m/ ERROR:/ and $fail++;
115 | }
116 | $fail and die "POD has errors. Fix them first!\n";
117 | }
118 |
119 | eval { require Pod::Markdown; };
120 | if ($@) {
121 | warn "Cannot convert pod to markdown: $@\n";
122 | }
123 | else {
124 | foreach my $pm (@pm) {
125 | my $md = dext ($pm, "md");
126 | my $enc = $enc{$pm} ? "encoding($enc{$pm})" : "bytes";
127 | printf STDERR "%-43s <- %s (%s)\n", $md, $pm, $enc if $opt_v;
128 | open my $ph, "<:$enc", $pm;
129 | my $p = Pod::Markdown->new ();
130 | $p->output_string (\my $m);
131 | $p->parse_file ($ph);
132 | close $ph;
133 |
134 | $m && $m =~ m/\S/ or next;
135 | if (open my $old, "<:encoding(utf-8)", $md) {
136 | local $/;
137 | $m eq scalar <$old> and next;
138 | }
139 | $opt_v and say "Writing $md (", length $m, ")";
140 | open my $oh, ">:encoding(utf-8)", $md or die "$md: $!\n";
141 | print $oh $m;
142 | close $oh;
143 | }
144 | }
145 |
146 | eval { require Pod::Html; };
147 | if ($@) {
148 | warn "Cannot convert pod to HTML: $@\n";
149 | }
150 | else {
151 | foreach my $pm (@pm) {
152 | $pod{$pm} or next; # Skip HTML for files without pod
153 | my $html = dext ($pm, "html");
154 | printf STDERR "%-43s <- %s (%s)\n", $html, $pm, $enc{$pm} // "-" if $opt_v;
155 | my $tf = "x_$$.html";
156 | unlink $tf if -e $tf;
157 | Pod::Html::pod2html ("--infile=$pm", "--outfile=$tf", "--quiet");
158 | my $h = do { local (@ARGV, $/) = ($tf); <> } =~ s/[\r\n\s]+\z/\n/r;
159 | unlink $tf if -e $tf;
160 | $h && $h =~ m/\S/ or next;
161 | if (open my $old, "<:encoding(utf-8)", $html) {
162 | local $/;
163 | $h eq scalar <$old> and next;
164 | }
165 | $opt_v and say "Writing $html (", length $h, ")";
166 | open my $oh, ">:encoding(utf-8)", $html or die "$html: $!\n";
167 | print $oh $h;
168 | close $oh;
169 | }
170 | unlink "pod2htmd.tmp";
171 | }
172 |
173 | eval { require Pod::Man; };
174 | if ($@) {
175 | warn "Cannot convert pod to man: $@\n";
176 | }
177 | else {
178 | my $nrf = first { -x }
179 | map { "$_/nroff" }
180 | grep { length and -d }
181 | split m/:+/ => $ENV{PATH};
182 | $opt_v and say $nrf;
183 | foreach my $pm (@pm) {
184 | my $man = dext ($pm, "3");
185 | printf STDERR "%-43s <- %s\n", $man, $pm if $opt_v;
186 | open my $fh, ">", \my $p;
187 | Pod::Man->new (section => 3)->parse_from_file ($pm, $fh);
188 | close $fh;
189 | $p && $p =~ m/\S/ or next;
190 | $p = decode ("utf-8", $p);
191 | if (open my $old, "<:encoding(utf-8)", $man) {
192 | local $/;
193 | $p eq scalar <$old> and next;
194 | }
195 | $opt_v and say "Writing $man (", length $p, ")";
196 | open my $oh, ">:encoding(utf-8)", $man or die "$man: $!\n";
197 | print $oh $p;
198 | close $oh;
199 | $nrf or next;
200 | if (open my $fh, "-|", $nrf, "-mandoc", "-T", "utf8", $man) {
201 | local $/;
202 | $p = <$fh>;
203 | close $fh;
204 | $p = decode ("utf-8", $p
205 | =~ s{(?:\x{02dc}|\xcb\x9c )}{~}grx # ~
206 | =~ s{(?:\x{02c6}|\xcb\x86 )}{^}grx # ^
207 | =~ s{(?:\x{2018}|\xe2\x80\x98
208 | |\x{2019}|\xe2\x80\x99 )}{'}grx # '
209 | =~ s{(?:\x{201c}|\xe2\x80\x9c
210 | |\x{201d}|\xe2\x80\x9d )}{"}grx # "
211 | =~ s{(?:\x{2212}|\xe2\x88\x92
212 | |\x{2010}|\xe2\x80\x90 )}{-}grx # -
213 | =~ s{(?:\x{2022}|\xe2\x80\xa2 )}{*}grx # BULLET
214 | =~ s{(?:\e\[|\x9b)[0-9;]*m} {}grx); # colors
215 | }
216 |
217 | my $mfn = $man =~ s/3$/man/r;
218 | if (open my $mh, "<:encoding(utf-8)", $mfn) {
219 | local $/;
220 | $p eq <$mh> and next;
221 | }
222 | $opt_v and say "Writing $mfn (", length $p, ")";
223 | open $oh, ">:encoding(utf-8)", $mfn or die "$mfn: $!\n";
224 | # nroff / troff / grotty cause double-encoding
225 | print $oh encode ("iso-8859-1", decode ("utf-8", $p));
226 | close $oh;
227 | }
228 | }
229 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The Artistic License 2.0
2 |
3 | Copyright (c) 2018-2025 H.Merijn Brand
4 |
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | This license establishes the terms under which a given free software
11 | Package may be copied, modified, distributed, and/or redistributed.
12 | The intent is that the Copyright Holder maintains some artistic
13 | control over the development of that Package while still keeping the
14 | Package available as open source and free software.
15 |
16 | You are always permitted to make arrangements wholly outside of this
17 | license directly with the Copyright Holder of a given Package. If the
18 | terms of this license do not permit the full use that you propose to
19 | make of the Package, you should contact the Copyright Holder and seek
20 | a different licensing arrangement.
21 |
22 | Definitions
23 |
24 | "Copyright Holder" means the individual(s) or organization(s)
25 | named in the copyright notice for the entire Package.
26 |
27 | "Contributor" means any party that has contributed code or other
28 | material to the Package, in accordance with the Copyright Holder's
29 | procedures.
30 |
31 | "You" and "your" means any person who would like to copy,
32 | distribute, or modify the Package.
33 |
34 | "Package" means the collection of files distributed by the
35 | Copyright Holder, and derivatives of that collection and/or of
36 | those files. A given Package may consist of either the Standard
37 | Version, or a Modified Version.
38 |
39 | "Distribute" means providing a copy of the Package or making it
40 | accessible to anyone else, or in the case of a company or
41 | organization, to others outside of your company or organization.
42 |
43 | "Distributor Fee" means any fee that you charge for Distributing
44 | this Package or providing support for this Package to another
45 | party. It does not mean licensing fees.
46 |
47 | "Standard Version" refers to the Package if it has not been
48 | modified, or has been modified only in ways explicitly requested
49 | by the Copyright Holder.
50 |
51 | "Modified Version" means the Package, if it has been changed, and
52 | such changes were not explicitly requested by the Copyright
53 | Holder.
54 |
55 | "Original License" means this Artistic License as Distributed with
56 | the Standard Version of the Package, in its current version or as
57 | it may be modified by The Perl Foundation in the future.
58 |
59 | "Source" form means the source code, documentation source, and
60 | configuration files for the Package.
61 |
62 | "Compiled" form means the compiled bytecode, object code, binary,
63 | or any other form resulting from mechanical transformation or
64 | translation of the Source form.
65 |
66 |
67 | Permission for Use and Modification Without Distribution
68 |
69 | (1) You are permitted to use the Standard Version and create and use
70 | Modified Versions for any purpose without restriction, provided that
71 | you do not Distribute the Modified Version.
72 |
73 |
74 | Permissions for Redistribution of the Standard Version
75 |
76 | (2) You may Distribute verbatim copies of the Source form of the
77 | Standard Version of this Package in any medium without restriction,
78 | either gratis or for a Distributor Fee, provided that you duplicate
79 | all of the original copyright notices and associated disclaimers. At
80 | your discretion, such verbatim copies may or may not include a
81 | Compiled form of the Package.
82 |
83 | (3) You may apply any bug fixes, portability changes, and other
84 | modifications made available from the Copyright Holder. The resulting
85 | Package will still be considered the Standard Version, and as such
86 | will be subject to the Original License.
87 |
88 |
89 | Distribution of Modified Versions of the Package as Source
90 |
91 | (4) You may Distribute your Modified Version as Source (either gratis
92 | or for a Distributor Fee, and with or without a Compiled form of the
93 | Modified Version) provided that you clearly document how it differs
94 | from the Standard Version, including, but not limited to, documenting
95 | any non-standard features, executables, or modules, and provided that
96 | you do at least ONE of the following:
97 |
98 | (a) make the Modified Version available to the Copyright Holder
99 | of the Standard Version, under the Original License, so that the
100 | Copyright Holder may include your modifications in the Standard
101 | Version.
102 |
103 | (b) ensure that installation of your Modified Version does not
104 | prevent the user installing or running the Standard Version. In
105 | addition, the Modified Version must bear a name that is different
106 | from the name of the Standard Version.
107 |
108 | (c) allow anyone who receives a copy of the Modified Version to
109 | make the Source form of the Modified Version available to others
110 | under
111 |
112 | (i) the Original License or
113 |
114 | (ii) a license that permits the licensee to freely copy,
115 | modify and redistribute the Modified Version using the same
116 | licensing terms that apply to the copy that the licensee
117 | received, and requires that the Source form of the Modified
118 | Version, and of any works derived from it, be made freely
119 | available in that license fees are prohibited but Distributor
120 | Fees are allowed.
121 |
122 |
123 | Distribution of Compiled Forms of the Standard Version
124 | or Modified Versions without the Source
125 |
126 | (5) You may Distribute Compiled forms of the Standard Version without
127 | the Source, provided that you include complete instructions on how to
128 | get the Source of the Standard Version. Such instructions must be
129 | valid at the time of your distribution. If these instructions, at any
130 | time while you are carrying out such distribution, become invalid, you
131 | must provide new instructions on demand or cease further distribution.
132 | If you provide valid instructions or cease distribution within thirty
133 | days after you become aware that the instructions are invalid, then
134 | you do not forfeit any of your rights under this license.
135 |
136 | (6) You may Distribute a Modified Version in Compiled form without
137 | the Source, provided that you comply with Section 4 with respect to
138 | the Source of the Modified Version.
139 |
140 |
141 | Aggregating or Linking the Package
142 |
143 | (7) You may aggregate the Package (either the Standard Version or
144 | Modified Version) with other packages and Distribute the resulting
145 | aggregation provided that you do not charge a licensing fee for the
146 | Package. Distributor Fees are permitted, and licensing fees for other
147 | components in the aggregation are permitted. The terms of this license
148 | apply to the use and Distribution of the Standard or Modified Versions
149 | as included in the aggregation.
150 |
151 | (8) You are permitted to link Modified and Standard Versions with
152 | other works, to embed the Package in a larger work of your own, or to
153 | build stand-alone binary or bytecode versions of applications that
154 | include the Package, and Distribute the result without restriction,
155 | provided the result does not expose a direct interface to the Package.
156 |
157 |
158 | Items That are Not Considered Part of a Modified Version
159 |
160 | (9) Works (including, but not limited to, modules and scripts) that
161 | merely extend or make use of the Package, do not, by themselves, cause
162 | the Package to be a Modified Version. In addition, such works are not
163 | considered parts of the Package itself, and are not subject to the
164 | terms of this license.
165 |
166 |
167 | General Provisions
168 |
169 | (10) Any use, modification, and distribution of the Standard or
170 | Modified Versions is governed by this Artistic License. By using,
171 | modifying or distributing the Package, you accept this license. Do not
172 | use, modify, or distribute the Package, if you do not accept this
173 | license.
174 |
175 | (11) If your Modified Version has been derived from a Modified
176 | Version made by someone other than you, you are nevertheless required
177 | to ensure that your Modified Version complies with the requirements of
178 | this license.
179 |
180 | (12) This license does not grant you the right to use any trademark,
181 | service mark, tradename, or logo of the Copyright Holder.
182 |
183 | (13) This license includes the non-exclusive, worldwide,
184 | free-of-charge patent license to make, have made, use, offer to sell,
185 | sell, import and otherwise transfer the Package with respect to any
186 | patent claims licensable by the Copyright Holder that are necessarily
187 | infringed by the Package. If you institute patent litigation
188 | (including a cross-claim or counterclaim) against any party alleging
189 | that the Package constitutes direct or contributory patent
190 | infringement, then this Artistic License to you shall terminate on the
191 | date that such litigation is filed.
192 |
193 | (14) Disclaimer of Warranty:
194 | THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
195 | IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
196 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
197 | NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
198 | LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
199 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
200 | DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
201 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
202 |
203 |
--------------------------------------------------------------------------------
/sandbox/test1.xml:
--------------------------------------------------------------------------------
1 |
2 | ccdiff_PNAQQ;_9IRQ 5@@7gi3_VEJ_aOb;120MZO6HYWHWAL+QhKSZ1e7WWiaHM3jeUHG+C_3TV8KF2g?IBZLJ5bGbSFdaDWVHL65W44FX;H:?HD4MPjTZR5fFZD i+c1jTBeEga9QPdYeT3I@W;TQ^JOT+9SaMRe5_U1IT3U^PAP +VOQ:CG2EBODEIE988VRPCUMFPjM2 JA3J7#9FPi6bTK14AF8HL0DAFDba`QUj@F5FIUUEBQ;1:TeS`XT83DPGHPNiC64ebe#+iJ;WE+H;0fDAEif_LYU9O_NJV9`h0NHL8bCX:YCXiO`HBdf6^ERW`:jO42GUgV #d#D@HiOZ9+O2;7H6R6gIJgiBNMSJ#W34UIG;I0C7XY^DFg?RgNHeaJH:XeG0LVOOg6@jDLXZe:NF`GWD7T9h0+:9a#jeb:adU0Za1ReAR@UgF4TDa^VWcE@FceM84G;UW65SO8#dL0PJgS#DHZUQCdi74:H8e_bK_eC4I`HBMF#0O:jjhcHNSFH7^dNbSXhI;2gPZd83a;bZROC?^U2QRNAED VZ`UOPBEchgM2Pb+QOb7YMT?VNOM@3J8BWQ^KS6#9Qj;d9a?77he
3 |
--------------------------------------------------------------------------------
/sandbox/test2.xml:
--------------------------------------------------------------------------------
1 |
2 | ccdiff_PNAQQ;_9IRQ 5@@7gi3_VEJ_aOb;120MZO6HYWHWAL+QhKSZ1e7WWiaHM3jeUHG+C_3TV8KF2g?IBZLJ5bGbSFdaDWVHL65W44FX;H:?HD4MPjTZR5fFZD i+c1jTBeEga9QPdYeT3I@W;TQ^JOT+9SaMRe5_U1IT3U^PAP +VOQ:CG2EBODEIE988VRPCUMFPjM2 JA3J7#9FPi6bTK14AF8HL0DAFDba`QUj@F5FIUUEBQ;1:TeS`XT83DPGHPNiC64ebe#+iJ;WE+H;0fDAEif_LYU9O_NJV9`h0NHL8bCX:YCXiO`HBdf6^ERW`:jO42GUgV #d#D@HiOZ9+O2;7H6R6gIJgiBNMSJ#W34UIG;I0C7XY^DFg?RgNHeaJH:XeG0LVOOg6@jDLXZe:NF`GWD7T9h0+:9a#jeb:adU0Za1ReAR@UgF4TDa^VWcE@FceM84G;UW65SO8#dL0PJgS#DHZUQCdi74:H8e_bK_eC4I`HBMF#0O:jjhcHNSFH7^dNbSXhI;2gPZd83a;bZROC?^U2QRNAED VZ`UOPBEchgM2Pb+QOb7!MT?VNOM@3J8BWQ^KS6#9Qj;d9a?77he
3 |
--------------------------------------------------------------------------------
/sandbox/genMETA.pm:
--------------------------------------------------------------------------------
1 | #!/pro/bin/perl
2 |
3 | package genMETA;
4 |
5 | our $VERSION = "1.18-20250113";
6 |
7 | use 5.014001;
8 | use warnings;
9 | use Carp;
10 |
11 | use CPAN::Meta::Converter;
12 | use CPAN::Meta::Validator;
13 | use Data::Peek;
14 | use Date::Calc qw( Delta_Days );
15 | use Encode qw( encode decode );
16 | use File::Find;
17 | use JSON::PP;
18 | use List::Util qw( first );
19 | use Parse::CPAN::Meta;
20 | use Software::Security::Policy::Individual;
21 | use Term::ANSIColor qw(:constants);
22 | use Test::CPAN::Meta::YAML::Version;
23 | use Test::More ();
24 | use Text::Diff;
25 | use YAML::Syck;
26 |
27 | sub new {
28 | my $package = shift;
29 | return bless { @_ }, $package;
30 | } # new
31 |
32 | sub extract_version {
33 | my $fh = shift;
34 | my @vsn;
35 | while (<$fh>) {
36 | m/\$VERSION\b/ and push @vsn => $_;
37 | m{^(?:our\s+)? # declaration
38 | \$VERSION \s*=\s* # variable
39 | ["']? ([0-9._]+) # version
40 | (?:\s* - \s* [0-9]{4}-?[0-9]{2}-?[0-9]{2} \s*)? # date "0.01 - 20230412"
41 | ['"]?
42 | \s*;\s*
43 | (?:\x23 \s* [0-9]{4}-?[0-9]{2}-?[0-9]{2} \s*)? # date "0.01"; # 20230502
44 | $}x or next;
45 | return $1;
46 | }
47 | # No match on first scan, try without date
48 | for (@vsn) {
49 | m{^(?:our\s+)? # declaration
50 | \$VERSION \s*=\s* # variable
51 | ([""'']) ([0-9._]+) \1 # version
52 | \s*;
53 | }x or next;
54 | return $2;
55 | }
56 | } # extract_version
57 |
58 | sub version_from {
59 | my ($self, $src) = @_;
60 |
61 | $self->{mfpr} = {};
62 | if (open my $mh, "<", "Makefile.PL") {
63 | my $mf = do { local $/; <$mh> };
64 |
65 | if ($mf =~ m{\b NAME \s*=>\s* ["'] (\S+) ['"]}x) {
66 | $self->{name} = $1;
67 | $self->{name} =~ m/-/ and
68 | warn RED, "NAME in Makefile.PL contains a -", RESET, "\n";
69 | $self->{name} =~ s/::/-/g;
70 | }
71 | if ($mf =~ m{\b DISTNAME \s*=>\s* ["'] (\S+) ['"]}x) {
72 | $self->{name} = $1;
73 | }
74 |
75 | if ($mf =~ m{\b VERSION_FROM \s*=>\s* ["'] (\S+) ['"]}x) {
76 | my $from = $1;
77 | -f $from or
78 | croak RED, "Makefile wants version from nonexisten $from", RESET, "\n";
79 | $self->{from} //= $from;
80 | $from eq $self->{from} or
81 | croak RED, "VERSION_FROM mismatch Makefile.PL ($from) / YAML ($self->{from})", RESET, "\n";
82 | }
83 |
84 | if ($mf =~ m[\b PREREQ_PM \s*=>\s* \{ ( [^}]+ ) \}]x) {
85 | my @pr = split m/\n/ => $1;
86 | $self->{mfpr} = { map { (m{ \b ["']? (\S+?) ['"]? \s*=>\s* ["']? ([-0-9._]+) ['"]? }x) } grep !m/^\s*#/ => @pr };
87 | }
88 |
89 | $mf =~ m{--format=ustar} or
90 | warn RED, "TARFLAGS macro is missing", RESET, "\n";
91 | }
92 |
93 | $src //= $self->{from} or croak "No file to extract version from";
94 |
95 | open my $pm, "<", $src or croak "Cannot read $src";
96 | my $version = extract_version ($pm) or croak "Cannot extract VERSION from $src\n";
97 | close $pm;
98 | $self->{version} = $version;
99 | return $version
100 | } # version_from
101 |
102 | sub from_data {
103 | my ($self, @data) = @_;
104 | $self->{version} or $self->version_from ();
105 | s/VERSION/$self->{version}/g for @data;
106 | my ($dsct, $dmod);
107 | for (@data) {
108 | s/[ \t]+$//;
109 | m/^\s*(\w+):$/ and $dsct = $1;
110 | m/^\s*(\w(?:[\w:]+\w)?):\s+\d/ and $dmod = $1;
111 | s/\s+#\s*ignore\b\s*[:=]?\s*(\S+)$//i or next;
112 | $self->{cve_ignore}{$dsct}{$dmod} = $1;
113 | }
114 | $self->{yml} = \@data;
115 | $self->check_yaml ();
116 | $self->check_provides ();
117 | #DDumper $self->{cve_ignore};
118 | return @data;
119 | } # from_data
120 |
121 | sub check_encoding {
122 | my $self = shift;
123 | my @tf = grep m{^(?: change | readme | .*\.pod )}ix => glob "*";
124 | (my $tf = join ", " => @tf) =~ s/.*\K, / and /;
125 |
126 | print "Check if $tf are still valid UTF8 ...\n";
127 | foreach my $tf (@tf) {
128 | open my $fh, "<", $tf or croak "$tf: $!\n";
129 | my @c = <$fh>;
130 | my $c = join "" => @c;
131 | my @e;
132 | my $s = decode ("utf-8", $c, sub { push @e, shift; });
133 | if (@e) {
134 | my @l;
135 | my $n = 0;
136 | for (@c) {
137 | $n++;
138 | eval { decode ("utf-8", $_, 1) };
139 | $@ or next;
140 | $@ =~ s{ at /\S+ line \d+.*}{};
141 | print BLUE, "$tf:$n\t$_\t$@", RESET;
142 | }
143 | croak "$tf is not valid UTF-8\n";
144 | }
145 | my $u = encode ("utf-8", $s);
146 | $c eq $u and next;
147 |
148 | my $n;
149 | $n = 1; $c =~ s/^/$n++ . "\t"/gem;
150 | $n = 1; $u =~ s/^/$n++ . "\t"/gem;
151 | croak "$tf: recode makes content differ\n". diff \$c, \$u;
152 | }
153 | } # check_encoding
154 |
155 | sub check_required {
156 | my $self = shift;
157 |
158 | my $yml = $self->{h} or croak "No YAML to check";
159 |
160 | warn "Check required and recommended module versions ...\n";
161 | BEGIN { $V::NO_EXIT = $V::NO_EXIT = 1 } require V;
162 | my %req = map { %{$yml->{$_}} } grep m/requires/ => keys %{$yml};
163 | my %rec = map { %{$yml->{$_}} } grep m/recommends/ => keys %{$yml};
164 | my %sug = map { %{$yml->{$_}} } grep m/suggests/ => keys %{$yml};
165 | if (my $of = $yml->{optional_features}) {
166 | foreach my $f (values %{$of}) {
167 | my %q = map { %{$f->{$_}} } grep m/requires/ => keys %{$f};
168 | my %c = map { %{$f->{$_}} } grep m/recommends/ => keys %{$f};
169 | my %s = map { %{$f->{$_}} } grep m/suggests/ => keys %{$f};
170 | @req{keys %q} = values %q;
171 | @rec{keys %c} = values %c;
172 | @sug{keys %s} = values %s;
173 | }
174 | }
175 | if (my $of = $yml->{prereqs}) {
176 | foreach my $f (values %{$of}) {
177 | my %q = map { %{$f->{$_}} } grep m/requires/ => keys %{$f};
178 | my %c = map { %{$f->{$_}} } grep m/recommends/ => keys %{$f};
179 | my %s = map { %{$f->{$_}} } grep m/suggests/ => keys %{$f};
180 | @req{keys %q} = values %q;
181 | @rec{keys %c} = values %c;
182 | @sug{keys %s} = values %s;
183 | }
184 | }
185 | my %vsn = ( %req, %rec, %sug );
186 | delete @vsn{qw( perl version )};
187 | for (sort keys %vsn) {
188 | if (my $mfv = delete $self->{mfpr}{$_}) {
189 | $req{$_} eq $mfv or
190 | croak RED, "PREREQ mismatch for $_ Makefile.PL ($mfv) / YAML ($req{$_})", RESET, "\n";
191 | }
192 | $vsn{$_} eq "0" and next;
193 | my $v = V::get_version ($_);
194 | $v eq $vsn{$_} and next;
195 | printf STDERR "%s%-35s %-6s => %s%s%s\n", BLUE, $_, $vsn{$_}, GREEN, $v, RESET;
196 | }
197 | if (my @mfpr = grep { $_ ne "version" } sort keys %{$self->{mfpr}}) {
198 | croak RED, "Makefile.PL requires @mfpr, YAML does not", RESET, "\n";
199 | }
200 |
201 | find (sub {
202 | $File::Find::dir =~ m{^blib\b} and return;
203 | $File::Find::name =~ m{(?:^|/)Bundle/.*\.pm} or return;
204 | if (open my $bh, "<", $_) {
205 | warn "Check bundle module versions $File::Find::name ...\n";
206 | while (<$bh>) {
207 | my ($m, $dv) = m/^([A-Za-z_:]+)\s+([0-9.]+)\s*$/ or next;
208 | my $v = $m eq $self->{name} ? $self->{version} : V::get_version ($m);
209 | $v eq $dv and next;
210 | printf STDERR "%s%-35s %-6s => %s%s%s\n", BLUE, $m, $dv, GREEN, $v, RESET;
211 | }
212 | }
213 | }, glob "*");
214 | } # check_required
215 |
216 | sub check_yaml {
217 | my $self = shift;
218 |
219 | my @yml = @{$self->{yml}} or croak "No YAML to check";
220 |
221 | warn "Checking generated YAML ...\n" unless $self->{quiet};
222 | my $h;
223 | my $yml = join "", @yml;
224 | eval { $h = Load ($yml) };
225 | $@ and croak "$@\n";
226 | $self->{name} //= $h->{name};
227 | $self->{name} eq $h->{name} or
228 | croak RED, "NAME mismatch Makefile.PL / YAML", RESET, "\n";
229 | $self->{name} =~ s/-/::/g;
230 | warn "Checking for $self->{name}-$self->{version}\n" unless $self->{quiet};
231 |
232 | $self->{verbose} and print Dump $h;
233 |
234 | my $t = Test::CPAN::Meta::YAML::Version->new (data => $h);
235 | $t->parse () and
236 | croak join "\n", "Test::CPAN::Meta::YAML reported failure:", $t->errors, "";
237 |
238 | eval { Parse::CPAN::Meta::Load ($yml) };
239 | $@ and croak "$@\n";
240 |
241 | $self->{h} = $h;
242 | $self->{yaml} = $yml;
243 | } # check_yaml
244 |
245 | sub check_minimum {
246 | my $self = shift;
247 | my $reqv = $self->{h}{requires}{perl} || $self->{h}{prereqs}{runtime}{requires}{perl};
248 | my $locs;
249 |
250 | for (@_) {
251 | if (ref $_ eq "ARRAY") {
252 | $locs = { paths => $_ };
253 | }
254 | elsif (ref $_ eq "HASH") {
255 | $locs = $_;
256 | }
257 | else {
258 | $reqv = $_;
259 | }
260 | }
261 | my $paths = (join ", " => @{($locs // {})->{paths} // []}) || "default paths";
262 |
263 | $reqv or croak "No minimal required version for perl";
264 | my $tmv = 0;
265 | $reqv > 5.009 and eval "use Test::MinimumVersion::Fast; \$tmv = 1";
266 | $tmv or eval "use Test::MinimumVersion;";
267 | print "Checking if $reqv is still OK as minimal version for $paths\n";
268 | # All other minimum version checks done in xt
269 | Test::More::subtest "Minimum perl version $reqv" => sub {
270 | all_minimum_version_ok ($reqv, $locs);
271 | } or warn RED, "\n### Use 'perlver --blame' on the failing file(s)\n\n", RESET;
272 | } # check_minimum
273 |
274 | sub check_provides {
275 | my $self = shift;
276 | my $prov = $self->{h}{provides};
277 |
278 | print "Check distribution module versions ...\n";
279 |
280 | $prov or croak RED, "META does not contain a provides section", RESET, "\n";
281 |
282 | ref $prov eq "HASH" or
283 | croak RED, "The provides section in META is not a HASH", RESET, "\n";
284 |
285 | my $fail = 0;
286 | foreach my $m (sort keys %{$prov}) {
287 | my ($file, $pvsn) = @{$prov->{$m}}{qw( file version )};
288 | unless ($file) {
289 | $fail++;
290 | say RED, " provided $m does not refer to a file", RESET;
291 | next;
292 | }
293 | unless ($pvsn) {
294 | $fail++;
295 | say RED, " provided $m does not declare a version", RESET;
296 | next;
297 | }
298 |
299 | printf " Expect %5s for %-32s ", $pvsn, $m;
300 | open my $fh, "<", $file;
301 | unless ($fh) {
302 | $fail++;
303 | say RED, "$file: $!\n", RESET;
304 | next;
305 | }
306 |
307 | my $version = extract_version ($fh);
308 | close $fh;
309 | unless ($version) {
310 | $fail++;
311 | say RED, "$file does not contain a VERSION", RESET;
312 | next;
313 | }
314 |
315 | if ($version ne $pvsn) {
316 | $fail++;
317 | say RED, "mismatch: $version", RESET;
318 | next;
319 | }
320 | say "ok";
321 | }
322 |
323 | $fail and exit 1;
324 | } # check_provides
325 |
326 | sub check_changelog {
327 | # Check if the first date has been updated ...
328 | my @td = grep m/^Change(?:s|Log)$/i => glob "[Cc]*";
329 | unless (@td) {
330 | warn "No ChangeLog to check\n";
331 | return;
332 | }
333 | my %mnt = qw( jan 1 feb 2 mar 3 apr 4 may 5 jun 6 jul 7 aug 8 sep 9 oct 10 nov 11 dec 12 );
334 | open my $fh, "<", $td[0] or croak "$td[0]: $!\n";
335 | while (<$fh>) {
336 | s/\b([0-9]{4}) (?:[- ])
337 | ([0-9]{1,2}) (?:[- ])
338 | ([0-9]{1,2})\b/$3-$2-$1/x; # 2015-01-15 => 15-01-2015
339 | m/\b([0-9]{1,2}) (?:[- ])
340 | ([0-9]{1,2}|[ADFJMNOSadfjmnos][acekopu][abcgilnprtvy]) (?:[- ])
341 | ([0-9]{4})\b/x or next;
342 | my ($d, $m, $y) = ($1 + 0, ($mnt{lc $2} || $2) + 0, $3 + 0);
343 | printf STDERR "Most recent ChangeLog entry is dated %02d-%02d-%04d\n", $d, $m, $y;
344 | unless ($ENV{SKIP_CHANGELOG_DATE}) {
345 | my @t = localtime;
346 | my $D = Delta_Days ($y, $m , $d, $t[5] + 1900, $t[4] + 1, $t[3]);
347 | $D < 0 and croak RED, "Last entry in $td[0] is in the future!", RESET, "\n";
348 | $D > 2 and croak RED, "Last entry in $td[0] is not up to date ($D days ago)", RESET, "\n";
349 | $D > 0 and warn YELLOW, "Last entry in $td[0] is not today", RESET, "\n";
350 | }
351 | last;
352 | }
353 | close $fh;
354 | } # check_changelog
355 |
356 | sub done_testing {
357 | check_changelog ();
358 | Test::More::done_testing ();
359 | } # done_testing
360 |
361 | sub quiet {
362 | my $self = shift;
363 | @_ and $self->{quiet} = defined $_[0];
364 | $self->{quiet};
365 | } # quiet
366 |
367 | sub print_json {
368 | my $self = shift;
369 | my $jsn = $self->{jsn} || $self->add_json ();
370 | print JSON::PP->new->utf8 (1)->pretty (1)->encode ($jsn);
371 | } # print_json
372 |
373 | sub print_yaml {
374 | my $self = shift;
375 | print @{$self->{yml}};
376 | } # print_yaml
377 |
378 | sub write_yaml {
379 | my ($self, $out) = @_;
380 | $out ||= "META.yml";
381 | $out =~ s/\.jso?n$/.yml/;
382 | open my $fh, ">", $out or croak "$out: $!\n";
383 | print $fh @{$self->{yml}};
384 | close $fh;
385 | $self->fix_meta ($out);
386 | } # print_yaml
387 |
388 | sub add_json {
389 | my $self = shift;
390 | # Convert to meta-spec version 2
391 | # licenses are lists now
392 | my $jsn = $self->{h};
393 | $jsn->{"meta-spec"} = {
394 | version => "2",
395 | url => "https://metacpan.org/module/CPAN::Meta::Spec?#meta-spec",
396 | };
397 | exists $jsn->{resources}{license} and
398 | $jsn->{resources}{license} = [ $jsn->{resources}{license} ];
399 | delete $jsn->{distribution_type};
400 | if (exists $jsn->{license}) {
401 | if (ref $jsn->{license} eq "ARRAY") {
402 | $jsn->{license}[0] =~ s/^perl$/perl_5/i;
403 | }
404 | else {
405 | $jsn->{license} =~ s/^perl$/perl_5/i;
406 | $jsn->{license} = [ $jsn->{license} ];
407 | }
408 | }
409 | if (exists $jsn->{resources}{bugtracker}) {
410 | my $url = $jsn->{resources}{bugtracker};
411 | $jsn->{resources}{bugtracker} = {
412 | web => $url,
413 | };
414 | }
415 | if (exists $jsn->{resources}{repository}) {
416 | my $url = $jsn->{resources}{repository};
417 | my $web = $url;
418 | $url =~ s{repo.or.cz/w/}{repo.or.cz/r/};
419 | $web =~ s{repo.or.cz/r/}{repo.or.cz/w/};
420 | $jsn->{resources}{repository} = {
421 | type => "git",
422 | web => $web,
423 | url => $url,
424 | };
425 | }
426 | foreach my $sct ("", "configure_", "build_", "test_") {
427 | (my $x = $sct || "runtime") =~ s/_$//;
428 | for (qw( requires recommends suggests )) {
429 | exists $jsn->{"$sct$_"} and
430 | $jsn->{prereqs}{$x}{$_} = delete $jsn->{"$sct$_"};
431 | }
432 | }
433 |
434 | # optional features do not yet know about requires and/or recommends diirectly
435 | if (my $of = $jsn->{optional_features}) {
436 | foreach my $f (keys %$of) {
437 | if (my $r = delete $of->{$f}{requires}) {
438 | #$jsn->{prereqs}{runtime}{recommends}{$_} //= $r->{$_} for keys %$r;
439 | $of->{$f}{prereqs}{runtime}{requires} = $r;
440 | }
441 | if (my $r = delete $of->{$f}{recommends}) {
442 | #$jsn->{prereqs}{runtime}{recommends}{$_} //= $r->{$_} for keys %$r;
443 | $of->{$f}{prereqs}{runtime}{recommends} = $r;
444 | }
445 | if (my $r = delete $of->{$f}{suggests}) {
446 | #$jsn->{prereqs}{runtime}{suggests}{$_} //= $r->{$_} for keys %$r;
447 | $of->{$f}{prereqs}{runtime}{suggests} = $r;
448 | }
449 | }
450 | }
451 |
452 | $jsn = CPAN::Meta::Converter->new ($jsn)->convert (version => "2");
453 | $jsn->{generated_by} = "Author";
454 | $self->{jsn} = $jsn;
455 | } # add_json
456 |
457 | sub fix_meta {
458 | my ($self, $yf) = @_;
459 |
460 | my $jsn = $self->add_json ();
461 |
462 | my $cmv = CPAN::Meta::Validator->new ($jsn);
463 | $cmv->is_valid or
464 | croak join "\n" => RED, "META Validator found fail:\n", $cmv->errors, RESET, "";
465 |
466 | unless ($yf) {
467 | my @my = grep { -s } glob ("*/META.yml"), "META.yml" or croak "No META files";
468 | $yf = $my[0];
469 | }
470 | my $jf = $yf =~ s/yml$/json/r;
471 | open my $jh, ">", $jf or croak "Cannot update $jf: $!\n";
472 | print $jh JSON::PP->new->utf8 (1)->pretty (1)->encode ($jsn);
473 | close $jh;
474 |
475 | # Now that 2.0 JSON is corrrect, create a 1.4 YAML back from the modified stuff
476 | my $yml = $jsn;
477 | # 1.4 does not know about test_*, move them to *
478 | if (my $tp = delete $yml->{prereqs}{test}) {
479 | foreach my $phase (keys %{$tp}) {
480 | my $p = $tp->{$phase};
481 | #DDumper { $phase => $p };
482 | $yml->{prereqs}{runtime}{$phase}{$_} //= $p->{$_} for keys %{$p};
483 | }
484 | }
485 |
486 | # Optional features in 1.4 knows requires, but not recommends.
487 | # The Lancaster Consensus moves 2.0 optional recommends promote to
488 | # requires in 1.4
489 | if (my $of = $yml->{optional_features}) {
490 | foreach my $f (keys %$of) {
491 | if (my $r = delete $of->{$f}{prereqs}{runtime}{recommends}) {
492 | $of->{$f}{requires} = $r;
493 | }
494 | if (my $r = delete $of->{$f}{prereqs}{runtime}{suggests}) {
495 | $of->{$f}{suggests} = $r;
496 | }
497 | }
498 | }
499 | # runtime and test_requires are unknown as top-level in 1.4
500 | foreach my $phase (qw( xuntime test_requires )) {
501 | if (my $p = delete $yml->{$phase}) {
502 | foreach my $f (keys %$p) {
503 | $yml->{$f}{$_} ||= $p->{$f}{$_} for keys %{$p->{$f}};
504 | }
505 | }
506 | }
507 |
508 | #DDumper $yml;
509 | # This does NOT create a correct YAML id the source does not comply!
510 | $yml = CPAN::Meta::Converter->new ($yml)->convert (version => "1.4");
511 | $yml->{requires}{perl} //= $jsn->{prereqs}{runtime}{requires}{perl}
512 | // $self->{h}{requires}{perl}
513 | // "";
514 | $yml->{build_requires} && !keys %{$yml->{build_requires}} and
515 | delete $yml->{build_requires};
516 | #DDumper $yml;
517 | #exit;
518 |
519 | open my $my, ">", $yf or croak "Cannot update $yf: $!\n";
520 | print $my Dump $yml; # @{$self->{yml}};
521 | close $my;
522 |
523 | chmod 0644, glob "*/META.*";
524 | unlink glob "MYMETA*";
525 | } # fix_meta
526 |
527 | sub _cpfd {
528 | my ($self, $jsn, $sct, $f) = @_;
529 |
530 | open my $sh, ">", \my $b;
531 | my $sep = "";
532 | for (qw( requires recommends suggests )) {
533 | my $x = "$sct$_";
534 | my $s = $jsn->{$x} or next;
535 | print $sh $sep;
536 | foreach my $m (sort keys %$s) {
537 | $m eq "perl" and next;
538 | my $v = $s->{$m};
539 | printf $sh qq{%-10s "%s"}, $_, $m;
540 | my $aw = (24 - length $m); $aw < 0 and $aw = 0;
541 | printf $sh qq{%s => "%s"}, " " x $aw, $v if $v;
542 | print $sh ";";
543 | if (my $i = $self->{cve_ignore}{$x}{$m}) {
544 | print $sh " # ignore : $i";
545 | }
546 | say $sh "";
547 | }
548 | $sep = "\n";
549 | }
550 | close $sh;
551 | $sct || $f and $b and $b .= "};";
552 | return $b;
553 | } # _cpfd
554 |
555 | sub gen_cpanfile {
556 | my $self = shift;
557 |
558 | warn "Generating cpanfile ...\n";
559 | open my $fh, ">", "cpanfile";
560 |
561 | my $jsn = $self->{h};
562 | foreach my $sct_ ("", "configure_", "build_", "test_", "runtime_") {
563 |
564 | my $sct = $sct_ =~ s/_$//r;
565 |
566 | my $b = _cpfd ($self, $jsn, $sct_, 0) or next;
567 |
568 | if ($sct) {
569 | say $fh qq/\non "$sct" => sub {/;
570 | say $fh $b =~ s/^(?=\S)/ /gmr;
571 | }
572 | else {
573 | print $fh $b;
574 | }
575 | }
576 |
577 | if (my $of = $jsn->{optional_features}) {
578 | foreach my $f (sort keys %$of) {
579 | my $fs = $of->{$f};
580 | say $fh qq/\nfeature "$f", "$fs->{description}" => sub {/;#}
581 | say $fh _cpfd ($self, $fs, "", 1) =~ s/^(?=\S)/ /gmr;
582 | }
583 | }
584 |
585 | close $fh;
586 |
587 | warn "Check CVE's ...\n";
588 | if (system "cpan-cve.pl", "-d", ".") {
589 | warn "### CVE WARNING\n";
590 | warn "#\n";
591 | warn "# The current release would have recommended versions\n";
592 | warn "# with known CVE's that are not (yet) ignored\n";
593 | sleep (5);
594 | }
595 | } # gen_cpanfile
596 |
597 | sub security_md {
598 | my ($self, $update) = @_;
599 |
600 | my $sfn = "SECURITY.md";
601 | my $policy = Software::Security::Policy::Individual->new ({
602 | maintainer => $self->{h}{author}[0],
603 | program => $self->{name},
604 | timeframe => "10 days",
605 | url => $self->{h}{resources}{repository},
606 | perl_support_years => 5,
607 | });
608 |
609 | my $smd = $policy->fulltext;
610 |
611 | unless (-s $sfn) {
612 | open my $fh, ">:encoding(utf-8)", $sfn or die "$sfn: $! \n";
613 | print $fh $smd;
614 | close $fh;
615 |
616 | if (open $fh, "<", "MANIFEST") {
617 | my @m = <$fh>;
618 | close $fh;
619 | unless (grep m/^$sfn(?:\s|$)/ => @m) {
620 | open $fh, ">>", "MANIFEST" or die "MANIFEST: $!\n";
621 | say $fh "$sfn\t\tGuide for reporting security issues";
622 | close $fh;
623 | }
624 | }
625 | say "$sfn added";
626 | }
627 |
628 | open my $fh, "<:encoding(utf-8)", $sfn or die "$sfn: $!\n";
629 | my $old = do { local $/; <$fh> };
630 | close $fh;
631 |
632 | $old eq $smd and return;
633 |
634 | if ($update) {
635 | open my $fh, ">:encoding(utf-8)", $sfn or die "$sfn: $!\n";
636 | print $fh $smd;
637 | close $fh;
638 | say "$sfn updated";
639 | }
640 | else {
641 | say "$sfn required updates:";
642 | say diff \$old, \$smd;
643 | say "to apply, use $0 --check --update";
644 | }
645 | } # gen_security
646 |
647 | 1;
648 |
--------------------------------------------------------------------------------
/doc/ccdiff.md:
--------------------------------------------------------------------------------
1 | # NAME
2 |
3 | ccdiff - Colored Character diff
4 |
5 | # SYNOPSIS
6 |
7 | ccdiff [options] file1|- file2|-
8 | ccdiff [options] dir1 dir2
9 |
10 | ccdiff --help
11 | ccdiff --man
12 | ccdiff --info
13 |
14 | # DESCRIPTION
15 |
16 | Show the diff between two files on a character by character base. In contrast to
17 | the standard diff tools, this tool uses the diff algorithm horizontally for each
18 | line in the vertical diff, highlighting the changes. This is very handy in hard
19 | to spot changes like `O` to `0`, `I` to `l` or `1` and whitespace.
20 |
21 | If there are two argument, and both are a folder/directory, a recursive diff is
22 | executed. This is not available whan used as a (sub)class.
23 |
24 | # OPTIONS
25 |
26 | ## Command line options
27 |
28 | - --help -?
29 |
30 | Show a summary of the available command-line options and exit.
31 |
32 | - --version -V
33 |
34 | Show the version and exit.
35 |
36 | - --man
37 |
38 | Show this manual using pod2man and nroff.
39 |
40 | - --info
41 |
42 | Show this manual using pod2text.
43 |
44 | - --utf-8 -U
45 |
46 | All I/O (streams to compare and standard out) are in UTF-8.
47 |
48 | - --diff-class=C --dc=C --pp
49 |
50 | Select the class used to execute the diff. By default `ccdiff` will select
51 | the first available out of `Algorithm::Diff::XS` or `Algorithm::Diff`.
52 |
53 | Sometime the `XS` version fails on encoding and the pure-perl version will
54 | work just fine. You can force `ccdiff` to use either
55 |
56 | Select the pure-perl version with any of `PP`, `AD`, `Algorthm::Diff`,
57 | `Algorithm-Diff`, or `Algorithm::Diff::PP` (case insensitive).
58 | For convenience, `--dc=pp` can be abbreviated to `--pp`.
59 |
60 | --pp
61 | --dc=pp
62 | --dc=algorithm-diff
63 | --diff-class=Algorithm::Diff::PP
64 |
65 | Select the XS version with any of `XS`, `ADX`, `Algorthm::Diff::XS`, or
66 | `Algorithm-Diff-XS` (case insensitive).
67 |
68 | --dc=xs
69 | --dc=algorithm-diff-xs
70 | --diff-class=Algorithm::Diff::XS
71 |
72 | - --unified\[=3\] -u \[3\]
73 |
74 | Generate a unified diff. The number of context lines is optional. When omitted
75 | it defaults to 3. Currently there is no provision of dealing with overlapping
76 | diff chunks. If the common part between two diff chunks is shorter than twice
77 | the number of context lines, some lines may show twice.
78 |
79 | The default is to use traditional diff:
80 |
81 | 5,5c5,5
82 | < Sat Dec 18 07:00:33 1993,I.O.D.U.,,756194433,1442539
83 | ---
84 | > Sat Dec 18 07:08:33 1998,I.O.D.U.,,756194433,1442539
85 |
86 | a unified diff (-u1) would be
87 |
88 | 5,5c5,5
89 | Tue Sep 6 05:43:59 2005,B.O.Q.S.,,1125978239,1943341
90 | -Sat Dec 18 07:00:33 1993,I.O.D.U.,,756194433,1442539
91 | +Sat Dec 18 07:08:33 1998,I.O.D.U.,,756194433,1442539
92 | Mon Feb 23 10:37:02 2004,R.X.K.S.,van,1077529022,1654127
93 |
94 | - --verbose\[=1\] -v\[1\]
95 |
96 | Show an additional line for each old or new section in a change chunk (not for
97 | added or deleted lines) that shows the hexadecimal value of each character. If
98 | `--utf-8` is in effect, it will show the Unicode character name(s).
99 |
100 | This is a debugging option, so invisible characters can still be "seen".
101 |
102 | `--verbose` accepts an optional verbosity-level. On level 2 and up, all
103 | horizontal changes get left-and-right markers inserted to enable seeing the
104 | location of the ZERO WIDTH or invisible characters. With level 3 and up and
105 | Unicode enabled, the changed characters will also show the codepoint in hex.
106 |
107 | An example of this:
108 |
109 | With -Uu0v0:
110 |
111 | 1,1c1,1
112 | - A BCDE Fg
113 | + A BcdEFg
114 |
115 | With -Uu0v1:
116 |
117 | 1,1c1,1
118 | - A BCDE Fg
119 | - -- verbose : SPACE, LATIN CAPITAL LETTER C, LATIN CAPITAL LETTER D, SPACE
120 | + A BcdEFg
121 | + -- verbose : LATIN SMALL LETTER C, LATIN SMALL LETTER D, ZERO WIDTH SPACE
122 |
123 | With -Uu0v2:
124 |
125 | 1,1c1,1
126 | - A ↱ ↰B↱CD↰E↱ ↰Fg
127 | - -- verbose : SPACE, LATIN CAPITAL LETTER C, LATIN CAPITAL LETTER D, SPACE
128 | + A B↱cd↰E↱↰Fg
129 | + -- verbose : LATIN SMALL LETTER C, LATIN SMALL LETTER D, ZERO WIDTH SPACE
130 |
131 | With -Uu0v3:
132 |
133 | 1,1c1,1
134 | - A ↱ ↰B↱CD↰E↱ ↰Fg
135 | - -- verbose : SPACE (U+000020), LATIN CAPITAL LETTER C (U+000043), LATIN CAPITAL LETTER D (U+000044), SPACE (U+000020)
136 | + A B↱cd↰E↱↰Fg
137 | + -- verbose : LATIN SMALL LETTER C (U+000063), LATIN SMALL LETTER D (U+000064), ZERO WIDTH SPACE (U+00200B)
138 |
139 | With -Uu0v2 --ascii:
140 |
141 | 1,1c1,1
142 | - A > CD cd Sat Dec 18 07:08:33 1998,I.O.D.U.,,756194433,1442539
79 |
80 | a unified diff (-u1) would be
81 |
82 | 5,5c5,5
83 | Tue Sep 6 05:43:59 2005,B.O.Q.S.,,1125978239,1943341
84 | -Sat Dec 18 07:00:33 1993,I.O.D.U.,,756194433,1442539
85 | +Sat Dec 18 07:08:33 1998,I.O.D.U.,,756194433,1442539
86 | Mon Feb 23 10:37:02 2004,R.X.K.S.,van,1077529022,1654127
87 |
88 | --verbose[=1] -v[1]
89 | Show an additional line for each old or new section in a change chunk
90 | (not for added or deleted lines) that shows the hexadecimal value of
91 | each character. If "--utf-8" is in effect, it will show the Unicode
92 | character name(s).
93 |
94 | This is a debugging option, so invisible characters can still be
95 | "seen".
96 |
97 | "--verbose" accepts an optional verbosity-level. On level 2 and up,
98 | all horizontal changes get left-and-right markers inserted to enable
99 | seeing the location of the ZERO WIDTH or invisible characters. With
100 | level 3 and up and Unicode enabled, the changed characters will also
101 | show the codepoint in hex.
102 |
103 | An example of this:
104 |
105 | With -Uu0v0:
106 |
107 | 1,1c1,1
108 | - A BCDE Fg
109 | + A BcdEFg
110 |
111 | With -Uu0v1:
112 |
113 | 1,1c1,1
114 | - A BCDE Fg
115 | - -- verbose : SPACE, LATIN CAPITAL LETTER C, LATIN CAPITAL LETTER D, SPACE
116 | + A BcdEFg
117 | + -- verbose : LATIN SMALL LETTER C, LATIN SMALL LETTER D, ZERO WIDTH SPACE
118 |
119 | With -Uu0v2:
120 |
121 | 1,1c1,1
122 | - A ? ?B?CD?E? ?Fg
123 | - -- verbose : SPACE, LATIN CAPITAL LETTER C, LATIN CAPITAL LETTER D, SPACE
124 | + A B?cd?E??Fg
125 | + -- verbose : LATIN SMALL LETTER C, LATIN SMALL LETTER D, ZERO WIDTH SPACE
126 |
127 | With -Uu0v3:
128 |
129 | 1,1c1,1
130 | - A ? ?B?CD?E? ?Fg
131 | - -- verbose : SPACE (U+000020), LATIN CAPITAL LETTER C (U+000043), LATIN CAPITAL LETTER D (U+000044), SPACE (U+000020)
132 | + A B?cd?E??Fg
133 | + -- verbose : LATIN SMALL LETTER C (U+000063), LATIN SMALL LETTER D (U+000064), ZERO WIDTH SPACE (U+00200B)
134 |
135 | With -Uu0v2 --ascii:
136 |
137 | 1,1c1,1
138 | - A > CD cd.
20 | .ie n \{\
21 | . ds C` ""
22 | . ds C' ""
23 | 'br\}
24 | .el\{\
25 | . ds C`
26 | . ds C'
27 | 'br\}
28 | .\"
29 | .\" Escape single quotes in literal strings from groff's Unicode transform.
30 | .ie \n(.g .ds Aq \(aq
31 | .el .ds Aq '
32 | .\"
33 | .\" If the F register is >0, we'll generate index entries on stderr for
34 | .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
35 | .\" entries marked with X<> in POD. Of course, you'll have to process the
36 | .\" output yourself in some meaningful fashion.
37 | .\"
38 | .\" Avoid warning from groff about undefined register 'F'.
39 | .de IX
40 | ..
41 | .nr rF 0
42 | .if \n(.g .if rF .nr rF 1
43 | .if (\n(rF:(\n(.g==0)) \{\
44 | . if \nF \{\
45 | . de IX
46 | . tm Index:\\$1\t\\n%\t"\\$2"
47 | ..
48 | . if !\nF==2 \{\
49 | . nr % 0
50 | . nr F 2
51 | . \}
52 | . \}
53 | .\}
54 | .rr rF
55 | .\"
56 | .\" Required to disable full justification in groff 1.23.0.
57 | .if n .ds AD l
58 | .\" ========================================================================
59 | .\"
60 | .IX Title "App::ccdiff 3"
61 | .TH App::ccdiff 3 2025-01-03 "perl v5.40.0" "User Contributed Perl Documentation"
62 | .\" For nroff, turn off justification. Always turn off hyphenation; it makes
63 | .\" way too many mistakes in technical documents.
64 | .if n .ad l
65 | .nh
66 | .SH NAME
67 | ccdiff \- Colored Character diff
68 | .SH SYNOPSIS
69 | .IX Header "SYNOPSIS"
70 | .Vb 2
71 | \& ccdiff [options] file1|\- file2|\-
72 | \& ccdiff [options] dir1 dir2
73 | \&
74 | \& ccdiff \-\-help
75 | \& ccdiff \-\-man
76 | \& ccdiff \-\-info
77 | .Ve
78 | .SH DESCRIPTION
79 | .IX Header "DESCRIPTION"
80 | Show the diff between two files on a character by character base. In contrast to
81 | the standard diff tools, this tool uses the diff algorithm horizontally for each
82 | line in the vertical diff, highlighting the changes. This is very handy in hard
83 | to spot changes like \f(CW\*(C`O\*(C'\fR to \f(CW0\fR, \f(CW\*(C`I\*(C'\fR to \f(CW\*(C`l\*(C'\fR or \f(CW1\fR and whitespace.
84 | .PP
85 | If there are two argument, and both are a folder/directory, a recursive diff is
86 | executed. This is not available whan used as a (sub)class.
87 | .SH OPTIONS
88 | .IX Header "OPTIONS"
89 | .SS "Command line options"
90 | .IX Subsection "Command line options"
91 | .IP "\-\-help \-?" 2
92 | .IX Item "--help -?"
93 | Show a summary of the available command\-line options and exit.
94 | .IP "\-\-version \-V" 2
95 | .IX Item "--version -V"
96 | Show the version and exit.
97 | .IP \-\-man 2
98 | .IX Item "--man"
99 | Show this manual using pod2man and nroff.
100 | .IP \-\-info 2
101 | .IX Item "--info"
102 | Show this manual using pod2text.
103 | .IP "\-\-utf\-8 \-U" 2
104 | .IX Item "--utf-8 -U"
105 | All I/O (streams to compare and standard out) are in UTF\-8.
106 | .IP "\-\-diff\-class=C \-\-dc=C \-\-pp" 2
107 | .IX Item "--diff-class=C --dc=C --pp"
108 | Select the class used to execute the diff. By default \f(CW\*(C`ccdiff\*(C'\fR will select
109 | the first available out of \f(CW\*(C`Algorithm::Diff::XS\*(C'\fR or \f(CW\*(C`Algorithm::Diff\*(C'\fR.
110 | .Sp
111 | Sometime the \f(CW\*(C`XS\*(C'\fR version fails on encoding and the pure\-perl version will
112 | work just fine. You can force \f(CW\*(C`ccdiff\*(C'\fR to use either
113 | .Sp
114 | Select the pure\-perl version with any of \f(CW\*(C`PP\*(C'\fR, \f(CW\*(C`AD\*(C'\fR, \f(CW\*(C`Algorthm::Diff\*(C'\fR,
115 | \&\f(CW\*(C`Algorithm\-Diff\*(C'\fR, or \f(CW\*(C`Algorithm::Diff::PP\*(C'\fR (case insensitive).
116 | For convenience, \f(CW\*(C`\-\-dc=pp\*(C'\fR can be abbreviated to \f(CW\*(C`\-\-pp\*(C'\fR.
117 | .Sp
118 | .Vb 4
119 | \& \-\-pp
120 | \& \-\-dc=pp
121 | \& \-\-dc=algorithm\-diff
122 | \& \-\-diff\-class=Algorithm::Diff::PP
123 | .Ve
124 | .Sp
125 | Select the XS version with any of \f(CW\*(C`XS\*(C'\fR, \f(CW\*(C`ADX\*(C'\fR, \f(CW\*(C`Algorthm::Diff::XS\*(C'\fR, or
126 | \&\f(CW\*(C`Algorithm\-Diff\-XS\*(C'\fR (case insensitive).
127 | .Sp
128 | .Vb 3
129 | \& \-\-dc=xs
130 | \& \-\-dc=algorithm\-diff\-xs
131 | \& \-\-diff\-class=Algorithm::Diff::XS
132 | .Ve
133 | .IP "\-\-unified[=3] \-u [3]" 2
134 | .IX Item "--unified[=3] -u [3]"
135 | Generate a unified diff. The number of context lines is optional. When omitted
136 | it defaults to 3. Currently there is no provision of dealing with overlapping
137 | diff chunks. If the common part between two diff chunks is shorter than twice
138 | the number of context lines, some lines may show twice.
139 | .Sp
140 | The default is to use traditional diff:
141 | .Sp
142 | .Vb 4
143 | \& 5,5c5,5
144 | \& < Sat Dec 18 07:00:33 1993,I.O.D.U.,,756194433,1442539
145 | \& \-\-\-
146 | \& > Sat Dec 18 07:08:33 1998,I.O.D.U.,,756194433,1442539
147 | .Ve
148 | .Sp
149 | a unified diff (\-u1) would be
150 | .Sp
151 | .Vb 5
152 | \& 5,5c5,5
153 | \& Tue Sep 6 05:43:59 2005,B.O.Q.S.,,1125978239,1943341
154 | \& \-Sat Dec 18 07:00:33 1993,I.O.D.U.,,756194433,1442539
155 | \& +Sat Dec 18 07:08:33 1998,I.O.D.U.,,756194433,1442539
156 | \& Mon Feb 23 10:37:02 2004,R.X.K.S.,van,1077529022,1654127
157 | .Ve
158 | .IP "\-\-verbose[=1] \-v[1]" 2
159 | .IX Item "--verbose[=1] -v[1]"
160 | Show an additional line for each old or new section in a change chunk (not for
161 | added or deleted lines) that shows the hexadecimal value of each character. If
162 | \&\f(CW\*(C`\-\-utf\-8\*(C'\fR is in effect, it will show the Unicode character name(s).
163 | .Sp
164 | This is a debugging option, so invisible characters can still be "seen".
165 | .Sp
166 | \&\f(CW\*(C`\-\-verbose\*(C'\fR accepts an optional verbosity\-level. On level 2 and up, all
167 | horizontal changes get left\-and\-right markers inserted to enable seeing the
168 | location of the ZERO WIDTH or invisible characters. With level 3 and up and
169 | Unicode enabled, the changed characters will also show the codepoint in hex.
170 | .Sp
171 | An example of this:
172 | .Sp
173 | With \-Uu0v0:
174 | .Sp
175 | .Vb 3
176 | \& 1,1c1,1
177 | \& \- A BCDE Fg
178 | \& + A BcdE\:Fg
179 | .Ve
180 | .Sp
181 | With \-Uu0v1:
182 | .Sp
183 | .Vb 5
184 | \& 1,1c1,1
185 | \& \- A BCDE Fg
186 | \& \- \-\- verbose : SPACE, LATIN CAPITAL LETTER C, LATIN CAPITAL LETTER D, SPACE
187 | \& + A BcdE\:Fg
188 | \& + \-\- verbose : LATIN SMALL LETTER C, LATIN SMALL LETTER D, ZERO WIDTH SPACE
189 | .Ve
190 | .Sp
191 | With \-Uu0v2:
192 | .Sp
193 | .Vb 5
194 | \& 1,1c1,1
195 | \& \- A ↱ ↰B↱CD↰E↱ ↰Fg
196 | \& \- \-\- verbose : SPACE, LATIN CAPITAL LETTER C, LATIN CAPITAL LETTER D, SPACE
197 | \& + A B↱cd↰E↱\:↰Fg
198 | \& + \-\- verbose : LATIN SMALL LETTER C, LATIN SMALL LETTER D, ZERO WIDTH SPACE
199 | .Ve
200 | .Sp
201 | With \-Uu0v3:
202 | .Sp
203 | .Vb 5
204 | \& 1,1c1,1
205 | \& \- A ↱ ↰B↱CD↰E↱ ↰Fg
206 | \& \- \-\- verbose : SPACE (U+000020), LATIN CAPITAL LETTER C (U+000043), LATIN CAPITAL LETTER D (U+000044), SPACE (U+000020)
207 | \& + A B↱cd↰E↱\:↰Fg
208 | \& + \-\- verbose : LATIN SMALL LETTER C (U+000063), LATIN SMALL LETTER D (U+000064), ZERO WIDTH SPACE (U+00200B)
209 | .Ve
210 | .Sp
211 | With \-Uu0v2 \-\-ascii:
212 | .Sp
213 | .Vb 5
214 | \& 1,1c1,1
215 | \& \- A > CD cd\: