2 package MooseX::Getopt;
7 use MooseX::Getopt::OptionTypeMap;
8 use MooseX::Getopt::Meta::Attribute;
10 our $VERSION = '0.03';
11 our $AUTHORITY = 'cpan:STEVAN';
13 has ARGV => (is => 'rw', isa => 'ArrayRef');
14 has extra_argv => (is => 'rw', isa => 'ArrayRef');
16 sub new_with_options {
17 my ($class, %params) = @_;
19 my (@options, %name_to_init_arg);
20 foreach my $attr ($class->meta->compute_all_applicable_attributes) {
21 my $name = $attr->name;
25 if ($attr->isa('MooseX::Getopt::Meta::Attribute')) {
26 $name = $attr->cmd_flag if $attr->has_cmd_flag;
27 $aliases = $attr->cmd_aliases if $attr->has_cmd_aliases;
30 next if $name =~ /^_/;
33 $name_to_init_arg{$name} = $attr->init_arg;
35 my $opt_string = $aliases
36 ? join(q{|}, $name, @$aliases)
39 if ($attr->has_type_constraint) {
40 my $type_name = $attr->type_constraint->name;
41 if (MooseX::Getopt::OptionTypeMap->has_option_type($type_name)) {
42 $opt_string .= MooseX::Getopt::OptionTypeMap->get_option_type($type_name);
46 push @options => $opt_string;
51 # Get a clean copy of the original @ARGV
52 my $argv_copy = [ @ARGV ];
55 local $SIG{__WARN__} = sub { die $_[0] };
56 Getopt::Long::GetOptions(\%options, @options);
59 # Get a copy of the Getopt::Long-mangled @ARGV
60 my $argv_mangled = [ @ARGV ];
62 # Restore the original @ARGV;
66 #warn Dumper \@options;
67 #warn Dumper \%name_to_init_arg;
68 #warn Dumper \%options;
72 extra_argv => $argv_mangled,
75 $name_to_init_arg{$_} => $options{$_}
88 MooseX::Getopt - A Moose role for processing command line options
96 with 'MooseX::Getopt';
98 has 'out' => (is => 'rw', isa => 'Str', required => 1);
99 has 'in' => (is => 'rw', isa => 'Str', required => 1);
101 # ... rest of the class here
108 my $app = My::App->new_with_options();
109 # ... rest of the script here
111 ## on the command line
112 % perl my_app_script.pl -in file.input -out file.dump
116 This is a role which provides an alternate constructor for creating
117 objects using parameters passed in from the command line.
119 This module attempts to DWIM as much as possible with the command line
120 params by introspecting your class's attributes. It will use the name
121 of your attribute as the command line option, and if there is a type
122 constraint defined, it will configure Getopt::Long to handle the option
125 You can use the attribute metaclass L<MooseX::Getopt::Meta::Attribute>
126 to get non-default commandline option names and aliases.
128 By default, attributes which start with an underscore are not given
129 commandline argument support, unless the attribute's metaclass is set
130 to L<MooseX::Getopt::Meta::Attribute>. If you don't want you accessors
131 to have the leading underscore in thier name, you can do this:
133 # for read/write attributes
134 has '_foo' => (accessor => 'foo', ...);
136 # or for read-only attributes
137 has '_bar' => (reader => 'bar', ...);
139 This will mean that Getopt will not handle a --foo param, but your
140 code can still call the C<foo> method.
142 =head2 Supported Type Constraints
148 A I<Bool> type constraint is set up as a boolean option with
149 Getopt::Long. So that this attribute description:
151 has 'verbose' => (is => 'rw', isa => 'Bool');
153 would translate into C<verbose!> as a Getopt::Long option descriptor,
154 which would enable the following command line options:
156 % my_script.pl --verbose
157 % my_script.pl --noverbose
159 =item I<Int>, I<Float>, I<Str>
161 These type constraints are set up as properly typed options with
162 Getopt::Long, using the C<=i>, C<=f> and C<=s> modifiers as appropriate.
166 An I<ArrayRef> type constraint is set up as a multiple value option
167 in Getopt::Long. So that this attribute description:
172 default => sub { [] }
175 would translate into C<includes=s@> as a Getopt::Long option descriptor,
176 which would enable the following command line options:
178 % my_script.pl --include /usr/lib --include /usr/local/lib
182 A I<HashRef> type constraint is set up as a hash value option
183 in Getopt::Long. So that this attribute description:
188 default => sub { {} }
191 would translate into C<define=s%> as a Getopt::Long option descriptor,
192 which would enable the following command line options:
194 % my_script.pl --define os=linux --define vendor=debian
198 =head2 Custom Type Constraints
200 It is possible to create custom type constraint to option spec
201 mappings if you need them. The process is fairly simple (but a
202 little verbose maybe). First you create a custom subtype, like
205 subtype 'ArrayOfInts'
207 => where { scalar (grep { looks_like_number($_) } @$_) };
209 Then you register the mapping, like so:
211 MooseX::Getopt::OptionTypeMap->add_option_type_to_map(
212 'ArrayOfInts' => '=i@'
215 Now any attribute declarations using this type constraint will
216 get the custom option spec. So that, this:
220 isa => 'ArrayOfInts',
221 default => sub { [0] }
224 Will translate to the following on the command line:
226 % my_script.pl --nums 5 --nums 88 --nums 199
228 This example is fairly trivial, but more complex validations are
229 easily possible with a little creativity. The trick is balancing
230 the type constraint validations with the Getopt::Long validations.
232 Better examples are certainly welcome :)
234 =head2 Inferred Type Constraints
236 If you define a custom subtype which is a subtype of one of the
237 standard L</Supported Type Constraints> above, and do not explicitly
238 provide custom support as in L</Custom Type Constraints> above,
239 MooseX::Getopt will treat it like the parent type for Getopt
242 For example, if you had the same custom C<ArrayOfInts> subtype
243 from the examples above, but did not add a new custom option
244 type for it to the C<OptionTypeMap>, it would be treated just
245 like a normal C<ArrayRef> type for Getopt purposes (that is,
252 =item B<new_with_options (%params)>
254 This method will take a set of default C<%params> and then collect
255 params from the command line (possibly overriding those in C<%params>)
256 and then return a newly constructed object.
258 If L<Getopt::Long/GetOptions> fails (due to invalid arguments),
259 C<new_with_options> will throw an exception.
263 This accessor contains a reference to a copy of the C<@ARGV> array
264 as it originally existed at the time of C<new_with_options>.
268 This accessor contains an arrayref of leftover C<@ARGV> elements that
269 L<Getopt::Long> did not parse. Note that the real C<@ARGV> is left
274 This returns the role meta object.
280 All complex software has bugs lurking in it, and this module is no
281 exception. If you find a bug please either email me, or add the bug
286 Stevan Little E<lt>stevan@iinteractive.comE<gt>
288 Brandon L. Black, E<lt>blblack@gmail.comE<gt>
290 =head1 COPYRIGHT AND LICENSE
292 Copyright 2007 by Infinity Interactive, Inc.
294 L<http://www.iinteractive.com>
296 This library is free software; you can redistribute it and/or modify
297 it under the same terms as Perl itself.