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