App-CSVUtils

 view release on metacpan or  search on metacpan

lib/App/CSVUtils/paras2csv.pm  view on Meta::CPAN

package App::CSVUtils::paras2csv;

use 5.010001;
use strict;
use warnings;

our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
our $DATE = '2025-02-04'; # DATE
our $DIST = 'App-CSVUtils'; # DIST
our $VERSION = '1.036'; # VERSION

use App::CSVUtils qw(gen_csv_util);

sub _unescape_field {
    my $val = shift;
    $val =~ s/(\\:|\\n|\\\\|[^\\:]+)/$1 eq "\\\\" ? "\\" : $1 eq "\\n" ? "\n" : $1 eq "\\:" ? ":" : $1/eg;
    $val;
}

sub _unescape_value {
    my $val = shift;
    $val =~ s/(\\n|\\\\|[^\\]+)/$1 eq "\\\\" ? "\\" : $1 eq "\\n" ? "\n" : $1/eg;
    $val;
}

sub _parse_line {
    my $line = shift;
    $line =~ s/\R //g;
    $line =~ /((?:[^\\:]+|\\n|\\\\|\\:)+): (.*)/ or return;
    my $field = _unescape_field($1);
    my $value = _unescape_value($2);
    ($field, $value);
}

sub _parse_para {
    my ($r, $para, $idx) = @_;

    my @h;
    while ($para =~ s/\A(.+(?:\R .*)*)(?:\R|\z)//g) {
        #say "D:line=<$1>, para=<$para>";
        my ($field, $val) = _parse_line($1);
        defined $field or die [400, "Paragraph[$idx]: Can't parse line $1"];
        if ($r->{util_args}{trim_header}) {
            $field =~ s/\A\s+//;
            $field =~ s/\s+\z//;
        } elsif ($r->{util_args}{ltrim_header}) {
            $field =~ s/\A\s+//;
        } elsif ($r->{util_args}{rtrim_header}) {
            $field =~ s/\s+\z//;
        }
        push @h, $field, $val;
    }
    @h;
}

gen_csv_util(
    name => 'paras2csv',
    summary => 'Convert paragraphs to CSV',
    description => <<'_',

This utility is the counterpart of the <prog:csv2paras> utility. See its
documentation for more details.

Keywords: paragraphs, cards, pages, headers

_
    add_args => {
        input_file => {
            schema => 'filename*',
            default => '-',
            pos => 0,
        },
        trim_header => {
            schema => 'bool*',
        },
        rtrim_header => {
            schema => 'bool*',
        },
        ltrim_header => {
            schema => 'bool*',
        },
    },
    add_args_rels => {
        'choose_one&' => [ [qw/trim_header rtrim_header ltrim_header/] ],
    },
    links => [
        {url=>'prog:csv2paras'},
    ],
    tags => ['category:converting'],

    examples => [
        {
            summary => 'Convert paragraphs format to CSV',
            src => '[[prog]] - OUTPUT.csv',
            src_plang => 'bash',
            test => 0,
            'x.doc.show_result' => 0,
        },
    ],

    reads_csv => 0,

    after_read_input => sub {
        my $r = shift;

        my $fh;
        if ($r->{util_args}{input_file} eq '-') {
            $fh = \*STDIN;
        } else {
            open $fh, "<", $r->{util_args}{input_file}
                or die [500, "Can't read file '$r->{util_args}{input_file}: $!"];
        }

        local $/ = "";
        my $i = 0;
        while (my $para = <$fh>) {
            $para =~ s/\R{2}\z//;
            #say "D:para=<$para>";
            my @h = _parse_para($r, $para, $i);
            $i++;
            if ($i == 1) {
                my @h2 = @h;
                my $j = 0;
                while (my ($field, $value) = splice @h2, 0, 2) {
                    $r->{output_fields}[$j] = $field;
                    $r->{output_fields_idx}{$field} = $j;
                    $j++;
                }
            }
            my @vals;
            while (my ($field, $value) = splice @h, 0, 2) {
                push @vals, $value;
            }
            $r->{code_print_row}->(\@vals);
        }
    },
);

1;
# ABSTRACT: Convert paragraphs to CSV

__END__

=pod

=encoding UTF-8

=head1 NAME

App::CSVUtils::paras2csv - Convert paragraphs to CSV

=head1 VERSION

This document describes version 1.036 of App::CSVUtils::paras2csv (from Perl distribution App-CSVUtils), released on 2025-02-04.

=head1 FUNCTIONS


=head2 paras2csv

Usage:

 paras2csv(%args) -> [$status_code, $reason, $payload, \%result_meta]

Convert paragraphs to CSV.

This utility is the counterpart of the L<csv2paras> utility. See its
documentation for more details.

Keywords: paragraphs, cards, pages, headers

This function is not exported.

Arguments ('*' denotes required arguments):

=over 4

=item * B<input_file> => I<filename> (default: "-")



( run in 0.309 second using v1.01-cache-2.11-cpan-d7a12ab2c7f )