cvsuser 05/01/14 06:01:07
Modified: App-Options/lib/App Options.pm
Log:
added --version
Revision Changes Path
1.12 +147 -24 p5ee/App-Options/lib/App/Options.pm
Index: Options.pm
===================================================================
RCS file: /cvs/public/p5ee/App-Options/lib/App/Options.pm,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- Options.pm 7 Jan 2005 13:04:38 -0000 1.11
+++ Options.pm 14 Jan 2005 14:01:07 -0000 1.12
@@ -1,6 +1,6 @@
#############################################################################
-## $Id: Options.pm,v 1.11 2005/01/07 13:04:38 spadkins Exp $
+## $Id: Options.pm,v 1.12 2005/01/14 14:01:07 spadkins Exp $
#############################################################################
package App::Options;
@@ -14,7 +14,7 @@
use File::Spec;
use Config;
-$VERSION = "0.93";
+$VERSION = "0.94";
=head1 NAME
@@ -47,8 +47,8 @@
$HOME/.app/app.conf
$PROGDIR/prog.conf
$PROGDIR/app.conf
- $PREFIX/prog.conf
- $PREFIX/app.conf
+ $PREFIX/etc/app/prog.conf
+ $PREFIX/etc/app/app.conf
/etc/app/app.conf
with a file format like
@@ -85,7 +85,7 @@
/usr/myproduct/version).
The description of the AppConfig distribution sounds similar
-to is described here. However, the following are the key
+to what is described here. However, the following are some key
differences.
* App::Options does its option processing in the BEGIN block.
@@ -101,8 +101,8 @@
* App::Options consults a cascading set of option files.
These files include those which are system global, project
global, and user private. This allows for system
- administrators, project developers, and in individual
- users to all have complementary roles on defining
+ administrators, project developers, and individual
+ users to all have complementary roles in defining
the configuration values.
* App::Options is not a toolkit but a standardized way of
@@ -111,7 +111,7 @@
code the "--help" feature. With App::Options, you simply
"use App::Options;" and all the hard work is done.
Advanced options can be added later as necessary as args
- to the "use" statement.
+ to the "use App::Options;" statement.
App::Options is also the easiest command-line processing system
that I have found anywhere. It then provides a smooth transition to
@@ -119,8 +119,7 @@
quick and dirty script I ever write from now on can afford
to use App::Options.
-The documentation of App::Options takes three
-forms below.
+The documentation of App::Options takes three forms below.
API Reference - describing the API (methods, args)
Logic Flow - describing the order and logic of processing
@@ -420,9 +419,9 @@
#################################################################
my $is_unix = 1; # pretend we are not on Unix (use File::Spec)
- my $prog_cat = ""; # start with no catalog
- my $prog_dir = $0; # start with the full script path
+ my ($prog_cat, $prog_dir, $prog_file);
if ($is_unix) {
+ $prog_dir = $0;
# i.e. /usr/local/bin/app, /app
if ($prog_dir =~ m!^/!) { # absolute path
# i.e. /usr/local/bin/app, /app
@@ -433,13 +432,15 @@
$prog_dir =~ s!/?[^/]+$!!; # trim off the program name
$prog_dir = "." if (!$prog_dir); # if nothing left, directory is
current dir
}
+ $prog_file = $0;
+ $prog_file =~ s!.*/!!;
+ $prog_cat = "";
}
else {
# i.e. C:\perl\bin\app, \app
- my ($file);
- ($prog_cat, $prog_dir, $file) = File::Spec->splitpath($prog_dir);
+ ($prog_cat, $prog_dir, $prog_file) = File::Spec->splitpath($0);
}
- print STDERR "2. Found Directory of Program. catalog=[$prog_cat]
dir=[$prog_dir]\n"
+ print STDERR "2. Found Directory of Program. catalog=[$prog_cat]
dir=[$prog_dir] file=[$prog_file]\n"
if ($debug_options);
#################################################################
@@ -505,8 +506,7 @@
}
}
if (!$app) {
- $app = $0; # start with the full script path
- $app =~ s!.*/!!; # strip off leading path
+ $app = $prog_file; # start with the full program name
$app =~ s/\.[^.]+$//; # strip off trailing file type (i.e. ".pl")
$app_origin = "program name ($0)";
}
@@ -672,7 +672,7 @@
}
#################################################################
- # 6. fill in ENV vars and defaults
+ # 6. fill in ENV vars
#################################################################
if (!$init_args{no_env_vars}) {
@@ -814,15 +814,40 @@
else {
my $libdir = "$prefix/lib";
my $libdir_found = 0;
+ # Look to see whether this PREFIX has been included already in @INC.
+ # If it has, we do *not* want to automagically guess which
directories
+ # should be searched and in which order.
foreach my $incdir (@INC) {
if ($incdir =~ /^$libdir/) {
$libdir_found = 1;
+ last;
}
}
+
+ # The traditional way to install software from CPAN uses
+ # ExtUtils::MakeMaker via Makefile.PL with the "make install"
+ # command. If you are installing this software to non-standard
+ # places, you would use the "perl Makefile.PL PREFIX=$PREFIX"
+ # command. This would typically put modules into the
+ # $PREFIX/lib/perl5/site_perl/$perlversion directory.
+
+ # However, a newer way to install software (and recent versions
+ # of CPAN.pm understand this) uses Module::Build via Build.PL
+ # with the "Build install" command. If you are installing this
+ # software to non-standard places, you would use the
+ # "perl Build.PL install_base=$PREFIX" command. This would
+ # typically put modules into the $PREFIX/lib directory.
+
+ # So if we need to guess about extra directories to add to the
+ # @INC variable ($PREFIX/lib is nowhere currently represented
+ # in @INC), we should add directories which work for software
+ # installed with either Module::Build or ExtUtils::MakeMaker.
+
if (!$libdir_found) {
unshift(@INC, "$libdir");
if ($^V) {
my $perlversion = sprintf("%vd", $^V);
+ unshift(@INC, $libdir);
unshift(@INC, "$libdir/perl5/site_perl/$perlversion"); #
site_perl goes first!
unshift(@INC, "$libdir/perl5/$perlversion");
}
@@ -850,7 +875,16 @@
}
#################################################################
- # 11. perform validations, print help, and exit
+ # 11. print version information (--version)
+ #################################################################
+
+ if ($values->{version}) {
+ &print_version($prog_file, $values);
+ exit(0);
+ }
+
+ #################################################################
+ # 12. perform validations, print help, and exit
#################################################################
my $exit_status = -1;
@@ -907,13 +941,13 @@
elsif ($type eq "datetime") {
if ($value !~ /^[0-9]{4}-[01][0-9]-[0-3][0-9]
[0-2][0-9]:[0-5][0-9]:[0-5][0-9]$/) {
$exit_status = 1;
- print "Error: \"$var\" must be of type \"$type\" (format
\"YYYY-MM-DD HH:MM::SS\") (not \"$value\")\n";
+ print "Error: \"$var\" must be of type \"$type\" (format
\"YYYY-MM-DD HH:MM:SS\") (not \"$value\")\n";
}
}
elsif ($type eq "time") {
if ($value !~ /^[0-2][0-9]:[0-5][0-9]:[0-5][0-9]$/) {
$exit_status = 1;
- print "Error: \"$var\" must be of type \"$type\" (format
\"HH:MM::SS\") (not \"$value\")\n";
+ print "Error: \"$var\" must be of type \"$type\" (format
\"HH:MM:SS\") (not \"$value\")\n";
}
}
elsif ($type =~ m!^/(.*)/$!) {
@@ -997,6 +1031,80 @@
}
}
+sub print_version {
+ my ($prog_file, $values) = @_;
+ print "Program: $prog_file\n";
+ print "(use --version_packages to see version info for specific perl
packages)\n";
+ my ($module, $package, $version, $full_path);
+ if ($values->{version_packages}) {
+ foreach my $package (split(/[ ;,]+/,$values->{version_packages})) {
+ $module = "$package.pm";
+ $module =~ s!::!/!g;
+ if ($package =~ /^[A-Z][A-Za-z0-9:_]*$/) {
+ eval {
+ require $module;
+ };
+ if ($@) {
+ my $error = $@;
+ $error =~ s/ *\([EMAIL PROTECTED] contains:.*//s;
+ print "WARNING: $package: $error\n";
+ }
+ }
+ }
+ }
+ print "Version Package\n";
+ print "------- ----------------------------\n";
+ printf("%7s main\n", $main::VERSION || "undef");
+
+ my ($show_module, @package_pattern, $version_sys_packages);
+
+ # There are lots of modules which get loaded up which have
+ # nothing to do with your program and which you would ordinarily
+ # not want to see. So ...
+ # --version=1 will show only the packages you specify
+ # --version=2 will show all packages
+ if ($values->{version_packages}) {
+ $version_sys_packages = $values->{version_sys_packages};
+ $version_sys_packages =
"App::Options,Carp,Sys::Hostname,Cwd,File::Spec,Config"
+ if (!defined $version_sys_packages);
+ @package_pattern = split(/[ ;,]+/,$version_sys_packages);
+ if ($values->{version_packages}) {
+ push(@package_pattern, split(/[
;,]+/,$values->{version_packages}));
+ }
+ }
+
+ # I should look into doing this from the symbol table rather
+ # than %INC which reflects the *modules*, not the packages.
+ # For most purposes, this will be good enough.
+ foreach $module (sort keys %INC) {
+ $full_path = $INC{$module};
+ $package = $module;
+ $package =~ s/\.p[lm]$//;
+ $package =~ s!/!::!g;
+
+ if ($values->{version_packages} && $values->{version} eq "1") {
+ $show_module = 0;
+ foreach my $package_pattern (@package_pattern) {
+ if ($package =~ /$package_pattern/) {
+ $show_module = 1;
+ last;
+ }
+ }
+ }
+ else {
+ $show_module = 1;
+ }
+
+ if ($show_module) {
+ $version = "";
+ eval "\$version = \$${package}::VERSION;";
+ $version = "undef" if (!$version);
+ printf("%7s %-20s\n", $version, $package);
+ #printf("%7s %-20s %s\n", "", $module, $full_path);
+ }
+ }
+}
+
=head1 LOGIC FLOW: OPTION PROCESSING DETAILS
Basic Concept - By calling App::Options->init(),
@@ -1359,6 +1467,19 @@
and the resulting list of include directories (@INC) is printed
out.
+=head2 Version
+
+If the "--version" option is set on the command line,
+the version information for the loaded modules is printed,
+and the program is exited.
+
+If additional modules should be loaded so that their version
+number can be ascertained, use the --version_packages option.
+
+ prog --version
+ prog --version --version_packages=CGI
+ prog --version --version_packages=CGI,Template
+
=head2 Help and Validations
After all values have been parsed, various conditions are
@@ -1423,6 +1544,9 @@
demo1 --debug_options -?
demo1 -x=5 --verbose=10 --foo=bar --debug_options -?
+ demo1 --version
+ demo1 --version --version_packages=CGI
+
Now create a copy of the program.
cp demo1 demo2
@@ -1517,8 +1641,8 @@
PREFIX environment variable and the program is not installed in
$PREFIX/bin, he would have to put the above lines
in either the "app.conf" file or the "listcust.conf" file
-in either the global /etc/app directory or in the same
-directory as "listcust".
+in the same directory as "listcust" or in the global
+"/etc/app/app.conf" option file.
A user (without privileges to the "$PREFIX/etc/app" directory
or the directory in which "listcust" lives) would have to put
@@ -1672,7 +1796,6 @@
"first_name", "last_name", "birth_dt", "company_id",
"wholesale_ind", "change_dttm",
],
- show_all => 1,
);
Using the "options" arg causes the options to