mirror of
https://github.com/mbierlee/mirage-config.git
synced 2024-11-15 04:44:01 +01:00
Add support for multiline values
This commit is contained in:
parent
b0895cc13f
commit
86a2fa0f9f
4
TODO.md
4
TODO.md
|
@ -6,13 +6,13 @@
|
|||
- Config manip
|
||||
- Env and config var substitution
|
||||
- Escaping
|
||||
- Generic
|
||||
- Base64 decoding of values
|
||||
- Java properties
|
||||
- Add unicode escaping
|
||||
- Support multi-line values with backslash
|
||||
- Add escaping of key/value separator = and :
|
||||
- INI config
|
||||
- Case insensitive properties and sections
|
||||
- Escape characters
|
||||
- Support multi-line values with backslash
|
||||
- TOML
|
||||
- Add support for the standard (https://github.com/toml-lang/toml)
|
|
@ -14,7 +14,7 @@ module mirage.ini;
|
|||
import mirage.config : ConfigDictionary;
|
||||
import mirage.keyvalue : KeyValueConfigFactory, SupportHashtagComments, SupportSemicolonComments,
|
||||
SupportExclamationComments, SupportSections, NormalizeQuotedValues, SupportEqualsSeparator,
|
||||
SupportColonSeparator, SupportKeysWithoutValues;
|
||||
SupportColonSeparator, SupportKeysWithoutValues, SupportMultilineValues;
|
||||
|
||||
/**
|
||||
* Creates configuration dictionaries from INI files.
|
||||
|
@ -30,7 +30,8 @@ class IniConfigFactory : KeyValueConfigFactory!(
|
|||
NormalizeQuotedValues.yes,
|
||||
SupportEqualsSeparator.yes,
|
||||
SupportColonSeparator.yes,
|
||||
SupportKeysWithoutValues.no
|
||||
SupportKeysWithoutValues.no,
|
||||
SupportMultilineValues.yes
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ module mirage.java;
|
|||
import mirage.config : ConfigDictionary;
|
||||
import mirage.keyvalue : KeyValueConfigFactory, SupportHashtagComments, SupportSemicolonComments,
|
||||
SupportExclamationComments, SupportSections, NormalizeQuotedValues, SupportEqualsSeparator,
|
||||
SupportColonSeparator, SupportKeysWithoutValues;
|
||||
SupportColonSeparator, SupportKeysWithoutValues, SupportMultilineValues;
|
||||
|
||||
/**
|
||||
* Creates configuration dictionaries from Java properties.
|
||||
|
@ -31,7 +31,8 @@ class JavaPropertiesFactory : KeyValueConfigFactory!(
|
|||
NormalizeQuotedValues.no,
|
||||
SupportEqualsSeparator.yes,
|
||||
SupportColonSeparator.yes,
|
||||
SupportKeysWithoutValues.yes
|
||||
SupportKeysWithoutValues.yes,
|
||||
SupportMultilineValues.yes
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ alias NormalizeQuotedValues = Flag!"NormalizeQuotedValues";
|
|||
alias SupportEqualsSeparator = Flag!"SupportEqualsSeparator";
|
||||
alias SupportColonSeparator = Flag!"SupportColonSeparator";
|
||||
alias SupportKeysWithoutValues = Flag!"SupportKeysWithoutValues";
|
||||
alias SupportMultilineValues = Flag!"SupportMultilineValues";
|
||||
|
||||
/**
|
||||
* A generic reusable key/value config factory that can be configured to parse
|
||||
|
@ -40,7 +41,8 @@ class KeyValueConfigFactory(
|
|||
NormalizeQuotedValues normalizeQuotedValues = NormalizeQuotedValues.no,
|
||||
SupportEqualsSeparator supportEqualsSeparator = SupportEqualsSeparator.no,
|
||||
SupportColonSeparator supportColonSeparator = SupportColonSeparator.no,
|
||||
SupportKeysWithoutValues supportKeysWithoutValues = SupportKeysWithoutValues.no
|
||||
SupportKeysWithoutValues supportKeysWithoutValues = SupportKeysWithoutValues.no,
|
||||
SupportMultilineValues supportMultilineValues = SupportMultilineValues.no
|
||||
) : ConfigFactory {
|
||||
|
||||
/**
|
||||
|
@ -57,6 +59,9 @@ class KeyValueConfigFactory(
|
|||
auto lines = contents.lineSplitter().array;
|
||||
auto properties = new ConfigDictionary();
|
||||
auto section = "";
|
||||
string key = null;
|
||||
string valueBuffer = "";
|
||||
|
||||
foreach (size_t index, string line; lines) {
|
||||
auto processedLine = line;
|
||||
|
||||
|
@ -75,7 +80,9 @@ class KeyValueConfigFactory(
|
|||
|
||||
processedLine = processedLine.strip;
|
||||
|
||||
if (supportSections && processedLine.startsWith('[') && processedLine.endsWith(']')) {
|
||||
if (supportSections &&
|
||||
key is null &&
|
||||
processedLine.startsWith('[') && processedLine.endsWith(']')) {
|
||||
auto parsedSection = processedLine[1 .. $ - 1];
|
||||
if (parsedSection.startsWith('.')) {
|
||||
section ~= parsedSection;
|
||||
|
@ -90,6 +97,9 @@ class KeyValueConfigFactory(
|
|||
continue;
|
||||
}
|
||||
|
||||
string value;
|
||||
|
||||
if (key is null) {
|
||||
char keyValueSplitter;
|
||||
if (supportEqualsSeparator && processedLine.indexOf('=') >= 0) {
|
||||
keyValueSplitter = '=';
|
||||
|
@ -104,17 +114,28 @@ class KeyValueConfigFactory(
|
|||
enforce!ConfigCreationException(supportKeysWithoutValues || parts.length == 2, "Missing value assignment (L" ~ index
|
||||
.to!string ~ "): " ~ processedLine);
|
||||
|
||||
auto value = supportKeysWithoutValues && parts.length == 1 ? "" : parts[1].strip;
|
||||
|
||||
if (normalizeQuotedValues &&
|
||||
value.length > 1 &&
|
||||
(value.startsWith('"') || value.startsWith('\'')) &&
|
||||
(value.endsWith('"') || value.endsWith('\''))) {
|
||||
value = value[1 .. $ - 1];
|
||||
key = [section, parts[0].strip].join('.');
|
||||
value = supportKeysWithoutValues && parts.length == 1 ? "" : parts[1].strip;
|
||||
} else {
|
||||
value = processedLine;
|
||||
}
|
||||
|
||||
auto key = [section, parts[0].strip].join('.');
|
||||
properties.set(key, value);
|
||||
if (supportMultilineValues && value.endsWith('\\')) {
|
||||
valueBuffer ~= value[0 .. $ - 1];
|
||||
continue;
|
||||
}
|
||||
|
||||
auto fullValue = valueBuffer ~ value;
|
||||
if (normalizeQuotedValues &&
|
||||
fullValue.length > 1 &&
|
||||
(fullValue.startsWith('"') || fullValue.startsWith('\'')) &&
|
||||
(fullValue.endsWith('"') || fullValue.endsWith('\''))) {
|
||||
fullValue = fullValue[1 .. $ - 1];
|
||||
}
|
||||
|
||||
properties.set(key, fullValue);
|
||||
key = null;
|
||||
valueBuffer = "";
|
||||
}
|
||||
|
||||
return properties;
|
||||
|
@ -133,7 +154,8 @@ version (unittest) {
|
|||
NormalizeQuotedValues.no,
|
||||
SupportEqualsSeparator.yes,
|
||||
SupportColonSeparator.no,
|
||||
SupportKeysWithoutValues.no
|
||||
SupportKeysWithoutValues.no,
|
||||
SupportMultilineValues.no
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -325,4 +347,55 @@ version (unittest) {
|
|||
assertThrown!ConfigCreationException(new KeyValueConfigFactory!()().parseConfig("a=b")); // No separator is configured
|
||||
}
|
||||
|
||||
@("Support multiline values")
|
||||
unittest {
|
||||
auto config = new KeyValueConfigFactory!(
|
||||
SupportHashtagComments.yes,
|
||||
SupportSemicolonComments.no,
|
||||
SupportExclamationComments.no,
|
||||
SupportSections.yes,
|
||||
NormalizeQuotedValues.yes,
|
||||
SupportEqualsSeparator.yes,
|
||||
SupportColonSeparator.no,
|
||||
SupportKeysWithoutValues.yes,
|
||||
SupportMultilineValues.yes
|
||||
)().parseConfig("
|
||||
sentence = the quick \\
|
||||
'brown fox' \\ # comments
|
||||
[jump]\\
|
||||
\\
|
||||
ed over \\ #are not part of the
|
||||
the lazy \\
|
||||
'[dog]' #value
|
||||
|
||||
not part of the sentence
|
||||
");
|
||||
|
||||
assert(config.get("sentence") == "the quick 'brown fox' [jump]ed over the lazy '[dog]'");
|
||||
}
|
||||
|
||||
@("Normalize multiline values with quotes")
|
||||
unittest {
|
||||
auto config = new KeyValueConfigFactory!(
|
||||
SupportHashtagComments.no,
|
||||
SupportSemicolonComments.no,
|
||||
SupportExclamationComments.no,
|
||||
SupportSections.no,
|
||||
NormalizeQuotedValues.yes,
|
||||
SupportEqualsSeparator.yes,
|
||||
SupportColonSeparator.no,
|
||||
SupportKeysWithoutValues.no,
|
||||
SupportMultilineValues.yes
|
||||
)().parseConfig("
|
||||
doubles = \"Well then there I was \\
|
||||
doing my thing.\"
|
||||
singles = 'When suddenly \\
|
||||
a shark bit me \\
|
||||
from the sky'
|
||||
");
|
||||
|
||||
assert(config.get("doubles") == "Well then there I was doing my thing.");
|
||||
assert(config.get("singles") == "When suddenly a shark bit me from the sky");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue