File Coverage

blib/lib/Config/Cmd.pm
Criterion Covered Total %
statement 69 77 89.6
branch 26 30 86.6
condition n/a
subroutine 10 11 90.9
pod 3 3 100.0
total 108 121 89.2


line stmt bran cond sub pod time code
1             package Config::Cmd;
2 2     2   101139 use Mo qw(default);
  2         1008  
  2         11  
3 2     2   4670 use YAML qw'DumpFile LoadFile';
  2         24037  
  2         158  
4 2     2   2081 use Modern::Perl;
  2         29289  
  2         11  
5 2     2   550 use Carp;
  2         4  
  2         165  
6              
7             # ABSTRACT: Command line to config file two way interface
8             our $VERSION = '0.002'; # VERSION
9              
10 2     2   12 use constant EXT => '_conf.yaml';
  2         3  
  2         2040  
11              
12             has section => ();
13             has filename => ();
14             has quote => ( default => sub { q(') } );
15              
16             sub set {
17 0     0 1 0 my $self = shift;
18 0         0 my $args = shift;
19              
20 0         0 say STDERR "# writing into ". $self->_set_file;
21 0         0 say STDERR "# options: ". "@$args";
22              
23 0         0 $self->set_silent($args);
24             }
25              
26             sub set_silent {
27 10     10 1 7348 my $self = shift;
28 10         20 my $args = shift;
29              
30             # process arguments
31 10         43 my $section = $self->section;
32 10 100       236 croak "Set section before writing into a file" unless $section;
33 9         32 my $config->{$section} = [];
34              
35 9         20 my $key = '';
36 9         38 while (my $e = shift @$args) {
37 37 100       155 if ($e eq '=') {
    100          
    100          
38 2         7 next;
39             }
40             elsif ($e =~ /(-.+)=(.+)/) {
41 2 100       7 if ($key) {
42 1         3 my $tuple->{key} = $key ;
43 1         2 push @{$config->{$section}}, $tuple;
  1         3  
44 1         2 $key = '';
45             }
46 2         7 my $tuple->{key} = $1 ;
47 2         4 $tuple->{value} = $2 ;
48 2         3 push @{$config->{$section}}, $tuple;
  2         7  
49             }
50             elsif ($e =~ /^-/) {
51 20 100       86 if ($key) {
52 5         13 my $tuple->{key} = $key ;
53 5         8 push @{$config->{$section}}, $tuple;
  5         14  
54             }
55 20         60 $key = $e;
56             } else {
57 13 100       29 if ($key) {
58 12         34 my $tuple->{key} = $key ;
59 12         22 $tuple->{value} = $e ;
60 12         19 push @{$config->{$section}}, $tuple;
  12         28  
61             }
62 13         43 $key = '';
63             }
64              
65             }
66 9 100       26 if ($key) {
67 2         7 my $tuple->{key} = $key;
68 2         29 push @{$config->{$section}}, $tuple;
  2         7  
69             }
70              
71 9         27 DumpFile $self->_set_file, $config;
72             }
73              
74             sub get {
75 9     9 1 52762 my $self = shift;
76 9         45 my $section = $self->section;
77              
78 9         68 my $config = LoadFile($self->_get_file);
79              
80 9         51760 my @list;
81 9         22 for my $tuple (@{$config->{$section}}) {
  9         36  
82 22 100       75 if (defined $tuple->{value}) {
83 14         35 my $value = $tuple->{value};
84 14 100       60 $value = $self->quote. $value. $self->quote if $value =~ /\s/;
85 14         70 push @list, $tuple->{key}, $value;
86             } else {
87 8         54 push @list, $tuple->{key};
88             }
89             }
90 9         107 return join ' ', @list;
91             }
92              
93             # internal methods
94              
95             sub _default_filename {
96 24     24   227 return shift->section. EXT;
97             }
98              
99             sub _set_file {
100 9     9   17 my $self = shift;
101              
102 9 100       35 return $self->filename if defined $self->filename;
103 8 50       59 return $self->_default_filename if $self->section;
104 0         0 return; # if no matching files were found
105             }
106              
107              
108             sub _get_file {
109 9     9   18 my $self = shift;
110              
111 9 100       33 return $self->filename if defined $self->filename;
112 8 50       75 if (-e $self->_default_filename) {
    0          
113 8         203 return $self->_default_filename;
114             } elsif (-e $ENV{HOME}. '.'. $self->_default_filename) { #check home directory
115 0           return $ENV{HOME}. '.'. $self->_default_filename;
116             }
117 0           return; # if no matching files were found
118             }
119              
120             1;
121              
122             __END__
123              
124             =pod
125              
126             =head1 NAME
127              
128             Config::Cmd - Command line to config file two way interface
129              
130             =head1 VERSION
131              
132             version 0.002
133              
134             =head1 SYNOPSIS
135              
136             # user writes options in a file;
137             configcmd parallel -j 8 --verbose
138             # stored in ./parallel_conf.yaml
139              
140             # same functionality when using the module directly
141             use Config::Cmd;
142             my $conf = Config::Cmd(section => 'parallel');
143             $conf->set('-j 8 --verbose');
144              
145             # main application uses the options
146             use Config::Cmd;
147             my $conf = Config::Cmd(section => 'parallel');
148             my $parallel_opts = $conf->get; # read from ./parallel_conf.yaml
149             # call external program
150             `$exe $parallel_opts @args`;
151              
152             =head1 DESCRIPTION
153              
154             This module makes it easy to take a set of command line options, store
155             them into a config file, and read them later in for passing to an
156             external program. Part of this distribution is a command line program
157             L<configcmd> for writing these options into a file. The main
158             application can then use this module to automate reading of these
159             options and passing them on.
160              
161             The options stored by Command::Cmd and its command line tool use
162             single quotes around options with white space, but that can be changed
163             to double quotes if needed by using method L<quote>. Usually you will
164             want stick with single quotes.
165              
166             =head2 Finding the configuration files
167              
168             The command line program writes into the working directory. The
169             default filename is the section name appended with string
170             '_conf.yaml'. This file can be moved and renamed.
171              
172             The method L<filename> can be used to set the path where the file is
173             found. This overrides all other potential places. If the filename has
174             not been set, the module uses the section name to find the
175             configuration file from the working directory (./[section]_conf.yaml).
176             If that file is not found, it looks into user's home directory for a
177             file ~/.[section]_conf.yaml.
178              
179             =head1 METHODS
180              
181             =head2 section
182              
183             The obligatory section name for the stored configuration. This string,
184             typically a program name, defines the name of the config file.
185              
186             =head2 filename
187              
188             Override method that allows user to determine the filename where a
189             config is to be written or read.
190              
191             =head2 set
192              
193             Store the command line into a file as YAML. Returns true value on
194             success.
195              
196             =head2 set_silent
197              
198             Same as set() but does not report to STDERR.
199              
200             =head2 get
201              
202             Get the command line options stored in the file as a string.
203              
204             =head2 quote
205              
206             The quote character to put around a string with white spaces by method
207             L<get>. Defaults to single quote to make it possible to use double
208             quotes for the whole string. Can be set to any string but you would
209             foolish to set to anything else than single or double quote character.
210              
211             =head1 SEE ALSO
212              
213             L<configcmd>, L<Config::Auto>
214              
215             =head1 AUTHOR
216              
217             Heikki Lehvaslaiho <heikki.lehvaslaiho@gmail.com>
218              
219             =head1 COPYRIGHT AND LICENSE
220              
221             This software is copyright (c) 2012 by Heikki Lehvaslaiho.
222              
223             This is free software; you can redistribute it and/or modify it under
224             the same terms as the Perl 5 programming language system itself.
225              
226             =cut