diff options
-rw-r--r-- | META6.json | 4 | ||||
-rw-r--r-- | lib/Config.pm6 | 98 | ||||
-rw-r--r-- | t/having.t | 4 | ||||
-rw-r--r-- | t/reading.t | 27 | ||||
-rw-r--r-- | t/setting.t | 4 |
5 files changed, 111 insertions, 26 deletions
@@ -1,12 +1,12 @@ { "perl": "6", "name": "Config", - "version": "1.0.0", + "version": "1.1.0", "auth": "github:scriptkitties", "description": "Extensible library for reading and writing configuration files.", "license": "GPL-3.0", "depends": [ - + "Hash::Merge" ], "provides": { "Config": "lib/Config.pm6", diff --git a/lib/Config.pm6 b/lib/Config.pm6 index 2fa01bf..40bfa27 100644 --- a/lib/Config.pm6 +++ b/lib/Config.pm6 @@ -2,6 +2,8 @@ use v6.c; +use Hash::Merge; + use Config::Exception::MissingParserException; use Config::Exception::UnknownTypeException; use Config::Exception::FileNotFoundException; @@ -10,28 +12,38 @@ use Config::Parser; class Config is export { - has $!content = {}; - has $!path; - has $!parser; + has Hash $!content = {}; + has Str $!path = ""; + has Str $!parser = ""; - multi method get(Str $key, Any $default = Nil) + #| Clear the config. + method clear() { - my $index = $!content; - - for $key.split(".") -> $part { - return $default unless defined($index{$part}); + $!content = {}; + $!path = ""; + $!parser = ""; + } - $index = $index{$part}; - } + #| Return the entire config hash. + multi method get() + { + return $!content; + } - $index; + #| Get a value from the config object. To get a nested + #| key, use a . to descent a level. + multi method get(Str $key, Any $default = Nil) + { + self.get($key.split(".").list, $default); } - multi method get(@keyparts, Any $default = Nil) + #| Get a value from the config object using a list + #| to indicate the nested key to get. + multi method get(List $keyparts, Any $default = Nil) { my $index = $!content; - for @keyparts -> $part { + for $keyparts.list -> $part { return $default unless defined($index{$part}); $index = $index{$part}; @@ -40,6 +52,8 @@ class Config is export $index; } + #| Get the name of the parser module to use for the + #| given path. method get-parser(Str $path, Str $parser = "") { if ($parser ne "") { @@ -49,12 +63,13 @@ class Config is export my $type = self.get-parser-type($path); Config::Exception::UnknownTypeException.new( - type => $type + file => $path ).throw() if $type eq Config::Type::unknown; "Config::Parser::" ~ $type; } + #| Get the type of parser required for the given path. method get-parser-type(Str $path) { given ($path) { @@ -74,23 +89,40 @@ class Config is export return Config::Type::unknown; } - method has(Str $key) { + #| Check wether a given key exists. + multi method has(Str $key) { + self.has($key.split(".").list); + } + + #| Check wether a given key exists using a list to supply + #| the nested key to check. + multi method has(List $keyparts) + { my $index = $!content; - for $key.split(".") -> $part { + for $keyparts.list -> $part { return False unless defined($index{$part}); $index = $index{$part}; } - True; + defined($index); } + #| Reload the configuration. Requires the configuration to + #| have been loaded from a file. multi method read() { + if ($!path eq "") { + return False; + } + return self.load($!path); } + #| Load a configuration file from the given path. Optionally + #| set a parser module name to use. If not set, Config will + #| attempt to deduce the parser to use. multi method read(Str $path, Str $parser = "") { Config::Exception::FileNotFoundException.new( @@ -109,22 +141,43 @@ class Config is export } require ::($!parser); - $!content = ::($!parser).read($path); + + self.read(::($!parser).read($path)); } return True; } + #| Read a list of paths. Will fail on the first file that + #| fails to load for whatever reason. + multi method read(List $paths, Str $parser = "") + { + for $paths.list -> $path { + self.read($path, $parser); + } + + return True; + } + + #| Read a plain Hash into the configuration. multi method read(Hash $hash) { - $!content = $hash; + $!content.merge($hash); + + return True; + } + + #| Set a single key to a given value; + multi method set(Str $key, Any $value) + { + self.set($key.split(".").list, $value); } - method set(Str $key, Any $value) + multi method set(List $keyparts, Any $value) { my $index := $!content; - for $key.split(".") -> $part { + for $keyparts.list -> $part { $index{$part} = {} unless defined($index{$part}); $index := $index{$part}; @@ -135,6 +188,9 @@ class Config is export self; } + #| Write the current configuration to the given path. If + #| no parser is given, it tries to use the parser that + #| was used when loading the configuration. method write(Str $path, Str $parser = "") { $parser = self.get-parser($path, $parser); @@ -4,7 +4,7 @@ use v6.c; use Test; use lib "lib"; -plan 2; +plan 4; use Config; @@ -19,3 +19,5 @@ $config.read({ ok $config.has("a"), "Check existence of simple key"; ok $config.has("b.c"), "Check existence of nested key"; +ok $config.has(["a"]), "Check existence of simple key using array"; +ok $config.has(["b", "c"]), "Check existence of nested key using array"; diff --git a/t/reading.t b/t/reading.t index 52859af..e43252a 100644 --- a/t/reading.t +++ b/t/reading.t @@ -4,7 +4,7 @@ use v6.c; use Test; use lib "lib"; -plan 3; +plan 5; use Config; @@ -13,3 +13,28 @@ my $config = Config.new(); throws-like { $config.read("nonexistant-config") }, Config::Exception::FileNotFoundException, "Reading nonexisting file"; throws-like { $config.read("t/test-stub") }, Config::Exception::UnknownTypeException, "Reading file of unknown type"; throws-like { $config.read("t/test-stub", "Config::Parser:NoSuchParserForTest") }, Config::Exception::MissingParserException, "Using non-existing parser"; + +my $hash = { + "a" => "a", + "b" => { + "c" => "test" + } +}; + +$config.read($hash); + +is-deeply $config.get(), $hash, "Correctly sets hash"; + +$config.read({ + "b" => { + "d" => "another" + } +}); + +is-deeply $config.get(), { + "a" => "a", + "b" => { + "c" => "test", + "d" => "another" + } +}, "Correctly merges new hash into existing config"; diff --git a/t/setting.t b/t/setting.t index d9f0854..7e3a457 100644 --- a/t/setting.t +++ b/t/setting.t @@ -4,7 +4,7 @@ use v6.c; use Test; use lib "lib"; -plan 2; +plan 4; use Config; @@ -12,3 +12,5 @@ my $config = Config.new(); ok $config.set("a", "test").get("a") eq "test", "Setting simple key"; ok $config.set("b.c", "test").get("b.c") eq "test", "Setting nested key"; +ok $config.set(["d"], "test").get("d") eq "test", "Setting simple key using array"; +ok $config.set(["e", "f"], "test").get("e.f") eq "test", "Setting nested key using array"; |