mirror of https://github.com/oxen-io/lokinet
Support for comments in config definition
This commit is contained in:
parent
1653b73ee5
commit
18ee23c2a3
|
@ -112,6 +112,21 @@ Configuration::acceptAllOptions()
|
|||
});
|
||||
}
|
||||
|
||||
void
|
||||
Configuration::addSectionComment(const std::string& section,
|
||||
std::string comment)
|
||||
{
|
||||
m_sectionComments[section].push_back(std::move(comment));
|
||||
}
|
||||
|
||||
void
|
||||
Configuration::addOptionComment(const std::string& section,
|
||||
const std::string& name,
|
||||
std::string comment)
|
||||
{
|
||||
m_definitionComments[section][name].push_back(std::move(comment));
|
||||
}
|
||||
|
||||
std::string
|
||||
Configuration::generateINIConfig(bool useValues)
|
||||
{
|
||||
|
@ -123,9 +138,25 @@ Configuration::generateINIConfig(bool useValues)
|
|||
if (sectionsVisited > 0)
|
||||
oss << "\n";
|
||||
|
||||
// TODO: this will create empty objects as a side effect of map's operator[]
|
||||
// TODO: this also won't handle sections which have no definition
|
||||
for (const std::string& comment : m_sectionComments[section])
|
||||
{
|
||||
oss << "# " << comment << "\n";
|
||||
}
|
||||
|
||||
oss << "[" << section << "]\n";
|
||||
|
||||
visitDefinitions(section, [&](const std::string& name, const ConfigDefinition_ptr& def) {
|
||||
|
||||
// TODO: as above, this will create empty objects
|
||||
// TODO: as above (but more important): this won't handle definitions with no entries
|
||||
// (i.e. those handled by UndeclaredValueHandler's)
|
||||
for (const std::string& comment : m_definitionComments[section][name])
|
||||
{
|
||||
oss << "# " << comment << "\n";
|
||||
}
|
||||
|
||||
if (useValues and def->numFound > 0)
|
||||
{
|
||||
oss << name << "=" << def->valueAsString(false) << "\n";
|
||||
|
|
|
@ -299,6 +299,24 @@ namespace llarp
|
|||
void
|
||||
acceptAllOptions();
|
||||
|
||||
/// Add comments for a given section. Comments are replayed in-order during config file
|
||||
/// generation. A proper comment prefix will automatically be applied, and the entire comment
|
||||
/// will otherwise be used verbatim (no automatic line separation, etc.).
|
||||
///
|
||||
/// @param section
|
||||
/// @param comment
|
||||
void
|
||||
addSectionComment(const std::string& section, std::string comment);
|
||||
|
||||
/// Add comments for a given option. Similar to addSectionComment, but applies to a specific
|
||||
/// [section]:name pair.
|
||||
///
|
||||
/// @param section
|
||||
/// @param name
|
||||
/// @param comment
|
||||
void
|
||||
addOptionComment(const std::string& section, const std::string& name, std::string comment);
|
||||
|
||||
/// Generate a config string from the current config definition, optionally using overridden
|
||||
/// values. The generated config will preserve insertion order of both sections and their
|
||||
/// definitions.
|
||||
|
@ -331,6 +349,12 @@ namespace llarp
|
|||
// track insertion order
|
||||
std::vector<std::string> m_sectionOrdering;
|
||||
std::unordered_map<std::string, std::vector<std::string>> m_definitionOrdering;
|
||||
|
||||
// comments for config file generation
|
||||
using CommentList = std::vector<std::string>;
|
||||
using CommentsMap = std::unordered_map<std::string, CommentList>;
|
||||
CommentsMap m_sectionComments;
|
||||
std::unordered_map<std::string, CommentsMap> m_definitionComments;
|
||||
};
|
||||
|
||||
} // namespace llarp
|
||||
|
|
|
@ -54,3 +54,103 @@ TEST_CASE("Configuration useValue test", "[config]")
|
|||
CHECK(config.generateINIConfig(true) == expectedWhenValueProvided);
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration section comments test")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
|
||||
config.addSectionComment("foo", "test comment");
|
||||
config.addSectionComment("foo", "test comment 2");
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
"foo", "bar", true, 1));
|
||||
|
||||
std::string output = config.generateINIConfig();
|
||||
|
||||
CHECK(output == R"raw(# test comment
|
||||
# test comment 2
|
||||
[foo]
|
||||
bar=1
|
||||
)raw");
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration option comments test")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
|
||||
config.addOptionComment("foo", "bar", "test comment 1");
|
||||
config.addOptionComment("foo", "bar", "test comment 2");
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
"foo", "bar", true, 1));
|
||||
|
||||
std::string output = config.generateINIConfig();
|
||||
|
||||
CHECK(output == R"raw([foo]
|
||||
# test comment 1
|
||||
# test comment 2
|
||||
bar=1
|
||||
)raw");
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration empty comments test")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
|
||||
config.addSectionComment("foo", "section comment");
|
||||
config.addSectionComment("foo", "");
|
||||
|
||||
config.addOptionComment("foo", "bar", "option comment");
|
||||
config.addOptionComment("foo", "bar", "");
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
"foo", "bar", true, 1));
|
||||
|
||||
std::string output = config.generateINIConfig();
|
||||
|
||||
CHECK(output == R"raw(# section comment
|
||||
#
|
||||
[foo]
|
||||
# option comment
|
||||
#
|
||||
bar=1
|
||||
)raw");
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration multi option comments")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
|
||||
config.addSectionComment("foo", "foo section comment");
|
||||
|
||||
config.addOptionComment("foo", "bar", "foo bar option comment");
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
"foo", "bar", true, 1));
|
||||
|
||||
config.addOptionComment("foo", "baz", "foo baz option comment");
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
"foo", "baz", true, 1));
|
||||
|
||||
std::string output = config.generateINIConfig();
|
||||
|
||||
CHECK(output == R"raw(# foo section comment
|
||||
[foo]
|
||||
# foo bar option comment
|
||||
bar=1
|
||||
# foo baz option comment
|
||||
baz=1
|
||||
)raw");
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration should print comments for missing keys")
|
||||
{
|
||||
// TODO: this currently fails: how to implement?
|
||||
llarp::Configuration config;
|
||||
|
||||
config.addSectionComment("foo", "foo section comment");
|
||||
config.addOptionComment("foo", "bar", "foo bar option comment");
|
||||
|
||||
std::string output = config.generateINIConfig();
|
||||
|
||||
CHECK(output == R"raw(# foo section comment
|
||||
[foo]
|
||||
# foo bar option comment
|
||||
bar=
|
||||
)raw");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue