Perinci-CmdLine

 view release on metacpan or  search on metacpan

lib/Perinci/CmdLine/Manual/HowTo/99Examples.pod  view on Meta::CPAN

 gen_modified_sub(
     output_name => 'f1',
     base_name   => 'Package::F1::f1',
     modify_args => {
         foo => sub { my $as = shift; delete $as->{cmdline_aliases}   },
         fee => sub { my $as = shift; $as->{cmdline_aliases} = {f=>{} },
     },
 );
 Perinci::CmdLine->new(url => '/main/f1')->run;

=head2 Overriding common option

Example: My function has argument named 'format', but it is blocked by common
option '--format'!

To add/remove/rename common options, see the documentation on C<common_opts>
attribute. In this case, you want:

 delete $cmd->common_opts->{format};
 #delete $cmd->common_opts->{format_options}; # you might also want this

or perhaps rename it:

 $cmd->common_opts->{output_format} = $cmd->common_opts->{format};
 delete $cmd->common_opts->{format};

=head1 INPUT

=head2 Accepting input from STDIN (or files)

If you specify 'cmdline_src' to 'stdin' to a 'str' argument, the argument's
value will be retrieved from standard input if not specified. Example:

 use Perinci::CmdLine;
 $SPEC{cmd} = {
     v => 1.1,
     args => {
         arg => {
             schema => 'str*',
             cmdline_src => 'stdin',
         },
     },
 };
 sub cmd {
     my %args = @_;
     [200, "OK", "arg is '$args{arg}'"];
 }
 Perinci::CmdLine->new(url=>'/main/cmd')->run;

When run from command line:

 % cat file.txt
 This is content of file.txt
 % cat file.txt | cmd
 arg is 'This is content of file.txt'

If your function argument is an array, array of lines will be provided to your
function.

Note that this will glob the whole content of input into memory. If you want
streaming, see the next section.

=head2 Accept streaming input

To accept streaming input, you specify one or more of your arguments as C<<
stream=>1 >>. Also, these arguments need to specify their source either from
file, STDIN, or STDIN/files, by setting C<< cmdline_src =>
file|stdin|stdin_or_files >>, because otherwise, just receiving value from
command-line option like C<--arg val> is not very interesting :-). You will
receive your function argument as a coderef which you can call repeatedly until
input is exhausted (at the point of which the coderef will return undef).

 $SPEC{perl_wc} = {
     v => 1.1,
     args => {
         input => {
             schema => 'str*',
             stream => 1,
             cmdline_src => 'stdin_or_files',
         },
     },
 };
 sub perl_wc {
     my %args = @_;
     my $input = $args{input};

     my $chars = 0;
     my $words = 0;
     my $lines = 0;
     while (my $line = $input->()) {
         $lines++;
         $chars += length($line);
         chomp $line;
         my @w = split /[ \t]+/o, $line; $words += @w;
     }

     [200, "OK", {chars=>$chars, words=>$words, lines=>$lines}];
 }

When run:

 % ls -l | perl_wc
 +-------+-------+
 | key   | value |
 +-------+-------+
 | chars |  1995 |
 | lines |    42 |
 | words |    61 |
 +-------+-------+

Note: by default you will get string/text input line-by-line, and for binary
(C<buf>) per-64k. This will be configurable in the future.

If argument type is not simple (e.g. an array or hash), then JSON stream input
will be assumed. This means, each line of input will be parsed as JSON.

=head1 OUTPUT

=head2 Default output format

TODO

=head2 Removing borders

By default, the text format produces bordered tables in interactive mode, e.g.
if you have this program:

 $SPEC{foo} = {v=>1.1};
 sub foo {
     [200, "OK", [[1,2], [3,4], [5,6]]];
 }
 use Perinci::CmdLine::Any;
 Perinci::CmdLine::Any->new(url => '/main/foo')->run;

and you run it, you will have:

 % foo
 +---+---+
 | 1 | 2 |
 | 3 | 4 |
 | 5 | 6 |
 +---+---+

and if you use C<--format text-simple>, only then it will become a tab-separated
format:

 % foo --format text-simple
 1       2
 3       4
 5       6

But if you don't like this formatting and want to default to simpler formatting
by default, you can add C<cmdline.default_format> attribute to your function
metadata:

 $SPEC{foo} = {v=>1.1, 'cmdline.default_format' => 'text-simple'};

Using this attribute, you can also default to JSON, and so on if you want.

You can also do this on a per-result basis, by adding C<cmdline.default_format>
attribute in your result metadata, e.g.:

 sub foo {
     [200, "OK", [[1,2], [3,4], [5,6]], {'cmdline.default_format'=>'text-simple'}];
 }

=head2 Streaming output

To produce streaming output, set C<< stream=>1 >> in C<result> spec in function
metadata. Then in your function, return a subroutine reference that will allow
caller to read data from.

 $SPEC{nat} = {
     v => 1.1,
     summary => 'Generate an infinite sequence of natural numbers',
     args => {},
     result => {
         stream => 1,
         schema => 'str*',
     },
 };
 sub nat {
     my $n = 1;
     [200, "OK", sub { $n++ }];
 }

If result type is not simple (e.g. an array or hash), then each record will be
encoded into JSON, to produce JSON stream.

If you want to return a file content as a stream (instead of slurping the whole
content into memory):

 $SPEC{catfile} = {
     v => 1.1,
     summary => "Display file contents",
     args => { file => { schema => 'filename*', req=>1, pos=>0 } },
     result => { stream => 1, schema => 'str*' },
 };
 sub catfile {
     my %args = @_;
     my $file = $args{file};
     open my $fh, "<", $file or return [500, "Can't open file '$file': $!"];
     [200, "OK", sub { scalar(<$fh>) }];
 }

=head2 Adding support for new format

TODO

=head2 Pager

TODO

=head2 Word wrapping

If your table has long text that is better shown in a multi-line cell, you can
do:

 % FORMAT_PRETTY_TABLE_BACKEND=Text::ANSITable your-app ...

to use L<Text::ANSITable>, which by default wraps long text in table cells.

=head1 CONFIGURATION

=head2 Basics

In the function-centric world of Perinci::CmdLine, configuration is just another
way to supply values to function arguments (before being potentially overridden
by command-line arguments). Configuration files are written in L<IOD> format,



( run in 1.772 second using v1.01-cache-2.11-cpan-437f7b0c052 )