Browse code
Define sequence protocol, add atom item categories
Ed Langley authored on 12/03/2019 01:53:41
Showing 7 changed files
Showing 7 changed files
- alimenta-clim.lisp
- alimenta.asd
- alimenta.lisp
- atom.lisp
- collections-sbcl-iterators.lisp
- package.lisp
- render-protocol.lisp
... | ... |
@@ -28,18 +28,18 @@ |
28 | 28 |
(:panes |
29 | 29 |
(feeds :application |
30 | 30 |
:height 400 |
31 |
- ;; :width 100 |
|
31 |
+ :width 300 |
|
32 | 32 |
:display-function 'display-app |
33 | 33 |
:default-view (clim:with-application-frame (frame) |
34 | 34 |
(feed-list frame))) |
35 | 35 |
(items :application |
36 | 36 |
:height 400 |
37 |
- ;; :width 200 |
|
37 |
+ :width 600 |
|
38 | 38 |
:display-function #'display-app |
39 | 39 |
:default-view *feed-view*) |
40 | 40 |
(articles :application |
41 | 41 |
:height 400 |
42 |
- ;; :width 300 |
|
42 |
+ :width 600 |
|
43 | 43 |
:display-function 'display-app |
44 | 44 |
) |
45 | 45 |
(int :interactor |
... | ... |
@@ -158,14 +158,13 @@ |
158 | 158 |
(t 'default))))) |
159 | 159 |
|
160 | 160 |
|
161 |
+ |
|
161 | 162 |
(defun main () |
162 | 163 |
(clim:run-frame-top-level |
163 | 164 |
(clim:make-application-frame 'alimenta-clim::alimenta |
164 | 165 |
:feed-list |
165 | 166 |
(make-instance 'feed-list |
166 |
- :feeds (list (make-instance 'feed-url |
|
167 |
- :uri |
|
168 |
- "http://thomism.wordpress.com/feed") |
|
169 |
- (make-instance 'feed-url |
|
170 |
- :uri |
|
171 |
- "http://planet.lisp.org/rss20.xml")))))) |
|
167 |
+ :feeds (list |
|
168 |
+ (make-instance 'feed-url |
|
169 |
+ :uri |
|
170 |
+ "http://planet.lisp.org/rss20.xml")))))) |
... | ... |
@@ -10,7 +10,7 @@ |
10 | 10 |
#:chronicity |
11 | 11 |
#:drakma |
12 | 12 |
#:for |
13 |
- #:fwoar.lisputils |
|
13 |
+ #:fwoar-lisputils |
|
14 | 14 |
#:collection-class |
15 | 15 |
#:lquery |
16 | 16 |
#:plump |
... | ... |
@@ -23,12 +23,13 @@ |
23 | 23 |
(:file "alimenta") |
24 | 24 |
(:file "data-class") |
25 | 25 |
(:file "date-handling") |
26 |
+ (:file "render-protocol") |
|
26 | 27 |
(:file "atom") |
27 | 28 |
(:file "rss") |
28 | 29 |
(:file "fetching") |
29 | 30 |
(:file "discovery"))) |
30 | 31 |
|
31 |
-(defsystem :alimenta+patmatch |
|
32 |
+(defsystem :alimenta/patmatch |
|
32 | 33 |
:description "" |
33 | 34 |
:author "Ed L <edward@elangley.org>" |
34 | 35 |
:license "MIT" |
... | ... |
@@ -36,7 +37,7 @@ |
36 | 37 |
#:uiop |
37 | 38 |
#:serapeum |
38 | 39 |
#:alimenta |
39 |
- #:fwoar.lisputils) |
|
40 |
+ #:fwoar-lisputils) |
|
40 | 41 |
:serial t |
41 | 42 |
:components ((:file "pattern-matcher"))) |
42 | 43 |
|
... | ... |
@@ -24,17 +24,6 @@ |
24 | 24 |
(:documentation "Given a lisp object representing a feed, return it rendered |
25 | 25 |
to the specified format")) |
26 | 26 |
|
27 |
-(defgeneric render-feed (feed renderer) |
|
28 |
- (:documentation "Render the container for the feed's items. Return an object |
|
29 |
- to which the items can be added via add-rendered-item")) |
|
30 |
- |
|
31 |
-(defgeneric render-item (item renderer) |
|
32 |
- (:documentation "Render an item to be added to a feed. Return an object that |
|
33 |
- can be added to the container by add-rendered-item")) |
|
34 |
- |
|
35 |
-(defgeneric add-rendered-item (item-representation feed-representation renderer) |
|
36 |
- (:documentation "Add the rendered item to the rendered feed")) |
|
37 |
- |
|
38 | 27 |
(defgeneric generate-xml (feed feed-type &key partial) |
39 | 28 |
(:documentation "Given a lisp object representing a feed, return an xml |
40 | 29 |
document")) |
... | ... |
@@ -55,9 +44,13 @@ |
55 | 44 |
(source-type :initarg :source-type :initform nil :accessor source-type))) |
56 | 45 |
|
57 | 46 |
(defmethod render ((feed feed) renderer) |
58 |
- (let ((doc (render-feed feed renderer))) |
|
47 |
+ (let ((doc (alimenta.render:render-feed feed renderer))) |
|
59 | 48 |
(for:for ((item over feed)) |
60 |
- (add-rendered-item (render-item item renderer) doc renderer)))) |
|
49 |
+ (setf doc |
|
50 |
+ (alimenta.render:add-rendered-item doc |
|
51 |
+ (alimenta.render:render-item item feed renderer) |
|
52 |
+ renderer))) |
|
53 |
+ doc)) |
|
61 | 54 |
|
62 | 55 |
(defmethod (setf feed-link) ((value string) (feed feed)) |
63 | 56 |
(setf (slot-value feed 'feed-link) |
... | ... |
@@ -180,8 +173,8 @@ |
180 | 173 |
#'local-time:timestamp> |
181 | 174 |
:key #'date))))) |
182 | 175 |
|
183 |
- ;(defun generate-xml (feed &key (feed-type :rss)) |
|
184 |
- ; (%generate-xml feed feed-type)) |
|
176 |
+;;(defun generate-xml (feed &key (feed-type :rss)) |
|
177 |
+;; (%generate-xml feed feed-type)) |
|
185 | 178 |
|
186 | 179 |
(defun to-feed (doc &key type feed-link) |
187 | 180 |
"Makes an instance of feed from the given document. Specialize to-feed with |
... | ... |
@@ -192,11 +185,11 @@ |
192 | 185 |
(-to-feed doc type :feed-link feed-link)) |
193 | 186 |
|
194 | 187 |
|
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)))) |
|
188 |
+;;(defun -get-items (feed xml-dom &key type) |
|
189 |
+;; (with-accessors ((items items)) feed |
|
190 |
+;; (loop for item across (get-items xml-dom type) |
|
191 |
+;; do (push (make-item xml-dom type) items) |
|
192 |
+;; finally (return items)))) |
|
200 | 193 |
|
201 | 194 |
(defun make-feed (&key title link items feed-link description) |
202 | 195 |
(make-instance 'feed |
... | ... |
@@ -232,16 +225,16 @@ of this mapping directly, however any modifications to an item mutate |
232 | 225 |
the original.") |
233 | 226 |
|
234 | 227 |
(:method :around (item transform) |
235 |
- (call-next-method) |
|
236 |
- item) |
|
228 |
+ (call-next-method) |
|
229 |
+ item) |
|
237 | 230 |
|
238 | 231 |
(:method ((feed feed-entity) transform) |
239 | 232 |
(funcall transform feed)) |
240 | 233 |
|
241 | 234 |
(:method :after ((feed feed) transform) |
242 |
- (map nil (lambda (it) |
|
243 |
- (transform it transform)) |
|
244 |
- (items feed)))) |
|
235 |
+ (map nil (lambda (it) |
|
236 |
+ (transform it transform)) |
|
237 |
+ (items feed)))) |
|
245 | 238 |
|
246 | 239 |
(defun transform-content (item function) |
247 | 240 |
(setf (content item) |
... | ... |
@@ -257,13 +250,13 @@ the original.") |
257 | 250 |
(items feed))) |
258 | 251 |
|
259 | 252 |
(deftest push-item () |
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)))))) |
|
253 |
+ (let ((feed (make-instance 'feed)) |
|
254 |
+ (item (make-instance 'item))) |
|
255 |
+ (with-accessors ((items items)) feed |
|
256 |
+ ;;(should signal error (push-item feed 2)) |
|
257 |
+ (should be eql item |
|
258 |
+ (progn |
|
259 |
+ (push-item feed item) |
|
260 |
+ (car items)))))) |
|
268 | 261 |
|
269 | 262 |
;; vim: set foldmethod=marker: |
... | ... |
@@ -5,6 +5,8 @@ |
5 | 5 |
((term :initarg :term :initform nil :accessor term) |
6 | 6 |
(label :initarg :label :initform nil :accessor label) |
7 | 7 |
(scheme :initarg :scheme :initform nil :accessor scheme))) |
8 |
+(defmethod print-object ((o atom-category) s) |
|
9 |
+ (format s "#.(~s ~s ~s ~s)" 'make-category (term o) (label o) (scheme o))) |
|
8 | 10 |
|
9 | 11 |
(defclass atom-person () |
10 | 12 |
((name :initarg :name :type (or null string) :initform nil :accessor name) |
... | ... |
@@ -25,7 +27,8 @@ |
25 | 27 |
(alimenta::target :initarg :target))) |
26 | 28 |
|
27 | 29 |
(defclass atom-item (alimenta:item) |
28 |
- ((author-uri :initarg :author-uri :initform nil :accessor author-uri))) |
|
30 |
+ ((author-uri :initarg :author-uri :initform nil :accessor author-uri) |
|
31 |
+ (categories :initarg :categories :type (or null list) :initform nil :accessor categories))) |
|
29 | 32 |
|
30 | 33 |
(defun make-category (term &optional label scheme) |
31 | 34 |
(make-instance 'atom-category :term term :label label :scheme scheme)) |
... | ... |
@@ -60,17 +63,21 @@ |
60 | 63 |
(item-content ($ "> content" (text) (node))) |
61 | 64 |
(item-author ($ "> author > name" (text) (node))) |
62 | 65 |
(item-author-uri ($ "> author > uri" (text) (node))) |
66 |
+ (item-categories ($ (inline xml-dom) "> category" |
|
67 |
+ (combine (attr "term") (attr "label") (attr "scheme")) |
|
68 |
+ (map-apply #'make-category))) |
|
63 | 69 |
(*tag-dispatchers* *html-tags*) |
64 | 70 |
(content (with-output-to-string (s) |
65 | 71 |
(awhen (or item-content item-description) (serialize (parse it) s))))) |
66 | 72 |
(make-instance 'atom-item |
67 |
- :doc xml-dom |
|
73 |
+ :doc xml-dom |
|
68 | 74 |
:content content |
69 | 75 |
:date (local-time:parse-timestring item-date) |
70 | 76 |
:id item-guid |
71 | 77 |
:author item-author |
72 | 78 |
:author-uri item-author-uri |
73 | 79 |
:link item-link |
80 |
+ :categories (coerce item-categories 'list) |
|
74 | 81 |
:title item-title))) |
75 | 82 |
|
76 | 83 |
(defun get-authors (xml-dom) |
... | ... |
@@ -1,14 +1,40 @@ |
1 | 1 |
(in-package :collection-class) |
2 | 2 |
|
3 |
+#+nil |
|
4 |
+(defmethod sequence:length ((sequence collection)) |
|
5 |
+ (length (items sequence))) |
|
6 |
+ |
|
7 |
+#+sbcl |
|
3 | 8 |
(defmethod sb-sequence:length ((sequence collection)) |
4 | 9 |
(length (items sequence))) |
5 | 10 |
|
11 |
+#+nil |
|
12 |
+(defmethod sequence:elt ((sequence collection) index) |
|
13 |
+ (elt (items sequence) index)) |
|
14 |
+ |
|
15 |
+#+sbcl |
|
6 | 16 |
(defmethod sb-sequence:elt ((sequence collection) index) |
7 | 17 |
(elt (items sequence) index)) |
8 | 18 |
|
19 |
+#+nil |
|
20 |
+(defmethod (setf sequence:elt) (new-value (sequence collection) index) |
|
21 |
+ (setf (elt (items sequence) index) new-value)) |
|
22 |
+ |
|
23 |
+#+sbcl |
|
9 | 24 |
(defmethod (setf sb-sequence:elt) (new-value (sequence collection) index) |
10 | 25 |
(setf (elt (items sequence) index) new-value)) |
11 | 26 |
|
27 |
+#+nil |
|
28 |
+(defmethod sequence:adjust-sequence ((sequence collection) length &key initial-element initial-contents) |
|
29 |
+ (let ((result (duplicate-collection sequence))) |
|
30 |
+ (when (or initial-element initial-contents) |
|
31 |
+ (setf (items result) |
|
32 |
+ (sequence:adjust-sequence (items result) length |
|
33 |
+ :initial-element initial-element |
|
34 |
+ :initial-contents initial-contents))) |
|
35 |
+ result)) |
|
36 |
+ |
|
37 |
+#+sbcl |
|
12 | 38 |
(defmethod sb-sequence:adjust-sequence ((sequence collection) length &key initial-element initial-contents) |
13 | 39 |
(let ((result (duplicate-collection sequence))) |
14 | 40 |
(when (or initial-element initial-contents) |
... | ... |
@@ -18,6 +44,16 @@ |
18 | 44 |
:initial-contents initial-contents))) |
19 | 45 |
result)) |
20 | 46 |
|
47 |
+#+nil |
|
48 |
+(defmethod sequence:make-sequence-like ((sequence collection) length &key initial-element initial-contents) |
|
49 |
+ (let ((result (duplicate-collection sequence))) |
|
50 |
+ (setf (items result) |
|
51 |
+ (sequence:make-sequence-like (items result) length |
|
52 |
+ :initial-element initial-element |
|
53 |
+ :initial-contents initial-contents)) |
|
54 |
+ result)) |
|
55 |
+ |
|
56 |
+#+sbcl |
|
21 | 57 |
(defmethod sb-sequence:make-sequence-like ((sequence collection) length &key initial-element initial-contents) |
22 | 58 |
(let ((result (duplicate-collection sequence))) |
23 | 59 |
(setf (items result) |
... | ... |
@@ -4,6 +4,10 @@ |
4 | 4 |
(:use #:cl #:alexandria #:serapeum) |
5 | 5 |
(:export collection value-error push-item define-collection random-item nth-item items)) |
6 | 6 |
|
7 |
+(defpackage :alimenta.render |
|
8 |
+ (:use :cl ) |
|
9 |
+ (:export #:render-feed #:render-item #:add-rendered-item)) |
|
10 |
+ |
|
7 | 11 |
(defpackage #:data-class |
8 | 12 |
(:use #:cl #:should-test #:lquery #:plump #:alexandria #:anaphora) |
9 | 13 |
(:export #:define-data-class)) |
10 | 14 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,12 @@ |
1 |
+(in-package :alimenta.render) |
|
2 |
+ |
|
3 |
+(defgeneric render-feed (feed renderer) |
|
4 |
+ (:documentation "Render the container for the feed's items. Return an object |
|
5 |
+ to which the items can be added via add-rendered-item")) |
|
6 |
+ |
|
7 |
+(defgeneric render-item (item feed renderer) |
|
8 |
+ (:documentation "Render an item to be added to a feed. Return an object that |
|
9 |
+ can be added to the container by add-rendered-item")) |
|
10 |
+ |
|
11 |
+(defgeneric add-rendered-item (feed-representation item-representation renderer) |
|
12 |
+ (:documentation "Add the rendered item to the rendered feed")) |