add join function (#204)

* add join function

* fix formatting to match single include

* add join test

* add join to documentation

* fix MSVC warning: signed/unsigned mismatch

Co-authored-by: Wim Leflere <wleflere@cochlear.com>
This commit is contained in:
Wim Leflere
2021-06-17 20:54:22 +02:00
committed by GitHub
parent 9cf7db8a06
commit 91c93bfb77
5 changed files with 49 additions and 0 deletions

View File

@@ -224,6 +224,10 @@ render("{{ last(guests) }} was last.", data); // "Patir was last."
render("{{ sort([3,2,1]) }}", data); // "[1,2,3]"
render("{{ sort(guests) }}", data); // "[\"Jeff\", \"Patrick\", \"Tom\"]"
// Join a list with a separator
render("{{ join([1,2,3], \" + \") }}", data); // "1 + 2 + 3"
render("{{ join(guests, \", \") }}", data); // "Jeff, Patrick, Tom"
// Round numbers to a given precision
render("{{ round(3.1415, 0) }}", data); // 3
render("{{ round(3.1415, 3) }}", data); // 3.142

View File

@@ -65,6 +65,7 @@ public:
Sort,
Upper,
Super,
Join,
Callback,
ParenLeft,
ParenRight,
@@ -109,6 +110,7 @@ private:
{std::make_pair("upper", 1), FunctionData { Operation::Upper }},
{std::make_pair("super", 0), FunctionData { Operation::Super }},
{std::make_pair("super", 1), FunctionData { Operation::Super }},
{std::make_pair("join", 2), FunctionData { Operation::Join }},
};
public:

View File

@@ -528,6 +528,24 @@ class Renderer : public NodeVisitor {
json_tmp_stack.push_back(result_ptr);
json_eval_stack.push(result_ptr.get());
} break;
case Op::Join: {
const auto args = get_arguments<2>(node);
const auto separator = args[1]->get<std::string>();
std::ostringstream os;
std::string sep;
for (const auto& value : *args[0]) {
os << sep;
if (value.is_string()) {
os << value.get<std::string>(); // otherwise the value is surrounded with ""
} else {
os << value;
}
sep = separator;
}
result_ptr = std::make_shared<json>(os.str());
json_tmp_stack.push_back(result_ptr);
json_eval_stack.push(result_ptr.get());
} break;
case Op::ParenLeft:
case Op::ParenRight:
case Op::None:

View File

@@ -1602,6 +1602,7 @@ public:
Sort,
Upper,
Super,
Join,
Callback,
ParenLeft,
ParenRight,
@@ -1646,6 +1647,7 @@ private:
{std::make_pair("upper", 1), FunctionData { Operation::Upper }},
{std::make_pair("super", 0), FunctionData { Operation::Super }},
{std::make_pair("super", 1), FunctionData { Operation::Super }},
{std::make_pair("join", 2), FunctionData { Operation::Join }},
};
public:
@@ -4022,6 +4024,24 @@ class Renderer : public NodeVisitor {
json_tmp_stack.push_back(result_ptr);
json_eval_stack.push(result_ptr.get());
} break;
case Op::Join: {
const auto args = get_arguments<2>(node);
const auto separator = args[1]->get<std::string>();
std::ostringstream os;
std::string sep;
for (const auto& value : *args[0]) {
os << sep;
if (value.is_string()) {
os << value.get<std::string>(); // otherwise the value is surrounded with ""
} else {
os << value;
}
sep = separator;
}
result_ptr = std::make_shared<json>(os.str());
json_tmp_stack.push_back(result_ptr);
json_eval_stack.push(result_ptr.get());
} break;
case Op::ParenLeft:
case Op::ParenRight:
case Op::None:

View File

@@ -174,6 +174,11 @@ TEST_CASE("functions") {
"[inja.exception.render_error] (at 1:22) variable 'sister' not found");
}
SUBCASE("join") {
CHECK(env.render("{{ join(names, \" | \") }}", data) == "Jeff | Seb | Peter | Tom");
CHECK(env.render("{{ join(vars, \", \") }}", data) == "2, 3, 4, 0, -1, -2, -3");
}
SUBCASE("isType") {
CHECK(env.render("{{ isBoolean(is_happy) }}", data) == "true");
CHECK(env.render("{{ isBoolean(vars) }}", data) == "false");