roxbase is a minimal and very simple Template System for Lisp. It isn't yet feature-complete and first and foremost intended for my own use. I have only 'tested' (used) it under .[1]
What do I mean by Template System? I wanted something similar to Edi Weitz' (of fame) , but more akin to ASP.NET than that Perl templating module which inspired aforementioned HTML-TEMPLATE.
So the basic idea is to embed Lisp code in text files (think HTML pages) and process those files so that each Lisp expression be replaced with the result of evaluating it.
The most obvious use for roxbase is within a web context. The system integrates well with Hunchentoot, this website for one runs on Hunchentoot and roxbase. However, you can use within any other kind of context. roxbase only provides some basic string processing logic as described below.
Once you have set it up, you can feed roxbase templates such as this:
<a href="<%= (my-url-function (random 50)) %>">
<%@ 'link-caption %>
</a>
There are two kinds of expressions that are being processed by roxbase:
| Name | Description | Example |
| Inline Expressions | Contains self-contained Lisp expressions. |
Two and two makes <%= (+ 2 2) %>
|
| Mix-In Expressions | Mixes Lisp code and template contents arbitrarily. |
Let's loop <b>ten</b> times:
|
(Beware of creating endless loops when dynamically generating new mix-in or inline expressions!)
The process-template function processes all inline expressions (InLexes) it finds in the template it is given. InLexes start with <% (unless you change the value of +inlex-start-tag+) and end with %> (unless you change the value of +inlex-end-tag+). In addition, <% must be followed directly by a character that identifies the kind of InLex you're writing. The following InLexes are already built into roxbase. Needless to say, you can define your own. Only the first three InLex handlers really come with their own specific evaluation logic, the others translate into more complex InLex expressions of <%= or <%%.
| Name: | Description: | Example: | |
| <%= | Eval | Replaced with the result of evaluating the enclosed Lisp expression. | <%= (+ (random 20) (random 40)) %> |
| <%% | Def | No output is generated. Can be used for defuns and other definitions. Your definitions are available to Eval InLexes. In contrast to Eval InLexes, the args hashtable is not available. Pass it as an argument to your functions if you need to access the template arguments. |
<%%
|
| <%! | Comment | No output is generated. Content is ignored and discarded. | <%! (needs-fix) %> |
| <%~ | Load | No output is generated. Load .lisp / .fasl code files. Unless an absolute path (starting with '/') is specified, the search path is considered relative to your root-path. |
<%~ "code/my-page-tools"
|
| <%? | Query | If you're using Hunchentoot, replaced with the value of the URL query string parameter with the specified name. |
<%? "foo" %>
|
| <%& | Form | If you're using Hunchentoot, replaced with the value of the POSTed form parameter with the specified name. |
<%& "foo" %>
|
| <%$ | Session | If you're using Hunchentoot, replaced with the value of the session variable with the specified name. |
<%$ "foo" %>
|
| <%| | Header | If you're using Hunchentoot, replaced with the value of the request header with the specified name. |
<%| "Accept-Content-Type" %>
|
| <%@ | Argument | Replaced with the value associated with the specified key in the template's args hash table. |
<%@ "my-arg" %>
or
<%@ 'my-other-arg %>
or whatever you chose to use for a hash key in the args table.
|
| <%" | HTML Encoder | Replaced with the result of passing the enclosed Lisp expression to Hunchentoot's escape-for-html function. |
<pre><%" "Sample code:
|
| <%' | JavaScript Encoder | Replaced with the result of passing the enclosed Lisp expression to the escape-for-js function. |
alert("<%' "'Bobo'
|
| <%: | Safe Encoder | Replaced with the result of passing the enclosed Lisp expression to the escape-for-safe function, which accepts multiple strings, concatenates them with *rox-escape-char* (by default, the underscore) and replaces all non-alphanumeric characters in the resulting string with said escape character. |
<a name="<%: "why not?" %>">
|
| <%# | Sub Template | Replaced with the result of processing the specified template with the specified arguments (those will be available to the template in its args hash table). |
<%# "/controls/footer.html"
|
Before you can use it, roxbase needs to be initialized. Call the following function:
As described above, the port argument implicitly controls whether server-startup starts up and returns a new Hunchentoot server instance. If this is the case, roxbase sets up its own Hunchentoot request handlers that either simply return a file unprocessed if the request path fits the directory specification (relative to pathname-root) in foldername-static, otherwise, it invokes the specified script-path-handler function and processes the file represented by the path (relative to pathname-root) returned by the function call.
After you're done with your template processing, you can call the server-shutdown function to clean things up. If your previous server-startup call initialized a new Hunchentoot server instance (that is still stored in the global variable *rox-server*), the service is stopped. Afterwards, the following global hash tables are cleared:
If you're using roxbase with Hunchentoot, each non-static request is handled by handle-request, which returns a string that is the result of processing the file indicated by the script-path-handler you specified when you called server-startup. You can call handle-request yourself, it has the same signature as a script-path-handler. In case you ever need to do just that, pass the following arguments:
Unless called manually, handle-request is called either in response to a Hunchentoot web request or by the load-template macro, which is a syntactically compact way to recursively load sub-templates during a parent template processing request.
14 comment(s) pending moderation.