File Coverage

blib/lib/Module/TestConfig.pm
Criterion Covered Total %
statement 182 207 87.9
branch 72 108 66.6
condition 12 26 46.1
subroutine 31 32 96.8
pod 21 21 100.0
total 318 394 80.7


line stmt bran cond sub pod time code
1             # -*- perl -*-
2             #
3             # Module::TestConfig - asks questions to autowrite a config module
4              
5             package Module::TestConfig;
6             {
7             $Module::TestConfig::VERSION = '0.06_01';
8             }
9              
10             require 5.008;
11 7     7   279142 use strict;
  7         21  
  7         297  
12 7     7   41 use Carp;
  7         11  
  7         1636  
13 7     7   45 use Fcntl;
  7         19  
  7         2989  
14 7     7   48 use File::Basename qw/dirname/;
  7         208  
  7         1397  
15 7     7   8970 use Params::Validate;
  7         139317  
  7         1610  
16 7     7   6909 use Config::Auto;
  7         54804  
  7         279  
17 7     7   7005 use Module::TestConfig::Question;
  7         21  
  7         18907  
18              
19             # Dynamically loaded modules
20             # Data::Dumper;
21             # Text::FormatTable;
22             # Term::ReadKey;
23             # File::Path
24              
25             #------------------------------------------------------------
26             # Methods
27             #------------------------------------------------------------
28              
29             sub new {
30 8     8 1 208 my $proto = shift;
31 8   33     64 my $class = ref $proto || $proto;
32 8         29 my $self = bless {}, $class;
33 8         63 return $self->init(
34             verbose => 1,
35             defaults => 'defaults.config',
36             file => 'MyConfig.pm',
37             package => 'MyConfig',
38             order => [ qw/defaults/ ],
39             questions => [ ],
40             _defaults => { },
41             qi => 0,
42             @_,
43             );
44             }
45              
46             sub init {
47 8     8 1 94 my ( $self, %args ) = @_;
48              
49 8         64 while ( my ( $method, $args ) = each %args ) {
50 63 100       311 if ( $self->can( $method ) ) {
51 62         192 $self->$method( $args );
52             } else {
53 1         211 croak "Can't handle arg: '$method'. Aborting";
54             }
55             }
56              
57 7         28 $self->load_defaults;
58              
59             Params::Validate::validation_options(
60 22     22   334 on_fail => sub { $_[0] =~ s/to.*did //; die "Your answer didn't validate.\n$_[0]" },
  22         122  
61 7         14225 );
62              
63 7         253 return $self;
64             }
65              
66             sub load_defaults {
67 7     7 1 14 my $self = shift;
68 7 100       36 $self->{_defaults} = Config::Auto::parse( $self->defaults )
69             if -r $self->defaults;
70             }
71              
72             sub verbose {
73 11     11 1 27 my $self = shift;
74 11 100       44 $self->{verbose} = shift if @_;
75 11         52 $self->{verbose};
76             }
77              
78             sub file {
79 14     14 1 26 my $self = shift;
80 14 100       95 $self->{file} = shift if @_;
81 14         198 $self->{file};
82             }
83              
84             sub package {
85 10     10 1 20 my $self = shift;
86 10 100       71 $self->{package} = shift if @_;
87 10         66 $self->{package};
88             }
89              
90             # The filename of the defaults file.
91             sub defaults {
92 21     21 1 33 my $self = shift;
93 21 100       72 $self->{defaults} = shift if @_;
94 21         264 $self->{defaults};
95             }
96              
97             # The defaults hash
98             sub _defaults {
99 17     17   27 my $self = shift;
100 17 100       66 $self->{_defaults} = shift if @_;
101 17         74 $self->{_defaults};
102             }
103              
104             # Question index
105             sub qi {
106 120     120 1 149 my $self = shift;
107 120 100       245 $self->{qi} = shift if @_;
108 120         353 $self->{qi};
109             }
110              
111             sub order {
112 53     53 1 75 my $self = shift;
113              
114 53 100       132 if ( @_ ) {
115 9 100       39 my @order = ref $_[0] eq "ARRAY" ? @{ $_[0] } : @_;
  8         43  
116 9         80 for my $order ( @order ) {
117 12 50       328 croak "Bad arg given to order(): '$order'"
118             unless grep /^$order$/, qw/defaults env/;
119             }
120 9         39 $self->{order} = [ @order ];
121             }
122              
123 53 100       121 return wantarray ? @{ $self->{order} } : $self->{order};
  46         164  
124             }
125              
126             sub questions {
127 111     111 1 177 my $self = shift;
128              
129 111 50 66     611 if ( @_ > 1 ) {
    100          
    50          
130 0         0 $self->{questions}
131 0         0 = [ map { Module::TestConfig::Question->new( $_ ) } @_ ];
132             } elsif ( @_ == 1 && ref $_[0] eq "ARRAY" ) {
133 23         112 $self->{questions}
134 8         36 = [ map { Module::TestConfig::Question->new( $_ ) } @{ $_[0] } ];
  8         30  
135             } elsif ( @_ ) {
136 0         0 croak "questions() got bad args. Needs a list or arrayref.";
137             }
138              
139 111 100       456 return wantarray ? @{ $self->{questions} } : $self->{questions};
  2         12  
140             }
141              
142             sub answers {
143 17     17 1 20 my $self = shift;
144 17 100       36 $self->{answers} = shift if @_;
145 17 100       60 return wantarray ? %{ $self->{answers} } : $self->{answers};
  2         24  
146             }
147              
148             sub answer {
149 102     102 1 3937 my $self = shift;
150 102         165 my ($key, $val) = @_;
151 102 50       250 return if not defined $key;
152 102 100       848 return $self->{answers}{$key} if not defined $val;
153 21         124 return $self->{answers}{$key} = $val;
154             }
155              
156             sub ask {
157 6     6 1 367 my $self = shift;
158              
159 23         50 do {
160 23         54 my $q = $self->questions->[$self->qi];
161 23         75 my $name = $q->name;
162              
163             # Skip the question?
164 23 50       76 if ( $q->skip ) {
165 0 0       0 if ( ref $q->skip eq "CODE" ) {
    0          
166 0 0       0 next if $q->skip->( $self );
167             } elsif ( not ref $q->skip ) {
168 0 0       0 next if $q->skip;
169             } else {
170 0         0 croak "Don't know how to handle question #" . $self->qi . "'s skip block";
171             }
172             }
173 23         31 my $attempts = 0;
174              
175 43         114 ASK: {
176 23         28 my @args = ( $name => $self->prompt( $q ) );
177              
178             # Valid answer?
179 43 100       167 if ( $q->validate ) {
180 25 50       69 croak "validate must be a hashref. Aborting"
181             unless ref $q->validate eq "HASH";
182              
183 25         38 eval { validate( @args, { $name => $q->validate } ) };
  25         78  
184              
185 25 100       2344 if ( $@ ) {
186 22         96 warn $@;
187              
188 22 100       1064 if ( ++$attempts > 10 ) {
189 2         7 warn "Let's just skip that question, shall we?\n\n";
190 2         100 last ASK;
191             } else {
192 20         133 warn "Please try again. [Attempt $attempts]\n\n";
193 20         859 redo ASK;
194             }
195             }
196             }
197              
198 21         122 $self->answer($name, $args[-1]);
199             }
200              
201 6         15 } while ( $self->qi( $self->qi + 1 ) < scalar @{ $self->questions } );
202              
203 6         43 return $self;
204             }
205              
206             sub get_default {
207 43     43 1 55 my ($self, $i) = @_;
208              
209 43   66     146 $i ||= $self->qi;
210 43         77 my $q = $self->questions->[$i];
211 43         132 my $default = $q->default;
212 43 50       107 my $name = $q->name
213             or croak "No name defined for question \#$i.";
214              
215 43         93 for ( $self->order ) {
216 55 100       182 if ( /^env/o ) {
217 19 100       94 return $ENV{"\U$name"} if defined $ENV{"\U$name"};
218 14 100       54 return $ENV{"\L$name"} if defined $ENV{"\L$name"};
219             }
220              
221 48 100 100     314 return $self->_defaults->{$name}
222             if /^defaults/ && $self->{_defaults}{$name};
223             }
224              
225 27         134 my $answer = $self->answer($name);
226 27 100       90 return defined $answer ? $answer : $default;
227             }
228              
229             sub save {
230 1     1 1 6 my ($self) = @_;
231              
232 1 50       3 my $text = $self->package_text
233             or croak "No text to save. Aborting.";
234              
235 1         5 my $dir = dirname( $self->file );
236 1 50       17 unless ( -d $dir ) {
237 0         0 require File::Path;
238 0 0       0 File::Path::mkpath( [ $dir ], $self->verbose )
239             or croak "Can't make path $dir: $!";
240             }
241              
242 1 50       5 sysopen my $fh, $self->file, O_CREAT | O_WRONLY | O_TRUNC, 0600
243             or croak "Can't open '" . $self->file . "' for write: $!";
244 1         6 print $fh $text;
245 1 50       46 close $fh or carp ("Can't close '" . $self->file . "'. $!"), return;
246              
247 1 50       38 print "Module::TestConfig saved " . $self->file . " with these settings:\n"
248             . $self->report if $self->verbose;
249             }
250              
251             sub save_defaults {
252 2     2 1 95 my $self = shift;
253 2         11 my %args = (
254             file => $self->defaults,
255             sep => ':',
256             @_,
257             );
258              
259 7     7   55 no warnings "io";
  7         13  
  7         738  
260              
261 2 50       257 open my $fh, "> $args{file}"
262             or carp ("Unable to write to $args{file}: $!"), return;
263              
264 7     7   34 use warnings "io";
  7         14  
  7         9806  
265              
266 2         9 print $fh "# This defaults file was autogenerated by Module::TestConfig for "
267             . $self->package . "\n\n";
268              
269 2         4 while ( my ($k, $v) = each %{ $self->answers } ) {
  14         1011  
270 12 100       114 carp ("Skipping bad key with a separator in it: '$k'"), next
271             if $k =~ /$args{sep}/;
272 10         24 print $fh "$k$args{sep}$v\n";
273             }
274              
275 2 50       94 close $fh or return;
276              
277 2         27 return 1;
278             }
279              
280             # Try to report using the best method
281             sub report {
282 6     6 1 526 my $self = shift;
283              
284 6         28 eval { require Text::FormatTable };
  6         834  
285              
286 6 50       2490 return $@
287             ? $self->report_plain
288             : $self->report_pretty
289             }
290              
291             # Report using Test::FormatTable
292             sub report_pretty {
293 6     6 1 13 my $self = shift;
294              
295 6 50       69 croak "Can't use report_pretty() unless Text::AutoFormat is loaded."
296             unless UNIVERSAL::can('Text::FormatTable', 'new');
297              
298 6   50     22 my $screen_width = eval { require Term::ReadKey; (Term::ReadKey::GetTerminalSize())[0] } || 79;
299 6         125163 my $table = Text::FormatTable->new( '| r | l |' );
300              
301 6         1281 $table->rule('=');
302 6         229 $table->head('Name', 'Value');
303 6         621 $table->rule('=');
304              
305 6         60 for my $q ( @{ $self->questions } ) {
  6         113  
306 30 50       764 if ( $q->noecho ) {
307 0         0 $table->row( $q->name, '*****' );
308             } else {
309 30         147 $table->row( $q->name, $self->answer( $q->name ) );
310             }
311             }
312              
313 6         188 $table->rule('-');
314              
315 6         269 my $report = $table->render($screen_width);
316 6         11648 $report =~ s/^/\t/mg; # indent
317              
318 6         1086 return $report;
319             }
320              
321             # Report with plain text.
322             sub report_plain {
323 0     0 1 0 my $self = shift;
324              
325 0         0 my $report = '';
326              
327 0         0 for my $q ( @{ $self->questions } ) {
  0         0  
328 0 0       0 if ( $q->noecho ) {
329 0         0 $report .= $q->name . ": *****\n";
330             } else {
331 0         0 $report .= $q->name . ": ". $self->answer( $q->name ) . "\n";
332             }
333             }
334              
335 0         0 $report =~ s/^/\t/mg; # indent
336              
337 0         0 return $report;
338             }
339              
340             sub package_text {
341 1     1 1 2 my $self = shift;
342              
343              
344 1         3 my $data_pos = tell DATA;
345 1         4 local $/ = undef;
346 1         17 local $_ = ;
347 1         6 seek DATA, $data_pos, 0;
348              
349 1         7 my $pkg = $self->package;
350              
351 1         991 require Data::Dumper;
352 1         5480 $Data::Dumper::Terse = 2;
353 1         7 my $answers = Data::Dumper->Dump( [ { $self->answers } ] );
354              
355 1         88 s/%%PACKAGE%%/$pkg/mg;
356 1         5 s/%%ANSWERS%%/$answers/m;
357              
358 1         8 return $_;
359             }
360              
361              
362             # Based on ExtUtils::MakeMaker::prompt().
363             sub prompt {
364 43     43 1 48 my $self = shift;
365 43   33     256 my $q = shift || $self->questions->[$self->qi];
366              
367 43         689 local $| = 1;
368              
369 43 50 33     174 croak "prompt() called incorrectly"
370             unless defined $q->msg && defined $q->name;
371              
372 43         114 my $def = $self->get_default;
373 43 50       118 my $dispdef = defined $def ? " [$def] " : " ";
374 43 50       72 $def = defined $def ? $def : "";
375              
376 43         130 print $q->msg . $dispdef;
377              
378 43         93 my $ans = '';
379 43   33     180 my $ISA_TTY = -t STDIN && (-t STDOUT || !(-f STDOUT || -c STDOUT)); # Pipe?
380              
381 43 50       88 if ( $ISA_TTY ) {
382 0 0 0     0 if ( $Term::ReadKey::VERSION && $q->noecho ) {
383 0         0 ReadMode( 'noecho' );
384 0         0 chomp( $ans = ReadLine(0) );
385 0         0 ReadMode( 'normal' );
386 0         0 print "\n";
387             } else {
388 0         0 chomp( $ans = );
389             }
390             } else {
391 43         7369 print "$def\n";
392             }
393              
394 43 50       325 return $ans ne '' ? $ans : $def;
395             }
396              
397              
398             #------------------------------------------------------------
399             # Docs
400             #------------------------------------------------------------
401              
402             =head1 NAME
403              
404             Module::TestConfig - Interactively prompt user to generate a config module
405              
406             =head1 VERSION
407              
408             version 0.06_01
409              
410             =head1 SYNOPSIS
411              
412             use Module::TestConfig;
413              
414             Module::TestConfig->new(
415             verbose => 1,
416             defaults => 'defaults.config',
417             file => 'MyConfig.pm',
418             package => 'MyConfig',
419             order => [ qw/defaults env/ ],
420             questions => [
421             [ 'Would you like tea?' => 'tea', 'y' ],
422             [ 'Crumpets?' => 'crumpets', 'y' ],
423             ]
424             )->ask->save;
425              
426             # and in another module or test file:
427              
428             use MyConfig;
429              
430             my $config = MyConfig->new;
431             print $config->tea eq 'y'
432             ? "We're having tea today; splendid!"
433             : "No tea, I'm afraid. P'raps tomorrow.";
434              
435             print $config->crumpets eq 'y'
436             ? "Crumpets; lovely!"
437             : "Alas, we have no crumpets today";
438              
439              
440             =head1 DESCRIPTION
441              
442             This module prompts a user for info and writes a module for later use.
443             You can use it during the module build process (e.g. perl Makefile.PL)
444             to share info among your test files. You can also use it to install
445             that module into your site_perl.
446              
447             Module::TestConfig writes an object-oriented file. You specify
448             the file's location as well as the package name. When you use()
449             the file, each of the questions' names will become an object method.
450              
451             For example, if you asked the questions:
452              
453             Module::TestConfig->new(
454             file => 't/MyConfig.pm',
455             package => 'MyConfig',
456             questions => [
457             [ 'Can you feel that bump?', 'feel', 'n' ],
458             [ 'Would you like another?', 'another', 'y' ],
459             { msg => 'How many fingers am I holding up?',
460             name => 'fingers',
461             default => 11,
462             },
463             ],
464             )->ask->save;
465              
466             You'd see something like this:
467              
468             Can you feel that bump? [n] y
469             Would you like another? [y] n
470             How many fingers am I holding up? [11]
471             Module::TestConfig saved t/MyConfig.pm with these settings:
472             ===================
473             | Name | Value |
474             ===================
475             | feel | y |
476             | another | n |
477             | fingers | 11 |
478             +---------+-------+
479              
480             ...and the file t/MyConfig.pm was written. To use it, add this to
481             another file:
482              
483             use MyConfig;
484              
485             my $config = MyConfig->new;
486             print $config->fingers; # prints 11
487             print $config->feel; # prints 'y'
488             print $config->another; # prints 'n'
489              
490             =head1 PUBLIC METHODS
491              
492             =over 2
493              
494             =item new()
495              
496             Args and defaults:
497              
498             verbose => 1,
499             defaults => 'defaults.config',
500             file => 'MyConfig.pm',
501             package => 'MyConfig',
502             order => [ 'defaults' ],
503             questions => [ ... ],
504              
505             Returns: a new Module::TestConfig object.
506              
507             =item init()
508              
509             Sets object attributes.
510              
511             =item questions()
512              
513             Set up the questions that we'll ask of the user. This is a list (or
514             array) of questions. Each question can be in one of two forms, the
515             array form or the hash form. See L for
516             more about the question's arguments.
517              
518             Args:
519             an array of question hashes (or question arrays)
520             a list of question hashes (or question arrays)
521              
522             e.g. (to keep it simple, I'll only give an example of a hash-style
523             question):
524              
525             [
526             { question => "Question to ask:",
527             name => "foo",
528             default => 42,
529             noecho => 0,
530             skip => sub { shift->answer('bar') }, # skip if bar is true
531             validate => { regex => /^\d+$/ }, # answer must be all numbers
532             },
533             ...
534             ]
535              
536             Returns:
537             a list of questions in list context
538             an arrayref of questions in scalar context.
539              
540             Here's an overview of the hash-style arguments to set up a question.
541             See L for more details.
542              
543             Args:
544              
545             =over 4
546              
547             =item question or msg:
548              
549             A string like "Have you seen my eggplant?" or "Kittens:". They look
550             best when they end with a ':' or a '?'.
551              
552             =item name:
553              
554             A simple mnemonic used for looking up values later. Since it will turn
555             into a method name in the future, it ought to match /\w+/.
556              
557             =item default or def:
558              
559             optional. a default answer.
560              
561             =item noecho:
562              
563             optional. 1 or 0. Do we print the user's answer while they are typing?
564             This is useful when asking for for passwords.
565              
566             =item skip:
567              
568             optional. Accepts either a coderef or a scalar. The Module::TestConfig
569             object will be passed to the coderef as its first and only
570             argument. Use it to look up answer()s. If the coderef returns true or
571             the scalar is true, the current question will be skipped.
572              
573             =item validate:
574              
575             optional. A hashref suitable for Params::Validate::validate_pos().
576             See L. The question will loop over and over until
577             the user types in a correct answer - or at least one that validates.
578             After the user tries and fails 10 times, Module::TestConfig will give
579             up and skip the question.
580              
581             e.g.
582              
583             Module::TestConfig->new(
584             questions => [
585             {
586             question => 'Choose any integer: ',
587             name => 'num',
588             default => 0,
589             validate => { regex => qr/^\d+$/ },
590             },
591             {
592             question => 'Pick an int between 1 and 10: ',
593             name => 'guess',
594             default => 5,
595             validate => {
596             callbacks => {
597             '1 <= guess <= 10',
598             sub {
599             my $n = shift;
600             return unless $n =~ /^\d+$/;
601             return if $n < 1 || $n > 10;
602             return 1;
603             },
604             },
605             },
606             },
607             ]
608             )->ask->save;
609              
610             would behave like this when run:
611              
612             Pick a number, any integer: [0] peach
613             Your answer didn't validate.
614             The 'num' parameter did not pass regex check
615             Please try again. [Attempt 1]
616              
617             Pick a number, any integer: [0] plum
618             Your answer didn't validate.
619             The 'num' parameter did not pass regex check
620             Please try again. [Attempt 2]
621              
622             Pick a number, any integer: [0] 5
623             Pick an integer between 1 and 10: [5] 12
624             Your answer didn't validate.
625             The 'guess' parameter did not pass the '1 <= guess <= 10' callback
626             Please try again. [Attempt 1]
627              
628             Pick an integer between 1 and 10: [5] -1
629             Your answer didn't validate.
630             The 'guess' parameter did not pass the '1 <= guess <= 10' callback
631             Please try again. [Attempt 2]
632              
633             Pick an integer between 1 and 10: [5] 3
634             Module::TestConfig saved MyConfig.pm with these settings:
635             =================
636             | Name | Value |
637             =================
638             | num | 5 |
639             | guess | 3 |
640             +-------+-------+
641              
642             =back
643              
644             =item ask()
645              
646             Asks the user the questions.
647              
648             Returns: a Module::TestConfig object.
649              
650             =item save()
651              
652             Writes our answers to the file. The file created will always be
653             0600 for security reasons. This may change in the future. See
654             L<"SECURITY"> for more info.
655              
656             =item defaults()
657              
658             A file parsed by Config::Auto which may be used as default answers to
659             the questions. See L<"order()">
660              
661             Default: "defaults.config"
662              
663             Args: A filename or path.
664              
665             Returns: A filename or path.
666              
667             =item save_defaults()
668              
669             Writes a new defaults file. The key-value separator should be either
670             ':' or '=' to keep it compatible with L. See
671             L<"order()"> for more about defaults.
672              
673             Args and defaults:
674              
675             file => $object->defaults, # 'defaults.config'
676             sep => ':',
677              
678             Returns: 1 on success, undef on failure. Any error message can be
679             found in $!.
680              
681             =item file()
682              
683             The filename that gets written during save().
684              
685             Default: "MyConfig.pm"
686              
687             Args: a filepath that should probably end in ".pm". e.g. "t/MyConfig.pm"
688              
689             Returns: the filename or path.
690              
691             =item package()
692              
693             The file's package name written during save().
694              
695             Default: "MyConfig"
696              
697             Args: a package namespace. e.g. "Foo::Bar::Baz"
698              
699             Returns: the set package.
700              
701             =item order()
702              
703             Default: [ 'defaults' ]
704              
705             Args: [ qw/defaults env/ ]
706             [ qw/env defaults/ ]
707             [ qw/defaults/ ]
708             [ qw/env/ ]
709             [ ] # Don't preload defaults from file or env
710              
711             Where do we look up defaults for the questions? They can come from
712             either a file, the environment or perhaps come combination of both.
713              
714             =over 4
715              
716             =item defaults:
717              
718             a file read by Config::Auto that must parse to a hash of question
719             names and values.
720              
721             =item env:
722              
723             environment variables in either upper or lowercase.
724              
725             =back
726              
727             The following will also be checked, in order:
728              
729             =over 4
730              
731             =item answers:
732              
733             Any answers already hard-set via answers().
734              
735             =item a question's default:
736              
737             A default supplied with the question.
738              
739             =back
740              
741             There's a security risk accepting defaults from the environment or
742             from a file. See L<"SECURITY">.
743              
744             =item answer()
745              
746             Get the current value of a question. Useful when paired with a skip
747             or validate.
748              
749             Args: a question's name.
750              
751             Returns: The current value or undef.
752              
753             =item verbose()
754              
755             Should the module be chatty while running? Should it print a report at
756             the end?
757              
758             Default: 1
759              
760             Args: 1 or 0
761              
762             Returns: current value
763              
764             =back
765              
766             =head1 PROTECTED METHODS
767              
768             These are documented primarily for subclassing.
769              
770             =over 2
771              
772             =item answers()
773              
774             A user's questions get stored here. If you preset any answers before
775             calling ask(), they may be used as defaults. See L<"order()"> for
776             those rules.
777              
778             Args: a hash of question names and answers
779              
780             Returns: A hash in list context, a hashref in scalar context.
781              
782             =item prompt()
783              
784             Ask the user a question. It's your job to store the answer in
785             the answers().
786              
787             Args: $question, $default_answer, \%options
788              
789             Returns: the user's answer, a suitable default or ''.
790              
791             =item get_default()
792              
793             Get a question's default answer from env, file, answer() or the
794             question. It's printed with a prompt()ed question.
795              
796             =item load_defaults()
797              
798             Uses Config::Auto to parse the file specified by defaults(). Defaults
799             are stored in $obj-E{_defaults}.
800              
801             =item package_text()
802              
803             Returns the new file's text. This should take package() and
804             answers() into account.
805              
806             =item qi()
807              
808             The current question index.
809              
810             Args: A number
811              
812             Returns: The current number
813              
814             =item report()
815              
816             Returns a report of question names and values. Will be printed if the
817             object is in verbose mode. This calls report_pretty() or
818             report_plain() depending on whether Text::AutoFormat is
819             available. Won't print any passwords (questions called with C
820             =E 1> ) in plaintext.
821              
822             =item report_pretty()
823              
824             Prints the report like this:
825              
826             ==================
827             | Name | Value |
828             ==================
829             | one | 1 |
830             | two | 2 |
831             | three | 3 |
832             | fruit | kiwi |
833             | meat | pork |
834             | passwd | ***** |
835             +--------+-------+
836              
837             =item report_plain()
838              
839             Prints the report like this:
840              
841             one: 1
842             two: 2
843             three: 3
844             fruit: kiwi
845             meat: pork
846             passwd: *****
847              
848             =back
849              
850             =head1 SECURITY
851              
852             The resultant file (MyConfig.pm by default) will be chmod'd to 0600
853             but it will remain on the system.
854              
855             The default action is to load a file named 'defaults.config' and use
856             that for, well, defaults. If someone managed to put their own
857             defaults.config into your working directory, they might be able to
858             sneak a bad default past an unwitting user.
859              
860             Using the environment as input may be a security risk - or a potential
861             bug - especially if your names mimic existing environment variables.
862              
863             =head1 AUTHOR
864              
865             Joshua Keroes Ejoshua@cpan.orgE
866              
867             =head1 COPYRIGHT AND LICENSE
868              
869             Copyright 2003-2013 by Joshua Keroes Ejoshua@cpan.orgE
870              
871             This library is free software; you can redistribute it and/or modify
872             it under the same terms as Perl itself.
873              
874             =head1 SEE ALSO
875              
876             L
877             L
878             L
879              
880             =cut
881              
882             # Template for module generation follows:
883              
884             __DATA__