2 package MooseX::Getopt;
7 use MooseX::Getopt::OptionTypeMap;
8 use MooseX::Getopt::Meta::Attribute;
10 our $VERSION = '0.01';
11 our $AUTHORITY = 'cpan:STEVAN';
13 has ARGV => (is => 'rw', isa => 'ArrayRef');
15 sub new_with_options {
16 my ($class, %params) = @_;
18 my (@options, %name_to_init_arg);
19 foreach my $attr ($class->meta->compute_all_applicable_attributes) {
20 my $name = $attr->name;
24 if ($attr->isa('MooseX::Getopt::Meta::Attribute')) {
25 $name = $attr->cmd_flag if $attr->has_cmd_flag;
26 $aliases = $attr->cmd_aliases if $attr->has_cmd_aliases;
29 next if $name =~ /^_/;
32 $name_to_init_arg{$name} = $attr->init_arg;
34 my $opt_string = $aliases
35 ? join(q{|}, $name, @$aliases)
38 if ($attr->has_type_constraint) {
39 my $type_name = $attr->type_constraint->name;
40 if (MooseX::Getopt::OptionTypeMap->has_option_type($type_name)) {
41 $opt_string .= MooseX::Getopt::OptionTypeMap->get_option_type($type_name);
45 push @options => $opt_string;
48 my $saved_argv = [ @ARGV ];
51 GetOptions(\%options, @options);
54 #warn Dumper \@options;
55 #warn Dumper \%name_to_init_arg;
56 #warn Dumper \%options;
62 $name_to_init_arg{$_} => $options{$_}
75 MooseX::Getopt - A Moose role for processing command line options
83 with 'MooseX::Getopt';
85 has 'out' => (is => 'rw', isa => 'Str', required => 1);
86 has 'in' => (is => 'rw', isa => 'Str', required => 1);
88 # ... rest of the class here
95 my $app = My::App->new_with_options();
96 # ... rest of the script here
98 ## on the command line
99 % perl my_app_script.pl -in file.input -out file.dump
103 This is a role which provides an alternate constructor for creating
104 objects using parameters passed in from the command line.
106 This module attempts to DWIM as much as possible with the command line
107 params by introspecting your class's attributes. It will use the name
108 of your attribute as the command line option, and if there is a type
109 constraint defined, it will configure Getopt::Long to handle the option
112 You can use the attribute metaclass L<MooseX::Getopt::Meta::Attribute>
113 to get non-default commandline option names and aliases.
115 By default, attributes which start with an underscore are not given
116 commandline argument support, unless the attribute's metaclass is set
117 to L<MooseX::Getopt::Meta::Attribute>.
119 =head2 Supported Type Constraints
125 A I<Bool> type constraint is set up as a boolean option with
126 Getopt::Long. So that this attribute description:
128 has 'verbose' => (is => 'rw', isa => 'Bool');
130 would translate into C<verbose!> as a Getopt::Long option descriptor,
131 which would enable the following command line options:
133 % my_script.pl --verbose
134 % my_script.pl --noverbose
136 =item I<Int>, I<Float>, I<Str>
138 These type constraints are set up as properly typed options with
139 Getopt::Long, using the C<=i>, C<=f> and C<=s> modifiers as appropriate.
143 An I<ArrayRef> type constraint is set up as a multiple value option
144 in Getopt::Long. So that this attribute description:
149 default => sub { [] }
152 would translate into C<includes=s@> as a Getopt::Long option descriptor,
153 which would enable the following command line options:
155 % my_script.pl --include /usr/lib --include /usr/local/lib
159 A I<HashRef> type constraint is set up as a hash value option
160 in Getopt::Long. So that this attribute description:
165 default => sub { {} }
168 would translate into C<define=s%> as a Getopt::Long option descriptor,
169 which would enable the following command line options:
171 % my_script.pl --define os=linux --define vendor=debian
175 =head2 Custom Type Constraints
177 It is possible to create custom type constraint to option spec
178 mappings if you need them. The process is fairly simple (but a
179 little verbose maybe). First you create a custom subtype, like
182 subtype 'ArrayOfInts'
184 => where { scalar (grep { looks_like_number($_) } @$_) };
186 Then you register the mapping, like so:
188 MooseX::Getopt::OptionTypeMap->add_option_type_to_map(
189 'ArrayOfInts' => '=i@'
192 Now any attribute declarations using this type constraint will
193 get the custom option spec. So that, this:
197 isa => 'ArrayOfInts',
198 default => sub { [0] }
201 Will translate to the following on the command line:
203 % my_script.pl --nums 5 --nums 88 --nums 199
205 This example is fairly trivial, but more complex validations are
206 easily possible with a little creativity. The trick is balancing
207 the type constraint validations with the Getopt::Long validations.
209 Better examples are certainly welcome :)
215 =item B<new_with_options (%params)>
217 This method will take a set of default C<%params> and then collect
218 params from the command line (possibly overriding those in C<%params>)
219 and then return a newly constructed object.
223 This accessor contains a reference to a copy of the C<@ARGV> array
224 which was copied before L<Getopt::Long> mangled it, in case you want
225 to see your original options.
229 This returns the role meta object.
235 All complex software has bugs lurking in it, and this module is no
236 exception. If you find a bug please either email me, or add the bug
241 Stevan Little E<lt>stevan@iinteractive.comE<gt>
243 =head1 COPYRIGHT AND LICENSE
245 Copyright 2007 by Infinity Interactive, Inc.
247 L<http://www.iinteractive.com>
249 This library is free software; you can redistribute it and/or modify
250 it under the same terms as Perl itself.