[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