A RUst Compiling TEmplate system, ructe


#1

I have written a compiling template system, i.e. a preprocessor that takes web page templates (similar to twirl, mustache, or jinja2) and converts them to rust source code.

Blog entry: http://rasmus.krats.se/2016/ructe.en
Github repo: https://github.com/kaj/ructe

I think that this, in principle, is a sound way to get web templates without unpleasant run-time surprises. However, lots of details remain to be ironed-out, including the final syntax of the template language.

Comments very much welcome!


#2

I’ve made PR to awesome rust: https://github.com/kud1ing/awesome-rust/pull/207
Few notes:

  1. Is it extensible (in the sense of django templates or jinja)?
  2. Single file would be painful to debug.
  3. From the point of view of a someone who may work with templates a lot: runtime-interpreted mode would be welcome.

#3

Thanks for the PR to awesome rust, even if I personally think it’s a bit early to call this project awesome yet … :slight_smile:

For the notes:

  1. I don’t know all ways to extend django templates of jinja, but I think being able to directly call any rust function or ructe template covers rather a lot of ground.

  2. I agree at least partially, but Jethro Beekman pointed out in a comment on my blog that it should be rather easy to fix that. We’ll see soon …

  3. That would be very much out of scope for this project, but if someone else writes a runtime template system with the same syntax I have no objections.


#4
  1. I don’t know all ways to extend django templates of jinja, but I think being able to directly call any rust function or ructe template covers rather a lot of ground.

Function probably cover lot of things. However filters offer nicer syntax:

django: {{ email|as_url }} vs ructe @as_url(email)

this composes better. Generaly I’d say that having some way of writing

@f(g(h(value))) as something like @value|f|g|h (I am not sure about best syntax for it, special operator would do)
would be nice to have
Also the general idea of django is that you can define your own tags, and they can modify AST. That allows you do things like

{% cached 5min username %}
{{ username }}
{% end_cached %}

where all arguments after first (so only username in this case) are used to build cache key

  1. That would be very much out of scope for this project, but if someone else writes a runtime template system with the same syntax I have no objections.

If you are just calling rust code, this may be impossible.

Generally as a developer, I like ructe, becouse its close to rust. As a developer who may hand this over to frontent devs, I don’t, because its close to rust.


#5

For the first, “pipeline”, example, I think as_url should probably not be callable for any value, but only for things that is convertible to an url. That should be expressed by implementing a trait, and that trait declares a suitable method.

So the ructe version would be @email.as_url().

For the second version, the tag needs to take a sub-template as a parameter. So it should be possible to write a cached function to be used like this:

@cached(time, key, {
     @username
})

#6

That’s a good idea. Assuming @use is a direct translation to rust use. that would allow
to defined modules with traits usable for templating (to separate them form the rest of rust code).

Hm, not as elegant and convenient as django, but that would do I guess.


#7

The solution suggested by Jethro Beekman worked out fine and is now committed to github (but not released to crates.io yet). So this should no longer be an issue.