
Introducing Tera, a template engine in Rust - adamnemecek
https://blog.wearewizards.io/introducing-tera-a-template-engine-in-rust
======
the_mitsuhiko
As someone who spent way too much time building Django inspired template
engines (Jinja, Jinja2, Twig, etc.) I must say this is really cool and very
close to what I wanted to build myself for Rust but did not have the time.

> Tera uses serde which means that in the example above

Very good. But serde needs to get stable :(

> beautiful html output out of the box (ie no need for the {{- tags)

This is a request that comes up often but I tested this so much and always
came back to not doing magic. It breaks too many applications in unintended
ways (particularly plain text output).

> able to register new tags easily like the {% url ... %} in Django

I would not do that again. Jinja has an extension interface and I regret
adding it. I much rather have people just expose functions to the templates.
That said, in Rust that might be not a good idea because there are no keyword
arguments so make it makes sense there.

> no macros or other complex logic in the template […] include partial
> templates

Another thing i strongly disagree with but I can see the motivation. Macros in
Jinja I prefer so much over includes because it becomes clear what values
exist. Includes become really messy unless you are very organized. Macros
(which are just functions) accept the parameters and it becomes clear what the
thing does. Just look at that macro as an example:
[https://github.com/pallets/website/blob/master/templates/mac...](https://github.com/pallets/website/blob/master/templates/macros/navigation.html)

It's absolutely clear what it accepts as parameters. If that was a partial
include the "caller" needs to set up the variables appropriately and there is
no clear documentation on what the template wants etc.

But awesome to see this happen for Rust!

~~~
Keats
> Very good. But serde needs to get stable :(

I agree :(

> This is a request that comes up often but I tested this so much and always
> came back to not doing magic. It breaks too many applications in unintended
> ways (particularly plain text output).

That was even the first feature request I got. I don't think I'll go more into
magic than what it currently is, seems to be okay-ish

> I would not do that again. Jinja has an extension interface and I regret
> adding it. I much rather have people just expose functions to the templates.
> That said, in Rust that might be not a good idea because there are no
> keyword arguments so make it makes sense there.

That was my first thought on a better way to do template tags but not sure how
to do that in Rust. If anyone has an idea, there's
[https://github.com/Keats/tera/issues/23](https://github.com/Keats/tera/issues/23)
now

Good point about macros, maybe I can have a look later. Macros and include
feel like they fill the same spot in my mind in terms of features so I'd
rather not have both.

~~~
lomnakkus
> Good point about macros, maybe I can have a look later. Macros and include
> feel like they fill the same spot in my mind in terms of features so I'd
> rather not have both.

You could always repurpose includes as _imports_ , i.e. not generate any
output from imports, but to allow their use as purely an organizational tool
for importing macros.

------
Pxtl
I've been expermenting with Mustache under the hood lately, so I'm interested
in template implementations. It seems odd, you've chosen an odd middle-ground
of "support arithmetic" and "no real heavy logic".

Having played with the subject a few times, I've come to the general feeling
that it's best to choose a hard line on one side or the other - either the
mustache "pure logicless" or just do straight string interpolation (assuming
the language provides a good syntax for multi-line string interpolation - C#
_almost_ does except that you have to escape all your quotes. Dunno if other
languages to better).

Any particular reason why you chose to support _some_ logic instead of none or
all?

~~~
JBReefer
Do you know if the quote escape is still required with C# 6 interpolation?

~~~
Pxtl
C#6 string interpolation is glorious, but if you use the multiline

    
    
        var myString = $@"
        Hey, string interpolation is nifty.
        Look ma, no { this.Hands.ToString().ToUpper() }
        More text.
        But this is a ""quote"".  It's ""ugly"" isn't it?
        ";
    

As you can see, you need to double your double quotes to escape them. Almost
perfect. You can even nest string interpolations to do next template stuff
with functional-programming loops and whatnot.

~~~
virtualwhys
Scala seems to do what you want:

    
    
        val str = s"""
          Tripe quoted string interpolation
          Allows for $variables and ${method.foo(bar)}
          Mixed with "quotes" 
        """
    

Can also use double quoted string interpolation for inline/one-liners where
embedded quotes above aren't needed.

~~~
Pxtl
Neat! With facilities like that, Id be tempted to skip templating libraries
altogether and just have a normal interface for templates and use the regular
string expressions... Unless I needed then internationalized, and that's where
Mustache shines, IMHO.

------
acjohnson55
After using many templating systems over the years, I'm sold on the opposite
approach of embedding (a description of) the output language in the host
language, rather than trying to embed logic in the output language. Think
React or Scalatags. Logic becomes trivial, because it's the logic of the host
language. And the output can be the output language, directly, or some other
data structure (VDOM, in the case of React).

It's similar to the concept of the free monad [1].

[1] [http://underscore.io/blog/posts/2015/04/14/free-monads-
are-s...](http://underscore.io/blog/posts/2015/04/14/free-monads-are-
simple.html)

------
nikolay
Clean, meaningful syntax! Great job!

Edit: Why spread the ugliness of "endif" and "endblock"? Why not just "end"?
Why have the unnatural "elif" as well?

~~~
the_mitsuhiko
> Edit: Why spread the ugliness of "endif" and "endblock"? Why not just "end"?
> Why have the unnatural "elif" as well?

Not the developer but I did not remove endif for twig or jinja either coming
from Django. Reasons for it: it becomes a lot more readable in the templates
and it avoids lots of debug headache due to accidentally deleting things. It's
already hard enough to debug template code sometimes but this way at least
it's very quickly clear what the problem is.

What would you use instead of elif? `{% else if %}` is in no way nicer than
`{% elif %}`. I picked `elif` in Jinja because it's what Python uses and
that's where Jinja is at home.

~~~
Keats
I was about to reply exactly that, thanks!

~~~
nikolay
You have to indent anyway. Then "endblock" becomes redundant. Also, you can't
have a blank "{% elif %}" \- it needs to be followed by a condition. I think a
more natural and English-like syntax beats having to memorize deviations.

------
bfrog
Why add the requirement of naming the end tags? Seems like a relatively small
change except if your trying to re-use templates everywhere

~~~
Keats
Just for the sake of readability. At a previous job we had pretty huge
templates and I would forget the name of the block by the time I reached the
end

~~~
nikolay
Give people an option. I prefer "end" \- make "endblock" work like "end", but
check nesting.

