The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
=pod

=head1 NAME

Pod::Tidy - a reformatting Pod Processor

=head1 SYNOPSIS

    use Pod::Tidy qw( tidy_files tidy_filehandle );

    my $processed = Pod::Tidy::tidy_files(
        files       => \@list,
        ignore      => [qr/foo/, qr/bar/],
        recursive   => $recursive,
        verbose     => $verbose,
        inplace     => $inplace,
        nobackup    => $nobackup,
    );

    Pod::Tidy::tidy_filehandle($input);

=head1 DESCRIPTION

This module provides the I<heavy lifting> needed by the C<podtidy> utility
although the API should be general enough that it can be used directly.

=head1 USAGE

=head2 Import Parameters

This module accepts no arguments to it's C<import> method and exports no
I<symbols>.

=head2 Exportable Subroutines

=over 4

=item * tidy_files( ... )

Accepts a mandatory hash.

    my $processed = Pod::Tidy::tidy_files(
        files       => \@list,
        ignore      => [qr/foo/, qr/bar/],
        recursive   => $recursive,
        verbose     => $verbose,
        inplace     => $inplace,
        nobackup    => $nobackup,
    );

=over 4

=item * files

An array ref to a list of files and/or directories.

=item * ignore

An array ref to regex objects that are used to reject files and/or directories.
Each pattern is tried for a match against (in order) the absolute file path,
the relative file path (canonical), and the basename.  In the case of
directories, the "basename" is considered to be the right most path component.
For example, the "basename" of C</foo/bar/baz/> would be to be C<baz>.

This key is optional.

=item * recursive

Accepts C<undef>, C<0>, or C<1>.  If set to C<1> any directories provided to
the C<files> key will be recursively expanded.  Defaults to C<undef>

This key is optional.

=item * verbose

Accepts C<undef>, C<0>, or C<1>.  C<1> enables verbose warnings. Defaults to
C<undef>.

This key is optional.

=item * inplace

Accepts C<undef>, C<0>, or C<1>.  C<1> enables I<in place> reformatting of
files.  Updated files will be backed up unless the C<nobackup> key is set.  The
C<mtime> of the file is guarenteed not to be changed unless formating changes
did occur.  Defaults to C<undef>.

This key is optional.

=item * nobackup

Accepts C<undef>, C<0>, or C<1>.  If set to C<1> files being reformatted in
place will not be backed up.  Defaults to C<undef>.

This key is optional.

=back

Before processing a file it is checked for:

=over 4

=item * correct access permissions

=item * containing Pod

=item * legal Pod syntax

=back

Any file failing to meet those criteria will I<not> be processed.

Returns a count of processed files or C<undef> if no files could be processed.

=item * tidy_filehandle($input)

Accepts an open filehandle.  Data from the filehandle is processed as it is
read so this subroutine can be used to filter large amounts of data.  Because
of this behavior the input can not be checked in advance to verify a) That it's
actually Pod and b) that the Pod document uses only valid Pod syntax.  Output
is set to C<STDOUT>.  Returns nothing.

=back

=head2 Internal Subroutines

These subroutines are not exportable.

=over 4

=item * backup_file

=item * base

=item * build_pod_queue

=item * process_pod_queue

=item * valid_pod_syntax

=back

=head1 DEVELOPER NOTES

=head2 Efficiency concerns

The C<tidy_files()> subroutine does a number of highly inefficient things. Each
file is opened and closed at least 3 different times as it is passed through a
number of different modules to see if it meets the processing criteria.  This
shouldn't be a major performance issue with an modern OS's VM subsystem but it
still leaves much to be desired.  When doing C<inplace> file reformatting a
complete copy of the original file and the updated file and held in memory for
comparison.  Thus you are limited to reformatting Pod documents C< < (
available_system_memory / 2 )>.

=head1 GOTCHAS

=head2 Pod files not identified

Due to a bug in the version of L<Pod::Find/contains_pod> bundled with
L<Pod::Parser> 1.33, Pod containing files will not be detected if the only
C<=[foo]N> directive is on the first line of the file.  For example:

    =head1 foo
    
    foobarbaz

    =cut

Would not be detected unless there was a newline before C<=head1 foo>.  See
CPAN bug #14871 for a patch to correct L<Pod::Find>.  This should be fixed in
version 1.34 of L<Pod::Parser>

=head2 Mangled verbatim blocks

Unfortunately, the C<perldoc> utility doesn't follow L<perlpodspec> for what it
considers a verbatim block.  As far as C<perldoc> is concerned, any line that
begins with whitespace is in a verbatim block.  While the Pod spec requires
that all blocks are separated by a blank line.

Consider this example:

    =head1 What Would Brian Boitano Do?

    What would Brian Boitano do
    If he was here right now?
    He'd make a plan and he'd follow through
    That's what Brian Boitano'd do
        When Brian Boitano was in the olympics
        Skating for the gold
        He'd do sound cows and a triple relux
        wearin a blindfold

    =cut

C<perldoc> incorrectly considers the second paragraph to be indented and would
display it as one might be expecting.  However, C<podtidy> would turn it into
this:

    =head1 What Would Brian Boitano Do?

    What would Brian Boitano do If he was here right now?  He'd make a plan and
    he'd follow through That's what Brian Boitano'd do     When Brian Boitano was
    in the olympics     Skating for the gold     He'd do sound cows and a triple
    relux     wearin a blindfold

    =cut

If a single blank line is added between the two paragraphs as required by
L<perlpodspec>, the original document would look like this:

    =head1 What Would Brian Boitano Do?

    What would Brian Boitano do
    If he was here right now?
    He'd make a plan and he'd follow through
    That's what Brian Boitano'd do

        When Brian Boitano was in the olympics
        Skating for the gold
        He'd do sound cows and a triple relux
        wearin a blindfold

    =cut

Then the result from C<podtidy> would be nice and... well... I<tidy>.

    =head1 What Would Brian Boitano Do?

    What would Brian Boitano do If he was here right now? He'd make a plan and he'd
    follow through That's what Brian Boitano'd do

        When Brian Boitano was in the olympics
        Skating for the gold
        He'd do sound cows and a triple relux
        wearin a blindfold

    =cut

=head1 CREDITS

Larry Denneau C<denneau@ifa.hawaii.edu> reported test failures caused by
L<Module::Build> stripping the execute bit from F<scripts/podtidy>.

Grant McLean C<grant@mclean.net.nz> caught a grammatical error in the
documentation.

Michael Cartmell C<Michael.Cartmell@thomson.com> provided some grammatical
corrections and a patch to fix C<Pod::Tidy::build_pod_queue()> tests on Win32,
reporting test failures on Win32 caused by differing newline encodings, and
reporting L<CPANPLUS> playing badly with L<Module::Build>'s C<build_requires>.

=head1 SUPPORT

Please contact the author directly via e-mail.

=head1 AUTHOR

Joshua Hoblitt C<jhoblitt@cpan.org>

=head1 COPYRIGHT

Copyright (c) 2005  Joshua Hoblitt. All rights reserved. This program is free
software; you can redistribute it and/or modify it under the same terms as Perl
itself.

The full text of the licenses can be found in the F<LICENSE> file included with
this module, or in L<perlartistic> and L<perlgpl> Pods as supplied with Perl
5.8.1 and later.

=head1 SEE ALSO

L<podtidy>, L<Pod::Wrap::Pretty>, L<podwrap>, L<Pod::Wrap>, L<Perl::Tidy>

=cut