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