mirage-config/source/mirage/ini.d

132 lines
3.8 KiB
D
Raw Normal View History

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!");
}
}