view release on metacpan or search on metacpan
lib/App/DocKnot/Generate.pm view on Meta::CPAN
return $to_thread;
}
##############################################################################
# Helper methods
##############################################################################
# Word-wrap a paragraph of text. This is a helper function for _wrap, mostly
# so that it can be invoked recursively to wrap bulleted paragraphs.
#
# If the paragraph looks like regular text, which means indented by two or
# four spaces and consistently on each line, remove the indentation and then
# add it back in while wrapping the text.
#
# $para - A paragraph of text to wrap
# $options_ref - Options to controll the wrapping
# ignore_indent - Ignore indentation when choosing whether to wrap
#
# Returns: The wrapped paragraph
sub _wrap_paragraph {
my ($self, $para, $options_ref) = @_;
$options_ref //= {};
my ($indent) = ($para =~ m{ \A ([ ]*) \S }xms);
# If the indent is longer than five characters and the ignore indent
# option is not set, leave it alone. Allow an indent of five characters
# since it may be a continuation of a numbered list entry.
if (length($indent) > 5 && !$options_ref->{ignore_indent}) {
return $para;
}
# If this looks like thread commands or URLs, leave it alone.
if ($para =~ m{ \A \s* (?: \\ | \[\d+\] ) }xms) {
return $para;
}
# If this starts with a bullet, strip the bullet off, wrap the paragraph,
# and then add it back in.
if ($para =~ s{ \A (\s*) [*] (\s+) }{$1 $2}xms) {
my $offset = length($1);
$para = $self->_wrap_paragraph($para, { ignore_indent => 1 });
substr($para, $offset, 1, q{*});
lib/App/DocKnot/Generate.pm view on Meta::CPAN
# If this starts with a number, strip the number off, wrap the paragraph,
# and then add it back in.
if ($para =~ s{\A (\s*) (\d+[.]) (\s+)}{$1 . q{ } x length($2) . $3}xmse) {
my $offset = length($1);
my $number = $2;
$para = $self->_wrap_paragraph($para, { ignore_indent => 1 });
substr($para, $offset, length($number), $number);
return $para;
}
# If this looks like a Markdown block quote, strip trailing whitespace,
# remove the leading indentation marks, wrap the paragraph, and then put
# them back.
## no critic (RegularExpressions::ProhibitCaptureWithoutTest)
if ($para =~ m{ \A (\s*) > \s }xms) {
$para =~ s{ [ ]+ \n }{\n}xmsg;
$para =~ s{ ^ (\s*) > (\s) }{$1 $2}xmsg;
my $offset = length($1);
$para = $self->_wrap_paragraph($para, { ignore_indent => 1 });
$para =~ s{ ^ (\s{$offset}) \s }{$1>}xmsg;
return $para;
}
## use critic
# If this looks like a bunch of short lines, leave it alone.
if ($para =~ m{ \A (?: \Q$indent\E [^\n]{1,45} \n ){3,} }xms) {
return $para;
}
# If this paragraph is not consistently indented, leave it alone.
if ($para !~ m{ \A (?: \Q$indent\E \S[^\n]+ \n )+ \z }xms) {
return $para;
}
# Strip the indent from each line.
lib/App/DocKnot/Spin/RSS.pm view on Meta::CPAN
relative paths, and overrides any C<base> argument given to new(). Both FILE
and BASE may be strings or Path::Tiny objects.
=back
=head1 INPUT LANGUAGE
The input for App::DocKnot::Spin::RSS is normally a F<.rss> file in a tree
being processed by App::DocKnot::Spin. The file consists of one or more
blocks of RFC-2822-style fields with values, each separated by a blank line.
Each field and value looks like an e-mail header field, including possible
continuation lines:
Field: value
continuation of value
Any line beginning with whitespace is considered a continuation of the
previous line. If a value should contain a blank line, indicate that blank
line with a continuation line containing only a period. For example:
Field: first paragraph
lib/App/DocKnot/Spin/Text.pm view on Meta::CPAN
# Whether a paragraph is a content listing.
#
# $paragraph - Paragraph to classify
#
# Returns: True if so, false otherwise
sub _is_contents {
my ($paragraph) = @_;
return $paragraph =~ m{ \A (?: \s* [\d.]+[.\)] [ \t] \N* \n)+ \s* \z }xms;
}
# Whether a paragraph looks like a title and a description. Allows for
# multiple titles.
#
# $paragraph - Paragraph to classify
#
# Returns: True if so, false otherwise
sub _is_description {
my ($paragraph) = @_;
return if $paragraph !~ m{
\A
(\s*) \S \N* \n # title (1 is indent)
lib/App/DocKnot/Spin/Text.pm view on Meta::CPAN
return if $line =~ m{ \A [\w-]+: \s+ \N }xms;
}
# Whether a paragraph is a heading. This is all about heuristics and guesses,
# and there are a number of other things we could confuse for headings, so we
# have to be careful.
#
# If it's a single line and outdented from the baseline, it's probably a
# heading.
#
# If it's at the baseline, check to see if it looks like a heading and either
# it's in all caps or there is a rule underneath it. If we haven't seen a
# baseline, be more accepting about headers.
#
# If we're inside a contents block, be even more careful and disallow numbered
# things that look like a heading unless they're outdented.
#
# Unlike most of the classification functions, this is a regular method, since
# it needs access to the parsing state.
#
# $paragraph - Paragraph to classify
lib/App/DocKnot/Spin/Text.pm view on Meta::CPAN
# Save the header contents.
chomp($content);
$header{lc($header)} = $content;
}
$self->_buffer_line($line);
return \%header;
}
# Check to see if the header looks like that of a FAQ. If so, parse it.
#
# $header_ref - Hash into which to store the parse results.
sub _handle_faq_headers {
my ($self, $header_ref) = @_;
my $line = $self->_next_line();
# Skip over a leading "From " line from an mbox file.
if (defined($line) && $line !~ m{ \A From [ ] }xms) {
$self->_buffer_line($line);
}
lib/App/DocKnot/Spin/Text.pm view on Meta::CPAN
# posting to Usenet using postfaq, this will always be the first line of
# the file stored on disk.
my $line = $self->_next_line();
if (_is_id($line)) {
chomp($line);
$header{id} = $line;
$self->_skip_blank_lines();
$line = $self->_next_line();
}
# Check for the type of document. First, see if it looks like a FAQ with
# news/mail headers, and if so read those headers and the subheaders.
# Otherwise, skip over leading blank lines and rules.
$self->_buffer_line($line);
if (!$self->{title} && (_is_header($line) || $line =~ m{ \A From }xms)) {
$self->_handle_faq_headers(\%header);
}
$self->_skip_blank_lines_and_rules();
# See if we have a centered title at the top of the document. If so,
# we'll make that the document title unless we also saw a Subject header
lib/App/DocKnot/Spin/Text.pm view on Meta::CPAN
undef $INDENT;
next
}
# Everything else needs to have special characters escaped. We don't
# do this earlier because if we want to allow < and > in rules, the
# escaping would make our lives miserable.
$_ = escape $_;
# Do this before untabification and stashing of trailing whitespace,
# but after escaping. Check to see if this paragraph looks like
# literal text. If so, we wrap it in <pre> and output it as is. As a
# special exception to our normal paragraph handling, this paragraph
# doesn't end until we find a literal blank line; this hack lets full
# diffs be included in a FAQ without confusing the parser.
if (_is_literal $_) {
if (/\n[ \t]+$/) { $_ .= $self->_next_paragraph(1) }
$self->_output(pre(strip_indent($_, $INDENT)));
s/\n(\n\s*)$/\n/;
$space = $1;
$self->{pre} = 1;
lib/App/DocKnot/Spin/Text.pm view on Meta::CPAN
next;
}
# We're dealing with a normal paragraph of some sort, so go ahead and
# turn URLs into links. Check whether the paragraph is broken first,
# though, and stash that information, since turning URLs into links
# can artificially lengthen lines.
my $broken = _is_broken $_;
$_ = _format_urls($_);
# Check to see if we're in a contents section and this paragraph looks
# like a table of contents. If so, turn all of the section headings
# into links.
if ($self->{contents} && _is_contents($_)) {
$_ = _format_contents($_)
}
# Check for paragraphs that are entirely bulletted lines, and turn
# them into unordered lists without <p> tags.
if (_is_allbullet $_) {
my $last;
lib/App/DocKnot/Spin/Text.pm view on Meta::CPAN
=head1 DESCRIPTION
This is another of those odd breed of partially functional beasts, a text to
HTML converter.
This is not truly possible in general; people do too many varied things with
their text to intuit document structure from it. This is therefore a
converter that will translate documents written the way I write. It may or
may not work for you. The chances that it will work for you are directly
proportional to how much your writing looks like mine.
App::DocKnot::Spin::Text understands digest separators (lines of exactly
thirty hyphens, from the minimal digest standard) and will treat a C<Subject>
header immediately after them as a section header. Beyond that, headings must
either be outdented, underlined on the following line, or in all caps to be
recognized as section headers. (Outdenting means that the regular text is
indented by a few spaces, but headers start in column 0, or at least in a
column farther to the left than the regular text.)
Section headers that begin with numbers (with any number of periods) will be
lib/App/DocKnot/Spin/Thread.pm view on Meta::CPAN
Insert TEXT preformatted, preserving spacing and line breaks. This uses the
HTML C<< <pre> >> tag, and therefore is normally also shown in a fixed-width
font by the browser.
When using C<\pre> inside indented blocks or lists, some care must be taken
with indentation whitespace. Normally, the browser indents text inside
C<\pre> relative to the enclosing block, so you should only put as much
whitespace before each line in C<\pre> as those lines should be indented
relative to the enclosing text. However B<lynx>, unfortunately, indents
relative to the left margin, so it's difficult to use indentation that looks
correct in both B<lynx> and other browsers.
=item \quote[TEXT][AUTHOR][CITATION]
Used for quotes at the top of a web page.
The whole text will be enclosed in a C<< <blockquote> >> tag with class
C<quote> for style sheets. TEXT may be multiple paragraphs. Any formatting
instruction given to C<\quote> will be used as the formatting instruction for
each paragraph in TEXT (so an C<id> is normally not appropriate).
t/data/generate/lbcd/docknot.yaml view on Meta::CPAN
name: Expat
copyrights:
- holder: The Board of Trustees of the Leland Stanford Junior University
years: 1993-1994, 1996-1998, 2000, 2003-2009, 2012-2013
build:
autoconf: '2.64'
automake: '1.11'
autotools: true
middle: |
lbcd looks for `$sysconfdir/nolbcd` and returns the maximum load if that
file is present, allowing one to effectively drop a system out of a
load-balanced pool by touching that file. By default, the path is
`/usr/local/etc/nolbcd`, but you may want to pass `--sysconfdir=/etc` to
configure to use `/etc/nolbcd`.
lbcdclient is written in Perl, so you may have to edit the first line of
the script to point to the correct Perl location on your system. It does
not use any sophisticated Perl features or add-on modules.
suffix: |
You will generally want to start lbcd at system boot. All that is needed
t/data/generate/lbcd/output/readme view on Meta::CPAN
./configure
make
make install
If you are building from a Git clone, first run ./bootstrap in the
source directory to generate the build files. make install will
probably have to be done as root. Building outside of the source
directory is also supported, if you wish, by creating an empty directory
and then running configure with the correct relative path.
lbcd looks for $sysconfdir/nolbcd and returns the maximum load if that
file is present, allowing one to effectively drop a system out of a
load-balanced pool by touching that file. By default, the path is
/usr/local/etc/nolbcd, but you may want to pass --sysconfdir=/etc to
configure to use /etc/nolbcd.
lbcdclient is written in Perl, so you may have to edit the first line of
the script to point to the correct Perl location on your system. It
does not use any sophisticated Perl features or add-on modules.
Pass --enable-silent-rules to configure for a quieter build (similar to
t/data/generate/lbcd/output/readme-md view on Meta::CPAN
make
make install
```
If you are building from a Git clone, first run `./bootstrap` in the
source directory to generate the build files. `make install` will
probably have to be done as root. Building outside of the source
directory is also supported, if you wish, by creating an empty directory
and then running configure with the correct relative path.
lbcd looks for `$sysconfdir/nolbcd` and returns the maximum load if that
file is present, allowing one to effectively drop a system out of a
load-balanced pool by touching that file. By default, the path is
`/usr/local/etc/nolbcd`, but you may want to pass `--sysconfdir=/etc` to
configure to use `/etc/nolbcd`.
lbcdclient is written in Perl, so you may have to edit the first line of
the script to point to the correct Perl location on your system. It does
not use any sophisticated Perl features or add-on modules.
Pass `--enable-silent-rules` to configure for a quieter build (similar to
t/data/spin/input/journal/2011-08/006.th view on Meta::CPAN
Lois McMaster Bujold][
I don't like the early books as much as some, but I love some of the
later books. The last few have been disappointing, but overall very
much worth reading, and belongs around here on the list.
]
\n[Going Postal, by Terry Pratchett][Getting to it.]
\r[The Mote In God's Eye, by Larry Niven & Jerry Pournelle][
Read many years ago and barely remember it. I need to re-read it,
particularly since there's a new sequal by Pournelle's daughter that
looks well worth reading.
]
\p[The Sword Of Truth, by Terry Goodkind][
I read way too many books in this series. Others should not repeat my
mistake. Generic fantasy about incredibly stupid people that turns
into libertarian political ravings.
]
\n[The Road, by Cormac McCarthy][Not my thing.]
\r[\link[../../reviews/books/1-58234-416-7.html][Jonathan Strange & Mr
Norrell], by Susanna Clarke][
A nearly unique reading experience, and the best footnoted fantasy
t/data/spin/output/journal/2011-08/006.html view on Meta::CPAN
some point, but I'm not particularly eager.</li>
<li class="packed"><strong><a href="../../reviews/books/0-671-87749-6a.html">The Vorkosigan Saga</a>, by
Lois McMaster Bujold</strong>:
I don't like the early books as much as some, but I love some of the
later books. The last few have been disappointing, but overall very
much worth reading, and belongs around here on the list.</li>
<li class="packed">Going Postal, by Terry Pratchett: Getting to it.</li>
<li class="packed"><strong>The Mote In God's Eye, by Larry Niven & Jerry Pournelle</strong>:
Read many years ago and barely remember it. I need to re-read it,
particularly since there's a new sequal by Pournelle's daughter that
looks well worth reading.</li>
<li class="packed"><em>The Sword Of Truth, by Terry Goodkind</em>:
I read way too many books in this series. Others should not repeat my
mistake. Generic fantasy about incredibly stupid people that turns
into libertarian political ravings.</li>
<li class="packed">The Road, by Cormac McCarthy: Not my thing.</li>
<li class="packed"><strong><a href="../../reviews/books/1-58234-416-7.html">Jonathan Strange & Mr
Norrell</a>, by Susanna Clarke</strong>:
A nearly unique reading experience, and the best footnoted fantasy
that I've ever read (and that includes Pratchett). Great stuff if you
don't mind the slow pace. I'm eagerly hoping for an actual sequel.</li>
t/data/spin/output/journal/debian.rss view on Meta::CPAN
some point, but I'm not particularly eager.</li>
<li class="packed"><strong><a href="https://www.eyrie.org/~eagle/reviews/books/0-671-87749-6a.html">The Vorkosigan Saga</a>, by
Lois McMaster Bujold</strong>:
I don't like the early books as much as some, but I love some of the
later books. The last few have been disappointing, but overall very
much worth reading, and belongs around here on the list.</li>
<li class="packed">Going Postal, by Terry Pratchett: Getting to it.</li>
<li class="packed"><strong>The Mote In God's Eye, by Larry Niven & Jerry Pournelle</strong>:
Read many years ago and barely remember it. I need to re-read it,
particularly since there's a new sequal by Pournelle's daughter that
looks well worth reading.</li>
<li class="packed"><em>The Sword Of Truth, by Terry Goodkind</em>:
I read way too many books in this series. Others should not repeat my
mistake. Generic fantasy about incredibly stupid people that turns
into libertarian political ravings.</li>
<li class="packed">The Road, by Cormac McCarthy: Not my thing.</li>
<li class="packed"><strong><a href="https://www.eyrie.org/~eagle/reviews/books/1-58234-416-7.html">Jonathan Strange & Mr
Norrell</a>, by Susanna Clarke</strong>:
A nearly unique reading experience, and the best footnoted fantasy
that I've ever read (and that includes Pratchett). Great stuff if you
don't mind the slow pace. I'm eagerly hoping for an actual sequel.</li>
t/data/spin/output/journal/index.html view on Meta::CPAN
some point, but I'm not particularly eager.</li>
<li class="packed"><strong><a href="https://www.eyrie.org/~eagle/reviews/books/0-671-87749-6a.html">The Vorkosigan Saga</a>, by
Lois McMaster Bujold</strong>:
I don't like the early books as much as some, but I love some of the
later books. The last few have been disappointing, but overall very
much worth reading, and belongs around here on the list.</li>
<li class="packed">Going Postal, by Terry Pratchett: Getting to it.</li>
<li class="packed"><strong>The Mote In God's Eye, by Larry Niven & Jerry Pournelle</strong>:
Read many years ago and barely remember it. I need to re-read it,
particularly since there's a new sequal by Pournelle's daughter that
looks well worth reading.</li>
<li class="packed"><em>The Sword Of Truth, by Terry Goodkind</em>:
I read way too many books in this series. Others should not repeat my
mistake. Generic fantasy about incredibly stupid people that turns
into libertarian political ravings.</li>
<li class="packed">The Road, by Cormac McCarthy: Not my thing.</li>
<li class="packed"><strong><a href="https://www.eyrie.org/~eagle/reviews/books/1-58234-416-7.html">Jonathan Strange & Mr
Norrell</a>, by Susanna Clarke</strong>:
A nearly unique reading experience, and the best footnoted fantasy
that I've ever read (and that includes Pratchett). Great stuff if you
don't mind the slow pace. I'm eagerly hoping for an actual sequel.</li>
t/data/spin/output/journal/index.rss view on Meta::CPAN
some point, but I'm not particularly eager.</li>
<li class="packed"><strong><a href="https://www.eyrie.org/~eagle/reviews/books/0-671-87749-6a.html">The Vorkosigan Saga</a>, by
Lois McMaster Bujold</strong>:
I don't like the early books as much as some, but I love some of the
later books. The last few have been disappointing, but overall very
much worth reading, and belongs around here on the list.</li>
<li class="packed">Going Postal, by Terry Pratchett: Getting to it.</li>
<li class="packed"><strong>The Mote In God's Eye, by Larry Niven & Jerry Pournelle</strong>:
Read many years ago and barely remember it. I need to re-read it,
particularly since there's a new sequal by Pournelle's daughter that
looks well worth reading.</li>
<li class="packed"><em>The Sword Of Truth, by Terry Goodkind</em>:
I read way too many books in this series. Others should not repeat my
mistake. Generic fantasy about incredibly stupid people that turns
into libertarian political ravings.</li>
<li class="packed">The Road, by Cormac McCarthy: Not my thing.</li>
<li class="packed"><strong><a href="https://www.eyrie.org/~eagle/reviews/books/1-58234-416-7.html">Jonathan Strange & Mr
Norrell</a>, by Susanna Clarke</strong>:
A nearly unique reading experience, and the best footnoted fantasy
that I've ever read (and that includes Pratchett). Great stuff if you
don't mind the slow pace. I'm eagerly hoping for an actual sequel.</li>
t/data/spin/text/input/mjqmail view on Meta::CPAN
A virtual domain allows you to delegate an entire domain to a particular
user. Using virtual domains requires that you have sufficient control
over your DNS to set up a particular hostname just for your mailing lists.
You'll need to be able to pick an address, like lists.example.com, and set
up an MX record for it pointing to your mail server. If you're not able
to do this, use the qmail-users mechanism described in the next section.
Choose the subdomain that you're going to give to Majordomo (such as
lists.example.com). Add a line to /var/qmail/control/virtualdomains that
looks like:
lists.example.com:lists
replacing lists.example.com with your virtual domain and lists with your
Majordomo user. All addresses in that domain will now be handled by
.qmail files in the Majordomo user's home directory (well, after qmail is
restarted or qmail-send gets a HUP signal). See the qmail-send man page
for more details.
It's possible to use the virtual domain system under qmail 1.03 or later
t/data/spin/text/output/mjqmail.html view on Meta::CPAN
user. Using virtual domains requires that you have sufficient control
over your DNS to set up a particular hostname just for your mailing lists.
You'll need to be able to pick an address, like lists.example.com, and set
up an MX record for it pointing to your mail server. If you're not able
to do this, use the qmail-users mechanism described in the next section.
</p>
<p>
Choose the subdomain that you're going to give to Majordomo (such as
lists.example.com). Add a line to /var/qmail/control/virtualdomains that
looks like:
</p>
<pre> lists.example.com:lists</pre>
<p>
replacing lists.example.com with your virtual domain and lists with your
Majordomo user. All addresses in that domain will now be handled by
.qmail files in the Majordomo user's home directory (well, after qmail is
restarted or qmail-send gets a HUP signal). See the qmail-send man page
for more details.
t/data/update/lbcd/docknot.yaml view on Meta::CPAN
information about system load, number of logged-on users, uptime, and free
/tmp space. This information can be used to accumulate system status
across a cluster with light-weight queries or can be used as input to a
load-balancing system to choose the best system to which to direct new
incoming connections.
build:
autoconf: '2.64'
automake: '1.11'
autotools: true
middle: |
lbcd looks for `$sysconfdir/nolbcd` and returns the maximum load if that
file is present, allowing one to effectively drop a system out of a
load-balanced pool by touching that file. By default, the path is
`/usr/local/etc/nolbcd`, but you may want to pass `--sysconfdir=/etc` to
configure to use `/etc/nolbcd`.
lbcdclient is written in Perl, so you may have to edit the first line of
the script to point to the correct Perl location on your system. It does
not use any sophisticated Perl features or add-on modules.
suffix: |
You will generally want to start lbcd at system boot. All that is needed
t/data/update/lbcd/old/build/middle view on Meta::CPAN
lbcd looks for `$sysconfdir/nolbcd` and returns the maximum load if that
file is present, allowing one to effectively drop a system out of a
load-balanced pool by touching that file. By default, the path is
`/usr/local/etc/nolbcd`, but you may want to pass `--sysconfdir=/etc` to
configure to use `/etc/nolbcd`.
lbcdclient is written in Perl, so you may have to edit the first line of
the script to point to the correct Perl location on your system. It does
not use any sophisticated Perl features or add-on modules.
t/lib/Test/RRA.pm view on Meta::CPAN
# 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.
t/lib/Test/RRA.pm view on Meta::CPAN
DESC is a description of the tests being skipped. A space and C<normally
skipped> 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<plan skip_all>
from Test::More) with a skip reason saying that MODULE is required for the
test.
VERSION will be passed to C<use> 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 <eagle@eyrie.org>
=head1 COPYRIGHT AND LICENSE
t/lib/Test/RRA/Config.pm view on Meta::CPAN
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<data/perl.conf> 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<t> relative to the
current directory, which will be the case for stand-alone Perl modules.
The following variables are supported:
=over 4
t/style/module-version.t view on Meta::CPAN
=head1 DESCRIPTION
This script has a dual purpose as either a test script or a utility script.
The intent is to assist with maintaining consistent versions in a Perl
distribution, supporting both the package keyword syntax introduced in Perl
5.12 or the older explicit setting of a $VERSION variable.
As a test, it reads the current version of a package from the F<MYMETA.json>
file in the current directory (which should be the root of the distribution)
and then looks for any Perl modules in F<lib>. If it finds any, it checks
that the version number of the Perl module matches the version number of the
package from the F<MYMETA.json> file. These test results are reported with
Test::More, suitable for any TAP harness.
As a utility script, when run with the B<--update> option, it similarly finds
all Perl modules in F<lib> and then rewrites their version setting to match
the version of the package as determined from the F<MYMETA.json> file.
=head1 OPTIONS