diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3431805 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +/Build +/Build.bat +/MANIFEST.bak +/Makefile +/Makefile.old +/META.json +/META.yml +/MYMETA.json +/MYMETA.yml +/Term-ANSIColor-*/ +/Term-ANSIColor-*.tar.gz +/Term-ANSIColor-*.tar.gz.asc +/_build/ +/blib/ +/cover_db/ +/pm_to_blib diff --git a/Changes b/Changes new file mode 100644 index 0000000..2f20d30 --- /dev/null +++ b/Changes @@ -0,0 +1,286 @@ + User-Visible Term::ANSIColor Changes + +Term::ANSIColor 4.06 (2016-10-28) + + Add aliases ansi16 through ansi255 and on_ansi16 through on_ansi255 + (plus the corresponding constants) for the grey and rgb colors so that + one can refer to all of the 256 ANSI colors with consistent names. + These are aliases; the colors returned by uncolor will still use the + grey and rgb names. (#118267) + +Term::ANSIColor 4.05 (2016-03-20) + + Color aliases are now restricted to ASCII alphanumerics, due to the + below change. + + Delay loading of the Carp module and avoid using [:upper:], \w, and \d + in regular expressions to reduce the amount of memory this module + consumes. (Normally, I wouldn't worry about this, but this module is + very light-weight and can be useful even in highly space-constrained + environments, and the impact is slight.) Thanks, Nicolas R. + (#111552) + + Provide a mailto address in bug tracking metadata, use the shorter + form of the RT bug tracker URL, and fix the license value to match the + new metadata specification. Rework Makefile.PL so that the munging + for older versions of ExtUtils::MakeMaker is less intrusive. + +Term::ANSIColor 4.04 (2015-12-06) + + Revert the build system back to ExtUtils::MakeMaker. This is the + build system actually used in Perl core, so this removes a level of + indirectly generated files and means that normal module development + tests the same build system used by Perl. Update Makefile.PL with the + additional metadata from the Module::Build build system. + + For versions of Perl prior to 5.11, install the module into the Perl + core module directories, since in those versions site modules did not + take precedence over Perl core modules. + + Rename NEWS to Changes to match the normal Perl convention. + +Term::ANSIColor 4.03 (2014-03-23) + + Switch the module build system to Module::Build, but still generate a + Makefile.PL file for backward compatibility and for the use of Perl + core. + + Fix typo in SYNOPSIS (colorstrip example) and duplicated word. + Thanks, Olivier Mengué and David Steinbrunner. (#85480, #94006) + + Skip POD and some other style tests unless doing automated or release + testing. Skip POD spelling, coverage, and Perl::Critic tests unless + doing author testing. Use the Lancaster Consensus environment + variables instead of RRA_MAINTAINER_TESTS. (#93474) + + Add SEE ALSO reference to Win32::Console::ANSI. (#87295) + +Term::ANSIColor 4.02 (2013-01-07) + + When testing 256-color support, list the tag first in the import list + for compatibility with the Exporter from Perl 5.6.2. Thanks to David + Cantrell for the testing and debugging. + + Add the minimum Perl version to the package metadata. + +Term::ANSIColor 4.01 (2012-12-31) + + Fix logic for skipping tests when Test::Warn is not installed. + +Term::ANSIColor 4.00 (2012-12-30) + + Add constants (with tag :constants256) and attributes for 256-color + emulators. Thanks, Kurt Starsinic. + + Add support for custom color names configured with either a new + function, coloralias, or the ANSI_COLORS_ALIASES environment variable + as set during module load. Thanks, Stephen Tirlwall. + + Only honor ANSI_COLORS_DISABLED if it is set to a true value. + + The module now requires Perl 5.6 or later and makes use of Perl 5.6 + features. + + Replace the AUTOLOAD support for ANSI_COLORS_DISABLED with generation + of constant subs that check for ANSI_COLORS_DISABLED when they're + called. This fixes behavior if the constant were used before the + environment variable was set and then used again afterwards. + + PUSHCOLOR now takes an array like all the other constant functions and + joins all arguments together before manipulating them, making behavior + more consistent in some edge cases. + + $AUTOLOCAL now takes precedence over $AUTORESET, reversing the + previous behavior. It is also now properly documented. + + Add a COMPATIBILITY section to the documentation collecting all + information about when features were introduced and adding the version + of Perl that they shipped with. Add appropriate version numbers to + the use statements in the SYNOPSIS. + + Add a new generate-colors example script that can generate various + test and demonstration files, including for 256 colors and various + attributes. Remove the VT100 test files, which had an unclear + license. generate-colors can now generate better tests for everything + of significance to this package. + +Term::ANSIColor 3.02 (2012-03-18) + + In AUTOLOAD, only return pass-through behavior if the function that + was called was one of our constants, rather than turning every unknown + function in the Term::ANSIColor namespace into a passthrough join + function when colors are disabled. + + Add the italic attribute and the ITALIC constant. Document that + support for it is rare. + + Preserve an existing value of $@ when generating a constant sub and + restore it afterwards. Diagnose errors in creating the constant sub + and die instead of ignoring them. + +Term::ANSIColor 3.01 (2011-07-20) + + In colored, only interpret an initial array reference as a list of + colors, not any initial reference, allowing the colored function to + work properly on objects with stringification defined. Thanks, Revilo + Reegiles. + + Warn in the documentation that attributes are not supported in and + will not work with Perl formats. + +Term::ANSIColor 3.00 (2010-01-04) + + Add bright versions of the basic eight foreground and background + colors using the 9x and 10x codes, supported by emulators with 16 + color support. + + Reword the explanation of bright and regular colors, and provide some + advice about which to use. + + Reorganize the documentation and be clearer about the function + interface parameters. + +Term::ANSIColor 2.02 (2009-08-30) + + Add the new function colorvalid, which takes an attribute and returns + whether it's a known attribute. + + Add FAINT as a synonym for DARK and export it when constants are + requested. + + Update the terminal compatibility matrix to reflect that xterm now + supports blink. + +Term::ANSIColor 2.01 (2009-07-04) + + Add the new function colorstrip, which removes ANSI color codes from + strings. Thanks, Paul Miller. + + When reporting errors for bad escape sequences in uncolor, don't + include the leading \e[ or trailing m in the error message. + + Untaint $AUTOLOAD when generating constant subs, which is required by + Perl 5.10 and later running in taint mode. Thanks, Tim Bellinghausen. + +Term::ANSIColor 2.00 (2009-02-28) + + Add new functions PUSHCOLOR, POPCOLOR, and LOCALCOLOR, which maintain + a stack of colors using the constant syntax. PUSHCOLOR stores the + attributes being set on its internal stack, POPCOLOR returns to the + previous attribute set, and LOCALCOLOR surrounds its argument in + PUSHCOLOR and POPCOLOR. If $AUTOLOCAL is set, each sequence of color + constants will be implicitly preceded by LOCALCOLOR. This support was + contributed by openmethods.com voice solutions. + + When AUTOLOAD is called to generate a constant sub and the environment + variable ANSI_COLORS_DISABLED is set, return the stringified arguments + rather than creating a sub. This allows colors to work later if + ANSI_COLORS_DISABLED is unset rather than making its effects + permanent. It also avoids adding a reset escape sequence when + $AUTORESET and ANSI_COLORS_DISABLED are both set. + + Add faint as a synonym for dark. + + Fix spelling and markup errors in the documentation and improve the + documentation of text attributes. + +Term::ANSIColor 1.12 (2007-04-22) + + Use the correct syntax for internal POD links in the documentation. + + Document cyan and white as supported attributes. + +Term::ANSIColor 1.11 (2006-06-22) + + Clarify in the documentation the behavior of terminals when background + colors are set across newlines, and rewrite some of the examples to + avoid doing things that confuse the terminal. + +Term::ANSIColor 1.10 (2005-08-21) + + Fix $EACHLINE handling of lines consisting solely of "0". + + Add terminal test files from Joe Smith to the distribution. + +Term::ANSIColor 1.09 (2004-12-03) + + Add compatibility information for Mac OS X Terminal to the terminal + emulators table. Thanks, Daniel Lindsley. + +Term::ANSIColor 1.08 (2004-02-19) + + Export DARK as a constant. This was missed when dark was added as a + supported attribute. + +Term::ANSIColor 1.07 (2003-03-25) + + Document the behavior of PuTTY, Windows telnet, and Cygwin OpenSSH in + the terminal emulators table. + + Update the URL to the ECMA standard. + +Term::ANSIColor 1.06 (2002-12-09) + + Fix a typo in an L<> link in the documentation. + +Term::ANSIColor 1.05 (2002-06-28) + + Document the Windows consoles that don't work with this module. + + Update the documentation formatting style. + +Term::ANSIColor 1.04 (2001-07-10) + + Add a new uncolor function, which takes a set of escape sequences and + returns a list of attribute names set by those escape sequences. This + is the opposite function as color. + + If ANSI_COLORS_DISABLED is set in the environment, all of the + functions and constants in this module become no-ops that pass through + text without coloring it. + + Add information about the relevant standards to the documentation. + +Term::ANSIColor 1.03 (2000-08-06) + + In the colored function, allow the attributes to be passed as an + initial array reference as well as a trailing list. When called with + that syntax, all subsequent arguments are taken as text to be colored. + + Add the dark attribute. + + Improve the documentation by including a table of supported attributes + on different terminal emulators in the documentation and documenting + whether diagnostics are fatal errors or warnings. + + Install into the Perl library directory for Perl 5.6.0 or later, since + this module is now part of core. + +Term::ANSIColor 1.02 (1998-11-27) + + Call croak instead of die if the AUTOLOAD function to synthesize + constants fails. + + Set ABSTRACT and AUTHOR in Makefile.PL to support PPD generation for + binary distributions or the Perl Resource Kits. + +Term::ANSIColor 1.01 (1997-12-10) + + Fix the call to carp when running under Perl versions later than + 5.004_04, which no longer import Carp in strict.pm and thereby declare + the function at compile time. + +Term::ANSIColor 1.00 (1997-11-29) + + Correctly handle trailing delimiters when $EACHLINE is set. + + Call croak instead of die if a caller uses an invalid attribute name, + since the error is really at the call site. + + Add the correct rules to Makefile.PL to build a distribution. + +Term::ANSIColor 0.09 (1997-02-17) + + Initial public release. (Possibly. It's the oldest version available + on BackPan and dates back to when the "package" version was based on + the RCS revision of the ANSIColor.pm file.) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..64d99a2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,48 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Comment: This file documents the copyright statements and licenses for + every file in this package in a machine-readable format. For a less + detailed, higher-level overview, see README. + . + For any copyright year range specified as YYYY-ZZZZ in this file, the + range specifies every single year in that closed interval. + +Files: * +Copyright: 1996 Zenin + 1996-2002, 2005-2006, 2008-2016 Russ Allbery + 2011 Revilo Reegiles + 2012 Kurt Starsinic + 2012 Stephen Thirlwall +License: Perl + This program is free software; you may redistribute it and/or modify it + under the same terms as Perl itself. This means that you may choose + between the two licenses that Perl is released under: the GNU GPL and the + Artistic License. Please see your Perl distribution for the details and + copies of the licenses. + +Files: t/data/perlcriticrc t/docs/pod-coverage.t t/docs/pod-spelling.t + t/docs/pod.t t/docs/synopsis.t t/docs/urls.t t/lib/Test/RRA.pm + t/lib/Test/RRA/Config.pm t/style/coverage.t t/style/critic.t + t/style/minimum-version.t t/style/strict.t +Copyright: 2011-2014 + The Board of Trustees of the Leland Stanford Junior University + 2015-2016 Russ Allbery +License: Expat + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + . + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT + OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..7208657 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,41 @@ +.gitignore +Changes +docs/metadata/blurb +docs/metadata/description +docs/metadata/metadata.json +docs/metadata/notices +docs/metadata/quote +docs/metadata/README +docs/metadata/requirements +examples/generate-colors +lib/Term/ANSIColor.pm +LICENSE +Makefile.PL +MANIFEST This list of files +MANIFEST.SKIP +README +README.md +t/data/perl.conf +t/data/perlcriticrc +t/data/perltidyrc +t/docs/pod-coverage.t +t/docs/pod-spelling.t +t/docs/pod.t +t/docs/synopsis.t +t/docs/urls.t +t/lib/Test/RRA.pm +t/lib/Test/RRA/Config.pm +t/module/aliases-env.t +t/module/aliases-func.t +t/module/basic.t +t/module/basic256.t +t/module/eval.t +t/module/stringify.t +t/style/coverage.t +t/style/critic.t +t/style/minimum-version.t +t/style/strict.t +t/taint/basic.t +THANKS +META.yml Module YAML meta-data (added by MakeMaker) +META.json Module JSON meta-data (added by MakeMaker) diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP new file mode 100644 index 0000000..b5b5799 --- /dev/null +++ b/MANIFEST.SKIP @@ -0,0 +1,39 @@ +# -*- conf -*- + +# Avoid version control files. +^\.git/ + +# Avoid generated build files. +^Makefile$ +\bblib/ +^pm_to_blib$ + +# Avoid temp and backup files. +~$ +\.old$ +\#$ +\b\.# +\.bak$ +\.tmp$ +\.# +\.rej$ + +# Avoid OS-specific files/dirs +# Mac OSX metadata +\B\.DS_Store +# Mac OSX SMB mount metadata files +\B\._ + +# Avoid Devel::Cover and Devel::CoverX::Covered files. +\bcover_db\b +\bcovered\b + +# Avoid MYMETA files +^MYMETA\. + +# Avoid archives of this distribution +\bTerm-ANSIColor-[\d\.\_]+ + +# CI configuration. Do not include in the distribution so that it doesn't +# make its way into Perl core. +^\.travis\.yml$ diff --git a/META.json b/META.json new file mode 100644 index 0000000..a7e5493 --- /dev/null +++ b/META.json @@ -0,0 +1,54 @@ +{ + "abstract" : "Color output using ANSI escape sequences", + "author" : [ + "Russ Allbery " + ], + "dynamic_config" : 1, + "generated_by" : "ExtUtils::MakeMaker version 7.1002, CPAN::Meta::Converter version 2.150010", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "Term-ANSIColor", + "no_index" : { + "directory" : [ + "t", + "inc" + ] + }, + "prereqs" : { + "build" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "runtime" : { + "requires" : { + "perl" : "5.006" + } + } + }, + "release_status" : "stable", + "resources" : { + "bugtracker" : { + "mailto" : "bug-Term-ANSIColor@rt.cpan.org", + "web" : "https://rt.cpan.org/Dist/Display.html?Name=Term-ANSIColor" + }, + "homepage" : "https://www.eyrie.org/~eagle/software/ansicolor/", + "repository" : { + "type" : "git", + "url" : "git://github.com/rra/ansicolor.git", + "web" : "https://github.com/rra/ansicolor" + } + }, + "version" : "4.06", + "x_serialization_backend" : "JSON::PP version 2.27300_01" +} diff --git a/META.yml b/META.yml new file mode 100644 index 0000000..ec366b2 --- /dev/null +++ b/META.yml @@ -0,0 +1,27 @@ +--- +abstract: 'Color output using ANSI escape sequences' +author: + - 'Russ Allbery ' +build_requires: + ExtUtils::MakeMaker: '0' +configure_requires: + ExtUtils::MakeMaker: '0' +dynamic_config: 1 +generated_by: 'ExtUtils::MakeMaker version 7.1002, CPAN::Meta::Converter version 2.150010' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: '1.4' +name: Term-ANSIColor +no_index: + directory: + - t + - inc +requires: + perl: '5.006' +resources: + bugtracker: https://rt.cpan.org/Dist/Display.html?Name=Term-ANSIColor + homepage: https://www.eyrie.org/~eagle/software/ansicolor/ + repository: git://github.com/rra/ansicolor.git +version: '4.06' +x_serialization_backend: 'CPAN::Meta::YAML version 0.018' diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..ca65267 --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,76 @@ +# Build instructions for Term::ANSIColor. +# +# We prefer to use ExtUtils::MakeMaker since this module is part of Perl core, +# which only supports that build method. While Module::Build can generate a +# backards-compatible Makefile.PL, this way normal releases test the same +# build system that is used for Perl core. +# +# Copyright 1999, 2000, 2001, 2008, 2010, 2012, 2014, 2015, 2016 +# Russ Allbery +# +# This program is free software; you may redistribute it and/or modify it +# under the same terms as Perl itself. + +use 5.006; +use strict; +use warnings; + +use Config; +use ExtUtils::MakeMaker; +use File::Spec; + +my $BUGS = 'https://rt.cpan.org/Dist/Display.html?Name=Term-ANSIColor'; + +# The hash of all the metadata. This will be modified before WriteMakefile to +# remove keys not supported by the local version of ExtUtils::MakeMaker. +my %metadata = ( + NAME => 'Term::ANSIColor', + ABSTRACT => 'Color output using ANSI escape sequences', + AUTHOR => 'Russ Allbery ', + LICENSE => 'perl_5', + VERSION_FROM => 'lib/Term/ANSIColor.pm', + MIN_PERL_VERSION => '5.006', + realclean => { FILES => 'MANIFEST.bak cover_db' }, + + # Older versions of ExtUtils::MakeMaker don't pick up nested test + # directories by default. + test => { TESTS => 't/*/*.t' }, + + # For older versions of Perl, we have to force installation into the Perl + # module directories since site modules did not take precedence over core + # modules. + INSTALLDIRS => $] lt '5.011' ? 'perl' : 'site', + + # Additional metadata. + META_ADD => { + 'meta-spec' => { version => 2 }, + resources => { + bugtracker => { + mailto => 'bug-Term-ANSIColor@rt.cpan.org', + web => $BUGS, + }, + homepage => 'https://www.eyrie.org/~eagle/software/ansicolor/', + repository => { + url => 'git://github.com/rra/ansicolor.git', + web => 'https://github.com/rra/ansicolor', + type => 'git', + }, + }, + }, +); + +# Remove keys that aren't supported by this version of ExtUtils::MakeMaker. +# This hash maps keys to the minimum supported version. +my %supported = ( + LICENSE => 6.31, + META_ADD => 6.46, + MIN_PERL_VERSION => 6.48, +); +for my $key (keys(%supported)) { + if ($ExtUtils::MakeMaker::VERSION < $supported{$key}) { + delete $metadata{$key}; + } +} + +# Generate the actual Makefile. +WriteMakefile(%metadata); diff --git a/README b/README new file mode 100644 index 0000000..648f0c3 --- /dev/null +++ b/README @@ -0,0 +1,163 @@ + Term::ANSIColor 4.06 + (simple ANSI text attribute control module) + Maintained by Russ Allbery + + Copyright 1996-1998, 2000-2002, 2005-2006, 2008-2016 Russ Allbery + . Copyright 1996 Zenin. Copyright 2012 Kurt Starsinic + . This software is distributed under the same + terms as Perl itself. Please see the section LICENSE below for more + information. + +BLURB + + Term::ANSIColor provides constants and simple functions for setting ANSI + text attributes, most notably colors. It can be used to set the current + text attributes or to apply a set of attributes to a string and reset + the current text attributes at the end of that string. Eight-color, + sixteen-color, and 256-color escape sequences are all supported. + +DESCRIPTION + + This Perl module is a simple and convenient interface to the ANSI + terminal escape sequences for color (from ECMA-48, also included in ISO + 6429). The color sequences are provided in two forms, either as + constants for each color or via a function that takes the names of + colors and returns the appropriate escape codes or wraps them around the + provided text. The non-color text style codes from ANSI X3.64 (bold, + dark, underline, and reverse, for example), which were also included in + ECMA-48 and ISO 6429, are also supported. Also supported are the + extended colors used for sixteen-color and 256-color emulators. + + This module is very stable, and I've used it in a wide variety of + applications. It has been included in the core Perl distribution + starting with version 5.6.0, so you don't need to download and install + it yourself unless you have an old version of Perl or need a newer + version of the module than comes with your version of Perl. I continue + to maintain it as a separate module, and the version included in Perl is + resynced with mine before each release. + + The original module came out of a discussion in comp.lang.perl.misc and + is a combination of two approaches, one with constants by Zenin and one + with functions that I wrote. I offered to maintain a combined module + that included both approaches. + +REQUIREMENTS + + Term::ANSIColor is written in pure Perl and has no module dependencies + that aren't found in Perl core. It should work with any version of Perl + after 5.6, although it hasn't been tested with old versions in some + time. + + In order to actually see color, you will need to use a terminal window + that supports the ANSI escape sequences for color. Any recent version + of xterm, most xterm derivatives and replacements, and most telnet and + ssh clients for Windows and Macintosh should work, as will the MacOS X + Terminal application (although Terminal.app reportedly doesn't support + 256 colors). The console windows for Windows NT and Windows 2000 will + not work, as they do not even attempt to support ANSI X3.64. + + For a complete (to my current knowledge) compatibility list, see the + Term::ANSIColor module documentation. If you have any additions to the + table in the documentation, please send them to me. + + The test suite requires Test::More (part of Perl since 5.6.2). The + following additional Perl modules will be used by the test suite if + present: + + * Devel::Cover + * Test::MinimumVersion + * Test::Perl::Critic + * Test::Pod + * Test::Pod::Coverage + * Test::Spelling + * Test::Strict + * Test::Synopsis + * Test::Warn + + All are available on CPAN. Those tests will be skipped if the modules + are not available. + + To enable tests that don't detect functionality problems but are used to + sanity-check the release, set the environment variable RELEASE_TESTING + to a true value. To enable tests that may be sensitive to the local + environment or that produce a lot of false positives without uncovering + many problems, set the environment variable AUTHOR_TESTING to a true + value. + +BUILDING AND INSTALLATION + + Term::ANSIColor uses ExtUtils::MakeMaker and can be installed using the + same process as any other ExtUtils::MakeMaker module: + + perl Makefile.PL + make + make test + make install + + You'll probably need to do the last as root unless you're installing + into a local Perl module tree in your home directory. + +SUPPORT + + The Term::ANSIColor web page at: + + https://www.eyrie.org/~eagle/software/ansicolor/ + + will always have the current version of this package, the current + documentation, and pointers to any additional resources. + + For bug tracking, use the CPAN bug tracker at: + + https://rt.cpan.org/Dist/Display.html?Name=Term-ANSIColor + + However, please be aware that I tend to be extremely busy and work + projects often take priority. I'll save your report and get to it as + soon as I can, but it may take me a couple of months. + +SOURCE REPOSITORY + + Term::ANSIColor is maintained using Git. You can access the current + source on GitHub at: + + https://github.com/rra/ansicolor + + or by cloning the repository at: + + https://git.eyrie.org/git/perl/ansicolor.git + + or view the repository via the web at: + + https://git.eyrie.org/?p=perl/ansicolor.git + + The eyrie.org repository is the canonical one, maintained by the author, + but using GitHub is probably more convenient for most purposes. Pull + requests are gratefully reviewed and normally accepted. It's probably + better to use the CPAN bug tracker than GitHub issues, though, to keep + all Perl module issues in the same place. + +LICENSE + + The Term::ANSIColor package as a whole is covered by the following + copyright statement and license: + + Copyright 1996-1998, 2000-2002, 2005-2006, 2008-2016 + Russ Allbery + Copyright 1996 Zenin + Copyright 2012 Kurt Starsinic + + This program is free software; you may redistribute it and/or modify + it under the same terms as Perl itself. This means that you may + choose between the two licenses that Perl is released under: the GNU + GPL and the Artistic License. Please see your Perl distribution for + the details and copies of the licenses. + + PUSH/POP support submitted 2007 by openmethods.com voice solutions + + Some files in this distribution are individually released under + different licenses, all of which are compatible with the above general + package license but which may require preservation of additional + notices. All required notices, and detailed information about the + licensing of each file, are recorded in the LICENSE file. + + For any copyright range specified by files in this package as YYYY-ZZZZ, + the range specifies every single year in that closed interval. diff --git a/README.md b/README.md new file mode 100644 index 0000000..3e495a8 --- /dev/null +++ b/README.md @@ -0,0 +1,158 @@ +# Term::ANSIColor 4.06 + +Copyright 1996-1998, 2000-2002, 2005-2006, 2008-2016 Russ Allbery +. Copyright 1996 Zenin. Copyright 2012 Kurt Starsinic +. This software is distributed under the same terms +as Perl itself. Please see the section [License](#license) below for more +information. + +## Blurb + +Term::ANSIColor provides constants and simple functions for setting ANSI +text attributes, most notably colors. It can be used to set the current +text attributes or to apply a set of attributes to a string and reset the +current text attributes at the end of that string. Eight-color, +sixteen-color, and 256-color escape sequences are all supported. + +## Description + +This Perl module is a simple and convenient interface to the ANSI terminal +escape sequences for color (from ECMA-48, also included in ISO 6429). The +color sequences are provided in two forms, either as constants for each +color or via a function that takes the names of colors and returns the +appropriate escape codes or wraps them around the provided text. The +non-color text style codes from ANSI X3.64 (bold, dark, underline, and +reverse, for example), which were also included in ECMA-48 and ISO 6429, +are also supported. Also supported are the extended colors used for +sixteen-color and 256-color emulators. + +This module is very stable, and I've used it in a wide variety of +applications. It has been included in the core Perl distribution starting +with version 5.6.0, so you don't need to download and install it yourself +unless you have an old version of Perl or need a newer version of the +module than comes with your version of Perl. I continue to maintain it as +a separate module, and the version included in Perl is resynced with mine +before each release. + +The original module came out of a discussion in comp.lang.perl.misc and is +a combination of two approaches, one with constants by Zenin and one with +functions that I wrote. I offered to maintain a combined module that +included both approaches. + +## Requirements + +Term::ANSIColor is written in pure Perl and has no module dependencies +that aren't found in Perl core. It should work with any version of Perl +after 5.6, although it hasn't been tested with old versions in some time. + +In order to actually see color, you will need to use a terminal window +that supports the ANSI escape sequences for color. Any recent version of +xterm, most xterm derivatives and replacements, and most telnet and ssh +clients for Windows and Macintosh should work, as will the MacOS X +Terminal application (although Terminal.app reportedly doesn't support 256 +colors). The console windows for Windows NT and Windows 2000 will not +work, as they do not even attempt to support ANSI X3.64. + +For a complete (to my current knowledge) compatibility list, see the +Term::ANSIColor module documentation. If you have any additions to the +table in the documentation, please send them to me. + +The test suite requires Test::More (part of Perl since 5.6.2). The +following additional Perl modules will be used by the test suite if +present: + +* Devel::Cover +* Test::MinimumVersion +* Test::Perl::Critic +* Test::Pod +* Test::Pod::Coverage +* Test::Spelling +* Test::Strict +* Test::Synopsis +* Test::Warn + +All are available on CPAN. Those tests will be skipped if the modules are +not available. + +To enable tests that don't detect functionality problems but are used to +sanity-check the release, set the environment variable `RELEASE_TESTING` +to a true value. To enable tests that may be sensitive to the local +environment or that produce a lot of false positives without uncovering +many problems, set the environment variable `AUTHOR_TESTING` to a true +value. + +## Building and Installation + +Term::ANSIColor uses ExtUtils::MakeMaker and can be installed using the +same process as any other ExtUtils::MakeMaker module: + +``` + perl Makefile.PL + make + make test + make install +``` + +You'll probably need to do the last as root unless you're installing into +a local Perl module tree in your home directory. + +## Support + +The [Term::ANSIColor web +page](https://www.eyrie.org/~eagle/software/ansicolor/) will always have +the current version of this package, the current documentation, and +pointers to any additional resources. + +For bug tracking, use the [CPAN bug +tracker](https://rt.cpan.org/Dist/Display.html?Name=Term-ANSIColor). +However, please be aware that I tend to be extremely busy and work +projects often take priority. I'll save your mail and get to it as soon +as I can, but it may take me a couple of months. + +## Source Repository + +Term::ANSIColor is maintained using Git. You can access the current +source on [GitHub](https://github.com/rra/ansicolor) or by cloning the +repository at: + +https://git.eyrie.org/git/perl/ansicolor.git + +or [view the repository on the +web](https://git.eyrie.org/?p=perl/ansicolor.git). + +The eyrie.org repository is the canonical one, maintained by the author, +but using GitHub is probably more convenient for most purposes. Pull +requests are gratefully reviewed and normally accepted. It's probably +better to use the CPAN bug tracker than GitHub issues, though, to keep all +Perl module issues in the same place. + +## License + +The Term::ANSIColor package as a whole is covered by the following +copyright statement and license: + +> Copyright 1996-1998, 2000-2002, 2005-2006, 2008-2016 +> Russ Allbery +> +> Copyright 1996 +> Zenin +> +> Copyright 2012 +> Kurt Starsinic +> +> This program is free software; you may redistribute it and/or modify it +> under the same terms as Perl itself. This means that you may choose +> between the two licenses that Perl is released under: the GNU GPL and the +> Artistic License. Please see your Perl distribution for the details and +> copies of the licenses. +> +> PUSH/POP support submitted 2007 by openmethods.com voice solutions + +Some files in this distribution are individually released under different +licenses, all of which are compatible with the above general package +license but which may require preservation of additional notices. All +required notices, and detailed information about the licensing of each +file, are recorded in the LICENSE file. + +For any copyright range specified by files in this package as YYYY-ZZZZ, +the range specifies every single year in that closed interval. diff --git a/THANKS b/THANKS new file mode 100644 index 0000000..685a203 --- /dev/null +++ b/THANKS @@ -0,0 +1,92 @@ + Term::ANSIColor Thanks + +Thanks to all of the following people for helping with the development of +this module. + +To Jon Lennox for looking at early versions of this module, providing +feedback, and offering suggestions for improvement. + +To Jesse Taylor for writing the first significant script to use this +module (colorized calsplit), thus offering innumerable opportunities to +test and debug. + +To Jean Delvare for providing documentation of what the various attributes +do on various different terminal emulators, and for noting that attribute +2 is dark. + +To Edward Avis for the implementation of uncolor. + +To Rani Pinchuk for the idea of ANSI_COLORS_DISABLED and an initial +implementation. + +To ATricket for the information about what PuTTY, Windows telnet, and +OpenSSH under Cygwin support. + +To Richard Maus for pointing out DARK was missing from the exported +constants list and CYAN and WHITE were missing from the documentation. + +To Autrijus Tang for noticing a problem with string comparisons in the +test suite. + +To Daniel Lindsley for the information about what Mac OS X Terminal +supports. + +To Joe Smith for the original test files that exercise a wide variety of +VT100 escape sequences including the ECMA-48 color control codes. These +have been replaced by an example script, but they were very useful. + +To James Bowlin for catching a bug in colored when $EACHLINE is set that +caused it to not color lines consisting solely of 0. + +To Helge Kreutzmann for pointing out the need for warnings in the +documentation about background colors that span newlines. + +To Baron Schwartz for pointing out that cyan and white were missing from +the documentation. + +To Michael R. Wolf for pointing out that Wikipedia and the ECMA standard +use faint instead of dark as the name of attribute 2. + +To openmethods.com voice solutions for contributing PUSHCOLOR, POPCOLOR, +and LOCALCOLOR support. + +To Tim Bellinghausen for the AUTOLOAD taint fix for Perl 5.10. + +To Paul Miller for the idea and initial implementation of colorstrip. + +To Jakob Ilves for sixteen-color support and the initial documentation of +bright color issues. + +To Revilo Reegiles for reporting problems with the colored function and +non-array references with stringification defined, and providing a test +case. + +To Kent Fredric for the request for italic and the report of a terminal +emulator that supports it. + +To Simon Wistow for reporting that Term::ANSIColor was inadvertantly +clobbering $@ when generating constant subs. + +To Kurt Starsinic for the initial implementation of 256-color support. + +To Magnus Woldrich for Term::ExtendedColor and for research on which +emulators support 256 colors. + +To Stephen Thirlwall for the initial implementation of custom color +support. + +To BlueT - Matthew Lien - 練喆明 for quick testing of 4.00 and reporting a +problem with skipping one of the tests. + +To David Cantrell for testing with Perl 5.6.2 and debugging why a test +case didn't work with its version of Exporter. + +To Olivier Mengué for fixing a SYNOPSIS quoting error and for various +other build fixes and recommendations about environment variables for test +control. + +To Nicolas R for pointing out a 70% memory usage increase over Perl 5.14 +that could be mostly avoided by dodging POSIX character classes in regexes +and delaying loading of the Carp module. + +To Larry Wall, as always, for Perl. diff --git a/docs/metadata/README b/docs/metadata/README new file mode 100644 index 0000000..26316da --- /dev/null +++ b/docs/metadata/README @@ -0,0 +1,6 @@ +This directory contains configuration for DocKnot used to generate +documentation files (like README.md) and web pages. Other documentation +in this package is generated automatically from these files as part of the +release process. For more information, see DocKnot's documentation. + +DocKnot is available from . diff --git a/docs/metadata/blurb b/docs/metadata/blurb new file mode 100644 index 0000000..36c74f5 --- /dev/null +++ b/docs/metadata/blurb @@ -0,0 +1,5 @@ +Term::ANSIColor provides constants and simple functions for setting ANSI +text attributes, most notably colors. It can be used to set the current +text attributes or to apply a set of attributes to a string and reset the +current text attributes at the end of that string. Eight-color, +sixteen-color, and 256-color escape sequences are all supported. diff --git a/docs/metadata/description b/docs/metadata/description new file mode 100644 index 0000000..b1e259a --- /dev/null +++ b/docs/metadata/description @@ -0,0 +1,22 @@ +This Perl module is a simple and convenient interface to the ANSI terminal +escape sequences for color (from ECMA-48, also included in ISO 6429). The +color sequences are provided in two forms, either as constants for each +color or via a function that takes the names of colors and returns the +appropriate escape codes or wraps them around the provided text. The +non-color text style codes from ANSI X3.64 (bold, dark, underline, and +reverse, for example), which were also included in ECMA-48 and ISO 6429, +are also supported. Also supported are the extended colors used for +sixteen-color and 256-color emulators. + +This module is very stable, and I've used it in a wide variety of +applications. It has been included in the core Perl distribution starting +with version 5.6.0, so you don't need to download and install it yourself +unless you have an old version of Perl or need a newer version of the +module than comes with your version of Perl. I continue to maintain it as +a separate module, and the version included in Perl is resynced with mine +before each release. + +The original module came out of a discussion in comp.lang.perl.misc and is +a combination of two approaches, one with constants by Zenin and one with +functions that I wrote. I offered to maintain a combined module that +included both approaches. diff --git a/docs/metadata/metadata.json b/docs/metadata/metadata.json new file mode 100644 index 0000000..a965f1a --- /dev/null +++ b/docs/metadata/metadata.json @@ -0,0 +1,57 @@ +{ + "name": "Term::ANSIColor", + "version": "4.06", + "synopsis": "simple ANSI text attribute control module", + "maintainer": "Russ Allbery ", + "copyrights": [ + { + "holder": "Russ Allbery ", + "years": "1996-1998, 2000-2002, 2005-2006, 2008-2016", + }, + { + "holder": "Zenin", + "years": "1996", + }, + { + "holder": "Kurt Starsinic ", + "years": "2012", + }, + ], + "license": "Perl", + "build": { + "lancaster": true, + "type": "ExtUtils::MakeMaker", + }, + "support": { + "cpan": "Term-ANSIColor", + "email": "rra@cpan.org", + "web": "https://www.eyrie.org/~eagle/software/ansicolor/", + }, + "vcs": { + "type": "Git", + "url": "https://git.eyrie.org/git/perl/ansicolor.git", + "browse": "https://git.eyrie.org/?p=perl/ansicolor.git", + "github": "rra/ansicolor", + "openhub": "https://www.openhub.net/p/ansicolor", + }, + "quote": { + "author": "Dave van Domelen", + }, + "distribution": { + "section": "devel", + "tarname": "Term-ANSIColor", + "version": "term-ansicolor", + }, + "docs": { + "user": [ + { + "name": "docs", + "title": "Module documentation", + }, + { + "name": "thanks", + "title": "Thanks and credits", + }, + ], + }, +} diff --git a/docs/metadata/notices b/docs/metadata/notices new file mode 100644 index 0000000..c38fa5a --- /dev/null +++ b/docs/metadata/notices @@ -0,0 +1 @@ +PUSH/POP support submitted 2007 by openmethods.com voice solutions diff --git a/docs/metadata/quote b/docs/metadata/quote new file mode 100644 index 0000000..21d524c --- /dev/null +++ b/docs/metadata/quote @@ -0,0 +1 @@ +Ah, September, when the sysadmins turn colors and fall off the trees.... diff --git a/docs/metadata/requirements b/docs/metadata/requirements new file mode 100644 index 0000000..da259e0 --- /dev/null +++ b/docs/metadata/requirements @@ -0,0 +1,32 @@ +Term::ANSIColor is written in pure Perl and has no module dependencies +that aren't found in Perl core. It should work with any version of Perl +after 5.6, although it hasn't been tested with old versions in some time. + +In order to actually see color, you will need to use a terminal window +that supports the ANSI escape sequences for color. Any recent version of +xterm, most xterm derivatives and replacements, and most telnet and ssh +clients for Windows and Macintosh should work, as will the MacOS X +Terminal application (although Terminal.app reportedly doesn't support 256 +colors). The console windows for Windows NT and Windows 2000 will not +work, as they do not even attempt to support ANSI X3.64. + +For a complete (to my current knowledge) compatibility list, see the +Term::ANSIColor module documentation. If you have any additions to the +table in the documentation, please send them to me. + +The test suite requires Test::More (part of Perl since 5.6.2). The +following additional Perl modules will be used by the test suite if +present: + +* Devel::Cover +* Test::MinimumVersion +* Test::Perl::Critic +* Test::Pod +* Test::Pod::Coverage +* Test::Spelling +* Test::Strict +* Test::Synopsis +* Test::Warn + +All are available on CPAN. Those tests will be skipped if the modules are +not available. diff --git a/examples/generate-colors b/examples/generate-colors new file mode 100755 index 0000000..4dd29dc --- /dev/null +++ b/examples/generate-colors @@ -0,0 +1,298 @@ +#!/usr/bin/perl +# +# Generate 256-color test files. +# +# Takes one or more of six arguments: basic, bright, fg256 (foreground), bg256 +# (background), grey, or ansi256. Generates a test file for either basic ANSI +# colors or 256-color emulators, testing that region of colors. +# +# This script requires Term::ANSIColor 4.00 or later already be installed or +# that this script be run manually under Perl with flags pointing to where the +# module is. +# +# Copyright 2012 Kurt Starsinic +# Copyright 2012, 2014, 2016 Russ Allbery +# +# This program is free software; you may redistribute it and/or modify it +# under the same terms as Perl itself. + +use 5.006; +use strict; +use warnings; + +use Carp qw(croak); +use Term::ANSIColor 4.00 qw(color); + +# Screen width for centering headings. +use constant SCREEN_WIDTH => 80; + +# The basic attributes and eight colors. +use constant ATTRIBUTES => qw(bold dark italic underline blink concealed); +use constant COLORS => qw(black red green yellow blue magenta cyan white); + +# print and printf with error checking. autodie unfortunately can't help us +# with these because they can't be prototyped and hence can't be overridden. + +## no critic (Subroutines::RequireArgUnpacking) +sub print_checked { print @_ or croak('print failed'); return } +sub printf_checked { printf @_ or croak('printf failed'); return } +## use critic + +# The sample background or foreground colors for 256-color tests. +my @SAMPLES = qw(000 222 555); + +# The list of all possible RGB values. +my @RGB; +for my $r (0 .. 5) { + for my $g (0 .. 5) { + push(@RGB, map { "$r$g$_" } 0 .. 5); + } +} + +# Center a text string with spaces. +# +# $text - Text to center +# $width - Width in which to center the text +# +# Returns: Text centered within that width +sub center { + my ($text, $width) = @_; + my $padding = $width - length($text); + my $trailing = int($padding / 2); + my $leading = $padding - $trailing; + return (q{ } x $leading) . $text . (q{ } x $trailing); +} + +# Print out the test file that tries all the basic eight ANSI colors. +# +# Returns: undef +# Throws: Text exception on I/O failure +sub print_basic_test { + print_checked("Basic ANSI colors (eight-color, or dim)\n\n"); + for my $bg (COLORS) { + printf_checked('%4s %-7s ', q{ }, $bg); + for my $fg (COLORS) { + print_checked(color($fg, "on_$bg"), center($fg, 8)); + } + print_checked(color('reset'), "\n"); + printf_checked('%4s %-7s ', 'bold', $bg); + for my $fg (COLORS) { + print_checked(color($fg, 'bold', "on_$bg"), center($fg, 8)); + } + print_checked(color('reset'), "\n"); + } + print_checked("\nAttributes: "); + for my $fg (ATTRIBUTES) { + print_checked(center($fg, 10)); + } + print_checked("\n", q{ } x 12); + for my $fg (ATTRIBUTES) { + print_checked(color($fg), center('testing', 10), color('reset')); + } + print_checked("\n\n"); + return; +} + +# Print out the test file that tries all the bright colors from the +# sixteen-color palette. +# +# Returns: undef +# Throws: Text exception on I/O failure +sub print_bright_test { + print_checked("Bright ANSI colors (sixteen-color)\n\n"); + for my $bg (COLORS) { + printf_checked('%6s %-7s ', 'dim', $bg); + for my $fg (COLORS) { + my $escape = color("bright_$fg", "on_$bg"); + print_checked($escape, center($fg, 8)); + } + print_checked(color('reset'), "\n"); + printf_checked('%6s %-7s ', 'bright', $bg); + for my $fg (COLORS) { + my $escape = color("bright_$fg", "on_bright_$bg"); + print_checked($escape, center($fg, 8)); + } + print_checked(color('reset'), "\n"); + } + print_checked("\n"); + return; +} + +# Print out the test file that tries all valid RGB foreground colors. +# +# Returns: undef +# Throws: Text exception on I/O failure +sub print_fg256_test { + print_checked("RGB000 - RGB555 from 256-color palette (foreground)\n"); + for my $bg (@SAMPLES) { + for my $i (0 .. $#RGB) { + if (($i % 18) == 0) { + printf_checked("%s\nbg %03d %s", + color('reset'), $bg, color("on_rgb$bg")); + } + printf_checked('%s%03d ', color("rgb$RGB[$i]"), $RGB[$i]); + } + } + print_checked(color('reset'), "\n\n"); + return; +} + +# Print out the test file that tries all valid RGB background colors. +# +# Returns: undef +# Throws: Text exception on I/O failure +sub print_bg256_test { + print_checked("RGB000 - RGB555 from 256-color palette (background)\n"); + for my $fg (@SAMPLES) { + for my $i (0 .. $#RGB) { + if (($i % 18) == 0) { + printf_checked("%s\nfg %03d %s", + color('reset'), $fg, color("rgb$fg")); + } + printf_checked('%s%03d ', color("on_rgb$RGB[$i]"), $RGB[$i]); + } + } + print_checked(color('reset'), "\n\n"); + return; +} + +# Print out the test file that shows all valid grey-scale colors. +# +# Returns: undef +# Throws: Text exception on I/O failure +sub print_grey_test { + print_checked("Grey0 - Grey23 from 256-color palette\n\n"); + for my $bg (0 .. 23) { + printf_checked('%2d %s', $bg, color("on_grey$bg")); + for my $fg (0 .. 23) { + printf_checked('%s%d ', color("grey$fg"), $fg); + } + print_checked(color('reset'), "\n"); + } + print_checked("\n"); + return; +} + +# Print out the test file that shows the 16 ANSI colors from the 256-color +# palette. +# +# Returns: undef +# Throws: Text exception on I/O failure +sub print_ansi256_test { + print_checked("ANSI colors 0 - 15 from 256-color palette\n\n"); + for my $bg (0 .. 15) { + printf_checked('%2d %s', $bg, color("on_ansi$bg")); + for my $fg (0 .. 15) { + printf_checked('%s%d ', color("ansi$fg"), $fg); + } + print_checked(color('reset'), "\n"); + } + print_checked("\n"); + return; +} + +# Main routine. Scan @ARGV for which test files to print out. +my %tests = ( + basic => \&print_basic_test, + bright => \&print_bright_test, + fg256 => \&print_fg256_test, + bg256 => \&print_bg256_test, + grey => \&print_grey_test, + ansi256 => \&print_ansi256_test, +); +for my $file (@ARGV) { + if ($tests{$file}) { + $tests{$file}->(); + } else { + die "Unknown test file: $file\n"; + } +} + +__END__ + +=for stopwords +fg256 bg256 RGB rgb000 rgb222 rgb555 ansi256 CPAN Starsinic Allbery grey +grey-scale + +=head1 NAME + +generate-colors - Generate color test patterns for ANSI terminal support + +=head1 SYNOPSIS + +B I [I ...] + +=head1 REQUIREMENTS + +Perl 5.6 and Term::ANSIColor 4.00 or later. + +=head1 DESCRIPTION + +B generates test and demonstration tables for ANSI color +and text attribute support for eight-color, sixteen-color, and 256-color +terminal emulators. The I command-line argument specifies a table +to print to standard output. Multiple I arguments can be specified, +and each of those tables will be printed in the order given. + +The supported values of I are: + +=over 8 + +=item basic + +The basic eight ANSI colors as both foreground and background, as well as +examples of bold for each color and a separate table of the non-color text +attributes supported by Term::ANSIColor. + +=item bright + +The "bright" ANSI colors from the sixteen-color palette (colors 8 through +15) on all possible color backgrounds (colors 0 through 15). + +=item fg256 + +All of the 216 colors in the 256-color palette that are specified by three +RGB values (each from 0 to 5) as foreground colors, shown against three +possible backgrounds (rgb000, rgb222, and rgb555). + +=item bg256 + +The same as C except showing all of the background colors for three +different possible foreground colors (rgb000, rgb222, and rgb555). + +=item grey + +The 24 grey-scale colors in the 256-color palette, shown as both foreground +and background. + +=item ansi256 + +The 256-color palette devotes the lowest 16 colors to duplicating the colors +from the sixteen-color palette. This test table shows all sixteen as both +foreground and background colors, but using the 256-color escape sequence +format to specify them. It's possible that this test will not work with +some emulators that support C and C if 256-color support is +not implemented. + +=back + +=head1 SEE ALSO + +L + +This script is an example in the Term::ANSIColor distribution, available +from its web site at L +or from CPAN. + +=head1 AUTHORS + +Original script written by Kurt Starsinic. It was restructured and updated +by Russ Allbery to add the C and C test tables. + +=head1 COPYRIGHT AND LICENSE + +Copyright 2012 Russ Allbery . Copyright 2012 Kurt Starsinic +. This program is free software; you may +redistribute it and/or modify it under the same terms as Perl itself. + +=cut diff --git a/lib/Term/ANSIColor.pm b/lib/Term/ANSIColor.pm new file mode 100644 index 0000000..730124b --- /dev/null +++ b/lib/Term/ANSIColor.pm @@ -0,0 +1,1272 @@ +# Color screen output using ANSI escape sequences. +# +# Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2005, 2006, 2008, 2009, 2010, +# 2011, 2012, 2013, 2014, 2015, 2016 Russ Allbery +# Copyright 1996 Zenin +# Copyright 2012 Kurt Starsinic +# +# This program is free software; you may redistribute it and/or modify it +# under the same terms as Perl itself. +# +# PUSH/POP support submitted 2007 by openmethods.com voice solutions +# +# Ah, September, when the sysadmins turn colors and fall off the trees.... +# -- Dave Van Domelen + +############################################################################## +# Modules and declarations +############################################################################## + +package Term::ANSIColor; + +use 5.006; +use strict; +use warnings; + +# Also uses Carp but loads it on demand to reduce memory usage. + +use Exporter (); + +# use Exporter plus @ISA instead of use base for 5.6 compatibility. +## no critic (ClassHierarchies::ProhibitExplicitISA) + +# Declare variables that should be set in BEGIN for robustness. +## no critic (Modules::ProhibitAutomaticExportation) +our (@EXPORT, @EXPORT_OK, %EXPORT_TAGS, @ISA, $VERSION); + +# We use autoloading, which sets this variable to the name of the called sub. +our $AUTOLOAD; + +# Set $VERSION and everything export-related in a BEGIN block for robustness +# against circular module loading (not that we load any modules, but +# consistency is good). +BEGIN { + $VERSION = '4.06'; + + # All of the basic supported constants, used in %EXPORT_TAGS. + my @colorlist = qw( + CLEAR RESET BOLD DARK + FAINT ITALIC UNDERLINE UNDERSCORE + BLINK REVERSE CONCEALED + + BLACK RED GREEN YELLOW + BLUE MAGENTA CYAN WHITE + ON_BLACK ON_RED ON_GREEN ON_YELLOW + ON_BLUE ON_MAGENTA ON_CYAN ON_WHITE + + BRIGHT_BLACK BRIGHT_RED BRIGHT_GREEN BRIGHT_YELLOW + BRIGHT_BLUE BRIGHT_MAGENTA BRIGHT_CYAN BRIGHT_WHITE + ON_BRIGHT_BLACK ON_BRIGHT_RED ON_BRIGHT_GREEN ON_BRIGHT_YELLOW + ON_BRIGHT_BLUE ON_BRIGHT_MAGENTA ON_BRIGHT_CYAN ON_BRIGHT_WHITE + ); + + # 256-color constants, used in %EXPORT_TAGS. + my @colorlist256 = ( + (map { ("ANSI$_", "ON_ANSI$_") } 0 .. 255), + (map { ("GREY$_", "ON_GREY$_") } 0 .. 23), + ); + for my $r (0 .. 5) { + for my $g (0 .. 5) { + push(@colorlist256, map { ("RGB$r$g$_", "ON_RGB$r$g$_") } 0 .. 5); + } + } + + # Exported symbol configuration. + @ISA = qw(Exporter); + @EXPORT = qw(color colored); + @EXPORT_OK = qw(uncolor colorstrip colorvalid coloralias); + %EXPORT_TAGS = ( + constants => \@colorlist, + constants256 => \@colorlist256, + pushpop => [@colorlist, qw(PUSHCOLOR POPCOLOR LOCALCOLOR)], + ); + Exporter::export_ok_tags('pushpop', 'constants256'); +} + +############################################################################## +# Package variables +############################################################################## + +# If this is set, any color changes will implicitly push the current color +# onto the stack and then pop it at the end of the constant sequence, just as +# if LOCALCOLOR were used. +our $AUTOLOCAL; + +# Caller sets this to force a reset at the end of each constant sequence. +our $AUTORESET; + +# Caller sets this to force colors to be reset at the end of each line. +our $EACHLINE; + +############################################################################## +# Internal data structures +############################################################################## + +# This module does quite a bit of initialization at the time it is first +# loaded, primarily to set up the package-global %ATTRIBUTES hash. The +# entries for 256-color names are easier to handle programmatically, and +# custom colors are also imported from the environment if any are set. + +# All basic supported attributes, including aliases. +#<<< +our %ATTRIBUTES = ( + 'clear' => 0, + 'reset' => 0, + 'bold' => 1, + 'dark' => 2, + 'faint' => 2, + 'italic' => 3, + 'underline' => 4, + 'underscore' => 4, + 'blink' => 5, + 'reverse' => 7, + 'concealed' => 8, + + 'black' => 30, 'on_black' => 40, + 'red' => 31, 'on_red' => 41, + 'green' => 32, 'on_green' => 42, + 'yellow' => 33, 'on_yellow' => 43, + 'blue' => 34, 'on_blue' => 44, + 'magenta' => 35, 'on_magenta' => 45, + 'cyan' => 36, 'on_cyan' => 46, + 'white' => 37, 'on_white' => 47, + + 'bright_black' => 90, 'on_bright_black' => 100, + 'bright_red' => 91, 'on_bright_red' => 101, + 'bright_green' => 92, 'on_bright_green' => 102, + 'bright_yellow' => 93, 'on_bright_yellow' => 103, + 'bright_blue' => 94, 'on_bright_blue' => 104, + 'bright_magenta' => 95, 'on_bright_magenta' => 105, + 'bright_cyan' => 96, 'on_bright_cyan' => 106, + 'bright_white' => 97, 'on_bright_white' => 107, +); +#>>> + +# Generating the 256-color codes involves a lot of codes and offsets that are +# not helped by turning them into constants. + +# The first 16 256-color codes are duplicates of the 16 ANSI colors. The rest +# are RBG and greyscale values. +for my $code (0 .. 15) { + $ATTRIBUTES{"ansi$code"} = "38;5;$code"; + $ATTRIBUTES{"on_ansi$code"} = "48;5;$code"; +} + +# 256-color RGB colors. Red, green, and blue can each be values 0 through 5, +# and the resulting 216 colors start with color 16. +for my $r (0 .. 5) { + for my $g (0 .. 5) { + for my $b (0 .. 5) { + my $code = 16 + (6 * 6 * $r) + (6 * $g) + $b; + $ATTRIBUTES{"rgb$r$g$b"} = "38;5;$code"; + $ATTRIBUTES{"on_rgb$r$g$b"} = "48;5;$code"; + } + } +} + +# The last 256-color codes are 24 shades of grey. +for my $n (0 .. 23) { + my $code = $n + 232; + $ATTRIBUTES{"grey$n"} = "38;5;$code"; + $ATTRIBUTES{"on_grey$n"} = "48;5;$code"; +} + +# Reverse lookup. Alphabetically first name for a sequence is preferred. +our %ATTRIBUTES_R; +for my $attr (reverse sort keys %ATTRIBUTES) { + $ATTRIBUTES_R{ $ATTRIBUTES{$attr} } = $attr; +} + +# Provide ansiN names for all 256 characters to provide a convenient flat +# namespace if one doesn't want to mess with the RGB and greyscale naming. Do +# this after creating %ATTRIBUTES_R since we want to use the canonical names +# when reversing a color. +for my $code (16 .. 255) { + $ATTRIBUTES{"ansi$code"} = "38;5;$code"; + $ATTRIBUTES{"on_ansi$code"} = "48;5;$code"; +} + +# Import any custom colors set in the environment. +our %ALIASES; +if (exists $ENV{ANSI_COLORS_ALIASES}) { + my $spec = $ENV{ANSI_COLORS_ALIASES}; + $spec =~ s{\s+}{}xmsg; + + # Error reporting here is an interesting question. Use warn rather than + # carp because carp would report the line of the use or require, which + # doesn't help anyone understand what's going on, whereas seeing this code + # will be more helpful. + ## no critic (ErrorHandling::RequireCarping) + for my $definition (split m{,}xms, $spec) { + my ($new, $old) = split m{=}xms, $definition, 2; + if (!$new || !$old) { + warn qq{Bad color mapping "$definition"}; + } else { + my $result = eval { coloralias($new, $old) }; + if (!$result) { + my $error = $@; + $error =~ s{ [ ] at [ ] .* }{}xms; + warn qq{$error in "$definition"}; + } + } + } +} + +# Stores the current color stack maintained by PUSHCOLOR and POPCOLOR. This +# is global and therefore not threadsafe. +our @COLORSTACK; + +############################################################################## +# Helper functions +############################################################################## + +# Stub to load the Carp module on demand. +sub croak { + my (@args) = @_; + require Carp; + Carp::croak(@args); +} + +############################################################################## +# Implementation (constant form) +############################################################################## + +# Time to have fun! We now want to define the constant subs, which are named +# the same as the attributes above but in all caps. Each constant sub needs +# to act differently depending on whether $AUTORESET is set. Without +# autoreset: +# +# BLUE "text\n" ==> "\e[34mtext\n" +# +# If $AUTORESET is set, we should instead get: +# +# BLUE "text\n" ==> "\e[34mtext\n\e[0m" +# +# The sub also needs to handle the case where it has no arguments correctly. +# Maintaining all of this as separate subs would be a major nightmare, as well +# as duplicate the %ATTRIBUTES hash, so instead we define an AUTOLOAD sub to +# define the constant subs on demand. To do that, we check the name of the +# called sub against the list of attributes, and if it's an all-caps version +# of one of them, we define the sub on the fly and then run it. +# +# If the environment variable ANSI_COLORS_DISABLED is set to a true value, +# just return the arguments without adding any escape sequences. This is to +# make it easier to write scripts that also work on systems without any ANSI +# support, like Windows consoles. +# +# Avoid using character classes like [:upper:] and \w here, since they load +# Unicode character tables and consume a ton of memory. All of our constants +# only use ASCII characters. +# +## no critic (ClassHierarchies::ProhibitAutoloading) +## no critic (Subroutines::RequireArgUnpacking) +## no critic (RegularExpressions::ProhibitEnumeratedClasses) +sub AUTOLOAD { + my ($sub, $attr) = $AUTOLOAD =~ m{ + \A ( [a-zA-Z0-9:]* :: ([A-Z0-9_]+) ) \z + }xms; + + # Check if we were called with something that doesn't look like an + # attribute. + if (!($attr && defined($ATTRIBUTES{ lc $attr }))) { + croak("undefined subroutine &$AUTOLOAD called"); + } + + # If colors are disabled, just return the input. Do this without + # installing a sub for (marginal, unbenchmarked) speed. + if ($ENV{ANSI_COLORS_DISABLED}) { + return join(q{}, @_); + } + + # We've untainted the name of the sub. + $AUTOLOAD = $sub; + + # Figure out the ANSI string to set the desired attribute. + my $escape = "\e[" . $ATTRIBUTES{ lc $attr } . 'm'; + + # Save the current value of $@. We can't just use local since we want to + # restore it before dispatching to the newly-created sub. (The caller may + # be colorizing output that includes $@.) + my $eval_err = $@; + + # Generate the constant sub, which should still recognize some of our + # package variables. Use string eval to avoid a dependency on + # Sub::Install, even though it makes it somewhat less readable. + ## no critic (BuiltinFunctions::ProhibitStringyEval) + ## no critic (ValuesAndExpressions::ProhibitImplicitNewlines) + my $eval_result = eval qq{ + sub $AUTOLOAD { + if (\$ENV{ANSI_COLORS_DISABLED}) { + return join(q{}, \@_); + } elsif (\$AUTOLOCAL && \@_) { + return PUSHCOLOR('$escape') . join(q{}, \@_) . POPCOLOR; + } elsif (\$AUTORESET && \@_) { + return '$escape' . join(q{}, \@_) . "\e[0m"; + } else { + return '$escape' . join(q{}, \@_); + } + } + 1; + }; + + # Failure is an internal error, not a problem with the caller. + ## no critic (ErrorHandling::RequireCarping) + if (!$eval_result) { + die "failed to generate constant $attr: $@"; + } + + # Restore $@. + ## no critic (Variables::RequireLocalizedPunctuationVars) + $@ = $eval_err; + + # Dispatch to the newly-created sub. + ## no critic (References::ProhibitDoubleSigils) + goto &$AUTOLOAD; +} +## use critic + +# Append a new color to the top of the color stack and return the top of +# the stack. +# +# $text - Any text we're applying colors to, with color escapes prepended +# +# Returns: The text passed in +sub PUSHCOLOR { + my (@text) = @_; + my $text = join(q{}, @text); + + # Extract any number of color-setting escape sequences from the start of + # the string. + my ($color) = $text =~ m{ \A ( (?:\e\[ [\d;]+ m)+ ) }xms; + + # If we already have a stack, append these escapes to the set from the top + # of the stack. This way, each position in the stack stores the complete + # enabled colors for that stage, at the cost of some potential + # inefficiency. + if (@COLORSTACK) { + $color = $COLORSTACK[-1] . $color; + } + + # Push the color onto the stack. + push(@COLORSTACK, $color); + return $text; +} + +# Pop the color stack and return the new top of the stack (or reset, if +# the stack is empty). +# +# @text - Any text we're applying colors to +# +# Returns: The concatenation of @text prepended with the new stack color +sub POPCOLOR { + my (@text) = @_; + pop(@COLORSTACK); + if (@COLORSTACK) { + return $COLORSTACK[-1] . join(q{}, @text); + } else { + return RESET(@text); + } +} + +# Surround arguments with a push and a pop. The effect will be to reset the +# colors to whatever was on the color stack before this sequence of colors was +# applied. +# +# @text - Any text we're applying colors to +# +# Returns: The concatenation of the text and the proper color reset sequence. +sub LOCALCOLOR { + my (@text) = @_; + return PUSHCOLOR(join(q{}, @text)) . POPCOLOR(); +} + +############################################################################## +# Implementation (attribute string form) +############################################################################## + +# Return the escape code for a given set of color attributes. +# +# @codes - A list of possibly space-separated color attributes +# +# Returns: The escape sequence setting those color attributes +# undef if no escape sequences were given +# Throws: Text exception for any invalid attribute +sub color { + my (@codes) = @_; + @codes = map { split } @codes; + + # Return the empty string if colors are disabled. + if ($ENV{ANSI_COLORS_DISABLED}) { + return q{}; + } + + # Build the attribute string from semicolon-separated numbers. + my $attribute = q{}; + for my $code (@codes) { + $code = lc($code); + if (defined($ATTRIBUTES{$code})) { + $attribute .= $ATTRIBUTES{$code} . q{;}; + } elsif (defined($ALIASES{$code})) { + $attribute .= $ALIASES{$code} . q{;}; + } else { + croak("Invalid attribute name $code"); + } + } + + # We added one too many semicolons for simplicity. Remove the last one. + chop($attribute); + + # Return undef if there were no attributes. + return ($attribute ne q{}) ? "\e[${attribute}m" : undef; +} + +# Return a list of named color attributes for a given set of escape codes. +# Escape sequences can be given with or without enclosing "\e[" and "m". The +# empty escape sequence '' or "\e[m" gives an empty list of attrs. +# +# There is one special case. 256-color codes start with 38 or 48, followed by +# a 5 and then the 256-color code. +# +# @escapes - A list of escape sequences or escape sequence numbers +# +# Returns: An array of attribute names corresponding to those sequences +# Throws: Text exceptions on invalid escape sequences or unknown colors +sub uncolor { + my (@escapes) = @_; + my (@nums, @result); + + # Walk the list of escapes and build a list of attribute numbers. + for my $escape (@escapes) { + $escape =~ s{ \A \e\[ }{}xms; + $escape =~ s{ m \z } {}xms; + my ($attrs) = $escape =~ m{ \A ((?:\d+;)* \d*) \z }xms; + if (!defined($attrs)) { + croak("Bad escape sequence $escape"); + } + + # Pull off 256-color codes (38;5;n or 48;5;n) as a unit. + push(@nums, $attrs =~ m{ ( 0*[34]8;0*5;\d+ | \d+ ) (?: ; | \z ) }xmsg); + } + + # Now, walk the list of numbers and convert them to attribute names. + # Strip leading zeroes from any of the numbers. (xterm, at least, allows + # leading zeroes to be added to any number in an escape sequence.) + for my $num (@nums) { + $num =~ s{ ( \A | ; ) 0+ (\d) }{$1$2}xmsg; + my $name = $ATTRIBUTES_R{$num}; + if (!defined($name)) { + croak("No name for escape sequence $num"); + } + push(@result, $name); + } + + # Return the attribute names. + return @result; +} + +# Given a string and a set of attributes, returns the string surrounded by +# escape codes to set those attributes and then clear them at the end of the +# string. The attributes can be given either as an array ref as the first +# argument or as a list as the second and subsequent arguments. +# +# If $EACHLINE is set, insert a reset before each occurrence of the string +# $EACHLINE and the starting attribute code after the string $EACHLINE, so +# that no attribute crosses line delimiters (this is often desirable if the +# output is to be piped to a pager or some other program). +# +# $first - An anonymous array of attributes or the text to color +# @rest - The text to color or the list of attributes +# +# Returns: The text, concatenated if necessary, surrounded by escapes to set +# the desired colors and reset them afterwards +# Throws: Text exception on invalid attributes +sub colored { + my ($first, @rest) = @_; + my ($string, @codes); + if (ref($first) && ref($first) eq 'ARRAY') { + @codes = @{$first}; + $string = join(q{}, @rest); + } else { + $string = $first; + @codes = @rest; + } + + # Return the string unmolested if colors are disabled. + if ($ENV{ANSI_COLORS_DISABLED}) { + return $string; + } + + # Find the attribute string for our colors. + my $attr = color(@codes); + + # If $EACHLINE is defined, split the string on line boundaries, suppress + # empty segments, and then colorize each of the line sections. + if (defined($EACHLINE)) { + my @text = map { ($_ ne $EACHLINE) ? $attr . $_ . "\e[0m" : $_ } + grep { length > 0 } + split(m{ (\Q$EACHLINE\E) }xms, $string); + return join(q{}, @text); + } else { + return $attr . $string . "\e[0m"; + } +} + +# Define a new color alias, or return the value of an existing alias. +# +# $alias - The color alias to define +# $color - The standard color the alias will correspond to (optional) +# +# Returns: The standard color value of the alias +# undef if one argument was given and the alias was not recognized +# Throws: Text exceptions for invalid alias names, attempts to use a +# standard color name as an alias, or an unknown standard color name +sub coloralias { + my ($alias, $color) = @_; + if (!defined($color)) { + if (!exists $ALIASES{$alias}) { + return; + } else { + return $ATTRIBUTES_R{ $ALIASES{$alias} }; + } + } + + # Avoid \w here to not load Unicode character tables, which increases the + # memory footprint of this module considerably. + # + ## no critic (RegularExpressions::ProhibitEnumeratedClasses) + if ($alias !~ m{ \A [a-zA-Z0-9._-]+ \z }xms) { + croak(qq{Invalid alias name "$alias"}); + } elsif ($ATTRIBUTES{$alias}) { + croak(qq{Cannot alias standard color "$alias"}); + } elsif (!exists $ATTRIBUTES{$color}) { + croak(qq{Invalid attribute name "$color"}); + } + ## use critic + + # Set the alias and return. + $ALIASES{$alias} = $ATTRIBUTES{$color}; + return $color; +} + +# Given a string, strip the ANSI color codes out of that string and return the +# result. This removes only ANSI color codes, not movement codes and other +# escape sequences. +# +# @string - The list of strings to sanitize +# +# Returns: (array) The strings stripped of ANSI color escape sequences +# (scalar) The same, concatenated +sub colorstrip { + my (@string) = @_; + for my $string (@string) { + $string =~ s{ \e\[ [\d;]* m }{}xmsg; + } + return wantarray ? @string : join(q{}, @string); +} + +# Given a list of color attributes (arguments for color, for instance), return +# true if they're all valid or false if any of them are invalid. +# +# @codes - A list of color attributes, possibly space-separated +# +# Returns: True if all the attributes are valid, false otherwise. +sub colorvalid { + my (@codes) = @_; + @codes = map { split(q{ }, lc) } @codes; + for my $code (@codes) { + if (!(defined($ATTRIBUTES{$code}) || defined($ALIASES{$code}))) { + return; + } + } + return 1; +} + +############################################################################## +# Module return value and documentation +############################################################################## + +# Ensure we evaluate to true. +1; +__END__ + +=head1 NAME + +Term::ANSIColor - Color screen output using ANSI escape sequences + +=for stopwords +cyan colorize namespace runtime TMTOWTDI cmd.exe cmd.exe. 4nt.exe. 4nt.exe +command.com NT ESC Delvare SSH OpenSSH aixterm ECMA-048 Fraktur overlining +Zenin reimplemented Allbery PUSHCOLOR POPCOLOR LOCALCOLOR openmethods.com +openmethods.com. grey ATTR urxvt mistyped prepending Bareword filehandle +Cygwin Starsinic aterm rxvt CPAN RGB Solarized Whitespace alphanumerics +undef + +=head1 SYNOPSIS + + use Term::ANSIColor; + print color('bold blue'); + print "This text is bold blue.\n"; + print color('reset'); + print "This text is normal.\n"; + print colored("Yellow on magenta.", 'yellow on_magenta'), "\n"; + print "This text is normal.\n"; + print colored(['yellow on_magenta'], 'Yellow on magenta.', "\n"); + print colored(['red on_bright_yellow'], 'Red on bright yellow.', "\n"); + print colored(['bright_red on_black'], 'Bright red on black.', "\n"); + print "\n"; + + # Map escape sequences back to color names. + use Term::ANSIColor 1.04 qw(uncolor); + my $names = uncolor('01;31'); + print join(q{ }, @{$names}), "\n"; + + # Strip all color escape sequences. + use Term::ANSIColor 2.01 qw(colorstrip); + print colorstrip("\e[1mThis is bold\e[0m"), "\n"; + + # Determine whether a color is valid. + use Term::ANSIColor 2.02 qw(colorvalid); + my $valid = colorvalid('blue bold', 'on_magenta'); + print "Color string is ", $valid ? "valid\n" : "invalid\n"; + + # Create new aliases for colors. + use Term::ANSIColor 4.00 qw(coloralias); + coloralias('alert', 'red'); + print "Alert is ", coloralias('alert'), "\n"; + print colored("This is in red.", 'alert'), "\n"; + + use Term::ANSIColor qw(:constants); + print BOLD, BLUE, "This text is in bold blue.\n", RESET; + + use Term::ANSIColor qw(:constants); + { + local $Term::ANSIColor::AUTORESET = 1; + print BOLD BLUE "This text is in bold blue.\n"; + print "This text is normal.\n"; + } + + use Term::ANSIColor 2.00 qw(:pushpop); + print PUSHCOLOR RED ON_GREEN "This text is red on green.\n"; + print PUSHCOLOR BRIGHT_BLUE "This text is bright blue on green.\n"; + print RESET BRIGHT_BLUE "This text is just bright blue.\n"; + print POPCOLOR "Back to red on green.\n"; + print LOCALCOLOR GREEN ON_BLUE "This text is green on blue.\n"; + print "This text is red on green.\n"; + { + local $Term::ANSIColor::AUTOLOCAL = 1; + print ON_BLUE "This text is red on blue.\n"; + print "This text is red on green.\n"; + } + print POPCOLOR "Back to whatever we started as.\n"; + +=head1 DESCRIPTION + +This module has two interfaces, one through color() and colored() and the +other through constants. It also offers the utility functions uncolor(), +colorstrip(), colorvalid(), and coloralias(), which have to be explicitly +imported to be used (see L). + +See L for the versions of Term::ANSIColor that introduced +particular features and the versions of Perl that included them. + +=head2 Supported Colors + +Terminal emulators that support color divide into three types: ones that +support only eight colors, ones that support sixteen, and ones that +support 256. This module provides the ANSI escape codes for all of them. +These colors are referred to as ANSI colors 0 through 7 (normal), 8 +through 15 (16-color), and 16 through 255 (256-color). + +Unfortunately, interpretation of colors 0 through 7 often depends on +whether the emulator supports eight colors or sixteen colors. Emulators +that only support eight colors (such as the Linux console) will display +colors 0 through 7 with normal brightness and ignore colors 8 through 15, +treating them the same as white. Emulators that support 16 colors, such +as gnome-terminal, normally display colors 0 through 7 as dim or darker +versions and colors 8 through 15 as normal brightness. On such emulators, +the "normal" white (color 7) usually is shown as pale grey, requiring +bright white (15) to be used to get a real white color. Bright black +usually is a dark grey color, although some terminals display it as pure +black. Some sixteen-color terminal emulators also treat normal yellow +(color 3) as orange or brown, and bright yellow (color 11) as yellow. + +Following the normal convention of sixteen-color emulators, this module +provides a pair of attributes for each color. For every normal color (0 +through 7), the corresponding bright color (8 through 15) is obtained by +prepending the string C to the normal color name. For example, +C is color 1 and C is color 9. The same applies for +background colors: C is the normal color and C is +the bright color. Capitalize these strings for the constant interface. + +For 256-color emulators, this module additionally provides C +through C, which are the same as colors 0 through 15 in +sixteen-color emulators but use the 256-color escape syntax, C +through C ranging from nearly black to nearly white, and a set of +RGB colors. The RGB colors are of the form C> where I, I, +and I are numbers from 0 to 5 giving the intensity of red, green, and +blue. The grey and RGB colors are also available as C through +C if you want simple names for all 256 colors. C variants +of all of these colors are also provided. These colors may be ignored +completely on non-256-color terminals or may be misinterpreted and produce +random behavior. Additional attributes such as blink, italic, or bold may +not work with the 256-color palette. + +There is unfortunately no way to know whether the current emulator +supports more than eight colors, which makes the choice of colors +difficult. The most conservative choice is to use only the regular +colors, which are at least displayed on all emulators. However, they will +appear dark in sixteen-color terminal emulators, including most common +emulators in UNIX X environments. If you know the display is one of those +emulators, you may wish to use the bright variants instead. Even better, +offer the user a way to configure the colors for a given application to +fit their terminal emulator. + +=head2 Function Interface + +The function interface uses attribute strings to describe the colors and +text attributes to assign to text. The recognized non-color attributes +are clear, reset, bold, dark, faint, italic, underline, underscore, blink, +reverse, and concealed. Clear and reset (reset to default attributes), +dark and faint (dim and saturated), and underline and underscore are +equivalent, so use whichever is the most intuitive to you. + +Note that not all attributes are supported by all terminal types, and some +terminals may not support any of these sequences. Dark and faint, italic, +blink, and concealed in particular are frequently not implemented. + +The recognized normal foreground color attributes (colors 0 to 7) are: + + black red green yellow blue magenta cyan white + +The corresponding bright foreground color attributes (colors 8 to 15) are: + + bright_black bright_red bright_green bright_yellow + bright_blue bright_magenta bright_cyan bright_white + +The recognized normal background color attributes (colors 0 to 7) are: + + on_black on_red on_green on yellow + on_blue on_magenta on_cyan on_white + +The recognized bright background color attributes (colors 8 to 15) are: + + on_bright_black on_bright_red on_bright_green on_bright_yellow + on_bright_blue on_bright_magenta on_bright_cyan on_bright_white + +For 256-color terminals, the recognized foreground colors are: + + ansi0 .. ansi255 + grey0 .. grey23 + +plus C> for I, I, and I values from 0 to 5, such as +C or C. Similarly, the recognized background colors are: + + on_ansi0 .. on_ansi255 + on_grey0 .. on_grey23 + +plus C> for I, I, and I values from 0 to 5. + +For any of the above listed attributes, case is not significant. + +Attributes, once set, last until they are unset (by printing the attribute +C or C). Be careful to do this, or otherwise your attribute +will last after your script is done running, and people get very annoyed +at having their prompt and typing changed to weird colors. + +=over 4 + +=item color(ATTR[, ATTR ...]) + +color() takes any number of strings as arguments and considers them to be +space-separated lists of attributes. It then forms and returns the escape +sequence to set those attributes. It doesn't print it out, just returns +it, so you'll have to print it yourself if you want to. This is so that +you can save it as a string, pass it to something else, send it to a file +handle, or do anything else with it that you might care to. color() +throws an exception if given an invalid attribute. + +=item colored(STRING, ATTR[, ATTR ...]) + +=item colored(ATTR-REF, STRING[, STRING...]) + +As an aid in resetting colors, colored() takes a scalar as the first +argument and any number of attribute strings as the second argument and +returns the scalar wrapped in escape codes so that the attributes will be +set as requested before the string and reset to normal after the string. +Alternately, you can pass a reference to an array as the first argument, +and then the contents of that array will be taken as attributes and color +codes and the remainder of the arguments as text to colorize. + +Normally, colored() just puts attribute codes at the beginning and end of +the string, but if you set $Term::ANSIColor::EACHLINE to some string, that +string will be considered the line delimiter and the attribute will be set +at the beginning of each line of the passed string and reset at the end of +each line. This is often desirable if the output contains newlines and +you're using background colors, since a background color that persists +across a newline is often interpreted by the terminal as providing the +default background color for the next line. Programs like pagers can also +be confused by attributes that span lines. Normally you'll want to set +$Term::ANSIColor::EACHLINE to C<"\n"> to use this feature. + +=item uncolor(ESCAPE) + +uncolor() performs the opposite translation as color(), turning escape +sequences into a list of strings corresponding to the attributes being set +by those sequences. uncolor() will never return C through +C, instead preferring the C and C names (and likewise +for C through C). + +=item colorstrip(STRING[, STRING ...]) + +colorstrip() removes all color escape sequences from the provided strings, +returning the modified strings separately in array context or joined +together in scalar context. Its arguments are not modified. + +=item colorvalid(ATTR[, ATTR ...]) + +colorvalid() takes attribute strings the same as color() and returns true +if all attributes are known and false otherwise. + +=item coloralias(ALIAS[, ATTR]) + +If ATTR is specified, coloralias() sets up an alias of ALIAS for the +standard color ATTR. From that point forward, ALIAS can be passed into +color(), colored(), and colorvalid() and will have the same meaning as +ATTR. One possible use of this facility is to give more meaningful names +to the 256-color RGB colors. Only ASCII alphanumerics, C<.>, C<_>, and +C<-> are allowed in alias names. + +If ATTR is not specified, coloralias() returns the standard color name to +which ALIAS is aliased, if any, or undef if ALIAS does not exist. + +This is the same facility used by the ANSI_COLORS_ALIASES environment +variable (see L below) but can be used at runtime, not just +when the module is loaded. + +Later invocations of coloralias() with the same ALIAS will override +earlier aliases. There is no way to remove an alias. + +Aliases have no effect on the return value of uncolor(). + +B: Aliases are global and affect all callers in the same process. +There is no way to set an alias limited to a particular block of code or a +particular object. + +=back + +=head2 Constant Interface + +Alternately, if you import C<:constants>, you can use the following +constants directly: + + CLEAR RESET BOLD DARK + FAINT ITALIC UNDERLINE UNDERSCORE + BLINK REVERSE CONCEALED + + BLACK RED GREEN YELLOW + BLUE MAGENTA CYAN WHITE + BRIGHT_BLACK BRIGHT_RED BRIGHT_GREEN BRIGHT_YELLOW + BRIGHT_BLUE BRIGHT_MAGENTA BRIGHT_CYAN BRIGHT_WHITE + + ON_BLACK ON_RED ON_GREEN ON_YELLOW + ON_BLUE ON_MAGENTA ON_CYAN ON_WHITE + ON_BRIGHT_BLACK ON_BRIGHT_RED ON_BRIGHT_GREEN ON_BRIGHT_YELLOW + ON_BRIGHT_BLUE ON_BRIGHT_MAGENTA ON_BRIGHT_CYAN ON_BRIGHT_WHITE + +These are the same as color('attribute') and can be used if you prefer +typing: + + print BOLD BLUE ON_WHITE "Text", RESET, "\n"; + +to + + print colored ("Text", 'bold blue on_white'), "\n"; + +(Note that the newline is kept separate to avoid confusing the terminal as +described above since a background color is being used.) + +If you import C<:constants256>, you can use the following constants +directly: + + ANSI0 .. ANSI255 + GREY0 .. GREY23 + + RGBXYZ (for X, Y, and Z values from 0 to 5, like RGB000 or RGB515) + + ON_ANSI0 .. ON_ANSI255 + ON_GREY0 .. ON_GREY23 + + ON_RGBXYZ (for X, Y, and Z values from 0 to 5) + +Note that C<:constants256> does not include the other constants, so if you +want to mix both, you need to include C<:constants> as well. You may want +to explicitly import at least C, as in: + + use Term::ANSIColor 4.00 qw(RESET :constants256); + +When using the constants, if you don't want to have to remember to add the +C<, RESET> at the end of each print line, you can set +$Term::ANSIColor::AUTORESET to a true value. Then, the display mode will +automatically be reset if there is no comma after the constant. In other +words, with that variable set: + + print BOLD BLUE "Text\n"; + +will reset the display mode afterward, whereas: + + print BOLD, BLUE, "Text\n"; + +will not. If you are using background colors, you will probably want to +either use say() (in newer versions of Perl) or print the newline with a +separate print statement to avoid confusing the terminal. + +If $Term::ANSIColor::AUTOLOCAL is set (see below), it takes precedence +over $Term::ANSIColor::AUTORESET, and the latter is ignored. + +The subroutine interface has the advantage over the constants interface in +that only two subroutines are exported into your namespace, versus +thirty-eight in the constants interface. On the flip side, the constants +interface has the advantage of better compile time error checking, since +misspelled names of colors or attributes in calls to color() and colored() +won't be caught until runtime whereas misspelled names of constants will +be caught at compile time. So, pollute your namespace with almost two +dozen subroutines that you may not even use that often, or risk a silly +bug by mistyping an attribute. Your choice, TMTOWTDI after all. + +=head2 The Color Stack + +You can import C<:pushpop> and maintain a stack of colors using PUSHCOLOR, +POPCOLOR, and LOCALCOLOR. PUSHCOLOR takes the attribute string that +starts its argument and pushes it onto a stack of attributes. POPCOLOR +removes the top of the stack and restores the previous attributes set by +the argument of a prior PUSHCOLOR. LOCALCOLOR surrounds its argument in a +PUSHCOLOR and POPCOLOR so that the color resets afterward. + +If $Term::ANSIColor::AUTOLOCAL is set, each sequence of color constants +will be implicitly preceded by LOCALCOLOR. In other words, the following: + + { + local $Term::ANSIColor::AUTOLOCAL = 1; + print BLUE "Text\n"; + } + +is equivalent to: + + print LOCALCOLOR BLUE "Text\n"; + +If $Term::ANSIColor::AUTOLOCAL is set, it takes precedence over +$Term::ANSIColor::AUTORESET, and the latter is ignored. + +When using PUSHCOLOR, POPCOLOR, and LOCALCOLOR, it's particularly +important to not put commas between the constants. + + print PUSHCOLOR BLUE "Text\n"; + +will correctly push BLUE onto the top of the stack. + + print PUSHCOLOR, BLUE, "Text\n"; # wrong! + +will not, and a subsequent pop won't restore the correct attributes. +PUSHCOLOR pushes the attributes set by its argument, which is normally a +string of color constants. It can't ask the terminal what the current +attributes are. + +=head1 DIAGNOSTICS + +=over 4 + +=item Bad color mapping %s + +(W) The specified color mapping from ANSI_COLORS_ALIASES is not valid and +could not be parsed. It was ignored. + +=item Bad escape sequence %s + +(F) You passed an invalid ANSI escape sequence to uncolor(). + +=item Bareword "%s" not allowed while "strict subs" in use + +(F) You probably mistyped a constant color name such as: + + $Foobar = FOOBAR . "This line should be blue\n"; + +or: + + @Foobar = FOOBAR, "This line should be blue\n"; + +This will only show up under use strict (another good reason to run under +use strict). + +=item Cannot alias standard color %s + +(F) The alias name passed to coloralias() matches a standard color name. +Standard color names cannot be aliased. + +=item Cannot alias standard color %s in %s + +(W) The same, but in ANSI_COLORS_ALIASES. The color mapping was ignored. + +=item Invalid alias name %s + +(F) You passed an invalid alias name to coloralias(). Alias names must +consist only of alphanumerics, C<.>, C<->, and C<_>. + +=item Invalid alias name %s in %s + +(W) You specified an invalid alias name on the left hand of the equal sign +in a color mapping in ANSI_COLORS_ALIASES. The color mapping was ignored. + +=item Invalid attribute name %s + +(F) You passed an invalid attribute name to color(), colored(), or +coloralias(). + +=item Invalid attribute name %s in %s + +(W) You specified an invalid attribute name on the right hand of the equal +sign in a color mapping in ANSI_COLORS_ALIASES. The color mapping was +ignored. + +=item Name "%s" used only once: possible typo + +(W) You probably mistyped a constant color name such as: + + print FOOBAR "This text is color FOOBAR\n"; + +It's probably better to always use commas after constant names in order to +force the next error. + +=item No comma allowed after filehandle + +(F) You probably mistyped a constant color name such as: + + print FOOBAR, "This text is color FOOBAR\n"; + +Generating this fatal compile error is one of the main advantages of using +the constants interface, since you'll immediately know if you mistype a +color name. + +=item No name for escape sequence %s + +(F) The ANSI escape sequence passed to uncolor() contains escapes which +aren't recognized and can't be translated to names. + +=back + +=head1 ENVIRONMENT + +=over 4 + +=item ANSI_COLORS_ALIASES + +This environment variable allows the user to specify custom color aliases +that will be understood by color(), colored(), and colorvalid(). None of +the other functions will be affected, and no new color constants will be +created. The custom colors are aliases for existing color names; no new +escape sequences can be introduced. Only alphanumerics, C<.>, C<_>, and +C<-> are allowed in alias names. + +The format is: + + ANSI_COLORS_ALIASES='newcolor1=oldcolor1,newcolor2=oldcolor2' + +Whitespace is ignored. + +For example the L colors +can be mapped with: + + ANSI_COLORS_ALIASES='\ + base00=bright_yellow, on_base00=on_bright_yellow,\ + base01=bright_green, on_base01=on_bright_green, \ + base02=black, on_base02=on_black, \ + base03=bright_black, on_base03=on_bright_black, \ + base0=bright_blue, on_base0=on_bright_blue, \ + base1=bright_cyan, on_base1=on_bright_cyan, \ + base2=white, on_base2=on_white, \ + base3=bright_white, on_base3=on_bright_white, \ + orange=bright_red, on_orange=on_bright_red, \ + violet=bright_magenta,on_violet=on_bright_magenta' + +This environment variable is read and applied when the Term::ANSIColor +module is loaded and is then subsequently ignored. Changes to +ANSI_COLORS_ALIASES after the module is loaded will have no effect. See +coloralias() for an equivalent facility that can be used at runtime. + +=item ANSI_COLORS_DISABLED + +If this environment variable is set to a true value, all of the functions +defined by this module (color(), colored(), and all of the constants not +previously used in the program) will not output any escape sequences and +instead will just return the empty string or pass through the original +text as appropriate. This is intended to support easy use of scripts +using this module on platforms that don't support ANSI escape sequences. + +=back + +=head1 COMPATIBILITY + +Term::ANSIColor was first included with Perl in Perl 5.6.0. + +The uncolor() function and support for ANSI_COLORS_DISABLED were added in +Term::ANSIColor 1.04, included in Perl 5.8.0. + +Support for dark was added in Term::ANSIColor 1.08, included in Perl +5.8.4. + +The color stack, including the C<:pushpop> import tag, PUSHCOLOR, +POPCOLOR, LOCALCOLOR, and the $Term::ANSIColor::AUTOLOCAL variable, was +added in Term::ANSIColor 2.00, included in Perl 5.10.1. + +colorstrip() was added in Term::ANSIColor 2.01 and colorvalid() was added +in Term::ANSIColor 2.02, both included in Perl 5.11.0. + +Support for colors 8 through 15 (the C variants) was added in +Term::ANSIColor 3.00, included in Perl 5.13.3. + +Support for italic was added in Term::ANSIColor 3.02, included in Perl +5.17.1. + +Support for colors 16 through 256 (the C, C, and C +colors), the C<:constants256> import tag, the coloralias() function, and +support for the ANSI_COLORS_ALIASES environment variable were added in +Term::ANSIColor 4.00, included in Perl 5.17.8. + +$Term::ANSIColor::AUTOLOCAL was changed to take precedence over +$Term::ANSIColor::AUTORESET, rather than the other way around, in +Term::ANSIColor 4.00, included in Perl 5.17.8. + +C through C, as aliases for the C and C +colors, and the corresponding C names and C and C +constants, were added in Term::ANSIColor 4.06. + +=head1 RESTRICTIONS + +It would be nice if one could leave off the commas around the constants +entirely and just say: + + print BOLD BLUE ON_WHITE "Text\n" RESET; + +but the syntax of Perl doesn't allow this. You need a comma after the +string. (Of course, you may consider it a bug that commas between all the +constants aren't required, in which case you may feel free to insert +commas unless you're using $Term::ANSIColor::AUTORESET or +PUSHCOLOR/POPCOLOR.) + +For easier debugging, you may prefer to always use the commas when not +setting $Term::ANSIColor::AUTORESET or PUSHCOLOR/POPCOLOR so that you'll +get a fatal compile error rather than a warning. + +It's not possible to use this module to embed formatting and color +attributes using Perl formats. They replace the escape character with a +space (as documented in L), resulting in garbled output from +the unrecognized attribute. Even if there were a way around that problem, +the format doesn't know that the non-printing escape sequence is +zero-length and would incorrectly format the output. For formatted output +using color or other attributes, either use sprintf() instead or use +formline() and then add the color or other attributes after formatting and +before output. + +=head1 NOTES + +The codes generated by this module are standard terminal control codes, +complying with ECMA-048 and ISO 6429 (generally referred to as "ANSI +color" for the color codes). The non-color control codes (bold, dark, +italic, underline, and reverse) are part of the earlier ANSI X3.64 +standard for control sequences for video terminals and peripherals. + +Note that not all displays are ISO 6429-compliant, or even X3.64-compliant +(or are even attempting to be so). This module will not work as expected +on displays that do not honor these escape sequences, such as cmd.exe, +4nt.exe, and command.com under either Windows NT or Windows 2000. They +may just be ignored, or they may display as an ESC character followed by +some apparent garbage. + +Jean Delvare provided the following table of different common terminal +emulators and their support for the various attributes and others have +helped me flesh it out: + + clear bold faint under blink reverse conceal + ------------------------------------------------------------------------ + xterm yes yes no yes yes yes yes + linux yes yes yes bold yes yes no + rxvt yes yes no yes bold/black yes no + dtterm yes yes yes yes reverse yes yes + teraterm yes reverse no yes rev/red yes no + aixterm kinda normal no yes no yes yes + PuTTY yes color no yes no yes no + Windows yes no no no no yes no + Cygwin SSH yes yes no color color color yes + Terminal.app yes yes no yes yes yes yes + +Windows is Windows telnet, Cygwin SSH is the OpenSSH implementation under +Cygwin on Windows NT, and Mac Terminal is the Terminal application in Mac +OS X. Where the entry is other than yes or no, that emulator displays the +given attribute as something else instead. Note that on an aixterm, clear +doesn't reset colors; you have to explicitly set the colors back to what +you want. More entries in this table are welcome. + +Support for code 3 (italic) is rare and therefore not mentioned in that +table. It is not believed to be fully supported by any of the terminals +listed, although it's displayed as green in the Linux console, but it is +reportedly supported by urxvt. + +Note that codes 6 (rapid blink) and 9 (strike-through) are specified in +ANSI X3.64 and ECMA-048 but are not commonly supported by most displays +and emulators and therefore aren't supported by this module at the present +time. ECMA-048 also specifies a large number of other attributes, +including a sequence of attributes for font changes, Fraktur characters, +double-underlining, framing, circling, and overlining. As none of these +attributes are widely supported or useful, they also aren't currently +supported by this module. + +Most modern X terminal emulators support 256 colors. Known to not support +those colors are aterm, rxvt, Terminal.app, and TTY/VC. + +=head1 AUTHORS + +Original idea (using constants) by Zenin, reimplemented using subs by Russ +Allbery , and then combined with the original idea by +Russ with input from Zenin. 256-color support is based on work by Kurt +Starsinic. Russ Allbery now maintains this module. + +PUSHCOLOR, POPCOLOR, and LOCALCOLOR were contributed by openmethods.com +voice solutions. + +=head1 COPYRIGHT AND LICENSE + +Copyright 1996 Zenin + +Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2005, 2006, 2008, 2009, 2010, +2011, 2012, 2013, 2014, 2015, 2016 Russ Allbery + +Copyright 2012 Kurt Starsinic + +This program is free software; you may redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +The CPAN module L provides a different and more +comprehensive interface for 256-color emulators that may be more +convenient. The CPAN module L provides ANSI color +(and other escape sequence) support in the Win32 Console environment. +The CPAN module L provides a different interface using +objects and operator overloading. + +ECMA-048 is available on-line (at least at the time of this writing) at +L. + +ISO 6429 is available from ISO for a charge; the author of this module +does not own a copy of it. Since the source material for ISO 6429 was +ECMA-048 and the latter is available for free, there seems little reason +to obtain the ISO standard. + +The 256-color control sequences are documented at +L (search for +256-color). + +The current version of this module is always available from its web site +at L. It is also part +of the Perl core distribution as of 5.6.0. + +=cut diff --git a/t/data/perl.conf b/t/data/perl.conf new file mode 100644 index 0000000..aeb50bd --- /dev/null +++ b/t/data/perl.conf @@ -0,0 +1,19 @@ +# Configuration for Perl tests. -*- perl -*- + +# The level of coverage achieved by the test suite. +$COVERAGE_LEVEL = 100; + +# Skip taint tests when doing coverage analysis since Devel::Cover can't +# handle taint checking. +@COVERAGE_SKIP_TESTS = qw(taint); + +# Default minimum version requirement. +$MINIMUM_VERSION = '5.006'; + +# Some of the constant subs are documented but not in a way that +# Test::Pod::Coverage can understand. croak is an internal helper function +# because Carp consumes a lot of memory. +@POD_COVERAGE_EXCLUDE = (qr{ \A \w+ COLOR \z }xms, qr{ \A croak \z }xms); + +# File must end with this line. +1; diff --git a/t/data/perlcriticrc b/t/data/perlcriticrc new file mode 100644 index 0000000..cf33376 --- /dev/null +++ b/t/data/perlcriticrc @@ -0,0 +1,100 @@ +# -*- conf -*- +# +# Default configuration for perlcritic. Be sure to copy this into the source +# for packages that run perlcritic tests automatically during the build for +# reproducible test results. +# +# This file has been updated to match perlcritic 1.118. +# +# The canonical version of this file is maintained in the rra-c-util package, +# which can be found at . +# +# Written by Russ Allbery +# Copyright 2011, 2012, 2013 +# The Board of Trustees of the Leland Stanford Junior University +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +severity = 1 +verbose = %f:%l:%c: [%p] %m (%e, Severity: %s)\n + +# I prefer this policy (a lot, actually), but other people in my group at +# Stanford really didn't like it, so this is my compromise to agree with a +# group coding style. +[-CodeLayout::ProhibitParensWithBuiltins] + +# Stanford's coding style allows postfix unless for flow control. There +# doesn't appear to be any way to allow it only for flow control (the logic +# for "if" and "when" appears to be special-cased), so we have to allow unless +# globally. +[ControlStructures::ProhibitPostfixControls] +allow = unless + +# This is handled with a separate test case that uses Test::Spelling. +[-Documentation::PodSpelling] + +# Pod::Man and Pod::Text fixed this bug years ago. I know, I maintain them. +[-Documentation::RequirePodLinksIncludeText] + +# The POD sections Perl::Critic wants are incompatible with the POD template +# from perlpodstyle, which is what I use for my POD documentation. +[-Documentation::RequirePodSections] + +# This problem was fixed in Perl 5.14, which now properly preserves the value +# of $@ even if destructors run at exit from the eval block. +[-ErrorHandling::RequireCheckingReturnValueOfEval] + +# The default of 9 is too small and forces weird code contortions. +[InputOutput::RequireBriefOpen] +lines = 25 + +# This is correct 80% of the time, but it isn't correct for a lot of scripts +# inside packages, where maintaining $VERSION isn't worth the effort. +# Unfortunately, there's no way to override it, so it gets turned off +# globally. +[-Modules::RequireVersionVar] + +# This sounds interesting but is actually useless. Any large blocks of +# literal text, which does not add to the complexity of the regex, will set it +# off. +[-RegularExpressions::ProhibitComplexRegexes] + +# I generally don't want to require Readonly as a prerequisite for all my Perl +# modules. +[-ValuesAndExpressions::ProhibitConstantPragma] + +# A good idea, but there are too many places where this would be more +# confusing than helpful. Pull out numbers if one might change them +# independent of the algorithm, but don't do so for mathematical formulae. +[-ValuesAndExpressions::ProhibitMagicNumbers] + +# Increase this to six digits so that I'm not told to add underscores to +# port numbers (which is just silly). +[ValuesAndExpressions::RequireNumberSeparators] +min_value = 100000 + +# Text::Wrap has a broken interface that requires use of package variables. +[Variables::ProhibitPackageVars] +add_packages = Text::Wrap + +# use English was one of the worst ideas in the history of Perl. It makes the +# code slightly more readable for amateurs at the cost of confusing +# experienced Perl programmers and sending people in futile quests for where +# these magical global variables are defined. +[-Variables::ProhibitPunctuationVars] diff --git a/t/data/perltidyrc b/t/data/perltidyrc new file mode 100644 index 0000000..e35e8a8 --- /dev/null +++ b/t/data/perltidyrc @@ -0,0 +1,14 @@ +# -*- conf -*- +# +# Default options for perltidy for proper Perl code reformatting. +# +# The canonical version of this file is maintained in the rra-c-util package, +# which can be found at . + +-bbao # put line breaks before any operator +-nbbc # don't force blank lines before comments (bad for else blocks) +-ce # cuddle braces around else +-l=79 # usually use 78, but don't want 79-long lines reformatted +-pt=2 # don't add extra whitespace around parentheses +-sbt=2 # ...or square brackets +-sfs # no space before semicolon in for (not that I use this form) diff --git a/t/docs/pod-coverage.t b/t/docs/pod-coverage.t new file mode 100755 index 0000000..a15444b --- /dev/null +++ b/t/docs/pod-coverage.t @@ -0,0 +1,47 @@ +#!/usr/bin/perl +# +# Test that all methods are documented in POD. +# +# The canonical version of this file is maintained in the rra-c-util package, +# which can be found at . +# +# Written by Russ Allbery +# Copyright 2013, 2014 +# The Board of Trustees of the Leland Stanford Junior University +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +use 5.006; +use strict; +use warnings; + +use lib 't/lib'; + +use Test::More; +use Test::RRA qw(skip_unless_automated use_prereq); +use Test::RRA::Config qw(@POD_COVERAGE_EXCLUDE); + +# Skip for normal user installs since this doesn't affect functionality. +skip_unless_automated('POD coverage tests'); + +# Load prerequisite modules. +use_prereq('Test::Pod::Coverage'); + +# Test everything found in the distribution. +all_pod_coverage_ok({ also_private => [@POD_COVERAGE_EXCLUDE] }); diff --git a/t/docs/pod-spelling.t b/t/docs/pod-spelling.t new file mode 100755 index 0000000..dc11b9c --- /dev/null +++ b/t/docs/pod-spelling.t @@ -0,0 +1,66 @@ +#!/usr/bin/perl +# +# Check for spelling errors in POD documentation. +# +# The canonical version of this file is maintained in the rra-c-util package, +# which can be found at . +# +# Written by Russ Allbery +# Copyright 2013, 2014 +# The Board of Trustees of the Leland Stanford Junior University +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +use 5.006; +use strict; +use warnings; + +use lib 't/lib'; + +use Test::More; +use Test::RRA qw(skip_unless_author use_prereq); + +# Only run this test for the module author since the required stopwords are +# too sensitive to the exact spell-checking program and dictionary. +skip_unless_author('Spelling tests'); + +# Load prerequisite modules. +use_prereq('Test::Spelling'); + +# Check all POD in the Perl distribution. Add the examples directory if it +# exists. Also add any files in usr/bin or usr/sbin, which are widely used in +# Stanford-internal packages. +my @files = all_pod_files(); +if (-d 'examples') { + push(@files, all_pod_files('examples')); +} +for my $dir (qw(usr/bin usr/sbin)) { + if (-d $dir) { + push(@files, glob("$dir/*")); + } +} + +# We now have a list of all files to check, so output a plan and run the +# tests. We can't use all_pod_files_spelling_ok because it refuses to check +# non-Perl files and Stanford-internal packages have a lot of shell scripts +# with POD documentation. +plan tests => scalar(@files); +for my $file (@files) { + pod_file_spelling_ok($file); +} diff --git a/t/docs/pod.t b/t/docs/pod.t new file mode 100755 index 0000000..2ef7bf0 --- /dev/null +++ b/t/docs/pod.t @@ -0,0 +1,65 @@ +#!/usr/bin/perl +# +# Check all POD documents for POD formatting errors. +# +# The canonical version of this file is maintained in the rra-c-util package, +# which can be found at . +# +# Written by Russ Allbery +# Copyright 2012, 2013, 2014 +# The Board of Trustees of the Leland Stanford Junior University +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +use 5.006; +use strict; +use warnings; + +use lib 't/lib'; + +use Test::More; +use Test::RRA qw(skip_unless_automated use_prereq); + +# Skip this test for normal user installs, although pod2man may still fail. +skip_unless_automated('POD syntax tests'); + +# Load prerequisite modules. +use_prereq('Test::Pod'); + +# Check all POD in the Perl distribution. Add the examples directory if it +# exists. Also add any files in usr/bin or usr/sbin, which are widely used in +# Stanford-internal packages. +my @files = all_pod_files(); +if (-d 'examples') { + push(@files, all_pod_files('examples')); +} +for my $dir (qw(usr/bin usr/sbin)) { + if (-d $dir) { + push(@files, glob("$dir/*")); + } +} + +# We now have a list of all files to check, so output a plan and run the +# tests. We can't use all_pod_files_ok because it refuses to check non-Perl +# files and Stanford-internal packages have a lot of shell scripts with POD +# documentation. +plan tests => scalar(@files); +for my $file (@files) { + pod_file_ok($file); +} diff --git a/t/docs/synopsis.t b/t/docs/synopsis.t new file mode 100755 index 0000000..384e407 --- /dev/null +++ b/t/docs/synopsis.t @@ -0,0 +1,74 @@ +#!/usr/bin/perl +# +# Check the SYNOPSIS section of the documentation for syntax errors. +# +# The canonical version of this file is maintained in the rra-c-util package, +# which can be found at . +# +# Written by Russ Allbery +# Copyright 2013, 2014 +# The Board of Trustees of the Leland Stanford Junior University +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +use 5.006; +use strict; +use warnings; + +use lib 't/lib'; + +use File::Spec; +use Test::More; +use Test::RRA qw(skip_unless_automated use_prereq); + +# Skip for normal user installs since this doesn't affect functionality. +skip_unless_automated('Synopsis syntax tests'); + +# Load prerequisite modules. +use_prereq('Perl::Critic::Utils'); +use_prereq('Test::Synopsis'); + +# Helper function that checks to see if a given path starts with blib/script. +# This is written a bit weirdly so that it's portable to Windows and VMS. +# +# $path - Path to a file +# +# Returns: True if the file doesn't start with blib/script, false otherwise. +sub in_blib_script { + my ($path) = @_; + my ($volume, $dir, $file) = File::Spec->splitpath($path); + my @dir = File::Spec->splitdir($dir); + return (scalar(@dir) < 2 || $dir[0] ne 'blib' || $dir[1] ne 'script'); +} + +# The default Test::Synopsis all_synopsis_ok() function requires that the +# module be in a lib directory. Use Perl::Critic::Utils to find the modules +# in blib, or lib if it doesn't exist. However, strip out anything in +# blib/script, since scripts use a different SYNOPSIS syntax. +my @files = Perl::Critic::Utils::all_perl_files('blib'); +@files = grep { in_blib_script($_) } @files; +if (!@files) { + @files = Perl::Critic::Utils::all_perl_files('lib'); +} +plan tests => scalar @files; + +# Run the actual tests. +for my $file (@files) { + synopsis_ok($file); +} diff --git a/t/docs/urls.t b/t/docs/urls.t new file mode 100755 index 0000000..db1f7cb --- /dev/null +++ b/t/docs/urls.t @@ -0,0 +1,93 @@ +#!/usr/bin/perl +# +# Check URLs in source files. +# +# Examine all source files in a distribution for bad URL patterns and report +# on files that fail this check. Currently, this just checks that all the +# links to www.eyrie.org are https. +# +# The canonical version of this file is maintained in the rra-c-util package, +# which can be found at . +# +# Copyright 2016 Russ Allbery +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +use 5.006; +use strict; +use warnings; + +use lib 't/lib'; + +use File::Find qw(find); +use Test::More; +use Test::RRA qw(skip_unless_automated); + +# Bad patterns to search for. +my @BAD_REGEXES = (qr{ http:// \S+ [.]eyrie[.]org }xms); +my @BAD_STRINGS = qw(rra@stanford.edu); + +# File or directory names to always skip. +my %SKIP = map { $_ => 1 } qw(.git _build blib cover_db); + +# Only run this test during automated testing, since failure doesn't indicate +# any user-noticable flaw in the package itself. +skip_unless_automated('Documentation URL tests'); + +# Scan files for bad URL patterns. This is meant to be run as the wanted +# function from File::Find. +sub check_file { + my $filename = $_; + + # Ignore this check itself (or the non-Perl version of it). Ignore any + # directories or binary files. Ignore and prune any skipped files. + if ($SKIP{$filename}) { + $File::Find::prune = 1; + return; + } + return if -d $filename; + return if !-T $filename; + return if ($filename eq 'urls.t' || $filename eq 'urls-t'); + + # Scan the file. + open(my $fh, '<', $filename) or BAIL_OUT("Cannot open $File::Find::name"); + while (defined(my $line = <$fh>)) { + for my $regex (@BAD_REGEXES) { + if ($line =~ $regex) { + ok(0, "$File::Find::name contains $regex"); + close($fh) or BAIL_OUT("Cannot close $File::Find::name"); + return; + } + } + for my $string (@BAD_STRINGS) { + if (index($line, $string) != -1) { + ok(0, "$File::Find::name contains $string"); + close($fh) or BAIL_OUT("Cannot close $File::Find::name"); + return; + } + } + } + close($fh) or BAIL_OUT("Cannot close $File::Find::name"); + ok(1, $File::Find::name); + return; +} + +# Use File::Find to scan all files from the top of the directory. +find(\&check_file, q{.}); +done_testing(); diff --git a/t/lib/Test/RRA.pm b/t/lib/Test/RRA.pm new file mode 100644 index 0000000..bcd6532 --- /dev/null +++ b/t/lib/Test/RRA.pm @@ -0,0 +1,279 @@ +# Helper functions for test programs written in Perl. +# +# This module provides a collection of helper functions used by test programs +# written in Perl. This is a general collection of functions that can be used +# by both C packages with Automake and by stand-alone Perl modules. See +# Test::RRA::Automake for additional functions specifically for C Automake +# distributions. + +package Test::RRA; + +use 5.006; +use strict; +use warnings; + +use Exporter; +use File::Temp; +use Test::More; + +# For Perl 5.006 compatibility. +## no critic (ClassHierarchies::ProhibitExplicitISA) + +# Declare variables that should be set in BEGIN for robustness. +our (@EXPORT_OK, @ISA, $VERSION); + +# Set $VERSION and everything export-related in a BEGIN block for robustness +# against circular module loading (not that we load any modules, but +# consistency is good). +BEGIN { + @ISA = qw(Exporter); + @EXPORT_OK = qw( + is_file_contents skip_unless_author skip_unless_automated use_prereq + ); + + # This version should match the corresponding rra-c-util release, but with + # two digits for the minor version, including a leading zero if necessary, + # so that it will sort properly. + $VERSION = '6.02'; +} + +# Compare a string to the contents of a file, similar to the standard is() +# function, but to show the line-based unified diff between them if they +# differ. +# +# $got - The output that we received +# $expected - The path to the file containing the expected output +# $message - The message to use when reporting the test results +# +# Returns: undef +# Throws: Exception on failure to read or write files or run diff +sub is_file_contents { + my ($got, $expected, $message) = @_; + + # If they're equal, this is simple. + open(my $fh, '<', $expected) or BAIL_OUT("Cannot open $expected: $!\n"); + my $data = do { local $/ = undef; <$fh> }; + close($fh) or BAIL_OUT("Cannot close $expected: $!\n"); + if ($got eq $data) { + is($got, $data, $message); + return; + } + + # Otherwise, we show a diff, but only if we have IPC::System::Simple. + eval { require IPC::System::Simple }; + if ($@) { + ok(0, $message); + return; + } + + # They're not equal. Write out what we got so that we can run diff. + my $tmp = File::Temp->new(); + my $tmpname = $tmp->filename; + print {$tmp} $got or BAIL_OUT("Cannot write to $tmpname: $!\n"); + my @command = ('diff', '-u', $expected, $tmpname); + my $diff = IPC::System::Simple::capturex([0 .. 1], @command); + diag($diff); + + # Remove the temporary file and report failure. + ok(0, $message); + return; +} + +# Skip this test unless author tests are requested. Takes a short description +# of what tests this script would perform, which is used in the skip message. +# Calls plan skip_all, which will terminate the program. +# +# $description - Short description of the tests +# +# Returns: undef +sub skip_unless_author { + my ($description) = @_; + if (!$ENV{AUTHOR_TESTING}) { + plan skip_all => "$description only run for author"; + } + return; +} + +# Skip this test unless doing automated testing or release testing. This is +# used for tests that should be run by CPAN smoke testing or during releases, +# but not for manual installs by end users. Takes a short description of what +# tests this script would perform, which is used in the skip message. Calls +# plan skip_all, which will terminate the program. +# +# $description - Short description of the tests +# +# Returns: undef +sub skip_unless_automated { + my ($description) = @_; + for my $env (qw(AUTOMATED_TESTING RELEASE_TESTING AUTHOR_TESTING)) { + return if $ENV{$env}; + } + plan skip_all => "$description normally skipped"; + return; +} + +# Attempt to load a module and skip the test if the module could not be +# loaded. If the module could be loaded, call its import function manually. +# If the module could not be loaded, calls plan skip_all, which will terminate +# the program. +# +# The special logic here is based on Test::More and is required to get the +# imports to happen in the caller's namespace. +# +# $module - Name of the module to load +# @imports - Any arguments to import, possibly including a version +# +# Returns: undef +sub use_prereq { + my ($module, @imports) = @_; + + # If the first import looks like a version, pass it as a bare string. + my $version = q{}; + if (@imports >= 1 && $imports[0] =~ m{ \A \d+ (?: [.][\d_]+ )* \z }xms) { + $version = shift(@imports); + } + + # Get caller information to put imports in the correct package. + my ($package) = caller; + + # Do the import with eval, and try to isolate it from the surrounding + # context as much as possible. Based heavily on Test::More::_eval. + ## no critic (BuiltinFunctions::ProhibitStringyEval) + ## no critic (ValuesAndExpressions::ProhibitImplicitNewlines) + my ($result, $error, $sigdie); + { + local $@ = undef; + local $! = undef; + local $SIG{__DIE__} = undef; + $result = eval qq{ + package $package; + use $module $version \@imports; + 1; + }; + $error = $@; + $sigdie = $SIG{__DIE__} || undef; + } + + # If the use failed for any reason, skip the test. + if (!$result || $error) { + my $name = length($version) > 0 ? "$module $version" : $module; + plan skip_all => "$name required for test"; + } + + # If the module set $SIG{__DIE__}, we cleared that via local. Restore it. + ## no critic (Variables::RequireLocalizedPunctuationVars) + if (defined($sigdie)) { + $SIG{__DIE__} = $sigdie; + } + return; +} + +1; +__END__ + +=for stopwords +Allbery Allbery's DESC bareword sublicense MERCHANTABILITY NONINFRINGEMENT +rra-c-util CPAN + +=head1 NAME + +Test::RRA - Support functions for Perl tests + +=head1 SYNOPSIS + + use Test::RRA + qw(skip_unless_author skip_unless_automated use_prereq); + + # Skip this test unless author tests are requested. + skip_unless_author('Coding style tests'); + + # Skip this test unless doing automated or release testing. + skip_unless_automated('POD syntax tests'); + + # Load modules, skipping the test if they're not available. + use_prereq('Perl6::Slurp', 'slurp'); + use_prereq('Test::Script::Run', '0.04'); + +=head1 DESCRIPTION + +This module collects utility functions that are useful for Perl test scripts. +It assumes Russ Allbery's Perl module layout and test conventions and will +only be useful for other people if they use the same conventions. + +=head1 FUNCTIONS + +None of these functions are imported by default. The ones used by a script +should be explicitly imported. + +=over 4 + +=item skip_unless_author(DESC) + +Checks whether AUTHOR_TESTING is set in the environment and skips the whole +test (by calling C from Test::More) if it is not. DESC is a +description of the tests being skipped. A space and C +will be appended to it and used as the skip reason. + +=item skip_unless_automated(DESC) + +Checks whether AUTHOR_TESTING, AUTOMATED_TESTING, or RELEASE_TESTING are set +in the environment and skips the whole test (by calling C from +Test::More) if they are not. This should be used by tests that should not run +during end-user installs of the module, but which should run as part of CPAN +smoke testing and release testing. + +DESC is a description of the tests being skipped. A space and C will be appended to it and used as the skip reason. + +=item use_prereq(MODULE[, VERSION][, IMPORT ...]) + +Attempts to load MODULE with the given VERSION and import arguments. If this +fails for any reason, the test will be skipped (by calling C +from Test::More) with a skip reason saying that MODULE is required for the +test. + +VERSION will be passed to C as a version bareword if it looks like a +version number. The remaining IMPORT arguments will be passed as the value of +an array. + +=back + +=head1 AUTHOR + +Russ Allbery + +=head1 COPYRIGHT AND LICENSE + +Copyright 2013, 2014 The Board of Trustees of the Leland Stanford Junior +University + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +=head1 SEE ALSO + +Test::More(3), Test::RRA::Automake(3), Test::RRA::Config(3) + +This module is maintained in the rra-c-util package. The current version is +available from L. + +The functions to control when tests are run use environment variables defined +by the L. + +=cut diff --git a/t/lib/Test/RRA/Config.pm b/t/lib/Test/RRA/Config.pm new file mode 100644 index 0000000..bdb31e6 --- /dev/null +++ b/t/lib/Test/RRA/Config.pm @@ -0,0 +1,222 @@ +# Configuration for Perl test cases. +# +# In order to reuse the same Perl test cases in multiple packages, I use a +# configuration file to store some package-specific data. This module loads +# that configuration and provides the namespace for the configuration +# settings. + +package Test::RRA::Config; + +use 5.006; +use strict; +use warnings; + +# For Perl 5.006 compatibility. +## no critic (ClassHierarchies::ProhibitExplicitISA) + +use Exporter; +use Test::More; + +# Declare variables that should be set in BEGIN for robustness. +our (@EXPORT_OK, @ISA, $VERSION); + +# Set $VERSION and everything export-related in a BEGIN block for robustness +# against circular module loading (not that we load any modules, but +# consistency is good). +BEGIN { + @ISA = qw(Exporter); + @EXPORT_OK = qw( + $COVERAGE_LEVEL @COVERAGE_SKIP_TESTS @CRITIC_IGNORE $LIBRARY_PATH + $MINIMUM_VERSION %MINIMUM_VERSION @MODULE_VERSION_IGNORE + @POD_COVERAGE_EXCLUDE @STRICT_IGNORE @STRICT_PREREQ + ); + + # This version should match the corresponding rra-c-util release, but with + # two digits for the minor version, including a leading zero if necessary, + # so that it will sort properly. + $VERSION = '6.02'; +} + +# If C_TAP_BUILD or C_TAP_SOURCE are set in the environment, look for +# data/perl.conf under those paths for a C Automake package. Otherwise, look +# in t/data/perl.conf for a standalone Perl module or tests/data/perl.conf for +# Perl tests embedded in a larger distribution. Don't use Test::RRA::Automake +# since it may not exist. +our $PATH; +for my $base ($ENV{C_TAP_BUILD}, $ENV{C_TAP_SOURCE}, './t', './tests') { + next if !defined($base); + my $path = "$base/data/perl.conf"; + if (-r $path) { + $PATH = $path; + last; + } +} +if (!defined($PATH)) { + BAIL_OUT('cannot find data/perl.conf'); +} + +# Pre-declare all of our variables and set any defaults. +our $COVERAGE_LEVEL = 100; +our @COVERAGE_SKIP_TESTS; +our @CRITIC_IGNORE; +our $LIBRARY_PATH; +our $MINIMUM_VERSION = '5.008'; +our %MINIMUM_VERSION; +our @MODULE_VERSION_IGNORE; +our @POD_COVERAGE_EXCLUDE; +our @STRICT_IGNORE; +our @STRICT_PREREQ; + +# Load the configuration. +if (!do($PATH)) { + my $error = $@ || $! || 'loading file did not return true'; + BAIL_OUT("cannot load $PATH: $error"); +} + +1; +__END__ + +=for stopwords +Allbery rra-c-util Automake perlcritic .libs namespace subdirectory sublicense +MERCHANTABILITY NONINFRINGEMENT regexes + +=head1 NAME + +Test::RRA::Config - Perl test configuration + +=head1 SYNOPSIS + + use Test::RRA::Config qw($MINIMUM_VERSION); + print "Required Perl version is $MINIMUM_VERSION\n"; + +=head1 DESCRIPTION + +Test::RRA::Config encapsulates per-package configuration for generic Perl test +programs that are shared between multiple packages using the rra-c-util +infrastructure. It handles locating and loading the test configuration file +for both C Automake packages and stand-alone Perl modules. + +Test::RRA::Config looks for a file named F relative to the +root of the test directory. That root is taken from the environment variables +C_TAP_BUILD or C_TAP_SOURCE (in that order) if set, which will be the case for +C Automake packages using C TAP Harness. If neither is set, it expects the +root of the test directory to be a directory named F relative to the +current directory, which will be the case for stand-alone Perl modules. + +The following variables are supported: + +=over 4 + +=item $COVERAGE_LEVEL + +The coverage level achieved by the test suite for Perl test coverage testing +using Test::Strict, as a percentage. The test will fail if test coverage less +than this percentage is achieved. If not given, defaults to 100. + +=item @COVERAGE_SKIP_TESTS + +Directories under F whose tests should be skipped when doing coverage +testing. This can be tests that won't contribute to coverage or tests that +don't run properly under Devel::Cover for some reason (such as ones that use +taint checking). F and F