#!/usr/bin/perl # workaround for dzil package runpm; BEGIN { $runpm::VERSION = '0.36'; } use 5.010; use strict; use warnings; use Getopt::Long; use Sub::Spec::CmdLine qw(run); my %opts = ( library => [], ); Getopt::Long::Configure('pass_through', 'no_permute'); GetOptions( 'library|I=s' => $opts{library}, 'help' => \$opts{help}, ); if ($opts{help} || !@ARGV) { print <<USAGE; Usage: $0 -h|--help $0 [options] <Perl::Module::Name> -l $0 [options] <Perl::Module::Name> <subname> [--help | [subargs]] Options: -I LIB Add LIB to Perl search dir (a la Perl's -I) USAGE exit 0; } for my $dir (@{ $opts{library} }) { require lib; lib->import($dir) } my $module = shift @ARGV; my $modulep = $module; $modulep =~ s!::!/!g; $modulep .= ".pm"; eval { require $modulep }; die $@ if $@; my %subs; { no strict 'refs'; %subs = %{"$module\::SPEC"} or die "Sorry, no spec found in Perl module $module\n"; } run( module => $module, load => 0, cmd => $ENV{PERL_RUNPM_PROG} // "$0 $module", subcommands => { map { $_ => {} } keys %subs, }, dash_to_underscore => 1, ); =pod =head1 NAME runpm - Run Perl module as a command-line application =head1 VERSION version 0.36 =head1 SYNOPSIS From command-line: % runpm Foo::Bar Or save this in C<foobar> somewhere in PATH: #!/bin/bash export PERL_RUNPM_PROG=`basename $0` runpm Foo::Bar You can now do: % foobar --help; # show help % foobar --list; # list all subcommands, which are subroutines in Foo::Bar % foobar sub1 --arg1 ... --arg2 ...; # execute sub1 % foobar --yaml sub1 ...; # execute sub1 and return output as YAML % foobar --help sub1; # show help usage for sub1 % foobar --version % complete -C foobar foobar % foobar <TAB>; # tab completion will now work =head1 DESCRIPTION One of the lazy ways of writing a command-line application is by not writing it. You just write your module functions, following a few conventions outlined in L<Sub::Spec>. Later you can "export" your module as a command-line application with B<runpm> and get these features for free: options parsing, --help (including for each subroutine), output formatting, even bash completion. To make bash completion work, you need to install L<Sub::Spec::BashComplete> first. B<runpm> calls L<Sub::Spec::CmdLine>'s run() under the hood. Currently runpm offers little options, it's just a quick way to run your module. For more customization (e.g. only export some functions, rename subcommands, run two or more modules, etc), write a wrapper script for run() directly. =head1 SEE ALSO L<Sub::Spec> L<Sub::Spec::CmdLine> A few applications using Sub::Spec::CmdLine: L<File::RsyBak> (the B<rsybak> command), L<Git::Bunch> (the B<gitbunch> command). =head1 AUTHOR Steven Haryanto <stevenharyanto@gmail.com> =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 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 __END__ # ABSTRACT: Run Perl module as a command-line application