diff --git a/gem300.rkt b/gem300.rkt index 027847b..d7ca0d5 100644 --- a/gem300.rkt +++ b/gem300.rkt @@ -3,6 +3,83 @@ (require openssl) (require net/url) +(struct text (str)) +(struct link (url str)) +(struct preformatted (str)) + +(define (parse-url line) + (let ([split (string-split (substring line 2))]) + ;; there are necessarily at least two elements + ;; in the split (the => and the URL) otherwise + ;; its just text. + (if (>= (length split) 2) + (link (second split) + ;; if there are at least three elements in the split, + ;; that means that everything after the URL is text. + (if (>= (length split) 3) + (string-join (drop split 2)) + #f)) + (text line)))) + + +(define (gemtext-parse lines) + (define (iter document lines state) + ;; when there are no more lines, we have finished parsing. + (if (empty? lines) + document + + ;; otherwise, we have a state machine to traverse. + (cond + ;; turn off preformatted mode + [(and (symbol=? 'preformatted state) + (or (empty? (cdr lines)) + (string-prefix? (car lines) "```"))) + + (iter document + (cdr lines) + 'normal)] + + ;; add line to most recent preformat block + [(symbol=? 'preformatted state) + (if (preformatted? (car document)) + ;; little bit hard to follow: take the existing + ;; preformatted blocks content, cons the new line; + ;; then, cons the new preformatted block to the cdr of + ;; the document + (iter (cons (preformatted (cons (car lines) + (preformatted-str (car document)))) + (cdr document)) + (cdr lines) + 'preformatted) + + (iter (cons (preformatted (list)) document) + (cdr lines) + 'preformatted))] + + ;; rest of this is normal mode + + ;; link lines + [(string-prefix? (car lines) "=>") + (iter (cons (parse-url (car lines)) + document) + (cdr lines) + 'normal)] + + ;; preformatting toggle lines + [(string-prefix? (car lines) "```") + ;; add preformatted block to document and toggle mode + (iter document + (cdr lines) + 'preformatted)] + + [else + (iter (cons (text (car lines)) + document) + (cdr lines) + 'normal)]))) + + (displayln (iter (list) lines 'normal))) + (define (request url-str) (define url (string->url url-str)) (define-values (c-in c-out)