[Moose-commits] r7620 - MooseX-Role-Cmd/lib/MooseX/Role
isillitoe at code2.0beta.co.uk
isillitoe at code2.0beta.co.uk
Thu Feb 12 13:40:38 GMT 2009
Author: isillitoe
Date: 2009-02-12 05:40:37 -0800 (Thu, 12 Feb 2009)
New Revision: 7620
Modified:
MooseX-Role-Cmd/lib/MooseX/Role/Cmd.pm
Log:
Changes to documentation (mainly additions)
cmd_args()
- use get_all_attributes() to allow for inherited attributes
- possibly breaks compatibility if mixing with other roles but pretty useful
e.g. using inheritance to provide different usage cases for executables
_attr_name_to_cmd_options()
- Changed to _attr_to_cmd_options (i.e. attribute not attribute name) to provide more flexibility
Modified: MooseX-Role-Cmd/lib/MooseX/Role/Cmd.pm
===================================================================
--- MooseX-Role-Cmd/lib/MooseX/Role/Cmd.pm 2009-02-12 12:50:53 UTC (rev 7619)
+++ MooseX-Role-Cmd/lib/MooseX/Role/Cmd.pm 2009-02-12 13:40:37 UTC (rev 7620)
@@ -19,9 +19,6 @@
package Cmd::Perl;
- use strict;
- use warnings;
-
use Moose;
with 'MooseX::Role::Cmd';
@@ -37,7 +34,9 @@
use Cmd::Perl;
my $perl = Cmd::Perl->new(e => q{'print join ", ", @ARGV'});
+
print $perl->run(qw/foo bar baz/);
+
# prints the STDOUT captured from running:
# perl -e 'print join ", ", @ARGV' foo bar baz
@@ -47,6 +46,111 @@
command-line wrapper modules. It automatically maps L<Moose> objects into
command strings which are passed to L<IPC::Cmd>.
+=head2 Setting the executable
+
+By default the name of the binary executable is taken from the last part of the class name
+(in lower case). The path is set during the L<run> method by scanning through your current
+PATH for the given executable (see also the 'can_run' function from L<IPC::Cmd>)
+
+ package MyApp::Commands::Scanner;
+ use Moose;
+ with 'MooseX::Role::Cmd';
+
+ $cmd = MyApp::Commands::Scanner->new();
+ $cmd->bin_name
+ # /path/to/scanner
+
+If this default behaviour doesn't suit your application then you can override the L<build_bin_name>
+subroutine to explicitly set the executable name
+
+ sub build_bin_name { 'scanner.exe' }
+ # /path/to/scanner.exe
+
+Or you could explicitly set the path with
+
+ sub build_bin_name { '/only/use/this/path/scanner.exe' }
+ # /only/use/this/path/scanner.exe
+
+=head2 How attributes are mapped to parameters
+
+The attributes of the module consuming this role map directly to the parameters passed
+to the executable. There are a couple of things to note about the default behaviour
+governing the way these attributes are mapped.
+
+=over 8
+
+=item Single character attributes are prefixed with '-'
+
+=item Multiple character attributes are prefixed with '--'
+
+=item Boolean attributes are treated as flags (no values)
+
+=item Non-boolean attributes are treated as parameters (with values)
+
+=item Attributes with undefined values will be ignored
+
+=back
+
+These points are illustrated by the following attributes (in the same order as list above)
+
+ package MyApp::Commands::Scanner;
+ use Moose;
+ with 'MooseX::Role::Cmd';
+
+ has 'i' => ( is => 'rw', isa => 'Str', default => 'input.txt' );
+ has 'out' => ( is => 'rw', isa => 'Str', default => 'output.txt' );
+ has 'verbose' => ( is => 'rw', isa => 'Bool', default => 1 );
+ has 'level' => ( is => 'rw', isa => 'Int', default => 5 );
+ has 'option' => ( is => 'rw', isa => 'Str' );
+
+ # results in:
+ # /path/to/scanner -i input.txt --out output.txt --verbose --level 5
+
+=head2 Changing names of parameters
+
+It's possible that the parameters your system command expects do not adhere to this
+naming scheme. In this case you can use the 'CmdOpt' trait which allows you to
+specify exactly how you want the parameter to appear on the command line.
+
+ has 'option' => ( isa => 'Bool' );
+ # --option
+
+=head3 cmdopt_prefix
+
+This lets you override the prefix used for the option (for example to use the short
+form of multi-character options).
+
+ has 'option' => ( traits => [ 'CmdOpt' ],
+ isa => 'Bool',
+ cmdopt_prefix => '-'
+ );
+ # -option
+
+=head3 cmdopt_name
+
+This lets you completely override the option name with whatever string you want
+
+ has 'option' => ( traits => [ 'CmdOpt' ],
+ isa => 'Bool',
+ cmdopt_name => '+foo'
+ );
+ # +foo
+
+=head3 cmdopt_env
+
+This will set an environment variable with the attribute name/value rather than pass
+it along as a command line param
+
+ has 'home_dir' => ( traits => [ 'CmdOpt' ],
+ isa => 'Str',
+ cmdopt_env => 'APP_HOME'
+ default => '/my/app/home'
+ );
+
+ # ENV{APP_HOME} = /my/app/home
+
+See L<MooseX::Role::Cmd::Meta::Attribute::Trait>
+
=head1 ATTRIBUTES
=head2 $cmd->bin_name
@@ -79,11 +183,12 @@
has 'stderr' => ( isa => 'ArrayRef', is => 'rw' );
+
no Moose;
=head1 METHODS
-=head2 my $bin_name = $cmd->build_bin_name
+=head2 $bin_name = $cmd->build_bin_name
Builds the default string for the command name based on the class name.
@@ -99,28 +204,14 @@
return lc( ( split '::', $class )[-1] ); ## no critic
}
-=head2 my @stdout = $cmd->run(@args);
+=head2 @stdout = $cmd->run(@args);
Builds the command string and runs it based on the objects current attribute
settings. This will treat all the attributes defined in your class as flags
to be passed to the command.
-Suppose the following setup:
+B<NOTE:> All quoting issues are left to be solved by the user.
- has 'in' => (isa => 'Str', is => 'rw')
- has 'out' => (isa => 'Str', is => 'rw');
-
- # ...
-
- $cmd->in('foo');
- $cmd->out('bar');
-
-The command will be invoked as:
-
- cmd -in foo -out bar
-
-All quoting issues are left to be solved by the user.
-
=cut
sub run {
@@ -135,6 +226,7 @@
# build full list of cmd args from attrs
@args = $self->cmd_args( @args );
+ #warn "CMD: " . $full_path . " " . join (" ", map { "'$_'" } @args );
my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
IPC::Cmd::run( command => [ $full_path, @args ] );
@@ -158,24 +250,25 @@
# exclude this role's attributes from the flag list
# could use custom metaclasses and introspection, but this will do for now
- my %non_flag = map { $_ => 1 } __PACKAGE__->meta->get_attribute_list;
- my @flag_attrs = grep { !$non_flag{$_} } $self->meta->get_attribute_list;
+ my %non_flag = map { $_ => 1 } __PACKAGE__->meta->get_attribute_list;
+ my @flag_attrs = grep { !$non_flag{$_->name} } $self->meta->get_all_attributes;
#####
# IS: 2008/10/15
# Changed the following to make a start on the suggestion above...
#####
#my @flags = map { ( "-$_" => $self->$_ ) } @flag_attrs;
- my @flags = map { ( $self->_attr_name_to_cmd_options( $_ ) ) } @flag_attrs;
+ my @flags = map { ( $self->_attr_to_cmd_options( $_ ) ) } @flag_attrs;
my @args = ( @flags, @extra_args );
return wantarray ? @args : \@args;
}
+
=head1 PRIVATE METHODS
-=head2 _attr_name_to_cmd_options
+=head2 _attr_to_cmd_options
Returns an array (or array reference) of command options that correspond
to the given attribute name. This essentially provides the following
@@ -212,15 +305,17 @@
cmdopt_env => 'APP_HOME'
default => '/my/app/home'
);
-
+
# $ENV{APP_HOME} = /my/app/home
+Don't consider attributes with undef values
+
=cut
-sub _attr_name_to_cmd_options {
- my ( $self, $attr_name ) = @_;
+sub _attr_to_cmd_options {
+ my ( $self, $attr ) = @_;
- my $attr = $self->meta->get_attribute( $attr_name );
+ my $attr_name = $attr->name;
# decide the default settings
my $opt_prefix = length( $attr_name ) == 1 ? '-' : '--';
@@ -239,10 +334,11 @@
# environment vars not used as params
return;
}
-
+
if ($attr->has_cmdopt_prefix) {
$opt_prefix = $attr->cmdopt_prefix;
}
+
if ($attr->has_cmdopt_name) {
$opt_prefix = ''; # name overrides prefix
$opt_name = $attr->cmdopt_name;
More information about the Moose-commits
mailing list