1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
#!/usr/bin/env perl
use strict;
use warnings;
use 5.010;
use YAML::PP;
use Data::Dumper;
my $ypp = YAML::PP->new( schema => ['Failsafe'] );
my ($filename) = @ARGV;
my $external_data = {
env => \%ENV,
argv => \@ARGV,
config => { prefix => '/usr/local' },
};
my $schema = $ypp->schema;
$schema->add_resolver(
tag => "!external",
match => [ all => => sub {
my ($constructor, $event) = @_;
my $value = $event->{value};
path($external_data, $value)
}],
implicit => 0,
);
$schema->add_resolver(
tag => "!template",
match => [ all => sub {
my ($constructor, $event) = @_;
my $value = $event->{value};
template($external_data, $value)
}],
implicit => 0,
);
my $data = $ypp->load_file($filename);
say $ypp->dump_string($data);
# utility functions
# turn /env/FOO into $data->{env}->{FOO}
sub path {
my ($data, $path) = @_;
my @paths = split qr{/}, $path;
my $replaced = $data;
for my $p (@paths) {
next unless length $p;
if (ref $replaced eq 'ARRAY') {
if ($p !~ tr/0-9//c and $p < @$replaced) {
$replaced = $replaced->[ $p ];
}
else {
return;
}
}
elsif (ref $replaced eq 'HASH') {
$replaced = $replaced->{ $p };
}
last unless defined $replaced;
}
return $replaced;
}
# replace ${/some/path} in string with path(...)
sub template {
my ($data, $string) = @_;
$string =~ s<\$\{([\w/]+)\}>
<path($data, $1)>eg;
return $string;
}
|