File Coverage

lib/Wrapper/GetoptLong.pm
Criterion Covered Total %
statement 98 105 93.3
branch 25 38 65.7
condition 0 2 0.0
subroutine 11 12 91.6
pod 7 7 100.0
total 141 164 85.9


line stmt bran cond sub pod time code
1             package Wrapper::GetoptLong;
2              
3 4     4   298116 use 5.006;
  4         46  
4 4     4   19 use strict;
  4         10  
  4         75  
5 4     4   16 use warnings;
  4         9  
  4         134  
6              
7 4     4   24 use File::Basename qw(basename);
  4         9  
  4         444  
8 4     4   3129 use Getopt::Long qw(GetOptions);
  4         52852  
  4         29  
9              
10             # @(#) NMG/2WM - $Id: GetoptLong.pm,v 1.1.1.1 2023/02/08 02:16:13 user Exp $
11              
12             =head1 NAME
13             Wrapper::GetoptLong - A wrapper for the Getopt::Long module
14              
15             =head1 VERSION
16             Version 0.01
17              
18             =head1 ABSTRACT
19             A wrapper to the Getopt::Long module
20              
21             =cut
22              
23             our $VERSION = '0.01';
24              
25             # Add your own module that defines the supporting functions, pass an instance of it to the constructor (new) as $obj.
26              
27             our @EXPORT = qw($obj print_usage_and_die);
28              
29             my %opts=();
30             my @usage_arr=();
31             my $usage='';
32             our $obj;
33             my $config_href=();
34             my @opts_arr=();
35             my $retval='';
36              
37              
38             # opt_arg_eg : is option argument example, to be used in the usage message.
39             # the -help option is a freebie, added by this module to the %OPT_CONFIG hash.
40             # with the print_usage_and_die exported function.
41              
42             my $dflt_help_opt= {
43             'desc' => 'Will print this usage message and exit',
44             'func' => 'print_usage_and_die()',
45             'opt_arg_eg' => '',
46             'opt_arg_type' => '',
47             };
48              
49              
50             =head1 SYNOPSIS
51              
52             A wrapper for the Getopts::Long module.
53              
54             use MyMainModule; # has the definition for function the_date. In real practice, not a demo,
55             # MyMainModule defines all the support functions for the options.
56            
57             use Wrapper::GetoptLong;
58             my $mmm=MyMainModule->new();
59             my %OPTS_CONFIG=(
60             'the_date' => {
61             'desc' => q^Print today's date. Takes date_format as argument.^,
62             'func' => q^MyModule::the_date($obj->opts{'the_date'})^,
63             'opt_arg_eg' => '%m/%d/%Y',
64             'opt_arg_type' => 's',
65             },
66             );
67              
68             @ARGV=('--the_date', '%m/%d/%Y');
69             my $golw_obj=new Wrapper::GetoptLong(\%OPTS_CONFIG, $mmm);
70             $golw->run_getopt();
71             my $rc=$golw->execute_opt();
72             if(ref($rc))
73             {
74             use Data::Dumper;
75             print Dumper $rc;
76             }
77             else
78             {
79             print $rc, "\n";
80             }
81             =cut
82              
83             =head2 DEMO
84             A full demo is available on GitHub.
85             Requires a database , mySQL or MariaDB - the repository includes a file to create and populate the database.
86             https://github.com/ngabriel8/WGOLDemo
87              
88             =head1 EXPORT
89              
90             obj
91             print_usage_and_die
92              
93             =head1 METHODS
94              
95             =over 4
96              
97             =cut
98              
99              
100             =item I
101              
102             my $golw = new Wrapper::GetoptLong($config_href, $MyObj);
103              
104             The constructor takes two arguments: a reference to an OPTS_CONFIG hash and an object ref (optional).
105              
106             =cut
107              
108             sub new
109             {
110 3     3 1 3262 my $name = basename(__FILE__, '.pm');
111 3         22 my $golw_usage=sprintf('Usage: my $gow=new %s(\%%OPTS_CONFIG, $object);', $name);
112 3         9 $!=0;
113 3 50       14 (scalar(@_) == 1) && die $golw_usage;
114 3         6 my $class=shift;
115 3         7 ($config_href, $obj)=@_;
116 3         7 my $self=();
117 3         8 $self->{'name'}=$name;
118 3         7 bless($self, $class);
119 3         6 my @opts=sort keys %{$config_href};
  3         13  
120 3         52 my @fnd=grep /^help$/i, @opts;
121 3 50       14 ($#fnd == -1) && ($config_href->{'help'}=$dflt_help_opt);
122              
123 3         12 push(@usage_arr, "Usage $0: ");
124 3         11 $self->init_getopts();
125 3         10 return $self;
126             } # new
127              
128             =back
129              
130             =head2 print_usage_and_die
131             Prints Usage message for the calling script and exists.
132             =cut
133              
134             sub print_usage_and_die
135             {
136 0     0 1 0 my($self, $extra_msg)=@_;
137 0   0     0 $extra_msg ||=undef;
138              
139 0 0       0 (defined $extra_msg) && print STDERR $extra_msg;
140 0         0 print STDERR $usage;
141 0         0 exit 0;
142             } # print_usage_and_die
143              
144             =head2 init_getopts
145             Called by the constructor. Initializes usage, opts_array ...etc, for the GetOption call.
146             =cut
147              
148             sub init_getopts
149             {
150 3     3 1 7 my ($self)=@_;
151 3         6 my @opts_no_arg=();
152 3         5 my @opts_with_arg=();
153 3         12 $self->mk_get_opt_array(\@opts_no_arg, \@opts_with_arg);
154             # cmd_str looks like this : GetOptions(\%opts, @opts_arr) || print_usage_and_die($usage, 'Invalid command line option');^;
155 3         6 my $no_arg_str='';
156 3         5 my $count=scalar(@opts_no_arg);
157 3 50       8 if($count > 0)
158             {
159 3 100       19 $no_arg_str = ($count == 1) ? sprintf('-%s', $opts_no_arg[0]) : sprintf('-[%s]', join('|', @opts_no_arg));
160             # push(@usage_arr, $no_arg_str);
161 3         11 $usage_arr[0] .= " $no_arg_str";
162             }
163 3         6 my $with_arg_str='';
164 3         12 $count=scalar(@opts_with_arg);
165 3 100       53 if($count > 0)
166             {
167 1         5 $with_arg_str = join("\n", @opts_with_arg);
168 1         2 push(@usage_arr, $with_arg_str);
169             }
170 3         29 $self->add_desc();
171 3         5 my @desc_arr=();
172 3         8 foreach (@usage_arr)
173             {
174 12 100       29 (/^$/) && next;
175 9         22 push(@desc_arr, $_);
176             }
177 3         13 $usage=join("\n", @desc_arr) . "\n";
178 3 50       14 ($#ARGV == -1) && print_usage_and_die();
179             } # init_getopts
180              
181             =head2 mk_get_opt_array
182             Makes the array of valid options to pass to GetOption.
183             =cut
184              
185             sub mk_get_opt_array
186             {
187 3     3 1 7 my ($self, $no_arg_aref, $with_arg_aref)=@_;
188 3         6 @opts_arr=();
189 3         6 my @no_args=();
190 3         6 foreach my $opt (sort keys %{$config_href})
  3         12  
191             {
192 5         8 my $opt_str=$opt;
193 5 100       16 if($config_href->{$opt}->{'opt_arg_type'} eq '')
194             {
195 4         7 push(@no_args, $opt);
196             }
197             else
198             {
199 1         5 $opt_str .= sprintf(':%s', $config_href->{$opt}->{'opt_arg_type'});
200 1         2 my $eg=$config_href->{$opt}->{'opt_arg_eg'};
201 1         2 push(@{$with_arg_aref}, "--$opt $eg");
  1         4  
202             }
203 5         12 push(@opts_arr, $opt_str);
204             } # foreach $opt
205 3 50       9 if(scalar(@no_args))
206             {
207 3         5 my @tmp=();
208 3         5 my $help=undef;
209 3         18 foreach (@no_args)
210             {
211 4 100       19 (/^help$/i) ? ($help=$_) : push(@tmp, $_);
212             } # foreach @no_args
213 3 50       11 (defined $help) && unshift(@tmp, $help);
214 3         5 push(@{$no_arg_aref}, @tmp);
  3         9  
215             } # if scalar(@no_args)
216             } # mk_get_opt_array
217              
218              
219             =head2 add_desc
220             Makes the description part of the usage message.
221              
222             =cut
223              
224             sub add_desc
225             {
226 3     3 1 8 my ($self)=@_;
227 3         5 my @desc=();
228 3         6 my $help='';
229 3         11 foreach my $opt (sort keys %{$config_href})
  3         13  
230             {
231 5         9 my $str='';
232 5 100       38 if($opt =~ /^help$/i)
    100          
233             {
234 3         28 $help="-$opt $config_href->{$opt}->{'desc'}";
235             }
236             elsif($config_href->{$opt}->{'opt_arg_type'} eq '')
237             {
238 1         5 $str="-$opt $config_href->{$opt}->{'desc'}";
239             }
240             else
241             {
242 1         3 $str="--$opt $config_href->{$opt}->{'desc'}";
243             }
244 5         11 push(@desc, $str);
245             } # foreach $opt
246              
247 3 50       16 ($help) && unshift(@desc, $help);
248 3         10 push(@usage_arr, @desc);
249             } # add_desc
250              
251             =head2 run_getopt
252             Calls the GetOptions function to populate the %opts hash.
253              
254             =cut
255              
256             sub run_getopt
257             {
258 2     2 1 10 my ($self)=@_;
259 2 50       16 GetOptions(\%opts, @opts_arr) || print_usage_and_die('Invalid command line option');
260             } # run_getopt
261              
262             =head2 execute_opt
263             If %opts is not empty, executes the function associated with that option (passed from the command line).
264              
265             =cut
266              
267             sub execute_opt
268             {
269 2     2 1 899 my ($self)=@_;
270 2         5 my $rc=0;
271              
272 2         9 foreach my $opt (sort keys %opts)
273             {
274 2 50       6 if(defined $config_href->{$opt})
275             {
276 2         10 my $cmd=sprintf('$retval=%s;', $config_href->{$opt}->{'func'});
277             # print "Working on $opt, evaluating $cmd\n";
278 2         147 eval($cmd);
279 2 50       226 if(!$@)
280             {
281 2 50       12 ($cmd =~ /print_usage_and_die/) && exit(0);
282 2         6 $rc=$retval;
283             }
284             else
285             {
286 0         0 print STDERR $@;
287 0         0 $rc=1;
288             }
289 2         5 last; # There should be only one opt active. But, be safe...
290             }
291             } # foreach $opt
292 2         6 return $rc;
293             } # run_getopt
294              
295             =head1 AUTHOR
296              
297             Nazar Gabriel, C<< >>
298              
299             =head1 BUGS
300              
301             Please report any bugs or feature requests to C, or through
302             the web interface at L. I will be notified, and then you'll
303             automatically be notified of progress on your bug as I make changes.
304              
305             =head1 SUPPORT
306              
307             You can find documentation for this module with the perldoc command.
308              
309             perldoc Wrapper::GetoptLong
310              
311             You can also look for information at:
312              
313             =over 4
314              
315             =item * RT: CPAN's request tracker (report bugs here)
316              
317             L
318              
319             =item * CPAN Ratings
320              
321             L
322              
323             =item * Search CPAN
324              
325             L
326              
327             =back
328              
329              
330             =head1 ACKNOWLEDGEMENTS
331              
332             =head1 LICENSE AND COPYRIGHT
333              
334             This software is Copyright (c) 2023 by Nazar Gabriel.
335              
336             This is free software, licensed under:
337              
338             The Artistic License 2.0 (GPL Compatible)
339              
340             =cut
341              
342             1; # End of Wrapper::GetoptLong