File Coverage

blib/lib/PDL/Options.pm
Criterion Covered Total %
statement 160 252 63.4
branch 42 102 41.1
condition 5 12 41.6
subroutine 23 30 76.6
pod 23 26 88.4
total 253 422 59.9


line stmt bran cond sub pod time code
1              
2             package PDL::Options;
3              
4             =head1 NAME
5              
6             PDL::Options - simplifies option passing by hash in PerlDL
7              
8             =head1 SYNOPSIS
9              
10             use PDL::Options;
11              
12             %hash = parse( \%defaults, \%user_options);
13              
14             use PDL::Options ();
15              
16             $opt = new PDL::Options;
17             $opt = new PDL::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 122     122   930 use strict;
  122         305  
  122         4314  
40 122     122   664 use Carp;
  122         255  
  122         9443  
41              
42 122     122   738 use vars qw/$VERSION %EXPORT_TAGS %DEF_SYNS @ISA/;
  122         255  
  122         300121  
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 53     53 1 113 my ($href) = @_;
111 53 100 66     276 return defined $href && ref $href eq 'HASH' ? $href : {};
112             }
113              
114 1     1 1 5 sub parse { return _parse(1,@_) }
115 18     18 1 65 sub iparse { return _parse(0,@_) }
116              
117             sub _parse {
118              
119 19 50   19   84 croak 'Usage: parse( \%defaults, \%user )' if scalar(@_) != 3;
120              
121 19         41 my $casechk = shift;
122 19         33 my $defaults = shift;
123 19 50       59 croak ("First argument is not a hash reference")
124             unless ref($defaults) eq "HASH";
125              
126 19         37 my $user = shift;
127 19 50       59 croak ("Second argument is not a hash reference")
128             unless ref($user) eq "HASH";
129              
130             # Create new object
131 19         108 my $opt = new PDL::Options ( $defaults );
132              
133             # Set up default behaviour
134 19         72 $opt->minmatch(1);
135 19         60 $opt->casesens($casechk);
136 19         69 $opt->synonyms( \%DEF_SYNS );
137              
138             # Process the options
139 19         71 my $optref = $opt->options( $user );
140              
141 19         193 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 PDL::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 98     98 1 304 my $proto = shift;
172 98   33     788 my $class = ref($proto) || $proto;
173              
174 98         261 my $opt = {};
175              
176             # Set up object structure
177 98         364 $opt->{DEFAULTS} = {}; # Default options
178 98         281 $opt->{CURRENT} = {}; # Current options
179 98         294 $opt->{CurrKeys} = []; # list of selected keys if full_options(0)
180 98         253 $opt->{SYNONYMS} = {}; # List of synonyms
181 98         280 $opt->{INC} = 0; # Flag to decide whether we are incremental on cur
182 98         228 $opt->{CaseSens} = 0; # Are options case sensitive
183 98         221 $opt->{MinMatch} = 1; # Minimum matching on keys
184 98         323 $opt->{Translation} = {};# Translation from eg 'RED' to 1
185 98         220 $opt->{AutoTranslate}= 1;# Automatically translate options when processing
186 98         232 $opt->{MinMatchTrans} = 0; # Min matching during translation
187 98         222 $opt->{CaseSensTrans} = 0; # Case sensitive during translation
188             # Return full options list
189 98         288 $opt->{FullOptions} = $default->{FullOptions};
190             # Whether to warn for options that are invalid or not
191 98         214 $opt->{WarnOnMissing}= $default->{WarnOnMissing};
192 98         345 $opt->{DEBUG} = $default->{DEBUG}; # Turn on debug messages
193              
194             # Bless into class
195 98         255 bless ( $opt, $class);
196              
197             # If we were passed arguments, pass to defaults method
198 98 50       811 if (@_) { $opt->defaults( @_ ); }
  98         418  
199              
200 98         324 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 0 my ($self, $opt)=@_;
213              
214 0         0 my $class = ref($self);
215 0         0 my $h = {%{$self}};
  0         0  
216 0 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         0 $h->{SYNONYMS}={%{$self->{SYNONYMS}}};
  0         0  
223 0         0 $h->{Translation}={%{$self->{Translation}}};
  0         0  
224 0         0 $h->{CurrKeys}=[@{$self->{CurrKeys}}];
  0         0  
225             #
226             # Create the extended option list.
227             #
228 0         0 my %all_options = (%{$opt}, %{$self->{DEFAULTS}});
  0         0  
  0         0  
229              
230             # Bless it
231 0         0 bless ($h, $class);
232              
233             # And parse the default options
234 0         0 $h->defaults(\%all_options);
235              
236 0         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 185     185 1 337 my $self = shift;
276              
277 185 100       494 if (@_) {
278 98         189 my $arg = shift;
279 98 50       371 croak("Argument is not a hash reference") unless ref($arg) eq "HASH";
280 98         800 $self->{DEFAULTS} = $arg;
281              
282             # Reset the current state (making sure that I disconnect the
283             # hashes
284 98         600 my %hash = %$arg;
285 98         467 $self->curr_full(\%hash);
286              
287             }
288              
289             # Decouple the hash to protect it from being modified outside the
290             # object
291 185         384 my %hash = %{$self->{DEFAULTS}};
  185         732  
292 185         437 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 0 my $self=shift;
305 0 0       0 return unless @_;
306 0         0 my $arg = shift;
307 0 0       0 croak("Synonym argument is not a hash reference") unless ref($arg) eq "HASH";
308              
309 0         0 foreach (keys %$arg) {
310 0         0 $self->{SYNONYMS}{$_}=$arg->{$_};
311             }
312 0         0 my %hash = %{$self->{SYNONYMS}};
  0         0  
313 0         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 0 my $self = shift;
327 0 0       0 return unless @_;
328 0         0 my $arg = shift;
329 0 0       0 croak("Translation argument is not a hash reference") unless ref($arg) eq 'HASH';
330              
331 0         0 foreach (keys %$arg) {
332 0         0 $self->{Translation}{$_}=$arg->{$_};
333             }
334 0         0 my %hash = %{$self->{Translation}};
  0         0  
335              
336 0         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 117     117 1 178 my $self = shift;
353              
354 117 100       268 if (@_) {
355 30         43 my $arg = shift;
356 30 50       87 croak("Argument is not a hash reference") unless ref($arg) eq "HASH";
357 30         64 $self->{SYNONYMS} = $arg;
358             }
359              
360             # Decouple the hash to protect it from being modified outside the
361             # object
362 117         159 my %hash = %{$self->{SYNONYMS}};
  117         346  
363 117         350 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 116     116 1 183 my $self = shift;
381              
382 116 50       246 if ($self->full_options) {
383 116         213 return $self->curr_full;
384             } else {
385 0         0 my @keys = $self->curr_keys;
386 0         0 my %hash = ();
387 0         0 my $curr = $self->curr_full;
388              
389 0         0 foreach my $key (@keys) {
390 0 0       0 $hash{$key} = $$curr{$key} if exists $$curr{$key};
391             }
392 0         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 0 my $self = shift;
405 0         0 @{$self->{CurrKeys}}=();
  0         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 87     87 0 142 my $self = shift;
417 87 100       223 if (@_) { @{$self->{CurrKeys}} = @_; }
  39         79  
  39         113  
418 87         130 return @{$self->{CurrKeys}};
  87         169  
419             }
420              
421             # Method to set the full state of the object
422             # Not publicising this
423              
424             sub curr_full {
425 475     475 0 659 my $self = shift;
426              
427 475 100       922 if (@_) {
428 272         398 my $arg = shift;
429 272 50       668 croak("Argument is not a hash reference") unless ref($arg) eq "HASH";
430 272         683 $self->{CURRENT} = $arg;
431             }
432              
433             # Decouple the hash
434 475         641 my %hash = %{$self->{CURRENT}};
  475         1558  
435 475         1475 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 87     87 1 130 my $self = shift;
470              
471 87 50       218 if (@_) {
472 0         0 my $arg = shift;
473 0 0       0 croak("Argument is not a hash reference") unless ref($arg) eq "HASH";
474 0         0 $self->{Translation} = $arg;
475             }
476              
477             # Decouple the hash to protect it from being modified outside the
478             # object
479 87         127 my %hash = %{$self->{Translation}};
  87         195  
480 87         209 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 87     87 1 144 my $self = shift;
498 87 50       203 if (@_) { $self->{INC} = shift; }
  0         0  
499 87         292 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 116     116 1 160 my $self = shift;
520 116 50       266 if (@_) { $self->{FullOptions} = shift; }
  0         0  
521 116         276 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 83     83 1 125 my $self = shift;
536 83 100       175 if (@_) { $self->{CaseSens} = shift; }
  20         36  
537 83         147 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 83     83 1 119 my $self = shift;
558 83 100       175 if (@_) { $self->{MinMatch} = shift; }
  20         44  
559 83         138 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 87     87 1 142 my $self = shift;
575 87 50       215 if (@_) { $self->{AutoTranslate} = shift; }
  0         0  
576 87         324 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 0 my $self = shift;
591 0 0       0 if (@_) { $self->{CaseSensTrans} = shift; }
  0         0  
592 0         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 0 my $self = shift;
612 0 0       0 if (@_) { $self->{MinMatchTrans} = shift; }
  0         0  
613 0         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 0 my $self = shift;
628 0 0       0 if (ref $self) {
629 0 0       0 if (@_) { $self->{WarnOnMissing}=shift;}
  0         0  
630 0         0 return $self->{WarnOnMissing};
631             } else {
632 0 0       0 $default->{WarnOnMissing} = shift if @_;
633 0         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 60     60 1 88 my $self = shift;
647 60 50       140 if (ref $self) {
648 60 50       147 if (@_) { $self->{DEBUG} = shift; }
  0         0  
649 60         209 return $self->{DEBUG};
650             } else {
651 0 0       0 $default->{DEBUG} = shift if @_;
652 0         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 87     87 1 153 my $self = shift;
688              
689             # If there is an argument do something clever
690 87 50       213 if (@_) {
691              
692             # check that the arg is a hash
693 87         139 my $arg = shift;
694 87 50       255 croak("Argument is not a hash reference") unless ref($arg) eq "HASH";
695              
696             # Turn the options into a real hash
697 87         262 my %user = %$arg;
698              
699             # Now read in the base options
700 87         170 my $base;
701 87 50       220 if ($self->incremental) {
702 0         0 $base = $self->curr_full;
703             } else {
704 87         210 $base = $self->defaults;
705             }
706              
707             # Turn into a real hash for convenience
708 87         337 my %base = %$base;
709              
710             # Store a list of all the expanded user keys
711 87         221 my @list = ();
712              
713             # Read in synonyms
714 87         179 my %syn = %{$self->synonyms};
  87         210  
715              
716             # Now go through the keys in the user hash and compare with
717             # the defaults
718 87         388 foreach my $userkey (sort keys %user) {
719              
720             # Check for matches in the default set
721 60         205 my @matched = $self->compare_with_list(0, $userkey, keys %base);
722              
723             # If we had no matches, check the synonyms list
724 60 100       168 if ($#matched == -1) {
725 3         11 @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 3         11 for (my $i =0; $i <= $#matched; $i++) {
730 3         10 $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 60 50       157 if ($#matched == -1) {
737 0 0       0 print "Warning: $userkey is not a valid option\n" if $self->{WarnOnMissing};
738             } else {
739 60 50       140 if ( $#matched > 0 ) {
740 0         0 print "Warning: Multiple matches for option $userkey\n";
741 0         0 print "Warning: Could be any of the following:\n";
742 0         0 print join("\n",@matched) . "\n";
743 0         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 60         136 $base{$matched[0]} = $user{$userkey};
748 60         109 push(@list, $matched[0]);
749 60 50       153 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 87         292 $self->curr_keys(@list);
756 87         248 $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 87 50       256 $self->translate if $self->autotrans;
766              
767             }
768              
769             # Current state should now be in current.
770             # Simply return it
771 87         368 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 87     87 1 147 my $self = shift;
789              
790 87         121 my %trans = %{$self->translation};
  87         210  
791 87         169 my %opt = %{$self->curr_full}; # Process all options
  87         157  
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 87         316 foreach my $key ( keys %opt ) {
797 381 50       692 if (exists $trans{$key}) {
798             # Okay so a translation might exist
799             # Now compare keys in the hash in the hash
800 0         0 my %subhash = %{$trans{$key}};
  0         0  
801              
802             my @matched =
803 0         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       0 if ($#matched > -1) {
810 0 0       0 if ( $#matched > 0 ) {
811 0         0 print "Warning: Multiple matches for $opt{$key} in option $key\n";
812 0         0 print "Warning: Could be any of the following:\n";
813 0         0 print join("\n",@matched) . "\n";
814 0         0 print "Accepting the first match ($matched[0])\n";
815              
816             }
817             # Modify the value in the options set
818 0 0       0 print "Translation: $opt{$key} translated to $subhash{$matched[0]}\n"
819             if $self->debug;
820 0         0 $opt{$key} = $subhash{$matched[0]};
821              
822             }
823              
824             }
825              
826             }
827              
828             # Update the current state
829 87         240 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 63     63 0 101 my $self = shift;
850              
851 63         100 my $flag = shift;
852 63         95 my $key = shift;
853 63         140 my @list = @_;
854              
855 63         98 my @result = ();
856              
857 63         111 my ($casesens, $minmatch);
858 63 50       170 if ($flag == 0) {
859 63         143 $casesens = $self->casesens;
860 63         131 $minmatch = $self->minmatch;
861             } else {
862 0         0 $casesens = $self->casesenstrans;
863 0         0 $minmatch = $self->minmatchtrans;
864             }
865              
866             # Do matches
867              
868             # Case Sensitive
869 63 50       124 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         0 @result = grep { /^$key$/ } @list;
  0         0  
878              
879             # Proceed to minimum match if we detected nothing
880             # Minumum match/ Case sensitive
881 0 0 0     0 if ($#result == -1 && $minmatch) {
882              
883 0         0 @result = grep { /^$key/ } @list;
  0         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 63         100 local $^W = undef; # To silence warnings about uninitialised values
  63         250  
895 63         126 @result = grep { /^$key$/i } @list;
  261         1359  
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 63 100 66     278 if ($#result == -1 && $minmatch) {
902              
903 15         28 @result = grep { /^$key/i } @list;
  30         143  
904              
905             }
906             }
907 63         175 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 PDL::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 containing
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 PDL::Options ();
946              
947             # Create new object and supply defaults
948             $opt = new PDL::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 PDL distribution. If this file is
1003             separated from the PDL distribution, the copyright notice should be
1004             included in the file.
1005              
1006             =cut
1007              
1008              
1009             1;
1010