diff --git a/.gitignore b/.gitignore index 6ad59b4..f3d5f57 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,53 @@ -.*.swp +# Specific /tags +/fatlib +/stuff +# Dist +/Text-PerlPP* + +# Editor +*.bak +*~ +~* +*.swp + +# from GitHub's perl .gitignore: +!Build/ +.last_cover_stats +/META.yml +/META.json +/MYMETA.* +*.o +*.pm.tdy +*.bs + +# Devel::Cover +cover_db/ + +# Devel::NYTProf +nytprof.out + +# Dizt::Zilla +/.build/ + +# Module::Build +_build/ +Build +Build.bat + +# Module::Install +inc/ + +# ExtUtils::MakeMaker +/blib/ +/_eumm/ +/*.gz +/Makefile +/Makefile.old +/MANIFEST.bak +/pm_to_blib +/*.zip + +# Capture::Tiny +DEBUG* diff --git a/Changes b/Changes new file mode 100644 index 0000000..9595548 --- /dev/null +++ b/Changes @@ -0,0 +1,5 @@ +Revision history for Text-PerlPP + +0.3.1 2018/05/11 + First CPAN version, released on an unsuspecting world. + diff --git a/LICENSE.txt b/LICENSE similarity index 94% rename from LICENSE.txt rename to LICENSE index 05e39d5..a5845ea 100644 --- a/LICENSE.txt +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) Copyright © 2013 Andrey Shubin -Portions copyright © 2016 Chris White +Portions copyright © 2016-2018 Chris White Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..05c23e5 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,23 @@ +bin/perlpp The command-line invoker +Changes +lib/Text/PerlPP.pm The main code and perldoc +LICENSE +Makefile.PL +MANIFEST This list of files +MANIFEST.SKIP +pack.PL Script to make the packed version +README +README.md The tutorial +t/00-load.t +t/01-basic.t +t/01-readme.t +t/02-cmdline.t +t/03-idempotency.t +t/04-include.t +t/05-external-command.t +t/06-macro.t +t/07-invalid.t +t/a.txt +t/b.txt +t/c.txt +t/included.txt diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP new file mode 100644 index 0000000..5ea13a7 --- /dev/null +++ b/MANIFEST.SKIP @@ -0,0 +1,77 @@ +# MANIFEST.SKIP for Text::PerlPP + +#!start included /home/ChrisW/perl5/perlbrew/perls/perl-5.26.1/lib/5.26.1/ExtUtils/MANIFEST.SKIP +# Avoid version control files. +\bRCS\b +\bCVS\b +\bSCCS\b +,v$ +\B\.svn\b +\B\.git\b +\B\.gitignore\b +\b_darcs\b +\B\.cvsignore$ + +# Avoid VMS specific MakeMaker generated files +\bDescrip.MMS$ +\bDESCRIP.MMS$ +\bdescrip.mms$ + +# Avoid Makemaker generated and utility files. +\bMANIFEST\.bak +\bMakefile$ +\bblib/ +\bMakeMaker-\d +\bpm_to_blib\.ts$ +\bpm_to_blib$ +\bblibdirs\.ts$ # 6.18 through 6.25 generated this +\b_eumm/ # 7.05_05 and above + +# Avoid Module::Build generated and utility files. +\bBuild$ +\b_build/ +\bBuild.bat$ +\bBuild.COM$ +\bBUILD.COM$ +\bbuild.com$ + +# and Module::Build::Tiny generated files +\b_build_params$ + +# Avoid temp and backup files. +~$ +\.old$ +\#$ +\b\.# +\.bak$ +\.tmp$ +\.# +\.rej$ +\..*\.sw.?$ + +# 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 prove files +\B\.prove$ + +# Avoid MYMETA files +^MYMETA\. +#!end included /home/ChrisW/perl5/perlbrew/perls/perl-5.26.1/lib/5.26.1/ExtUtils +/MANIFEST.SKIP + +# Skip directories +^stuff\b +^fatlib\b +^xt\b + +# Skip some specific files +^Makefile-premodule +^tags diff --git a/Makefile b/Makefile deleted file mode 100644 index 07e3d24..0000000 --- a/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# Hacky makefile for perlpp -# Chris White, 2017. -all: test - -test: - perl -e 'use Test::Harness "runtests"; runtests @ARGV;' -- t/*.t 2>/dev/null - - -#Note: if you don't have Test::Harness, you can use: -# for f in t/*.t ; do echo "$$f" ; perl "$$f" ; done 2>/dev/null - diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..d7caa5f --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,44 @@ +use 5.010; +use strict; +use warnings; +use ExtUtils::MakeMaker; + +sub MY::postamble { + return < 'Text::PerlPP', + AUTHOR => q{Christopher White }, + VERSION_FROM => 'lib/Text/PerlPP.pm', + ABSTRACT_FROM => 'lib/Text/PerlPP.pm', + LICENSE => 'mit', + + EXE_FILES => [ 'bin/perlpp' ], + MIN_PERL_VERSION => '5.010', + CONFIGURE_REQUIRES => { + 'ExtUtils::MakeMaker' => '0', + }, + BUILD_REQUIRES => { + 'Test::More' => '0', + 'App::FatPacker' => '0', + }, + PREREQ_PM => { + 'Pod::Usage' => '0', + 'Getopt::Long' => '2.50', # Per issue #17 + }, + dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, + clean => { FILES => 'Text-PerlPP-* fatlib' }, +); +# vi: set ts=4 sts=4 sw=4 et ai: # diff --git a/README b/README new file mode 100644 index 0000000..174086c --- /dev/null +++ b/README @@ -0,0 +1,77 @@ +Text-PerlPP - a Perl preprocessor + +Translates text files with embedded Perl code to plain text files. +See README.md for details. A simple example: + + + +will output + + Hello, World! + 42 + + is a Perl code chunk, runs an external command, and + prints a Perl expression. There are more commands, listed in +README.md. + +REQUIRES + +Perl 5.10+ and Getopt::Long 2.50. There is a fatpacked version that +already includes Getopt::Long in the GitHub releases archive: +https://github.com/interpreters/perlpp/releases + +INSTALLATION + +Easy installation, using App::cpanminus: + + cpanm Text::PerlPP + +Easy installation, using the release from GitHub: + + - Copy the release file to a directory in your PATH + +Slightly less easy installation, using ExtUtils::MakeMaker: + + - Unpack the tarball + - In the resulting directory, run the following commands: + + perl Makefile.PL + make + make test + make install + +Yet another alternative way of installing + + - Copy lib/Text/PerlPP.pm to a directory in your @INC + - Copy bin/perlpp to a directory in your PATH. + +SUPPORT AND DOCUMENTATION + +After installing, you can find documentation for this module with the +perldoc command. + + perldoc Text::PerlPP + +You can also look for information at: + + GitHub (report bugs here) + https://github.com/interpreters/perlpp + + AnnoCPAN, Annotated CPAN documentation + http://annocpan.org/dist/Text-PerlPP + + CPAN Ratings + http://cpanratings.perl.org/d/Text-PerlPP + + Search CPAN + http://search.cpan.org/dist/Text-PerlPP/ + +LICENSE AND COPYRIGHT + +Copyright 2013-2018 Andrey Shubin and Christopher White. + +This program is distributed under the MIT (X11) License: +http://www.opensource.org/licenses/mit-license.php + +See LICENSE for full details. + diff --git a/bin/perlpp b/bin/perlpp new file mode 100755 index 0000000..16e9e04 --- /dev/null +++ b/bin/perlpp @@ -0,0 +1,6 @@ +#!perl -w +# To run this manually from the source tree, do +# perl -Ilib bin/perlpp +use strict; use warnings; use Text::PerlPP; +exit(Text::PerlPP::Main(\@ARGV)); +# vi: set ft=perl: # diff --git a/perlpp.pl b/lib/Text/PerlPP.pm old mode 100755 new mode 100644 similarity index 84% rename from perlpp.pl rename to lib/Text/PerlPP.pm index 8c46add..26b522f --- a/perlpp.pl +++ b/lib/Text/PerlPP.pm @@ -1,17 +1,15 @@ -#!/usr/bin/env perl -# PerlPP: Perl preprocessor. See documentation after __END__. +#!perl +# PerlPP: Perl preprocessor. See the perldoc for usage. -# Some info about scoping in Perl: -# http://darkness.codefu.org/wordpress/2003/03/perl-scoping/ +package Text::PerlPP; -package PerlPP; -our $VERSION = '0.3.0'; +our $VERSION = '0.3.1'; -use v5.10; # provides // - http://perldoc.perl.org/perl5100delta.html +use 5.010; # provides // - http://perldoc.perl.org/perl5100delta.html use strict; use warnings; -use Getopt::Long; +use Getopt::Long 2.50 qw(GetOptionsFromArray); use Pod::Usage; # === Constants =========================================================== @@ -67,12 +65,12 @@ package PerlPP; my %Prefixes = (); # set by ExecuteCommand; used by PrepareString # -D definitions. -Dfoo creates $Defs{foo}==true and $Defs_repl_text{foo}==''. -my %Defs = (); # Command-line -D arguments +our %Defs = (); # Command-line -D arguments my $Defs_RE = false; # Regex that matches any -D name my %Defs_repl_text = (); # Replacement text for -D names # -s definitions. -my %Sets = (); # Command-line -s arguments +our %Sets = (); # Command-line -s arguments # Output-buffer stack my @OutputBuffers = (); # each entry is a two-element array @@ -146,6 +144,7 @@ sub GetModeOfOB { sub DQuoteString { # wrap $_[0] in double-quotes, escaped properly # Not currently used by PerlPP, but provided for use by scripts. + # TODO? inject into the generated script? my $s = shift; $s =~ s{\\}{\\\\}g; @@ -289,7 +288,7 @@ sub ShellOut { # Run an external command print( qq{do { my \$output = qx${cmd}; - my \$status = PerlPP::GetStatusReport(\$?, \$!); + my \$status = Text::PerlPP::GetStatusReport(\$?, \$!); if(\$status) { $error_response("perlpp: command '" . ${cmd} . "' failed: \${status}; invoked"); } else { @@ -340,7 +339,7 @@ sub OnOpening { } if ( $plainMode == OBMODE_CAPTURE ) { - print PrepareString( $plain ) . " . do { PerlPP::StartOB(); "; + print PrepareString( $plain ) . " . do { Text::PerlPP::StartOB(); "; StartOB( $plainMode ); # wrap the inset in a capturing mode } else { print "print " . PrepareString( $plain ) . ";\n"; @@ -378,7 +377,7 @@ sub OnClosing { } if ( GetModeOfOB() == OBMODE_CAPTURE ) { # if the inset is wrapped - print EndOB() . " PerlPP::EndOB(); } . "; # end of do { .... } statement + print EndOB() . " Text::PerlPP::EndOB(); } . "; # end of do { .... } statement $nextMode = OBMODE_CAPTURE; # back to capturing } } @@ -504,7 +503,7 @@ sub OutputResult { DEFS => ['D','|define:s%'], # In %D, and text substitution EVAL => ['e','|eval=s', ''], # -h and --help reserved - # INPUT_FILENAME assigned by parse_command_line_into() + # INPUT_FILENAME assigned by parse_command_line() KEEP_GOING => ['k','|keep-going',false], # --man reserved OUTPUT_FILENAME => ['o','|output=s', ""], @@ -514,11 +513,12 @@ sub OutputResult { # -? reserved ); -sub parse_command_line_into { - # Takes reference to hash to populate. Fills in that hash with the - # values from the command line, keyed by the keys in %CMDLINE_OPTS. +sub parse_command_line { + # Takes reference to arg list, and reference to hash to populate. + # Fills in that hash with the values from the command line, keyed + # by the keys in %CMDLINE_OPTS. - my $hrOptsOut = shift; + my ($lrArgs, $hrOptsOut) = @_; # Easier syntax for checking whether optional args were provided. # Syntax thanks to http://www.perlmonks.org/?node_id=696592 @@ -534,16 +534,20 @@ sub parse_command_line_into { ); # Get options - GetOptions($hrOptsOut, # destination hash - 'usage|?', 'h|help', 'man', # options we handle here + GetOptionsFromArray($lrArgs, $hrOptsOut, # destination hash + 'usage|?', 'h|help', 'man', # options we handle here map { $_->[0] . $_->[1] } values %CMDLINE_OPTS, # options strs ) - or pod2usage(-verbose => 0, -exitval => EXIT_PARAM_ERR); # unknown opt + or pod2usage(-verbose => 0, -exitval => EXIT_PARAM_ERR, -input => __FILE__); + # unknown opt # Help, if requested - pod2usage(-verbose => 0, -exitval => EXIT_PROC_ERR) if have('usage'); - pod2usage(-verbose => 1, -exitval => EXIT_PROC_ERR) if have('h'); - pod2usage(-verbose => 2, -exitval => EXIT_PROC_ERR) if have('man'); + pod2usage(-verbose => 0, -exitval => EXIT_PROC_ERR, -input => __FILE__) + if have('usage'); + pod2usage(-verbose => 1, -exitval => EXIT_PROC_ERR, -input => __FILE__) + if have('h'); + pod2usage(-verbose => 2, -exitval => EXIT_PROC_ERR, -input => __FILE__) + if have('man'); # Map the option names from GetOptions back to the internal names we use, # e.g., $hrOptsOut->{EVAL} from $hrOptsOut->{e}. @@ -560,11 +564,12 @@ sub parse_command_line_into { # Process other arguments. TODO? support multiple input filenames? $hrOptsOut->{INPUT_FILENAME} = $ARGV[0] // ""; -} #parse_command_line_into() +} #parse_command_line() # === Main ================================================================ sub Main { - parse_command_line_into \%Opts; + my $lrArgv = shift // []; + parse_command_line $lrArgv, \%Opts; if($Opts{PRINT_VERSION}) { print "PerlPP version $VERSION\n"; @@ -676,8 +681,7 @@ sub Main { return EXIT_OK; } #Main() -exit Main( @ARGV ); - +1; __END__ # ### Documentation ####################################################### @@ -687,11 +691,11 @@ sub Main { =head1 NAME -PerlPP: Perl preprocessor +Text::PerlPP - Perl preprocessor: process Perl code within any text file =head1 USAGE -perl perlpp.pl [options] [--] [filename] + perlpp [options] [--] [filename] If no [filename] is given, input will be read from stdin. @@ -715,14 +719,14 @@ =head1 OPTIONS If B cannot be evaluated, no substitution is made for B. If you omit the B<< =value >>, the value will be the constant C -(see L, below), and no text substitution +(see L<"The generated script"|/"THE GENERATED SCRIPT">, below), and no text substitution will be performed. -This also saves the value, or C, in the generation-time -hash C<< %Defs >>. This can be used, e.g., to select include filenames -depending on B<-D> arguments. +This also saves the value, or C, in the generation-time hash +C<< %Text::PerlPP::Defs >>. This can be used, e.g., to select include +filenames depending on B<-D> arguments. -See L, below, for more information. +See L<"Definitions"|/"DEFINITIONS">, below, for more information. =item -e, --eval B @@ -752,7 +756,7 @@ =head1 OPTIONS =item * -Saves into C<< %Sets >> at generation time; and +Saves into C<< %Text::PerlPP::Sets >> at generation time; and =item * @@ -772,12 +776,12 @@ =head1 OPTIONS Shows just the usage summary -=back - =item --version Show the version number of perlpp +=back + =head1 DEFINITIONS B<-D> and B<-s> items may be evaluated in any order --- @@ -822,14 +826,74 @@ =head1 THE GENERATED SCRIPT (the defined-or operator) and the builtin C. The preamble also keeps you safe from some basic issues. -=head1 COPYRIGHT +=head1 BUGS + +Please report any bugs or feature requests through GitHub, via +L. + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command. + + perldoc Text::PerlPP + +You can also look for information at: + +=over 4 + +=item * AnnoCPAN: Annotated CPAN documentation + +L + +=item * CPAN Ratings + +L -Code at L. -Distributed under MIT license. -By Andrey Shubin (d-ash at Github; L) and +=item * Search CPAN + +L + +=back + +=head1 ALTERNATIVES + +Turns out there are about 2^googol modules that do similar things. We think +this one works pretty nicely, but here are some others in case you disagree. +In no particular order: L, L, L, +L, L, L, L, L, L. + +=head1 AUTHORS + +Andrey Shubin (d-ash at Github; L) and Chris White (cxw42 at Github; L). -=cut +=head1 LICENSE AND COPYRIGHT + +Copyright 2013-2018 Andrey Shubin and Christopher White. + +This program is distributed under the MIT (X11) License: +L + +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: -# vi: set ts=4 sts=0 sw=4 noet ai fo-=o: # +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. + +=cut diff --git a/pack.PL b/pack.PL new file mode 100755 index 0000000..ae1884c --- /dev/null +++ b/pack.PL @@ -0,0 +1,87 @@ +#!perl +# pack.PL: fatpack perlpp +# Copyright (c) 2018 Chris White. Licensed MIT. + +use strict; +use warnings; + +############################# +# Custom packer that will only pack Text::PerlPP and Getopt::Long. +# This is used so that the packed version doesn't have OS-specific +# dependencies. + +package MyPacker; +use strict; +use warnings; + +use parent 'App::FatPacker'; + +sub collect_files { + my ($self, $dir, $files) = @_; + + my %innerfiles; + $self->SUPER::collect_files($dir, \%innerfiles); + my @filenames = grep { m{Text/PerlPP} || m{Getopt/Long} } keys %innerfiles; + @{$files}{@filenames} = @innerfiles{@filenames}; +} + +############################# +# Main routine + +package main; + +my $packer = MyPacker->new; +my $packed; + +do { + open my $savedstdout, '>&', STDOUT or die $!; # save stdout + close STDOUT; + + open STDOUT, '>>', \$packed; # capture packed text on stdout + $packer->script_command_pack(['bin/perlpp']); + close STDOUT; + + open STDOUT, '>&', $savedstdout; # restore stdout +}; + +# Clean up, and move the Text::PerlPP pod where pod2usage can find it + +my @lines; # For the source +my @podlines; # For the POD we're going to move + +my ($in_getopt, $in_text, $in_doc); +open my $iter, '<', \$packed; + +while(<$iter>) { + chomp; + s/\s+$//; + + $in_getopt = m{fatpacked\S+Getopt/Long} .. m{^GETOPT_LONG}; + $in_text = m{fatpacked\S+Text/PerlPP} .. m{^TEXT_PERLPP}; + $in_doc = /^ =head1 NAME/ .. /^ =cut/; + # have to test indentation level because the POD for Getopt::Long + # includes a quoted POD sample + + #print STDERR "$in_getopt\t$in_text\t$in_doc\t$_\n"; + + next if $in_getopt && $in_doc; # no POD for Getopt::Long + if($in_text && $in_doc && ($in_text !~ /E0$/)) { + s/^ //; + push @podlines, $_; + } else { + push @lines, $_ if $_; + } +} +close $iter; +undef $packed; + +# Output in the appropriate order +open my $fh, '>', 'blib/perlpp'; +print $fh "$_\n" for @lines; +print $fh "__END__\n=pod\n\n"; +print $fh "$_\n" for @podlines; +close $fh; + +print STDERR "Done packing\n"; + +# vi: set ts=4 sts=4 sw=4 et ai: # diff --git a/t/00-load.t b/t/00-load.t new file mode 100644 index 0000000..87ce289 --- /dev/null +++ b/t/00-load.t @@ -0,0 +1,18 @@ +#!perl +use 5.010; +use strict; +use warnings; +use Test::More; + +BEGIN { + if($ENV{PERLPP_NOUSE} || 0) { + plan skip_all => 'Loading not tested in this configuration (PERLPP_NOUSE)'; + } else { + plan tests => 1; + use_ok( 'Text::PerlPP' ) || print "Bail out!\n"; + diag("Included from $INC{'Text/PerlPP.pm'}"); + } +} + +done_testing(); +# vi: set ts=4 sts=4 sw=4 et ai: # diff --git a/t/basic.t b/t/01-basic.t similarity index 91% rename from t/basic.t rename to t/01-basic.t index dd30e59..cd2d81a 100755 --- a/t/basic.t +++ b/t/01-basic.t @@ -4,7 +4,8 @@ use strict; use warnings; use Test::More; use IPC::Run3; -use constant CMD => 'perl perlpp.pl'; +use constant CMD => ($ENV{PERLPP_CMD} || 'perl -Iblib/lib blib/script/perlpp'); +diag "perlpp command: " . CMD; my ($in, $out, $err); @@ -38,4 +39,3 @@ for my $lrTest (@testcases) { } # foreach test # vi: set ts=4 sts=0 sw=4 noet ai: # - diff --git a/t/readme.t b/t/01-readme.t similarity index 96% rename from t/readme.t rename to t/01-readme.t index 82328ce..b076a03 100755 --- a/t/readme.t +++ b/t/01-readme.t @@ -4,7 +4,7 @@ use strict; use warnings; use Test::More; use IPC::Run3; -use constant CMD => 'perl perlpp.pl'; +use constant CMD => ($ENV{PERLPP_CMD} || 'perl -Iblib/lib blib/script/perlpp'); my ($in, $out, $err); @@ -103,4 +103,3 @@ for my $lrTest (@testcases) { } # foreach test # vi: set ts=4 sts=0 sw=4 noet ai: # - diff --git a/t/cmdline.t b/t/02-cmdline.t similarity index 98% rename from t/cmdline.t rename to t/02-cmdline.t index bda63c0..2fcea47 100755 --- a/t/cmdline.t +++ b/t/02-cmdline.t @@ -4,7 +4,7 @@ use strict; use warnings; use Test::More; use IPC::Run3; -use constant CMD => 'perl perlpp.pl'; +use constant CMD => ($ENV{PERLPP_CMD} || 'perl -Iblib/lib blib/script/perlpp'); my @testcases=( # [$cmdline_options, $in (the script), $out_re (expected output), @@ -132,4 +132,3 @@ for my $lrTest (@testcases) { # TODO test -o / --output, and processing input from files rather than stdin # vi: set ts=4 sts=0 sw=4 noet ai: # - diff --git a/t/03-idempotency.t b/t/03-idempotency.t new file mode 100755 index 0000000..73d3f23 --- /dev/null +++ b/t/03-idempotency.t @@ -0,0 +1,25 @@ +#!/usr/bin/env perl -W +# Test running perlpp on itself - nothing should change. +# Always uses the Text/PerlPP.pm in lib, for simplicity. +use strict; +use warnings; +use Test::More tests => 1; +use IPC::Run3; + +use constant CMD => ($ENV{PERLPP_CMD} || 'perl -Iblib/lib blib/script/perlpp') + . ' lib/Text/PerlPP.pm'; +diag 'idempotency-test command: ' . CMD; + +my ($wholefile, $out); + +$wholefile = do { + my $fh; + open($fh, '<', 'lib/Text/PerlPP.pm') or die("Couldn't open"); + local $/; + <$fh>; +}; + +run3 CMD, undef, \$out; +is($out, $wholefile); + +# vi: set ts=4 sts=0 sw=4 noet ai: # diff --git a/t/include.t b/t/04-include.t similarity index 89% rename from t/include.t rename to t/04-include.t index ed05328..66621aa 100755 --- a/t/include.t +++ b/t/04-include.t @@ -4,10 +4,11 @@ use strict; use warnings; use Test::More; use IPC::Run3; -use constant CMD => 'perl perlpp.pl'; +use constant CMD => ($ENV{PERLPP_CMD} || 'perl -Iblib/lib blib/script/perlpp'); -(my $whereami = __FILE__) =~ s/include\.t$//; +(my $whereami = __FILE__) =~ s/04-include\.t$//; my $incfn = '"' . $whereami . 'included.txt"'; +diag "Including from $incfn\n"; my ($in, $out, $err); @@ -42,4 +43,3 @@ for my $lrTest (@testcases) { } # foreach test # vi: set ts=4 sts=0 sw=4 noet ai: # - diff --git a/t/external-command.t b/t/05-external-command.t similarity index 94% rename from t/external-command.t rename to t/05-external-command.t index ea0a643..b040a46 100755 --- a/t/external-command.t +++ b/t/05-external-command.t @@ -4,7 +4,7 @@ use strict; use warnings; use Test::More; use IPC::Run3; -use constant CMD => 'perl perlpp.pl'; +use constant CMD => ($ENV{PERLPP_CMD} || 'perl -Iblib/lib blib/script/perlpp'); (my $whereami = __FILE__) =~ s/macro\.t$//; my $incfn = '\"' . $whereami . 'included.txt\"'; @@ -54,4 +54,3 @@ for my $lrTest (@testcases) { # TODO test -o / --output, and processing input from files rather than stdin # vi: set ts=4 sts=0 sw=4 noet ai: # - diff --git a/t/macro.t b/t/06-macro.t similarity index 71% rename from t/macro.t rename to t/06-macro.t index 5be997d..1da43d5 100755 --- a/t/macro.t +++ b/t/06-macro.t @@ -4,21 +4,23 @@ use strict; use warnings; use Test::More 'no_plan'; use IPC::Run3; -use constant CMD => 'perl perlpp.pl'; +use Text::PerlPP; +use constant CMD => ($ENV{PERLPP_CMD} || 'perl -Iblib/lib blib/script/perlpp'); -(my $whereami = __FILE__) =~ s/macro\.t$//; +(my $whereami = __FILE__) =~ s/06-macro\.t$//; my $incfn = '\"' . $whereami . 'included.txt\"'; # escape the quotes for the shell +diag "Including from $incfn\n"; my @testcases=( # [$cmdline_options, $in (the script), $out_re (expected output), # $err_re (stderr output, if any)] # %Defs - ['-D foo=42', '', qr/^42/], - ['-D incfile=' . $incfn , '', + ['-D foo=42', '', qr/^42/], + ['-D incfile=' . $incfn , '', qr/^a4b/], - ['-s incfile=' . $incfn , '', + ['-s incfile=' . $incfn , '', qr/^a4b/], ['', '',qr/^128$/], @@ -48,4 +50,3 @@ for my $lrTest (@testcases) { # TODO test -o / --output, and processing input from files rather than stdin # vi: set ts=4 sts=0 sw=4 noet ai: # - diff --git a/t/invalid.t b/t/07-invalid.t similarity index 82% rename from t/invalid.t rename to t/07-invalid.t index 3398de5..31963da 100755 --- a/t/invalid.t +++ b/t/07-invalid.t @@ -4,7 +4,7 @@ use strict; use warnings; use Test::More; use IPC::Run3; -use constant CMD => 'perl perlpp.pl'; +use constant CMD => ($ENV{PERLPP_CMD} || 'perl -Iblib/lib blib/script/perlpp'); my ($out, $err); @@ -13,7 +13,7 @@ my @testcases=( ['', qr/syntax error/], ['', qr/string terminator '"'/], ['', qr/string terminator "'"/], - ['#define QUUX ()', qr/syntax error/], [''], ); #@testcases @@ -22,7 +22,7 @@ plan tests => scalar @testcases; for my $lrTest (@testcases) { my ($testin, $err_re) = @$lrTest; - $err_re = qr/./ if(!defined $err_re); + $err_re = qr/./ if(!defined $err_re); # by default, accept any stderr output as indicative of a failure # (a successful test case). @@ -32,4 +32,3 @@ for my $lrTest (@testcases) { } # foreach test # vi: set ts=4 sts=0 sw=4 noet ai: # - diff --git a/t/idempotency.t b/t/idempotency.t deleted file mode 100755 index c532592..0000000 --- a/t/idempotency.t +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env perl -W -# Test running perlpp on itself - nothing should change -use strict; -use warnings; -use Test::More tests => 1; -use IPC::Run3; -use constant CMD => 'perl perlpp.pl perlpp.pl'; - -my ($wholefile, $out); - -$wholefile = do { - my $fh; - open($fh, '<', 'perlpp.pl') or die("Couldn't open"); - local $/; - <$fh>; -}; - -run3 CMD, undef, \$out; -is($out, $wholefile); - -# vi: set ts=4 sts=0 sw=4 noet ai: # - diff --git a/xt/Module-Starter-generated-pod.t b/xt/Module-Starter-generated-pod.t new file mode 100644 index 0000000..05eb56f --- /dev/null +++ b/xt/Module-Starter-generated-pod.t @@ -0,0 +1,16 @@ +#!perl -T +use 5.010; +use strict; +use warnings; +use Test::More; + +unless ( $ENV{RELEASE_TESTING} ) { + plan( skip_all => "Author tests not required for installation" ); +} + +# Ensure a recent version of Test::Pod +my $min_tp = 1.22; +eval "use Test::Pod $min_tp"; +plan skip_all => "Test::Pod $min_tp required for testing POD" if $@; + +all_pod_files_ok(); diff --git a/xt/boilerplate.t b/xt/boilerplate.t new file mode 100644 index 0000000..0f82a5c --- /dev/null +++ b/xt/boilerplate.t @@ -0,0 +1,57 @@ +#!perl -T +use 5.010; +use strict; +use warnings; +use Test::More; + +plan tests => 3; + +sub not_in_file_ok { + my ($filename, %regex) = @_; + open( my $fh, '<', $filename ) + or die "couldn't open $filename for reading: $!"; + + my %violated; + + while (my $line = <$fh>) { + while (my ($desc, $regex) = each %regex) { + if ($line =~ $regex) { + push @{$violated{$desc}||=[]}, $.; + } + } + } + + if (%violated) { + fail("$filename contains boilerplate text"); + diag "$_ appears on lines @{$violated{$_}}" for keys %violated; + } else { + pass("$filename contains no boilerplate text"); + } +} + +sub module_boilerplate_ok { + my ($module) = @_; + not_in_file_ok($module => + 'the great new $MODULENAME' => qr/ - The great new /, + 'boilerplate description' => qr/Quick summary of what the module/, + 'stub function definition' => qr/function[12]/, + ); +} + +TODO: { + local $TODO = "Need to replace the boilerplate text"; + + not_in_file_ok(README => + "The README is used..." => qr/The README is used/, + "'version information here'" => qr/to provide version information/, + ); + + not_in_file_ok(Changes => + "placeholder date/time" => qr(Date/time) + ); + + module_boilerplate_ok('lib/Text/PerlPP.pm'); + + +} + diff --git a/xt/manifest.t b/xt/manifest.t new file mode 100644 index 0000000..f45b0bc --- /dev/null +++ b/xt/manifest.t @@ -0,0 +1,15 @@ +#!perl -T +use 5.010; +use strict; +use warnings; +use Test::More; + +unless ( $ENV{RELEASE_TESTING} ) { + plan( skip_all => "Author tests not required for installation" ); +} + +my $min_tcm = 0.9; +eval "use Test::CheckManifest $min_tcm"; +plan skip_all => "Test::CheckManifest $min_tcm required" if $@; + +ok_manifest(); diff --git a/xt/pod-coverage.t b/xt/pod-coverage.t new file mode 100644 index 0000000..5808683 --- /dev/null +++ b/xt/pod-coverage.t @@ -0,0 +1,24 @@ +#!perl -T +use 5.010; +use strict; +use warnings; +use Test::More; + +unless ( $ENV{RELEASE_TESTING} ) { + plan( skip_all => "Author tests not required for installation" ); +} + +# Ensure a recent version of Test::Pod::Coverage +my $min_tpc = 1.08; +eval "use Test::Pod::Coverage $min_tpc"; +plan skip_all => "Test::Pod::Coverage $min_tpc required for testing POD coverage" + if $@; + +# Test::Pod::Coverage doesn't require a minimum Pod::Coverage version, +# but older versions don't recognize some common documentation styles +my $min_pc = 0.18; +eval "use Pod::Coverage $min_pc"; +plan skip_all => "Pod::Coverage $min_pc required for testing POD coverage" + if $@; + +all_pod_coverage_ok(); diff --git a/xt/pod.t b/xt/pod.t new file mode 100755 index 0000000..e48779b --- /dev/null +++ b/xt/pod.t @@ -0,0 +1,14 @@ +#!/usr/bin/env perl -W +# Check that the POD is well-formed +use strict; +use warnings; +use Test::More tests => 1; +#use IPC::Run3; +use Pod::Checker; +use constant IN_FILE => 'perlpp.pl'; + +is(podchecker(IN_FILE), 0); + # 0 => does contain POD, and no errors found. + +# vi: set ts=4 sts=0 sw=4 noet ai: # +