├── .aspell.local.pws ├── .gitignore ├── .releaserc ├── .travis.yml ├── .whitesource ├── 2lib ├── CONTRIBUTING.md ├── ChangeLog ├── Files ├── 01_1.txt ├── 01_2.txt └── git-ccdiff ├── LICENSE ├── MANIFEST ├── MANIFEST.SKIP ├── META.json ├── META.yml ├── Makefile.PL ├── README.md ├── Talk ├── 5c5a.uchar ├── README ├── README.lt ├── Umuv2.png ├── Umv2.png ├── ccdiff1 ├── e0 ├── export.csv ├── hc0 ├── hc1 ├── m0 ├── m0.csv ├── m1.csv ├── member.csv ├── t0 ├── t1 ├── termcap ├── termcap-blue ├── zws1 └── zws2 ├── ccdiff ├── cpanfile ├── doc ├── README.md ├── ccdiff.3 ├── ccdiff.html ├── ccdiff.man ├── ccdiff.md └── make-doc.pl ├── sandbox ├── 30a4cd45-1 ├── 30a4cd45-2 ├── TEST_A.txt ├── TEST_B.txt ├── genMETA.pl ├── genMETA.pm ├── genxml.pl ├── pm1221078-1 ├── pm1221078-2 ├── test1.xml └── test2.xml ├── t └── 01-no-color.t └── xt ├── 00_perlversion.t ├── 02_pod.t ├── 10_perm.t ├── 20_kwalitee.t └── 50_manifest.t /.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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.whitesource: -------------------------------------------------------------------------------- 1 | { 2 | "generalSettings": { 3 | "shouldScanRepo": true 4 | }, 5 | "checkRunSettings": { 6 | "vulnerableCheckRunConclusionLevel": "failure" 7 | } 8 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 0.35 - 2025-03-19 2 | * 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | 19 | # These are TODO 20 | ^foo.$ 21 | Files/01_[34].txt 22 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Talk/Umuv2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tux/App-ccdiff/e1622f213393ade59898b872f6fe6e373c131a89/Talk/Umuv2.png -------------------------------------------------------------------------------- /Talk/Umv2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tux/App-ccdiff/e1622f213393ade59898b872f6fe6e373c131a89/Talk/Umv2.png -------------------------------------------------------------------------------- /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/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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Talk/zws1: -------------------------------------------------------------------------------- 1 | A BCDE Fg 2 | -------------------------------------------------------------------------------- /Talk/zws2: -------------------------------------------------------------------------------- 1 | A BcdE​Fg 2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /doc/ccdiff.3: -------------------------------------------------------------------------------- 1 | .\" -*- mode: troff; coding: utf-8 -*- 2 | .\" Automatically generated by Pod::Man v6.0.2 (Pod::Simple 3.45) 3 | .\" 4 | .\" Standard preamble: 5 | .\" ======================================================================== 6 | .de Sp \" Vertical space (when we can't use .PP) 7 | .if t .sp .5v 8 | .if n .sp 9 | .. 10 | .de Vb \" Begin verbatim text 11 | .ft CW 12 | .nf 13 | .ne \\$1 14 | .. 15 | .de Ve \" End verbatim text 16 | .ft R 17 | .fi 18 | .. 19 | .\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. 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\: 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 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 BcdE​Fg 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 BcdE​Fg 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 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /sandbox/pm1221078-1: -------------------------------------------------------------------------------- 1 | 2 | foo.work.se 3 | splat.work.se 4 | 5 | -------------------------------------------------------------------------------- /sandbox/pm1221078-2: -------------------------------------------------------------------------------- 1 | 2 | foo-test.work.se 3 | 4 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 [ 14 | "ccdiff", glob ("t/*"), glob ("xt/*"), glob ("*.PL"), 15 | ]}); 16 | 17 | done_testing (); 18 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------