about summary refs log tree commit diff stats
path: root/README.md
blob: b667597aaa083e3de8c6eeb2dfef4c3c60fd73fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# 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:

```scheme
(define some-string #<#end
Here is a multiline string literal with #(display "embedded") Scheme code.
1 + 2 = #(+ 1 2), etc.
end
)
```

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):

```sh
cat <<EOF
Here is a here-document in bourne shell.  It performs expansion, so you can
include things like $(echo "this") in.
1 + 2 = $((1 + 2)), etc.
EOF
```

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:

- [r7rs](http://wiki.call-cc.org/eggref/5/r7rs)
- [utf8](http://wiki.call-cc.org/eggref/5/utf8)
- [srfi-1](http://wiki.call-cc.org/eggref/5/srfi-1)
- [html-parser](http://wiki.call-cc.org/eggref/5/html-parser)

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

```scheme
`((#\, . ,(lambda (in)
            (eval (read in) (render-environment)))))
```

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-environment`s.

### 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`

```scheme
(list (cons "#<unspecified>" unprintable/skip)
      (cons "#!eof" unprintable/backtrack))
```

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.

[COPYING]: /schmaltz/tree/COPYING

### 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.