* MooseX::Getopt: New method get_options_from_argv.
[gitmo/MooseX-Getopt.git] / lib / MooseX / Getopt.pm
CommitLineData
5dac17c3 1
2package MooseX::Getopt;
3use Moose::Role;
4
550da402 5use Moose::Util::TypeConstraints;
6
8034a232 7use MooseX::Getopt::OptionTypeMap;
550da402 8
c6c1f628 9use MooseX::Getopt::Session;
550da402 10
5dac17c3 11use MooseX::Getopt::Meta::Attribute;
0f8232b6 12use MooseX::Getopt::Meta::Attribute::NoGetopt;
5dac17c3 13
75a6449b 14
e4ab19b9 15our $VERSION = '0.15';
8034a232 16our $AUTHORITY = 'cpan:STEVAN';
17
550da402 18
c6c1f628 19use constant _default_getopt_session => 'MooseX::Getopt::Session';
20
21
c6c1f628 22has getopt => (
550da402 23 is => 'rw',
c6c1f628 24 isa => 'MooseX::Getopt::Session',
550da402 25 metaclass => 'NoGetopt',
ac2073c8 26 handles => [ 'ARGV', 'extra_argv' ],
550da402 27);
3899e5df 28
ee211848 29
c6c1f628 30sub new_with_options {
31 my $class = shift;
6bb4cb66 32
4848d3bb 33 return $class->new( $class->get_options_from_argv(@_) );
34};
35
36
37sub get_options_from_argv {
38 my $class = shift;
39
40 Moose->throw_error("Single parameters to get_options_from_argv() must be a HASH ref")
c6c1f628 41 if ref $_[0] and ref $_ ne 'HASH';
75a6449b 42
c6c1f628 43 my %params = ( @_ == 1 ? %{ $_[0] } : @_ );
6bb4cb66 44
c6c1f628 45 my $getopt = defined $params{getopt}
46 ? $params{getopt}
c7ecf9ea 47 : $class->_default_getopt_session->new(
ac2073c8 48 classes_filter => sub { $_ eq $class },
49 params => \%params,
50 );
ee211848 51
4848d3bb 52 my %new_params = (
053fa19e 53 %{ $getopt->params }, # params from session object
54 %params, # explicit params to ->new
ac2073c8 55 %{ $getopt->options }, # params from CLI
4848d3bb 56 getopt => $getopt,
ee211848 57 );
4848d3bb 58
59 return %new_params;
c6c1f628 60};
0e715336 61
0e715336 62
bff3807b 63sub _compute_getopt_attrs {
64 my $class = shift;
c6c1f628 65
66 return grep {
67 $_->does('MooseX::Getopt::Meta::Attribute::Trait')
bff3807b 68 or
69 $_->name !~ /^_/
adbe3e57 70 } grep {
71 !$_->does('MooseX::Getopt::Meta::Attribute::Trait::NoGetopt')
c6c1f628 72 } $class->meta->compute_all_applicable_attributes;
73};
4ad81caf 74
5dac17c3 75
8034a232 76no Moose::Role; 1;
5dac17c3 77
78__END__
79
80=pod
81
82=head1 NAME
83
8034a232 84MooseX::Getopt - A Moose role for processing command line options
5dac17c3 85
86=head1 SYNOPSIS
87
4e086633 88 ## In your class
5dac17c3 89 package My::App;
90 use Moose;
4e086633 91
5dac17c3 92 with 'MooseX::Getopt';
4e086633 93
5dac17c3 94 has 'out' => (is => 'rw', isa => 'Str', required => 1);
95 has 'in' => (is => 'rw', isa => 'Str', required => 1);
4e086633 96
5dac17c3 97 # ... rest of the class here
4e086633 98
5dac17c3 99 ## in your script
100 #!/usr/bin/perl
4e086633 101
5dac17c3 102 use My::App;
4e086633 103
5dac17c3 104 my $app = My::App->new_with_options();
105 # ... rest of the script here
4e086633 106
5dac17c3 107 ## on the command line
108 % perl my_app_script.pl -in file.input -out file.dump
109
110=head1 DESCRIPTION
111
4e086633 112This is a role which provides an alternate constructor for creating
113objects using parameters passed in from the command line.
8034a232 114
4e086633 115This module attempts to DWIM as much as possible with the command line
116params by introspecting your class's attributes. It will use the name
117of your attribute as the command line option, and if there is a type
8034a232 118constraint defined, it will configure Getopt::Long to handle the option
3899e5df 119accordingly.
120
2814de27 121You can use the trait L<MooseX::Getopt::Meta::Attribute::Trait> or the
122attribute metaclass L<MooseX::Getopt::Meta::Attribute> to get non-default
123commandline option names and aliases.
3899e5df 124
2814de27 125You can use the trait L<MooseX::Getopt::Meta::Attribute::Trait::NoGetopt>
126or the attribute metaclass L<MooseX::Getopt::Meta::Attribute::NoGetopt>
0f8232b6 127to have C<MooseX::Getopt> ignore your attribute in the commandline options.
128
3899e5df 129By default, attributes which start with an underscore are not given
130commandline argument support, unless the attribute's metaclass is set
3d9a716d 131to L<MooseX::Getopt::Meta::Attribute>. If you don't want you accessors
132to have the leading underscore in thier name, you can do this:
133
134 # for read/write attributes
135 has '_foo' => (accessor => 'foo', ...);
4e086633 136
3d9a716d 137 # or for read-only attributes
4e086633 138 has '_bar' => (reader => 'bar', ...);
3d9a716d 139
4e086633 140This will mean that Getopt will not handle a --foo param, but your
141code can still call the C<foo> method.
8034a232 142
ee69c4ba 143If your class also uses a configfile-loading role based on
144L<MooseX::ConfigFromFile>, such as L<MooseX::SimpleConfig>,
145L<MooseX::Getopt>'s C<new_with_options> will load the configfile
b4a79051 146specified by the C<--configfile> option (or the default you've
147given for the configfile attribute) for you.
148
149Options specified in multiple places follow the following
150precendence order: commandline overrides configfile, which
151overrides explicit new_with_options parameters.
ee69c4ba 152
8034a232 153=head2 Supported Type Constraints
154
155=over 4
156
157=item I<Bool>
158
4e086633 159A I<Bool> type constraint is set up as a boolean option with
8034a232 160Getopt::Long. So that this attribute description:
161
162 has 'verbose' => (is => 'rw', isa => 'Bool');
163
4e086633 164would translate into C<verbose!> as a Getopt::Long option descriptor,
8034a232 165which would enable the following command line options:
166
167 % my_script.pl --verbose
4e086633 168 % my_script.pl --noverbose
169
8034a232 170=item I<Int>, I<Float>, I<Str>
171
4e086633 172These type constraints are set up as properly typed options with
8034a232 173Getopt::Long, using the C<=i>, C<=f> and C<=s> modifiers as appropriate.
174
175=item I<ArrayRef>
176
177An I<ArrayRef> type constraint is set up as a multiple value option
178in Getopt::Long. So that this attribute description:
179
180 has 'include' => (
4e086633 181 is => 'rw',
182 isa => 'ArrayRef',
8034a232 183 default => sub { [] }
184 );
185
4e086633 186would translate into C<includes=s@> as a Getopt::Long option descriptor,
8034a232 187which would enable the following command line options:
188
189 % my_script.pl --include /usr/lib --include /usr/local/lib
190
191=item I<HashRef>
192
193A I<HashRef> type constraint is set up as a hash value option
194in Getopt::Long. So that this attribute description:
195
196 has 'define' => (
4e086633 197 is => 'rw',
198 isa => 'HashRef',
8034a232 199 default => sub { {} }
200 );
201
4e086633 202would translate into C<define=s%> as a Getopt::Long option descriptor,
8034a232 203which would enable the following command line options:
204
205 % my_script.pl --define os=linux --define vendor=debian
206
207=back
208
209=head2 Custom Type Constraints
210
4e086633 211It is possible to create custom type constraint to option spec
8034a232 212mappings if you need them. The process is fairly simple (but a
4e086633 213little verbose maybe). First you create a custom subtype, like
8034a232 214so:
215
216 subtype 'ArrayOfInts'
217 => as 'ArrayRef'
218 => where { scalar (grep { looks_like_number($_) } @$_) };
219
220Then you register the mapping, like so:
221
222 MooseX::Getopt::OptionTypeMap->add_option_type_to_map(
223 'ArrayOfInts' => '=i@'
224 );
225
4e086633 226Now any attribute declarations using this type constraint will
8034a232 227get the custom option spec. So that, this:
228
229 has 'nums' => (
230 is => 'ro',
231 isa => 'ArrayOfInts',
232 default => sub { [0] }
233 );
234
235Will translate to the following on the command line:
236
237 % my_script.pl --nums 5 --nums 88 --nums 199
238
4e086633 239This example is fairly trivial, but more complex validations are
8034a232 240easily possible with a little creativity. The trick is balancing
241the type constraint validations with the Getopt::Long validations.
242
243Better examples are certainly welcome :)
244
f63e6310 245=head2 Inferred Type Constraints
246
247If you define a custom subtype which is a subtype of one of the
248standard L</Supported Type Constraints> above, and do not explicitly
249provide custom support as in L</Custom Type Constraints> above,
250MooseX::Getopt will treat it like the parent type for Getopt
251purposes.
252
253For example, if you had the same custom C<ArrayOfInts> subtype
254from the examples above, but did not add a new custom option
255type for it to the C<OptionTypeMap>, it would be treated just
256like a normal C<ArrayRef> type for Getopt purposes (that is,
257C<=s@>).
258
ac2073c8 259=head2 Session
260
261L<MooseX::Getopt> can handle more than one class which contain
262attributes filled from CLI. In this case, you need to use explicite
263L<MooseX::Getopt::Session> object and then the Getopt attributes will be
264searched in any class which does L<MooseX::Getopt>.
265
266 package My::App;
267 use Moose;
268 with 'MooseX::Getopt';
269 has 'send' => (is => 'rw', predicate => 'has_send');
270
271 package My::App::Send;
272 use Moose;
273 with 'MooseX::Getopt';
274 has 'to' => (is => 'rw', isa => 'Str', default => 'localhost');
275 sub send { my $self = shift; warn "Sending mail to ", $self->to; }
276
277 # ... rest of the class here
278
279 ## in your script
280 #!/usr/bin/perl
281
282 my $getopt = MooseX::Getopt::Session->new;
283
284 my $app = My::App->new_with_options( getopt => $getopt );
285 if ($app->has_send) {
286 # Use the same command line
287 my $sender = My::App::Send->new_with_options( getopt => $getopt );
288 $sender->send;
289 }
290 # ... rest of the script here
291
292 ## on the command line
293 % perl my_app_script.pl --send --to server.example.net
294
5dac17c3 295=head1 METHODS
296
297=over 4
298
299=item B<new_with_options (%params)>
300
4e086633 301This method will take a set of default C<%params> and then collect
8034a232 302params from the command line (possibly overriding those in C<%params>)
303and then return a newly constructed object.
304
f63e6310 305If L<Getopt::Long/GetOptions> fails (due to invalid arguments),
306C<new_with_options> will throw an exception.
307
fad5da09 308If you have L<Getopt::Long::Descriptive> a the C<usage> param is also passed to
309C<new>.
310
4848d3bb 311=item B<get_options_from_argv (%params)>
312
313This method returns the list of parameters collected from command line
314without creating the new object.
315
3899e5df 316=item B<ARGV>
317
ac2073c8 318This accessor contains a reference to a copy of the C<@ARGV> array as it
319originally existed at the time of C<new_with_options>.
320
321The C<ARGV> is delegated from L<MooseX::Getopt::Session> object.
f63e6310 322
323=item B<extra_argv>
324
325This accessor contains an arrayref of leftover C<@ARGV> elements that
326L<Getopt::Long> did not parse. Note that the real C<@ARGV> is left
327un-mangled.
3899e5df 328
ac2073c8 329The C<extra_argv> is delegated from L<MooseX::Getopt::Session> object.
330
331=item B<getopt>
332
333This accessor contains a L<MooseX::Getopt::Session> object. This object can
334be shared between more than one class which does L<MooseX::Getopt>. The new
335object is created by default.
336
5dac17c3 337=item B<meta>
338
8034a232 339This returns the role meta object.
340
5dac17c3 341=back
342
ac2073c8 343=head1 SEE ALSO
344
345=over 4
346
347=item L<MooseX::Getopt::Strict>
348
349=item L<MooseX::Getopt::Session>
350
351=item L<MooseX::Getopt::Parser>
352
353=back
354
5dac17c3 355=head1 BUGS
356
4e086633 357All complex software has bugs lurking in it, and this module is no
5dac17c3 358exception. If you find a bug please either email me, or add the bug
359to cpan-RT.
360
361=head1 AUTHOR
362
363Stevan Little E<lt>stevan@iinteractive.comE<gt>
364
e2911e34 365Brandon L. Black, E<lt>blblack@gmail.comE<gt>
366
630657d5 367Yuval Kogman, E<lt>nothingmuch@woobling.orgE<gt>
368
78a71ae5 369=head1 CONTRIBUTORS
370
371Ryan D Johnson, E<lt>ryan@innerfence.comE<gt>
372
ac2073c8 373Piotr Roszatycki, E<lt>dexter@cpan.orgE<gt>
374
5dac17c3 375=head1 COPYRIGHT AND LICENSE
376
adbe3e57 377Copyright 2007-2008 by Infinity Interactive, Inc.
5dac17c3 378
379L<http://www.iinteractive.com>
380
381This library is free software; you can redistribute it and/or modify
382it under the same terms as Perl itself.
383
384=cut