The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Template::ExpandHash - Do template expansion on the values of a hash.

VERSION

Version 0.01

SYNOPSIS

    use Template::ExpandHash qw(expand_hash);
    # ... time passes
    %expanded_hash    = expand_hash(%hash);
    $expanded_hashref = expand_hash($hashref);

Pass a hash, get back a similar hash with [% key %] expanded into the value associated with that key. Recursive substitutions are supported, and the substituting goes into sub-hashes. (Sub-hashes can expand to keys from the surrounding hash, but not vice versa.) Template expressions can be escaped using backslashes.

INTENDED USE CASE

When loading a configuration it often makes sense to start with a base configuration data structure, and then load multiple layers of tweaks for specific environments. This can happen within pure Perl as in this example:

    $PARAM{prod} = {
        email_qa_email      => undef,
        email_pager_email   => 'pagerlist@company.com',
        some_escaped_value  => '\[% user ]%',
        # etc
        email => {
          qa_email          => '[% email_qa_email %]',
          pager_email       => '[% email_pager_email %]',
          # etc
        },
        # More data here.
    };

    $PARAM{sandbox} = {
        %{$PARAM{prod}},
        default_email       => '[% user %]@company.com',
        email_qa_email      => 'QA <[% default_email %]>',
        email_pager_email   => 'Pagers <[% default_email %]>',
        # More data here, some of which overrides prod.
    };

    $PARAM{btilly} = {
        %{$PARAM{sandbox}},
        user                => 'btilly',
        # More data here, some of which overrides the sandbox.
    };

Alternately it can happen in a series of files which you might load from a list of external sources with code like this:

    use Config::Any;

    # ... code here.
    my $raw_config_list
        = Config::Any->load_files({files => \@config_path, use_ext => 1});
    my $config = {map %$_, map values %$_, @$raw_config_list};

Either way there is a tendency for the set of overrides at the detail level to get very long. However with templating we could make this much shorter. Suppose that our final set of parameters worked out to be something like:

    $config =  {
        user                => 'btilly',
        default_email       => '[% user %]@company.com',
        email_qa_email      => 'QA <[% default_email %]>',
        email_pager_email   => 'Pagers <[% default_email %]>',
        some_escaped_value  => '\[% user ]%',
        # etc
        email => {
          qa_email          => '[% email_qa_email %]',
          pager_email       => '[% email_pager_email %]',
          # etc
        },
        # More data here.
    }

Then we can expand all of the template parameters:

    $expanded_param = expand_hash($param);

And get:

    {
        user               => 'btilly',
        default_email      => 'btilly@company.com',
        email_qa_email     => 'QA <btilly@company.com>',
        email_pager_email  => 'Pagers <btilly@company.com>',
        some_escaped_value => '[% user ]%',
        # etc
        email => {
            qa_email       => 'QA <btilly@company.com>',
            pager_email    => 'Pagers <btilly@company.com>',
            # etc
        },
        # More data here.
    }

without having to manually override a long list of values. This makes your configuration much simpler and cleaner than it otherwise would be.

SUBROUTINES/METHODS

expand_hash

The only externally usable function. You pass it a hash or hash ref and it will recursively expand template parameters and return you a hash or hash ref.

AUTHOR

Ben Tilly, <btilly at gmail.com>

TODO

Error checking

No checks currently exist for malformed templates, or template references to variables that are not available. These would catch common typos and should be added.

Performance

Currently it keeps on passing through the list of not yet done variables until no further progress is made. Calculating a dependency graph up front could significantly help performance.

Refactor

All of the real work is done in one giant recursive function. It could be broken up into more digestable pieces.

Conditionals and loops

Common template features do not work. Perhaps they would be useful.

Recursive macro expansion

[% foo[% bar %] %] does not currently work. It may be simple to add.

BUGS

Please report any bugs or feature requests to bug-template-expandhash at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Template-ExpandHash. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Template::ExpandHash

Or email the author at <btilly at gmail.com>.

The project home is https://github.com/btilly/Template-ExpandHash.

ACKNOWLEDGEMENTS

This module was produced under contract to ZipRecruiter.com. They are a good group of people, and I thank them for allowing this to be open sourced.

All mistakes are, of course, mine.

LICENSE AND COPYRIGHT

Copyright 2012 Ben Tilly.

Sponsored by ZipRecruiter.com.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.