git.fiddlerwoaroof.com
Browse code

feat: improve indentation-based formatter, add org format

Edward Langley authored on 24/10/2022 03:40:17
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))