From 423ac382f9e73bf1ca7fc6b400f98db087cd7d22 Mon Sep 17 00:00:00 2001
From: Case Duckworth
Date: Wed, 5 Jun 2024 09:21:25 -0500
Subject: Write executable
This involved moving `src' to `lib' and making `bin'.
`bin' holds the program, which only imports `jimmy.main' from lib.
---
Makefile | 44 +++++++++++++++++-----------
bin/jimmy.scm | 48 ++++++++++++++++++++++++++++++
jimmy.egg | 25 ++++++++++++----
lib/emit.scm | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/html.scm | 61 ++++++++++++++++++++++++++++++++++++++
lib/main.scm | 19 ++++++++++++
lib/read.scm | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/util.scm | 49 +++++++++++++++++++++++++++++++
lib/wrap.scm | 21 +++++++++++++
src/emit.scm | 89 -------------------------------------------------------
src/html.scm | 61 --------------------------------------
src/read.scm | 88 -------------------------------------------------------
src/util.scm | 49 -------------------------------
src/wrap.scm | 23 ---------------
14 files changed, 426 insertions(+), 333 deletions(-)
create mode 100644 bin/jimmy.scm
create mode 100644 lib/emit.scm
create mode 100644 lib/html.scm
create mode 100644 lib/main.scm
create mode 100644 lib/read.scm
create mode 100644 lib/util.scm
create mode 100644 lib/wrap.scm
delete mode 100644 src/emit.scm
delete mode 100644 src/html.scm
delete mode 100644 src/read.scm
delete mode 100644 src/util.scm
delete mode 100644 src/wrap.scm
diff --git a/Makefile b/Makefile
index 8eead3a..d2a1003 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
NAME = jimmy
CSC = /usr/bin/csc
-CSC_OPTIONS = -setup-mode -host -I $(PWD) -C -I$(PWD)
+CSC_OPTIONS = -setup-mode -host -I $(PWD) -C -I$(BUILD)
CSC_LIB_OPTIONS = -D compiling-extension -emit-all-import-libraries -dynamic -regenerate-import-libraries
CSC_OPTIONS_EXTRA = -X utf8 -X module-declarations
CSI = /usr/bin/csi
@@ -12,7 +12,7 @@ TEST_ENV = env BUILD=$(BUILD) TESTS=$(TESTS)
TEST_ENV_EXTRA = TEST_USE_ANSI=0
.PHONY: all test clean install uninstall
-all: build/jimmy.util.so build/jimmy.read.so build/jimmy.emit.so build/jimmy.html.so build/jimmy.wrap.so
+all: build/jimmy.util.so build/jimmy.read.so build/jimmy.emit.so build/jimmy.html.so build/jimmy.wrap.so build/jimmy.main.so build/jimmy
test: all
cd $(BUILD) && $(TEST_ENV) $(TEST_ENV_EXTRA) $(CSI) -setup-mode -s $(TESTS)/run.scm $(NAME)
clean:
@@ -24,28 +24,38 @@ uninstall:
# jimmy
-build/jimmy.util.so: src/util.scm
+build/jimmy.util.so: lib/util.scm
@mkdir -p $(BUILD)
- cd $(BUILD) && \
- $(CSC) $(CSC_OPTIONS) $(CSC_LIB_OPTIONS) $(CSC_OPTIONS_EXTRA) ../$< -o $(@F)
+ $(CSC) $(CSC_OPTIONS) $(CSC_LIB_OPTIONS) $(CSC_OPTIONS_EXTRA) $< -o $@
@test -f jimmy.util.import.scm &&mv jimmy.util.import.scm $(BUILD)/||true
-build/jimmy.read.so: src/read.scm src/util.scm
+
+build/jimmy.read.so: lib/read.scm lib/util.scm
@mkdir -p $(BUILD)
- cd $(BUILD) && \
- $(CSC) $(CSC_OPTIONS) $(CSC_LIB_OPTIONS) $(CSC_OPTIONS_EXTRA) ../$< -o $(@F)
+ $(CSC) $(CSC_OPTIONS) $(CSC_LIB_OPTIONS) $(CSC_OPTIONS_EXTRA) $< -o $@
@test -f jimmy.read.import.scm &&mv jimmy.read.import.scm $(BUILD)/||true
-build/jimmy.emit.so: src/emit.scm src/util.scm
+
+build/jimmy.emit.so: lib/emit.scm lib/util.scm
@mkdir -p $(BUILD)
- cd $(BUILD) && \
- $(CSC) $(CSC_OPTIONS) $(CSC_LIB_OPTIONS) $(CSC_OPTIONS_EXTRA) ../$< -o $(@F)
+ $(CSC) $(CSC_OPTIONS) $(CSC_LIB_OPTIONS) $(CSC_OPTIONS_EXTRA) $< -o $@
@test -f jimmy.emit.import.scm &&mv jimmy.emit.import.scm $(BUILD)/||true
-build/jimmy.html.so: src/html.scm src/util.scm src/emit.scm
+
+build/jimmy.html.so: lib/html.scm lib/util.scm lib/emit.scm
@mkdir -p $(BUILD)
- cd $(BUILD) && \
- $(CSC) $(CSC_OPTIONS) $(CSC_LIB_OPTIONS) $(CSC_OPTIONS_EXTRA) ../$< -o $(@F)
+ $(CSC) $(CSC_OPTIONS) $(CSC_LIB_OPTIONS) $(CSC_OPTIONS_EXTRA) $< -o $@
@test -f jimmy.html.import.scm &&mv jimmy.html.import.scm $(BUILD)/||true
-build/jimmy.wrap.so: src/wrap.scm src/util.scm src/emit.scm
+
+build/jimmy.wrap.so: lib/wrap.scm lib/util.scm lib/emit.scm
@mkdir -p $(BUILD)
- cd $(BUILD) && \
- $(CSC) $(CSC_OPTIONS) $(CSC_LIB_OPTIONS) $(CSC_OPTIONS_EXTRA) ../$< -o $(@F)
+ $(CSC) $(CSC_OPTIONS) $(CSC_LIB_OPTIONS) $(CSC_OPTIONS_EXTRA) $< -o $@
@test -f jimmy.wrap.import.scm &&mv jimmy.wrap.import.scm $(BUILD)/||true
+
+build/jimmy.main.so: lib/main.scm lib/util.scm lib/emit.scm lib/read.scm lib/wrap.scm
+ @mkdir -p $(BUILD)
+ $(CSC) $(CSC_OPTIONS) $(CSC_LIB_OPTIONS) $(CSC_OPTIONS_EXTRA) $< -o $@
+ @test -f jimmy.main.import.scm &&mv jimmy.main.import.scm $(BUILD)/||true
+
+build/jimmy: bin/jimmy.scm lib/main.scm
+ @mkdir -p $(BUILD)
+ $(CSC) $(CSC_OPTIONS) $(CSC_OPTIONS_EXTRA) $< -o $@
+ @test -f jimmy.import.scm &&mv jimmy.import.scm $(BUILD)/||true
+
diff --git a/bin/jimmy.scm b/bin/jimmy.scm
new file mode 100644
index 0000000..17e12ba
--- /dev/null
+++ b/bin/jimmy.scm
@@ -0,0 +1,48 @@
+;;; (jimmy main) --- the program
+
+(import (chicken file)
+ (chicken port)
+ (chicken process-context)
+ (jimmy main)
+ args)
+
+(define opts
+ (list (args:make-option (t to) (required: "FORMAT")
+ (string-append "Translate input to FORMAT."
+ " One of `gemini', `html', or"
+ " a filename."))
+ (args:make-option (n no-extensions) #:none
+ "Don't use gemtext extensions.")
+ (args:make-option (T template) (required: "TEMPLATE")
+ "Wrap the generated text in TEMPLATE.")
+ (args:make-option (h help) #:none "Display this text"
+ (usage 0))))
+
+(define (usage #!optional (exit-code 1))
+ (with-output-to-port (current-error-port)
+ (lambda ()
+ (print "Usage: " (car (argv)) " [OPTIONS...] [FILE]")
+ (newline)
+ (print (args:usage options))
+ (print "Report bugs to acdw@acdw.net.")))
+ (exit exit-code))
+
+(define (main args)
+ (receive (options operands) (args:parse args opts)
+ (let ((to (alist-ref 'to options))
+ (template (alist-ref 'template options)))
+
+ (cond
+ ((not to)) ; default: gemini
+ ((equal? to "html")
+ (import (jimmy html)))
+ ((file-exists? to)
+ (load to))
+ (else (error "File does not exist" to)))
+
+ (print (apply jimmy (list (car operands) template))))))
+
+(cond-expand
+ (compiling
+ (main (command-line-arguments)))
+ (else))
diff --git a/jimmy.egg b/jimmy.egg
index 84bf83c..be5b680 100644
--- a/jimmy.egg
+++ b/jimmy.egg
@@ -2,6 +2,7 @@
(synopsis "The ssg king")
(license "BSD-3-clause")
(dependencies (chicken "5.3.0")
+ args ; for (jimmy main)
module-declarations
utf8)
(test-dependencies test)
@@ -10,22 +11,34 @@
(components
;; Utility library
(extension jimmy.util
- (source src/util.scm))
+ (source lib/util.scm))
;; Read gemini files into internal format
(extension jimmy.read
- (source src/read.scm)
+ (source lib/read.scm)
(component-dependencies jimmy.util))
;; Emit the output format (includes gemini)
(extension jimmy.emit
- (source src/emit.scm)
+ (source lib/emit.scm)
(component-dependencies jimmy.util))
;; Emit HTML -- import this *after* emit (is this the best way?)
(extension jimmy.html
- (source src/html.scm)
+ (source lib/html.scm)
(component-dependencies jimmy.util
jimmy.emit))
;; Wrap output in templates
(extension jimmy.wrap
- (source src/wrap.scm)
+ (source lib/wrap.scm)
(component-dependencies jimmy.util
- jimmy.emit))))
+ jimmy.emit))
+ ;; Main entry point (for command line)
+ (extension jimmy.main
+ (source lib/main.scm)
+ (component-dependencies jimmy.util
+ jimmy.emit
+ jimmy.read
+ jimmy.wrap))
+ ;; Command-line program
+ (program jimmy
+ (csc-options -static)
+ (source bin/jimmy.scm)
+ (component-dependencies jimmy.main))))
diff --git a/lib/emit.scm b/lib/emit.scm
new file mode 100644
index 0000000..2a8ab97
--- /dev/null
+++ b/lib/emit.scm
@@ -0,0 +1,94 @@
+(declare (module (jimmy emit)))
+
+(import scheme (chicken base)
+ (chicken format)
+ (chicken irregex)
+ (chicken port)
+ (chicken string)
+ (only utf8-srfi-13 string-join)
+ (jimmy util))
+
+(define-public (emit doc)
+ (for-each display (map format-stanza doc)))
+
+(define-public (emit-string doc)
+ (with-output-to-string
+ (lambda () (emit doc))))
+
+(define-public formats
+ (make-parameter
+ ;; (TYPE (line . LINE-FMT) (stanza . STANZA-FMT) (inline . INLINE-FMT))
+ '((para (line . "~A")
+ (stanza . "~A~%~%"))
+ (verb (line . "~A~%")
+ (stanza . "```~%~A```~%~%"))
+ (link (line . "=> ~A ~A~%") ; Note: link has 2 format arguments
+ (stanza . "~A~%")
+ (inline . "~%=> ~A ~A~%"))
+ (list (line . "* ~A~%")
+ (stanza . "~A~%"))
+ (quot (line . "~A")
+ (stanza . "> ~A~%~%"))
+ (hdr1 (line . "# ~A~%")
+ (stanza . "~A~%"))
+ (hdr2 (line . "## ~A~%")
+ (stanza . "~A~%"))
+ (hdr3 (line . "### ~A~%")
+ (stanza . "~A~%")))))
+
+(define-public filters
+ (make-parameter
+ ;; (TYPE (line . LINE-FILTER) (stanza . STANZA-FILTER))
+ ;; line-filter : (lambda (list-of-strs) ...) -> list-of-strs (for format)
+ ;; stanza-filter : (lambda (list-of-strs) ...) -> str
+ `((verb (line . ,identity)
+ (stanza . ,join-lines))
+ (default
+ (line . ,identity)
+ (stanza . ,flush-lines-left)))))
+
+(define (format-line line el)
+ (cond
+ ((string? (car line)) ; regular stanza line
+ (sprintf* (get-format el 'line)
+ ((get-filter el 'line) line)))
+ ((symbol? (car line)) ; inline element
+ (sprintf* (get-format (car line) 'inline)
+ ((get-filter (car line) 'line) (cdr line))))
+ (else (error "Malformed line" line))))
+
+(define (format-stanza stanza)
+ (let* ((type (car stanza))
+ (data (cdr stanza))
+ (text (map (lambda (ln)
+ (format-line ln type))
+ data)))
+ (sprintf (get-format type 'stanza)
+ ((get-filter type 'stanza) text))))
+
+;;; Utilities
+
+(define (get-from alist el scope)
+ (or (alist-walk alist el scope)
+ (alist-walk alist 'default scope)
+ (and (eq? scope 'inline)
+ (alist-walk alist 'default 'line))))
+
+(define (get-format el scope)
+ (or (get-from (formats) el scope)
+ ""))
+(define (get-filter el scope) (get-from (filters) el scope))
+
+(define (sprintf* fmt lis)
+ (let loop ((num (length (irregex-extract "~[aA]" fmt)))
+ (lis lis)
+ (out '()))
+ (cond
+ ((null? lis)
+ (apply sprintf fmt (reverse out)))
+ ((= 1 num)
+ (loop 0 '() (cons (string-join lis) out)))
+ (else
+ (loop (- num 1)
+ (cdr lis)
+ (cons (car lis) out))))))
diff --git a/lib/html.scm b/lib/html.scm
new file mode 100644
index 0000000..07cd921
--- /dev/null
+++ b/lib/html.scm
@@ -0,0 +1,61 @@
+(declare (module (jimmy html)))
+
+(import scheme (chicken base)
+ (chicken irregex)
+ (jimmy emit)
+ (jimmy util))
+
+(define (escape-entities s)
+ (irregex-replace/all "[&<>]" s
+ (lambda (m)
+ (let ((c (irregex-match-substring m)))
+ (cond
+ ((equal? c "&") "&")
+ ((equal? c "<") "<")
+ ((equal? c ">") ">"))))))
+
+(define (add-inline-markup s)
+ (define (char->tag ch tag)
+ (lambda (s)
+ (irregex-replace/all `(: ,ch ($ (* (~ ,ch))) ,ch) s
+ "<" tag ">" 1 "" tag ">")))
+
+ ((o (char->tag "*" "b")
+ (char->tag "_" "i")
+ (char->tag "`" "code")) s))
+
+(formats
+ '((para (line . "~a~%")
+ (stanza . "
~% ~a
~%"))
+ (verb (line . "~a~%")
+ (stanza . "~a
~%"))
+ (link (line . "~a~%")
+ (stanza . "~%")
+ (inline . "~a~%"))
+ (list (line . "~a~%")
+ (stanza . "~%"))
+ (quot (line . "~a~%")
+ (stanza . "~% ~a
~%"))
+ (hdr1 (line . "~a")
+ (stanza . "~a
~%"))
+ (hdr2 (line . "~a")
+ (stanza . "~a
~%"))
+ (hdr3 (line . "~a")
+ (stanza . "~a
~%"))))
+
+(filters
+ `((verb (line . ,identity)
+ (stanza . ,join-lines))
+ (link (line . ,(lambda (ln)
+ (cons (car ln)
+ ((o list
+ add-inline-markup
+ escape-entities
+ string-join)
+ (cdr ln))))))
+ (default
+ (line . ,(o list
+ add-inline-markup
+ escape-entities
+ string-join))
+ (stanza . ,string-join))))
diff --git a/lib/main.scm b/lib/main.scm
new file mode 100644
index 0000000..b97d66a
--- /dev/null
+++ b/lib/main.scm
@@ -0,0 +1,19 @@
+(declare (module (jimmy main)))
+
+(import scheme (chicken base)
+ (chicken port)
+ (jimmy util)
+ (jimmy read)
+ (jimmy emit)
+ (jimmy wrap))
+
+(define-public (jimmy #!optional file template)
+ (parameterize ((current-input-port
+ (if file
+ (open-input-file file)
+ (current-input-port))))
+ (let ((doc (parse))
+ (post-proc (if template
+ (cut wrap-with <> template)
+ emit-string)))
+ (post-proc doc))))
diff --git a/lib/read.scm b/lib/read.scm
new file mode 100644
index 0000000..1b611bb
--- /dev/null
+++ b/lib/read.scm
@@ -0,0 +1,88 @@
+(declare (module (jimmy read)))
+
+(import scheme (chicken base)
+ (jimmy util)
+ (only (chicken io) read-lines)
+ (only (chicken string) string-split))
+
+(define-public line-types
+ ;; (sigil type inlines word-select)
+ `((default para (link) ,identity) ; if nothing else matches
+ ("```" verb)
+ ("=>" link)
+ (">" quot)
+ ("#" hdr1)
+ ("##" hdr2)
+ ("###" hdr3)
+ ("*" list)
+ ;; extra!
+ (":" meta)))
+
+(define-public (parse #!optional port)
+ (parse-lines (read-lines (or port (current-input-port))) '()))
+
+(define (line-type line)
+ (let ((lin (if (string? line) (string-split line) line))
+ (def (cdr (assoc 'default line-types))))
+ (cond
+ ((null? lin) def) ; empty line
+ ((assoc (car lin) line-types) => cdr) ; a line type exists
+ (else def)))) ; otherwise ...
+
+(define (parse-lines lines doc)
+ (if (null? lines) (reverse doc)
+ (let ((words (string-split (car lines))))
+ (cond
+ ((null? words) ; empty line
+ (parse-lines (cdr lines) doc))
+ ((equal? (car words) "```") ; verbatim
+ ;; Format for verbatim header:
+ ;; ``` ?html | command ...
+ ;; -- only run command on block with html output.
+ ;; other outputs process the block normally
+ ;; ``` ?!html | command ...
+ ;; -- only run command on block when *not* outputting html.
+ ;; html processes the block normally
+ ;; ``` ?:html | command ...
+ ;; -- like ?html, but ignore the block in non-html outputs.
+ ;;;; FIXME: I think this necessitates a special emit-verbatim
+ ;;;; function.
+ (parse-verbatim (cdr lines) doc '()
+ #; (if (< 1 (length words))
+ (cons 'verb (cdr words))
+ 'verb)
+ 'verb))
+ (else ; another line type
+ (apply parse-stanza lines doc '() (line-type words)))))))
+
+(define (parse-verbatim lines doc block bhead)
+ (define (close-verbatim) (cons (cons bhead (reverse block)) doc))
+ (cond
+ ((null? lines) ; end of document
+ (parse-lines lines (close-verbatim)))
+ ((equal? (car lines) "```") ; end of verbatim block
+ (parse-lines (cdr lines) (close-verbatim)))
+ (else ; verbatim block continues
+ (parse-verbatim (cdr lines) doc (cons (list (car lines)) block) bhead))))
+
+(define (parse-stanza lines doc stanza st-type
+ #!optional (st-inlines '()) (st-words cdr))
+ (define (close-stanza) (cons (cons st-type (reverse stanza)) doc))
+ (if (null? lines) ; end of document
+ (parse-lines lines (close-stanza))
+ (let* ((ln (car lines))
+ (ws (string-split ln))
+ (lt (line-type ln)))
+ (cond
+ ((null? ws) ; end of stanza (blank line)
+ (parse-lines (cdr lines) (close-stanza)))
+ ((memq (car lt) st-inlines) ; in-line for *this* stanza
+ (parse-stanza (cdr lines) doc
+ (cons (cons (car lt) (cdr ws)) stanza)
+ st-type st-inlines st-words))
+ ((not (eq? st-type (car (line-type ws)))) ; beginning of a new stanza
+ (parse-lines lines (close-stanza)))
+ (else ; continue this stanza
+ (parse-stanza (cdr lines) doc
+ (cons (st-words ws) stanza)
+ st-type st-inlines st-words))))))
diff --git a/lib/util.scm b/lib/util.scm
new file mode 100644
index 0000000..c71c600
--- /dev/null
+++ b/lib/util.scm
@@ -0,0 +1,49 @@
+(module (jimmy util) *
+
+ (import scheme (chicken base)
+ (chicken condition)
+ (only (chicken irregex) irregex-replace/all)
+ (chicken string))
+
+ (define-syntax define-public
+ (syntax-rules ()
+ ((define-public (name . arg) forms ...)
+ (begin (export name)
+ (define (name . arg) forms ...)))
+ ((define-public (name args ...) forms ...)
+ (begin (export name)
+ (define (name args ...) forms ...)))
+ ((define-public name value)
+ (begin (export name)
+ (define name value)))))
+
+ (define-syntax ignore-errors
+ (syntax-rules ()
+ ((ignore-errors x)
+ (handle-exceptions e #f x))))
+
+ (define (alist-walk lis . keys)
+ (if (null? keys)
+ lis
+ (let ((kv (assoc (car keys) lis)))
+ (cond
+ ((not kv) #f)
+ ((atom? (cdr kv))
+ (and (null? (cdr keys)) ; this shouldn't error...
+ (cdr kv)))
+ ((list? (cdr kv))
+ (apply alist-walk (cdr kv) (cdr keys)))))))
+
+ (define (string-join ss #!optional (sep " "))
+ (string-intersperse ss sep))
+
+ (define (flush-lines-left lines)
+ (irregex-replace/all '(: bol (* space))
+ (string-join lines) ""))
+
+ (define (join-lines lines)
+ (apply string-append lines))
+
+ )
+
+
diff --git a/lib/wrap.scm b/lib/wrap.scm
new file mode 100644
index 0000000..f801029
--- /dev/null
+++ b/lib/wrap.scm
@@ -0,0 +1,21 @@
+(declare (module (jimmy wrap)))
+
+(import scheme (chicken base)
+ (jimmy emit)
+ (jimmy util)
+ (only (chicken io) read-string)
+ (only (chicken port) with-output-to-string)
+ (only (chicken string) string-translate* string-intersperse))
+
+;; templates are strings with variables interpolated with "{{variables}}"
+
+(define-public (wrap document template)
+ (let* ((meta (map (lambda (el)
+ (cons (string-append "{{" (car el) "}}")
+ (string-intersperse (cdr el) " ")))
+ (alist-walk document 'meta)))
+ (body (cons "{{body}}" (emit-string document))))
+ (string-translate* template (cons body meta))))
+
+(define-public (wrap-with document file)
+ (wrap document (with-input-from-file file read-string)))
diff --git a/src/emit.scm b/src/emit.scm
deleted file mode 100644
index 4c3581f..0000000
--- a/src/emit.scm
+++ /dev/null
@@ -1,89 +0,0 @@
-(declare (module (jimmy emit)))
-
-(import scheme (chicken base)
- (chicken format)
- (chicken irregex)
- (chicken string)
- (only utf8-srfi-13 string-join)
- (jimmy util))
-
-(define-public (emit doc)
- (for-each display (map format-stanza doc)))
-
-(define-public formats
- (make-parameter
- ;; (TYPE (line . LINE-FMT) (stanza . STANZA-FMT) (inline . INLINE-FMT))
- '((para (line . "~A")
- (stanza . "~A~%~%"))
- (verb (line . "~A~%")
- (stanza . "```~%~A```~%~%"))
- (link (line . "=> ~A ~A~%") ; Note: link has 2 format arguments
- (stanza . "~A~%")
- (inline . "~%=> ~A ~A~%"))
- (list (line . "* ~A~%")
- (stanza . "~A~%"))
- (quot (line . "~A")
- (stanza . "> ~A~%~%"))
- (hdr1 (line . "# ~A~%")
- (stanza . "~A~%"))
- (hdr2 (line . "## ~A~%")
- (stanza . "~A~%"))
- (hdr3 (line . "### ~A~%")
- (stanza . "~A~%")))))
-
-(define-public filters
- (make-parameter
- ;; (TYPE (line . LINE-FILTER) (stanza . STANZA-FILTER))
- ;; line-filter : (lambda (list-of-strs) ...) -> list-of-strs (for format)
- ;; stanza-filter : (lambda (list-of-strs) ...) -> str
- `((verb (line . ,identity)
- (stanza . ,join-lines))
- (default
- (line . ,identity)
- (stanza . ,flush-lines-left)))))
-
-(define (format-line line el)
- (cond
- ((string? (car line)) ; regular stanza line
- (sprintf* (get-format el 'line)
- ((get-filter el 'line) line)))
- ((symbol? (car line)) ; inline element
- (sprintf* (get-format (car line) 'inline)
- ((get-filter (car line) 'line) (cdr line))))
- (else (error "Malformed line" line))))
-
-(define (format-stanza stanza)
- (let* ((type (car stanza))
- (data (cdr stanza))
- (text (map (lambda (ln)
- (format-line ln type))
- data)))
- (sprintf (get-format type 'stanza)
- ((get-filter type 'stanza) text))))
-
-;;; Utilities
-
-(define (get-from alist el scope)
- (or (alist-walk alist el scope)
- (alist-walk alist 'default scope)
- (and (eq? scope 'inline)
- (alist-walk alist 'default 'line))))
-
-(define (get-format el scope)
- (or (get-from (formats) el scope)
- ""))
-(define (get-filter el scope) (get-from (filters) el scope))
-
-(define (sprintf* fmt lis)
- (let loop ((num (length (irregex-extract "~[aA]" fmt)))
- (lis lis)
- (out '()))
- (cond
- ((null? lis)
- (apply sprintf fmt (reverse out)))
- ((= 1 num)
- (loop 0 '() (cons (string-join lis) out)))
- (else
- (loop (- num 1)
- (cdr lis)
- (cons (car lis) out))))))
diff --git a/src/html.scm b/src/html.scm
deleted file mode 100644
index 07cd921..0000000
--- a/src/html.scm
+++ /dev/null
@@ -1,61 +0,0 @@
-(declare (module (jimmy html)))
-
-(import scheme (chicken base)
- (chicken irregex)
- (jimmy emit)
- (jimmy util))
-
-(define (escape-entities s)
- (irregex-replace/all "[&<>]" s
- (lambda (m)
- (let ((c (irregex-match-substring m)))
- (cond
- ((equal? c "&") "&")
- ((equal? c "<") "<")
- ((equal? c ">") ">"))))))
-
-(define (add-inline-markup s)
- (define (char->tag ch tag)
- (lambda (s)
- (irregex-replace/all `(: ,ch ($ (* (~ ,ch))) ,ch) s
- "<" tag ">" 1 "" tag ">")))
-
- ((o (char->tag "*" "b")
- (char->tag "_" "i")
- (char->tag "`" "code")) s))
-
-(formats
- '((para (line . "~a~%")
- (stanza . "~% ~a
~%"))
- (verb (line . "~a~%")
- (stanza . "~a
~%"))
- (link (line . "~a~%")
- (stanza . "~%")
- (inline . "~a~%"))
- (list (line . "~a~%")
- (stanza . "~%"))
- (quot (line . "~a~%")
- (stanza . "~% ~a
~%"))
- (hdr1 (line . "~a")
- (stanza . "~a
~%"))
- (hdr2 (line . "~a")
- (stanza . "~a
~%"))
- (hdr3 (line . "~a")
- (stanza . "~a
~%"))))
-
-(filters
- `((verb (line . ,identity)
- (stanza . ,join-lines))
- (link (line . ,(lambda (ln)
- (cons (car ln)
- ((o list
- add-inline-markup
- escape-entities
- string-join)
- (cdr ln))))))
- (default
- (line . ,(o list
- add-inline-markup
- escape-entities
- string-join))
- (stanza . ,string-join))))
diff --git a/src/read.scm b/src/read.scm
deleted file mode 100644
index 1b611bb..0000000
--- a/src/read.scm
+++ /dev/null
@@ -1,88 +0,0 @@
-(declare (module (jimmy read)))
-
-(import scheme (chicken base)
- (jimmy util)
- (only (chicken io) read-lines)
- (only (chicken string) string-split))
-
-(define-public line-types
- ;; (sigil type inlines word-select)
- `((default para (link) ,identity) ; if nothing else matches
- ("```" verb)
- ("=>" link)
- (">" quot)
- ("#" hdr1)
- ("##" hdr2)
- ("###" hdr3)
- ("*" list)
- ;; extra!
- (":" meta)))
-
-(define-public (parse #!optional port)
- (parse-lines (read-lines (or port (current-input-port))) '()))
-
-(define (line-type line)
- (let ((lin (if (string? line) (string-split line) line))
- (def (cdr (assoc 'default line-types))))
- (cond
- ((null? lin) def) ; empty line
- ((assoc (car lin) line-types) => cdr) ; a line type exists
- (else def)))) ; otherwise ...
-
-(define (parse-lines lines doc)
- (if (null? lines) (reverse doc)
- (let ((words (string-split (car lines))))
- (cond
- ((null? words) ; empty line
- (parse-lines (cdr lines) doc))
- ((equal? (car words) "```") ; verbatim
- ;; Format for verbatim header:
- ;; ``` ?html | command ...
- ;; -- only run command on block with html output.
- ;; other outputs process the block normally
- ;; ``` ?!html | command ...
- ;; -- only run command on block when *not* outputting html.
- ;; html processes the block normally
- ;; ``` ?:html | command ...
- ;; -- like ?html, but ignore the block in non-html outputs.
- ;;;; FIXME: I think this necessitates a special emit-verbatim
- ;;;; function.
- (parse-verbatim (cdr lines) doc '()
- #; (if (< 1 (length words))
- (cons 'verb (cdr words))
- 'verb)
- 'verb))
- (else ; another line type
- (apply parse-stanza lines doc '() (line-type words)))))))
-
-(define (parse-verbatim lines doc block bhead)
- (define (close-verbatim) (cons (cons bhead (reverse block)) doc))
- (cond
- ((null? lines) ; end of document
- (parse-lines lines (close-verbatim)))
- ((equal? (car lines) "```") ; end of verbatim block
- (parse-lines (cdr lines) (close-verbatim)))
- (else ; verbatim block continues
- (parse-verbatim (cdr lines) doc (cons (list (car lines)) block) bhead))))
-
-(define (parse-stanza lines doc stanza st-type
- #!optional (st-inlines '()) (st-words cdr))
- (define (close-stanza) (cons (cons st-type (reverse stanza)) doc))
- (if (null? lines) ; end of document
- (parse-lines lines (close-stanza))
- (let* ((ln (car lines))
- (ws (string-split ln))
- (lt (line-type ln)))
- (cond
- ((null? ws) ; end of stanza (blank line)
- (parse-lines (cdr lines) (close-stanza)))
- ((memq (car lt) st-inlines) ; in-line for *this* stanza
- (parse-stanza (cdr lines) doc
- (cons (cons (car lt) (cdr ws)) stanza)
- st-type st-inlines st-words))
- ((not (eq? st-type (car (line-type ws)))) ; beginning of a new stanza
- (parse-lines lines (close-stanza)))
- (else ; continue this stanza
- (parse-stanza (cdr lines) doc
- (cons (st-words ws) stanza)
- st-type st-inlines st-words))))))
diff --git a/src/util.scm b/src/util.scm
deleted file mode 100644
index c71c600..0000000
--- a/src/util.scm
+++ /dev/null
@@ -1,49 +0,0 @@
-(module (jimmy util) *
-
- (import scheme (chicken base)
- (chicken condition)
- (only (chicken irregex) irregex-replace/all)
- (chicken string))
-
- (define-syntax define-public
- (syntax-rules ()
- ((define-public (name . arg) forms ...)
- (begin (export name)
- (define (name . arg) forms ...)))
- ((define-public (name args ...) forms ...)
- (begin (export name)
- (define (name args ...) forms ...)))
- ((define-public name value)
- (begin (export name)
- (define name value)))))
-
- (define-syntax ignore-errors
- (syntax-rules ()
- ((ignore-errors x)
- (handle-exceptions e #f x))))
-
- (define (alist-walk lis . keys)
- (if (null? keys)
- lis
- (let ((kv (assoc (car keys) lis)))
- (cond
- ((not kv) #f)
- ((atom? (cdr kv))
- (and (null? (cdr keys)) ; this shouldn't error...
- (cdr kv)))
- ((list? (cdr kv))
- (apply alist-walk (cdr kv) (cdr keys)))))))
-
- (define (string-join ss #!optional (sep " "))
- (string-intersperse ss sep))
-
- (define (flush-lines-left lines)
- (irregex-replace/all '(: bol (* space))
- (string-join lines) ""))
-
- (define (join-lines lines)
- (apply string-append lines))
-
- )
-
-
diff --git a/src/wrap.scm b/src/wrap.scm
deleted file mode 100644
index aa077d8..0000000
--- a/src/wrap.scm
+++ /dev/null
@@ -1,23 +0,0 @@
-(declare (module (jimmy wrap)))
-
-(import scheme (chicken base)
- (jimmy emit)
- (jimmy util)
- (only (chicken io) read-string)
- (only (chicken port) with-output-to-string)
- (only (chicken string) string-translate* string-intersperse))
-
-;; templates are strings with variables interpolated with "{{variables}}"
-
-(define-public (wrap document template)
- (let* ((meta (map (lambda (el)
- (cons (string-append "{{" (car el) "}}")
- (string-intersperse (cdr el) " ")))
- (alist-walk document 'meta)))
- (body (cons "{{body}}"
- (with-output-to-string
- (lambda () (emit document))))))
- (string-translate* template (cons body meta))))
-
-(define-public (wrap-with document file)
- (wrap document (with-input-from-file file read-string)))
--
cgit 1.4.1-21-gabe81