PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
Dir : /proc/thread-self/root/proc/self/root/proc/self/root/opt/sharedrads/perl/IMH/ |
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 IP: 209.182.202.254 |
Dir : //proc/thread-self/root/proc/self/root/proc/self/root/opt/sharedrads/perl/IMH/OptionParser.pm |
#!/usr/bin/perl # encoding: utf-8 # # author: Kyle Yetter # package IMH::OptionParser; use strict; use warnings; use Getopt::Long; use File::Basename; use Class::Struct; use Switch; use IMH::Terminal; use Text::Wrap; our $VERSION = '0.1'; our @TYPE_SIGNIFIERS = qw( s str string i int integer f float real o perl_int perl_integer ); our %CANONICAL_TYPES = ( 's' => 's', 'str' => 's', 'string' => 's', 'i' => 'i', 'int' => 'i', 'integer' => 'i', 'f' => 'f', 'float' => 'f', 'real' => 'f', 'o' => 'o', 'perl_int' => 'o', 'perl_integer' => 'o' ); our $TEMPLATE = q( package IMH::OptionParser::OptionSet<[id]>; use Class::Struct; struct( <[struct_spec]> ); ); sub new { my ( $class ) = shift; my $object = {}; bless( $object, $class || __PACKAGE__ ); $object->initialize( @_ ); return $object; } sub initialize { my ( $self, @args ) = @_; $self->{name} = basename( $0 ); $self->{version} = defined( $main::VERSION ) ? "$main::VERSION" : undef; $self->{description} = undef; $self->{entries} = []; $self->{config} = { bundling => 1 }; $self->{entries_by_name} = {}; $self->{usage} = undef; $self->{include_help} = 1; $self->{include_version} = $self->{version} ? 1 : 0; for my $arg ( @args ) { switch ( ref( $arg ) ) { case 'HASH' { for my $prop ( qw( include_version include_help usage version name ) ) { exists( $arg->{$prop} ) and $self->{$prop} = $arg->{$prop}; } } else { switch ( $arg ) { case qr(^(?:\d+\.)*\d+$) { $self->{version} = $arg; } else { $self->{name} = "$arg"; } } } } } return $self; } sub name { my $self = shift; if ( @_ ) { $self->{name} = shift; } return $self->{name}; } sub version { my $self = shift; if ( @_ ) { $self->{version} = shift; } return $self->{version}; } sub description { my $self = shift; if ( @_ ) { $self->{description} = join( "\n", @_ ); } return $self->{description}; } sub usage { my $self = shift; if ( @_ ) { $self->{ usage } = join( "\n", @_ ); } return $self->{ usage }; } sub enable { my $self = shift; my $config = $self->{config}; for my $config_attr ( @_ ) { $config->{ $config_attr } = 1; } return $self; } sub disable { my $self = shift; my $config = $self->{config}; for my $config_attr ( @_ ) { $config->{ $config_attr } = 0; } return $self; } sub option { my $self = shift; my %opts = ( arity => 0, argument_required => 0, type => 's' ); my @short = (); my @long = (); for my $arg ( @_ ) { switch ( ref( $arg ) ) { case 'HASH' { %opts = ( %opts, %$arg ); } case 'CODE' { $opts{callback} = $arg; } case 'ARRAY' { } else { switch ( $arg ) { case qr/^-([^\-])/ { push @short, $arg; } case qr/^--([^=:\s]+)/ { push @long, $arg; } case [ @TYPE_SIGNIFIERS ] { $opts{type} = "$arg"; } else { $opts{desc} = "$arg"; } } } } } if ( exists($opts{type}) ) { if ( exists($CANONICAL_TYPES{$opts{type}}) ) { $opts{type} = $CANONICAL_TYPES{$opts{type}}; } else { warn( "`$opts{type}' is not a valid option type specification" ); $opts{type} = 's'; } } unless ( exists( $opts{name} ) ) { if ( $long[0] =~ /^\-\-([^=:\s]+)/ ) { ( $opts{name} = $1 ) =~ y/- \t/_/; } } my $spec = OptionSpec->new( %opts ); $spec->long( [ @long ] ); $spec->short( [ @short ] ); for ( @short ) { if ( /^-?([^-])/ ) { $self->{entries_by_name}->{$1} = $spec; } if ( /[\s=](.+)/ ) { $spec->arity( 1 ); $spec->argument_required( 1 ); } elsif ( /:(.+)/ ) { $spec->arity( 1 ); $spec->argument_required( 0 ); } } for ( @long ) { if ( /^(?:--)?([^=\s:]+)/ ) { $self->{entries_by_name}->{$1} = $spec; } if ( /[\s=](.+)/ ) { $spec->arity( 1 ); $spec->argument_required( 1 ); } elsif ( /:(.+)/ ) { $spec->arity( 1 ); $spec->argument_required( 0 ); } } push @{ $self->{entries} }, $spec; return $spec; } sub build_option_object { my ( $self ) = @_; my $class_source = $TEMPLATE; my @struct_spec_parts = map { my $spec = $_; my $name = $spec->name; my $type = q('$'); "$name => $type"; } @{$self->{entries}}; my $params = { id => 0 + $self, struct_spec => join( ', ', @struct_spec_parts ) }; $class_source =~ s(<\[(\w+)\]>)($params->{$1};)eg; eval( $class_source ); my $option_object = eval( "IMH::OptionParser::OptionSet" . ( 0 + $self ) . "->new" ); for my $spec ( @{$self->{entries}} ) { if ( $spec->default_value ) { my $n = $spec->name; $option_object->$n( $spec->default_value ); } } return $option_object; } sub parse { my $self = shift; my $args = shift || [ @ARGV ]; $self->add_special_opts; my $option_object = $self->build_option_object; my $getopt = Getopt::Long::Parser->new; my $handler = sub { my ( $opt_info, $val ) = @_; my $oname = $opt_info->name; my $spec = $self->{entries_by_name}->{$oname}; if ( $spec->special ) { switch ( $spec->special ) { case 'h' { printf STDERR "%s\n", $self->build_help; exit( 0 ); } case 'v' { printf STDERR "%s\n", $self->{version}; exit( 0 ); } } } elsif ( $spec->callback ) { $spec->callback->($spec, $val); } else { my $n = $spec->name; if ( $spec->arity ) { $option_object->$n( $val ); } else { $option_object->$n( 1 ); } } }; my %getopt_spec; for my $spec ( @{$self->{entries}} ) { $getopt_spec{ make_opt_string( $spec ) } = $handler; } # set the options for Getopt::Long::Parser by selecting the keys in the # config hash that are set to 1 $getopt->configure( grep { $self->{config}->{ $_ } } keys %{$self->{config}} ); my @original_argv = @ARGV; @ARGV = @$args; $getopt->getoptions( %getopt_spec ); my @remaining_args = @ARGV; @ARGV = @original_argv; return ( $option_object, [ @remaining_args ] ); } sub add_special_opts { my ( $self ) = @_; unless ( $self->{help_option} || !$self->{include_help} ) { my @params = (); my $registry = $self->{entries_by_name}; unless ( exists( $registry->{h} ) ) { push( @params, '-h' ); } unless ( exists( $registry->{help} ) ) { push( @params, '--help' ); } if ( @params ) { push @params, { desc => "Show program usage details", special => 'h' }; $self->{help_option} = $self->option( @params ); } else { $self->{help_option} = $registry->{help}; } } unless ( $self->{version_option} || !$self->{include_version} ) { my @params = (); my $registry = $self->{entries_by_name}; unless ( exists( $registry->{v} ) ) { push( @params, '-v' ); } unless ( exists( $registry->{version} ) ) { push( @params, '--version' ); } if ( @params ) { push @params, { desc => "Print program version number and exit", special => 'v' }; $self->{version_option} = $self->option( @params ); } else { $self->{version_option} = $registry->{version}; } } return; } sub fail_with_help { my ( $self, $message ) = @_; if ( $message ) { print STDERR "ERROR: $message\n\n"; } printf STDERR "%s\n", $self->build_help; exit( 1 ); } sub make_opt_string { my ( $spec ) = @_; my @frags; for ( @{$spec->short} ) { if ( /^-?([^-])/ ) { push @frags, $1; } } for ( @{$spec->long} ) { if ( /^(?:--)?([^=\s:]+)/ ) { push @frags, $1; } } my $str = join( '|', @frags ); if ( $spec->arity ) { if ( $spec->argument_required ) { $str .= "=" . $spec->type; } else { $str .= ':' . $spec->type; } } return $str; } sub build_help { my ( $self, %opts ) = @_; my $program = $self->{name}; my $version = $self->{version}; my $description = $self->{description}; my $full_name = $version ? "$program v$version" : $program; my $width = $opts{width} || screen_width; my $indent = $opts{indent} || 4; my @entries = @{ $self->{entries} }; my $text = ''; my $opt_width = 0; my $usage = $self->{usage} || $opts{usage}; # || "$program [options]"; my $indent_text = ' ' x $indent; open( my $out, ">", \$text ); local $\ = "\n"; $Text::Wrap::columns = $width - $indent - 2; print $out "NAME"; print $out "$indent_text$full_name"; print $out ''; if ( $description ) { $description = wrap( '', '', $description ); for my $l ( split /\n/, $description ) { print $out "$indent_text$l"; } print $out ''; } if ( $usage ) { print $out "USAGE"; $usage = wrap( '', '', $usage ); for my $l ( split /\n/, $usage ) { print $out "$indent_text$l"; } print $out ''; } print $out "OPTIONS"; my @option_strings = map { my $spec = $_; my @opts = ( @{ $spec->short }, @{ $spec->long } ); my $s = join( ", ", @opts ); my $l = clen( $s ); if ( $l > $opt_width ) { $opt_width = $l; } $s; } @entries; my $desc_width = $width - $indent - 2 - $opt_width; if ( $desc_width < 20 ) { $desc_width = 20; } my $sep_span = ' ' x 2; my $padding_span = ' ' x $opt_width; $Text::Wrap::columns = $desc_width; for my $i ( 0 ... $#entries ) { my $spec = $entries[ $i ]; my $opt_string = $option_strings[ $i ]; my $desc = $spec->desc || ''; $desc = wrap( '', '', $desc ); my @desc_lines = split( /\r?\n/, $desc ); my $first_line = shift( @desc_lines ) || ''; print $out $indent_text, ljust( $opt_string, $opt_width ), $sep_span, $first_line; for my $line ( @desc_lines ) { print $out $indent_text, $padding_span, $sep_span, $line; } } close( $out ); return $text; } sub build_usage { my ( $self ) = @_; } struct( OptionSpec => [ 'short' => '@', 'long' => '@', 'name' => '$', 'arity' => '$', 'default_value' => '$', 'argument_required' => '$', 'type' => '$', 'desc' => '$', 'callback' => '$', 'special' => '$' ] ); 1;