File Coverage

blib/lib/Perl/ToPerl6/Config.pm
Criterion Covered Total %
statement 280 414 67.6
branch 48 110 43.6
condition 10 35 28.5
subroutine 45 72 62.5
pod 26 26 100.0
total 409 657 62.2


line stmt bran cond sub pod time code
1             package Perl::ToPerl6::Config;
2              
3 1     1   14 use 5.006001;
  1         3  
4 1     1   5 use strict;
  1         1  
  1         18  
5 1     1   4 use warnings;
  1         1  
  1         22  
6              
7 1     1   4 use English qw(-no_match_vars);
  1         2  
  1         6  
8 1     1   423 use Readonly;
  1         2  
  1         39  
9              
10 1     1   4 use List::MoreUtils qw(any none apply);
  1         1  
  1         8  
11 1     1   451 use Scalar::Util qw(blessed);
  1         1  
  1         55  
12              
13 1     1   513 use Perl::ToPerl6::Exception::AggregateConfiguration;
  1         2  
  1         43  
14 1     1   5 use Perl::ToPerl6::Exception::Configuration;
  1         2  
  1         38  
15 1     1   14948 use Perl::ToPerl6::Exception::Configuration::Option::Global::ParameterValue;
  1         2  
  1         48  
16 1     1   5 use Perl::ToPerl6::Exception::Fatal::Internal qw{ throw_internal };
  1         2  
  1         14  
17 1     1   604 use Perl::ToPerl6::TransformerFactory;
  1         3  
  1         7  
18 1     1   589 use Perl::ToPerl6::Theme qw( $RULE_INVALID_CHARACTER_REGEX cook_rule );
  1         3  
  1         17  
19 1     1   635 use Perl::ToPerl6::UserProfile qw();
  1         3  
  1         56  
20 1         65 use Perl::ToPerl6::Utils qw{
21             :booleans :characters :severities :internal_lookup :classification
22             :data_conversion
23 1     1   9 };
  1         2  
24 1         194 use Perl::ToPerl6::Utils::Constants qw<
25             :profile_strictness
26             $_MODULE_VERSION_TERM_ANSICOLOR
27 1     1   734 >;
  1         4  
28 1     1   7 use Perl::ToPerl6::Utils::DataConversion qw< boolean_to_number dor >;
  1         3  
  1         4213  
29              
30             #-----------------------------------------------------------------------------
31              
32             Readonly::Scalar my $SINGLE_TRANSFORMER_CONFIG_KEY => 'single-transformer';
33              
34             #-----------------------------------------------------------------------------
35             # Constructor
36              
37             sub new {
38              
39 3     3 1 11500 my ( $class, %args ) = @_;
40 3         10 my $self = bless {}, $class;
41 3         16 $self->_init( %args );
42 3         24 return $self;
43             }
44              
45             #-----------------------------------------------------------------------------
46              
47             sub _init {
48 3     3   9 my ( $self, %args ) = @_;
49              
50             # -top or -theme imply that -necessity is 1, unless it is already defined
51 3 50 33     29 if ( defined $args{-top} || defined $args{-theme} ) {
52 0   0     0 $args{-necessity} ||= $NECESSITY_LOWEST;
53             }
54              
55 3         40 my $errors = Perl::ToPerl6::Exception::AggregateConfiguration->new();
56              
57             # Construct the UserProfile to get default options.
58 3         1277 my $profile_source = $args{-profile}; # Can be file path or data struct
59 3         30 my $profile = Perl::ToPerl6::UserProfile->new( -profile => $profile_source );
60 3         12 my $options_processor = $profile->options_processor();
61 3         10 $self->{_profile} = $profile;
62              
63             $self->_validate_and_save_profile_strictness(
64 3         21 $args{'-profile-strictness'},
65             $errors,
66             );
67              
68             # If given, these options should always have a true value.
69             $self->_validate_and_save_regex(
70 3         18 'include', $args{-include}, $options_processor->include(), $errors
71             );
72             $self->_validate_and_save_regex(
73 3         18 'exclude', $args{-exclude}, $options_processor->exclude(), $errors
74             );
75             $self->_validate_and_save_regex(
76             $SINGLE_TRANSFORMER_CONFIG_KEY,
77 3         18 $args{ qq/-$SINGLE_TRANSFORMER_CONFIG_KEY/ },
78             $options_processor->single_transformer(),
79             $errors,
80             );
81             $self->_validate_and_save_color_necessity(
82 3         17 'color_necessity_highest', $args{'-color-necessity-highest'},
83             $options_processor->color_necessity_highest(), $errors
84             );
85             $self->_validate_and_save_color_necessity(
86 3         24 'color_necessity_high', $args{'-color-necessity-high'},
87             $options_processor->color_necessity_high(), $errors
88             );
89             $self->_validate_and_save_color_necessity(
90 3         18 'color_necessity_medium', $args{'-color-necessity-medium'},
91             $options_processor->color_necessity_medium(), $errors
92             );
93             $self->_validate_and_save_color_necessity(
94 3         18 'color_necessity_low', $args{'-color-necessity-low'},
95             $options_processor->color_necessity_low(), $errors
96             );
97             $self->_validate_and_save_color_necessity(
98 3         16 'color_necessity_lowest', $args{'-color-necessity-lowest'},
99             $options_processor->color_necessity_lowest(), $errors
100             );
101              
102 3         17 $self->_validate_and_save_verbosity($args{-verbose}, $errors);
103 3         17 $self->_validate_and_save_necessity($args{-necessity}, $errors);
104 3         16 $self->_validate_and_save_detail($args{-detail}, $errors);
105 3         18 $self->_validate_and_save_top($args{-top}, $errors);
106 3         14 $self->_validate_and_save_theme($args{-theme}, $errors);
107 3         15 $self->_validate_and_save_pager($args{-pager}, $errors);
108             $self->_validate_and_save_program_extensions(
109 3         16 $args{'-program-extensions'}, $errors);
110              
111             # If given, these options can be true or false (but defined)
112             # We normalize these to numeric values by multiplying them by 1;
113 3         18 $self->{_force} = boolean_to_number( dor( $args{-force}, $options_processor->force() ) );
114 3         18 $self->{_in_place} = boolean_to_number( dor( $args{'-in-place'}, $options_processor->in_place() ) );
115 3         16 $self->{_only} = boolean_to_number( dor( $args{-only}, $options_processor->only() ) );
116 3         18 $self->{_color} = boolean_to_number( dor( $args{-color}, $options_processor->color() ) );
117              
118              
119             # Construct a Factory with the Profile
120 3         15 my $factory =
121             Perl::ToPerl6::TransformerFactory->new(
122             -profile => $profile,
123             -errors => $errors,
124             '-profile-strictness' => $self->profile_strictness(),
125             );
126 3         10 $self->{_factory} = $factory;
127              
128             # Initialize internal storage for Transformers
129 3         8 $self->{_all_transformers_enabled_or_not} = [];
130 3         7 $self->{_transformers} = [];
131              
132             # "NONE" means don't load any transformers
133 3 100 66     19 if ( not defined $profile_source or $profile_source ne 'NONE' ) {
134             # Heavy lifting here...
135 1         6 $self->_load_transformers($errors);
136             }
137              
138 3 50       15 if ( $errors->has_exceptions() ) {
139 0         0 $errors->rethrow();
140             }
141              
142 3         109 return $self;
143             }
144              
145             #-----------------------------------------------------------------------------
146              
147             sub apply_transform {
148              
149 37     37 1 74 my ( $self, %args ) = @_;
150              
151 37 50       100 if ( not $args{-transformer} ) {
152 0         0 throw_internal q{The -transformer argument is required};
153             }
154              
155 37         797 my $transformer = $args{-transformer};
156              
157             # If the -transformer is already a blessed object, then just add it directly.
158 37 50       121 if ( blessed $transformer ) {
159 37         71 $self->_apply_transform_if_enabled($transformer);
160 37         95 return $self;
161             }
162              
163             # NOTE: The "-config" option is supported for backward compatibility.
164 0   0     0 my $params = $args{-params} || $args{-config};
165              
166 0         0 my $factory = $self->{_factory};
167 0         0 my $transformer_object =
168             $factory->create_transformer(-name=>$transformer, -params=>$params);
169 0         0 $self->_apply_transform_if_enabled($transformer_object);
170              
171 0         0 return $self;
172             }
173              
174             #-----------------------------------------------------------------------------
175              
176             sub _apply_transform_if_enabled {
177 37     37   57 my ( $self, $transformer_object ) = @_;
178              
179 37 50       89 my $config = $transformer_object->__get_config()
180             or throw_internal
181             q{Transformer was not set up properly because it does not have }
182             . q{a value for its config attribute.};
183              
184 37         43 push @{ $self->{_all_transformers_enabled_or_not} }, $transformer_object;
  37         76  
185 37 50       186 if ( $transformer_object->initialize_if_enabled( $config ) ) {
186 37         173 $transformer_object->__set_enabled($TRUE);
187 37         40 push @{ $self->{_transformers} }, $transformer_object;
  37         63  
188             }
189             else {
190 0         0 $transformer_object->__set_enabled($FALSE);
191             }
192              
193 37         58 return;
194             }
195              
196             #-----------------------------------------------------------------------------
197              
198             sub _load_transformers {
199              
200 1     1   2 my ( $self, $errors ) = @_;
201 1         4 my $factory = $self->{_factory};
202 1         4 my @transformers = $factory->create_all_transformers( $errors );
203              
204 1 50       6 return if $errors->has_exceptions();
205              
206 1         22 for my $transformer ( @transformers ) {
207              
208             # If -single-transformer is true, only load transformers that match it
209 37 50       64 if ( $self->single_transformer() ) {
210 0 0       0 if ( $self->_transformer_is_single_transformer( $transformer ) ) {
211 0         0 $self->apply_transform( -transformer => $transformer );
212             }
213 0         0 next;
214             }
215              
216             # To load, or not to load -- that is the question.
217 37 50       72 my $load_me = $self->only() ? $FALSE : $TRUE;
218              
219 37 50       74 $load_me = $FALSE if $self->_transformer_is_disabled( $transformer );
220 37 50       78 $load_me = $TRUE if $self->_transformer_is_enabled( $transformer );
221 37 50       73 $load_me = $FALSE if $self->_transformer_is_unimportant( $transformer );
222 37 50       79 $load_me = $FALSE if not $self->_transformer_is_thematic( $transformer );
223 37 50       80 $load_me = $TRUE if $self->_transformer_is_included( $transformer );
224 37 50       116 $load_me = $FALSE if $self->_transformer_is_excluded( $transformer );
225              
226              
227 37 50       109 next if not $load_me;
228 37         94 $self->apply_transform( -transformer => $transformer );
229             }
230              
231             # When using -single-transformer, only one transformer should ever be loaded.
232 1 50 33     4 if ($self->single_transformer() && scalar $self->transformers() != 1) {
233 0         0 $self->_add_single_transformer_exception_to($errors);
234             }
235              
236 1         5 return;
237             }
238              
239             #-----------------------------------------------------------------------------
240              
241             sub _transformer_is_disabled {
242 37     37   45 my ($self, $transformer) = @_;
243 37         71 my $profile = $self->_profile();
244 37         98 return $profile->transformer_is_disabled( $transformer );
245             }
246              
247             #-----------------------------------------------------------------------------
248              
249             sub _transformer_is_enabled {
250 37     37   49 my ($self, $transformer) = @_;
251 37         66 my $profile = $self->_profile();
252 37         97 return $profile->transformer_is_enabled( $transformer );
253             }
254              
255             #-----------------------------------------------------------------------------
256              
257             sub _transformer_is_thematic {
258 37     37   41 my ($self, $transformer) = @_;
259 37         64 my $theme = $self->theme();
260 37         112 return $theme->transformer_is_thematic( -transformer => $transformer );
261             }
262              
263             #-----------------------------------------------------------------------------
264              
265             sub _transformer_is_unimportant {
266 37     37   51 my ($self, $transformer) = @_;
267 37         188 my $transformer_necessity = $transformer->get_necessity();
268 37         60 my $min_necessity = $self->{_necessity};
269 37         95 return $transformer_necessity < $min_necessity;
270             }
271              
272             #-----------------------------------------------------------------------------
273              
274             sub _transformer_is_included {
275 37     37   46 my ($self, $transformer) = @_;
276 37         57 my $transformer_long_name = ref $transformer;
277 37         70 my @inclusions = $self->include();
278 37     0   172 return any { $transformer_long_name =~ m/$_/ixms } @inclusions;
  0         0  
279             }
280              
281             #-----------------------------------------------------------------------------
282              
283             sub _transformer_is_excluded {
284 37     37   49 my ($self, $transformer) = @_;
285 37         51 my $transformer_long_name = ref $transformer;
286 37         86 my @exclusions = $self->exclude();
287 37     0   154 return any { $transformer_long_name =~ m/$_/ixms } @exclusions;
  0         0  
288             }
289              
290             #-----------------------------------------------------------------------------
291              
292             sub _transformer_is_single_transformer {
293 0     0   0 my ($self, $transformer) = @_;
294              
295 0         0 my @patterns = $self->single_transformer();
296 0 0       0 return if not @patterns;
297              
298 0         0 my $transformer_long_name = ref $transformer;
299 0     0   0 return any { $transformer_long_name =~ m/$_/ixms } @patterns;
  0         0  
300             }
301              
302             #-----------------------------------------------------------------------------
303              
304             sub _new_global_value_exception {
305 0     0   0 my ($self, @args) = @_;
306              
307             return
308 0         0 Perl::ToPerl6::Exception::Configuration::Option::Global::ParameterValue
309             ->new(@args);
310             }
311              
312             #-----------------------------------------------------------------------------
313              
314             sub _add_single_transformer_exception_to {
315 0     0   0 my ($self, $errors) = @_;
316              
317 0         0 my $message_suffix = $EMPTY;
318 0         0 my $patterns = join q{", "}, $self->single_transformer();
319              
320 0 0       0 if (scalar $self->transformers() == 0) {
321 0         0 $message_suffix =
322             q{did not match any transformers (in combination with }
323             . q{other transformer restrictions).};
324             }
325             else {
326 0         0 $message_suffix = qq{matched multiple transformers:\n\t};
327 0     0   0 $message_suffix .= join qq{,\n\t}, apply { chomp } sort $self->transformers();
  0         0  
328             }
329              
330 0         0 $errors->add_exception(
331             $self->_new_global_value_exception(
332             option_name => $SINGLE_TRANSFORMER_CONFIG_KEY,
333             option_value => $patterns,
334             message_suffix => $message_suffix,
335             )
336             );
337              
338 0         0 return;
339             }
340              
341             #-----------------------------------------------------------------------------
342              
343             sub _validate_and_save_regex {
344 9     9   20 my ($self, $option_name, $args_value, $default_value, $errors) = @_;
345              
346 9         12 my $full_option_name;
347             my $source;
348 0         0 my @regexes;
349              
350 9 50       21 if ($args_value) {
351 0         0 $full_option_name = "-$option_name";
352              
353 0 0       0 if (ref $args_value) {
354 0         0 @regexes = @{ $args_value };
  0         0  
355             }
356             else {
357 0         0 @regexes = ( $args_value );
358             }
359             }
360              
361 9 50       29 if (not @regexes) {
362 9         67 $full_option_name = $option_name;
363 9         19 $source = $self->_profile()->source();
364              
365 9 100       27 if (ref $default_value) {
    50          
366 6         10 @regexes = @{ $default_value };
  6         11  
367             }
368             elsif ($default_value) {
369 0         0 @regexes = ( $default_value );
370             }
371             }
372              
373 9         13 my $found_errors;
374 9         15 foreach my $regex (@regexes) {
375 0         0 eval { qr/$regex/ixms }
376 0 0       0 or do {
377 0   0     0 my $cleaned_error = $EVAL_ERROR || '<unknown reason>';
378 0         0 $cleaned_error =~
379             s/ [ ] at [ ] .* Config [.] pm [ ] line [ ] \d+ [.] \n? \z/./xms;
380              
381 0         0 $errors->add_exception(
382             $self->_new_global_value_exception(
383             option_name => $option_name,
384             option_value => $regex,
385             source => $source,
386             message_suffix => qq{is not valid: $cleaned_error},
387             )
388             );
389              
390 0         0 $found_errors = 1;
391             }
392             }
393              
394 9 50       21 if (not $found_errors) {
395 9         13 my $option_key = $option_name;
396 9         19 $option_key =~ s/ - /_/xmsg;
397              
398 9         22 $self->{"_$option_key"} = \@regexes;
399             }
400              
401 9         18 return;
402             }
403              
404             #-----------------------------------------------------------------------------
405              
406             sub _validate_and_save_profile_strictness {
407 3     3   9 my ($self, $args_value, $errors) = @_;
408              
409 3         7 my $option_name;
410             my $source;
411 0         0 my $profile_strictness;
412              
413 3 50       9 if ($args_value) {
414 0         0 $option_name = '-profile-strictness';
415 0         0 $profile_strictness = $args_value;
416             }
417             else {
418 3         6 $option_name = 'profile-strictness';
419              
420 3         12 my $profile = $self->_profile();
421 3         12 $source = $profile->source();
422 3         13 $profile_strictness = $profile->options_processor()->profile_strictness();
423             }
424              
425 3 50       18 if ( not $PROFILE_STRICTNESSES{$profile_strictness} ) {
426 0         0 $errors->add_exception(
427             $self->_new_global_value_exception(
428             option_name => $option_name,
429             option_value => $profile_strictness,
430             source => $source,
431             message_suffix => q{is not one of "}
432             . join ( q{", "}, (sort keys %PROFILE_STRICTNESSES) )
433             . q{".},
434             )
435             );
436              
437 0         0 $profile_strictness = $PROFILE_STRICTNESS_FATAL;
438             }
439              
440 3         30 $self->{_profile_strictness} = $profile_strictness;
441              
442 3         6 return;
443             }
444              
445             #-----------------------------------------------------------------------------
446              
447             sub _validate_and_save_verbosity {
448 3     3   7 my ($self, $args_value, $errors) = @_;
449              
450 3         5 my $option_name;
451             my $source;
452 0         0 my $verbosity;
453              
454 3 50       9 if ($args_value) {
455 0         0 $option_name = '-verbose';
456 0         0 $verbosity = $args_value;
457             }
458             else {
459 3         4 $option_name = 'verbose';
460              
461 3         8 my $profile = $self->_profile();
462 3         9 $source = $profile->source();
463 3         11 $verbosity = $profile->options_processor()->verbose();
464             }
465              
466 3 50 33     11 if (
467             is_integer($verbosity)
468             and not is_valid_numeric_verbosity($verbosity)
469             ) {
470 0         0 $errors->add_exception(
471             $self->_new_global_value_exception(
472             option_name => $option_name,
473             option_value => $verbosity,
474             source => $source,
475             message_suffix =>
476             'is not the number of one of the pre-defined verbosity formats.',
477             )
478             );
479             }
480             else {
481 3         35 $self->{_verbose} = $verbosity;
482             }
483              
484 3         8 return;
485             }
486              
487             #-----------------------------------------------------------------------------
488              
489             sub _validate_and_save_necessity {
490 3     3   6 my ($self, $args_value, $errors) = @_;
491              
492 3         4 my $option_name;
493             my $source;
494 0         0 my $necessity;
495              
496 3 50       9 if ($args_value) {
497 0         0 $option_name = '-necessity';
498 0         0 $necessity = $args_value;
499             }
500             else {
501 3         6 $option_name = 'necessity';
502              
503 3         6 my $profile = $self->_profile();
504 3         9 $source = $profile->source();
505 3         10 $necessity = $profile->options_processor()->necessity();
506             }
507              
508 3 50       7 if ( is_integer($necessity) ) {
    0          
509 3 50 33     19 if (
510             $necessity >= $NECESSITY_LOWEST and $necessity <= $NECESSITY_HIGHEST
511             ) {
512 3         10 $self->{_necessity} = $necessity;
513             }
514             else {
515 0         0 $errors->add_exception(
516             $self->_new_global_value_exception(
517             option_name => $option_name,
518             option_value => $necessity,
519             source => $source,
520             message_suffix =>
521             "is not between $NECESSITY_LOWEST (low) and $NECESSITY_HIGHEST (high).",
522             )
523             );
524             }
525             }
526 0     0   0 elsif ( not any { $_ eq lc $necessity } @NECESSITY_NAMES ) {
527 0         0 $errors->add_exception(
528             $self->_new_global_value_exception(
529             option_name => $option_name,
530             option_value => $necessity,
531             source => $source,
532             message_suffix =>
533             q{is not one of the valid necessity names: "}
534             . join (q{", "}, @NECESSITY_NAMES)
535             . q{".},
536             )
537             );
538             }
539             else {
540 0         0 $self->{_necessity} = necessity_to_number($necessity);
541             }
542              
543 3         4 return;
544             }
545              
546             #-----------------------------------------------------------------------------
547              
548             sub _validate_and_save_top {
549 3     3   8 my ($self, $args_value, $errors) = @_;
550              
551 3         6 my $option_name;
552             my $source;
553 0         0 my $top;
554              
555 3 50 33     10 if (defined $args_value and $args_value ne q{}) {
556 0         0 $option_name = '-top';
557 0         0 $top = $args_value;
558             }
559             else {
560 3         8 $option_name = 'top';
561              
562 3         7 my $profile = $self->_profile();
563 3         9 $source = $profile->source();
564 3         9 $top = $profile->options_processor()->top();
565             }
566              
567 3 50 33     9 if ( is_integer($top) and $top >= 0 ) {
568 3         7 $self->{_top} = $top;
569             }
570             else {
571 0         0 $errors->add_exception(
572             $self->_new_global_value_exception(
573             option_name => $option_name,
574             option_value => $top,
575             source => $source,
576             message_suffix => q{is not a non-negative integer.},
577             )
578             );
579             }
580              
581 3         7 return;
582             }
583              
584             #-----------------------------------------------------------------------------
585              
586             sub _validate_and_save_theme {
587 3     3   7 my ($self, $args_value, $errors) = @_;
588              
589 3         5 my $option_name;
590             my $source;
591 0         0 my $theme_rule;
592              
593 3 50       5 if ($args_value) {
594 0         0 $option_name = '-theme';
595 0         0 $theme_rule = $args_value;
596             }
597             else {
598 3         6 $option_name = 'theme';
599              
600 3         7 my $profile = $self->_profile();
601 3         10 $source = $profile->source();
602 3         7 $theme_rule = $profile->options_processor()->theme();
603             }
604              
605 3 50       15 if ( $theme_rule =~ m/$RULE_INVALID_CHARACTER_REGEX/xms ) {
606 0         0 my $bad_character = $1;
607              
608 0         0 $errors->add_exception(
609             $self->_new_global_value_exception(
610             option_name => $option_name,
611             option_value => $theme_rule,
612             source => $source,
613             message_suffix =>
614             qq{contains an illegal character ("$bad_character").},
615             )
616             );
617             }
618             else {
619 3         15 my $rule_as_code = cook_rule($theme_rule);
620 3         6 $rule_as_code =~ s/ [\w\d]+ / 1 /gxms;
621              
622             # eval of an empty string does not reset $@ in Perl 5.6.
623 3         7 local $EVAL_ERROR = $EMPTY;
624 3         70 eval $rule_as_code;
625              
626 3 50       12 if ($EVAL_ERROR) {
627 0         0 $errors->add_exception(
628             $self->_new_global_value_exception(
629             option_name => $option_name,
630             option_value => $theme_rule,
631             source => $source,
632             message_suffix => q{is not syntactically valid.},
633             )
634             );
635             }
636             else {
637             eval {
638             $self->{_theme} =
639 3         26 Perl::ToPerl6::Theme->new( -rule => $theme_rule );
640             }
641 3 50       5 or do {
642 0         0 $errors->add_exception_or_rethrow( $EVAL_ERROR );
643             };
644             }
645             }
646              
647 3         5 return;
648             }
649              
650             #-----------------------------------------------------------------------------
651              
652             sub _validate_and_save_pager {
653 3     3   7 my ($self, $args_value, $errors) = @_;
654              
655 3         5 my $pager;
656 3 50       13 if ( $args_value ) {
    50          
657 0 0       0 $pager = defined $args_value ? $args_value : $EMPTY;
658             }
659             elsif ( $ENV{PERLMOGRIFY_PAGER} ) {
660 0         0 $pager = $ENV{PERLMOGRIFY_PAGER};
661             }
662             else {
663 3         7 my $profile = $self->_profile();
664 3         9 $pager = $profile->options_processor()->pager();
665             }
666              
667 3 50       15 if ($pager eq '$PAGER') {
668 0         0 $pager = $ENV{PAGER};
669             }
670 3   33     13 $pager ||= $EMPTY;
671              
672 3         11 $self->{_pager} = $pager;
673              
674 3         7 return;
675             }
676              
677             #-----------------------------------------------------------------------------
678              
679             sub _validate_and_save_detail {
680 3     3   7 my ($self, $args_value, $errors) = @_;
681              
682 3         6 my $option_name;
683             my $source;
684 0         0 my $detail;
685              
686 3 50       9 if ($args_value) {
687 0         0 $option_name = '-detail';
688 0         0 $detail = $args_value;
689             }
690             else {
691 3         7 $option_name = 'detail';
692              
693 3         8 my $profile = $self->_profile();
694 3         11 $source = $profile->source();
695 3         9 $detail = $profile->options_processor()->detail();
696             }
697              
698 3 50       9 if ( is_integer($detail) ) {
    0          
699 3 50 33     19 if (
700             $detail >= $NECESSITY_LOWEST and $detail <= $NECESSITY_HIGHEST
701             ) {
702 3         9 $self->{_detail} = $detail;
703             }
704             else {
705 0         0 $errors->add_exception(
706             $self->_new_global_value_exception(
707             option_name => $option_name,
708             option_value => $detail,
709             source => $source,
710             message_suffix =>
711             "is not between $NECESSITY_LOWEST (low) and $NECESSITY_HIGHEST (high).",
712             )
713             );
714             }
715             }
716 0     0   0 elsif ( not any { $_ eq lc $detail } @NECESSITY_NAMES ) {
717 0         0 $errors->add_exception(
718             $self->_new_global_value_exception(
719             option_name => $option_name,
720             option_value => $detail,
721             source => $source,
722             message_suffix =>
723             q{is not one of the valid necessity names: "}
724             . join (q{", "}, @NECESSITY_NAMES)
725             . q{".},
726             )
727             );
728             }
729             else {
730 0         0 $self->{_detail} = necessity_to_number($detail);
731             }
732              
733 3         7 return;
734             }
735              
736             #-----------------------------------------------------------------------------
737              
738             sub _validate_and_save_color_necessity {
739 15     15   38 my ($self, $option_name, $args_value, $default_value, $errors) = @_;
740              
741 15         19 my $source;
742             my $color_necessity;
743 0         0 my $full_option_name;
744              
745 15 50       24 if (defined $args_value) {
746 0         0 $full_option_name = "-$option_name";
747 0         0 $color_necessity = lc $args_value;
748             }
749             else {
750 15         21 $full_option_name = $option_name;
751 15         68 $source = $self->_profile()->source();
752 15         29 $color_necessity = lc $default_value;
753             }
754 15         30 $color_necessity =~ s/ \s+ / /xmsg;
755 15         24 $color_necessity =~ s/ \A\s+ //xms;
756 15         23 $color_necessity =~ s/ \s+\z //xms;
757 15         41 $full_option_name =~ s/ _ /-/xmsg;
758              
759             # Should we really be validating this?
760 15         18 my $found_errors;
761 15 50       21 if (
762             eval {
763 15         3457 require Term::ANSIColor;
764 15         8082 Term::ANSIColor->VERSION( $_MODULE_VERSION_TERM_ANSICOLOR );
765 15         67 1;
766             }
767             ) {
768 15         39 $found_errors =
769             not Term::ANSIColor::colorvalid( words_from_string($color_necessity) );
770             }
771              
772             # If we do not have Term::ANSIColor we can not validate, but we store the
773             # values anyway for the benefit of Perl::ToPerl6::ProfilePrototype.
774              
775 15 50       156 if ($found_errors) {
776 0         0 $errors->add_exception(
777             $self->_new_global_value_exception(
778             option_name => $full_option_name,
779             option_value => $color_necessity,
780             source => $source,
781             message_suffix => 'is not valid.',
782             )
783             );
784             }
785             else {
786 15         23 my $option_key = $option_name;
787 15         21 $option_key =~ s/ - /_/xmsg;
788              
789 15         42 $self->{"_$option_key"} = $color_necessity;
790             }
791              
792 15         28 return;
793             }
794              
795             #-----------------------------------------------------------------------------
796              
797             sub _validate_and_save_program_extensions {
798 3     3   6 my ($self, $args_value, $errors) = @_;
799              
800 3         7 delete $self->{_program_extensions_as_regexes};
801              
802             my $extension_list = q{ARRAY} eq ref $args_value ?
803 3 50       12 [map {words_from_string($_)} @{ $args_value }] :
  0         0  
  0         0  
804             $self->_profile()->options_processor()->program_extensions();
805              
806 3         6 my %program_extensions = hashify( @{ $extension_list } );
  3         12  
807              
808 3         8 $self->{_program_extensions} = [keys %program_extensions];
809              
810 3         7 return;
811              
812             }
813              
814             #-----------------------------------------------------------------------------
815             # Begin ACCESSSOR methods
816              
817             sub _profile {
818 122     122   148 my ($self) = @_;
819 122         245 return $self->{_profile};
820             }
821              
822             #-----------------------------------------------------------------------------
823              
824             sub all_transformers_enabled_or_not {
825 0     0 1 0 my ($self) = @_;
826 0         0 return @{ $self->{_all_transformers_enabled_or_not} };
  0         0  
827             }
828              
829             #-----------------------------------------------------------------------------
830              
831             sub transformers {
832 0     0 1 0 my ($self) = @_;
833 0         0 return @{ $self->{_transformers} };
  0         0  
834             }
835              
836             #-----------------------------------------------------------------------------
837              
838             sub exclude {
839 37     37 1 65 my ($self) = @_;
840 37         39 return @{ $self->{_exclude} };
  37         68  
841             }
842              
843             #-----------------------------------------------------------------------------
844              
845             sub detail {
846 0     0 1 0 my ($self) = @_;
847 0         0 return $self->{_detail};
848             }
849              
850             #-----------------------------------------------------------------------------
851              
852             sub force {
853 0     0 1 0 my ($self) = @_;
854 0         0 return $self->{_force};
855             }
856              
857             #-----------------------------------------------------------------------------
858              
859             sub include {
860 37     37 1 42 my ($self) = @_;
861 37         35 return @{ $self->{_include} };
  37         77  
862             }
863              
864             #-----------------------------------------------------------------------------
865              
866             sub in_place {
867 0     0 1 0 my ($self) = @_;
868 0         0 return $self->{_in_place};
869             }
870              
871             #-----------------------------------------------------------------------------
872              
873             sub only {
874 37     37 1 61 my ($self) = @_;
875 37         88 return $self->{_only};
876             }
877              
878             #-----------------------------------------------------------------------------
879              
880             sub profile_strictness {
881 3     3 1 8 my ($self) = @_;
882 3         27 return $self->{_profile_strictness};
883             }
884              
885             #-----------------------------------------------------------------------------
886              
887             sub necessity {
888 0     0 1 0 my ($self) = @_;
889 0         0 return $self->{_necessity};
890             }
891              
892             #-----------------------------------------------------------------------------
893              
894             sub single_transformer {
895 38     38 1 49 my ($self) = @_;
896 38         43 return @{ $self->{_single_transformer} };
  38         103  
897             }
898              
899             #-----------------------------------------------------------------------------
900              
901             sub theme {
902 37     37 1 39 my ($self) = @_;
903 37         59 return $self->{_theme};
904             }
905              
906             #-----------------------------------------------------------------------------
907              
908             sub top {
909 0     0 1   my ($self) = @_;
910 0           return $self->{_top};
911             }
912              
913             #-----------------------------------------------------------------------------
914              
915             sub verbose {
916 0     0 1   my ($self) = @_;
917 0           return $self->{_verbose};
918             }
919              
920             #-----------------------------------------------------------------------------
921              
922             sub color {
923 0     0 1   my ($self) = @_;
924 0           return $self->{_color};
925             }
926              
927             #-----------------------------------------------------------------------------
928              
929             sub pager {
930 0     0 1   my ($self) = @_;
931 0           return $self->{_pager};
932             }
933              
934             #-----------------------------------------------------------------------------
935              
936             sub site_transformer_names {
937 0     0 1   return Perl::ToPerl6::TransformerFactory::site_transformer_names();
938             }
939              
940             #-----------------------------------------------------------------------------
941              
942             sub color_necessity_highest {
943 0     0 1   my ($self) = @_;
944 0           return $self->{_color_necessity_highest};
945             }
946              
947             #-----------------------------------------------------------------------------
948              
949             sub color_necessity_high {
950 0     0 1   my ($self) = @_;
951 0           return $self->{_color_necessity_high};
952             }
953              
954             #-----------------------------------------------------------------------------
955              
956             sub color_necessity_medium {
957 0     0 1   my ($self) = @_;
958 0           return $self->{_color_necessity_medium};
959             }
960              
961             #-----------------------------------------------------------------------------
962              
963             sub color_necessity_low {
964 0     0 1   my ($self) = @_;
965 0           return $self->{_color_necessity_low};
966             }
967              
968             #-----------------------------------------------------------------------------
969              
970             sub color_necessity_lowest {
971 0     0 1   my ($self) = @_;
972 0           return $self->{_color_necessity_lowest};
973             }
974              
975             #-----------------------------------------------------------------------------
976              
977             sub program_extensions {
978 0     0 1   my ($self) = @_;
979 0           return @{ $self->{_program_extensions} };
  0            
980             }
981              
982             #-----------------------------------------------------------------------------
983              
984             sub program_extensions_as_regexes {
985 0     0 1   my ($self) = @_;
986              
987 0           return @{ $self->{_program_extensions_as_regexes} }
988 0 0         if $self->{_program_extensions_as_regexes};
989              
990 0           my %program_extensions = hashify( $self->program_extensions() );
991 0           $program_extensions{'.PL'} = 1;
992             return @{
993 0           $self->{_program_extensions_as_regexes} = [
994 0           map { qr< @{[quotemeta $_]} \z >smx } sort keys %program_extensions
  0            
  0            
995             ]
996             };
997             }
998              
999             1;
1000              
1001             #-----------------------------------------------------------------------------
1002              
1003             __END__
1004              
1005             =pod
1006              
1007             =for stopwords colour INI-style -params
1008              
1009             =head1 NAME
1010              
1011             Perl::ToPerl6::Config - The final derived Perl::ToPerl6 configuration, combined from any profile file and command-line parameters.
1012              
1013              
1014             =head1 DESCRIPTION
1015              
1016             Perl::ToPerl6::Config takes care of finding and processing
1017             user-preferences for L<Perl::ToPerl6|Perl::ToPerl6>. The Config object
1018             defines which Transformer modules will be loaded into the Perl::ToPerl6
1019             engine and how they should be configured. You should never really
1020             need to instantiate Perl::ToPerl6::Config directly because the
1021             Perl::ToPerl6 constructor will do it for you.
1022              
1023              
1024             =head1 INTERFACE SUPPORT
1025              
1026             This is considered to be a non-public class. Its interface is subject
1027             to change without notice.
1028              
1029              
1030             =head1 CONSTRUCTOR
1031              
1032             =over
1033              
1034             =item C<< new(...) >>
1035              
1036             Not properly documented because you shouldn't be using this.
1037              
1038              
1039             =back
1040              
1041             =head1 METHODS
1042              
1043             =over
1044              
1045             =item C<< apply_transform( -transformer => $transformer_name, -params => \%param_hash ) >>
1046              
1047             Creates a Transformer object and loads it into this Config. If the object
1048             cannot be instantiated, it will throw a fatal exception. Otherwise,
1049             it returns a reference to this ToPerl6.
1050              
1051             B<-transformer> is the name of a
1052             L<Perl::ToPerl6::Transformer|Perl::ToPerl6::Transformer> subclass module. The
1053             C<'Perl::ToPerl6::Transformer'> portion of the name can be omitted for
1054             brevity. This argument is required.
1055              
1056             B<-params> is an optional reference to a hash of Transformer parameters.
1057             The contents of this hash reference will be passed into to the
1058             constructor of the Transformer module. See the documentation in the
1059             relevant Transformer module for a description of the arguments it supports.
1060              
1061              
1062             =item C< all_transformers_enabled_or_not() >
1063              
1064             Returns a list containing references to all the Transformer objects that
1065             have been seen. Note that the state of these objects is not
1066             trustworthy. In particular, it is likely that some of them are not
1067             prepared to examine any documents.
1068              
1069              
1070             =item C< transformers() >
1071              
1072             Returns a list containing references to all the Transformer objects that
1073             have been enabled and loaded into this Config.
1074              
1075              
1076             =item C< exclude() >
1077              
1078             Returns the value of the C<-exclude> attribute for this Config.
1079              
1080              
1081             =item C< include() >
1082              
1083             Returns the value of the C<-include> attribute for this Config.
1084              
1085              
1086             =item C< detail() >
1087              
1088             Returns the value of the C<-detail> attribute for this Config.
1089              
1090              
1091             =item C< force() >
1092              
1093             Returns the value of the C<-force> attribute for this Config.
1094              
1095              
1096             =item C< in_place() >
1097              
1098             Returns the value of the C<-in-place> attribute for this Config.
1099              
1100              
1101             =item C< only() >
1102              
1103             Returns the value of the C<-only> attribute for this Config.
1104              
1105              
1106             =item C< profile_strictness() >
1107              
1108             Returns the value of the C<-profile-strictness> attribute for this
1109             Config.
1110              
1111              
1112             =item C< necessity() >
1113              
1114             Returns the value of the C<-necessity> attribute for this Config.
1115              
1116              
1117             =item C< single_transformer() >
1118              
1119             Returns the value of the C<-single-transformer> attribute for this Config.
1120              
1121              
1122             =item C< theme() >
1123              
1124             Returns the L<Perl::ToPerl6::Theme|Perl::ToPerl6::Theme> object that was
1125             created for this Config.
1126              
1127              
1128             =item C< top() >
1129              
1130             Returns the value of the C<-top> attribute for this Config.
1131              
1132              
1133             =item C< verbose() >
1134              
1135             Returns the value of the C<-verbose> attribute for this Config.
1136              
1137              
1138             =item C< color() >
1139              
1140             Returns the value of the C<-color> attribute for this Config.
1141              
1142              
1143             =item C< pager() >
1144              
1145             Returns the value of the C<-pager> attribute for this Config.
1146              
1147              
1148             =item C< color_necessity_highest() >
1149              
1150             Returns the value of the C<-color-necessity-highest> attribute for this
1151             Config.
1152              
1153              
1154             =item C< color_necessity_high() >
1155              
1156             Returns the value of the C<-color-necessity-high> attribute for this
1157             Config.
1158              
1159              
1160             =item C< color_necessity_medium() >
1161              
1162             Returns the value of the C<-color-necessity-medium> attribute for this
1163             Config.
1164              
1165              
1166             =item C< color_necessity_low() >
1167              
1168             Returns the value of the C<-color-necessity-low> attribute for this
1169             Config.
1170              
1171              
1172             =item C< color_necessity_lowest() >
1173              
1174             Returns the value of the C<-color-necessity-lowest> attribute for this
1175             Config.
1176              
1177             =item C< program_extensions() >
1178              
1179             Returns the value of the C<-program_extensions> attribute for this Config.
1180             This is an array of the file name extensions that represent program files.
1181              
1182             =item C< program_extensions_as_regexes() >
1183              
1184             Returns the value of the C<-program_extensions> attribute for this Config, as
1185             an array of case-sensitive regexes matching the ends of the file names that
1186             represent program files.
1187              
1188             =back
1189              
1190              
1191             =head1 SUBROUTINES
1192              
1193             Perl::ToPerl6::Config has a few static subroutines that are used
1194             internally, but may be useful to you in some way.
1195              
1196              
1197             =over
1198              
1199             =item C<site_transformer_names()>
1200              
1201             Returns a list of all the Transformer modules that are currently installed
1202             in the Perl::ToPerl6:Transformer namespace. These will include modules that
1203             are distributed with Perl::ToPerl6 plus any third-party modules that
1204             have been installed.
1205              
1206              
1207             =back
1208              
1209              
1210             =head1 CONFIGURATION
1211              
1212             Most of the settings for Perl::ToPerl6 and each of the Transformer modules
1213             can be controlled by a configuration file. The default configuration
1214             file is called F<.perlmogrifyrc>.
1215             L<Perl::ToPerl6::Config|Perl::ToPerl6::Config> will look for this file
1216             in the current directory first, and then in your home directory.
1217             Alternatively, you can set the C<PERLMOGRIFY> environment variable to
1218             explicitly point to a different file in another location. If none of
1219             these files exist, and the C<-profile> option is not given to the
1220             constructor, then all Transformers will be loaded with their default
1221             configuration.
1222              
1223             The format of the configuration file is a series of INI-style blocks
1224             that contain key-value pairs separated by '='. Comments should start
1225             with '#' and can be placed on a separate line or after the name-value
1226             pairs if you desire.
1227              
1228             Default settings for Perl::ToPerl6 itself can be set B<before the first
1229             named block.> For example, putting any or all of these at the top of
1230             your configuration file will set the default value for the
1231             corresponding Perl::ToPerl6 constructor argument.
1232              
1233             necessity = 3 #Integer from 1 to 5
1234             in_place = 0 #Zero or One
1235             only = 1 #Zero or One
1236             detail = 0 #Integer from 1 to 5
1237             force = 0 #Zero or One
1238             verbose = 4 #Integer or format spec
1239             top = 50 #A positive integer
1240             theme = risky + (pbp * security) - cosmetic #A theme expression
1241             include = NamingConventions ClassHierarchies #Space-delimited list
1242             exclude = Variables Modules::RequirePackage #Space-delimited list
1243             color = 1 #Zero or One
1244             color-necessity-highest = bold red #Term::ANSIColor
1245             color-necessity-high = magenta #Term::ANSIColor
1246             color-necessity-medium = #no coloring
1247             color-necessity-low = #no coloring
1248             color-necessity-lowest = #no coloring
1249             program-extensions = #Space-delimited list
1250              
1251             The remainder of the configuration file is a series of blocks like
1252             this:
1253              
1254             [Perl::ToPerl6::Transformer::Category::TransformerName]
1255             necessity = 1
1256             set_themes = foo bar
1257             add_themes = baz
1258             arg1 = value1
1259             arg2 = value2
1260              
1261             C<Perl::ToPerl6::Transformer::Category::TransformerName> is the full name of a
1262             module that implements the transformer. The Transformer modules distributed
1263             with Perl::ToPerl6 have been grouped into categories according to the
1264             table of contents in Damian Conway's book B<Perl Best Practices>. For
1265             brevity, you can omit the C<'Perl::ToPerl6::Transformer'> part of the module
1266             name.
1267              
1268             C<necessity> is the level of importance you wish to assign to the
1269             Transformer. All Transformer modules are defined with a default necessity value
1270             ranging from 1 (least severe) to 5 (most severe). However, you may
1271             disagree with the default necessity and choose to give it a higher or
1272             lower necessity, based on your own coding philosophy.
1273              
1274             The remaining key-value pairs are configuration parameters that will
1275             be passed into the constructor of that Transformer. The constructors for
1276             most Transformer modules do not support arguments, and those that do should
1277             have reasonable defaults. See the documentation on the appropriate
1278             Transformer module for more details.
1279              
1280             Instead of redefining the necessity for a given Transformer, you can
1281             completely disable a Transformer by prepending a '-' to the name of the
1282             module in your configuration file. In this manner, the Transformer will
1283             never be loaded, regardless of the C<-necessity> given to the
1284             Perl::ToPerl6::Config constructor.
1285              
1286             A simple configuration might look like this:
1287              
1288             #--------------------------------------------------------------
1289             # I think these are really important, so always load them
1290              
1291             [TestingAndDebugging::RequireUseStrict]
1292             necessity = 5
1293              
1294             [TestingAndDebugging::RequireUseWarnings]
1295             necessity = 5
1296              
1297             #--------------------------------------------------------------
1298             # I think these are less important, so only load when asked
1299              
1300             [Variables::ProhibitPackageVars]
1301             necessity = 2
1302              
1303             [ControlStructures::ProhibitPostfixControls]
1304             allow = if unless #My custom configuration
1305             necessity = 2
1306              
1307             #--------------------------------------------------------------
1308             # Give these transformers a custom theme. I can activate just
1309             # these transformers by saying (-theme => 'larry + curly')
1310              
1311             [Modules::RequireFilenameMatchesPackage]
1312             add_themes = larry
1313              
1314             [TestingAndDebugging::RequireTestLables]
1315             add_themes = curly moe
1316              
1317             #--------------------------------------------------------------
1318             # I do not agree with these at all, so never load them
1319              
1320             [-NamingConventions::Capitalization]
1321             [-ValuesAndExpressions::ProhibitMagicNumbers]
1322              
1323             #--------------------------------------------------------------
1324             # For all other Transformers, I accept the default necessity, theme
1325             # and other parameters, so no additional configuration is
1326             # required for them.
1327              
1328             For additional configuration examples, see the F<perlmogrifyrc> file
1329             that is included in this F<t/examples> directory of this distribution.
1330              
1331              
1332             =head1 THE POLICIES
1333              
1334             A large number of Transformer modules are distributed with Perl::ToPerl6.
1335             They are described briefly in the companion document
1336             L<Perl::ToPerl6::TransformerSummary|Perl::ToPerl6::TransformerSummary> and in more
1337             detail in the individual modules themselves.
1338              
1339              
1340             =head1 TRANSFORMER THEMES
1341              
1342             Each Transformer is defined with one or more "themes". Themes can be used
1343             to create arbitrary groups of Transformers. They are intended to provide
1344             an alternative mechanism for selecting your preferred set of Transformers.
1345             For example, you may wish disable a certain subset of Transformers when
1346             analyzing test programs. Conversely, you may wish to enable only a
1347             specific subset of Transformers when analyzing modules.
1348              
1349             The Transformers that ship with Perl::ToPerl6 are have been broken into the
1350             following themes. This is just our attempt to provide some basic
1351             logical groupings. You are free to invent new themes that suit your
1352             needs.
1353              
1354             THEME DESCRIPTION
1355             --------------------------------------------------------------------------
1356             core All transformers that ship with Perl::ToPerl6
1357             pbp Transformers that come directly from "Perl Best Practices"
1358             bugs Transformers that prevent or reveal bugs
1359             maintenance Transformers that affect the long-term health of the code
1360             cosmetic Transformers that only have a superficial effect
1361             complexity Transformers that specificaly relate to code complexity
1362             security Transformers that relate to security issues
1363             tests Transformers that are specific to test programs
1364              
1365             Say C<`perlmogrify -list`> to get a listing of all available transformers
1366             and the themes that are associated with each one. You can also change
1367             the theme for any Transformer in your F<.perlmogrifyrc> file. See the
1368             L<"CONFIGURATION"> section for more information about that.
1369              
1370             Using the C<-theme> option, you can combine theme names with
1371             mathematical and boolean operators to create an arbitrarily complex
1372             expression that represents a custom "set" of Transformers. The following
1373             operators are supported
1374              
1375             Operator Alternative Meaning
1376             ----------------------------------------------------------------------------
1377             * and Intersection
1378             - not Difference
1379             + or Union
1380              
1381             Operator precedence is the same as that of normal mathematics. You
1382             can also use parenthesis to enforce precedence. Here are some
1383             examples:
1384              
1385             Expression Meaning
1386             ----------------------------------------------------------------------------
1387             pbp * bugs All transformers that are "pbp" AND "bugs"
1388             pbp and bugs Ditto
1389              
1390             bugs + cosmetic All transformers that are "bugs" OR "cosmetic"
1391             bugs or cosmetic Ditto
1392              
1393             pbp - cosmetic All transformers that are "pbp" BUT NOT "cosmetic"
1394             pbp not cosmetic Ditto
1395              
1396             -maintenance All transformers that are NOT "maintenance"
1397             not maintenance Ditto
1398              
1399             (pbp - bugs) * complexity All transformers that are "pbp" BUT NOT "bugs",
1400             AND "complexity"
1401             (pbp not bugs) and complexity Ditto
1402              
1403             Theme names are case-insensitive. If C<-theme> is set to an empty
1404             string, then it is equivalent to the set of all Transformers. A theme
1405             name that doesn't exist is equivalent to an empty set. Please See
1406             L<http://en.wikipedia.org/wiki/Set> for a discussion on set theory.
1407              
1408              
1409             =head1 SEE ALSO
1410              
1411             L<Perl::ToPerl6::OptionsProcessor|Perl::ToPerl6::OptionsProcessor>,
1412             L<Perl::ToPerl6::UserProfile|Perl::ToPerl6::UserProfile>
1413              
1414              
1415             =head1 AUTHOR
1416              
1417             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
1418              
1419              
1420             =head1 COPYRIGHT
1421              
1422             Copyright (c) 2005-2011 Imaginative Software Systems. All rights reserved.
1423              
1424             This program is free software; you can redistribute it and/or modify
1425             it under the same terms as Perl itself. The full text of this license
1426             can be found in the LICENSE file included with this module.
1427              
1428             =cut
1429              
1430             ##############################################################################
1431             # Local Variables:
1432             # mode: cperl
1433             # cperl-indent-level: 4
1434             # fill-column: 78
1435             # indent-tabs-mode: nil
1436             # c-indentation-style: bsd
1437             # End:
1438             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :