Browse files

initial import of MooseX::App::Cmd 0.06 from CPAN

git-cpan-module:   MooseX::App::Cmd
git-cpan-version:  0.06
git-cpan-authorid: NUFFIN
  • Loading branch information...
0 parents commit 61a96a6f90be43a5101a462a011bf98514d60545 @nothingmuch nothingmuch committed with Sep 17, 2009
20 Changes
@@ -0,0 +1,20 @@
+0.06
+ - various fixes for upstream version of App::Cmd (vovkasm & brunov)
+
+0.05
+ - Various minor fixes due to upstream module changes
+
+0.04
+ - Fix failing test when no Test::Output is available.
+ No code change (lestrrat)
+
+0.03
+ - EMulate App::Cmd's new + tests (groditi)
+ - Fix for newest MX::Getopt (dann)
+ - Add the ability to handle --configfile when used with MX::ConfigFromFile (lestrrat)
+
+0.02
+ - Use MooseX::Getopt 0.09's Getopt::Long::Descriptive features
+
+0.01
+ - Initial version
20 MANIFEST
@@ -0,0 +1,20 @@
+Changes
+lib/MooseX/App/Cmd.pm
+lib/MooseX/App/Cmd/Command.pm
+Makefile.PL
+MANIFEST This list of files
+MANIFEST.SKIP
+t/00-load.t
+t/basic.t
+t/build_emulates_new.t
+t/configfile.t
+t/lib/Test/ConfigFromFile.pm
+t/lib/Test/ConfigFromFile/Command/moo.pm
+t/lib/Test/ConfigFromFile/config.yaml
+t/lib/Test/MyCmd.pm
+t/lib/Test/MyCmd/Command/bark.pm
+t/lib/Test/MyCmd/Command/frobulate.pm
+t/lib/Test/MyCmd/Command/justusage.pm
+t/lib/Test/MyCmd/Command/stock.pm
+META.yml Module meta-data (added by MakeMaker)
+SIGNATURE Public-key signature (added by MakeMaker)
44 MANIFEST.SKIP
@@ -0,0 +1,44 @@
+# Avoid version control files.
+\bRCS\b
+\bCVS\b
+\bSCCS\b
+,v$
+\B\.svn\b
+\B\.git\b
+\b_darcs\b
+
+# Avoid Makemaker generated and utility files.
+\bMANIFEST\.bak
+\bMakefile$
+\bblib/
+\bMakeMaker-\d
+\bpm_to_blib\.ts$
+\bpm_to_blib$
+\bblibdirs\.ts$ # 6.18 through 6.25 generated this
+
+# Avoid Module::Build generated and utility files.
+\bBuild$
+\b_build/
+
+# Avoid temp and backup files.
+~$
+\.old$
+\#$
+\b\.#
+\.bak$
+
+# Avoid Devel::Cover files.
+\bcover_db\b
+
+### DEFAULT MANIFEST.SKIP ENDS HERE ####
+
+\.DS_Store$
+\.sw.$
+(\w+-)*(\w+)-\d\.\d+(?:\.tar\.gz)?$
+
+\.t\.log$
+
+\.prove$
+
+# XS shit
+\.(?:bs|c|o)$
25 META.yml
@@ -0,0 +1,25 @@
+--- #YAML:1.0
+name: MooseX-App-Cmd
+version: 0.06
+abstract: ~
+author: []
+license: unknown
+distribution_type: module
+configure_requires:
+ ExtUtils::MakeMaker: 0
+build_requires:
+ ExtUtils::MakeMaker: 0
+requires:
+ App::Cmd: 0.3
+ Getopt::Long::Descriptive: 0
+ Moose: 0.86
+ MooseX::Getopt: 0.18
+ Test::use::ok: 0
+no_index:
+ directory:
+ - t
+ - inc
+generated_by: ExtUtils::MakeMaker version 6.55_02
+meta-spec:
+ url: http://module-build.sourceforge.net/META-spec-v1.4.html
+ version: 1.4
21 Makefile.PL
@@ -0,0 +1,21 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+use ExtUtils::MakeMaker;
+
+WriteMakefile(
+ NAME => 'MooseX::App::Cmd',
+ VERSION_FROM => 'lib/MooseX/App/Cmd.pm',
+ INSTALLDIRS => 'site',
+ SIGN => 1,
+ PL_FILES => {},
+ PREREQ_PM => {
+ 'Test::use::ok' => 0,
+ 'App::Cmd' => 0.3,
+ 'Moose' => 0.86,
+ 'MooseX::Getopt' => "0.18",
+ 'Getopt::Long::Descriptive' => 0,
+ },
+);
+
42 SIGNATURE
@@ -0,0 +1,42 @@
+This file contains message digests of all files listed in MANIFEST,
+signed via the Module::Signature module, version 0.55.
+
+To verify the content in this distribution, first make sure you have
+Module::Signature installed, then type:
+
+ % cpansign -v
+
+It will check each file's integrity, as well as the signature's
+validity. If "==> Signature verified OK! <==" is not displayed,
+the distribution may already have been compromised, and you should
+not run its Makefile.PL or Build.PL.
+
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+SHA1 41ab8d2fee4d3585fa96cf7271185d7981770242 Changes
+SHA1 c740fe5cba821190dc99d8baf6d996a9094bea70 MANIFEST
+SHA1 190e9058eb9c6446a1a3f3ddf15b082f1ecde152 MANIFEST.SKIP
+SHA1 9aadae0336be8de9e394efa63925c46e63ff739b META.yml
+SHA1 dc4043304d3cfc51685c6617e9168c2698494f06 Makefile.PL
+SHA1 4a94f61c2fba8d1614bc31f94a425f1eee2b7302 lib/MooseX/App/Cmd.pm
+SHA1 7e9ff06775478b85c1546427eb78446e8077f598 lib/MooseX/App/Cmd/Command.pm
+SHA1 6fd801b5eb71c402d484782b81d0f4a8379a7f36 t/00-load.t
+SHA1 f952086edd71b83111f01d208454c51bc46dbf84 t/basic.t
+SHA1 622180410b221c9662e86ffd412f949c2eba8768 t/build_emulates_new.t
+SHA1 efd7c468870324bf54d442e06ea93f83dea173f8 t/configfile.t
+SHA1 2b412bcfb4193c32081d4b100e7fafd1381ff4ad t/lib/Test/ConfigFromFile.pm
+SHA1 c9829c568c78a7e48c976dbbe390a558dcf8fcb1 t/lib/Test/ConfigFromFile/Command/moo.pm
+SHA1 29e252d185222483c06a9af5070ea76942d4f64e t/lib/Test/ConfigFromFile/config.yaml
+SHA1 7c9fb28b6e6d4095bce936e3cc4c7ec2456aca10 t/lib/Test/MyCmd.pm
+SHA1 6421073332e3f07899509b35b9973d95c58a877c t/lib/Test/MyCmd/Command/bark.pm
+SHA1 1e2fc7e3c247156590ae2e11ddd61460dff2a3cf t/lib/Test/MyCmd/Command/frobulate.pm
+SHA1 f87824cb16d7cb5e8636376363ca3043e25afdd9 t/lib/Test/MyCmd/Command/justusage.pm
+SHA1 a0e952beb3dc6eaf2de0b3aefc80fb57a1c6e409 t/lib/Test/MyCmd/Command/stock.pm
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG/MacGPG2 v2.0.12 (Darwin)
+
+iEYEARECAAYFAkqyxaMACgkQVCwRwOvSdBjFsgCgkhKvchJwNzIacW4huwdglOqD
+2T8AnAuQLW9I4Vc5ugmnAKs4CDkAaqn1
+=A1Ra
+-----END PGP SIGNATURE-----
109 lib/MooseX/App/Cmd.pm
@@ -0,0 +1,109 @@
+#!/usr/bin/perl
+
+package MooseX::App::Cmd;
+use File::Basename ();
+use Moose;
+
+extends qw(Moose::Object App::Cmd);
+
+sub BUILDARGS {
+ my $class = shift;
+ return {} unless @_;
+ return { arg => $_[0] } if @_ == 1;;
+ return { @_ };
+}
+
+sub BUILD {
+ my ($self,$args) = @_;
+
+ my $class = blessed $self;
+ my $arg0 = $0;
+ $self->{arg0} = File::Basename::basename($arg0);
+ $self->{command} = $class->_command( {} );
+ $self->{full_arg0} = $arg0;
+}
+
+our $VERSION = "0.06";
+
+__PACKAGE__;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+MooseX::App::Cmd - Mashes up L<MooseX::Getopt> and L<App::Cmd>.
+
+=head1 SYNOPSIS
+
+See L<App::Cmd/SYNOPSIS>.
+
+ package YourApp::Cmd;
+ use Moose;
+
+ extends qw(MooseX::App::Cmd);
+
+
+
+ package YourApp::Cmd::Command::blort;
+ use Moose;
+
+ extends qw(MooseX::App::Cmd::Command);
+
+ has blortex => (
+ isa => "Bool",
+ is => "rw",
+ cmd_aliases => "X",
+ documentation => "use the blortext algorithm",
+ );
+
+ has recheck => (
+ isa => "Bool",
+ is => "rw",
+ cmd_aliases => "r",
+ documentation => "recheck all results",
+ );
+
+ sub execute {
+ my ( $self, $opt, $args ) = @_;
+
+ # you may ignore $opt, it's in the attributes anyway
+
+ my $result = $self->blortex ? blortex() : blort();
+
+ recheck($result) if $self->recheck;
+
+ print $result;
+ }
+
+=head1 DESCRIPTION
+
+This module marries L<App::Cmd> with L<MooseX::Getopt>.
+
+Use it like L<App::Cmd> advises (especially see L<App::Cmd::Tutorial>),
+swapping L<App::Cmd::Command> for L<MooseX::App::Cmd::Command>.
+
+Then you can write your moose commands as moose classes, with L<MooseX::Getopt>
+defining the options for you instead of C<opt_spec> returning a
+L<Getopt::Long::Descriptive> spec.
+
+=head1 AUTHOR
+
+Yuval Kogman E<lt>nothingmuch@woobling.orgE<gt>
+
+With contributions from:
+
+=over 4
+
+=item Guillermo Roditi E<lt>groditi@cpan.orgE<gt>
+
+=back
+
+=head1 COPYRIGHT
+
+ Copyright (c) 2007-2008 Infinity Interactive, Yuval Kogman. All rights
+ reserved This program is free software; you can redistribute it and/or
+ modify it under the same terms as Perl itself.
+
+=cut
127 lib/MooseX/App/Cmd/Command.pm
@@ -0,0 +1,127 @@
+#!/usr/bin/perl
+
+package MooseX::App::Cmd::Command;
+use Moose;
+
+with qw/MooseX::Getopt/;
+
+extends qw(Moose::Object App::Cmd::Command);
+
+with qw(MooseX::Getopt);
+
+use Getopt::Long::Descriptive ();
+
+has usage => (
+ metaclass => "NoGetopt",
+ isa => "Object",
+ is => "ro",
+ required => 1,
+);
+
+has app => (
+ metaclass => "NoGetopt",
+ isa => "MooseX::App::Cmd",
+ is => "ro",
+ required => 1,
+);
+
+sub _process_args {
+ my ( $class, $args, @params ) = @_;
+ local @ARGV = @$args;
+
+ my $config_from_file;
+ if($class->meta->does_role('MooseX::ConfigFromFile')) {
+ local @ARGV = @ARGV;
+
+ my $configfile;
+ my $opt_parser = Getopt::Long::Parser->new( config => [ qw( pass_through
+ ) ] );
+ $opt_parser->getoptions( "configfile=s" => \$configfile ); if(!defined $configfile) {
+ my $cfmeta = $class->meta->find_attribute_by_name('configfile');
+ $configfile = $cfmeta->default if $cfmeta->has_default;
+ }
+
+ if(defined $configfile) {
+ $config_from_file = $class->get_config_from_file($configfile);
+ }
+ }
+
+ my %processed = $class->_parse_argv(
+ params => { argv => \@ARGV },
+ options => [ $class->_attrs_to_options( $config_from_file ) ],
+ );
+
+ return (
+ $processed{params},
+ $processed{argv},
+ usage => $processed{usage},
+ # params from CLI are also fields in MooseX::Getopt
+ %{ $config_from_file ?
+ { %$config_from_file, %{$processed{params}} } :
+ $processed{params} },
+ );
+}
+
+sub _usage_format {
+ my $class = shift;
+ $class->usage_desc();
+}
+
+__PACKAGE__;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+MooseX::App::Cmd::Command - Base class for L<MooseX::Getopt> based L<App::Cmd::Command>s.
+
+=head1 SYNOPSIS
+
+ use Moose;
+
+ extends qw(MooseX::App::Cmd::Command);
+
+ # no need to set opt_spec
+ # see MooseX::Getopt for documentation on how to specify options
+ has option_field => (
+ isa => "Str",
+ is => "rw",
+ required => 1,
+ );
+
+ sub execute {
+ my ( $self, $opts, $args ) = @_;
+
+ print $self->option_field; # also available in $opts->{option_field}
+ }
+
+=head1 DESCRIPTION
+
+This is a replacement base class for L<App::Cmd::Command> classes that includes
+L<MooseX::Getopt> and the glue to combine the two.
+
+=head1 METHODS
+
+=over 4
+
+=item _process_args
+
+Replaces L<App::Cmd::Command>'s argument processing in in favour of
+L<MooseX::Getopt> based processing.
+
+=back
+
+=head1 TODO
+
+Full support for L<Getopt::Long::Descriptive>'s abilities is not yet written.
+
+This entails taking apart the attributes and getting at the descriptions.
+
+This might actually be added upstream to L<MooseX::Getopt>, so until we decide
+here's a functional but not very helpful (to the user) version anyway.
+
+=cut
+
+
7 t/00-load.t
@@ -0,0 +1,7 @@
+#!perl -T
+
+use Test::More tests => 2;
+
+use ok 'MooseX::App::Cmd';
+use ok 'MooseX::App::Cmd::Command';
+
91 t/basic.t
@@ -0,0 +1,91 @@
+#!perl -T
+
+use strict;
+use warnings;
+
+use Test::More tests => 12;
+
+use lib 't/lib';
+
+use Test::MyCmd;
+
+my $cmd = Test::MyCmd->new;
+
+isa_ok($cmd, 'Test::MyCmd');
+
+is_deeply(
+ [ sort $cmd->command_names ],
+ [ sort qw(help --help -h -? commands frob frobulate justusage stock bark) ],
+ "got correct list of registered command names",
+);
+
+use Data::Dumper;
+Dumper $cmd->command_plugins;
+is_deeply(
+ [ sort $cmd->command_plugins ],
+ [ qw(
+ App::Cmd::Command::commands
+ App::Cmd::Command::help
+ Test::MyCmd::Command::bark
+ Test::MyCmd::Command::frobulate
+ Test::MyCmd::Command::justusage
+ Test::MyCmd::Command::stock
+ ) ],
+ "got correct list of registered command plugins",
+);
+
+{
+ local @ARGV = qw(frob --widget wname your fat face);
+ eval { $cmd->run };
+
+ is(
+ $@,
+ "the widget name is wname - your fat face\n",
+ "command died with the correct string",
+ );
+}
+
+{
+ local @ARGV = qw(justusage);
+ eval { $cmd->run };
+
+ my $error = $@;
+
+ like(
+ $error,
+ qr/^basic.t justusage/,
+ "default usage_desc is okay",
+ );
+}
+
+{
+ local @ARGV = qw(stock);
+ eval { $cmd->run };
+
+ like($@, qr/mandatory method/, "un-subclassed &run leads to death");
+}
+
+{
+ local @ARGV = qw(bark);
+ eval { $cmd->run };
+
+ like(
+ $@,
+ qr/Required option missing: wow/,
+ "required option fileld is missing",
+ );
+}
+
+SKIP: {
+ my $have_TO = eval { require Test::Output; 1; };
+ print STDERR $@;
+ skip "these tests require Test::Output", 5 unless $have_TO;
+
+ local @ARGV = qw(commands);
+
+ my ($output) = Test::Output::output_from(sub { $cmd->run });
+
+ for my $name (qw(commands frobulate justusage stock bark)) {
+ like($output, qr/^\s+\Q$name\E/sm, "$name plugin in listing");
+ }
+}
18 t/build_emulates_new.t
@@ -0,0 +1,18 @@
+#!perl -T
+
+use strict;
+use warnings;
+
+use Test::More tests => 1;
+{
+
+ package Foo;
+ use base 'App::Cmd';
+
+ package Bar;
+ use Moose;
+ extends 'MooseX::App::Cmd';
+
+}
+
+is_deeply(\%{ Bar->new }, \%{ Foo->new }, 'Internal hashes match');
45 t/configfile.t
@@ -0,0 +1,45 @@
+#!perl -T
+
+use strict;
+use warnings;
+use Test::More;
+
+BEGIN
+{
+ eval {
+ require MooseX::ConfigFromFile;
+ require YAML;
+ };
+ if ($@) {
+ plan( skip_all => "These tests require MooseX::ConfigFromFile and YAML" );
+ } else {
+ plan( tests => 2 );
+ }
+}
+
+use lib 't/lib';
+use Test::ConfigFromFile;
+
+my $cmd = Test::ConfigFromFile->new;
+
+{
+ local @ARGV = qw(moo);
+ eval { $cmd->run };
+
+ like(
+ $@,
+ qr/Required option missing/,
+ "command died with the correct string",
+ );
+}
+
+{
+ local @ARGV = qw(moo --configfile=t/lib/Test/ConfigFromFile/config.yaml);
+ eval { $cmd->run };
+
+ like(
+ $@,
+ qr/cows go moo1 moo2 moo3/,
+ "command died with the correct string",
+ );
+}
6 t/lib/Test/ConfigFromFile.pm
@@ -0,0 +1,6 @@
+package Test::ConfigFromFile;
+use Moose;
+
+extends qw(MooseX::App::Cmd);
+
+1;
34 t/lib/Test/ConfigFromFile/Command/moo.pm
@@ -0,0 +1,34 @@
+package Test::ConfigFromFile::Command::moo;
+use Moose;
+use YAML();
+
+extends qw(MooseX::App::Cmd::Command);
+with 'MooseX::ConfigFromFile';
+
+=head1 NAME
+
+Test::MyCmd::Command::moo - reads from config file
+
+=cut
+
+has 'moo' => (
+ isa => "ArrayRef",
+ is => "ro",
+ required => 1,
+ auto_deref => 1,
+ documentation => "required option field",
+);
+
+sub execute {
+ my ($self, $opt, $arg) =@_;
+
+ die ("cows go " . join(' ', $self->moo));
+}
+
+sub get_config_from_file {
+ my ($self, $file) = @_;
+
+ return YAML::LoadFile($file);
+}
+
+1;
4 t/lib/Test/ConfigFromFile/config.yaml
@@ -0,0 +1,4 @@
+moo:
+ - moo1
+ - moo2
+ - moo3
6 t/lib/Test/MyCmd.pm
@@ -0,0 +1,6 @@
+package Test::MyCmd;
+use Moose;
+
+extends qw(MooseX::App::Cmd);
+
+1;
25 t/lib/Test/MyCmd/Command/bark.pm
@@ -0,0 +1,25 @@
+package Test::MyCmd::Command::bark;
+use Moose;
+
+extends qw(MooseX::App::Cmd::Command);
+
+=head1 NAME
+
+Test::MyCmd::Command::bark - required field is used
+
+=cut
+
+has wow => (
+ isa => "Str",
+ is => "ro",
+ required => 1,
+ documentation => "required option field",
+);
+
+sub execute {
+ my ($self, $opt, $arg) =@_;
+
+ die "my dog name barks " . $self->wow . "\n";
+}
+
+1;
31 t/lib/Test/MyCmd/Command/frobulate.pm
@@ -0,0 +1,31 @@
+package Test::MyCmd::Command::frobulate;
+use Moose;
+
+extends qw(MooseX::App::Cmd::Command);
+
+sub command_names {
+ return qw(frobulate frob);
+}
+
+has foo_bar => (
+ traits => [qw(Getopt)],
+ isa => "Bool",
+ is => "ro",
+ cmd_aliases => "F",
+ documentation => "enable foo-bar subsystem",
+);
+
+has widget => (
+ traits => [qw(Getopt)],
+ isa => "Str",
+ is => "ro",
+ documentation => "set widget name",
+);
+
+sub execute {
+ my ($self, $opt, $arg) = @_;
+
+ die "the widget name is " . $self->widget . " - @$arg\n";
+}
+
+1;
18 t/lib/Test/MyCmd/Command/justusage.pm
@@ -0,0 +1,18 @@
+package Test::MyCmd::Command::justusage;
+use Moose;
+
+extends qw(MooseX::App::Cmd::Command);
+
+=head1 NAME
+
+Test::MyCmd::Command::justusage - it just dies its own usage, no matter what
+
+=cut
+
+sub execute {
+ my ($self, $opt, $arg) = @_;
+
+ die $self->usage->text;
+}
+
+1;
14 t/lib/Test/MyCmd/Command/stock.pm
@@ -0,0 +1,14 @@
+package Test::MyCmd::Command::stock;
+use Moose;
+
+extends qw(MooseX::App::Cmd::Command);
+
+=head1 NAME
+
+Test::MyCmd::Command::stock - nothing here is overridden
+
+=cut
+
+# This package exists to test all the default command plugin behaviors.
+
+1;

0 comments on commit 61a96a6

Please sign in to comment.