#!/usr/bin/perl use 5.010; use strict; use warnings; use Getopt::Long; use Perinci::CmdLine; our $VERSION = '0.60'; # VERSION my %opts = ( library => [], subcommands => [], ); Getopt::Long::Configure('pass_through', 'no_permute'); GetOptions( 'library|I=s' => $opts{library}, 'help|h|?' => \$opts{help}, 'subcommand|s=s' => $opts{subcommands}, ); my $me = $0; $me =~ s!.+/!!; my $oscs = $opts{subcommands}; if ($opts{help} || !@ARGV && !@$oscs) { print <<USAGE; $me - Run commands (from any Riap function) on the command-line Usage: $me --help $me [common options] <command def> [subcommand] [action] *Common options* include: '--library' ('-I') to add directory to Perl search dir (a la Perl's '-I'), can be specified multiple times. *Command def* is either a single command definition or multiple subcommands definition. To define a single command, you can specify a Riap function URL (e.g. '/Foo/Bar/func'). For multiple subcommands, you can specify a Riap package URL (e.g. '/Foo/Bar/') or a Perl module name (e.g. 'Foo::Bar'), in which case all functions in the module/package will be listed and added as subcommands. Alternatively, you can specify each subcommand separately using '--subcommand' ('-s'). For example, the command below specifies two subcommands called 'func1' and 'altname': $me -s /Foo/Bar/func1 -s "/Foo/Bar/func2 altname" *Subcommand* picks a subcommand name, required only when you specify multiple subcommands. And not required for actions like '--list' and '--version'. *action* is either '--help' to get help message on the command or subcommand, '--list' to list subcommands, '--version' to get version, or zero or more command (function) arguments. Examples: List all subcommands (functions) in a module: $me Foo::Bar -l Show usage for a subcommand (function): $me Foo::Bar func1 --help $me /Foo/Bar/func1 -h Execute a command and display the result as YAML: $me http://example.org/api/Foo/Bar/func --format=yaml --arg 12 Execute a subcommand: $me -s "/Foo/Bar/func1 sc1" -s "/Foo/Baz/func1 sc2" sc2 --arg 12 Notes: * This is just a simple generic front-end for 'Perinci::CmdLine'. For more options/customizations, use or subclass the module directly. TODO: * HTTP authentication parameters USAGE exit 0; } for my $dir (@{ $opts{library} }) { require lib; lib->import($dir) } my $cmd = Perinci::CmdLine->new; if (@ARGV && !@$oscs) { # a single URL is specified. my $url = shift @ARGV; my $type; # Perl module (Foo::Bar) is specified, change it to /Foo/Bar/ if ($url =~ /\A\w+::(?:\w+)*\z/) { $url =~ s!::!/!; $url = "/$url/"; $type = 'package'; } else { # try to find out the entity type my $res = $cmd->_pa->request(info => $url); die "Can't 'info' $url: $res->[0] - $res->[1]\n" unless $res->[0] == 200; $type = $res->[2]{type} // ''; die "Please specify URL to a function or package, not '$type': $url\n" unless $type eq 'function' || $type eq 'package'; } $cmd->url($url); $cmd->program_name("$me $url") unless defined($ENV{PERINCI_CMDLINE_PROGRAM_NAME}); if ($type eq 'package') { my $res = $cmd->_pa->request(list => $url, {detail=>1}); die "Can't 'list' $url: $res->[0] - $res->[1]\n" unless $res->[0] == 200; my $scs = {}; for my $e (@{$res->[2]}) { next unless $e->{type} eq 'function'; my $sub = $e->{uri}; $sub =~ s!.+/!!; $scs->{$sub} = { url => $e->{uri}, summary => $e->{summary}, }; } $cmd->subcommands($scs); } } elsif (@$oscs) { # one or more subcommand URLs are specified. my $scs = {}; for my $item (@$oscs) { my ($url, $name); if ($item =~ /\s/) { ($url, $name) = split /\s+/, $item, 2; } else { $url = $item; my $i = 1; my $leaf = $url; $leaf =~ s!.+/(.+)!$1!; $leaf ||= "func"; while (1) { $name = $leaf . ($i > 1 ? $i : ""); last unless $scs->{$name}; $i++; } } $scs->{$name} = {url => $url}; } $cmd->subcommands($scs); } else { die "BUG: This shouldn't be reached"; } $cmd->run; #ABSTRACT: Run commands (from any Riap function) on the command-line #PODNAME: peri-run __END__ =pod =head1 NAME peri-run - Run commands (from any Riap function) on the command-line =head1 VERSION version 0.60 =head1 SYNOPSIS Type C<peri-run --help> for more help. =head1 SEE ALSO L<Perinci::CmdLine> =head1 AUTHOR Steven Haryanto <stevenharyanto@gmail.com> =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Steven Haryanto. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut