about summary refs log tree commit diff stats
path: root/schmaltz.sls
diff options
context:
space:
mode:
Diffstat (limited to 'schmaltz.sls')
-rw-r--r--schmaltz.sls79
1 files changed, 79 insertions, 0 deletions
diff --git a/schmaltz.sls b/schmaltz.sls new file mode 100644 index 0000000..25d926b --- /dev/null +++ b/schmaltz.sls
@@ -0,0 +1,79 @@
1;;; schmaltz --- render scheme forms in text
2;; every effort has been made to make this portable code, or at least to hide
3;; the unportability behind configuration.
4
5(define render
6 (case-lambda
7 (()
8 (render (current-input-port) (render-environment)))
9 ((port)
10 (render port (render-environment)))
11 ((port env)
12 (let loop ((ch (read-char port))
13 (acc '()))
14 (cond
15 ((not ch) ; after an expansion
16 (loop (read-char port) acc))
17 ((eof-object? ch) ; end of file
18 (list->string (reverse acc)))
19 ((eq? ch #\#) ; expansion
20 (let* ((next (peek-char port))
21 (proc (assq-ref next (render-specials))))
22 (cond
23 ((eq? next #\\) ; escape character -- #\,( => #,(
24 (read-char port) ; skip the \
25 (loop (read-char port) ; continue
26 (cons ch acc)))
27 ((not proc) ; this character isn't special
28 (loop (read-char port) ; continue
29 (cons ch acc)))
30 (else ; look up the reader and run it
31 (read-char port) ; skip the character
32 (loop #f (append (let* ((ins (displayed (eval (proc port) env)))
33 (out (assoc ins (render-unprintables))))
34 (if out
35 ((cdr out) next)
36 (reverse (string->list ins))))
37 acc))))))
38 (else (loop (read-char port) ; normal character
39 (cons ch acc))))))))
40
41(define render-string
42 (case-lambda
43 ((s) (render-string s (interaction-environment)))
44 ((s env)
45 (call-with-port (open-input-string s)
46 (lambda (port)
47 (render env port))))))
48
49;;; Configuration
50
51(define render-environment
52 (make-parameter
53 (interaction-environment)))
54
55(define render-specials
56 ;; Alist of (CHAR . PROCEDURE) mapping input characters to special reader
57 ;; meanings. Each PROCEDURE should take one parameter, a port.
58 (make-parameter
59 (list (cons #\, (lambda (port) (eval (read port) ; standard scheme read
60 (interaction-environment))))
61 #;(cons #\@ (lambda (port) ; wrap the next form in `sxml->html'
62 `(sxml->html ,(list 'quasiquote (read port))))))))
63
64(define render-unprintables
65 (make-parameter
66 (list #;(cons "#<unspecified>" (lambda _ '()))
67 #;(cons "#!eof" (lambda (ch) (list ch #\#))))))
68
69;;;: Utilities
70
71(define (displayed x)
72 (call-with-port (open-output-string)
73 (lambda (port)
74 (display x port)
75 (get-output-string port))))
76
77(define (assq-ref key lis)
78 (let ((val (assq key lis)))
79 (if val (cdr val) #f)))