NAME
    Perinci::CmdLine::Server - Create CLI application instance and functions
    to access it

VERSION
    This document describes version 0.04 of Perinci::CmdLine::Server (from
    Perl distribution Perinci-CmdLine-Server), released on 2014-11-07.

SYNOPSIS
  Running the server
    From your Perinci::Access::HTTP::Server-based PSGI application:

     use Perinci::CmdLine::Server qw(create_cmdline_server);
     create_cmdline_server(
         name         => 'app1',
         cmdline_args => {
             url         => '/Some/Module/some_func',
             log_any_app => 0,
         },
     );

    Or, shortcut for simple cases:

     use Perinci::CmdLine::Server -app1 => '/Some/Module/some_func';

    Or, for testing using peri-htserve:

     % peri-htserve --gepok-unix-sockets /tmp/app1.sock \
         -MPerinci::CmdLine::Server=-app1,/Some/Module/some_func \
         Perinci::CmdLine::Server::app::app1,noload

  Using the server for completion
     # foo-complete
     #!perl
     use HTTP::Tiny::UNIX;
     use JSON;

     my $hres = HTTP::Tiny::UNIX->new->post_form(
        'http:/tmp/app1.sock//api/Perinci/CmdLine/Server/app/app1/complete_cmdline',
        {
            cmdline     => $ENV{COMP_LINE},
            point       => $ENV{COMP_POINT},
            '-riap-fmt' => 'json',
        },
     );
     my $rres = decode_json($hres->{content});
     print $rres->[2];

    Activate bash tab completion:

     % chmod +x foo-complete
     % complete -C foo-complete foo
     % foo <Tab>

    Now foo will be tab-completed using Rinci specification from
    "Some::Module"'s "some_func".

DESCRIPTION
    Currently, Perinci::CmdLine-based CLI applications have a perceptible
    startup overhead (between 0.15-0.35s or even more, depending on your
    hardware, those numbers are for 2011-2013 PC/laptop hardware). Some of
    the cause of the overhead is subroutine wrapping (see
    Perinci::Sub::Wrapper) which also involves compilation of Sah schemas
    (see Data::Sah), all of which are necessary for the convenience of using
    Rinci metadata to specify aspects of your functions.

    This level of overhead is a bit annoying when we are doing shell tab
    completion (Perinci::CmdLine-based applications call themselves for
    doing tab completion, e.g. through bash's "complete -C progname
    progname" mechanism). Ideally, tab completion should take no longer than
    0.05-0.1s to feel instantaneous.

    One (temporary?) solution to this annoyance is to start a daemon that
    listens to Riap requests (either through Unix domain sockets or TCP/IP).
    This way, the completion external command can just be a lightweight HTTP
    client which asks the server for the completion and displays the result
    to STDOUT for bash (this only requires, e.g. HTTP::Tiny::Unix +
    Complete::Bash).

    In the future, other functionalities aside from completion can also be
    "off-loaded" to the server side to make the CLI program lighter and
    quicker to start. This might require a refactoring of Perinci::CmdLine
    codebase so it's more "stateless" and reusable/safer for multiple
    requests (perhaps will be made non-OO in the core so it's clear what
    states are being passed?)

    In the future, Perinci::CmdLine can also be configured to automatically
    start a daemon after the first run (and retire/kill the daemon after
    being idle for, say, 30 minute or an hour).

  How does it work?
    In your Perinci::Access::HTTP::Server-based PSGI application:

     use Perinci::CmdLine::Server qw(create_cmdline_server);
     create_cmdline_server(
         name         => 'app1',
         cmdline_args => {
             url         => '/Some/Module/some_func',
             log_any_app => 0,
         },
     );

    This will create an instance of Perinci::CmdLine object (the
    "cmdline_args" argument will be fed to the constructor). It will also
    create a Perl package dynamically (the default is
    "Perinci::CmdLine::Server::app::" + application name specified in "name"
    argument). The package will contain several functions along with their
    Rinci metadata. The functions can then be accessed over Riap protocol.
    So far, the only function available is: "complete_cmdline". You can use
    it to request command-line completion. The Perinci::CmdLine object will
    persist as long as the process lives. You can of course start several
    applications.

  Caveats
    Leaving daemons around could give rise to some security and
    resource-usage issues. It is ideal in situations where you already have
    a daemon for other purposes (for example, in Spanel there is already an
    API daemon service running; the command-line client uses this daemon to
    request for tab completion).

    Some code which normally runs on the client-side will now run on the
    server-side. For example, the "custom_completer" and
    "custom_arg_completer" code. You have to make sure that authentication
    and authorization issues are handled.

FUNCTIONS
  create_cmdline_server(%args) -> any
    Create Perinci::CmdLine object and some functions to access it in a Perl
    package.

    Currently the functions created are:

     complete_cmdline

    Arguments ('*' denotes required arguments):

    *   cmdline => *obj*

        A Perinci::CmdLine object.

        If you set this argument, you're passing an existing object.
        Otherwise, a new Perinci::CmdLine object will be created (with
        "cmdline_args" passed to its constructor).

        Note: it is desirable that your existing Perinci::CmdLine object has
        its attribute exit => 0 :-) Otherwise, it will exit after the first
        run().

    *   cmdline_args => *hash* (default: {})

        Arguments to be fed to Perinci::CmdLine constructor.

        If you specify this argument and not "cmdline", a new
        Perinci::CmdLine object will be created.

    *   name* => *str*

        Application name.

        This function stores the created functions in a hash, keyed by name.
        If you create an application with the same name as previously
        created, the previous instance will be replaced.

    *   package => *str*

        Where to put the functions to access the object.

        The default is "Perinci::CmdLine::Server::app::" + "<name>". But you
        can put it somewhere else. The functions will be installed here.

    Return value:

     (any)

SEE ALSO
    Perinci::CmdLine

    Perinci::Access::HTTP::Server

HOMEPAGE
    Please visit the project's homepage at
    <https://metacpan.org/release/Perinci-CmdLine-Server>.

SOURCE
    Source repository is at
    <https://github.com/perlancar/perl-Perinci-CmdLine-Server>.

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

    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.

