#!/usr/bin/perl
use 5.010;
use strict;
our $VERSION = '0.53'; # 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.53
=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