App-CSVUtils

 view release on metacpan or  search on metacpan

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

_
        tags => ['category:output'],
    },
);

our %argspecopt_input_filename = (
    input_filename => {
        summary => 'Input CSV file',
        description => <<'_',

Use `-` to read from stdin.

Encoding of input file is assumed to be UTF-8.

_
        schema => 'filename*',
        default => '-',
        'x.completion' => $xcomp_csvfiles,
        tags => ['category:input'],
    },
);

our %argspecopt_input_filenames = (
    input_filenames => {
        'x.name.is_plural' => 1,
        'x.name.singular' => 'input_filename',
        summary => 'Input CSV files',
        description => <<'_',

Use `-` to read from stdin.

Encoding of input file is assumed to be UTF-8.

_
        schema => ['array*', of=>'filename*'],
        default => ['-'],
        'x.completion' => $xcomp_csvfiles,
        tags => ['category:input'],
    },
);

our %argspecopt_overwrite = (
    overwrite => {
        summary => 'Whether to override existing output file',
        schema => 'bool*',
        cmdline_aliases=>{O=>{}},
        tags => ['category:output'],
    },
);

our %argspecsopt_inplace = (
    inplace => {
        summary => 'Output to the same file as input',
        schema => 'true*',
        description => <<'_',

Normally, you output to a different file than input. If you try to output to the
same file (`-o INPUT.csv -O`) you will clobber the input file; thus the utility
prevents you from doing it. However, with this `--inplace` option, you can
output to the same file. Like perl's `-i` option, this will first output to a
temporary file in the same directory as the input file then rename to the final
file at the end. You cannot specify output file (`-o`) when using this option,
but you can specify backup extension with `-b` option.

Some caveats:

- if input file is a symbolic link, it will be replaced with a regular file;
- renaming (implemented using `rename()`) can fail if input filename is too long;
- value specified in `-b` is currently not checked for acceptable characters;
- things can also fail if permissions are restrictive;

_
        tags => ['category:output'],
    },
    inplace_backup_ext => {
        summary => 'Extension to add for backup of input file',
        schema => 'str*',
        default => '',
        description => <<'_',

In inplace mode (`--inplace`), if this option is set to a non-empty string, will
rename the input file using this extension as a backup. The old existing backup
will be overwritten, if any.

_
        cmdline_aliases => {b=>{}},
        tags => ['category:output'],
    },
);

our %argspecopt_output_filename = (
    output_filename => {
        summary => 'Output filename',
        description => <<'_',

Use `-` to output to stdout (the default if you don't specify this option).

Encoding of output file is assumed to be UTF-8.

_
        schema => 'filename*',
        cmdline_aliases=>{o=>{}},
        tags => ['category:output'],
    },
);

our %argspecopt_output_filenames = (
    output_filenames => {
        summary => 'Output filenames',
        description => <<'_',

Use `-` to output to stdout (the default if you don't specify this option).

Encoding of output file is assumed to be UTF-8.

_
        schema => ['array*', of=>'filename*'],
        cmdline_aliases=>{o=>{}},
        tags => ['category:output'],
    },
);

our %argspecopt_field = (
    field => {
        summary => 'Field name',
        schema => 'str*',
        cmdline_aliases => { f=>{} },
        completion => \&_complete_field,
    },
);

our %argspecopt_field_1 = (
    field => {
        summary => 'Field name',
        schema => 'str*',
        pos => 1,
        cmdline_aliases => { f=>{} },
        completion => \&_complete_field,
    },
);

our %argspec_field_1 = (

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

                        # XXX actually close filehandle except stdin

                        if ($after_close_input_file) {
                            log_trace "[csvutil] Calling after_close_input_file handler ...";
                            $after_close_input_file->($r);
                            if (delete $r->{wants_skip_files}) {
                                log_trace "[csvutil] Handler wants to skip reading all file, skipping";
                                last READ_CSV;
                            }
                        }
                    } # for input_filename

                    if ($after_close_input_files) {
                        log_trace "[csvutil] Calling after_close_input_files handler ...";
                        $after_close_input_files->($r);
                    }

                } # READ_CSV

                # cleanup stash from csv-reading-related keys
                delete $r->{input_filenames};
                delete $r->{input_filenum};
                delete $r->{input_filename};
                delete $r->{input_fh};
                delete $r->{input_rownum};
                delete $r->{input_data_rownum};
                delete $r->{input_row};
                delete $r->{input_row_as_hashref};
                delete $r->{input_fields};
                delete $r->{input_fields_idx};
                delete $r->{orig_input_fields_idx};
                delete $r->{code_getline};
                delete $r->{wants_input_row_as_hashref};

                if ($after_read_input) {
                    log_trace "[csvutil] Calling after_read_input handler ...";
                    $after_read_input->($r);
                }

                # cleanup stash from csv-outputting-related keys
                delete $r->{output_num_of_files};
                delete $r->{output_filenum};
                if ($r->{output_fh}) {
                    if ($r->{output_filename} ne '-') {
                        log_info "[csvutil] Closing output file '$r->{output_filename}' ...";
                        close $r->{output_fh} or die [500, "Can't close output file '$r->{output_filename}': $!"];
                    }
                    delete $r->{output_fh};
                }
                if ($r->{util_args}{inplace}) {
                    my $output_filenum = $r->{output_filenum} // 0;
                    my $i = -1;
                    for my $output_filename (@{ $r->{output_filenames} }) {
                        $i++;
                        last if $i > $output_filenum;
                        (my $input_filename = $output_filename) =~ s/\.\w{5}\z//
                            or die [500, "BUG: Can't get original input file '$output_filename'"];
                        if (length(my $ext = $r->{util_args}{inplace_backup_ext})) {
                            my $backup_filename = $input_filename . $ext;
                            log_info "[csvutil] Backing up input file '$output_filename' -> '$backup_filename' ...";
                            rename $input_filename, $backup_filename or die [500, "Can't rename '$input_filename' -> '$backup_filename': $!"];
                        }
                        log_info "[csvutil] Renaming from temporary output file '$output_filename' -> '$input_filename' ...";
                        rename $output_filename, $input_filename or die [500, "Can't rename back '$output_filename' -> '$input_filename': $!"];
                    }
                }
                delete $r->{output_filenames};
                delete $r->{output_filename};
                delete $r->{output_rownum};
                delete $r->{output_data_rownum};
                delete $r->{code_print};
                delete $r->{code_print_row};
                delete $r->{code_print_header_row};
                delete $r->{has_printed_header};
                delete $r->{wants_switch_to_next_output_file};

                if ($on_end) {
                    log_trace "[csvutil] Calling on_end hook handler ...";
                    $on_end->($r);
                }

            }; # MAIN_EVAL

            my $err = $@;
            if ($err) {
                $err = [500, $err] unless ref $err;
                return $err;
            }

          RETURN_RESULT:
            if (!$r->{result}) {
                $r->{result} = [200];
            } elsif (!ref($r->{result})) {
                $r->{result} = [500, "BUG: Result (r->{result}) is set to a non-reference ($r->{result}), probably by one of the handlers"];
            } elsif (ref($r->{result}) ne 'ARRAY') {
                $r->{result} = [500, "BUG: Result (r->{result}) is not set to an enveloped result (arrayref) ($r->{result}), probably by one of the handlers"];
            }
            $r->{result};
        };
    } # CREATE_CODE

    my $meta;
  CREATE_META: {

        $meta = {
            v => 1.1,
            summary => $summary,
            description => $description,
            args => {},
            args_rels => {},
            links => $links,
            examples => $examples,
            tags => $tags,
        };

      CREATE_ARGS_PROP: {
            if ($add_args) {
                $meta->{args}{$_} = $add_args->{$_} for keys %$add_args;
            }

            if ($reads_csv) {
                $meta->{args}{$_} = {%{$argspecs_csv_input{$_}}} for keys %argspecs_csv_input;

                if ($reads_multiple_csv) {



( run in 2.232 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )