Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Getopt-Long-Descriptive CPAN distribution.

Report information
The Basics
Id: 66468
Status: resolved
Priority: 0/
Queue: Getopt-Long-Descriptive

People
Owner: Nobody in particular
Requestors: djerius [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: (no value)
Fixed in: (no value)



Subject: RFC: Handling "short-circuit" options
I'm migrating from Getopt::Long to G::L::D and have come across an incongruity which seems to bedevil most of the higher level option parsing packages, namely how to handle options like --help/--usage/--man if required options are present. For example, if I specify that option "--input" be required, then prog --help causes GLD to die with an error indicating that "--input" wasn't specified, rather than returning an options object with help set. True, the short help message is output as well, but that's a byproduct of the error message. I have traditionally provided a "--manpage" option which outputs the entire documentation, but, as far as I can tell, there's no way of indicating to G::L::D that such an option should take precedence over any other options' constraints. I would like to suggest creating a new attribute for "short-circuit" options which would cause GLD to return (rather than die) with a valid options object with only that option set, without performing a constraint check on the other options. (Another means of handling these would be to have G::L::D throw a particular type of exception to signal the presence of the short-circuit option, but this seems like too much a deviation from the present exception-on-error-only behavior). I've attached a patch against version 0.089 which implements and tests a "shortcircuit" attribute. The implementation still calls Getopt::Long for the command line; it simply doesn't call _validate_with if shortcircuit options are present. Diab
Subject: GLD-0.089.patch
# This is a patch for Getopt-Long-Descriptive-0.089.orig to update it to Getopt-Long-Descriptive-0.089 # # To apply this patch: # STEP 1: Chdir to the source directory. # STEP 2: Run the 'applypatch' program with this patch file as input. # # If you do not have 'applypatch', it is part of the 'makepatch' package # that you can fetch from the Comprehensive Perl Archive Network: # http://www.perl.com/CPAN/authors/Johan_Vromans/makepatch-x.y.tar.gz # In the above URL, 'x' should be 2 or higher. # # To apply this patch without the use of 'applypatch': # STEP 1: Chdir to the source directory. # If you have a decent Bourne-type shell: # STEP 2: Run the shell with this file as input. # If you don't have such a shell, you may need to manually create # the files as shown below. # STEP 3: Run the 'patch' program with this file as input. # # These are the commands needed to create/delete files/directories: # touch 't/shortcircuit.t' chmod 0644 't/shortcircuit.t' # # This command terminates the shell and need not be executed manually. exit # #### End of Preamble #### #### Patch data follows #### diff -c 'Getopt-Long-Descriptive-0.089.orig/lib/Getopt/Long/Descriptive.pm' 'Getopt-Long-Descriptive-0.089/lib/Getopt/Long/Descriptive.pm' Index: ./lib/Getopt/Long/Descriptive.pm *** ./lib/Getopt/Long/Descriptive.pm Thu Jan 13 07:22:17 2011 --- ./lib/Getopt/Long/Descriptive.pm Tue Mar 8 10:44:20 2011 *************** *** 212,217 **** --- 212,226 ---- [ mode => \@option_specs, \%constraints ] + + =item shortcircuit + + shortcircuit => 1 + + If this option is present no other options will be returned. Other + options present will be checked for proper types, but I<not> for + constraints. This provides a way of specifying C<--help> style options. + =item Params::Validate In addition, any constraint understood by Params::Validate may be used. *************** *** 351,357 **** --- 360,372 ---- push @opts, $one_opt; } } + if ( $opt->{constraint}{shortcircuit} && + exists $opt->{constraint}{default} + ) { + carp( 'option "', $opt->{name}, q[": 'default' does not make sense for shortcircuit options] ); + } push @opts, $opt; + } my @go_conf = @{ $arg->{getopt_conf} || $arg->{getopt} || [] }; *************** *** 407,414 **** $return{$newopt} = delete $return{$opt}; } ! for my $copt (grep { $_->{constraint} } @opts) { delete $copt->{constraint}->{hidden}; my $name = $copt->{name}; my $new = _validate_with( name => $name, --- 422,435 ---- $return{$newopt} = delete $return{$opt}; } ! # ensure that shortcircuit options are handled first ! for my $copt (sort { ($b->{constraint}{shortcircuit} || 0) ! <=> ($a->{constraint}{shortcircuit} || 0) ! } ! grep { $_->{constraint} } @opts ! ) { delete $copt->{constraint}->{hidden}; + my $is_shortcircuit = delete $copt->{constraint}{shortcircuit}; my $name = $copt->{name}; my $new = _validate_with( name => $name, *************** *** 419,424 **** --- 440,450 ---- ); next unless (defined($new) || exists($return{$name})); $return{$name} = $new; + if ( $is_shortcircuit ) + { + %return = ( $name => $return{$name} ); + last; + } } my $opt_obj = Getopt::Long::Descriptive::Opts->___new_opt_obj({ diff -c /dev/null 'Getopt-Long-Descriptive-0.089/t/shortcircuit.t' Index: ./t/shortcircuit.t *** ./t/shortcircuit.t Wed Dec 31 19:00:00 1969 --- ./t/shortcircuit.t Tue Mar 8 10:38:11 2011 *************** *** 0 **** --- 1,78 ---- + #!perl + use strict; + use warnings; + + use Test::More tests => 11; + + use_ok("Getopt::Long::Descriptive"); + + + my $nreq = 6; + my @reqs = map { "--req$_" } 1..$nreq; + + sub test { + + my $opts = shift; + local @ARGV = @_; + + my ( $opt, $usage) = + eval { + # catch carp's so we can test 'em + local $SIG{__WARN__} = sub {die @_ }; + + describe_options ( + "test %o", + # load with extra required to make sure + # sorting on shortcircuit attribute works; + ( map { [ "req$_", 'required' , { required => 1 } ] + } 1..$nreq ), + [ 'help', 'help', { shortcircuit => 1, %$opts } ], + ); + }; + my $error = $@; + return $opt, $usage, $error; + } + + { + my ( $opt, $usage, $error ) = test({} ); + + like( $error, qr/required/, 'no req: error' ); + } + + SKIP: + { + my ( $opt, $usage, $error ) = test( { default => 1 }, @reqs ); + + like( $error, qr/'default' does not make sense for shortcircuit/, 'shortcircuit + default' ); + } + + + SKIP: + { + my ( $opt, $usage, $error ) = test( {}, @reqs ); + + my $ok = is( $error, '', 'req: no error' ); + skip 'no object due to failure', 1, unless $ok; + ok( defined $opt->req1 && $opt->req1 == 1, 'req: req1 specified' ); + } + + SKIP: + { + my ( $opt, $usage, $error ) = test( {}, qw[ --help ] ); + + my $ok = is( $error, '', 'help: no error' ); + + skip 'no object due to failure', 2, unless $ok; + ok( $opt->help == 1, 'help: help flag' ); + ok( keys %{$opt} == 1, 'help: only help' ); + } + + SKIP: + { + my ( $opt, $usage, $error ) = test( {}, @reqs, '--help' ); + + my $ok = is( $error, '', 'help + req: no error' ); + skip 'no object due to failure', 2, unless $ok; + ok( $opt->help == 1, 'help + req: help flag' ); + ok( keys %{$opt} == 1, 'help + req: only help' ); + } #### End of Patch data #### #### ApplyPatch data follows #### # Data version : 1.0 # Date generated : Tue Mar 8 10:44:39 2011 # Generated by : makepatch 2.04 # Recurse directories : Yes # Excluded files : (\A|/).*\~\Z # (\A|/).*\.a\Z # (\A|/).*\.bak\Z # (\A|/).*\.BAK\Z # (\A|/).*\.elc\Z # (\A|/).*\.exe\Z # (\A|/).*\.gz\Z # (\A|/).*\.ln\Z # (\A|/).*\.o\Z # (\A|/).*\.obj\Z # (\A|/).*\.olb\Z # (\A|/).*\.old\Z # (\A|/).*\.orig\Z # (\A|/).*\.rej\Z # (\A|/).*\.so\Z # (\A|/).*\.Z\Z # (\A|/)\.del\-.*\Z # (\A|/)\.make\.state\Z # (\A|/)\.nse_depinfo\Z # (\A|/)core\Z # (\A|/)tags\Z # (\A|/)TAGS\Z # (\A|/)Makefile\Z # (\A|/)pm_to_blib\Z # (\A|/)blib\/.*\Z # (\A|/)\.hg\/.*\Z # p 'lib/Getopt/Long/Descriptive.pm' 16682 1299599060 0100644 # c 't/shortcircuit.t' 0 1299598691 0100644 #### End of ApplyPatch data #### #### End of Patch kit [created: Tue Mar 8 10:44:39 2011] #### #### Patch checksum: 201 5997 19171 #### #### Checksum: 231 7112 48158 ####
From: jean [...] veronis.fr
This is very nice, thanks ! I was running into the same problem... Is there a plan to incoporate this in a future release ?
On Tue Mar 08 10:51:28 2011, DJERIUS wrote: [a bunch of stuff] Is there any interest in this functionality? I'd be glad to update the patch against the latest version. Diab
This seems reasonable. I am tentatively resolving this ticket. I would greatly appreciate it if you could submit any updated patch to github.com/rjbs/Getopt-Long-Descriptive If this is a pain, and you'd rather re-open this ticket and attach a patch, that's okay, too. But GitHub will make my life a little easier, if it's all the same to you. I think the returned $opt should have some means of noting that it's not been validated. Possibly ->was_short_circuited or the like. Thank you. (I'm doing better at ticket response time now, really. ;) -- rjbs
On Thu Sep 05 09:18:45 2013, RJBS wrote: Show quoted text
> This seems reasonable. > > I am tentatively resolving this ticket. I would greatly appreciate it > if you could submit any updated patch to github.com/rjbs/Getopt-Long- > Descriptive > > If this is a pain, and you'd rather re-open this ticket and attach a > patch, that's okay, too. But GitHub will make my life a little > easier, if it's all the same to you. > > I think the returned $opt should have some means of noting that it's > not been validated. Possibly ->was_short_circuited or the like. > > Thank you. (I'm doing better at ticket response time now, really. ;)
GitHub it is.
shortcircuit has been deployed for a while now! :) -- rjbs
Subject: Re: [rt.cpan.org #66468] RFC: Handling "short-circuit" options
Date: Mon, 18 Jul 2016 11:06:56 -0400
To: bug-Getopt-Long-Descriptive [...] rt.cpan.org
From: Diab Jerius <djerius [...] cpan.org>
yes it has. thanks for incorporating it! On Sat, Jul 16, 2016 at 10:35 AM, Ricardo Signes via RT <bug-Getopt-Long-Descriptive@rt.cpan.org> wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=66468 > > > shortcircuit has been deployed for a while now! :) > > -- > rjbs