File Coverage

blib/lib/PDL/Options.pm
Criterion Covered Total %
statement 158 251 62.9
branch 43 104 41.3
condition 6 12 50.0
subroutine 22 30 73.3
pod 23 26 88.4
total 252 423 59.5


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