git.fiddlerwoaroof.com
Browse code

Add transform feed protocol

fiddlerwoaroof authored on 15/08/2017 01:14:31
Showing 2 changed files
... ...
@@ -1,5 +1,5 @@
1 1
 ;;;; alimenta.lisp
2
-(declaim (optimize (speed 0) (safety 3) (debug 3)))
2
+;; (declaim (optimize (speed 0) (safety 3) (debug 3)))
3 3
 
4 4
 (in-package #:alimenta)
5 5
 
... ...
@@ -102,19 +102,19 @@
102 102
   (let ((result (call-next-method feed feed-type)))
103 103
     (with-accessors ((items items)) feed
104 104
       (loop for item in items
105
-            do (generate-xml item feed-type :partial result)))
105
+         do (generate-xml item feed-type :partial result)))
106 106
     result))
107 107
 
108 108
 (defmethod -to-feed ((doc stream) doc-type &key feed-link)
109 109
   (-to-feed (plump:parse doc)
110
-	    doc-type
111
-	    :feed-link feed-link))
110
+            doc-type
111
+            :feed-link feed-link))
112 112
 
113 113
 (defmethod -to-feed ((doc string) doc-type &key feed-link)
114 114
   (-to-feed (plump:parse doc)
115
-	    doc-type
116
-	    :feed-link feed-link))
117
-    
115
+            doc-type
116
+            :feed-link feed-link))
117
+
118 118
 (defmethod -to-feed :around ((xml-dom plump:node) doc-type &key feed-link)
119 119
   "This wraps the particular methods so that _they_ don't have to implement
120 120
    item fetching.  NIL passed to the type activates auto-detection"
... ...
@@ -123,9 +123,9 @@
123 123
       (setf doc xml-dom
124 124
             source-type doc-type))
125 125
     (setf
126
-      (items it)
127
-      (loop for item across (get-items xml-dom doc-type)
128
-            collect (make-item item doc-type)))))
126
+     (items it)
127
+     (loop for item across (get-items xml-dom doc-type)
128
+        collect (make-item item doc-type)))))
129 129
 
130 130
 (defgeneric (setf link) (value self))
131 131
 (defmethod (setf link) ((value cons) (self item))
... ...
@@ -133,8 +133,8 @@
133 133
     (destructuring-bind (type . href) value
134 134
       (when (consp href)
135 135
         (if (null (cdr href))
136
-          (setf href (car href))
137
-          (error 'type-error "too many arguments")))
136
+            (setf href (car href))
137
+            (error 'type-error "too many arguments")))
138 138
       (let ((type-keyword (make-keyword (string-upcase type))))
139 139
         (when (slot-boundp self 'links)
140 140
           (multiple-value-bind (old-link old-link-p) (gethash type-keyword links) 
... ...
@@ -160,8 +160,8 @@
160 160
 
161 161
 (defun detect-feed-type (xml-dom)
162 162
   (let ((root-node-name (make-keyword (string-upcase
163
-                                        ($ (inline xml-dom) (children)
164
-                                           (map #'tag-name) (node))))))
163
+                                       ($ (inline xml-dom) (children)
164
+                                          (map #'tag-name) (node))))))
165 165
     (case root-node-name
166 166
       ((:feed) :atom)
167 167
       (t root-node-name))))
... ...
@@ -180,8 +180,8 @@
180 180
                  #'local-time:timestamp>
181 181
                  :key #'date)))))
182 182
 
183
-;(defun generate-xml (feed &key (feed-type :rss))
184
-;  (%generate-xml feed feed-type))
183
+                                        ;(defun generate-xml (feed &key (feed-type :rss))
184
+                                        ;  (%generate-xml feed feed-type))
185 185
 
186 186
 (defun to-feed (doc &key type feed-link)
187 187
   "Makes an instance of feed from the given document.  Specialize to-feed with
... ...
@@ -192,11 +192,11 @@
192 192
   (-to-feed doc type :feed-link feed-link))
193 193
 
194 194
 
195
-;(defun -get-items (feed xml-dom &key type)
196
-;  (with-accessors ((items items)) feed
197
-;    (loop for item across (get-items xml-dom type)
198
-;          do (push (make-item xml-dom type) items)
199
-;          finally (return items)))) 
195
+                                        ;(defun -get-items (feed xml-dom &key type)
196
+                                        ;  (with-accessors ((items items)) feed
197
+                                        ;    (loop for item across (get-items xml-dom type)
198
+                                        ;          do (push (make-item xml-dom type) items)
199
+                                        ;          finally (return items)))) 
200 200
 
201 201
 (defun make-feed (&key title link items feed-link description)
202 202
   (make-instance 'feed
... ...
@@ -219,10 +219,35 @@
219 219
 
220 220
 (defun filter-feed (feed function &key key)
221 221
   (setf (items feed)
222
-	(remove-if-not function (items feed)
223
-		       :key key))
222
+        (remove-if-not function (items feed)
223
+                       :key key))
224 224
   feed)
225 225
 
226
+(defgeneric transform (item transform)
227
+  (:documentation "transform a feed entity by TRANSFORM: the
228
+function will be called with either a feed or a item as an arguments
229
+and, if called upon a feed, it'll automatically be mapped across the
230
+feed's items after being called on the feed. We do not use the results
231
+of this mapping directly, however any modifications to an item mutate
232
+the original.")
233
+
234
+  (:method :around (item transform)
235
+    (call-next-method)
236
+    item)
237
+
238
+  (:method ((feed feed-entity) transform)
239
+    (funcall transform feed))
240
+
241
+  (:method :after ((feed feed) transform)
242
+    (map nil (lambda (it)
243
+                 (transform it transform))
244
+         (items feed))))
245
+
246
+(defun transform-content (item function)
247
+  (setf (content item)
248
+        (funcall function
249
+                 (content item))))
250
+
226 251
 (defun shorten-link (link)
227 252
   (let ((link (cl-ppcre:regex-replace "^https?:" link "")))
228 253
     (subseq link 0 (min 30 (length link)))))
... ...
@@ -232,13 +257,13 @@
232 257
         (items feed)))
233 258
 
234 259
 (deftest push-item ()
235
-  (let ((feed (make-instance 'feed))
236
-        (item (make-instance 'item)))
237
-    (with-accessors ((items items)) feed
238
-      ;(should signal error (push-item feed 2))
239
-      (should be eql item
240
-              (progn
241
-                (push-item feed item)
242
-                (car items))))))
260
+    (let ((feed (make-instance 'feed))
261
+          (item (make-instance 'item)))
262
+      (with-accessors ((items items)) feed
263
+                                        ;(should signal error (push-item feed 2))
264
+        (should be eql item
265
+                (progn
266
+                  (push-item feed item)
267
+                  (car items))))))
243 268
 
244 269
 ;; vim: set foldmethod=marker:
... ...
@@ -17,7 +17,8 @@
17 17
            #:doc #:source-type #:id #:date #:content #:item #:description
18 18
            #:%generate-xml #:%to-feed #:get-items #:make-item #:complex-value
19 19
            #:primary-value #:render #:author #:content-el #:feed-type-unsupported
20
-	   #:pop-token #:filter-feed #:feed-entity))
20
+           #:pop-token #:filter-feed #:feed-entity
21
+           #:transform))
21 22
 
22 23
 (defpackage #:alimenta.html
23 24
   (:use #:cl #:should-test #:lquery #:alexandria #:anaphora #:alimenta #:data-class