about summary refs log tree commit diff stats

Schmaltz

Render embedded Scheme in texts

Schmaltz is a way to embed Scheme code in text files using escape characters. This makes it a decent templating language à la PHP or shell here-documents.

Rationale

Schmaltz was inspired by shell here-documents as well as CHICKEN’s extension to Scheme string literals, which looks like this:

While this works fine enough, there are a number of limitations preventing it from more thorough use:

  • The above notation only works with string literals.
  • The end tag must be alone on a line and at the beginning of the line. That, plus the fact that this is a non-standard extension, mean that editors (Emacs) indent that end tag, leading to a mis-parse. Fixing it is possible but fiddly.
  • The escape notation isn’t extensible.

Here-documents, in shell and other scripts, are similar in form (I assume that CHICKEN’s extension was inspired by this syntax):

In shell here-documents, however, every expanded form is executed in a sub-shell, meaning that variable assignments and function definitions are not persistent across the document.

Schmaltz attempts to fix all of these problems. In fact, within a schmaltz-powered document you should have all of the power of Scheme within rendered forms, as well as persistence of environment and access to the rest of your Scheme system. Here is a schmaltz document in the same format as the above for illustration:

#,(define word "expansion")
Here is a schmaltz-powered text thing.  It can do #,(display word), as well as
arithmetic and all sorts of other things.
#,(import (scheme inexact))
The square root of 13 is #,(sqrt 13), etc.

Installation

Schmaltz is written in CHICKEN Scheme v.5.3.0 and Works on My Machine™. Your mileage may vary, though I welcome bug reports and merge requests!

To install schmaltz, you’ll need the following eggs:

This repository comes with an egg file, so you should just be able to run chicken-install -s inside of it to install all the dependencies as well as schmaltz.

Usage

Schmaltz is packaged both as a portable R7RS library (untested) and a CHICKEN executable.

R7RS library: (schmaltz)

The schmaltz library exports the following definitions in its public API:

(render [port] [environment]) procedure

Read the input PORT, evaluating every expansion form in ENVIRONMENT. PORT defaults to current-input-port and ENVIRONMENT defaults to render-environment. Outputs to current-output-port.

(render-string string [environment]) procedure

Perform render with STRING as the input port.

(render->string . args) procedure

Perform render, returning a string with the output. Takes the same arguments as render.

(render-string->string . args) procedure

Perform render-string, returning a string with the output. Takes the same arguments as render-string.

render-specials parameter

Special characters to trigger expansion. Every expansion begins with #, then another character, then a Scheme form. render-specials is an alist where CARs is a character literal and CDRs are procedures of one parameter, an input port.

render-specials defaults to

This renders #,(+ 1 2) to 3.

render-unprintables parameter

String results not to include in the rendered output. For example, define might return an unspecified or void value, which when displayed could be #<unspecified>. render-unprintables is an alist where CARs are strings and CDRs are procedures of one parameter, the current character being processed. The default value of render-unprintable is an empty list, but see the section on the schmaltz executable for a more useful example.

(unprintable/skip . _), (unprintable/backtrack char) procedures

Helper procedures for definitions in render-unprintables. See the example below for usage ideas.

unprintable/skip skips whatever output is given from the rendered Scheme code and prints nothing. unprintable/backtrack skips the output, but backtracks to output the character triggering the expansion as well as the preceding #.

render-environment parameter

The environment to evaluate rendered forms in. Defaults to interaction-environment.

environment procedure

Re-exported from (scheme eval) for ease of building render-environments.

Executable: schmaltz

The schmaltz executable reads standard input or files from the command line, rendering and concatenating all of them to standard output, like cat. Also like cat, if - is passed as a parameter to schmaltz, it will insert the contents of standard input at that position in the output.

You can call it as a compiled file or as a script as long as you have csi installed.

By default, schmaltz extends the definitions of the following library parameters:

render-specials

Adds @ for expanding to html via sxml->html, e.g.

#@(a (@ (href "https://example.com")) "link")

renders to

<a href="https://example.com">link</a>

It wraps the form in an implicit quasiquote so you can include (string) variables, e.g.

#,(define title "Schmaltz!")
#@(h1 ,title)

render-unprintables

The above skips printing unspecified values altogether, and the end-of-file marker backtracks to print the (non-)escaping # at the input’s end. I’d recommend doing the same for any Scheme implementation, but I don’t know how they might display unspecified, void, or end-of-file characters.

License

Schmaltz, the library and the program, are licensed under the GOD WILLING LICENSE, version 1.0. See COPYING for details.

Contributing

Contributions are welcome! Email me at git at acdw dot net or get in touch via whatever other channels you know how with questions or comments or whatever.