1 package MooseX::Runnable::Util::ArgParser;
2 # ABSTRACT: parse @ARGV for mx-run
5 use MooseX::Types::Moose qw(HashRef ArrayRef Str Bool);
6 use MooseX::Types::Path::Tiny qw(Path);
7 use Path::Tiny; # exports path()
8 use List::MoreUtils qw(first_index);
12 use namespace::autoclean -also => ['_look_for_dash_something', '_delete_first'];
34 has 'include_paths' => (
36 isa => ArrayRef[Path],
43 isa => HashRef[ArrayRef[Str]],
61 sub _build_class_name {
63 my @args = $self->argv;
66 my $need_dash_dash = 0;
79 next ARG if $arg =~ /^-[A-Za-z]/;
86 return $arg unless $need_dash_dash;
90 confess 'Parse error: expecting ClassName, got EOF';
93 confess 'Parse error: expecting --, got EOF';
96 confess "Parse error: looking for ClassName, but can't find it; perhaps you meant '--help' ?";
99 sub _look_for_dash_something($@) {
100 my ($something, @args) = @_;
103 my $rx = qr/^-$something(.*)$/;
105 for my $arg (@args) {
106 last ARG if $arg eq '--';
107 last ARG unless $arg =~ /^-/;
118 my @args = $self->argv;
119 return [ _look_for_dash_something 'M', @args ];
122 sub _build_include_paths {
124 my @args = $self->argv;
125 return [ map { path($_) } _look_for_dash_something 'I', @args ];
130 my @args = $self->argv;
132 (_look_for_dash_something 'h', @args) ||
133 (_look_for_dash_something '\\?', @args) ||
134 (_look_for_dash_something '-help', @args) ;;
139 my @args = $self->argv;
140 $self->class_name; # causes death when plugin syntax is wrong
144 my $in_plugin = undef;
147 for my $arg (@args) {
148 if(defined $in_plugin){
150 $plugins{$in_plugin} = [@accumulator];
154 elsif($arg =~ /^[+](.+)$/){
155 $plugins{$in_plugin} = [@accumulator];
161 push @accumulator, $arg;
164 else { # once we are $in_plugin, we can never be out again
168 elsif($arg =~ /^[+](.+)$/){
176 confess "Parse error: expecting arguments for plugin $in_plugin, but got EOF. ".
177 "Perhaps you forgot '--' ?";
183 sub _delete_first($\@) {
184 my ($to_delete, $list) = @_;
185 my $idx = first_index { $_ eq $to_delete } @$list;
186 splice @$list, $idx, 1;
190 # this is a dumb way to do it, but i forgot about it until just now,
191 # and don't want to rewrite the whole class ;) ;)
192 sub _build_app_args {
194 my @args = $self->argv;
196 return [] if $self->is_help; # LIES!!11!, but who cares
198 # functional programmers may wish to avert their eyes
199 _delete_first $_, @args for map { "-M$_" } $self->modules;
200 _delete_first $_, @args for map { "-I$_" } $self->include_paths;
202 my %plugins = %{ $self->plugins };
205 for my $p (keys %plugins){
206 my $vl = scalar @{ $plugins{$p} };
207 my $idx = first_index { $_ eq "+$p" } @args;
208 next PLUGIN if $idx == -1; # HORRIBLE API!
210 splice @args, $idx, $vl + 1;
213 if($args[0] eq '--'){
217 if($args[0] eq $self->class_name){
221 confess 'Parse error: Some residual crud was found before the app name: '.
230 my ($self, %opts) = @_;
232 confess 'Parser is help' if $self->is_help;
234 my @perl_flags = @{$opts{perl_flags} || []};
235 my @without_plugins = @{$opts{without_plugins} || []};
240 (map { "-I$_" } @INC),
242 $FindBin::Bin.'/'.$FindBin::Script,
244 push @cmdline, map { "-I$_" } $self->include_paths;
245 push @cmdline, map { "-M$_" } $self->modules;
248 for my $plugin (keys %{$self->plugins}){
249 for my $without (@without_plugins) {
250 next p if $without eq $plugin;
252 push @cmdline, "+$plugin", @{$self->plugins->{$plugin} || []};
255 push @cmdline, $self->class_name;
256 push @cmdline, $self->app_args;
271 my $parser = MooseX::Runnable::Util::ArgParser->new(
277 $parser->include_paths;