#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#
#   file: lib/Dist/Zilla/Plugin/Templates/FIle.pm

#pod =encoding UTF-8
#pod
#pod =head1 COPYRIGHT AND LICENSE
#pod
#pod Copyright © 2015 Van de Bugger
#pod
#pod This file is part of perl-Dist-Zilla-Plugin-Templates.
#pod
#pod perl-Dist-Zilla-Plugin-Templates is free software: you can redistribute it and/or modify it
#pod under the terms of the GNU General Public License as published by the Free Software Foundation,
#pod either version 3 of the License, or (at your option) any later version.
#pod
#pod perl-Dist-Zilla-Plugin-Templates is distributed in the hope that it will be useful, but WITHOUT
#pod ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
#pod PURPOSE. See the GNU General Public License for more details.
#pod
#pod You should have received a copy of the GNU General Public License along with
#pod perl-Dist-Zilla-Plugin-Templates. If not, see <http://www.gnu.org/licenses/>.
#pod
#pod =cut

#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

#pod =head1 SYNOPSIS
#pod
#pod In a template:
#pod
#pod     {{ include( 'as-is.txt' ); }}
#pod     {{ include( 'verbatim.txt' )->indent; }}
#pod     {{ include( 'template.txt' )->fill_in; }}
#pod     {{ include( 'readme.pod' )->pod2text; }}
#pod
#pod =head1 DESCRIPTION
#pod
#pod This is a helper module for C<Dist::Zilla::Templates>. It provides few frequently used operations
#pod on include files.
#pod
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod = L<Dist::Zilla>
#pod = L<Dist::Zilla::Role::FileFinderUser>
#pod = L<Dist::Zilla::Role::TextTemplater>
#pod = L<Text::Template>
#pod = L<Pod::Text>
#pod = L<Dist::Zilla::Plugin::Templates::Manual>
#pod
#pod =cut

package Dist::Zilla::Plugin::Templates::File;

use Moose;
use namespace::autoclean;
use version 0.77;

# ABSTRACT: TODO: Convert any text file into template
our $VERSION = 'v0.5.2'; # VERSION

extends 'Dist::Zilla::File::InMemory';

use overload '""' => sub {
    my ( $self ) = @_;
    return $self->content;
};

use Pod::Text qw{};     # `Pod::Text` exports `pod2text` by default. Let us avoid it.

# --------------------------------------------------------------------------------------------------

#pod =attr _plugin
#pod
#pod Reference to the plugin created this object.
#pod
#pod C<Object>, read-only.
#pod
#pod =cut

has _plugin => (
    isa         => 'Object',
    is          => 'ro',
    weak_ref    => 1,
);

# --------------------------------------------------------------------------------------------------

#pod =method chomp
#pod
#pod     $file->chomp();
#pod     $file->chomp( $count );
#pod
#pod Chomps file content C<$count> times. If C<$count> is not specified, the method chomps all the
#pod trailing newlines (more exactly: all the trailing input record separators; see core function
#pod C<chomp> for details).
#pod
#pod Note: The methods chomps newlines from the end of file, I<not> from each line.
#pod
#pod The method returns C<$self> for chaining.
#pod
#pod =cut

sub chomp {                             ## no critic ( ProhibitBuiltinHomonyms )
    my ( $self, $count ) = @_;
    my $content = $self->content;
    if ( not defined( $count ) ) {
        $count = -1;
    };
    while ( $count and CORE::chomp( $content ) ) {
        -- $count;
    };
    $self->content( $content );
    return $self;
};

# --------------------------------------------------------------------------------------------------

#pod =method fill_in
#pod
#pod     $file->fill_in();
#pod     $file->fill_in( \%variables, \%extra_args );
#pod
#pod Calls plugin's C<fill_in_file> method (which is defined in C<TextTemplater> role), passing C<$self>
#pod as the first argument. Returns C<$self>.
#pod
#pod Primary purpose of the method is including a file which is template itself:
#pod
#pod     {{ include( 'doc/chapter1.pod' )->fill_in; }}
#pod
#pod Without C<fill_in>, F<doc/chapter1.pod> is included as-is, Perl code fragments, if any, are not
#pod evaluated.
#pod
#pod See L<Dist::Zilla::Role::TextTemplater/"fill_in_file">.
#pod
#pod =cut

# TODO: Pass arguments recursively?

sub fill_in {
    my ( $self, @args ) = @_;
    $self->_plugin->fill_in_file( $self, @args );
    return $self;
};

# --------------------------------------------------------------------------------------------------

#pod =method indent
#pod
#pod     $file->indent();
#pod     $file->indent( $size );
#pod
#pod Indents file content by inserting specified number of spaces to the beginning of every non-empty
#pod line. By default, file is indented with 4 spaces. The method returns C<$self> for chaining.
#pod
#pod Primary purpose of the method is including a file into POD as verbatim paragraph(s):
#pod
#pod     =head2 example.pl
#pod
#pod     {{ include( 'ex/example.pl' )->indent; }}
#pod
#pod     =cut
#pod
#pod =cut

sub indent {
    my ( $self, $size ) = @_;
    my $indent  = ' ' x ( defined( $size ) ? $size : 4 );
    my $content = $self->content;
    $content =~ s{^(?!$)}{$indent}gmx;
    $self->content( $content );
    return $self;
};

# --------------------------------------------------------------------------------------------------

#pod =method pod2text
#pod
#pod     $file->pod2text( %options );
#pod
#pod Convert POD to plain text. It is a simple wrapper over C<Pod::Text>. See documentation on
#pod C<Pod::Text::new> for description of available options.
#pod
#pod Example:
#pod
#pod     {{ include( 'readme.pod' )->pod2text( width => 80, quotes => 'none', loose => 1 ); }}
#pod
#pod See L<Pod::Text/"DESCRIPTION">.
#pod
#pod =cut

sub pod2text {
    my ( $self, %opts ) = @_;
    # Create parser object:
    my $parser = Pod::Text->new( %opts );
    my $text;
    $parser->output_string( \$text );
    $parser->complain_stderr( 1 );
    {
        # Now do a dirty hack. `Pod::Simple` parser either print messages to `STDERR`,
        # or creates a section at the end of the document. Let us redefine its
        # `_complain_warn` function to catch error messages:
        no warnings 'redefine';                         ## no critic ( ProhibitNoWarnings )
        local *Pod::Simple::_complain_warn = sub {      ## no critic ( ProtectPrivateVars )
            my ( undef, $line, $msg ) = @_;
            ## no critic ( RequireCarping )
            warn sprintf( "%s at %s line %s.\n", $msg, $self->name, $line );
        };
        # Ok, now parse POD and reports errors, if any:
        $parser->parse_string_document( $self->content );
    }
    ## no critic ( RequireCarping )
    if ( $parser->any_errata_seen ) {
        #   TODO: Use `log_errors_in_file` to repot POD errors?
        die sprintf( "POD errata found at %s.\n", $self->name );
    };
    if ( not $parser->content_seen ) {
        die sprintf( "No POD content found at %s.\n", $self->name );
    };
    $self->content( $text );
    return $self;
};

# --------------------------------------------------------------------------------------------------

__PACKAGE__->meta->make_immutable();

1;

# --------------------------------------------------------------------------------------------------

# end of file #

__END__

=pod

=encoding UTF-8

=head1 NAME

Dist::Zilla::Plugin::Templates::File - TODO: Convert any text file into template

=head1 VERSION

Version v0.5.2, released on 2015-09-24 20:14 UTC.

=head1 SYNOPSIS

In a template:

    {{ include( 'as-is.txt' ); }}
    {{ include( 'verbatim.txt' )->indent; }}
    {{ include( 'template.txt' )->fill_in; }}
    {{ include( 'readme.pod' )->pod2text; }}

=head1 DESCRIPTION

This is a helper module for C<Dist::Zilla::Templates>. It provides few frequently used operations
on include files.

=head1 OBJECT ATTRIBUTES

=head2 _plugin

Reference to the plugin created this object.

C<Object>, read-only.

=head1 OBJECT METHODS

=head2 chomp

    $file->chomp();
    $file->chomp( $count );

Chomps file content C<$count> times. If C<$count> is not specified, the method chomps all the
trailing newlines (more exactly: all the trailing input record separators; see core function
C<chomp> for details).

Note: The methods chomps newlines from the end of file, I<not> from each line.

The method returns C<$self> for chaining.

=head2 fill_in

    $file->fill_in();
    $file->fill_in( \%variables, \%extra_args );

Calls plugin's C<fill_in_file> method (which is defined in C<TextTemplater> role), passing C<$self>
as the first argument. Returns C<$self>.

Primary purpose of the method is including a file which is template itself:

    {{ include( 'doc/chapter1.pod' )->fill_in; }}

Without C<fill_in>, F<doc/chapter1.pod> is included as-is, Perl code fragments, if any, are not
evaluated.

See L<Dist::Zilla::Role::TextTemplater/"fill_in_file">.

=head2 indent

    $file->indent();
    $file->indent( $size );

Indents file content by inserting specified number of spaces to the beginning of every non-empty
line. By default, file is indented with 4 spaces. The method returns C<$self> for chaining.

Primary purpose of the method is including a file into POD as verbatim paragraph(s):

    =head2 example.pl

    {{ include( 'ex/example.pl' )->indent; }}

    =cut

=head2 pod2text

    $file->pod2text( %options );

Convert POD to plain text. It is a simple wrapper over C<Pod::Text>. See documentation on
C<Pod::Text::new> for description of available options.

Example:

    {{ include( 'readme.pod' )->pod2text( width => 80, quotes => 'none', loose => 1 ); }}

See L<Pod::Text/"DESCRIPTION">.

=head1 SEE ALSO

=over 4

=item L<Dist::Zilla>

=item L<Dist::Zilla::Role::FileFinderUser>

=item L<Dist::Zilla::Role::TextTemplater>

=item L<Text::Template>

=item L<Pod::Text>

=item L<Dist::Zilla::Plugin::Templates::Manual>

=back

=head1 AUTHOR

Van de Bugger <van.de.bugger@gmail.com>

=head1 COPYRIGHT AND LICENSE

Copyright © 2015 Van de Bugger

This file is part of perl-Dist-Zilla-Plugin-Templates.

perl-Dist-Zilla-Plugin-Templates is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.

perl-Dist-Zilla-Plugin-Templates is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
perl-Dist-Zilla-Plugin-Templates. If not, see <http://www.gnu.org/licenses/>.

=cut
