Embedded Nim template compiler that is still work in progress.
ENim allows embedding Nim code into a text template using the switches <% %>
. It is inspired by and similar to ERB in the Ruby programming language. The opening <%
can be immediately followed by a directive as follows:
- No directive means the Nim code is simply evaluated e.g.
<% if true: %>
- Substitution directive evaluates the Nim code and inserts its result into the template e.g.
<%= greet(person) %>
- Comment directive simply ommits the text from the template output e.g.
<%# This is just a comment %>
- Tag directive creates an anchor point for injecting another template e.g.
<%@ content "footer" %>
Apart from the templating ability, what's interesting about ENim is its performance goal. While the template output can be a string its intermediate state is as an IOMap
object or tree. Instead of concatenating strings together to achive the output, an IOMap builds a hierarcy tree of the strings. In a template any regular (non-substituted) text is stored as a constant, in essence caching it and given a socket, the IOMap can be written to it without any concatenation using the UNIX writev
call. This is inspired by how Erlang handles strings using IOList.
Here's a sample template that happens to be HTML in templates/layout.enim
:
<!DOCTYPE html>
<html>
<head>
<title>Using ENim</title>
<%= csrf_meta_tags() %>
<%= csp_meta_tag() %>
<%@ content "assets": %>
<%= stylesheet_link_tag("application", true) %>
<%= javascript_include_tag("application", true) %>
<% end %>
</head>
<body>
<%@ yield %>
<footer>
<%@ content "footer": %>
<p>© 2019 MyCraft Ltd.</p>
<% end %>
</footer>
</body>
</html>
And in Nim code (src/user_view.nim
):
import enim/compile
import enim/iomap
proc userProfile(user: User): IOMap =
compileFile("../templates/user_profile.enim")