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