* MooseX::Getopt::Parser::Descriptive reimplemented.
[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 Getopt::Long::Descriptive;
9 use MooseX::Getopt::OptionTypeMap;
10
11 #use Smart::Comments;
12
13 # Special configuration for parser
14 has 'config' => (
15     is => 'rw',
16     isa => 'ArrayRef[Str]',
17     auto_deref => 1,
18     default => sub { [] },
19 );
20
21 # Format for usage description
22 has 'format' => (
23     is => 'rw',
24     isa => 'Str',
25     default => 'usage: %c %o',
26 );
27
28
29 sub build_options {
30     my $self = shift;
31     my ($getopt, @attrs) = @_;
32
33     Moose->throw_error('First argument is not a MooseX::Getopt::Session')
34         unless $getopt->isa('MooseX::Getopt::Session');
35
36     my ($options, $usage);
37     my @opts;
38
39     foreach my $attr (@attrs) {
40         my $name = $attr->name;
41
42         my ($flag, @aliases) = $getopt->_get_cmd_flags_for_attr($attr);
43         my $type = $getopt->_get_cmd_type_for_attr($attr);
44
45         my $opt_string = join '|', $flag, @aliases;
46         $opt_string .= MooseX::Getopt::OptionTypeMap->get_option_type($type);
47
48         my $doc;
49         $doc = $attr->documentation if $attr->has_documentation;
50         $doc = ' ' unless $doc;
51
52         my $is_required = $attr->is_required && !$attr->has_default && !$attr->has_builder;
53
54         push @opts, [
55             $opt_string => $doc,
56             {
57                 ( $is_required ? ( required => $attr->is_required ) : () ),
58             }
59         ];
60     };
61
62     ### MooseX::Getopt::Parser::Descriptive::build_options @opts : @opts
63
64     GETOPT: {
65         local @ARGV = $getopt->argv;
66         ### MooseX::Getopt::Parser::Descriptive::build_options @ARGV : @ARGV
67
68         local $SIG{__WARN__} = sub {
69             return warn @_ if $_[0]=~/^\###/;   # Smart::Comments
70             $getopt->strcat_warning( $_[0] )
71         };
72
73         eval {
74             ($options, $usage) = Getopt::Long::Descriptive::describe_options(
75                 $self->format, @opts, { getopt_conf => [ $self->config ] }
76             );
77         };
78         my $e = $@;
79         $getopt->strcat_warning( $e ) if $e;
80         $getopt->status( ! $e );
81
82         my $extra_argv = \@ARGV;
83         $getopt->extra_argv( $extra_argv );
84     };
85
86     #%options = map { $_ => $options{$_} } grep { defined $options{$_} } keys %options;
87     $getopt->options( defined $options ? $options : {} );
88
89     ### MooseX::Getopt::Parser::Descriptive::build_options $options : $options
90     ### MooseX::Getopt::Parser::Descriptive::build_options $usage : $usage
91     ### MooseX::Getopt::Parser::Descriptive::build_options $getopt->status : $getopt->status
92
93     die join '', $getopt->warning
94         if $getopt->die_on_warning && ($getopt->has_warning || !$getopt->status);
95
96     return $options;
97 };
98
99
100 1;