Browse code
feat: improve indentation-based formatter, add org format
Edward Langley authored on 24/10/2022 03:40:17
Showing 1 changed files
Showing 1 changed files
... | ... |
@@ -1,6 +1,7 @@ |
1 | 1 |
(defpackage :alimenta.format |
2 | 2 |
(:use :cl :alexandria :serapeum :fw.lu) |
3 |
- (:export format-document format-title format-link format-paragraph)) |
|
3 |
+ (:export format-document format-title format-link format-paragraph |
|
4 |
+ #:indent-feed)) |
|
4 | 5 |
(in-package :alimenta.format) |
5 | 6 |
|
6 | 7 |
(defclass document-formatter () |
... | ... |
@@ -41,6 +42,7 @@ |
41 | 42 |
|
42 | 43 |
;;; Define some output formats |
43 | 44 |
|
45 |
+;;;; Indentation-based |
|
44 | 46 |
(defclass indent-formatter (document-formatter) |
45 | 47 |
((%level :initarg :level :accessor level :initform 0))) |
46 | 48 |
|
... | ... |
@@ -75,6 +77,7 @@ |
75 | 77 |
(for:for ((item over document)) |
76 | 78 |
(format-document formatter stream item))) |
77 | 79 |
|
80 |
+;;;; HTML |
|
78 | 81 |
(defclass html-formatter (document-formatter) |
79 | 82 |
((%level :initarg :level :accessor level :initform 0))) |
80 | 83 |
|
... | ... |
@@ -105,3 +108,52 @@ |
105 | 108 |
(get-output-stream-string ostream)) |
106 | 109 |
(unless stream |
107 | 110 |
(close ostream))))) |
111 |
+ |
|
112 |
+;;;; Org |
|
113 |
+ |
|
114 |
+(defclass org-formatter (document-formatter) |
|
115 |
+ ((%level :initarg :level :accessor level :initform 0))) |
|
116 |
+ |
|
117 |
+(defmethod format-document ((formatter org-formatter) stream (document alimenta::feed-entity)) |
|
118 |
+ (format stream "~&~a~%~a~2%" |
|
119 |
+ (format-title formatter (alimenta:title document)) |
|
120 |
+ (format-link formatter (alimenta:link document)))) |
|
121 |
+ |
|
122 |
+(defmethod format-document ((formatter org-formatter) stream (document alimenta:item)) |
|
123 |
+ (call-next-method) |
|
124 |
+ (let ((paragraphs (remove-if (op (every #'whitespacep _)) |
|
125 |
+ (lquery:$ (initialize (alimenta:content document)) |
|
126 |
+ (children) |
|
127 |
+ (text))))) |
|
128 |
+ (format stream "~&~{~a~%~}~2&" |
|
129 |
+ (map 'list (op (format-paragraph formatter _)) |
|
130 |
+ paragraphs)))) |
|
131 |
+ |
|
132 |
+(defmethod format-title ((formatter org-formatter) (title string)) |
|
133 |
+ (with-output-to-string (s) |
|
134 |
+ (loop repeat (1+ (level formatter)) |
|
135 |
+ do (princ #\* s)) |
|
136 |
+ (princ #\space s) |
|
137 |
+ (princ (serapeum:trim-whitespace title) s))) |
|
138 |
+ |
|
139 |
+(defmethod format-link ((formatter org-formatter) (link string)) |
|
140 |
+ (format nil "~vt[[~a]]" (+ 2 (level formatter)) link)) |
|
141 |
+ |
|
142 |
+ |
|
143 |
+(defmethod format-paragraph ((formatter org-formatter) (paragraph string)) |
|
144 |
+ (format nil "~&~v,1@t~/alimenta.format::pp-fill/~%" (+ 2 (level formatter)) paragraph)) |
|
145 |
+ |
|
146 |
+(defmethod format-paragraph ((formatter org-formatter) (paragraph list)) |
|
147 |
+ (format nil "~&~{ ~a~%~}" paragraph)) |
|
148 |
+ |
|
149 |
+(defmethod format-document ((formatter org-formatter) stream (document alimenta:feed)) |
|
150 |
+ (call-next-method) |
|
151 |
+ (incf (level formatter)) |
|
152 |
+ (for:for ((item over document)) |
|
153 |
+ (format-document formatter stream item))) |
|
154 |
+ |
|
155 |
+ |
|
156 |
+(defun indent-feed (feed &optional (stream *standard-output*)) |
|
157 |
+ (format-document (make-instance 'alimenta.format::indent-formatter) |
|
158 |
+ stream |
|
159 |
+ feed)) |