2022-10-13 00:56:27 +02:00
|
|
|
/**
|
|
|
|
* Utilities for loading INI files.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Mike Bierlee, m.bierlee@lostmoment.com
|
|
|
|
* Copyright: 2022 Mike Bierlee
|
|
|
|
* License:
|
|
|
|
* This software is licensed under the terms of the MIT license.
|
|
|
|
* The full terms of the license can be found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
module mirage.ini;
|
|
|
|
|
|
|
|
import mirage.config : ConfigDictionary;
|
|
|
|
import mirage.keyvalue : KeyValueConfigFactory, SupportHashtagComments, SupportSemicolonComments,
|
|
|
|
SupportExclamationComments, SupportSections, NormalizeQuotedValues, SupportEqualsSeparator,
|
2022-10-13 20:14:25 +02:00
|
|
|
SupportColonSeparator, SupportKeysWithoutValues, SupportMultilineValues;
|
2022-10-13 00:56:27 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates configuration dictionaries from INI files.
|
|
|
|
*
|
|
|
|
* Format specifications:
|
|
|
|
* https://en.wikipedia.org/wiki/INI_file#Format
|
|
|
|
*/
|
|
|
|
class IniConfigFactory : KeyValueConfigFactory!(
|
|
|
|
SupportHashtagComments.yes,
|
|
|
|
SupportSemicolonComments.yes,
|
|
|
|
SupportExclamationComments.no,
|
|
|
|
SupportSections.yes,
|
|
|
|
NormalizeQuotedValues.yes,
|
|
|
|
SupportEqualsSeparator.yes,
|
|
|
|
SupportColonSeparator.yes,
|
2022-10-13 20:14:25 +02:00
|
|
|
SupportKeysWithoutValues.no,
|
|
|
|
SupportMultilineValues.yes
|
2022-10-13 00:56:27 +02:00
|
|
|
) {
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Parse configuration from the given INI config string.
|
|
|
|
|
|
|
|
* Params:
|
|
|
|
* contents = Text contents of the config to be parsed.
|
|
|
|
* Returns: The parsed configuration.
|
|
|
|
*/
|
|
|
|
ConfigDictionary parseIniConfig(const string contents) {
|
|
|
|
return new IniConfigFactory().parseConfig(contents);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Load a INI configuration file from disk.
|
|
|
|
*
|
|
|
|
* Params:
|
|
|
|
* filePath = Path to the INI configuration file.
|
|
|
|
* Returns: The loaded configuration.
|
|
|
|
*/
|
|
|
|
ConfigDictionary loadIniConfig(const string filePath) {
|
|
|
|
return new IniConfigFactory().loadFile(filePath);
|
|
|
|
}
|
|
|
|
|
|
|
|
version (unittest) {
|
|
|
|
import std.process : environment;
|
|
|
|
|
|
|
|
@("Parse INI config")
|
|
|
|
unittest {
|
|
|
|
auto config = parseIniConfig("
|
|
|
|
globalSection = yes
|
2022-10-13 20:31:34 +02:00
|
|
|
multi = 'we are \\
|
|
|
|
multi!'
|
2022-10-13 00:56:27 +02:00
|
|
|
|
|
|
|
[supersection]
|
|
|
|
thefirst = here
|
|
|
|
|
|
|
|
[supersection.sub]
|
|
|
|
sandwich=maybe tasty
|
|
|
|
|
|
|
|
[.way]
|
|
|
|
advertisement? = nah ; For real, not sponsored!
|
|
|
|
|
|
|
|
# Although money would be cool
|
|
|
|
[back]
|
|
|
|
to: basics
|
|
|
|
much = \"very much whitespace\"
|
|
|
|
many = 'very many whitespace'
|
|
|
|
");
|
|
|
|
|
|
|
|
assert(config.get("globalSection") == "yes");
|
2022-10-13 20:31:34 +02:00
|
|
|
assert(config.get("multi") == "we are multi!");
|
2022-10-13 00:56:27 +02:00
|
|
|
assert(config.get("supersection.thefirst") == "here");
|
|
|
|
assert(config.get("supersection.sub.sandwich") == "maybe tasty");
|
|
|
|
assert(config.get("supersection.sub.way.advertisement?") == "nah");
|
|
|
|
assert(config.get("back.much") == "very much whitespace");
|
|
|
|
assert(config.get("back.many") == "very many whitespace");
|
|
|
|
}
|
|
|
|
|
|
|
|
@("Load INI file")
|
|
|
|
unittest {
|
|
|
|
auto config = loadIniConfig("testfiles/fuzzy.ini");
|
|
|
|
|
|
|
|
assert(config.get("globalSection") == "yes");
|
|
|
|
assert(config.get("supersection.thefirst") == "here");
|
|
|
|
assert(config.get("supersection.sub.sandwich") == "maybe tasty");
|
|
|
|
assert(config.get("supersection.sub.way.advertisement?") == "nah");
|
|
|
|
assert(config.get("back.much") == "very much whitespace");
|
|
|
|
assert(config.get("back.many") == "very many whitespace");
|
|
|
|
}
|
|
|
|
|
|
|
|
@("Substitute env vars")
|
|
|
|
unittest {
|
|
|
|
environment["MIRAGE_TEST_INI_VAR"] = "I am ini";
|
|
|
|
auto config = parseIniConfig("
|
|
|
|
[app]
|
|
|
|
startInfo = ${MIRAGE_TEST_INI_VAR}
|
|
|
|
");
|
|
|
|
|
|
|
|
assert(config.get("app.startInfo") == "I am ini");
|
|
|
|
}
|
|
|
|
|
|
|
|
@("Use value from other key")
|
|
|
|
unittest {
|
|
|
|
auto config = parseIniConfig("
|
|
|
|
[app]
|
|
|
|
startInfo = \"Let's get started!\"
|
|
|
|
|
|
|
|
[logger]
|
|
|
|
startInfo = ${app.startInfo}
|
|
|
|
");
|
|
|
|
|
|
|
|
assert(config.get("app.startInfo") == "Let's get started!");
|
|
|
|
assert(config.get("logger.startInfo") == "Let's get started!");
|
|
|
|
}
|
|
|
|
}
|