Zoidberg

 view release on metacpan or  search on metacpan

lib/Zoidberg/Utils/GetOpt.pm  view on Meta::CPAN

		unless ($opt =~ s/\*$//) {
			$conf{$opt} = $arg;
			$conf{_alias}{$_} = $opt for @al;
		}
		else {
			error 'config syntax error' if @al || ! length $_;
			$conf{$opt} = $arg;
			$conf{_glob} ||= [];
			push @{$conf{_glob}}, $opt;
		}
	}
	$conf{_glob} = '^('.join('|', map {s/^\+/\\+/; $_} @{$conf{_glob}}).')(?!-)' if $conf{_glob};
	#use Data::Dumper; print STDERR 'conf: ', Dumper \%conf;

	PARSE_OPTS:
	for ( # set default options
		[qw/h help/,    \&help   ],
		[qw/u usage/,   \&usage  ],
		[qw/v version/, \&version]
	) {
		next if exists $conf{$$_[1]};
		$conf{$$_[1]} = $$_[2];
		$conf{_alias}{'-'.$$_[0]} = $$_[1]
			unless exists $conf{_alias}{'-'.$$_[0]} or exists $conf{_alias}{$$_[0]};
	}

	my $delim = 0;
	while (@args) { # parse opts
		last unless $args[0] =~ /^(-|\+.)/;
		$_ = shift @args;
		/^(--|-|\+)(.*)/;
		++$delim and last unless length $2;
		my ($pre, $opt, $arg) = ($1, split '=', $2, 2);

		my (@chars, $type);
		my $raw = $pre.$opt;
		if (exists $conf{_alias}{$raw} or exists $conf{$raw}) { $opt = $raw }
		elsif (exists $conf{_glob} and $raw =~ /$conf{_glob}/) {
			$opt = $raw;
			$type = $conf{$1};
		}
		elsif ($pre ne '--' and length $opt > 1) { # try short options
			@chars = split '', $opt;
		}

		PARSE_OPT:
		$opt = shift @chars if @chars;
		$opt = $conf{_alias}{$opt} if exists $conf{_alias}{$opt};
	
		unless (defined $type) { # type is set if glob
			if (exists $conf{$opt}) { $type = $conf{$opt} }
			else { error "unrecognized option '$opt'" }
		}

		push @opts, $opt;
		if (! $type) { # no arg
			error "option '$opt' doesn't take an argument" if defined $arg;
			$opts{$opt} = ($pre eq '+') ? 0 : 1;
		}
		elsif (ref $type) { # CODE ... for default opts
			output $type->( (caller(1))[3], (caller)[0] ); # subroutine, package
			error {silent => 1, exit_status => 0}, 'getopt needed to pop stack';
		}
		else {
			$arg = defined($arg) ? $arg : shift(@args);
			error "option '$opt' requires an argument" unless defined $arg;
			if    ($type eq '$') { $opts{$opt} = $arg }
			elsif ($type eq '@') {
				if (ref $arg) {
					error 'argument is not a ARRAY reference'
						if ref($arg) ne 'ARRAY';
					if ($opts{$opt}) { push @{$opts{$opt}}, @$arg }
					else { $opts{$opt} = $arg }
				}
				else {
					$opts{$opt} ||= [];
					push @{$opts{$opt}}, $arg;
				}
			}
		}
		$arg = $type = undef;
		goto PARSE_OPT if @chars;
	};
	error @opts 
		? "option '$opts[-1]' doesn't take an argument" 
		: 'options found after first argument'          if !$delim and grep /^-/, @args;
	$opts{_opts} = \@opts if @opts; # keep %opts empty unless there are opts

	PARSE_ARGS: # parse args
	unless ($conf{_args}) { $args = [@args] }
	elsif  ($conf{_args} eq '@') {
		error "argument should be a ARRAY reference"
			if grep {ref($_) and ref($_) ne 'ARRAY'} @args;
		if (ref $args[0] and @args == 1) { $args = $args[0] }
		else { $args = [ map {ref($_) ? @$_ : $_} @args] }
	}
	elsif  ($conf{_args} eq '%') {
		error "argument should be a HASH reference"
			if grep {ref($_) and ref($_) ne 'HASH'} @args;
		if (ref $args[0] and @args == 1) { $args = $args[0] }
		else {
			my $error;
			$args = { map {
				if (ref $_) { (%$_) }
				else {
					m/(.*?)=(.*)/ or $error++; 
					($1 => $2)
				}
	       		} @args };
			error 'syntax error, should be \'key=value\'' if $error;
		}
	}
	elsif ($conf{_args} eq '*') {
		my (@keys, %vals);
		for (@args) {
			if (ref $_) {
				my $t = ref $_;
				if ($t eq 'ARRAY') { push @keys, @$_ }
				elsif ($t eq 'HASH') {
					push @keys, keys %$_;
					%vals = (%vals, %$_);



( run in 0.762 second using v1.01-cache-2.11-cpan-cd2fffc590a )