work in progress, tests are failing, and parameterized role is not flexible enough...
[gitmo/MooseX-Getopt.git] / lib / MooseX / Getopt.pm
CommitLineData
5dac17c3 1package MooseX::Getopt;
669588e2 2# ABSTRACT: A Moose role for processing command line options
5dac17c3 3
a9e27700 4use MooseX::Role::Parameterized;
75a6449b 5
a9e27700 6parameter getopt_conf => (
7 isa => 'ArrayRef[Str]',
8 default => sub { [ 'pass_through' ] },
9);
10
11role {
12
13 my $p = shift;
14 my $getopt_conf = $p->getopt_conf;
15
16 with 'MooseX::Getopt::GLD' => { getopt_conf => $getopt_conf };
17
18};
5dac17c3 19
669588e2 20no Moose::Role;
5dac17c3 21
669588e2 221;
5dac17c3 23
24=head1 SYNOPSIS
25
4e086633 26 ## In your class
5dac17c3 27 package My::App;
28 use Moose;
4e086633 29
5dac17c3 30 with 'MooseX::Getopt';
4e086633 31
a9e27700 32 # or
33
34 with 'MooseX::Getopt' => { getopt_conf => [ 'getopt_compat', 'bundling', ... ] };
35
5dac17c3 36 has 'out' => (is => 'rw', isa => 'Str', required => 1);
37 has 'in' => (is => 'rw', isa => 'Str', required => 1);
4e086633 38
5dac17c3 39 # ... rest of the class here
4e086633 40
5dac17c3 41 ## in your script
42 #!/usr/bin/perl
4e086633 43
5dac17c3 44 use My::App;
4e086633 45
5dac17c3 46 my $app = My::App->new_with_options();
47 # ... rest of the script here
4e086633 48
5dac17c3 49 ## on the command line
50 % perl my_app_script.pl -in file.input -out file.dump
51
52=head1 DESCRIPTION
53
4e086633 54This is a role which provides an alternate constructor for creating
55objects using parameters passed in from the command line.
8034a232 56
4e086633 57This module attempts to DWIM as much as possible with the command line
58params by introspecting your class's attributes. It will use the name
59of your attribute as the command line option, and if there is a type
8034a232 60constraint defined, it will configure Getopt::Long to handle the option
3899e5df 61accordingly.
62
2814de27 63You can use the trait L<MooseX::Getopt::Meta::Attribute::Trait> or the
64attribute metaclass L<MooseX::Getopt::Meta::Attribute> to get non-default
65commandline option names and aliases.
3899e5df 66
2814de27 67You can use the trait L<MooseX::Getopt::Meta::Attribute::Trait::NoGetopt>
68or the attribute metaclass L<MooseX::Getopt::Meta::Attribute::NoGetopt>
0f8232b6 69to have C<MooseX::Getopt> ignore your attribute in the commandline options.
70
3899e5df 71By default, attributes which start with an underscore are not given
72commandline argument support, unless the attribute's metaclass is set
7f5f3d94 73to L<MooseX::Getopt::Meta::Attribute>. If you don't want your accessors
74to have the leading underscore in their name, you can do this:
3d9a716d 75
76 # for read/write attributes
77 has '_foo' => (accessor => 'foo', ...);
4e086633 78
3d9a716d 79 # or for read-only attributes
4e086633 80 has '_bar' => (reader => 'bar', ...);
3d9a716d 81
4e086633 82This will mean that Getopt will not handle a --foo param, but your
83code can still call the C<foo> method.
8034a232 84
ee69c4ba 85If your class also uses a configfile-loading role based on
86L<MooseX::ConfigFromFile>, such as L<MooseX::SimpleConfig>,
87L<MooseX::Getopt>'s C<new_with_options> will load the configfile
b4a79051 88specified by the C<--configfile> option (or the default you've
89given for the configfile attribute) for you.
90
91Options specified in multiple places follow the following
92precendence order: commandline overrides configfile, which
93overrides explicit new_with_options parameters.
ee69c4ba 94
a9e27700 95=head2 Global options
96
97This role is a parameterized role. It accepts a HashRef of parameters. For now
98there is only one configuration parameter, C<getopt_conf>. This parameter is an
99ArrayRef of strings, which are L<Getopt::Long> configuraion options (see
100"Configuring Getopt::Long" in L<Getopt::Long>). See L<SYNOPSIS> for an example.
101
8034a232 102=head2 Supported Type Constraints
103
104=over 4
105
106=item I<Bool>
107
4e086633 108A I<Bool> type constraint is set up as a boolean option with
8034a232 109Getopt::Long. So that this attribute description:
110
111 has 'verbose' => (is => 'rw', isa => 'Bool');
112
4e086633 113would translate into C<verbose!> as a Getopt::Long option descriptor,
8034a232 114which would enable the following command line options:
115
116 % my_script.pl --verbose
4e086633 117 % my_script.pl --noverbose
118
8034a232 119=item I<Int>, I<Float>, I<Str>
120
4e086633 121These type constraints are set up as properly typed options with
8034a232 122Getopt::Long, using the C<=i>, C<=f> and C<=s> modifiers as appropriate.
123
124=item I<ArrayRef>
125
126An I<ArrayRef> type constraint is set up as a multiple value option
127in Getopt::Long. So that this attribute description:
128
129 has 'include' => (
4e086633 130 is => 'rw',
131 isa => 'ArrayRef',
8034a232 132 default => sub { [] }
133 );
134
4e086633 135would translate into C<includes=s@> as a Getopt::Long option descriptor,
8034a232 136which would enable the following command line options:
137
138 % my_script.pl --include /usr/lib --include /usr/local/lib
139
140=item I<HashRef>
141
142A I<HashRef> type constraint is set up as a hash value option
143in Getopt::Long. So that this attribute description:
144
145 has 'define' => (
4e086633 146 is => 'rw',
147 isa => 'HashRef',
8034a232 148 default => sub { {} }
149 );
150
4e086633 151would translate into C<define=s%> as a Getopt::Long option descriptor,
8034a232 152which would enable the following command line options:
153
154 % my_script.pl --define os=linux --define vendor=debian
155
156=back
157
158=head2 Custom Type Constraints
159
4e086633 160It is possible to create custom type constraint to option spec
8034a232 161mappings if you need them. The process is fairly simple (but a
4e086633 162little verbose maybe). First you create a custom subtype, like
8034a232 163so:
164
165 subtype 'ArrayOfInts'
166 => as 'ArrayRef'
167 => where { scalar (grep { looks_like_number($_) } @$_) };
168
169Then you register the mapping, like so:
170
171 MooseX::Getopt::OptionTypeMap->add_option_type_to_map(
172 'ArrayOfInts' => '=i@'
173 );
174
4e086633 175Now any attribute declarations using this type constraint will
8034a232 176get the custom option spec. So that, this:
177
178 has 'nums' => (
179 is => 'ro',
180 isa => 'ArrayOfInts',
181 default => sub { [0] }
182 );
183
184Will translate to the following on the command line:
185
186 % my_script.pl --nums 5 --nums 88 --nums 199
187
4e086633 188This example is fairly trivial, but more complex validations are
8034a232 189easily possible with a little creativity. The trick is balancing
190the type constraint validations with the Getopt::Long validations.
191
192Better examples are certainly welcome :)
193
f63e6310 194=head2 Inferred Type Constraints
195
196If you define a custom subtype which is a subtype of one of the
197standard L</Supported Type Constraints> above, and do not explicitly
198provide custom support as in L</Custom Type Constraints> above,
199MooseX::Getopt will treat it like the parent type for Getopt
200purposes.
201
202For example, if you had the same custom C<ArrayOfInts> subtype
203from the examples above, but did not add a new custom option
204type for it to the C<OptionTypeMap>, it would be treated just
205like a normal C<ArrayRef> type for Getopt purposes (that is,
206C<=s@>).
207
669588e2 208=method B<new_with_options (%params)>
5dac17c3 209
4e086633 210This method will take a set of default C<%params> and then collect
8034a232 211params from the command line (possibly overriding those in C<%params>)
212and then return a newly constructed object.
213
035b1668 214The special parameter C<argv>, if specified should point to an array
0e3f178a 215reference with an array to use instead of C<@ARGV>.
216
f63e6310 217If L<Getopt::Long/GetOptions> fails (due to invalid arguments),
218C<new_with_options> will throw an exception.
219
47a89a8d 220If L<Getopt::Long::Descriptive> is installed and any of the following
2557b526 221command line params are passed, the program will exit with usage
81b19ed8 222information (and the option's state will be stored in the help_flag
223attribute). You can add descriptions for each option by including a
47a89a8d 224B<documentation> option for each attribute to document.
225
226 --?
227 --help
228 --usage
229
b766829d 230If you have L<Getopt::Long::Descriptive> the C<usage> param is also passed to
81b19ed8 231C<new> as the usage option.
fad5da09 232
669588e2 233=method B<ARGV>
3899e5df 234
235This accessor contains a reference to a copy of the C<@ARGV> array
f63e6310 236as it originally existed at the time of C<new_with_options>.
237
669588e2 238=method B<extra_argv>
f63e6310 239
240This accessor contains an arrayref of leftover C<@ARGV> elements that
241L<Getopt::Long> did not parse. Note that the real C<@ARGV> is left
242un-mangled.
3899e5df 243
81b19ed8 244=method B<usage>
245
246This accessor contains the L<Getopt::Long::Descriptive::Usage> object (if
247L<Getopt::Long::Descriptive> is used).
248
249=method B<help_flag>
250
251This accessor contains the boolean state of the --help, --usage and --?
252options (true if any of these options were passed on the command line).
253
669588e2 254=method B<meta>
5dac17c3 255
8034a232 256This returns the role meta object.
257
f3615693 258=method B<process_argv (%params)>
259
260This does most of the work of C<new_with_options>, analyzing the parameters
261and argv, except for actually calling the constructor. It returns a
262L<MooseX::Getopt::ProcessedArgv> object. C<new_with_options> uses this
263method internally, so modifying this method via subclasses/roles will affect
264C<new_with_options>.
265
5dac17c3 266=cut