white-tiger/src/white-tiger.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)))