The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package SHARYANTO::Role::Doc::Section::AddTextLines;

use 5.010;
use Log::Any '$log';
use Moo::Role;

our $VERSION = '0.72'; # VERSION

requires 'doc_lines';
requires 'doc_indent_level';
requires 'doc_indent_str';
has doc_wrap => (is => 'rw', default => sub {1});

sub add_doc_lines {
    my $self = shift;
    my $opts;
    if (ref($_[0]) eq 'HASH') { $opts = shift }
    $opts //= {};

    my @lines = map { $_ . (/\n\z/s ? "" : "\n") }
        map {/\n/ ? split /\n/ : $_} @_;

    # debug
    #my @c = caller(2);
    #$c[1] =~ s!.+/!!;
    #@lines = map {"[from $c[1]:$c[2]]$_"} @ lines;

    my $indent = $self->doc_indent_str x $self->doc_indent_level;
    my $wrap = $opts->{wrap} // $self->doc_wrap;

    if ($wrap) {
        require Text::Wrap;

        # split into paragraphs, merge each paragraph text into a single line
        # first
        my @para;
        my $i = 0;
        my ($start, $type);
        $type = '';
        #$log->warnf("lines=%s", \@lines);
        for (@lines) {
            if (/^\s*$/) {
                if (defined($start) && $type ne 'blank') {
                    push @para, [$type, [@lines[$start..$i-1]]];
                    undef $start;
                }
                $start //= $i;
                $type = 'blank';
            } elsif (/^\s{4,}\S+/ && (!$i || $type eq 'verbatim' ||
                         (@para && $para[-1][0] eq 'blank'))) {
                if (defined($start) && $type ne 'verbatim') {
                    push @para, [$type, [@lines[$start..$i-1]]];
                    undef $start;
                }
                $start //= $i;
                $type = 'verbatim';
            } else {
                if (defined($start) && $type ne 'normal') {
                    push @para, [$type, [@lines[$start..$i-1]]];
                    undef $start;
                }
                $start //= $i;
                $type = 'normal';
            }
            #$log->warnf("i=%d, lines=%s, start=%s, type=%s",
            #            $i, $_, $start, $type);
            $i++;
        }
        if (@para && $para[-1][0] eq $type) {
            push @{ $para[-1][1] }, [$type, [@lines[$start..$i-1]]];
        } else {
            push @para, [$type, [@lines[$start..$i-1]]];
        }
        #$log->warnf("para=%s", \@para);

        for my $para (@para) {
            if ($para->[0] eq 'blank') {
                push @{$self->doc_lines}, @{$para->[1]};
            } else {
                if ($para->[0] eq 'normal') {
                    for (@{$para->[1]}) {
                        s/\n/ /g;
                    }
                    $para->[1] = [join("", @{$para->[1]}) . "\n"];
                }
                #$log->warnf("para=%s", $para);
                local $Text::Wrap::columns = $ENV{COLUMNS} // 80;
                push @{$self->doc_lines},
                    Text::Wrap::wrap($indent, $indent, @{$para->[1]});
            }
        }
    } else {
        push @{$self->doc_lines},
            map {"$indent$_"} @lines;
    }
}

1;

# ABSTRACT: Provide add_doc_lines() to add text with optional text wrapping

__END__

=pod

=encoding UTF-8

=head1 NAME

SHARYANTO::Role::Doc::Section::AddTextLines - Provide add_doc_lines() to add text with optional text wrapping

=head1 VERSION

version 0.72

=head1 DESCRIPTION

This role provides C<add_doc_lines()> which can add optionally wrapped text to
C<doc_lines>.

The default column width for wrapping is from C<COLUMNS> environment variable,
or 80.

=head1 ATTRIBUTES

=head2 doc_wrap => BOOL (default: 1)

Whether to do text wrapping.

=head1 REQUIRES

These methods are provided by, e.g. L<SHARYANTO::Role::Doc::Section>.

=head2 $o->doc_lines()

=head2 $o->doc_indent_level()

=head2 $o->doc_lines_str()

=head1 METHODS

=head2 $o->add_doc_lines([\%opts, ]@lines)

Add lines of text, optionally wrapping each line if wrapping is enabled.

Available options:

=over 4

=item * wrap => BOOL

Whether to enable wrapping. Default is from the C<doc_wrap> attribute.

=back

=head1 ENVIRONMENT

=head2 COLUMNS => INT

Used to set column width.

=head1 SEE ALSO

L<SHARYANTO::Role::Doc::Section>

=head1 HOMEPAGE

Please visit the project's homepage at L<https://metacpan.org/release/SHARYANTO-Roles>.

=head1 SOURCE

Source repository is at L<https://github.com/sharyanto/perl-SHARYANTO-Roles>.

=head1 BUGS

Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=SHARYANTO-Roles>

When submitting a bug or request, please include a test-file or a
patch to an existing test-file that illustrates the bug or desired
feature.

=head1 AUTHOR

Steven Haryanto <stevenharyanto@gmail.com>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2014 by Steven Haryanto.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut