(in-package :html-jen) (defun dosya-metni-oku (dosya) (let* ((uzunluk 0) (metin (with-output-to-string (out) (with-open-file (in dosya :external-format :utf-8) (loop :with arabellek := (make-array 8192 :element-type 'character) :for n := (read-sequence arabellek in) :while (< 0 n) :do (incf uzunluk n) (write-sequence arabellek out :start 0 :end n)))))) (values metin uzunluk))) (defclass okur () ((metin :initarg :metin :accessor metin :documentation "Markdown string") (i :initform 0 :accessor i :documentation "Metin indeksi") (uzunluk :initarg :uzunluk :accessor uzunluk :documentation "Metin uzunluğu") (dosya-ismi :initarg :dosya-ismi :documentation "Okunan markdown dosyasının ismi"))) (defun okur! (dosya-ismi) (multiple-value-bind (metin uzunluk) (dosya-metni-oku dosya-ismi) (make-instance 'okur :metin metin :uzunluk uzunluk :dosya-ismi dosya-ismi))) (defmethod son? ((okur okur)) (>= (i okur) (uzunluk okur))) (defmethod index-reset ((okur okur)) (setf (i oo) 0)) (let ((blok-sonu (format nil "~%~%"))) (defmethod sonraki-blok ((okur okur)) (unless (son? okur) (with-slots (i uzunluk metin) okur (let ((son (or (search blok-sonu metin :start2 i) uzunluk))) (prog1 (make-array (- son i) :element-type 'character :displaced-to metin :displaced-index-offset i) (setf i (+ son 2)))))))) (defmethod okur-blok-listesi ((okur okur)) (let ((blok (sonraki-blok okur))) (if (null blok) nil (cons blok (okur-blok-listesi okur))))) (defgeneric ayrıştır (tag blok baş) (:documentation "Tag'a göre bloktaki elementleri belirler.")) (defmethod ayrıştır ((tag (eql :h)) blok baş) (let ((i baş) (son (length blok)) (h-sayı 0)) (loop :while (char= #\# (char blok i)) :do (incf i) (incf h-sayı)) (assert (char= #\Space (char blok i))) (assert (< h-sayı 7)) (incf i) (values (make-array (- son i) :element-type 'character :displaced-to blok :displaced-index-offset i) h-sayı))) (defmethod ayrıştır ((tag (eql :ul)) blok baş) (let ((i baş) (son (length blok))) (loop :while (< i son) :do (assert (string= "- " blok :start2 i :end2 (+ i 2))) (incf i 2) :collect (let ((yeni (or (position #\Newline blok :start i) son))) (prog1 (make-array (- yeni i) :element-type 'character :displaced-to blok :displaced-index-offset i) (setf i (+ yeni 1))))))) (defmethod ayrıştır ((tag (eql :ol)) blok baş) (let ((i baş) (son (length blok)) (item-sayısı 1)) (loop :while (< i son) :do (let ((i2 i)) (loop :while (char<= #\0 (char blok i2) #\9) :do (incf i2)) (assert (string= ". " blok :start2 i2 :end2 (+ i2 2))) (assert (= item-sayısı (parse-integer blok :start i :end i2))) (incf item-sayısı) (setf i (+ i2 2))) :collect (let ((yeni (or (position #\Newline blok :start i) son))) (prog1 (make-array (- yeni i) :element-type 'character :displaced-to blok :displaced-index-offset i) (setf i (+ yeni 1))))))) (defmethod ayrıştır ((tag (eql :code)) blok baş) (let ((son (length blok)) (kod-baş (+ baş 3)) (kod-son (- (length blok) 3))) (assert (string= "```" blok :start2 baş :end2 kod-baş)) (assert (string= "```" blok :start2 kod-son :end2 son)) (make-array (- kod-son kod-baş) :element-type 'character :displaced-to blok :displaced-index-offset kod-baş))) (defun blok-ayrıştır (blok) (let ((i 0)) (loop :while (char= #\Space (char blok i)) :do (incf i)) (case (char blok i) (#\# (ayrıştır :h blok i)) (#\- (ayrıştır :ul blok i)) (#\` (ayrıştır :code blok i)) ;; (#\> :blockquote) (t (if (char<= #\0 (char blok i) #\9) (ayrıştır :ol blok i) :p)) )))