Keats/tera

Ability to build an object or hashmap?

Opened this issue · 8 comments

Hey!

I'm trying to build some grouping functionality for my Zola blog and I wondered if it is currently possible (or planned) to build and mutate a JSON object or hashmap data structure?

For example, I'm currently iterating over an array of objects that each have their own tags.
I'd like to be able to group these objects into by their tags, ending up with a Hashmap<String, Vec<MyObject>> in rough Rust terms.

It looks like this would probably want to live in https://github.com/Keats/tera/blob/master/src/builtins/filters/object.rs as this is already concerned with handling serde_json::Value::Objects?

I'm happy to take a stab at this if you're okay with it 👍

This will be tremendously interesting to me. It will drastically reduce the number of parameters I have in macros and simplify a lot of code if optional fields can be grouped inside a single config object instead of each being a variable.

A way to create a hash literal is needed as well as the ability to set a field of an object.

@absolutejam your suggestion gives me an idea.

We can very simply write such a function, say make_obj, that returns a hash object from its parameters.

Until the native syntax arrives, this can be a huge boom in productivity as I can then write macros that take objects as parameters.

EDIT: I confirm that the idea works. I have obj function and mixin/polyfill filters and all are looking good!

What's not defined yet is what would be the syntax to update a hashmap

I solved it via a mixin filter:

{{ map | mixin(foo=42, bar=true) }}

will return a new map with the two properties replaced.

Setting properties then become:

set map = map | mixin(foo=42, bar=true)

Yeah the filter is the obvious one, it's just a bit verbose to set new things but maybe it's the simpler one

If you're looking for syntax suggestions, I suggest:

{% set_prop map.foo = 42 %}
{% set_prop map["foo"] = 42 %}

{% remove_prop map.foo %}
{% remove_prop map["foo"] %}

Or maybe just {% set map.foo = 42 %}? I don't know if we will need to remove things from a hashmap. I have never needed that in any template engine (so far)

Or maybe just {% set map.foo = 42 %}? I don't know if we will need to remove things from a hashmap. I have never needed that in any template engine (so far)

That would work too...

In that case we can do delete map.prop or delete_prop map.prop like JavaScript.