Codebase list libgetopt-lucid-perl / 8c5dcf8
Imported Upstream version 1.00 gregor herrmann 12 years ago
31 changed file(s) with 590 addition(s) and 353 deletion(s). Raw diff Collapse all Expand all
00 Revision history for Perl module Getopt::Lucid
1
2 1.00 2011-12-10 23:32:42 EST5EDT
3
4 - new() takes optional hashref of parameters
5 - Remove global $STRICT and replace with 'strict' object parameter
6 - Remove 'required' modifier for parameters and provide a new
7 'validate' method for late checking of prerequisites
8 - Fix missing $VERSION
19
210 0.19 2010-11-05 17:07:26 EST5EDT
311
0 This software is Copyright (c) 2010 by David Golden.
0 This software is Copyright (c) 2011 by David Golden.
11
22 This is free software, licensed under:
33
44 META.yml
55 Makefile.PL
66 README
7 README.PATCHING
78 Todo
89 dist.ini
910 examples/cpanget
1011 lib/Getopt/Lucid.pm
1112 lib/Getopt/Lucid/Exception.pm
13 perlcritic.rc
1214 t/00-compile.t
1315 t/00-new.t
1416 t/01-exceptions.t
2224 t/09-negation.t
2325 t/10-default-validation.t
2426 t/ErrorMessages.pm
27 xt/author/critic.t
2528 xt/release/distmeta.t
2629 xt/release/pod-coverage.t
2730 xt/release/pod-syntax.t
2831 xt/release/portability.t
32 xt/release/test-version.t
33 "David Golden <dagolden@cpan.org>"
44 ],
55 "dynamic_config" : 0,
6 "generated_by" : "Dist::Zilla version 4.102341, CPAN::Meta::Converter version 2.102400",
6 "generated_by" : "Dist::Zilla version 4.300003, CPAN::Meta::Converter version 2.112580",
77 "license" : [
88 "apache_2_0"
99 ],
2626 "prereqs" : {
2727 "configure" : {
2828 "requires" : {
29 "ExtUtils::MakeMaker" : "6.31"
29 "ExtUtils::MakeMaker" : "6.30"
3030 }
3131 },
3232 "runtime" : {
3636 "Exporter" : 0,
3737 "Storable" : "2.16",
3838 "perl" : "5.006",
39 "vars" : 0
39 "strict" : 0,
40 "warnings" : 0
4041 }
4142 },
4243 "test" : {
4546 "Exception::Class::TryCatch" : "1.10",
4647 "File::Find" : 0,
4748 "File::Temp" : 0,
48 "Test::More" : "0.62"
49 "Test::More" : "0.62",
50 "vars" : 0
4951 }
5052 }
5153 },
5254 "provides" : {
5355 "Getopt::Lucid" : {
5456 "file" : "lib/Getopt/Lucid.pm",
55 "version" : "0.19"
57 "version" : "1.00"
5658 },
5759 "Getopt::Lucid::Exception" : {
5860 "file" : "lib/Getopt/Lucid/Exception.pm",
59 "version" : "0.19"
61 "version" : "1.00"
6062 },
6163 "Getopt::Lucid::Spec" : {
6264 "file" : "lib/Getopt/Lucid.pm",
63 "version" : "0.19"
65 "version" : "1.00"
6466 }
6567 },
6668 "release_status" : "stable",
6769 "resources" : {
68 "homepage" : "http://github.com/dagolden/getopt-lucid/tree",
70 "bugtracker" : {
71 "mailto" : "bug-getopt-lucid at rt.cpan.org",
72 "web" : "http://rt.cpan.org/Public/Dist/Display.html?Name=Getopt-Lucid"
73 },
74 "homepage" : "https://github.com/dagolden/getopt-lucid",
6975 "repository" : {
7076 "type" : "git",
71 "url" : "git://github.com/dagolden/getopt-lucid.git",
72 "web" : "http://github.com/dagolden/getopt-lucid/tree"
77 "url" : "https://github.com/dagolden/getopt-lucid.git",
78 "web" : "https://github.com/dagolden/getopt-lucid"
7379 }
7480 },
75 "version" : "0.19"
81 "version" : "1.00"
7682 }
7783
77 File::Find: 0
88 File::Temp: 0
99 Test::More: 0.62
10 vars: 0
1011 configure_requires:
11 ExtUtils::MakeMaker: 6.31
12 ExtUtils::MakeMaker: 6.30
1213 dynamic_config: 0
13 generated_by: 'Dist::Zilla version 4.102341, CPAN::Meta::Converter version 2.102400'
14 generated_by: 'Dist::Zilla version 4.300003, CPAN::Meta::Converter version 2.112580'
1415 license: apache
1516 meta-spec:
1617 url: http://module-build.sourceforge.net/META-spec-v1.4.html
2728 provides:
2829 Getopt::Lucid:
2930 file: lib/Getopt/Lucid.pm
30 version: 0.19
31 version: 1.00
3132 Getopt::Lucid::Exception:
3233 file: lib/Getopt/Lucid/Exception.pm
33 version: 0.19
34 version: 1.00
3435 Getopt::Lucid::Spec:
3536 file: lib/Getopt/Lucid.pm
36 version: 0.19
37 version: 1.00
3738 requires:
3839 Carp: 0
3940 Exception::Class: 1.23
4041 Exporter: 0
4142 Storable: 2.16
4243 perl: 5.006
43 vars: 0
44 strict: 0
45 warnings: 0
4446 resources:
45 homepage: http://github.com/dagolden/getopt-lucid/tree
46 repository: git://github.com/dagolden/getopt-lucid.git
47 version: 0.19
47 bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=Getopt-Lucid
48 homepage: https://github.com/dagolden/getopt-lucid
49 repository: https://github.com/dagolden/getopt-lucid.git
50 version: 1.00
11 use strict;
22 use warnings;
33
4 BEGIN { require 5.006; }
4 use 5.006;
55
6 use ExtUtils::MakeMaker 6.31;
6 use ExtUtils::MakeMaker 6.30;
77
88
99
1010 my %WriteMakefileArgs = (
11 'ABSTRACT' => 'Clear, readable syntax for command line processing',
12 'AUTHOR' => 'David Golden <dagolden@cpan.org>',
13 'BUILD_REQUIRES' => {
14 'Data::Dumper' => '0',
15 'Exception::Class::TryCatch' => '1.10',
16 'File::Find' => '0',
17 'File::Temp' => '0',
18 'Test::More' => '0.62'
11 "ABSTRACT" => "Clear, readable syntax for command line processing",
12 "AUTHOR" => "David Golden <dagolden\@cpan.org>",
13 "BUILD_REQUIRES" => {
14 "Data::Dumper" => 0,
15 "Exception::Class::TryCatch" => "1.10",
16 "File::Find" => 0,
17 "File::Temp" => 0,
18 "Test::More" => "0.62",
19 "vars" => 0
1920 },
20 'CONFIGURE_REQUIRES' => {
21 'ExtUtils::MakeMaker' => '6.31'
21 "CONFIGURE_REQUIRES" => {
22 "ExtUtils::MakeMaker" => "6.30"
2223 },
23 'DISTNAME' => 'Getopt-Lucid',
24 'EXE_FILES' => [],
25 'LICENSE' => 'apache',
26 'NAME' => 'Getopt::Lucid',
27 'PREREQ_PM' => {
28 'Carp' => '0',
29 'Exception::Class' => '1.23',
30 'Exporter' => '0',
31 'Storable' => '2.16',
32 'vars' => '0'
24 "DISTNAME" => "Getopt-Lucid",
25 "EXE_FILES" => [],
26 "LICENSE" => "apache",
27 "NAME" => "Getopt::Lucid",
28 "PREREQ_PM" => {
29 "Carp" => 0,
30 "Exception::Class" => "1.23",
31 "Exporter" => 0,
32 "Storable" => "2.16",
33 "strict" => 0,
34 "warnings" => 0
3335 },
34 'VERSION' => '0.19',
35 'test' => {
36 'TESTS' => 't/*.t'
36 "VERSION" => "1.00",
37 "test" => {
38 "TESTS" => "t/*.t"
3739 }
3840 );
3941
11 Getopt::Lucid - Clear, readable syntax for command line processing
22
33 VERSION
4 version 0.19
4 version 1.00
55
66 SYNOPSIS
77 use Getopt::Lucid qw( :all );
1717 Switch("help|h")
1818 );
1919
20 $opt = Getopt::Lucid->getopt( \@specs );
20 $opt = Getopt::Lucid->getopt( \@specs )->validate;
2121
2222 $verbosity = $opt->get_verbose;
2323 @libs = $opt->get_lib;
2828 # advanced option specifications
2929
3030 @adv_spec = (
31 Param("input")->required, # required
31 Param("input"),
3232 Param("mode")->default("tcp"), # defaults
3333 Param("host")->needs("port"), # dependencies
3434 Param("port")->valid(qr/\d+/), # regex validation
3535 Param("config")->valid(sub { -r }),# custom validation
3636 Param("help")->anycase, # case insensitivity
3737 );
38 $opt = Getopt::Lucid->getopt( \@adv_spec );
39 $opt->validate( 'requires' => ['input'] );
3840
3941 # example with a config file
4042
43 $opt = Getopt::Lucid->getopt( \@adv_spec );
4144 use Config::Std;
4245 if ( -r $opt->get_config ) {
4346 read_config( $opt->get_config() => my %config_hash );
105108 In practice, this means that the specification need not use dashes, but
106109 if used on the command line, they will be treated appropriately.
107110
108 Alternatively, Getopt::Lucid can operate in "strict" mode by setting
109 $Getopt::Lucid::STRICT to a true value. In strict mode, option names and
111 Alternatively, Getopt::Lucid can operate in "strict" mode by setting the
112 C<strict> parameter to a true value. In strict mode, option names and
110113 aliases may still be specified in any of the three styles, but they will
111114 only be parsed from the command line if they are used in exactly the
112115 same style. E.g., given the name and alias "--help|-h", only "--help"
228231 );
229232
230233 Validation
234 Validation happens in two stages. First, individual parameters may have
235 validation criteria added to them. Second, the parsed options object may
236 be validated by checking that all requirements or prerequires are met.
237
238 Parameter validation
231239 The Param, List, and Keypair option types may be provided an optional
232240 validation specification. Values provided on the command line will be
233241 validated according to the specification or an exception will be thrown.
246254 If no default is explictly provided, validation is only applied if the
247255 option appears on the command line. (In other words, the built-in
248256 defaults are always considered valid if the option does not appear.) If
249 this is not desired, the "required()" modifier should be used to force
250 users to provide an explicit value.
257 this is not desired, the "required" option to the "validate" method
258 should be used to force users to provide an explicit value.
251259
252260 # Must be provided and is thus always validated
253 Param("width")->valid(qr/\d+/)->required
254
255 # Can be left blank, but is validated if provided
256 Param("height")->valid(qr/\d+/)
261 @spec = ( Param("width")->valid(qr/\d+/) );
262 $opt = Getopt::Lucid->getopt(\@spec);
263 $opt->validate( {requires => ['width']} );
257264
258265 For validation subroutines, the value found on the command line is
259266 passed as the first element of @_, and $_ is also set equal to the first
269276
270277 # deprecated
271278 Param("height", qr/\d+/)
279
280 Options object validation
281 The "validate" method should be called on the result of "getopt". This
282 will check that all parameter prerequisites defined by "needs" have been
283 met. It also takes a hashref of arguments. The optional "requires"
284 argument gives an arrayref of parameters that must exist.
285
286 The reason that object validation is done separate from "getopt" is to
287 allow for better control over different options that might be required
288 or to allow some dependencies (i.e. from "needs") to be met via a
289 configuration file.
290
291 @spec = (
292 Param("action")->needs(qw/user password/),
293 Param("user"),
294 Param("password"),
295 );
296 $opt = Getopt::Lucid->getopt(\@spec);
297 $opt->merge_defaults( read_config() ); # provides 'user' & 'password'
298 $opt->validate({requires => ['action']});
272299
273300 Parsing the Command Line
274301 Technically, Getopt::Lucid scans an array for command line options, not
338365 accessor calls. E.g.
339366
340367 @spec = (
341 Param("--input-file|-i")->required(),
368 Param("--input-file|-i")
342369 );
343370
344371 $opt = Getopt::Long->getopt( \@spec );
470497 METHODS
471498 new()
472499 $opt = Getopt::Lucid->new( \@option_spec );
500 $opt = Getopt::Lucid->new( \@option_spec, \%parameters );
473501 $opt = Getopt::Lucid->new( \@option_spec, \@option_array );
502 $opt = Getopt::Lucid->new( \@option_spec, \@option_array, \%parameters );
474503
475504 Creates a new Getopt::Lucid object. An array reference to an option spec
476505 is required as an argument. (See "USAGE" for a description of the object
477506 spec). By default, objects will be set to read @ARGV for command line
478507 options. An optional second argument with a reference to an array will
479 use that array for option processing instead. For typical cases, users
480 will likely prefer to call "getopt" instead, which creates a new object
481 and parses the command line with a single function call.
508 use that array for option processing instead. The final argument may be
509 a hashref of parameters. The only valid parameter currently is:
510
511 * strict -- enables strict mode when true
512
513 For typical cases, users will likely prefer to call "getopt" instead,
514 which creates a new object and parses the command line with a single
515 function call.
516
517 validate()
518 $opt->validate();
519 $opt->validate( \%arguments );
520
521 Takes an optional argument hashref, validates that all requirements and
522 prerequisites are met or throws an error. Valid argument keys are:
523
524 * "requires" -- an arrayref of options that must exist in the options
525 object.
526
527 This method returns the object for convenient chaining:
528
529 $opt = Getopt::Lucid->getopt(\@spec)->validate;
482530
483531 append_defaults()
484532 %options = append_defaults( %config_hash );
563611 options. This undoes the effect of a "merge_defaults" or "add_defaults"
564612 call.
565613
614 API CHANGES
615 In 1.00, the following API changes have been made:
616
617 * "new()" now takes an optional hashref of parameters as the last
618 argument
619
620 * The global $STRICT variable has been replaced with a per-object
621 parameter "strict"
622
623 * The "required" modifier has been removed and a new "validate" method
624 has been added to facilitate late/custom checks of required options
625
566626 SEE ALSO
567627 * Config::Tiny
568628
582642 When submitting a bug or request, please include a test-file or a patch
583643 to an existing test-file that illustrates the bug or desired feature.
584644
645 SUPPORT
646 Bugs / Feature Requests
647 Please report any bugs or feature requests through the issue tracker at
648 <http://rt.cpan.org/Public/Dist/Display.html?Name=Getopt-Lucid>. You
649 will be notified automatically of any progress on your issue.
650
651 Source Code
652 This is open source software. The code repository is available for
653 public review and contribution under the terms of the license.
654
655 <https://github.com/dagolden/getopt-lucid>
656
657 git clone https://github.com/dagolden/getopt-lucid.git
658
585659 AUTHOR
586660 David Golden <dagolden@cpan.org>
587661
588662 COPYRIGHT AND LICENSE
589 This software is Copyright (c) 2010 by David Golden.
663 This software is Copyright (c) 2011 by David Golden.
590664
591665 This is free software, licensed under:
592666
0 README.PATCHING
1
2 Thank you for considering contributing to this distribution. This file
3 contains instructions that will help you work with the source code.
4
5 The distribution is managed with Dist::Zilla. This means than many of the
6 usual files you might expect are not in the repository, but are generated
7 at release time (e.g. Makefile.PL).
8
9 However, you can run tests directly using the 'prove' tool:
10
11 $ prove -l
12 $ prove -lv t/some_test_file.t
13
14 For most distributions, 'prove' is entirely sufficent for you to test any
15 patches you have.
16
17 Likewise, much of the documentation Pod is generated at release time.
18 Depending on the distribution, some documentation may be written in a Pod
19 dialect called WikiDoc. (See Pod::WikiDoc on CPAN.) If you would like to
20 submit a documentation edit, please limit yourself to the documentation you
21 see.
22
23 If you see typos or documentation issues in the generated docs, please
24 email or open a bug ticket instead of patching.
25
26 Dist::Zilla is a very powerful authoring tool, but requires a number of
27 author-specific plugins. If you would like to use it for contributing,
28 install it from CPAN, then run one of the following commands, depending on
29 your CPAN client:
30
31 $ cpan `dzil authordeps`
32 $ dzil authordeps | cpanm
33
34 Once installed, here are some dzil commands you might try:
35
36 $ dzil build
37 $ dzil test
38 $ dzil xtest
39
40 You can learn more about Dist::Zilla at http://dzil.org/
41
3535 # Bugfixes/technical/other
3636 #--------------------------------------------------------------------------#
3737
38 - make STRICT an object parameter, not a global
3938 - test how negation is handled under $STRICT
4039 - write cookbook
4140 - refactor ugly code (module and tests)
33 copyright_holder = David Golden
44
55 [@DAGOLDEN]
6 git_remote = github
6 :version = 0.018
77
8 [Test::Perl::Critic]
9
00 #!/usr/bin/env perl
1 #
2 # This file is part of Getopt-Lucid
3 #
4 # This software is Copyright (c) 2010 by David Golden.
5 #
6 # This is free software, licensed under:
7 #
8 # The Apache License, Version 2.0, January 2004
9 #
101 use strict;
112 use warnings;
123
0 #
1 # This file is part of Getopt-Lucid
2 #
3 # This software is Copyright (c) 2010 by David Golden.
4 #
5 # This is free software, licensed under:
6 #
7 # The Apache License, Version 2.0, January 2004
8 #
90 use 5.006;
101 use strict;
112 use warnings;
123 package Getopt::Lucid::Exception;
13 BEGIN {
14 $Getopt::Lucid::Exception::VERSION = '0.19';
15 }
164 # ABSTRACT: Exception classes for Getopt::Lucid
5 our $VERSION = '1.00'; # VERSION
176
187 use Exception::Class 1.23 (
198 "Getopt::Lucid::Exception" => {
5847
5948 =head1 VERSION
6049
61 version 0.19
50 version 1.00
6251
6352 =head1 AUTHOR
6453
6655
6756 =head1 COPYRIGHT AND LICENSE
6857
69 This software is Copyright (c) 2010 by David Golden.
58 This software is Copyright (c) 2011 by David Golden.
7059
7160 This is free software, licensed under:
7261
0 #
1 # This file is part of Getopt-Lucid
2 #
3 # This software is Copyright (c) 2010 by David Golden.
4 #
5 # This is free software, licensed under:
6 #
7 # The Apache License, Version 2.0, January 2004
8 #
90 use 5.006;
101 use strict;
112 use warnings;
123 package Getopt::Lucid;
134 # ABSTRACT: Clear, readable syntax for command line processing
5 our $VERSION = '1.00'; # VERSION
146
157 our @EXPORT_OK = qw(Switch Counter Param List Keypair);
168 our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
3123 my $SHORT_BUNDLE = qr/-[$VALID_STARTCHAR]{2,}/;
3224 my $NEGATIVE = qr/(?:--)?no-/;
3325
34 my @valid_keys = qw( name type required default nocase valid needs canon );
26 my @valid_keys = qw( name type default nocase valid needs canon );
3527 my @valid_types = qw( switch counter parameter list keypair);
36
37 use vars qw( $STRICT );
38 $STRICT = 0;
39
4028
4129 sub Switch {
4230 return bless { name => shift, type => 'switch' },
6250 return bless $self, "Getopt::Lucid::Spec";
6351 }
6452
65 package # hide from PAUSE
53 package
6654 Getopt::Lucid::Spec;
67 our $VERSION = $Getopt::Lucid::VERSION;
55 $Getopt::Lucid::Spec::VERSION = $Getopt::Lucid::VERSION;
6856
6957 # alternate way to specify validation
7058 sub valid {
7563 return $self;
7664 }
7765
78 sub required { my $self = shift; $self->{required} = 1; return $self };
79
8066 sub default {
8167 my $self = shift;
8268 my $type = $self->{type};
11096 # new()
11197 #--------------------------------------------------------------------------#
11298
99 my @params = qw/strict target/;
100
113101 sub new {
114102 my ($class, $spec, $target) = @_;
103 my $args = ref($_[-1]) eq 'HASH' ? pop(@_) : {};
104 $args->{target} = ref($target) eq 'ARRAY' ? $target : \@ARGV;
105 my $self = {};
106 $self->{$_} = $args->{$_} for @params;
107 $self->{raw_spec} = $spec;
108 bless ($self, ref($class) ? ref($class) : $class);
115109 throw_usage("Getopt::Lucid->new() requires an option specification array reference")
116 unless ref($spec) eq 'ARRAY';
117 my $self = bless ({}, ref($class) ? ref($class) : $class);
118 _parse_spec($self, $spec);
110 unless ref($self->{raw_spec}) eq 'ARRAY';
111 _parse_spec($self);
119112 _set_defaults($self);
120113 $self->{options} = {};
121114 $self->{parsed} = [];
122115 $self->{seen}{$_} = 0 for keys %{$self->{spec}};
123 $self->{target} = $target || \@ARGV;
124116 return $self;
125117 }
126118
192184 if ( $self eq 'Getopt::Lucid' ) {
193185 throw_usage("Getopt::Lucid->getopt() requires an option specification array reference")
194186 unless ref($spec) eq 'ARRAY';
195 $self = new($self,$spec,$target)
187 $self = new(@_)
196188 }
197189 my (@passthrough);
198190 while (@{$self->{target}}) {
220212 push @passthrough, $orig;
221213 }
222214 }
223 _check_required($self);
224 _check_prereqs($self);
225215 _recalculate_options($self);
226216 @{$self->{target}} = (@passthrough, @{$self->{target}});
227217 return $self;
228218 }
229219
230220 BEGIN { *getopts = \&getopt }; # handy alias
221
222 #--------------------------------------------------------------------------#
223 # validate
224 #--------------------------------------------------------------------------#
225
226 sub validate {
227 my ($self, $arg) = @_;
228 throw_usage("Getopt::Lucid->validate() takes an optional hashref argument")
229 unless $arg && ref($arg) eq 'HASH';
230
231 for my $p ( @{$arg->{requires}} ) {
232 throw_argv("Required option '$self->{spec}{$p}{canon}' not found")
233 if ( ! $self->{seen}{$p} );
234 }
235 _check_prereqs($self);
236
237 return $self;
238 }
231239
232240 #--------------------------------------------------------------------------#
233241 # merge_defaults()
368376 }
369377
370378 #--------------------------------------------------------------------------#
371 # _check_required()
372 #--------------------------------------------------------------------------#
373
374 sub _check_required {
375 my ($self) = @_;
376 for ( keys %{$self->{spec}} ) {
377 throw_argv("Required option '$self->{spec}{$_}{canon}' not found")
378 if ( $self->{spec}{$_}{required} && ! $self->{seen}{$_} );
379 }
380 }
381
382 #--------------------------------------------------------------------------#
383379 # _counter()
384380 #--------------------------------------------------------------------------#
385381
397393 sub _find_arg {
398394 my ($self, $arg) = @_;
399395
400 $arg =~ s/^-*// unless $STRICT;
396 $arg =~ s/^-*// unless $self->{strict};
401397 return $self->{alias_hr}{$arg} if exists $self->{alias_hr}{$arg};
402398
403399 for ( keys %{$self->{alias_nocase}} ) {
477473 #--------------------------------------------------------------------------#
478474
479475 sub _parse_spec {
480 my ($self,$spec) = @_;
476 my ($self) = @_;
477 my $spec = $self->{raw_spec};
481478 for my $opt ( @$spec ) {
482479 my $name = $opt->{name};
483480 my @names = split( /\|/, $name );
484481 $opt->{canon} = $names[0];
485482 _validate_spec($self,\@names,$opt);
486 @names = map { s/^-*//; $_ } @names unless $STRICT; ## no critic
483 @names = map { s/^-*//; $_ } @names unless $self->{strict}; ## no critic
487484 for (@names) {
488485 $self->{alias_hr}{$_} = $names[0];
489486 $self->{alias_nocase}{$_} = $names[0] if $opt->{nocase};
669666 my ($self,$names,$details) = @_;
670667 for my $name ( @$names ) {
671668 my $alt_name = $name;
672 $alt_name =~ s/^-*// unless $STRICT;
669 $alt_name =~ s/^-*// unless $self->{strict};
673670 throw_spec(
674671 "'$name' is not a valid option name/alias"
675672 ) unless $name =~ /^$VALID_NAME$/;
775772
776773 =head1 VERSION
777774
778 version 0.19
775 version 1.00
779776
780777 =head1 SYNOPSIS
781778
792789 Switch("help|h")
793790 );
794791
795 $opt = Getopt::Lucid->getopt( \@specs );
792 $opt = Getopt::Lucid->getopt( \@specs )->validate;
796793
797794 $verbosity = $opt->get_verbose;
798795 @libs = $opt->get_lib;
803800 # advanced option specifications
804801
805802 @adv_spec = (
806 Param("input")->required, # required
803 Param("input"),
807804 Param("mode")->default("tcp"), # defaults
808805 Param("host")->needs("port"), # dependencies
809806 Param("port")->valid(qr/\d+/), # regex validation
810807 Param("config")->valid(sub { -r }),# custom validation
811808 Param("help")->anycase, # case insensitivity
812809 );
810 $opt = Getopt::Lucid->getopt( \@adv_spec );
811 $opt->validate( 'requires' => ['input'] );
813812
814813 # example with a config file
815814
815 $opt = Getopt::Lucid->getopt( \@adv_spec );
816816 use Config::Std;
817817 if ( -r $opt->get_config ) {
818818 read_config( $opt->get_config() => my %config_hash );
910910 used on the command line, they will be treated appropriately.
911911
912912 Alternatively, Getopt::Lucid can operate in "strict" mode by setting
913 C<<< $Getopt::Lucid::STRICT >>> to a true value. In strict mode, option names
913 the CE<lt>strictE<gt> parameter to a true value. In strict mode, option names
914914 and aliases may still be specified in any of the three styles, but they
915915 will only be parsed from the command line if they are used in exactly
916916 the same style. E.g., given the name and alias "--helpE<verbar>-h", only "--help"
10431043
10441044 =head2 Validation
10451045
1046 Validation happens in two stages. First, individual parameters may have
1047 validation criteria added to them. Second, the parsed options object may be
1048 validated by checking that all requirements or prerequires are met.
1049
1050 =head3 Parameter validation
1051
10461052 The Param, List, and Keypair option types may be provided an optional
10471053 validation specification. Values provided on the command line will be
10481054 validated according to the specification or an exception will be thrown.
10601066 If no default is explictly provided, validation is only applied if the option
10611067 appears on the command line. (In other words, the built-in defaults are always
10621068 considered valid if the option does not appear.) If this is not desired, the
1063 C<<< required() >>> modifier should be used to force users to provide an explicit
1064 value.
1069 C<<< required >>> option to the C<<< validate >>> method should be used to force users to
1070 provide an explicit value.
10651071
10661072 # Must be provided and is thus always validated
1067 Param("width")->valid(qr/\d+/)->required
1068
1069 # Can be left blank, but is validated if provided
1070 Param("height")->valid(qr/\d+/)
1073 @spec = ( Param("width")->valid(qr/\d+/) );
1074 $opt = Getopt::Lucid->getopt(\@spec);
1075 $opt->validate( {requires => ['width']} );
10711076
10721077 For validation subroutines, the value found on the command line is passed as
10731078 the first element of C<<< @_ >>>, and C<<< $_ >>> is also set equal to the first element.
10831088
10841089 # deprecated
10851090 Param("height", qr/\d+/)
1091
1092 =head3 Options object validation
1093
1094 The C<<< validate >>> method should be called on the result of C<<< getopt >>>. This will
1095 check that all parameter prerequisites defined by C<<< needs >>> have been met. It
1096 also takes a hashref of arguments. The optional C<<< requires >>> argument gives an
1097 arrayref of parameters that must exist.
1098
1099 The reason that object validation is done separate from C<<< getopt >>> is to allow
1100 for better control over different options that might be required or to allow
1101 some dependencies (i.e. from C<<< needs >>>) to be met via a configuration file.
1102
1103 @spec = (
1104 Param("action")->needs(qw/user password/),
1105 Param("user"),
1106 Param("password"),
1107 );
1108 $opt = Getopt::Lucid->getopt(\@spec);
1109 $opt->merge_defaults( read_config() ); # provides 'user' & 'password'
1110 $opt->validate({requires => ['action']});
10861111
10871112 =head2 Parsing the Command Line
10881113
11521177 calls. E.g.
11531178
11541179 @spec = (
1155 Param("--input-file|-i")->required(),
1180 Param("--input-file|-i")
11561181 );
11571182
11581183 $opt = Getopt::Long->getopt( \@spec );
13221347 =head2 new()
13231348
13241349 $opt = Getopt::Lucid->new( \@option_spec );
1350 $opt = Getopt::Lucid->new( \@option_spec, \%parameters );
13251351 $opt = Getopt::Lucid->new( \@option_spec, \@option_array );
1352 $opt = Getopt::Lucid->new( \@option_spec, \@option_array, \%parameters );
13261353
13271354 Creates a new Getopt::Lucid object. An array reference to an option spec is
13281355 required as an argument. (See L</USAGE> for a description of the object spec).
13291356 By default, objects will be set to read @ARGV for command line options. An
13301357 optional second argument with a reference to an array will use that array for
1331 option processing instead. For typical cases, users will likely prefer
1332 to call C<<< getopt >>> instead, which creates a new object and parses the command
1333 line with a single function call.
1358 option processing instead. The final argument may be a hashref of parameters.
1359 The only valid parameter currently is:
1360
1361 =over
1362
1363 =item *
1364
1365 strict -- enables strict mode when true
1366
1367 =back
1368
1369 For typical cases, users will likely prefer to call C<<< getopt >>> instead, which
1370 creates a new object and parses the command line with a single function call.
1371
1372 =head2 validate()
1373
1374 $opt->validate();
1375 $opt->validate( \%arguments );
1376
1377 Takes an optional argument hashref, validates that all requirements and
1378 prerequisites are met or throws an error. Valid argument keys are:
1379
1380 =over
1381
1382 =item *
1383
1384 C<<< requires >>> -- an arrayref of options that must exist in the options
1385 object.
1386
1387 =back
1388
1389 This method returns the object for convenient chaining:
1390
1391 $opt = Getopt::Lucid->getopt(\@spec)->validate;
13341392
13351393 =head2 append_defaults()
13361394
14181476 restored defaults, and returns a hash with the resulting options. This
14191477 undoes the effect of a C<<< merge_defaults >>> or C<<< add_defaults >>> call.
14201478
1479 =head1 API CHANGES
1480
1481 In 1.00, the following API changes have been made:
1482
1483 =over
1484
1485 =item *
1486
1487 C<<< new() >>> now takes an optional hashref of parameters as the last
1488 argument
1489
1490 =item *
1491
1492 The global C<<< $STRICT >>> variable has been replaced with a per-object
1493 parameter C<<< strict >>>
1494
1495 =item *
1496
1497 The C<<< required >>> modifier has been removed and a new C<<< validate >>> method
1498 has been added to facilitate lateE<sol>custom checks of required options
1499
1500 =back
1501
14211502 =head1 SEE ALSO
14221503
14231504 =over
14531534 When submitting a bug or request, please include a test-file or a patch to an
14541535 existing test-file that illustrates the bug or desired feature.
14551536
1537 =for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders
1538
1539 =head1 SUPPORT
1540
1541 =head2 Bugs / Feature Requests
1542
1543 Please report any bugs or feature requests through the issue tracker
1544 at L<http://rt.cpan.org/Public/Dist/Display.html?Name=Getopt-Lucid>.
1545 You will be notified automatically of any progress on your issue.
1546
1547 =head2 Source Code
1548
1549 This is open source software. The code repository is available for
1550 public review and contribution under the terms of the license.
1551
1552 L<https://github.com/dagolden/getopt-lucid>
1553
1554 git clone https://github.com/dagolden/getopt-lucid.git
1555
14561556 =head1 AUTHOR
14571557
14581558 David Golden <dagolden@cpan.org>
14591559
14601560 =head1 COPYRIGHT AND LICENSE
14611561
1462 This software is Copyright (c) 2010 by David Golden.
1562 This software is Copyright (c) 2011 by David Golden.
14631563
14641564 This is free software, licensed under:
14651565
0 severity = 5
1 verbose = 8
2
3 [Variables::ProhibitPunctuationVars]
4 allow = $@ $!
5
6 # Turn these off
7 [-BuiltinFunctions::ProhibitStringyEval]
8 [-ControlStructures::ProhibitPostfixControls]
9 [-ControlStructures::ProhibitUnlessBlocks]
10 [-Documentation::RequirePodSections]
11 [-InputOutput::ProhibitInteractiveTest]
12 [-Miscellanea::RequireRcsKeywords]
13 [-References::ProhibitDoubleSigils]
14 [-RegularExpressions::RequireExtendedFormatting]
15 [-InputOutput::ProhibitTwoArgOpen]
16 [-TestingAndDebugging::ProhibitNoStrict]
17
18 # Turn this on
19 [Lax::ProhibitStringyEval::ExceptForRequire]
20
00 #!perl
1 #
2 # This file is part of Getopt-Lucid
3 #
4 # This software is Copyright (c) 2010 by David Golden.
5 #
6 # This is free software, licensed under:
7 #
8 # The Apache License, Version 2.0, January 2004
9 #
101
112 use strict;
123 use warnings;
134
145 use Test::More;
6
7
8
159 use File::Find;
1610 use File::Temp qw{ tempdir };
1711
2923 'lib',
3024 );
3125
32 my @scripts = glob "bin/*";
26 my @scripts;
27 if ( -d 'bin' ) {
28 find(
29 sub {
30 return unless -f;
31 my $found = $File::Find::name;
32 # nothing to skip
33 push @scripts, $found;
34 },
35 'bin',
36 );
37 }
3338
3439 my $plan = scalar(@modules) + scalar(@scripts);
3540 $plan ? (plan tests => $plan) : (plan skip_all => "no tests to run");
0 # Getopt::Lucid::Exception
0 # Getopt::Lucid::Exception
11 use strict;
22 use Test::More 0.62;
33 #--------------------------------------------------------------------------#
435435 label => "required options",
436436 spec => [
437437 Counter("--verbose|-v"),
438 Param("--input|-i")->required,
438 Param("--input|-i")
439439 ],
440440 cases => [
441441 {
442442 argv => [ qw( -v ) ],
443443 exception => "Getopt::Lucid::Exception::ARGV",
444444 error_msg => _required("--input"),
445 required => ['input'],
445446 desc => "missing required option"
446447 },
447448 {
448449 argv => [ qw( --input 42 -vv ) ],
450 required => ['input'],
449451 result => { "verbose" => 2, "input" => 42 },
450452 desc => "required option present"
451453 },
452454 {
453455 argv => [ qw( --input info -v ) ],
456 required => ['input'],
454457 result => { "verbose" => 1, "input" => 'info' },
455458 desc => "required option param similar to option name"
456459 },
647650 push @good_specs, {
648651 label => "validate w/ string alternation regex",
649652 spec => [
650 Param( "mode|m", qr/test|live/ )->required
653 Param( "mode|m", qr/test|live/ ),
651654 ],
652655 cases => [
653656 {
654657 argv => [ qw( --mode test ) ],
658 required => ['mode'],
655659 result => {
656660 "mode" => 'test',
657661 },
659663 },
660664 {
661665 argv => [ qw( --mode foo ) ],
666 required => ['mode'],
662667 exception => "Getopt::Lucid::Exception::ARGV",
663668 error_msg => _param_invalid("mode","foo"),
664669 desc => "param mode not validating"
982987 my $gl = Getopt::Lucid->new($trial->{spec});
983988 @ARGV = @{$case->{argv}};
984989 my %opts;
985 try eval { %opts = $gl->getopt->options };
990 my $valid_args = $case->{required} ? {requires => $case->{required}}
991 : {};
992 try eval { %opts = $gl->getopt->validate($valid_args)->options };
986993 catch my $err;
987994 if (defined $case->{exception}) { # expected
988995 ok( $err && $err->isa( $case->{exception} ),
2121 my ($num_tests, @good_specs);
2222
2323 BEGIN {
24
25 push @good_specs, {
24
25 push @good_specs, {
2626 label => "parse another array than \@ARGV",
2727 spec => [
2828 Switch("--verbose"),
3030 Switch("-r"),
3131 ],
3232 cases => [
33 {
33 {
3434 argv => [ qw( --verbose -r -- --test ) ],
3535 result => { "verbose" => 1, "test" => 0, "r" => 1 },
3636 after => [ qw( --test ) ],
3737 desc => "stop after two"
38 },
39 {
38 },
39 {
4040 argv => [ qw( -- -r --test ) ],
4141 result => { "verbose" => 0, "test" => 0, "r" => 0 },
4242 after => [ qw(-r --test ) ],
4343 desc => "stop right away"
44 },
44 },
4545 ]
4646 };
4747
4848
49 } #BEGIN
49 } #BEGIN
5050
5151 for my $t (@good_specs) {
5252 $num_tests += 1 + 2 * @{$t->{cases}};
6464 try eval { Getopt::Lucid->new($trial->{spec}, \@cmd_line) };
6565 catch my $err;
6666 is( $err, undef, "$trial->{label}: spec should validate" );
67 SKIP: {
67 SKIP: {
6868 if ($err) {
6969 my $num_tests = 2 * @{$trial->{cases}};
7070 skip "because $trial->{label} spec did not validate", $num_tests;
7676 try eval { %opts = $gl->getopt->options };
7777 catch my $err;
7878 if (defined $case->{exception}) { # expected
79 ok( $err && $err->isa( $case->{exception} ),
79 ok( $err && $err->isa( $case->{exception} ),
8080 "$trial->{label}: $case->{desc} should throw exception" )
8181 or diag why( got => ref($err), expected => $case->{exception});
82 is( $err, $case->{error_msg},
82 is( $err, $case->{error_msg},
8383 "$trial->{label}: $case->{desc} error message correct");
8484 } elsif ($err) { # unexpected
8585 fail( "$trial->{label}: $case->{desc} threw an exception")
8686 or diag "Exception is '$err'";
8787 pass("$trial->{label}: skipping \@ARGV check");
8888 } else { # no exception
89 is_deeply( \%opts, $case->{result},
89 is_deeply( \%opts, $case->{result},
9090 "$trial->{label}: $case->{desc}" ) or
9191 diag why( got => \%opts, expected => $case->{result});
9292 my $argv_after = $case->{after} || [];
1818 # Test cases
1919 #--------------------------------------------------------------------------#
2020
21 my $spec = [
21 my $spec = [
2222 Switch("--ver-bose"),
2323 Switch("--test"),
2424 Switch("-r"),
3030 try eval { $gl = Getopt::Lucid->new($spec) };
3131 catch my $err;
3232 is( $err, undef, "spec should validate" );
33 SKIP: {
33 SKIP: {
3434 skip( "because spec did not validate", 1) if $err;
3535 my @expect = sort qw(ver-bose test r);
3636 my @got = sort $gl->names();
2222 Switch("-t"),
2323 Counter("--verb_osity"),
2424 Param("--file-name"),
25 List("-I"),
25 List("-I"),
2626 Keypair("-d"),
2727 ];
2828
29 my $case = {
30 argv => [ qw( --verb_osity -t --file-name=passwd
29 my $case = {
30 argv => [ qw( --verb_osity -t --file-name=passwd
3131 -I /etc -I /lib -d os=linux ) ],
32 result => {
33 t => 1,
34 verb_osity => 1,
35 "file-name" => "passwd",
32 result => {
33 t => 1,
34 verb_osity => 1,
35 "file-name" => "passwd",
3636 I => [qw(/etc /lib)],
3737 d => { os => "linux" },
3838 },
3939 desc => "getopt accessors"
4040 };
4141
42 my $replace = {
43 t => 2,
44 verb_osity => 3,
45 "file-name" => "group",
42 my $replace = {
43 t => 2,
44 verb_osity => 3,
45 "file-name" => "group",
4646 I => [qw(/var /tmp)],
4747 d => { os => "win32" },
4848 };
5454 try eval { $gl = Getopt::Lucid->new($spec, \@cmd_line) };
5555 catch my $err;
5656 is( $err, undef, "spec should validate" );
57 SKIP: {
57 SKIP: {
5858 if ($err) {
5959 skip "because spec did not validate", $num_tests - 1;
6060 }
7373 my $result = $case->{result}{$key};
7474 (my $clean_key = $key ) =~ s/-/_/g;
7575 if ( ref($result) eq 'ARRAY' ) {
76 is_deeply( [eval "\$gl->get_$clean_key"], $result,
76 is_deeply( [eval "\$gl->get_$clean_key"], $result,
7777 "accessor for '$key' correct");
7878 &{"Getopt::Lucid::set_$clean_key"}($gl,@{$replace->{$key}});
79 is_deeply( [eval "\$gl->get_$clean_key"], $replace->{$key},
79 is_deeply( [eval "\$gl->get_$clean_key"], $replace->{$key},
8080 "mutator for '$key' correct");
8181 } elsif ( ref($result) eq 'HASH' ) {
82 is_deeply( {eval "\$gl->get_$clean_key"}, $result,
82 is_deeply( {eval "\$gl->get_$clean_key"}, $result,
8383 "accessor for '$key' correct");
8484 &{"Getopt::Lucid::set_$clean_key"}($gl,%{$replace->{$key}});
85 is_deeply( {eval "\$gl->get_$clean_key"}, $replace->{$key},
85 is_deeply( {eval "\$gl->get_$clean_key"}, $replace->{$key},
8686 "mutator for '$key' correct");
8787 } else {
8888 is( (eval "\$gl->get_$clean_key") , $result,
8989 "accessor for '$key' correct");
9090 &{"Getopt::Lucid::set_$clean_key"}($gl,$replace->{$key});
91 is( eval "\$gl->get_$clean_key", $replace->{$key},
91 is( eval "\$gl->get_$clean_key", $replace->{$key},
9292 "mutator for '$key' correct");
9393 }
9494 }
6464
6565 # package variables for easier looping by name later
6666
67 use vars qw(
67 use vars qw(
6868 $merge_default $merge_result
6969 $append_default $append_result
7070 $replace_default $replace_result
178178 : undef;
179179 }
180180 is_deeply( {$gl->defaults}, \%basic_default,
181 "basic default options returned correctly") or
181 "basic default options returned correctly") or
182182 diag why( got => {$gl->options}, expected => \%basic_default);
183183 is_deeply( {$gl->options}, $expect,
184 "options with default from spec processed correctly") or
184 "options with default from spec processed correctly") or
185185 diag why( got => {$gl->options}, expected => $expect);
186186
187187 # Test things working correctly
196196 ? "hash version"
197197 : "hashref version";
198198 is_deeply( {$gl->defaults}, $$default,
199 "$call updated defaults correctly ($msg)") or
199 "$call updated defaults correctly ($msg)") or
200200 diag why( got => {$gl->defaults}, expected => $$default);
201201 is_deeply( {$gl->options}, $$result,
202 "$call refreshed options correctly ($msg)") or
202 "$call refreshed options correctly ($msg)") or
203203 diag why( got => {$gl->options}, expected => $$result);
204204 $gl->reset_defaults();
205205 is_deeply( {$gl->options}, $expect,
206 "options reset to spec correctly ($msg)") or
206 "options reset to spec correctly ($msg)") or
207207 diag why( got => {$gl->options}, expected => $expect);
208208 }
209209 }
2222 my ($num_tests, @good_specs);
2323
2424 BEGIN {
25
26 push @good_specs, {
25
26 push @good_specs, {
2727 label => "magic bare names in spec",
2828 spec => [
2929 Counter("ver-bose|v"),
3232 Param("f"),
3333 ],
3434 cases => [
35 {
35 {
3636 argv => [ qw( --ver-bose v -rtvf=test --r test -- test ) ],
37 result => {
38 "ver-bose" => 3,
39 "test" => 2,
40 "r" => 2,
37 result => {
38 "ver-bose" => 3,
39 "test" => 2,
40 "r" => 2,
4141 "f" => "test",
4242 },
4343 after => [qw( test )],
4444 desc => "all three types in command line"
45 },
46 {
45 },
46 {
4747 argv => [ qw( --ver-bose v -rtvf fest --r test -- test ) ],
48 result => {
49 "ver-bose" => 3,
50 "test" => 2,
51 "r" => 2,
48 result => {
49 "ver-bose" => 3,
50 "test" => 2,
51 "r" => 2,
5252 "f" => "fest",
5353 },
5454 after => [qw( test )],
5555 desc => "all three types in command line"
56 },
57 {
56 },
57 {
5858 argv => [ qw( -test ) ],
5959 exception => "Getopt::Lucid::Exception::ARGV",
6060 error_msg => _invalid_argument("-e"),
61 desc => "single dash with word"
62 },
63 {
61 desc => "single dash with word"
62 },
63 {
6464 argv => [ qw( f test ) ],
6565 exception => "Getopt::Lucid::Exception::ARGV",
6666 error_msg => _param_ambiguous("f", "test"),
67 desc => "ambiguous param -- bareword"
68 },
69 {
67 desc => "ambiguous param -- bareword"
68 },
69 {
7070 argv => [ qw( f --test ) ],
7171 exception => "Getopt::Lucid::Exception::ARGV",
7272 error_msg => _param_ambiguous("f", "--test"),
73 desc => "ambiguous param -- long form"
74 },
73 desc => "ambiguous param -- long form"
74 },
7575 ]
7676 };
7777
78 push @good_specs, {
78 push @good_specs, {
7979 label => "avoid ambiguity (RT 33462)",
8080 spec => [
81 Param("config|c")->required(),
81 Param("config|c"),
8282 Switch("help|h")->anycase(),
8383 ],
8484 cases => [
85 {
85 {
8686 argv => [ qw( -c /home/newuat5/nas/Abilit/newuat6/test_home/Data/tdg/testdatengenerator.conf ) ],
87 result => {
88 "config" => "/home/newuat5/nas/Abilit/newuat6/test_home/Data/tdg/testdatengenerator.conf",
87 required => ['config'],
88 result => {
89 "config" => "/home/newuat5/nas/Abilit/newuat6/test_home/Data/tdg/testdatengenerator.conf",
8990 "help" => 0,
9091 },
9192 after => [],
9293 desc => "single dash option"
93 },
94 },
9495 ]
9596 };
9697
9798
98 } #BEGIN
99 } #BEGIN
99100
100101 for my $t (@good_specs) {
101102 $num_tests += 1 + 2 * @{$t->{cases}};
113114 try eval { Getopt::Lucid->new($trial->{spec}, \@cmd_line) };
114115 catch my $err;
115116 is( $err, undef, "$trial->{label}: spec should validate" );
116 SKIP: {
117 SKIP: {
117118 if ($err) {
118119 my $num_tests = 2 * @{$trial->{cases}};
119120 skip "because $trial->{label} spec did not validate", $num_tests;
122123 my $gl = Getopt::Lucid->new($trial->{spec}, \@cmd_line);
123124 @cmd_line = @{$case->{argv}};
124125 my %opts;
125 try eval { %opts = $gl->getopt->options };
126 my $valid_args = $case->{required} ? {requires => $case->{required}}
127 : {};
128 try eval { %opts = $gl->getopt->validate($valid_args)->options };
126129 catch my $err;
127130 if (defined $case->{exception}) { # expected
128 ok( $err && $err->isa( $case->{exception} ),
131 ok( $err && $err->isa( $case->{exception} ),
129132 "$trial->{label}: $case->{desc} should throw exception" )
130133 or diag why( got => ref($err), expected => $case->{exception});
131 is( $err, $case->{error_msg},
134 is( $err, $case->{error_msg},
132135 "$trial->{label}: $case->{desc} error message correct");
133136 } elsif ($err) { # unexpected
134137 fail( "$trial->{label}: $case->{desc} threw an exception")
135138 or diag "Exception is '$err'";
136139 pass("$trial->{label}: skipping \@ARGV check");
137140 } else { # no exception
138 is_deeply( \%opts, $case->{result},
141 is_deeply( \%opts, $case->{result},
139142 "$trial->{label}: $case->{desc}" ) or
140143 diag why( got => \%opts, expected => $case->{result});
141144 my $argv_after = $case->{after} || [];
88 use Getopt::Lucid ':all';
99 use Getopt::Lucid::Exception;
1010 use t::ErrorMessages;
11
12 $Getopt::Lucid::STRICT = 1;
1311
1412 sub why {
1513 my %vars = @_;
2422 my ($num_tests, @good_specs);
2523
2624 BEGIN {
27
28 push @good_specs, {
25
26 push @good_specs, {
2927 label => "mixed format names in spec",
3028 spec => [
3129 Counter("ver-bose|-v"),
3432 Param("f"),
3533 ],
3634 cases => [
37 {
35 {
3836 argv => [ qw( ver-bose -v -rtv f=test -r --test -- test ) ],
39 result => {
40 "ver-bose" => 3,
41 "test" => 2,
42 "r" => 2,
37 result => {
38 "ver-bose" => 3,
39 "test" => 2,
40 "r" => 2,
4341 "f" => "test",
4442 },
4543 after => [qw( test )],
4644 desc => "all three types in command line"
47 },
48 {
45 },
46 {
4947 argv => [ qw( ver-bose -v -rtv f test -r --test -- test ) ],
50 result => {
51 "ver-bose" => 3,
52 "test" => 2,
53 "r" => 2,
48 result => {
49 "ver-bose" => 3,
50 "test" => 2,
51 "r" => 2,
5452 "f" => "test",
5553 },
5654 after => [qw( test )],
5755 desc => "bare param with bare like long-form in spec"
58 },
59 {
56 },
57 {
6058 argv => [ qw( ver-bose -v -rtv f=test -r test ) ],
61 result => {
62 "ver-bose" => 3,
63 "test" => 1,
64 "r" => 2,
59 result => {
60 "ver-bose" => 3,
61 "test" => 1,
62 "r" => 2,
6563 "f" => "test",
6664 },
6765 after => [qw( test )],
6866 desc => "bareword like long-form in spec passed through"
69 },
70 {
67 },
68 {
7169 argv => [ qw( -test ) ],
7270 exception => "Getopt::Lucid::Exception::ARGV",
7371 error_msg => _invalid_argument("-e"),
74 desc => "single dash with word"
75 },
76 {
72 desc => "single dash with word"
73 },
74 {
7775 argv => [ qw( --ver-bose ) ],
7876 exception => "Getopt::Lucid::Exception::ARGV",
7977 error_msg => _invalid_argument("--ver-bose"),
80 desc => "long form like bareword in spec"
81 },
82 {
78 desc => "long form like bareword in spec"
79 },
80 {
8381 argv => [ qw( --r ) ],
8482 exception => "Getopt::Lucid::Exception::ARGV",
8583 error_msg => _invalid_argument("--r"),
86 desc => "long form like short in spec"
87 },
88 {
84 desc => "long form like short in spec"
85 },
86 {
8987 argv => [ qw( -f=--test ) ],
9088 exception => "Getopt::Lucid::Exception::ARGV",
9189 error_msg => _invalid_argument("-f"),
92 desc => "shoft form like bare in spec"
93 },
90 desc => "shoft form like bare in spec"
91 },
9492 ]
9593 };
9694
9795
98 } #BEGIN
96 } #BEGIN
9997
10098 for my $t (@good_specs) {
10199 $num_tests += 1 + 2 * @{$t->{cases}};
110108 my ($trial, @cmd_line);
111109
112110 while ( $trial = shift @good_specs ) {
113 try eval { Getopt::Lucid->new($trial->{spec}, \@cmd_line) };
111 try eval { Getopt::Lucid->new($trial->{spec}, \@cmd_line, {strict => 1}) };
114112 catch my $err;
115113 is( $err, undef, "$trial->{label}: spec should validate" );
116 SKIP: {
114 SKIP: {
117115 if ($err) {
118116 my $num_tests = 2 * @{$trial->{cases}};
119117 skip "because $trial->{label} spec did not validate", $num_tests;
120118 }
121119 for my $case ( @{$trial->{cases}} ) {
122 my $gl = Getopt::Lucid->new($trial->{spec}, \@cmd_line);
120 my $gl = Getopt::Lucid->new($trial->{spec}, \@cmd_line, {strict => 1});
123121 @cmd_line = @{$case->{argv}};
124122 my %opts;
125123 try eval { %opts = $gl->getopt->options };
126124 catch my $err;
127125 if (defined $case->{exception}) { # expected
128 ok( $err && $err->isa( $case->{exception} ),
126 ok( $err && $err->isa( $case->{exception} ),
129127 "$trial->{label}: $case->{desc} should throw exception" )
130128 or diag why( got => ref($err), expected => $case->{exception});
131 is( $err, $case->{error_msg},
129 is( $err, $case->{error_msg},
132130 "$trial->{label}: $case->{desc} error message correct");
133131 } elsif ($err) { # unexpected
134132 fail( "$trial->{label}: $case->{desc} threw an exception")
135133 or diag "Exception is '$err'";
136134 pass("$trial->{label}: skipping \@ARGV check");
137135 } else { # no exception
138 is_deeply( \%opts, $case->{result},
136 is_deeply( \%opts, $case->{result},
139137 "$trial->{label}: $case->{desc}" ) or
140138 diag why( got => \%opts, expected => $case->{result});
141139 my $argv_after = $case->{after} || [];
131131 push @good_specs, {
132132 label => "required/prereq",
133133 spec => [
134 Switch("test")->required,
134 Switch("test"),
135135 Param("input")->needs("output"),
136136 Param("output"),
137137 ],
139139 {
140140 argv => [ qw( --test --no-test ) ],
141141 exception => "Getopt::Lucid::Exception::ARGV",
142 required => ['test'],
142143 error_msg => _required("test"),
143144 desc => "missing requirement after negation"
144145 },
146147 argv => [ qw( --test --input in.txt
147148 --output out.txt --no-output ) ],
148149 exception => "Getopt::Lucid::Exception::ARGV",
150 required => ['test'],
149151 error_msg => _prereq_missing("input","output",),
150152 desc => "missing prereq after negation"
151153 },
179181 my $gl = Getopt::Lucid->new($trial->{spec}, \@cmd_line);
180182 @cmd_line = @{$case->{argv}};
181183 my %opts;
182 try eval { %opts = $gl->getopt->options };
184 my $valid_args = $case->{required} ? {requires => $case->{required}}
185 : {};
186 try eval { %opts = $gl->getopt->validate($valid_args)->options };
183187 catch my $err;
184188 if (defined $case->{exception}) { # expected
185189 ok( $err && $err->isa( $case->{exception} ),
0 #
1 # This file is part of Getopt-Lucid
2 #
3 # This software is Copyright (c) 2010 by David Golden.
4 #
5 # This is free software, licensed under:
6 #
7 # The Apache License, Version 2.0, January 2004
8 #
9 package t::ErrorMessages;
10 @ISA = ("Exporter");
11 use strict;
12 use Exporter ();
13
14 sub _invalid_argument {sprintf("Invalid argument: %s",@_)}
15 sub _required {sprintf("Required option '%s' not found",@_)}
16 sub _switch_twice {sprintf("Switch used twice: %s",@_)}
17 sub _switch_value {sprintf("Switch can't take a value: %s=%s",@_)}
18 sub _counter_value {sprintf("Counter option can't take a value: %s=%s",@_)}
19 sub _param_ambiguous {sprintf("Ambiguous value for %s could be option: %s",@_)}
20 sub _param_invalid {sprintf("Invalid parameter %s = %s",@_)}
21 sub _param_neg_value {sprintf("Negated parameter option can't take a value: %s=%s",@_)}
22 sub _list_invalid {sprintf("Invalid list option %s = %s",@_)}
23 sub _keypair_invalid {sprintf("Invalid keypair '%s': %s => %s",@_)}
24 sub _list_ambiguous {sprintf("Ambiguous value for %s could be option: %s",@_)}
25 sub _keypair {sprintf("Badly formed keypair for '%s'",@_)}
26 sub _default_list {sprintf("Default for list '%s' must be array reference",@_)}
27 sub _default_keypair {sprintf("Default for keypair '%s' must be hash reference",@_)}
28 sub _default_invalid {sprintf("Default '%s' = '%s' fails to validate",@_)}
29 sub _name_invalid {sprintf("'%s' is not a valid option name/alias",@_)}
30 sub _name_not_unique {sprintf("'%s' is not unique",@_)}
31 sub _name_conflicts {sprintf("'%s' conflicts with other options",@_)}
32 sub _key_invalid {sprintf("'%s' is not a valid option specification key",@_)}
33 sub _type_invalid {sprintf("'%s' is not a valid option type",@_)}
34 sub _prereq_missing {sprintf("Option '%s' requires option '%s'",@_)}
35 sub _unknown_prereq {sprintf("Prerequisite '%s' for '%s' is not recognized",@_)}
36 sub _invalid_list {sprintf("Option '%s' in %s must be scalar or array reference",@_)}
37 sub _invalid_keypair {sprintf("Option '%s' in %s must be scalar or hash reference",@_)}
38 sub _invalid_splat_defaults {sprintf("Argument to %s must be a hash or hash reference",@_)}
39
40 # keep this last;
41 for (keys %t::ErrorMessages::) {
42 push @t::ErrorMessages::EXPORT, $_ if $_ =~ "^_";
43 }
44
45 1;
0 package t::ErrorMessages;
1 @ISA = ("Exporter");
2 use strict;
3 use Exporter ();
4
5 sub _invalid_argument {sprintf("Invalid argument: %s",@_)}
6 sub _required {sprintf("Required option '%s' not found",@_)}
7 sub _switch_twice {sprintf("Switch used twice: %s",@_)}
8 sub _switch_value {sprintf("Switch can't take a value: %s=%s",@_)}
9 sub _counter_value {sprintf("Counter option can't take a value: %s=%s",@_)}
10 sub _param_ambiguous {sprintf("Ambiguous value for %s could be option: %s",@_)}
11 sub _param_invalid {sprintf("Invalid parameter %s = %s",@_)}
12 sub _param_neg_value {sprintf("Negated parameter option can't take a value: %s=%s",@_)}
13 sub _list_invalid {sprintf("Invalid list option %s = %s",@_)}
14 sub _keypair_invalid {sprintf("Invalid keypair '%s': %s => %s",@_)}
15 sub _list_ambiguous {sprintf("Ambiguous value for %s could be option: %s",@_)}
16 sub _keypair {sprintf("Badly formed keypair for '%s'",@_)}
17 sub _default_list {sprintf("Default for list '%s' must be array reference",@_)}
18 sub _default_keypair {sprintf("Default for keypair '%s' must be hash reference",@_)}
19 sub _default_invalid {sprintf("Default '%s' = '%s' fails to validate",@_)}
20 sub _name_invalid {sprintf("'%s' is not a valid option name/alias",@_)}
21 sub _name_not_unique {sprintf("'%s' is not unique",@_)}
22 sub _name_conflicts {sprintf("'%s' conflicts with other options",@_)}
23 sub _key_invalid {sprintf("'%s' is not a valid option specification key",@_)}
24 sub _type_invalid {sprintf("'%s' is not a valid option type",@_)}
25 sub _prereq_missing {sprintf("Option '%s' requires option '%s'",@_)}
26 sub _unknown_prereq {sprintf("Prerequisite '%s' for '%s' is not recognized",@_)}
27 sub _invalid_list {sprintf("Option '%s' in %s must be scalar or array reference",@_)}
28 sub _invalid_keypair {sprintf("Option '%s' in %s must be scalar or hash reference",@_)}
29 sub _invalid_splat_defaults {sprintf("Argument to %s must be a hash or hash reference",@_)}
30
31 # keep this last;
32 for (keys %t::ErrorMessages::) {
33 push @t::ErrorMessages::EXPORT, $_ if $_ =~ "^_";
34 }
35
36 1;
0 #!perl
1
2 use strict;
3 use warnings;
4
5 use Test::More;
6 use English qw(-no_match_vars);
7
8 eval "use Test::Perl::Critic";
9 plan skip_all => 'Test::Perl::Critic required to criticise code' if $@;
10 Test::Perl::Critic->import( -profile => "perlcritic.rc" ) if -e "perlcritic.rc";
11 all_critic_ok();
00 #!perl
1 #
2 # This file is part of Getopt-Lucid
3 #
4 # This software is Copyright (c) 2010 by David Golden.
5 #
6 # This is free software, licensed under:
7 #
8 # The Apache License, Version 2.0, January 2004
9 #
101
112 use Test::More;
123
00 #!perl
1 #
2 # This file is part of Getopt-Lucid
3 #
4 # This software is Copyright (c) 2010 by David Golden.
5 #
6 # This is free software, licensed under:
7 #
8 # The Apache License, Version 2.0, January 2004
9 #
101
112 use Test::More;
123
00 #!perl
1 #
2 # This file is part of Getopt-Lucid
3 #
4 # This software is Copyright (c) 2010 by David Golden.
5 #
6 # This is free software, licensed under:
7 #
8 # The Apache License, Version 2.0, January 2004
9 #
101 use Test::More;
112
123 eval "use Test::Pod 1.41";
00 #!perl
1 #
2 # This file is part of Getopt-Lucid
3 #
4 # This software is Copyright (c) 2010 by David Golden.
5 #
6 # This is free software, licensed under:
7 #
8 # The Apache License, Version 2.0, January 2004
9 #
101
112 use Test::More;
123
0 #!/usr/bin/perl
1 use 5.006;
2 use strict;
3 use warnings;
4 use Test::More;
5
6 eval "use Test::Version 0.04";
7 plan skip_all => "Test::Version 0.04 required for testing versions"
8 if $@;
9
10 version_all_ok();
11 done_testing;