sfx.scm added by amk9 on Thu Aug 15 17:11:02 2013
(define-module (sfx)
#:use-module (ice-9 receive)
#:use-module (oop goops describe)
#:use-module (skribilo reader skribe))
;; debug
(define (debug procedure text)
(display "debug, ")
(display procedure)
(display ": ")
(display text)
(newline))
;;
(define (warning text)
(format #t "warning: ~a " text)
(newline))
(define (file->sexpr file)
(define reader (make-skribe-reader))
(reader (open-input-file file)))
;; dispatch table for consumers
(define consumers (make-hash-table))
(define (consumer-get symbol)
(hash-ref consumers (string->symbol (string-append "consume-" (symbol->string symbol)))))
(define (consumer-set! procedure)
(hash-set! consumers (procedure-name procedure) procedure))
;; dispatch table for rewriter
(define rewriters (make-hash-table))
(define (rewriter-get symbol)
(hash-ref rewriters (string->symbol (string-append "rewrite-" (symbol->string symbol)))))
(define (rewriter-set! procedure)
(hash-set! rewriters (procedure-name procedure) procedure))
;; consumers
(define (consume-keywords sexpr keywords)
(cond ((null? sexpr) sexpr)
((keyword? (car sexpr))
(hash-set! keywords (keyword->symbol (car sexpr)) (cadr sexpr))
(consume-keywords (cddr sexpr) keywords))
(else sexpr)))
(define (consume-node name environment output sexpr continue)
(let* ((keywords (make-hash-table))
(body (consume-keywords sexpr keywords))
(id (hash-ref keywords `id))
(classes (hash-ref keywords `classes))
(href (hash-ref keywords `href)))
(output (format #f "<~a" name))
(if id (output (format #f " id=~s" (symbol->string id))))
(if classes (output (format #f " class=~s" classes)))
(if href (output (format #f " href=~s" href)))
(output ">")
(continue environment output body)
(output (format #f "~a>" name))))
(define (consume-simple-node name environment output sexpr continue)
(let ((keywords (make-hash-table)))
(consume-keywords sexpr keywords)
(output (format #f "<~a " name))
(hash-for-each (lambda (key value) (output (format #f "~a=~s " (symbol->string key) value))) keywords)
(output "/>")))
(define (consume-sexpr environment output sexpr)
(cond ((null? sexpr))
((and (symbol? (car sexpr)) (consumer-get (car sexpr))) ((consumer-get (car sexpr)) environment output (cdr sexpr)))
((and (symbol? (car sexpr)) (rewriter-get (car sexpr))) (consume-sexpr environment output ((rewriter-get (car sexpr)) environment (cdr sexpr))))
((list? (car sexpr)) (consume-sexpr environment output (car sexpr)) (consume-sexpr environment output (cdr sexpr)))
((equal? `quasiquote (car sexpr)) (consume-sexpr environment output (cdr sexpr)))
((equal? `unquote (car sexpr)) (consume-sexpr environment output (cdr sexpr)))
((string? (car sexpr)) (output (car sexpr)) (consume-sexpr environment output (cdr sexpr)))))
(define (quote environment output sexpr)
(consume-node "cite" environment output sexpr consume-sexpr))
(consumer-set! quote)
(define (consume-division environment output sexpr)
(consume-node "div" environment output sexpr consume-sexpr))
(consumer-set! consume-division)
(define (consume-ordered-list environment output sexpr)
(consume-node "ol" environment output sexpr consume-sexpr))
(consumer-set! consume-ordered-list)
(define (consume-list environment output sexpr)
(consume-node "ul" environment output sexpr consume-sexpr))
(consumer-set! consume-list)
(define (consume-item environment output sexpr)
(consume-node "li" environment output sexpr consume-sexpr))
(consumer-set! consume-item)
(define (consume-link environment output sexpr)
(let* ((keywords (make-hash-table))
(body (consume-keywords sexpr keywords))
(id (hash-ref keywords `id))
(classes (hash-ref keywords `classes))
(href (hash-ref keywords `href))
(name "a"))
(output (format #f "<~a" name))
(if id (output (format #f " id=~s" (symbol->string id))))
(if classes (output (format #f " class=~s" classes)))
(if (and href (string-suffix? ".sfx" href))
(let* ((basename (car (string-split href #\.)))
(output-name (string-append basename ".html")))
(consume href)
(output (format #f " href=~s" output-name)))
(if href (output (format #f " href=~s" href))))
(output ">")
(consume-sexpr environment output body)
(output (format #f "~a>" name))))
(consumer-set! consume-link)
(define (consume-bold environment output sexpr)
(consume-node "bold" environment output sexpr consume-sexpr))
(consumer-set! consume-bold)
(define (consume-span environment output sexpr)
(consume-node "span" environment output sexpr consume-sexpr))
(consumer-set! consume-span)
(define (consume-italic environment output sexpr)
(consume-node "i" environment output sexpr consume-sexpr))
(consumer-set! consume-italic)
(define (consume-paragraph environment output sexpr)
(consume-node "p" environment output sexpr consume-sexpr))
(consumer-set! consume-paragraph)
(define (consume-title environment output sexpr)
(consume-node "h1" environment output sexpr consume-sexpr))
(consumer-set! consume-title)
(define (consume-subtitle environment output sexpr)
(consume-node "h2" environment output sexpr consume-sexpr))
(consumer-set! consume-subtitle)
(define (consume-subsubtitle environment output sexpr)
(consume-node "h3" environment output sexpr consume-sexpr))
(consumer-set! consume-subsubtitle)
(define (consume-subsubsubtitle environment output sexpr)
(consume-node "h4" environment output sexpr consume-sexpr))
(consumer-set! consume-subsubsubtitle)
(define (consume-html environment output sexpr)
(output "")
(consume-node "html" environment output sexpr consume-sexpr))
(consumer-set! consume-html)
(define (consume-head environment output sexpr)
(consume-node "head" environment output sexpr consume-sexpr))
(consumer-set! consume-head)
(define (consume-body environment output sexpr)
(consume-node "body" environment output sexpr consume-sexpr))
(consumer-set! consume-body)
(define (consume-super-title environment output sexpr)
(consume-node "title" environment output sexpr consume-sexpr))
(consumer-set! consume-super-title)
(define (consume-super-link environment output sexpr)
(consume-simple-node "link" environment output sexpr consume-sexpr))
(consumer-set! consume-super-link)
(define (consume-meta environment output sexpr)
(consume-simple-node "meta" environment output sexpr consume-sexpr))
(consumer-set! consume-meta)
(define (consume-html-document environment output sexpr)
(let* ((keywords (make-hash-table))
(body (consume-keywords sexpr keywords))
(title (hash-ref keywords `title))
(style (hash-ref keywords `style)))
(output "")
(if title (output (format #f "~a " title)))
(if style (output (format #f "" style)))
(output "")
(output "")
(if body (consume-sexpr environment output body))
(output "")))
(consumer-set! consume-html-document)
(define (consume-template environment output sexpr)
(let* ((keywords (make-hash-table))
(body (consume-keywords sexpr keywords)))
(consume-sexpr environment output body)
(cond ((hash-ref keywords `extends)
(consume-sexpr environment output (file->sexpr (hash-ref keywords `extends)))))))
(consumer-set! consume-template)
(define (consume-define environment output sexpr)
(hash-set! environment (car sexpr) (cadr sexpr)))
(consumer-set! consume-define)
(define (rewrite-for-rec symbol values code sexpr)
(cond ((null? values) sexpr)
(else
(rewrite-for-rec symbol
(cdr values)
code
(cons sexpr
(quasiquote ((define ,symbol ,(car values)) ,code)))))))
(define (rewrite-for environment sexpr)
(let ((symbol (car sexpr))
(value (cadr sexpr))
(code (caddr sexpr)))
(rewrite-for-rec symbol (if (symbol? value) (hash-ref environment value) value) code (list))))
(rewriter-set! rewrite-for)
(define (consume-display environment output sexpr)
(let ((value (hash-ref environment (car sexpr))))
(output (if value value (format #f "{{ ~a }}" (symbol->string (car sexpr)))))))
(consumer-set! consume-display)
(define (rewrite-consume environment sexpr)
(hash-ref environment (car sexpr)))
(rewriter-set! rewrite-consume)
(define (consume filename)
(display (format #f "processing ~s\n" filename))
(let* ((basename (car (string-split filename #\.)))
(output-file (open-output-file (string-append basename ".html")))
(output (lambda (text) (display text output-file)))
(sexpr (file->sexpr filename))
(environment (make-hash-table)))
(consume-sexpr environment output sexpr)
(close output-file)))
(consume "index.sfx")