File Coverage

lib/GetoptLongWrapper.pm
Criterion Covered Total %
statement 96 105 91.4
branch 24 38 63.1
condition 1 2 50.0
subroutine 12 12 100.0
pod 7 7 100.0
total 140 164 85.3


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