The_Marshall has asked for the wisdom of the Perl Monks concerning the following question:

Hey all,

In a nutshell, I'm trying to accomplish the following:

# config.ini include default.ini user_name = "Marshall" # Change value within default.ini list_of_items = ["apple", "ball", "cup"]

However, what I wind up with are 2 scalars:

{ 'user_name' => 'Marshall', 'list_of_items' => '["apple", "ball", "cup"]' }

I've tried so many different settings. The above generated with:

ParseConfig( -ConfigFile => 'simple.ini', -UseApacheInclude => 1, -MergeDuplicateOptions => 1 );

So, I need some advice. I've even tried to use blocks to hold arrays, but nothing seems to work.

Config::General::Version = '2.63'

Replies are listed 'Best First'.
Re: Config::General to read both scalars and arrays
by choroba (Cardinal) on May 22, 2019 at 16:06 UTC
    From the documentation it seems arrays are defined by repeating the key:
    list_of_items = apple list_of_items = ball list_of_items = cup

    The square brackets can be used for single-element arrays only under ForceArray.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

      Hey choroba,

      Thank you for the quick response.

      Yes, identical options generate an array. But, I'm explicitly needing the ability to:

      • Overwrite previous values
        user_name = "Marshall"# Change value within default.ini
      • Create an array of values
        list_of_items = ["apple", "ball", "cup"]

      The documentation is light on arrays. There's a few settings that seem to apply but, I can't get them to work as advertised. Well, at least how I understand it to be advertised.

      Mainly I've been playing around with MergeDuplicateOptions and MergeDuplicateBlocks.

Re: Config::General to read both scalars and arrays
by holli (Abbot) on May 22, 2019 at 18:22 UTC
    use PPR; use Modern::Perl; use Data::Dumper; use Config::General; use Sub::Signatures; my $conf = Config::General->new( -ConfigFile => "pm5.ini", -Plug => { post_parse_value => sub ($name, $value) { $value = split_array_str( $value ) if looks_like_array( $value ) ; return 1, $name, $value; } } ); #naive implementation, excercise for the reader to improve #PPR might be useful to parse this, assuming Perl syntax for the #array sub split_array_str ($value) { return [split ",", substr($value, 1, -1)]; } #naive implementation, excercise for the reader to improve sub looks_like_array ($value) { return $value =~ m#^\[# && $value =~ m#\]$#; } my %conf = $conf->getall; print Dumper( \%conf );


    holli

    You can lead your users to water, but alas, you cannot drown them.
      I didn't know we have state variables now. I've been away reeeally long =)
      use Text::CSV; use feature 'state'; sub split_array_str ($value) { state $csv = Text::CSV->new ({ sep_char => ",", quote_char => '"', + allow_whitespace => 1 }); return $csv->parse( substr($value,1,-1) ) ? [$csv->fields] : $value; }


      holli

      You can lead your users to water, but alas, you cannot drown them.