61 lines
1.6 KiB
Common Lisp
61 lines
1.6 KiB
Common Lisp
;; (defpackage white-tiger
|
|
;; (:use :cl)
|
|
;; (:export #:node #:make-node #:node-type #:node-text-component #:node-preformat #:start))
|
|
|
|
;; (in-package white-tiger)
|
|
|
|
(defstruct node
|
|
(type)
|
|
(text-component "" :type string)
|
|
(preformat nil :type boolean))
|
|
|
|
(defun type-of-line (line)
|
|
(if (= (length line) 0)
|
|
:text
|
|
(case (char line 0)
|
|
;; Headers
|
|
(#\# (if (eq (char line 1) #\#)
|
|
(if (eq (char line 2) #\#)
|
|
:h3
|
|
:h2)
|
|
:h1
|
|
))
|
|
;; List item
|
|
(#\* :list)
|
|
;; Quote
|
|
(#\> :quote)
|
|
;; preformat toggle
|
|
(#\` (if (and (eql #\` (char line 2)) (eql #\` (char line 1))) :preformat :text))
|
|
;; Link
|
|
(#\= (if (eq #\> (char line 1)) :link :text))
|
|
(otherwise :text))))
|
|
|
|
(defun read-file (filename)
|
|
(uiop:read-file-lines filename))
|
|
|
|
(defun type-of-file (filename)
|
|
(map 'list #'type-of-line (read-file filename)))
|
|
|
|
(defun xor (a b)
|
|
(or (and (not a) b) (and a (not b))))
|
|
|
|
(defun line-to-node (line type preformat)
|
|
(make-node
|
|
:preformat preformat
|
|
;; TODO: Split line on first whitespace; use cdr for text component
|
|
:type type
|
|
:text-component ""))
|
|
|
|
(defun parse-gemtext-file (line-list preformat-mode)
|
|
(if (= (length line-list) 0)
|
|
nil
|
|
;; Parse the line. If this line is a PREFORMAT, toggle the boolean moving forward.
|
|
(let ((line-type (type-of-line (car line-list))))
|
|
(cons (line-to-node (car line-list) line-type (if (eq line-type :preformat) nil preformat-mode))
|
|
(parse-gemtext-file (cdr line-list) (if (eq line-type :preformat) (not preformat-mode) preformat-mode))))))
|
|
|
|
(defun start (filename)
|
|
(let ((file-contents (read-file filename)))
|
|
(parse-gemtext-file file-contents nil)))
|
|
|