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');
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>. If you don't want you accessors
118 to have the leading underscore in thier name, you can do this:
120 # for read/write attributes
121 has '_foo' => (accessor => 'foo', ...);
123 # or for read-only attributes
124 has '_bar' => (reader => 'bar', ...);
126 This will mean that Getopt will not handle a --foo param, but your
127 code can still call the C<foo> method.
129 =head2 Supported Type Constraints
135 A I<Bool> type constraint is set up as a boolean option with
136 Getopt::Long. So that this attribute description:
138 has 'verbose' => (is => 'rw', isa => 'Bool');
140 would translate into C<verbose!> as a Getopt::Long option descriptor,
141 which would enable the following command line options:
143 % my_script.pl --verbose
144 % my_script.pl --noverbose
146 =item I<Int>, I<Float>, I<Str>
148 These type constraints are set up as properly typed options with
149 Getopt::Long, using the C<=i>, C<=f> and C<=s> modifiers as appropriate.
153 An I<ArrayRef> type constraint is set up as a multiple value option
154 in Getopt::Long. So that this attribute description:
159 default => sub { [] }
162 would translate into C<includes=s@> as a Getopt::Long option descriptor,
163 which would enable the following command line options:
165 % my_script.pl --include /usr/lib --include /usr/local/lib
169 A I<HashRef> type constraint is set up as a hash value option
170 in Getopt::Long. So that this attribute description:
175 default => sub { {} }
178 would translate into C<define=s%> as a Getopt::Long option descriptor,
179 which would enable the following command line options:
181 % my_script.pl --define os=linux --define vendor=debian
185 =head2 Custom Type Constraints
187 It is possible to create custom type constraint to option spec
188 mappings if you need them. The process is fairly simple (but a
189 little verbose maybe). First you create a custom subtype, like
192 subtype 'ArrayOfInts'
194 => where { scalar (grep { looks_like_number($_) } @$_) };
196 Then you register the mapping, like so:
198 MooseX::Getopt::OptionTypeMap->add_option_type_to_map(
199 'ArrayOfInts' => '=i@'
202 Now any attribute declarations using this type constraint will
203 get the custom option spec. So that, this:
207 isa => 'ArrayOfInts',
208 default => sub { [0] }
211 Will translate to the following on the command line:
213 % my_script.pl --nums 5 --nums 88 --nums 199
215 This example is fairly trivial, but more complex validations are
216 easily possible with a little creativity. The trick is balancing
217 the type constraint validations with the Getopt::Long validations.
219 Better examples are certainly welcome :)
225 =item B<new_with_options (%params)>
227 This method will take a set of default C<%params> and then collect
228 params from the command line (possibly overriding those in C<%params>)
229 and then return a newly constructed object.
233 This accessor contains a reference to a copy of the C<@ARGV> array
234 which was copied before L<Getopt::Long> mangled it, in case you want
235 to see your original options.
239 This returns the role meta object.
245 All complex software has bugs lurking in it, and this module is no
246 exception. If you find a bug please either email me, or add the bug
251 Stevan Little E<lt>stevan@iinteractive.comE<gt>
253 Brandon L. Black, E<lt>blblack@gmail.comE<gt>
255 =head1 COPYRIGHT AND LICENSE
257 Copyright 2007 by Infinity Interactive, Inc.
259 L<http://www.iinteractive.com>
261 This library is free software; you can redistribute it and/or modify
262 it under the same terms as Perl itself.