Getopt::WonderBra - Lift and Separate Command Line Options


Getopt-WonderBra documentation Contained in the Getopt-WonderBra distribution.

Index


Code Index:

NAME

Top

Getopt::WonderBra - Lift and Separate Command Line Options

SYNOPSIS

Top

	use Getopt::WonderBra;
	@ARGV = getopt( 'opts:-:', @ARGV );

	sub help() { print "Useless help message"; };
	sub version() { print "Useless version message"; };
	while ( ( $_ = shift ) ne '--' ) {
		if    (/^-o$/) { $opt_o++ }
		elsif (/^-p$/) { $opt_p++ }
		elsif (/^-t$/) { $opt_t++ }
		elsif (/^-s$/) { push( @opt_s, shift ); }
		elsif (/^--/)  { push( @opt_long, $_ ); }
		else           { die 'I do not grok -', $_; }
	}
	print "-o given $opt_o times" if $opt_o;
	print "-p given $opt_p times" if $opt_p;
	print "-t given $opt_t times" if $opt_t;
	print "-s given with arg $_" for @opt_s;
	print "long opt $_ given" for @opt_long;
	print "";
	print "  param: $_" for @ARGV;

REQUIRES

Top

perl5.008006, Carp, Exporter

EXPORTS

Top

getopt($@)

DESCRIPTION

Top

See eg/WonderBra.pl for an example of usage.

There just weren't enough command line processessing modules, so I had to write my own. Actually, it exists because it made it easy to port shell scripts to perl: it acts just like the getopt program. Oddly, none of the modules that are actually named after it do. (Though some act like the C function) The following sequence chops your args up and gives 'em to you straight:

HELP

Top

main::help() must exist prior to calling getopt(). It is wrapped by this module. This is done to ensure correct behavior for programs that use getopt. (e.g. error messages to stdout if --help in specified, so $ foo --help | less has the desired results)

main::help() is replaced by a wrapper that will exit the program. If it gets args, it will select STDERR, call your help function, print the passed args, and exit non-zero.

Otherwise, it will select STDOUT, call your help function, and exit non-zero.

Note that the program will exit if you call help after calling getopt, as well. This is not a bug. It's for issuing error messages while handling the parsed args.

The wrapper sub never returns.

VERSION

Top

If you define a main::version() sub, it will be called if the user specified --version, and the program will terminate.

STDOUT will always be selected.


Getopt-WonderBra documentation Contained in the Getopt-WonderBra distribution.

#!/usr/bin/env perl

package Getopt::WonderBra;
use strict;
our($VERSION)="1.04";


use strict;
use Carp;
use Carp qw(confess);
sub import {
	*{main::getopt}=\&getopt;
};
our (%switches, @arg, @noarg, $res);
my $mainhelp;
my $mainver;
sub version {
	select STDERR if ( @_ );
	$mainver->();
	if ( @_ ) {
		print "\n ERROR: @_\n";
	};
	exit @_ != 0;
};
sub help { 
	select STDERR if ( @_ );
	$mainhelp->(@_);
	if ( @_ ) {
		print "\n ERROR: @_\n";
	};
	exit @_ != 0;
};
sub rep_funcs {
	die "missing main::help" unless exists &main::help;
	die "missing main::version" unless exists &main::version;
	unless (defined($mainhelp)){
		$mainhelp = \&main::help;
		no warnings 'redefine';
		*main::help=\&Getopt::WonderBra::help;
	};
	unless (defined($mainver)){
		$mainver = \&main::version;
		no warnings 'redefine';
		*main::version=\&Getopt::WonderBra::version;
	};
};
sub parsefmt($){
	local $_ = shift;
	while(length) {
		my ($switch,$colons);
		($switch,$colons,$_) = m/^(.)(:?:?)(.*)/;
		confess "no optional args" if ( $colons eq '::' );
		confess ": is not a legal switch" if ( $switch eq ':' );
		confess "$switch repeated" if ( $switches{$switch} );
		if ( $colons ) {
			push(@arg, $switch);
			$switches{$switch}='arg';
		} else {
			push(@noarg, $switch);
			$switches{$switch}='noarg';
		};
	}
	$switches{'-'} = 'arg' if defined $switches{'-'};
	if ( defined($ENV{GETOPT_WONDERBRA_DUMP_FMT}) ) {
		eval 'use Data::Dumper;';
		print STDERR Dumper(\%switches);
	};
}

sub singleopt($\@){
	my $text = 'single: "'.join('","',@{$_[$#_]}).'"';
	local $_ = shift;
	my $arg = shift;
	my ($s, @res,$t);
	while(length) {
		( $s, $_ ) = m/^(.)(.*)/;
		if ( !exists $switches{$s} ) {
			help("illegal switch: $s (part of $s$_)");
		}
		my $type = $switches{$s};
		push(@res,"-$s");
		if ( $type eq 'noarg' )	{
			next;
		} elsif ( $type eq 'arg' ) {
			if ( length )			{ push(@res, $_);last; }
			if ( @$arg )			{ push(@res, shift @$arg);last; }
			help("switch $s missing required arg");
		} else {
			confess "Internal Error: $type";
		};
	}
	return ( @res );
};
sub doubleopt($\@){
	return help()			if $_[0] eq 'help';
	return version()		if $_[0] eq 'version';
	help("not accepting long opts, but got --$_[0]")
		unless defined $switches{'-'};
	return "--".$_[0];
}

sub getopt($\@) {
	rep_funcs;
	my ($opts,$args) = @_;
	confess "Internal Error: Missing switch specifiers" unless @_;
	parsefmt($opts);
	local *_ = $args;
	my @nonopts;
	my @opts;
	while(@_) {
		confess "undef amongst the args?" unless defined($_ = shift);
		if 		( !s/^-// ) 		{ push(@nonopts,$_); next; }
		if		( !length )			{ push(@nonopts,'-'); next; }
		if		( !s/^-// ) 		{ push(@opts,singleopt $_, @_);next; }
		if		( length )			{ push(@opts,doubleopt $_, @_);next; }
		last;
	};
	return @opts, '--', @nonopts, @_;
}
1;