Conditional strings for Whiskers.

This commit is contained in:
chriseth 2020-04-23 16:29:17 +02:00
parent 61b1369fc2
commit aa8107f45a
4 changed files with 45 additions and 6 deletions

View File

@ -356,6 +356,11 @@ by as many concatenations of its contents as there were sets of variables suppli
each time replacing any ``<inner>`` items by their respective value. Top-level variables can also be used
inside such areas.
There are also conditionals of the form ``<?name>...<!name>...</name>``, where template replacements
continue recursively either in the first or the second segment depending on the value of the boolean
parameter ``name``. If ``<?+name>...<!+name>...</+name>`` is used, then the check is whether
the string parameter ``name`` is non-empty.
.. _documentation-style:
Documentation Style Guide

View File

@ -132,7 +132,11 @@ string Whiskers::replace(
map<string, vector<StringMap>> const& _listParameters
)
{
static regex listOrTag("<(" + paramRegex() + ")>|<#(" + paramRegex() + ")>((?:.|\\r|\\n)*?)</\\2>|<\\?(" + paramRegex() + ")>((?:.|\\r|\\n)*?)(<!\\4>((?:.|\\r|\\n)*?))?</\\4>");
static regex listOrTag(
"<(" + paramRegex() + ")>|"
"<#(" + paramRegex() + ")>((?:.|\\r|\\n)*?)</\\2>|"
"<\\?(\\+?" + paramRegex() + ")>((?:.|\\r|\\n)*?)(<!\\4>((?:.|\\r|\\n)*?))?</\\4>"
);
return regex_replace(_template, listOrTag, [&](match_results<string::const_iterator> _match) -> string
{
string tagName(_match[1]);
@ -164,12 +168,26 @@ string Whiskers::replace(
else
{
assertThrow(!conditionName.empty(), WhiskersError, "");
assertThrow(
_conditions.count(conditionName),
WhiskersError, "Condition parameter " + conditionName + " not set."
);
bool conditionValue = false;
if (conditionName[0] == '+')
{
string tag = conditionName.substr(1);
assertThrow(
_parameters.count(tag),
WhiskersError, "Tag " + tag + " used as condition but was not set."
);
conditionValue = !_parameters.at(tag).empty();
}
else
{
assertThrow(
_conditions.count(conditionName),
WhiskersError, "Condition parameter " + conditionName + " not set."
);
conditionValue = _conditions.at(conditionName);
}
return replace(
_conditions.at(conditionName) ? _match[5] : _match[7],
conditionValue ? _match[5] : _match[7],
_parameters,
_conditions,
_listParameters

View File

@ -59,6 +59,9 @@ DEV_SIMPLE_EXCEPTION(WhiskersError);
* - Condition parameter: <?name>...<!name>...</name>, where "<!name>" is optional
* replaced (and recursively expanded) by the first part if the condition is true
* and by the second (or empty string if missing) if the condition is false
* - Conditional string parameter: <?+name>...<!+name>...</+name>
* Works similar to a conditional parameter where the checked condition is
* that the regular (string) parameter called "name" is non-empty.
* - List parameter: <#list>...</list>
* The part between the tags is repeated as often as values are provided
* in the mapping. Each list element can have its own parameter -> value mapping.

View File

@ -114,6 +114,19 @@ BOOST_AUTO_TEST_CASE(conditional_plus_list)
BOOST_CHECK_EQUAL(m.render(), " - ab - ");
}
BOOST_AUTO_TEST_CASE(string_as_conditional)
{
string templ = "<?+b>+<b><!+b>-</+b>";
BOOST_CHECK_EQUAL(Whiskers(templ)("b", "abc").render(), "+abc");
BOOST_CHECK_EQUAL(Whiskers(templ)("b", "").render(), "-");
}
BOOST_AUTO_TEST_CASE(string_as_conditional_wrong)
{
string templ = "<?+b>+<b></b>";
BOOST_CHECK_EQUAL(Whiskers(templ)("b", "abc").render(), "<?+b>+abc</b>");
}
BOOST_AUTO_TEST_CASE(complicated_replacement)
{
string templ = "a <b> x <complicated> \n <nested>>.";