Even though this site was intended to be simple, there were some annoyances when maintaining it by hand:

An HTML page generator/processor was called for. There are heaps around. Too many. So I wrote my own.

Enter spp.scm

spp.scm (1.2k), a Scheme preprocessor, is the result. Right now it's 37 lines long, or 25 lines excluding comments and blank lines. It reads in a pseudo-HTML document and generates Scheme code, which it subsequently executes to produce said HTML document. Within the document you can embed arbitrary Scheme programs. All the functionality is derived from the underlying programming language. I use scsh (the Scheme Shell) which provides many features for Unix scripting. That means all the utilities on my system are accessible, too. (e.g. the line counts at the start of this paragraph are generated with wc and grep).

Let's see... Scsh embeds shell scripting abilities into the Scheme programming language. spp.scm makes Scsh available into near-plaintext documents. spp documents have Scheme programming abilities, as well as shell scripting abilities. Good enough for me.


Example 1

Here is how an image is inserted into a document:

,(image "filename.png")

image is a Scheme procedure, defined in a site-wide library common.scm (6.2k), like so:

(define (image file . alt-text)
  (let-match (regexp-search (rx (submatch (+ digit)) "x" (submatch (+ digit)))
			    (run/string (identify ,(string-append *base-directory* file))))
	     (#f #f width height)
	     (fmt "<img src='~A' width=~A height=~A~A>" file width height
		  (if (null? alt-text)
		      (string-append " alt='" (car alt-text) "'")))))

identify is an external program that gives all sorts of information about images. We run it on the image file and grab its output, then generate a line like:

<img src='filename.png' width=123 height=456>

Example 2

Here is how a downloadable file is linked in a document:

,(file-link "filename" "some description")

Here is the procedure file-link:

(define (file-link file . text)
  (if (file-not-exists? (string-append *base-directory* file))
      (error "bad link to" file)
      (fmt "<a href='~A'>~A</a> (~A)"
	   file (:optional text file)
	   (human-size (file-size (string-append *base-directory* file))))))

file-link figures out the size of a linked file automatically. In addition, it checks that the file actually exists, saving the labour of verifying that on-site links are not broken. (An unexpected side-benefit: I didn't think of this until after file-size complained when I made a typo.)

So what?

There is only one escape character, a comma (followed by non-whitespace). The expression that follows it is parsed with a single Scheme procedure: read. That's all there is to it.

Given such simplicity, spp isn't able to do absolutely everything (e.g. embed HTML in Scheme in HTML). But who'd want to do that?


You can view the source (4.9k) for this page, if you like.

Go back

Back to Psyk Software homepage.