Common Lisp interface

We're getting down to details now. I'll document in this section how to
interface with Common Lisp, that is, define your own primitive functions,
define custom template handlers etc.

Sytes doesn't implement its own data structures; instead it uses ordinary
Common Lisp values, which makes it easy to interface with CL. Even a
lambda, compiles to an ordinary CL function, which means you can pass
functions defined in Sytes to Common Lisp, i.e.:

Defining custom URL handlers

Another way to interface with CL which might be convenient sometimes is to
intercept whole calls to an URL and perhaps decide which template to
execute (rather than delegate this responsibility to Sytes), or pass
additional variables to the template. This would work as well (maybe even
better) as a dhandler for the blog example, it's just another way to do
it.

(sytes:def-url-handler (*syte* "^/blog/([0-9]+)/([0-9]+)/([0-9]+)/(.*)$"
year month date title)
;; as you can see, it's regexp-based
;; when a blog URL is encountered, it'll get here,
;; and we also conveniently get the parts of the URL
;; that we're interested in (year, month, date and title)
(let ((entry ...fetch DB entry...))
`(:template "blog/index.syt"
:variables ("title" ,(blog-entry-title entry)
"body" ,(blog-entry-body entry)))))

Notice an important thing above: the variables that we pass
to the template needs to be a plist, and in particular, variable names
should be strings rather than CL symbols. They can also be Sytes symbols,
i.e. you can pass (intern "title" :sytes.%runtime%), with
the advantage that you can evaluate that at read-time, but it's uglier to
type.

A custom handler may return the keyword :continue in order
to decline and let Sytes continue handling the request normally.
Otherwise the return value should be a list of keyword-values (that's
passed to (destructuring-bind)) and it supports the
following keywords (some are exclusive):

:template — set the template to run. The path is
relative to the Syte root directory. If this property is not returned,
Sytes will decide what template to try based on the URL, as it does
normally.

:variables — definitions to make available in the
template. They will be only available at run-time, not at
compile-time.

:redirect — when present, tells Sytes an URL to
redirect to. Other values don't make sense in this case.

:static-file — serve the given file
using hunchentoot:handle-static-file.