File Coverage

blib/lib/PDLA/Options.pm
Criterion Covered Total %
statement 9 252 3.5
branch 0 102 0.0
condition 0 12 0.0
subroutine 3 30 10.0
pod 23 26 88.4
total 35 422 8.2


line stmt bran cond sub pod time code
1              
2             package PDLA::Options;
3              
4             =head1 NAME
5              
6             PDLA::Options - simplifies option passing by hash in PerlDL
7              
8             =head1 SYNOPSIS
9              
10             use PDLA::Options;
11              
12             %hash = parse( \%defaults, \%user_options);
13              
14             use PDLA::Options ();
15              
16             $opt = new PDLA::Options;
17             $opt = new PDLA::Options ( \%defaults );
18              
19             $opt->defaults ( \%defaults );
20             $opt->synonyms ( { 'COLOR' => 'COLOUR' } );
21              
22             $hashref = $opt->defaults;
23              
24             $opt->options ( \%user_options );
25              
26             $hashref = $opt->options;
27              
28             $opt->incremental(1);
29             $opt->full_options(0);
30              
31             =head1 DESCRIPTION
32              
33             Object to simplify option passing for PerlDL subroutines.
34             Allows you to merge a user defined options with defaults.
35             A simplified (non-OO) interface is provided.
36              
37             =cut
38              
39 117     117   628 use strict;
  117         197  
  117         4490  
40 117     117   601 use Carp;
  117         209  
  117         11144  
41              
42 117     117   693 use vars qw/$VERSION %EXPORT_TAGS %DEF_SYNS @ISA/;
  117         216  
  117         385212  
43              
44             require Exporter;
45              
46             # difference to 0.91 is that added CENTRE/CENTER as default
47             # synonymns (patch by Diab Jerius [ #469110 ])
48             our $VERSION = '0.92';
49             $VERSION = eval $VERSION;
50              
51             @ISA = qw(Exporter);
52              
53             %EXPORT_TAGS = (
54             'Func' => [qw/
55             parse iparse ifhref
56             /]
57             );
58              
59             Exporter::export_tags('Func');
60              
61             # List of default synonyms
62             %DEF_SYNS = (
63             COLOR => 'COLOUR',
64             COLOUR => 'COLOR',
65             CENTER => 'CENTRE',
66             CENTRE => 'CENTER',
67             );
68              
69             my $default = {
70             WarnOnMissing => 1,
71             FullOptions => 1,
72             DEBUG => 0,
73             };
74              
75             =head1 Utility functions
76              
77             =head2 ifhref
78              
79             parse({Ext => 'TIF', ifhref($opt)});
80              
81             just return the argument if it is a hashref otherwise return
82             an empty hashref. Useful in conjunction with parse to return
83             just the default values if argument is not a hash ref
84              
85             =head1 NON-OO INTERFACE
86              
87             A simplified non-object oriented interface is provided.
88             These routines are exported into the callers namespace by default.
89              
90             =over 4
91              
92             =item parse( \%defaults, \%user_options)
93              
94             This will parse user options by using the defaults. The following
95             settings are used for parsing: The options are case-sensitive, a
96             default synonym table is consulted (see L),
97             minimum-matching is turned on, and translation of values is not performed.
98              
99             A hash (not hash reference) containing the processed options is returned.
100              
101             %options = parse( { LINE => 1, COLOUR => 'red'}, { COLOR => 'blue'});
102              
103             =item iparse( \%defaults, \%user_options)
104              
105             Same as C but matching is case insensitive
106              
107             =cut
108              
109             sub ifhref {
110 0     0 1   my ($href) = @_;
111 0 0 0       return defined $href && ref $href eq 'HASH' ? $href : {};
112             }
113              
114 0     0 1   sub parse { return _parse(1,@_) }
115 0     0 1   sub iparse { return _parse(0,@_) }
116              
117             sub _parse {
118              
119 0 0   0     croak 'Usage: parse( \%defaults, \%user )' if scalar(@_) != 3;
120              
121 0           my $casechk = shift;
122 0           my $defaults = shift;
123 0 0         croak ("First argument is not a hash reference")
124             unless ref($defaults) eq "HASH";
125              
126 0           my $user = shift;
127 0 0         croak ("Second argument is not a hash reference")
128             unless ref($user) eq "HASH";
129              
130             # Create new object
131 0           my $opt = new PDLA::Options ( $defaults );
132              
133             # Set up default behaviour
134 0           $opt->minmatch(1);
135 0           $opt->casesens($casechk);
136 0           $opt->synonyms( \%DEF_SYNS );
137              
138             # Process the options
139 0           my $optref = $opt->options( $user );
140              
141 0           return %$optref;
142             }
143              
144              
145             =back
146              
147             =head2 Default Synonyms
148              
149             The following default synonyms are available in the non-OO interface:
150              
151             COLOR => COLOUR
152             COLOUR => COLOR
153             CENTER => CENTRE
154             CENTRE => CENTER
155              
156             =head1 METHODS
157              
158             The following methods are available to PDLA::Options objects.
159              
160             =over 4
161              
162             =item new()
163              
164             Constructor. Creates the object. With an optional argument can also
165             set the default options.
166              
167             =cut
168              
169             sub new {
170              
171 0     0 1   my $proto = shift;
172 0   0       my $class = ref($proto) || $proto;
173              
174 0           my $opt = {};
175              
176             # Set up object structure
177 0           $opt->{DEFAULTS} = {}; # Default options
178 0           $opt->{CURRENT} = {}; # Current options
179 0           $opt->{CurrKeys} = []; # list of selected keys if full_options(0)
180 0           $opt->{SYNONYMS} = {}; # List of synonyms
181 0           $opt->{INC} = 0; # Flag to decide whether we are incremental on cur
182 0           $opt->{CaseSens} = 0; # Are options case sensitive
183 0           $opt->{MinMatch} = 1; # Minimum matching on keys
184 0           $opt->{Translation} = {};# Translation from eg 'RED' to 1
185 0           $opt->{AutoTranslate}= 1;# Automatically translate options when processing
186 0           $opt->{MinMatchTrans} = 0; # Min matching during translation
187 0           $opt->{CaseSensTrans} = 0; # Case sensitive during translation
188             # Return full options list
189 0           $opt->{FullOptions} = $default->{FullOptions};
190             # Whether to warn for options that are invalid or not
191 0           $opt->{WarnOnMissing}= $default->{WarnOnMissing};
192 0           $opt->{DEBUG} = $default->{DEBUG}; # Turn on debug messages
193              
194             # Bless into class
195 0           bless ( $opt, $class);
196              
197             # If we were passed arguments, pass to defaults method
198 0 0         if (@_) { $opt->defaults( @_ ); }
  0            
199              
200 0           return $opt;
201             }
202              
203             =item extend (\%options)
204              
205             This will copy the existing options object and extend it with the
206             requested extra options.
207              
208             =cut
209              
210             sub extend {
211              
212 0     0 1   my ($self, $opt)=@_;
213              
214 0           my $class = ref($self);
215 0           my $h = {%{$self}};
  0            
216 0 0         croak ("Argument is not reference to hash!\n") unless ref($opt) eq 'HASH';
217             #
218             # The next step is to perform a deep copy of the hash
219             # references since we might want to change these without
220             # changing the originals.
221             #
222 0           $h->{SYNONYMS}={%{$self->{SYNONYMS}}};
  0            
223 0           $h->{Translation}={%{$self->{Translation}}};
  0            
224 0           $h->{CurrKeys}=[@{$self->{CurrKeys}}];
  0            
225             #
226             # Create the extended option list.
227             #
228 0           my %all_options = (%{$opt}, %{$self->{DEFAULTS}});
  0            
  0            
229              
230             # Bless it
231 0           bless ($h, $class);
232              
233             # And parse the default options
234 0           $h->defaults(\%all_options);
235              
236 0           return $h;
237              
238             }
239              
240             # =item change_defaults (\%options)
241              
242             # This will merge the options given with the defaults hash and hence change
243             # the default hash. This is not normally a good idea, but in certain dynamic
244             # situations you might want to adjust a default parameter for future calls
245             # to the routine.
246              
247             # =cut
248              
249             # sub change_defaults {
250              
251             # my $self=shift;
252              
253             # my $arg = shift;
254             # croak("Argument is not a hash reference!\n") unless ref($arg) eq 'HASH';
255              
256             # my $defs = $self->defaults($arg);
257              
258             # $self->defaults($)
259              
260              
261             # }
262              
263              
264             =item defaults( \%defaults )
265              
266             Method to set or return the current defaults. The argument should be
267             a reference to a hash. The hash reference is returned if no arguments
268             are supplied.
269              
270             The current values are reset whenever the defaults are changed.
271              
272             =cut
273              
274             sub defaults {
275 0     0 1   my $self = shift;
276              
277 0 0         if (@_) {
278 0           my $arg = shift;
279 0 0         croak("Argument is not a hash reference") unless ref($arg) eq "HASH";
280 0           $self->{DEFAULTS} = $arg;
281              
282             # Reset the current state (making sure that I disconnect the
283             # hashes
284 0           my %hash = %$arg;
285 0           $self->curr_full(\%hash);
286              
287             }
288              
289             # Decouple the hash to protect it from being modified outside the
290             # object
291 0           my %hash = %{$self->{DEFAULTS}};
  0            
292 0           return \%hash;
293              
294             }
295              
296             =item add_synonym (\%synonyms)
297              
298             Method to add another synonym to an option set
299             The argument should be a reference to a hash.
300              
301             =cut
302              
303             sub add_synonym {
304 0     0 1   my $self=shift;
305 0 0         return unless @_;
306 0           my $arg = shift;
307 0 0         croak("Synonym argument is not a hash reference") unless ref($arg) eq "HASH";
308              
309 0           foreach (keys %$arg) {
310 0           $self->{SYNONYMS}{$_}=$arg->{$_};
311             }
312 0           my %hash = %{$self->{SYNONYMS}};
  0            
313 0           return \%hash;
314              
315             }
316              
317             =item add_translation (\%translation)
318              
319             Method to add another translation rule to an option set.
320             The argument should be a reference to a hash.
321              
322             =cut
323              
324              
325             sub add_translation {
326 0     0 1   my $self = shift;
327 0 0         return unless @_;
328 0           my $arg = shift;
329 0 0         croak("Translation argument is not a hash reference") unless ref($arg) eq 'HASH';
330              
331 0           foreach (keys %$arg) {
332 0           $self->{Translation}{$_}=$arg->{$_};
333             }
334 0           my %hash = %{$self->{Translation}};
  0            
335              
336 0           return \%hash;
337              
338             }
339              
340             =item synonyms( \%synonyms )
341              
342             Method to set or return the current synonyms. The argument should be
343             a reference to a hash. The hash reference is returned if no arguments
344             are supplied.
345              
346             This allows you to provide alternate keywords (such as allowing
347             'COLOR' as an option when your defaults uses 'COLOUR').
348              
349             =cut
350              
351             sub synonyms {
352 0     0 1   my $self = shift;
353              
354 0 0         if (@_) {
355 0           my $arg = shift;
356 0 0         croak("Argument is not a hash reference") unless ref($arg) eq "HASH";
357 0           $self->{SYNONYMS} = $arg;
358             }
359              
360             # Decouple the hash to protect it from being modified outside the
361             # object
362 0           my %hash = %{$self->{SYNONYMS}};
  0            
363 0           return \%hash;
364              
365             }
366              
367              
368             =item current
369              
370             Returns the current state of the options. This is returned
371             as a hash reference (although it is not a reference to the
372             actual hash stored in the object). If full_options() is true
373             the full options hash is returned, if full_options() is false
374             only the modified options are returned (as set by the last call
375             to options()).
376              
377             =cut
378              
379             sub current {
380 0     0 1   my $self = shift;
381              
382 0 0         if ($self->full_options) {
383 0           return $self->curr_full;
384             } else {
385 0           my @keys = $self->curr_keys;
386 0           my %hash = ();
387 0           my $curr = $self->curr_full;
388              
389 0           foreach my $key (@keys) {
390 0 0         $hash{$key} = $$curr{$key} if exists $$curr{$key};
391             }
392 0           return \%hash;
393             }
394             }
395              
396             =item clear_current
397              
398             This routine clears the 'state' of the C object so that
399             the next call to current will return an empty list
400              
401             =cut
402              
403             sub clear_current {
404 0     0 1   my $self = shift;
405 0           @{$self->{CurrKeys}}=();
  0            
406             }
407              
408              
409             # Method to set the 'mini' state of the object
410             # This is just a list of the keys in %defaults that were selected
411             # by the user. current() returns the hash with these keys if
412             # called with full_options(0).
413             # Not publicising this
414              
415             sub curr_keys {
416 0     0 0   my $self = shift;
417 0 0         if (@_) { @{$self->{CurrKeys}} = @_; }
  0            
  0            
418 0           return @{$self->{CurrKeys}};
  0            
419             }
420              
421             # Method to set the full state of the object
422             # Not publicising this
423              
424             sub curr_full {
425 0     0 0   my $self = shift;
426              
427 0 0         if (@_) {
428 0           my $arg = shift;
429 0 0         croak("Argument is not a hash reference") unless ref($arg) eq "HASH";
430 0           $self->{CURRENT} = $arg;
431             }
432              
433             # Decouple the hash
434 0           my %hash = %{$self->{CURRENT}};
  0            
435 0           return \%hash;
436              
437             }
438              
439              
440             =item translation
441              
442             Provide translation of options to more specific values that are
443             recognised by the program. This allows, for example, the automatic
444             translation of the string 'red' to '#ff0000'.
445              
446             This method can be used to setup the dictionary and is hash reference
447             with the following structure:
448              
449             OPTIONA => {
450             'string1' => decode1,
451             'string2' => decode2
452             },
453             OPTIONB => {
454             's4' => decodeb1,
455             }
456             etc....
457              
458             Where OPTION? corresponds to the top level option name as stored in
459             the defaults array (eg LINECOLOR) and the anonymous hashes provide
460             the translation from string1 ('red') to decode1 ('#ff0000').
461              
462             An options string will be translated automatically during the main options()
463             processing if autotrans() is set to true. Else translation can be
464             initiated by the user using the translate() method.
465              
466             =cut
467              
468             sub translation {
469 0     0 1   my $self = shift;
470              
471 0 0         if (@_) {
472 0           my $arg = shift;
473 0 0         croak("Argument is not a hash reference") unless ref($arg) eq "HASH";
474 0           $self->{Translation} = $arg;
475             }
476              
477             # Decouple the hash to protect it from being modified outside the
478             # object
479 0           my %hash = %{$self->{Translation}};
  0            
480 0           return \%hash;
481              
482             }
483              
484              
485             =item incremental
486              
487             Specifies whether the user defined options will be treated as additions
488             to the current state of the object (1) or modifications to the default
489             values only (0).
490              
491             Can be used to set or return this value.
492             Default is false.
493              
494             =cut
495              
496             sub incremental {
497 0     0 1   my $self = shift;
498 0 0         if (@_) { $self->{INC} = shift; }
  0            
499 0           return $self->{INC};
500             }
501              
502             =item full_options
503              
504             Governs whether a complete set of options is returned (ie defaults
505             + expanded user options), true, or if just the expanded user
506             options are returned, false (ie the values specified by the user).
507              
508             This can be useful when you are only interested in the changes to
509             the options rather than knowing the full state. (For example, if
510             defaults contains keys for COLOUR and LINESTYLE and the user supplied
511             a key of COL, you may simply be interested in the modification to
512             COLOUR rather than the state of LINESTYLE and COLOUR.)
513              
514             Default is true.
515              
516             =cut
517              
518             sub full_options {
519 0     0 1   my $self = shift;
520 0 0         if (@_) { $self->{FullOptions} = shift; }
  0            
521 0           return $self->{FullOptions};
522              
523             }
524              
525             =item casesens
526              
527             Specifies whether the user defined options will be processed independent
528             of case (0) or not (1). Default is to be case insensitive.
529              
530             Can be used to set or return this value.
531              
532             =cut
533              
534             sub casesens {
535 0     0 1   my $self = shift;
536 0 0         if (@_) { $self->{CaseSens} = shift; }
  0            
537 0           return $self->{CaseSens};
538             }
539              
540             =item minmatch
541              
542             Specifies whether the user defined options will be minimum matched
543             with the defaults (1) or whether the user defined options should match
544             the default keys exactly. Defaults is true (1).
545              
546             If a particular key matches exactly (within the constraints imposed
547             bby case sensitivity) this key will always be taken as correct even
548             if others are similar. For example COL would match COL and COLOUR but
549             this implementation will always return COL in this case (note that
550             for CO it will return both COL and COLOUR and pick one at random.
551              
552             Can be used to set or return this value.
553              
554             =cut
555              
556             sub minmatch {
557 0     0 1   my $self = shift;
558 0 0         if (@_) { $self->{MinMatch} = shift; }
  0            
559 0           return $self->{MinMatch};
560             }
561              
562              
563             =item autotrans
564              
565             Specifies whether the user defined options will be processed via
566             the translate() method immediately following the main options
567             parsing. Default is to autotranslate (1).
568              
569             Can be used to set or return this value.
570              
571             =cut
572              
573             sub autotrans {
574 0     0 1   my $self = shift;
575 0 0         if (@_) { $self->{AutoTranslate} = shift; }
  0            
576 0           return $self->{AutoTranslate};
577             }
578              
579              
580             =item casesenstrans
581              
582             Specifies whether the keys in the options hash will be matched insensitive
583             of case (0) during translation() or not (1). Default is to be case insensitive.
584              
585             Can be used to set or return this value.
586              
587             =cut
588              
589             sub casesenstrans {
590 0     0 1   my $self = shift;
591 0 0         if (@_) { $self->{CaseSensTrans} = shift; }
  0            
592 0           return $self->{CaseSensTrans};
593             }
594              
595             =item minmatchtrans
596              
597             Specifies whether the keys in the options hash will be minimum matched
598             during translation(). Default is false (0).
599              
600             If a particular key matches exactly (within the constraints imposed
601             bby case sensitivity) this key will always be taken as correct even
602             if others are similar. For example COL would match COL and COLOUR but
603             this implementation will always return COL in this case (note that
604             for CO it will return both COL and COLOUR and pick one at random.
605              
606             Can be used to set or return this value.
607              
608             =cut
609              
610             sub minmatchtrans {
611 0     0 1   my $self = shift;
612 0 0         if (@_) { $self->{MinMatchTrans} = shift; }
  0            
613 0           return $self->{MinMatchTrans};
614             }
615              
616              
617             =item warnonmissing
618              
619             Turn on or off the warning message printed when an options is not in
620             the options hash. This can be convenient when a user passes a set of
621             options that has to be parsed by several different option objects down
622             the line.
623              
624             =cut
625              
626             sub warnonmissing {
627 0     0 1   my $self = shift;
628 0 0         if (ref $self) {
629 0 0         if (@_) { $self->{WarnOnMissing}=shift;}
  0            
630 0           return $self->{WarnOnMissing};
631             } else {
632 0 0         $default->{WarnOnMissing} = shift if @_;
633 0           return $default->{WarnOnMissing};
634             }
635             }
636              
637              
638             =item debug
639              
640             Turn on or off debug messages. Default is off (0).
641             Can be used to set or return this value.
642              
643             =cut
644              
645             sub debug {
646 0     0 1   my $self = shift;
647 0 0         if (ref $self) {
648 0 0         if (@_) { $self->{DEBUG} = shift; }
  0            
649 0           return $self->{DEBUG};
650             } else {
651 0 0         $default->{DEBUG} = shift if @_;
652 0           return $default->{DEBUG};
653             }
654             }
655              
656              
657             =item options
658              
659             Takes a set of user-defined options (as a reference to a hash)
660             and merges them with the current state (or the defaults; depends
661             on the state of incremental()).
662              
663             The user-supplied keys will be compared with the defaults.
664             Case sensitivity and minimum matching can be configured using
665             the mimatch() and casesens() methods.
666              
667             A warning is raised if keys present in the user options are not
668             present in the defaults unless warnonmissing is set.
669              
670             A reference to a hash containing the merged options is returned.
671              
672             $merged = $opt->options( { COL => 'red', Width => 1});
673              
674             The state of the object can be retrieved after this by using the
675             current() method or by using the options() method with no arguments.
676             If full_options() is true, all options are returned (options plus
677             overrides), if full_options() is false then only the modified
678             options are returned.
679              
680             Synonyms are supported if they have been configured via the synonyms()
681             method.
682              
683             =cut
684              
685             sub options {
686              
687 0     0 1   my $self = shift;
688              
689             # If there is an argument do something clever
690 0 0         if (@_) {
691              
692             # check that the arg is a hash
693 0           my $arg = shift;
694 0 0         croak("Argument is not a hash reference") unless ref($arg) eq "HASH";
695              
696             # Turn the options into a real hash
697 0           my %user = %$arg;
698              
699             # Now read in the base options
700 0           my $base;
701 0 0         if ($self->incremental) {
702 0           $base = $self->curr_full;
703             } else {
704 0           $base = $self->defaults;
705             }
706              
707             # Turn into a real hash for convenience
708 0           my %base = %$base;
709              
710             # Store a list of all the expanded user keys
711 0           my @list = ();
712              
713             # Read in synonyms
714 0           my %syn = %{$self->synonyms};
  0            
715              
716             # Now go through the keys in the user hash and compare with
717             # the defaults
718 0           foreach my $userkey (sort keys %user) {
719              
720             # Check for matches in the default set
721 0           my @matched = $self->compare_with_list(0, $userkey, keys %base);
722              
723             # If we had no matches, check the synonyms list
724 0 0         if ($#matched == -1) {
725 0           @matched = $self->compare_with_list(0, $userkey, keys %syn);
726              
727             # If we have matched then convert the key to the actual
728             # value stored in the object
729 0           for (my $i =0; $i <= $#matched; $i++) {
730 0           $matched[$i] = $syn{$matched[$i]};
731             }
732             }
733              
734             # At this point we have matched the userkey to a key in the
735             # defaults list (or if not say so)
736 0 0         if ($#matched == -1) {
737 0 0         print "Warning: $userkey is not a valid option\n" if $self->{WarnOnMissing};
738             } else {
739 0 0         if ( $#matched > 0 ) {
740 0           print "Warning: Multiple matches for option $userkey\n";
741 0           print "Warning: Could be any of the following:\n";
742 0           print join("\n",@matched) . "\n";
743 0           print "Accepting the first match ($matched[0])\n";
744             }
745             # Modify the value in %base and keep track of a separate
746             # array containing only the matched keys
747 0           $base{$matched[0]} = $user{$userkey};
748 0           push(@list, $matched[0]);
749 0 0         print "Matched: $userkey for $matched[0]\n" if $self->debug;
750             }
751             }
752              
753             # Finished matching so set this as the current state of the
754             # object
755 0           $self->curr_keys(@list);
756 0           $self->curr_full(\%base);
757              
758             # Now process the values via the provided translation
759             # if required. Note that the current design means that
760             # We have to run this after we have set the current state.
761             # Otherwise the translation() method would not work directly
762             # and we would have to provide a public version and a private one.
763             # Note that translate updates the current state of the object
764             # So we don't need to catch the return value
765 0 0         $self->translate if $self->autotrans;
766              
767             }
768              
769             # Current state should now be in current.
770             # Simply return it
771 0           return $self->current;
772              
773             }
774              
775             =item translate
776              
777             Translate the current option values (eg those set via the options()
778             method) using the provided translation().
779              
780             This method updates the current state of the object and returns the
781             updated options hash as a reference.
782              
783             $ref = $opt->translate;
784              
785             =cut
786              
787             sub translate {
788 0     0 1   my $self = shift;
789              
790 0           my %trans = %{$self->translation};
  0            
791 0           my %opt = %{$self->curr_full}; # Process all options
  0            
792              
793             # Now need to go through each of the keys
794             # and if the corresponding key exists in the translation
795             # hash we need to check that a valid translation exists
796 0           foreach my $key ( keys %opt ) {
797 0 0         if (exists $trans{$key}) {
798             # Okay so a translation might exist
799             # Now compare keys in the hash in the hash
800 0           my %subhash = %{$trans{$key}};
  0            
801              
802             my @matched =
803 0           $self->compare_with_list(1, $opt{$key}, keys %subhash);
804              
805             # At this point we have matched the userkey to a key in the
806             # dictionary. If there is no translation dont say anything
807             # since it may be a 'REAL' answer (ie 1 instead of 'red')
808              
809 0 0         if ($#matched > -1) {
810 0 0         if ( $#matched > 0 ) {
811 0           print "Warning: Multiple matches for $opt{$key} in option $key\n";
812 0           print "Warning: Could be any of the following:\n";
813 0           print join("\n",@matched) . "\n";
814 0           print "Accepting the first match ($matched[0])\n";
815              
816             }
817             # Modify the value in the options set
818 0 0         print "Translation: $opt{$key} translated to $subhash{$matched[0]}\n"
819             if $self->debug;
820 0           $opt{$key} = $subhash{$matched[0]};
821              
822             }
823              
824             }
825              
826             }
827              
828             # Update the current state
829 0           return $self->curr_full( \%opt );
830              
831             }
832              
833             # Private method to compare a key with a list of keys.
834             # The object controls whether case-sensitivity of minimum matching
835             # are required
836             # Arguments: flag to determine whether I am matchin options or translations
837             # this is needed since both methods are configurable with
838             # regards to minimum matching and case sensitivity.
839             # 0 - use $self->minmatch and $self->casesens
840             # 1 - use $self->minmatchtrans and $self->casesenstrans
841             # $key: Key to be compared
842             # @keys: List of keys
843             # Returns: Array of all keys that match $key taking into account the
844             # object state.
845             #
846             # There must be a more compact way of doing this
847              
848             sub compare_with_list {
849 0     0 0   my $self = shift;
850              
851 0           my $flag = shift;
852 0           my $key = shift;
853 0           my @list = @_;
854              
855 0           my @result = ();
856              
857 0           my ($casesens, $minmatch);
858 0 0         if ($flag == 0) {
859 0           $casesens = $self->casesens;
860 0           $minmatch = $self->minmatch;
861             } else {
862 0           $casesens = $self->casesenstrans;
863 0           $minmatch = $self->minmatchtrans;
864             }
865              
866             # Do matches
867              
868             # Case Sensitive
869 0 0         if ($casesens) {
870              
871             # Always start with the exact match before proceding to minimum
872             # match.
873             # We want to make sure that we will always match on the
874             # exact match even if alternatives exist (eg COL will always
875             # match just COL if the keys are COL and COLOUR)
876             # Case insensitive
877 0           @result = grep { /^$key$/ } @list;
  0            
878              
879             # Proceed to minimum match if we detected nothing
880             # Minumum match/ Case sensitive
881 0 0 0       if ($#result == -1 && $minmatch) {
882              
883 0           @result = grep { /^$key/ } @list;
  0            
884              
885             }
886              
887             } else {
888              
889             # We want to make sure that we will always match on the
890             # exact match even if alternatives exist (eg COL will always
891             # match just COL if the keys are COL and COLOUR)
892             # First do the exact match (case insensitive)
893             {
894 0           local $^W = undef; # To silence warnings about uninitialised values
  0            
895 0           @result = grep { /^$key$/i } @list;
  0            
896             }
897             # If this match came up with something then we will use it
898             # Else we will try a minimum match (assuming flag is true)
899              
900             # Minumum match/ Case insensitive
901 0 0 0       if ($#result == -1 && $minmatch) {
902              
903 0           @result = grep { /^$key/i } @list;
  0            
904              
905             }
906             }
907 0           return @result;
908             }
909              
910              
911              
912              
913             =back
914              
915             =head1 EXAMPLE
916              
917             Two examples are shown. The first uses the simplified interface and
918             the second uses the object-oriented interface.
919              
920             =head1 Non-OO
921              
922             use PDLA::Options (':Func');
923              
924             %options = parse( {
925             LINE => 1,
926             COLOUR => 'red',
927             },
928             {
929             COLOR => 'blue'
930             }
931             );
932              
933             This will return a hash containg
934              
935             %options = (
936             LINE => 1,
937             COLOUR => 'blue'
938             )
939              
940              
941             =head1 Object oriented
942              
943             The following example will try to show the main points:
944              
945             use PDLA::Options ();
946              
947             # Create new object and supply defaults
948             $opt = new PDLA::Options( { Colour => 'red',
949             LineStyle => 'dashed',
950             LineWidth => 1
951             }
952             );
953              
954             # Create synonyms
955             $opt->synonyms( { Color => 'Colour' } );
956              
957             # Create translation dictionary
958             $opt->translation( { Colour => {
959             'blue' => '#0000ff',
960             'red' => '#ff0000',
961             'green'=> '#00ff00'
962             },
963             LineStyle => {
964             'solid' => 1,
965             'dashed' => 2,
966             'dotted' => 3
967             }
968             }
969             );
970              
971             # Generate and parse test hash
972             $options = $opt->options( { Color => 'green',
973             lines => 'solid',
974             }
975             );
976              
977             When this code is run, $options will be the reference to a hash
978             containing the following:
979              
980             Colour => '#00ff00',
981             LineStyle => 1,
982             LineWidth => 1
983              
984             If full_options() was set to false (0), $options would be a reference
985             to a hash containing:
986              
987             Colour => '#00ff00',
988             LineStyle => 1
989              
990             Minimum matching and case insensitivity can be configured for both
991             the initial parsing and for the subsequent translating. The translation
992             can be turned off if not desired.
993              
994             Currently synonyms are not available for the translation although this
995             could be added quite simply.
996              
997             =head1 AUTHOR
998              
999             Copyright (C) Tim Jenness 1998 (t.jenness@jach.hawaii.edu). All
1000             rights reserved. There is no warranty. You are allowed to redistribute
1001             this software / documentation under certain conditions. For details,
1002             see the file COPYING in the PDLA distribution. If this file is
1003             separated from the PDLA distribution, the copyright notice should be
1004             included in the file.
1005              
1006             =cut
1007              
1008              
1009             1;
1010