Glyph 0.5.0 Released

Featuring Calibre integration, macro composition, Turing-completeness, and more

Too much time passed since the last Glyph release. Way too much. Finally I found the time and will to tidy up the last few remaining bugs, update the docs, and release it!

This new release was mainly focused on extending the features of Glyph as a language. Besides a few improvements that make writing Glyph code easier and more readable (e.g. macro composition), Glyph is now Turing-complete. It supports iterations, recursion, variable assignments, basic arithmetics… you can even write a program to compute the factorial of an integer, if you wanted to.

Additionally, it also features enhanced content reuse through fragments and output-independent macros, and a few bugfixes.

Calibre Integration

Tammy Cravit proposed (and more or less implemented) an interesting new feature: integrate Calibre to generate ebooks in EPUB and MOBI format from Glyph's native standalone HTML output format.

Although the support is still somewhat rough, you can, as a matter of fact, generate ebooks with Glyph, using Calibre.

Macro Composition

This release features an update at syntax-level: the possibility of “composing” macros, thereby eliminating nesting provided that containers take only one parameter and no attributes. What? This:

1?[
2  not[output?[pdf]]|
3  ...
4]

Can be written like this:

1?[
2  not/output?[pdf]|
3  ...
4]

In this case, the not macro was composed with the output? macro, thus removing one level of nesting.

Additionally, I used this features to create an xml macro dispatcher that can be used to render raw XML tags, and an s macro dispatcher that basically is able to call nearly all the instance methods of the Ruby String class. So you can write things like s/sub[This feature makes my life easier|/my/|your] and similar.

Turing-Completeness

As of this version, Glyph can be considered Turing-complete, as it satisfies the following requirements for Turing-completeness:

  • A conditional construct, implemented via the condition macro.
  • Variable assignment, by setting the value of snippets using the snippet: macro and of attributes using the attribute: macro.
  • (infinite) iteration implemented through the new while macro or recursion, which is possible thanks to the new define: macro.
  • A memory model which emulates an infinite store: there are no enforced limits on attribute/snippets allocations and number of algorithms or parameters.

Plus, Glyph now understand basic integer arithmetic:

1def:[factorial|
2  ?[
3    eq[{{0}}|0]|1|
4    multiply[
5      {{0}} | factorial[subtract[{{0}}|1]]
6    ]
7  ]
8]

Not that you need to be able to calculate factorials in your documents, but know that now you can. An you can also define lexically scoped variables, err… attributes, like this:

1let[
2  @:[a|bits]
3  @:[b|bobs]
4  section[
5    @title[Something more about attributes]
6Attributes are like lexically scoped variables. You can use them to store @[a] and @[b].
7  ]
8]

Handy enough.

Embeddable fragments

Too lazy to create snippets? Feel the urge to re-use something you already wrote somewhere? Use a fragment and embed it, as follows:

1Snippets and fragments ##[good_way|are a good way to reuse] small chunks of content, 
2while the include and load macros <=[good_way] entire files.

…And you can also use a new load macro, to embed entire files without performing any evaluation (like include does).

Incompatibilities with previous versions

To sum up:

  • snippets.yml is no more, define all your snippets inside your document instead.
  • New “invisible space separator”: \/ instead of \.. Because it's slightly prettier, nothing else.
  • The rewrite: macro has been replaced by the define: macro, which also allows recursion, so be careful!
  • If you want to render raw XML tags, use xml/tag_name instead of =tag_name.
  • No more match macro, use s/match instead.

For the full list of the issues fixed in this release, see the Changelog.

Hope you'll enjoy this new release of Glyph. If you want to contribute, go ahead and fork the repo!