Dotenv
view release on metacpan or search on metacpan
lib/Dotenv.pm view on Meta::CPAN
package Dotenv;
$Dotenv::VERSION = '0.002';
use strict;
use warnings;
use Carp ();
use Path::Tiny ();
sub import {
my ( $package, @args ) = @_;
if (@args) {
my $action = shift @args;
if ( $action eq '-load' ) {
$package->load(@args);
}
else {
Carp::croak "Unknown action $action";
}
}
}
my $parse = sub {
my ( $string, $env ) = @_;
$string =~ s/\A\x{feff}//; # drop BOM
my %kv;
for my $line ( split /$/m, $string ) {
chomp($line);
next if $line =~ /\A\s*(?:[#:]|\z)/; # skip blanks and comments
if (
my ( $k, $v ) =
$line =~ m{
\A # beginning of line
\s* # leading whitespace
(?:export\s+)? # optional export
([a-zA-Z_][a-zA-Z0-9_]+) # key
(?:\s*=\s*) # separator
( # optional value begin
'[^']*(?:\\'|[^']*)*' # single quoted value
| # or
"[^"]*(?:\\"|[^"]*)*" # double quoted value
| # or
[^\#\r\n]+ # unquoted value
)? # value end
\s* # trailing whitespace
(?:\#.*)? # optional comment
\z # end of line
}x
)
{
$v //= '';
$v =~ s/\s*\z//;
# single and double quotes semantics
if ( $v =~ s/\A(['"])(.*)\1\z/$2/ && $1 eq '"' ) {
$v =~ s/\\n/\n/g;
$v =~ s/\\//g;
}
$kv{$k} = $v;
}
else {
Carp::croak "Can't parse env line: $line";
}
}
return %kv;
};
sub parse {
my ( $package, @sources ) = @_;
@sources = ('.env') if !@sources;
my %env;
for my $source (@sources) {
Carp::croak "Can't handle an unitialized value"
if !defined $source;
my %kv;
my $ref = ref $source;
if ( $ref eq '' ) {
%kv = $parse->( Path::Tiny->new($source)->slurp_utf8, \%env );
}
elsif ( $ref eq 'HASH' ) { # bare hash ref
%kv = %$source;
}
( run in 3.345 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )