App-CSVUtils
view release on metacpan or search on metacpan
lib/App/CSVUtils.pm view on Meta::CPAN
by_code => {
summary => 'Sort fields using Perl code',
schema => $sch_req_str_or_code,
description => <<'_',
`$a` and `$b` (or the first and second argument) will contain `[$field_name,
$field_idx]`.
_
},
%argspecsopt_sortsub,
);
our %argspecopt_with_data_rows = (
with_data_rows => {
summary => 'Whether to also output data rows',
schema => 'bool',
},
);
our %argspecopt_hash = (
hash => {
summary => 'Provide row in $_ as hashref instead of arrayref',
schema => ['bool*', is=>1],
cmdline_aliases => {H=>{}},
},
);
# add a position to specified argument, if possible
sub _add_arg_pos {
my ($args, $argname, $is_slurpy) = @_;
# argument already has a position, return
return if defined $args->{$argname}{pos};
# position of slurpy argument
my $slurpy_pos;
for (keys %$args) {
next unless $args->{$_}{slurpy};
$slurpy_pos = $args->{$_}{pos};
last;
}
# there is already a slurpy arg, return
return if $is_slurpy && defined $slurpy_pos;
# find the lowest position that's not available
ARG:
for my $j (0 .. scalar(keys %$args)-1) {
last if defined $slurpy_pos && $j >= $slurpy_pos;
for (keys %$args) {
next ARG if defined $args->{$_}{pos} && $args->{$_}{pos} == $j;
}
$args->{$argname}{pos} = $j;
$args->{$argname}{slurpy} = 1 if $is_slurpy;
last;
}
}
sub _randext {
state $charset = [0..9, "A".."Z","a".."z"];
my $len = shift;
my $ext = "";
for (1..$len) { $ext .= $charset->[rand @$charset] }
$ext;
}
$SPEC{gen_csv_util} = {
v => 1.1,
summary => 'Generate a CSV utility',
description => <<'_',
This routine is used to generate a CSV utility in the form of a <pm:Rinci>
function (code and metadata). You can then produce a CLI from the Rinci function
simply using <pm:Perinci::CmdLine::Gen> or, if you use <pm:Dist::Zilla>,
<pm:Dist::Zilla::Plugin::GenPericmdScript> or, if on the command-line,
<prog:gen-pericmd-script>.
Using this routine, by providing just one or a few hooks and setting some
parameters like a couple of extra arguments, you will get a complete CLI with
decent POD/manpage, ability to read one or multiple CSV's and write one or
multiple CSV's, some command-line options to customize how the input CSV's
should be parsed and how the output CSV's should be formatted and named. Your
CLI also has tab completion, usage and help message, and other features.
To create a CSV utility, you specify a `name` (e.g. `csv_dump`; must be a valid
unqualified Perl identifier/function name) and optionally `summary`,
`description`, and other metadata like `links` or even `add_meta_props`. Then
you specify one or more of `on_*` or `before_*` or `after_*` arguments to supply
handlers (coderefs) for your CSV utility at various hook points.
*THE HOOKS*
All code for hooks should accept a single argument `r`. `r` is a stash (hashref)
of various data, the keys of which will depend on which hook point being called.
You can also add more keys to store data or for flow control (see hook
documentation below for more details).
The order of the hooks, in processing chronological order:
* on_begin
Called when utility begins, before reading CSV. You can use this hook e.g. to
process arguments, set output filenames (if you allow custom output
filenames).
* before_read_input
Called before opening any input CSV file. This hook is *still* called even if
your utility sets `reads_csv` to false.
At this point, the `input_filenames` stash key (as well as other keys like
`input_filename`, `input_filenum`, etc) has not been set. You can use this
hook e.g. to set a custom `input_filenames`.
* before_open_input_files
Called before an input CSV file is about to be opened, including for stdin
(`-`). You can use this hook e.g. to check/preprocess input file. Flow control
is available by setting `$r->{wants_skip_files}` to skip reading all the input
files and go directly to the `after_read_input` hook.
* before_open_input_file
( run in 0.868 second using v1.01-cache-2.11-cpan-39bf76dae61 )