The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Perinci::CmdLine::Manual::FAQ - FAQs

VERSION

This document describes version 0.27 of Perinci::CmdLine::Manual::FAQ (from Perl distribution Perinci-CmdLine-Lite), released on 2014-09-03.

FAQ

P::C denotes that the answer applies to Perinci::CmdLine only and not Perinci::CmdLine::Lite.

How do I debug my program?

[P::C] You can set environment DEBUG=1 or TRACE=1. See Log::Any::App for more details.

How does Perinci::CmdLine compare with other CLI-app frameworks?

The main difference is that Perinci::CmdLine accesses your code through Riap protocol, not directly. This means that aside from local Perl code, Perinci::CmdLine can also provide CLI for code in remote hosts/languages. For a very rough demo, download and run this PHP Riap::TCP server https://github.com/sharyanto/php-Phinci/blob/master/demo/phi-tcpserve-terbilang.php on your system. After that, try running:

 % peri-run riap+tcp://localhost:9090/terbilang --help
 % peri-run riap+tcp://localhost:9090/terbilang 1234

Everything from help message, calling, argument checking, tab completion works for remote code as well as local Perl code.

How to add support for new output format (e.g. XML, HTML)?

See Perinci::Result::Format.

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

To add/remove/rename common options, see the documentation on 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};

How to accept 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. A mechanism to be will be provided in the future (currently not yet specified in Rinci::function specification).

But I don't want the whole file content slurped into string/array, I want streaming!

If your function argument is of type stream or filehandle, an I/O handle will be provided to your function instead. But this part is not implemented yet.

Currently, see App::dux for an example on how to accomplish this on function argument of type array. Basically in App::dux, you feed an array tied with Tie::Diamond as a function argument. Thus you can get lines from file/STDIN iteratively with each().

My function has some cmdline_aliases or cmdline_src defined but I want to change it!

For example, your f1 function metadata might look like this:

 package Package::F1;
 our %SPEC;
 $SPEC{f1} = {
     v => 1.1,
     args => {
         foo => {
             cmdline_aliases => { f=> {} },
         },
         bar => { ... },
         fee => { ... },
     },
 };
 sub f1 { ... }
 1;

And your command-line script f1:

 #!perl
 use Perinci::CmdLine;
 Perinci::CmdLine->new(url => '/Package/F1/f1')->run;

Now you want to create a command-line script interface for this function, but with -f as an alias for --fee instead of --foo. This is best done by modifying the metadata and creating a wrapper function to do this, e.g. your command-line script f1 becomes:

 package main;
 use Perinci::CmdLine;
 use Package::F1;
 use Data::Clone;
 our %SPEC;
 $SPEC{f1} = clone $Package::F1::SPEC{f1};
 delete $SPEC{f1}{args}{foo}{cmdline_aliases};
 $SPEC{f1}{args}{fee}{cmdline_aliases} = {f=>{}};
 *f1 = \&Package::F1::f1;
 Perinci::CmdLine->new(url => '/main/f1')->run;

This also demonstrates the convenience of having the metadata as a data structure: you can manipulate it however you want. There is also a convenient function available in Perinci::Sub::Util when you want to create a modified subroutine based on another:

 package main;
 use Perinci::CmdLine;
 use Perinci::Sub::Util qw(gen_modified_sub);

 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;

How to do custom completion for my argument?

By default, Perinci::Sub::Complete's complete_arg_val() can employ some heuristics to complete argument values, e.g. from the in clause or max and min:

 $SPEC{set_ticket_status} = {
     v => 1.1,
     args => {
         ticket_id => { ... },
         status => {
             schema => ['str*', in => [qw/new open stalled resolved rejected/],
         },
     },
 }

But if you want to supply custom completion, the Rinci::function specification allows specifying a completion property for your argument, for example:

 use Complete::Util qw(complete_array_elem);
 $SPEC{del_user} = {
     v => 1.1,
     args => {
         username => {
             schema => 'str*',
             req => 1,
             pos => 0,
             completion => sub {
                 my %args = @_;

                 # get list of users from database or whatever
                 my @users = ...;
                 complete_array_elem(array=>\@users, word=>$args{word});
             },
         },
         ...
     },
 };

You can use completion your command-line program:

 % del-user --username <tab>
 % del-user <tab> ; # since the 'username' argument has pos=0

My custom completion does not work, how do I debug it?

Completion works by the shell invoking our (the same) program with COMP_LINE and COMP_POINT environment variables. You can do something like this to see debugging information:

 % COMP_LINE='myprog --arg x' COMP_POINT=13 PERL5OPT=-MLog::Any::App TRACE=1 myprog --arg x

My application is OO?

This framework is currently non-OO and function-centric. There are already several OO-based command-line frameworks on CPAN.

SEE ALSO

Perinci::CmdLine::Manual

HOMEPAGE

Please visit the project's homepage at https://metacpan.org/release/Perinci-CmdLine-Lite.

SOURCE

Source repository is at https://github.com/perlancar/perl-Perinci-CmdLine-Lite.

BUGS

Please report any bugs or feature requests on the bugtracker website https://rt.cpan.org/Public/Dist/Display.html?Name=Perinci-CmdLine-Lite

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.

AUTHOR

perlancar <perlancar@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2014 by perlancar@cpan.org.

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