diff --git a/src/internal_value.cpp b/src/internal_value.cpp index 81bb6a1..84bcbc6 100644 --- a/src/internal_value.cpp +++ b/src/internal_value.cpp @@ -698,7 +698,7 @@ InternalValueList ListAdapter::ToValueList() const InternalValue BuiltinMethod(InternalValue self, Callable::ExpressionCallable method) { - auto result = InternalValue(RecursiveWrapper(Callable(Callable::Kind::SpecialFunc, std::move(method)))); + auto result = InternalValue(RecursiveWrapper(Callable(Callable::Kind::UserCallable, std::move(method)))); result.SetParentData(std::move(self)); return result; } @@ -788,6 +788,21 @@ InternalValue DictUpdate(MapAdapter self) ); } +InternalValue DictItems(MapAdapter self) +{ + return BuiltinMethod( + self, + [self](const CallParams&, RenderContext&) { + InternalValueList items; + auto keys = self.GetKeys(); + std::sort(keys.begin(), keys.end()); + for (const auto& key : keys) + items.push_back(RecursiveWrapper(KeyValuePair{key, self.GetValueByName(key)})); + return InternalValue(ListAdapter::CreateAdapter(std::move(items))); + } + ); +} + InternalValue MapAdapter::GetBuiltinMethod(const std::string& name) const { if (!m_accessorProvider || !m_accessorProvider()) @@ -795,6 +810,8 @@ InternalValue MapAdapter::GetBuiltinMethod(const std::string& name) const if (name == "update") return DictUpdate(*this); + if (name == "items") + return DictItems(*this); return InternalValue(); } diff --git a/test/statements_tets.cpp b/test/statements_tets.cpp index 7fc1fca..43f7873 100644 --- a/test/statements_tets.cpp +++ b/test/statements_tets.cpp @@ -466,6 +466,24 @@ R"( R"( +a: 1 +b: 2 +)" +) +{ +} + +MULTISTR_TEST(ForTest, ForKeyValueInDictItems, +R"( +{% set d = {'a'=1,'b'=2} %} +{% for k, v in d.items() %} +{{ k }}: {{ v }} +{%- endfor %} +)", +//------------ +R"( + + a: 1 b: 2 )"