Config-Interactive

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN


	
0.04    6/16/2008
        Fixed list of-prereqs

0.03    6/6/2008 
        Cleaned whitespace noise in the pods
        Cleaned whitespace noise in the pods

0.02    3/6/2008 
        Fixed bug with storing only part of interpolated XML fragment
	Added 'use fields' and made constructor safer	
	
0.01    2/19/2008 
        First version, released on an unsuspecting world.

README  view on Meta::CPAN


VERSION

 0.04
 
 
DECRIPTION

Provides a convenient way for loading   config values from a given file and
returns it as a hash structure, allows interpolation for the   perl scalars ( $xxxx ${xxx} )
and inside of XML fragments as well.
Also, it can run interactive session with user, use predefined prompts, use validation patterns
and store back into the file, preserving the original order of the comments and definitions.
Motivation behind this module was inspired by Config::General module which was missing required
functionality ( preservation of the comments order and positioining, prompts and validation for 
command line based UI ). This module is extremely useful as CLI frontend to your application.
  


INSTALLATION

lib/Config/Interactive.pm  view on Meta::CPAN

package Config::Interactive;
use strict;
use warnings;
use 5.006_001;

=head1 NAME

Config::Interactive -  config module with support for interpolation, XML fragments and interactive UI

=head1 VERSION

Version 0.04

=cut

our $VERSION = '0.04';

=head1 DESCRIPTION

This module opens a config file and parses it's contents for you. The  I<new()> method
accepts several parameters. The method  'parse'  returns a hash reference
which contains all options and it's associated values of your config file as well as comments above.
If the dialog mode is set then at the moment of parsing user will be prompted to enter different value and
if validation pattern for this particular key was defined then it will be validated and user could be asked to
enter different value if it failed.
The format of config files supported by L<Config::Interactive> is   
C<< <name>=<value> >> pairs or XML fragments (by L<XML::Simple>,  namespaces are not supported) and comments are any line which starts with #.
Comments inside of XML fragments will pop-up on top of the related fragment. It will interpolate any perl variable 
which looks as C< ${?[A-Za-z]\w+}? >.
Please not that interpolation works for XML fragments as well, BUT interpolated varialbles MUST be defined
by C<key=value> definition and NOT inside of other XML fragment!
The order of appearance of such variables in the config file is not important, means you can use C<$bar> variable anywhere in the config file but
set it to something on the last line (or even skip setting it at all , then it will be undef).
It stores internally config file contents as hash ref where data structure is:
Please note that array ref is used to store XML text elements and scalar for attributes.

   
   ( 'key1' => {'comment' => "#some comment\n#more comments\n", 
                'value' => 'Value1',
                'order' => '1',
              },

lib/Config/Interactive.pm  view on Meta::CPAN

            if ( !$xml_start && m/^\<\s*([\w\-]+)\b?[^\>]*\>/xsm ) {
                $xml_start = $1;
                $xml_config .= $_;
            }
            # elsif  inside of XML
            elsif ($xml_start) {
                if (m/^\<\/\s*($xml_start)\s*\>/xsm) {
                    $xml_config .= $_;
                    my $xml_cf =  XMLin( $xml_config, KeyAttr => {}, ForceArray => 1 );
                    $config{$xml_start}{value} = $self->_parseXML($xml_cf);
                    carp " Parsed XML fragment: "  . Dumper $config{$xml_start}{value}  if $self->{debug};
                    if ($comment) {
                        $config{$xml_start}{comment} = $comment;
                        $comment = '';
                    }
                    $config{$xml_start}{order} = $order++;
                    $xml_start = undef;
                }
                else {
                    $xml_config .= $_;
                }

lib/Config/Interactive.pm  view on Meta::CPAN

    print(" interpolating...\n") if $self->{debug};

    #  interpolate all values

    $self->{data} = $self->_interpolate( \%config );
    print( " Config data: \n" . Dumper $self->{data} ) if $self->{debug};
    return $self->{data};
}

#
#  interpolate all values, in case of XML fragments the name of the interpolated variable
#  MUST be set by key=value definition and not by the element from other XML block
#
#
sub _interpolate {
    my ( $self, $config, $scalars, $xml_root ) = @_;
    my @keys = $xml_root ? keys %{ $config->{value} } : keys %{$config};

    #  interpolate all values
    foreach my $key (@keys) {
        ### go for recursion in case of XML fragment
        if ( !$xml_root ) {
            $self->_interpolate( $config->{$key}, $config, $key )
              if ref( $config->{$key}{value} ) eq 'HASH';
            ### interpolate if its simple key=value definition
            my @sub_keys =
              $config->{$key}{value} =~ /[^\\]?\$\{?([a-zA-Z]+(?:\w+)?)\}?/xsmg;
            foreach my $sub_key (@sub_keys) {
                print(
                    " CHECK  " . $config->{$key}{value} . " -> $sub_key  \n" )
                  if $self->{debug};

t/Config-Interactive.t  view on Meta::CPAN

 # 6
   
  ok($hashref3->{METADATA_DB_FILE} eq '/home/user/somefilel', "  Check for scalar interpolation failed ");  

# 7
   
  ok($hashref3->{SQL_DB_PATH} eq '/home/user', "  Check for XML   interpolation failed " );  

# 8
   
  ok($hashref3->{SQL_production} == 1, "  Check for XML fragment attribute failed ");  

# 9
   
  ok($hashref3->{SQL_DB_DRIVER} eq 'mysql', "  Check for XML fragment  element failed ");  

# 10
  eval {  
    $conf->store("/tmp/test_$$.conf")   
  };
  ok( !$@  && -e "/tmp/test_$$.conf", "Config::Interactive store file ". $@);  
  $@ = undef;
  # 11
  eval {    
   $conf = new Config::Interactive({file => $cfg,   dialog => undef,  validkeys => \%CONF_VALID, prompts => \%CONF_KEYS}); 



( run in 1.437 second using v1.01-cache-2.11-cpan-364913b4093 )