diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/emit.scm | 61 | ||||
-rw-r--r-- | src/read.scm | 95 | ||||
-rw-r--r-- | src/wrap.scm | 20 |
3 files changed, 99 insertions, 77 deletions
diff --git a/src/emit.scm b/src/emit.scm index aa36eb5..d6fe19e 100644 --- a/src/emit.scm +++ b/src/emit.scm | |||
@@ -34,18 +34,6 @@ | |||
34 | (line . "~A") | 34 | (line . "~A") |
35 | (block . "~A~%~%")))) | 35 | (block . "~A~%~%")))) |
36 | 36 | ||
37 | (define (string-join ss #!optional sep) | ||
38 | (if (string? ss) ss | ||
39 | (string-intersperse ss (or sep " ")))) | ||
40 | |||
41 | (define (char->tag char beg end) | ||
42 | (lambda (str) | ||
43 | (irregex-replace/all `(: ($ (or bos space)) | ||
44 | ,char ($ (+ (~ ,char))) ,char | ||
45 | ($ (or space eos))) | ||
46 | str | ||
47 | 1 beg 2 end 3))) | ||
48 | |||
49 | (define-public filters | 37 | (define-public filters |
50 | `((para | 38 | `((para |
51 | (line . ,(o (char->tag "*" "<strong>" "</strong>") | 39 | (line . ,(o (char->tag "*" "<strong>" "</strong>") |
@@ -58,16 +46,27 @@ | |||
58 | (line . ,(lambda (ln) | 46 | (line . ,(lambda (ln) |
59 | (let ((ws (cond ((list? ln) ln) | 47 | (let ((ws (cond ((list? ln) ln) |
60 | ((string? ln) (string-split ln))))) | 48 | ((string? ln) (string-split ln))))) |
61 | (list (car ws) (string-join (cdr ws))))))) | 49 | (let ((x (list (car ws) (string-join (cdr ws))))) |
50 | x))))) | ||
62 | (default | 51 | (default |
63 | (line . ,list) | 52 | (line . ,(lambda (x) (print x) (if (list? x) x (list x)))) |
64 | (block . ,identity)))) | 53 | (block . ,identity)))) |
65 | 54 | ||
55 | (define (string-join ss #!optional sep) | ||
56 | (if (string? ss) ss | ||
57 | (string-intersperse ss (or sep " ")))) | ||
58 | |||
59 | (define (char->tag char beg end) | ||
60 | (lambda (str) | ||
61 | (irregex-replace/all `(: ($ (or bos space)) | ||
62 | ,char ($ (+ (~ ,char))) ,char | ||
63 | ($ (or space eos))) | ||
64 | str | ||
65 | 1 beg 2 end 3))) | ||
66 | |||
66 | (define (get-from from type subtype) | 67 | (define (get-from from type subtype) |
67 | (or (alist-walk from type subtype) | 68 | (or (alist-walk from type subtype) |
68 | (if (eq? subtype 'inline) | 69 | (get-from from 'default subtype))) |
69 | (alist-walk from type 'list) | ||
70 | (lambda _ '(""))))) | ||
71 | 70 | ||
72 | (define (get-format type subtype) (get-from formats type subtype)) | 71 | (define (get-format type subtype) (get-from formats type subtype)) |
73 | (define (get-filter type subtype) (get-from filters type subtype)) | 72 | (define (get-filter type subtype) (get-from filters type subtype)) |
@@ -76,19 +75,19 @@ | |||
76 | (cond | 75 | (cond |
77 | ;; if LINE is a string, wrap it in a list | 76 | ;; if LINE is a string, wrap it in a list |
78 | ((string? line) | 77 | ((string? line) |
79 | (set! line (list line))) | 78 | (sprintf (get-format type 'line) |
79 | ((get-filter type 'line) line))) | ||
80 | ;; if it's a list of strings, join them together and filter them | 80 | ;; if it's a list of strings, join them together and filter them |
81 | ((and (list? line) | 81 | ((and (list? line) |
82 | (string? (car line))) | 82 | (string? (car line))) |
83 | (set! line ((get-filter type 'line) line))) | 83 | (sprintf (get-format type 'line) |
84 | (apply string-append ((get-filter type 'line) line)))) | ||
84 | ;; if the car of LINE is a symbol, it's an inline thing. | 85 | ;; if the car of LINE is a symbol, it's an inline thing. |
85 | ((and (list? line) | 86 | ((and (list? line) |
86 | (symbol? (car line))) | 87 | (symbol? (car line))) |
87 | (set! line (format-line (get-format (car line) 'inline) | 88 | (sprintf* (get-format (car line) 'inline) |
88 | ((get-filter (car line) 'line) (cdr line)) | 89 | ((get-filter (car line) 'line) (cdr line)))) |
89 | type))) | 90 | (else (error "Malformed line" line)))) |
90 | (else (error "Malformed line" line))) | ||
91 | (apply sprintf fmt line)) | ||
92 | 91 | ||
93 | (define (format-block block) | 92 | (define (format-block block) |
94 | (if (assq (car block) formats) | 93 | (if (assq (car block) formats) |
@@ -107,3 +106,17 @@ | |||
107 | (sprintf (get-format type 'block) | 106 | (sprintf (get-format type 'block) |
108 | ((get-filter type 'block) text))) | 107 | ((get-filter type 'block) text))) |
109 | "")) | 108 | "")) |
109 | |||
110 | (define (sprintf* fmt lis) | ||
111 | (let loop ((num (length (irregex-extract "~[aA]" fmt))) | ||
112 | (lis lis) | ||
113 | (out '())) | ||
114 | (cond | ||
115 | ((null? lis) | ||
116 | (apply sprintf fmt (reverse out))) | ||
117 | ((= 1 num) | ||
118 | (loop 0 '() (cons (string-join lis) out))) | ||
119 | (else | ||
120 | (loop (- num 1) | ||
121 | (cdr lis) | ||
122 | (cons (car lis) out)))))) | ||
diff --git a/src/read.scm b/src/read.scm index 00ffad4..5e655a7 100644 --- a/src/read.scm +++ b/src/read.scm | |||
@@ -2,73 +2,72 @@ | |||
2 | 2 | ||
3 | (import scheme (chicken base) | 3 | (import scheme (chicken base) |
4 | (jimmy util) | 4 | (jimmy util) |
5 | (only (chicken condition) handle-exceptions) | ||
6 | (only (chicken io) read-lines) | 5 | (only (chicken io) read-lines) |
7 | (only (chicken string) string-split)) | 6 | (only (chicken string) string-split)) |
8 | 7 | ||
9 | (define-public line-types | 8 | (define-public line-types |
10 | ;; (sigil type inlines preproc) | 9 | ;; (sigil type inlines word-select) |
11 | '(("=>" link) | 10 | `((default para (link) ,identity) ; if nothing else matches |
11 | ("```" verb) | ||
12 | ("=>" link) | ||
12 | (">" quot) | 13 | (">" quot) |
13 | ("#" hdr1) | 14 | ("#" hdr1) |
14 | ("##" hdr2) | 15 | ("##" hdr2) |
15 | ("###" hdr3) | 16 | ("###" hdr3) |
16 | ("*" list) | 17 | ("*" list) |
17 | ("```" verb) | ||
18 | ;; extra! | 18 | ;; extra! |
19 | (":" meta))) | 19 | (":" meta))) |
20 | 20 | ||
21 | (define-public (parse inport) | 21 | (define-public (parse #!optional port) |
22 | (parse-lines (read-lines inport) '())) | 22 | (parse-lines (read-lines (or port (current-input-port))) '())) |
23 | 23 | ||
24 | (define (line-type line) | 24 | (define (line-type line) |
25 | (let ((it (assoc (car (string-split line)) line-types))) | 25 | (let ((lin (if (string? line) (string-split line) line)) |
26 | (if it (cadr it) | 26 | (def (cdr (assoc 'default line-types)))) |
27 | 'para))) | 27 | (cond |
28 | ((null? lin) def) ; empty line | ||
29 | ((assoc (car lin) line-types) => cdr) ; a line type exists | ||
30 | (else def)))) ; otherwise ... | ||
28 | 31 | ||
29 | (define (parse-lines lines document) | 32 | (define (parse-lines lines doc) |
30 | (if (null? lines) (reverse document) | 33 | (if (null? lines) (reverse doc) |
31 | (let ((words (string-split (car lines)))) | 34 | (let ((words (string-split (car lines)))) |
32 | (cond | 35 | (cond |
33 | ((null? words) | 36 | ((null? words) ; empty line |
34 | (parse-lines (cdr lines) document)) | 37 | (parse-lines (cdr lines) doc)) |
35 | ((equal? (car words) "```") | 38 | ((equal? (car words) "```") ; verbatim |
36 | (parse-verbatim (cdr lines) document '())) | 39 | (parse-verbatim (cdr lines) doc '())) |
37 | ((assoc (car words) line-types) | 40 | (else ; another line type |
38 | => (lambda (it) | 41 | (apply parse-stanza lines doc '() (line-type words))))))) |
39 | (apply parse-block lines document '() (cdr it)))) | ||
40 | (else | ||
41 | (parse-block lines document '() 'para '(link) identity)))))) | ||
42 | 42 | ||
43 | (define (parse-verbatim lines document verb) | 43 | (define (parse-verbatim lines doc block) |
44 | (define (close-verbatim) (cons (cons 'verb (reverse block)) doc)) | ||
44 | (cond | 45 | (cond |
45 | ((null? lines) | 46 | ((null? lines) ; end of document |
46 | (parse-lines lines (cons (cons 'verb (reverse verb)) document))) | 47 | (parse-lines lines (close-verbatim))) |
47 | ((equal? (car lines) "```") | 48 | ((equal? (car lines) "```") ; end of verbatim block |
48 | (parse-lines (cdr lines) (cons (cons 'verb (reverse verb)) document))) | 49 | (parse-lines (cdr lines) (close-verbatim))) |
49 | (else | 50 | (else ; verbatim block continues |
50 | (parse-verbatim (cdr lines) document (cons (car lines) verb))))) | 51 | (parse-verbatim (cdr lines) doc (cons (car lines) block))))) |
51 | 52 | ||
52 | (define (parse-block lines document block type #!optional inlines preproc) | 53 | (define (parse-stanza lines doc stanza st-type |
53 | (let ((inlines (or inlines '())) | 54 | #!optional (st-inlines '()) (st-words cdr)) |
54 | (preproc (or preproc (lambda (ln) (cdr (string-split ln)))))) | 55 | (define (close-stanza) (cons (cons st-type (reverse stanza)) doc)) |
55 | (cond | 56 | (if (null? lines) ; end of document |
56 | ((null? lines) | 57 | (parse-lines lines (close-stanza)) |
57 | (parse-lines lines (cons (cons type (reverse block)) document))) | ||
58 | ((equal? (car lines) "") | ||
59 | (parse-lines (cdr lines) (cons (cons type (reverse block)) document))) | ||
60 | ((and (not (eq? type (line-type (car lines)))) | ||
61 | (not (memq (line-type (car lines)) inlines))) | ||
62 | (parse-lines lines (cons (cons type (reverse block)) document))) | ||
63 | ((memq (line-type (car lines)) inlines) | ||
64 | (let* ((ln (car lines)) | 58 | (let* ((ln (car lines)) |
65 | (ws (string-split ln)) | 59 | (ws (string-split ln)) |
66 | (lt (cdr (assoc (car ws) line-types)))) | 60 | (lt (line-type ln))) |
67 | (parse-block (cdr lines) document | 61 | (cond |
68 | (cons (cons (car lt) | 62 | ((null? ws) ; end of stanza (blank line) |
69 | ((or (ignore-errors (caddr lt)) cdr) ws)) | 63 | (parse-lines (cdr lines) (close-stanza))) |
70 | block) | 64 | ((memq (car lt) st-inlines) ; in-line for *this* stanza |
71 | type inlines preproc))) | 65 | (parse-stanza (cdr lines) doc |
72 | (else | 66 | (cons (cons (car lt) (cdr ws)) stanza) |
73 | (parse-block (cdr lines) document (cons (preproc (car lines)) block) | 67 | st-type st-inlines st-words)) |
74 | type inlines preproc))))) | 68 | ((not (eq? st-type (car (line-type ws)))) ; beginning of a new stanza |
69 | (parse-lines lines (close-stanza))) | ||
70 | (else ; continue this stanza | ||
71 | (parse-stanza (cdr lines) doc | ||
72 | (cons (st-words ws) stanza) | ||
73 | st-type st-inlines st-words)))))) | ||
diff --git a/src/wrap.scm b/src/wrap.scm index 3537dea..0ed8868 100644 --- a/src/wrap.scm +++ b/src/wrap.scm | |||
@@ -1,13 +1,23 @@ | |||
1 | (declare (module (jimmy wrap))) | 1 | (declare (module (jimmy wrap))) |
2 | 2 | ||
3 | (import scheme (chicken base) | 3 | (import scheme (chicken base) |
4 | (jimmy emit) | ||
4 | (jimmy util) | 5 | (jimmy util) |
5 | (chicken format)) | 6 | (only (chicken io) read-string) |
7 | (only (chicken port) with-output-to-string) | ||
8 | (only (chicken string) string-translate*)) | ||
6 | 9 | ||
7 | ;;; open question: how to do templating? | 10 | ;; templates are strings with variables interpolated with "{{variables}}" |
8 | 11 | ||
9 | (define-public (wrap document template) | 12 | (define-public (wrap document template) |
10 | #f) | 13 | (let* ((meta (map (lambda (el) |
14 | (cons (string-append "{{" (car el) "}}") | ||
15 | (string-intersperse (cdr el) " "))) | ||
16 | (alist-walk document 'meta))) | ||
17 | (body (cons "{{body}}" | ||
18 | (with-output-to-string | ||
19 | (lambda () (emit document)))))) | ||
20 | (string-translate* template (cons body meta)))) | ||
11 | 21 | ||
12 | (define (meta-get key document) | 22 | (define-public (wrap-with document file) |
13 | (alist-walk document 'meta key)) | 23 | (wrap document (with-input-from-file file read-string))) |