* MooseX::Getopt::Parser::*: default config for getopt is 'default'.
[gitmo/MooseX-Getopt.git] / lib / MooseX / Getopt / Parser / Descriptive.pm
1
2 package MooseX::Getopt::Parser::Descriptive;
3
4 use Moose;
5
6 with 'MooseX::Getopt::Parser';
7
8 use MooseX::Getopt::OptionTypeMap;
9
10 use Getopt::Long::Descriptive ();
11
12
13 # Special configuration for parser
14 has config => (
15     is => 'rw',
16     isa => 'ArrayRef[Str]',
17     default => sub { [ 'default' ] },
18 );
19
20 # Format for usage description
21 has format => (
22     is => 'rw',
23     isa => 'Str',
24     default => 'usage: %c %o',
25 );
26
27 # Usage object
28 has usage => (
29     is => 'rw',
30     isa => 'Maybe[Getopt::Long::Descriptive::Usage]',
31     predicate => 'has_usage',
32 );
33
34
35 sub build_options {
36     my $self = shift;
37     my ($getopt, @attrs) = @_;
38
39     Moose->throw_error('First argument is not a MooseX::Getopt::Session')
40         unless $getopt->isa('MooseX::Getopt::Session');
41
42     my $options = $getopt->options;
43     my $new_options = {};
44
45     my $usage;
46     my (@opts, %cmd_flags_to_names);
47
48     foreach my $attr (@attrs) {
49         my $name = $attr->name;
50
51         my ($flag, @aliases) = $getopt->_get_cmd_flags_for_attr($attr);
52         my $type = $getopt->_get_cmd_type_for_attr($attr);
53
54         my $opt_string = join '|', $flag, @aliases;
55         $opt_string .= MooseX::Getopt::OptionTypeMap->get_option_type($type) if $type;
56
57         # opt_string is unmangled; parsed options key is mangled
58         $flag =~ tr/-/_/;
59         $cmd_flags_to_names{$flag} = $name;
60
61         my $doc;
62         $doc = $attr->documentation if $attr->has_documentation;
63         $doc = ' ' unless $doc;
64
65         my $is_required = !exists $options->{$name}
66                           && $attr->is_required
67                           && !$attr->has_default
68                           && !$attr->has_builder;
69
70         push @opts, [
71             $opt_string => $doc,
72             {
73                 ( $is_required ? ( required => $attr->is_required ) : () ),
74             },
75         ];
76     };
77
78     my $warnings = '';
79
80     GETOPT: {
81         local @ARGV = @{ $getopt->ARGV };
82
83         local $SIG{__WARN__} = sub {
84             $warnings .= $_[0];
85         };
86
87         eval {
88             ($new_options, $usage) = Getopt::Long::Descriptive::describe_options(
89                 $self->format, @opts, { getopt_conf => $self->config }
90             );
91         };
92         my $e = $@;
93         $warnings .= $e if $e;
94
95         my $extra_argv = \@ARGV;
96         $getopt->extra_argv( $extra_argv );
97     };
98
99     # Store usage object
100     $self->usage( $usage );
101
102     # Convert cmd_flags back to names in options hashref
103     $new_options = { map { $cmd_flags_to_names{$_} => $new_options->{$_} } keys %$new_options };
104
105     # Include old options
106     $new_options = { %$options, %$new_options };
107
108     $getopt->status( ! $warnings );
109     $getopt->options( $new_options );
110
111     die $warnings if $warnings;
112
113     return $new_options;
114 };
115
116
117 1;
118
119 __END__
120
121 =pod
122
123 =head1 NAME
124
125 MooseX::Getopt::Parser::Descriptive - A Getopt::Long::Descriptive parser for MooseX::Getopt
126
127 =head1 SYNOPSIS
128
129   use MooseX::Getopt::Parser::Descriptive;
130
131   my $parser = MooseX::Getopt::Parser::Descriptive->new(
132       format => 'Usage: %c %o',
133       config => ['pass_through']
134   );
135   my $getopt = MooseX::Getopt::Session->new( parser => $parser );
136   my $app = My::App->new( getopt => $getopt );
137
138 =head1 DESCRIPTION
139
140 This class does L<MooseX::Getopt::Parser> for L<MooseX::Getopt>.  This
141 class is used by default if L<Getopt::Long::Descriptive> module is
142 missing.
143
144 =head1 METHODS
145
146 =over 4
147
148 =item B<build_options ($getopt, @attrs)>
149
150 This method parses the CLI options with L<Getopt::Long> and returns a hashref to options list.
151
152 The first argument have to be L<MooseX::Getopt::Session> object and
153 second argument is a list of attributes which contains options.
154
155 =item B<config>
156
157 This accessor contains the arrayref to list with special configuration
158 keywords for L<Getopt::Long>.
159
160 =item B<format>
161
162 This accessor contains the string with message printed by
163 L<Getopt::Long::Descriptive> if error is occured.
164
165 =back
166
167 =head1 BUGS
168
169 All complex software has bugs lurking in it, and this module is no
170 exception. If you find a bug please either email me, or add the bug
171 to cpan-RT.
172
173 =head1 SEE ALSO
174
175 =over 4
176
177 =item L<MooseX::Getopt::Parser>
178
179 =item L<MooseX::Getopt::Parser::Default>
180
181 =item L<MooseX::Getopt::Parser::Long>
182
183 =item L<Getopt::Long::Descriptive>
184
185 =back
186
187 =head1 AUTHOR
188
189 Piotr Roszatycki, E<lt>dexter@cpan.orgE<gt>
190
191 =head1 COPYRIGHT AND LICENSE
192
193 Copyright 2007-2008 by Infinity Interactive, Inc.
194
195 L<http://www.iinteractive.com>
196
197 This library is free software; you can redistribute it and/or modify
198 it under the same terms as Perl itself.
199
200 =cut