From aa8107f45a33ca195f85d68f043958279b52b038 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 23 Apr 2020 16:29:17 +0200 Subject: [PATCH] Conditional strings for Whiskers. --- docs/contributing.rst | 5 +++++ libsolutil/Whiskers.cpp | 30 ++++++++++++++++++++++++------ libsolutil/Whiskers.h | 3 +++ test/libsolutil/Whiskers.cpp | 13 +++++++++++++ 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index 98a01fd6d..395439018 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -356,6 +356,11 @@ by as many concatenations of its contents as there were sets of variables suppli each time replacing any ```` items by their respective value. Top-level variables can also be used inside such areas. +There are also conditionals of the form ``......``, where template replacements +continue recursively either in the first or the second segment depending on the value of the boolean +parameter ``name``. If ``......`` is used, then the check is whether +the string parameter ``name`` is non-empty. + .. _documentation-style: Documentation Style Guide diff --git a/libsolutil/Whiskers.cpp b/libsolutil/Whiskers.cpp index 208719d43..aebe55c69 100644 --- a/libsolutil/Whiskers.cpp +++ b/libsolutil/Whiskers.cpp @@ -132,7 +132,11 @@ string Whiskers::replace( map> const& _listParameters ) { - static regex listOrTag("<(" + paramRegex() + ")>|<#(" + paramRegex() + ")>((?:.|\\r|\\n)*?)|<\\?(" + paramRegex() + ")>((?:.|\\r|\\n)*?)(((?:.|\\r|\\n)*?))?"); + static regex listOrTag( + "<(" + paramRegex() + ")>|" + "<#(" + paramRegex() + ")>((?:.|\\r|\\n)*?)|" + "<\\?(\\+?" + paramRegex() + ")>((?:.|\\r|\\n)*?)(((?:.|\\r|\\n)*?))?" + ); return regex_replace(_template, listOrTag, [&](match_results _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 diff --git a/libsolutil/Whiskers.h b/libsolutil/Whiskers.h index 0165429fb..5eb00dce5 100644 --- a/libsolutil/Whiskers.h +++ b/libsolutil/Whiskers.h @@ -59,6 +59,9 @@ DEV_SIMPLE_EXCEPTION(WhiskersError); * - Condition parameter: ......, where "" 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: ...... + * Works similar to a conditional parameter where the checked condition is + * that the regular (string) parameter called "name" is non-empty. * - List parameter: <#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. diff --git a/test/libsolutil/Whiskers.cpp b/test/libsolutil/Whiskers.cpp index 3f2a48733..093b0acb6 100644 --- a/test/libsolutil/Whiskers.cpp +++ b/test/libsolutil/Whiskers.cpp @@ -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 = "+-"; + 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 = "+"; + BOOST_CHECK_EQUAL(Whiskers(templ)("b", "abc").render(), "+abc"); +} + BOOST_AUTO_TEST_CASE(complicated_replacement) { string templ = "a x \n >.";