Template-GLib

One of the things necessary in an IDE is the ability to create projects from templates. This is something we’ve been lacking since the beginning, and I’m finally in a position to follow through on it.

So, templates. What is a template? We have a couple layers of templates needed. We have, at a macro level, project templates. These are a collections of files, that get tweaked based on the project options.

Then we have per-file templates. These need to go through various tweaking and can get quite detailed, based on how much you want to do for the user.

I did a quick survey of what was available to reuse, and was not entire satisfied with the options. Thankfully I like programming languages and compilers, and decided to create exactly what I was hoping to find.

The result, was written over the past few days, and is called template-glib. It will look familiar to people who’ve used other template engines. Bits and pieces had inspiration from all over the place. I rather like python’s mako template API, but not much of a fan of the implementation. I also don’t want a bidirectional run-time[1] involved.

Some people really seem to like Go’s text templating. I’ve never used it, but like any language community full of crusaders, they’ll come to your door to let you know why they love it so much. Some things will be familiar to those people.

The API is designed in such a way that parsing and expanding the template are separate operations. If you were to use it in such a fashion, the parsing operation will be much less expensive.

Expanding of templates uses a TmplScope which can have inheritance. That allows for some nifty scoping control as you work your way down. I haven’t finished this to the level I’d like, but “it works”.

You can control resolving of included files using TmplTemplateLocator. This is similar to python mako’s TemplateLookup. Works as advertised.

You can include files, like:
{{include "foo.tmpl"}}

You can cycle through certain types of objects
{{for item in my_list}}
{{item.title}}
{{end}}

You can perform various expressions, including assignment.
{{x=sqrt(10)*sqrt(20)}}

You can call into methods via GObject Introspection.
{{item.short_description("with", "params")}}

You can use expressions in conditionals.
{{if item.year > 2016}}
Current: {{item.title}}
{{else}}
Archived: {{item.title}}
{{end}}

This code is very early, in fact less than a week old, but I’ll keep pushing it forward to add the features we need in Builder. Perhaps you’ll find it useful too. I’d certainly love to see someone make a nice GNOME 3 static blog generator.

You can find the lexer here and the parser here for the expression language.

[1] Bidirectional run-time meaning that objects can live en either the run-time or outside of it, and coordination of GC must occur.