support scalar cmd_aliases, so that singular aliases are not so clunky to type
[gitmo/MooseX-Getopt.git] / lib / MooseX / Getopt.pm
CommitLineData
5dac17c3 1
2package MooseX::Getopt;
3use Moose::Role;
4
5use Getopt::Long;
6
8034a232 7use MooseX::Getopt::OptionTypeMap;
5dac17c3 8use MooseX::Getopt::Meta::Attribute;
9
8034a232 10our $VERSION = '0.01';
11our $AUTHORITY = 'cpan:STEVAN';
12
5dac17c3 13sub new_with_options {
14 my ($class, %params) = @_;
15
8034a232 16 my (@options, %name_to_init_arg);
5dac17c3 17 foreach my $attr ($class->meta->compute_all_applicable_attributes) {
18 my $name = $attr->name;
de75868f 19 my $aliases;
20
21 if ($attr->isa('MooseX::Getopt::Meta::Attribute')) {
22 $name = $attr->cmd_flag if $attr->has_cmd_flag;
23 $aliases = $attr->cmd_aliases if $attr->has_cmd_aliases;
8034a232 24 }
5dac17c3 25
8034a232 26 $name_to_init_arg{$name} = $attr->init_arg;
5dac17c3 27
de75868f 28 my $opt_string = $aliases
29 ? join(q{|}, $name, @$aliases)
30 : $name;
31
5dac17c3 32 if ($attr->has_type_constraint) {
33 my $type_name = $attr->type_constraint->name;
8034a232 34 if (MooseX::Getopt::OptionTypeMap->has_option_type($type_name)) {
de75868f 35 $opt_string .= MooseX::Getopt::OptionTypeMap->get_option_type($type_name);
5dac17c3 36 }
37 }
38
de75868f 39 push @options => $opt_string;
5dac17c3 40 }
41
8034a232 42 my %options;
5dac17c3 43
8034a232 44 GetOptions(\%options, @options);
5dac17c3 45
8034a232 46 #use Data::Dumper;
47 #warn Dumper \@options;
48 #warn Dumper \%name_to_init_arg;
49 #warn Dumper \%options;
50
51 $class->new(
52 %params,
53 map {
54 $name_to_init_arg{$_} => $options{$_}
55 } keys %options
56 );
5dac17c3 57}
58
8034a232 59no Moose::Role; 1;
5dac17c3 60
61__END__
62
63=pod
64
65=head1 NAME
66
8034a232 67MooseX::Getopt - A Moose role for processing command line options
5dac17c3 68
69=head1 SYNOPSIS
70
71 ## In your class
72 package My::App;
73 use Moose;
74
75 with 'MooseX::Getopt';
76
77 has 'out' => (is => 'rw', isa => 'Str', required => 1);
78 has 'in' => (is => 'rw', isa => 'Str', required => 1);
79
80 # ... rest of the class here
81
82 ## in your script
83 #!/usr/bin/perl
84
85 use My::App;
86
87 my $app = My::App->new_with_options();
88 # ... rest of the script here
89
90 ## on the command line
91 % perl my_app_script.pl -in file.input -out file.dump
92
93=head1 DESCRIPTION
94
8034a232 95This is a role which provides an alternate constructor for creating
96objects using parameters passed in from the command line.
97
98This module attempts to DWIM as much as possible with the command line
99params by introspecting your class's attributes. It will use the name
100of your attribute as the command line option, and if there is a type
101constraint defined, it will configure Getopt::Long to handle the option
102accordingly.
103
104=head2 Supported Type Constraints
105
106=over 4
107
108=item I<Bool>
109
110A I<Bool> type constraint is set up as a boolean option with
111Getopt::Long. So that this attribute description:
112
113 has 'verbose' => (is => 'rw', isa => 'Bool');
114
115would translate into C<verbose!> as a Getopt::Long option descriptor,
116which would enable the following command line options:
117
118 % my_script.pl --verbose
119 % my_script.pl --noverbose
120
121=item I<Int>, I<Float>, I<Str>
122
123These type constraints are set up as properly typed options with
124Getopt::Long, using the C<=i>, C<=f> and C<=s> modifiers as appropriate.
125
126=item I<ArrayRef>
127
128An I<ArrayRef> type constraint is set up as a multiple value option
129in Getopt::Long. So that this attribute description:
130
131 has 'include' => (
132 is => 'rw',
133 isa => 'ArrayRef',
134 default => sub { [] }
135 );
136
137would translate into C<includes=s@> as a Getopt::Long option descriptor,
138which would enable the following command line options:
139
140 % my_script.pl --include /usr/lib --include /usr/local/lib
141
142=item I<HashRef>
143
144A I<HashRef> type constraint is set up as a hash value option
145in Getopt::Long. So that this attribute description:
146
147 has 'define' => (
148 is => 'rw',
149 isa => 'HashRef',
150 default => sub { {} }
151 );
152
153would translate into C<define=s%> as a Getopt::Long option descriptor,
154which would enable the following command line options:
155
156 % my_script.pl --define os=linux --define vendor=debian
157
158=back
159
160=head2 Custom Type Constraints
161
162It is possible to create custom type constraint to option spec
163mappings if you need them. The process is fairly simple (but a
164little verbose maybe). First you create a custom subtype, like
165so:
166
167 subtype 'ArrayOfInts'
168 => as 'ArrayRef'
169 => where { scalar (grep { looks_like_number($_) } @$_) };
170
171Then you register the mapping, like so:
172
173 MooseX::Getopt::OptionTypeMap->add_option_type_to_map(
174 'ArrayOfInts' => '=i@'
175 );
176
177Now any attribute declarations using this type constraint will
178get the custom option spec. So that, this:
179
180 has 'nums' => (
181 is => 'ro',
182 isa => 'ArrayOfInts',
183 default => sub { [0] }
184 );
185
186Will translate to the following on the command line:
187
188 % my_script.pl --nums 5 --nums 88 --nums 199
189
190This example is fairly trivial, but more complex validations are
191easily possible with a little creativity. The trick is balancing
192the type constraint validations with the Getopt::Long validations.
193
194Better examples are certainly welcome :)
195
5dac17c3 196=head1 METHODS
197
198=over 4
199
200=item B<new_with_options (%params)>
201
8034a232 202This method will take a set of default C<%params> and then collect
203params from the command line (possibly overriding those in C<%params>)
204and then return a newly constructed object.
205
5dac17c3 206=item B<meta>
207
8034a232 208This returns the role meta object.
209
5dac17c3 210=back
211
212=head1 BUGS
213
214All complex software has bugs lurking in it, and this module is no
215exception. If you find a bug please either email me, or add the bug
216to cpan-RT.
217
218=head1 AUTHOR
219
220Stevan Little E<lt>stevan@iinteractive.comE<gt>
221
222=head1 COPYRIGHT AND LICENSE
223
224Copyright 2007 by Infinity Interactive, Inc.
225
226L<http://www.iinteractive.com>
227
228This library is free software; you can redistribute it and/or modify
229it under the same terms as Perl itself.
230
231=cut