-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathwalk.lisp
More file actions
57 lines (48 loc) · 1.72 KB
/
Copy pathwalk.lisp
File metadata and controls
57 lines (48 loc) · 1.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
(uiop:define-package #:markup/walk
(:use #:cl)
(:export #:walk
#:add-attrs)
(:import-from #:markup/markup
#:unescaped-string
#:escaped-string
#:make-xml-tag
#:make-xml-merge-tag
#:xml-merge-tag
#:xml-tag-name
#:xml-merge-tag-children
#:xml-tag-children
#:abstract-xml-tag
#:xml-tag-attributes))
(in-package #:markup/walk)
(defgeneric walk (tree fn)
(:documentation "Walk the tree, giving you the option to transform
each element"))
(defmethod walk (tree fn)
;; do nothin
(error "unexpected ~S" tree))
(defmethod walk ((tree string) fn)
tree)
(defmethod walk ((tree unescaped-string) fn)
tree)
(defmethod walk ((tree escaped-string) fn)
tree)
(Defmethod walk ((tree xml-merge-tag) fn)
(make-xml-merge-tag
:children (loop for child in (xml-merge-tag-children tree) collect
(walk child fn))))
(defmethod walk ((tree list) fn)
(loop for x in tree collect
(walk x fn)))
(Defmethod walk ((tree abstract-xml-tag) fn)
(let ((ret (funcall fn tree)))
(make-xml-tag (xml-tag-name ret)
:attributes (xml-tag-attributes ret)
:children (walk (xml-tag-children ret) fn))))
(defmethod add-attrs ((tag abstract-xml-tag) &rest args &key &allow-other-keys)
(let ((attr (xml-tag-attributes tag)))
(dolist (item (alexandria:plist-alist args))
(destructuring-bind (key . value) item
(setf (alexandria:assoc-value attr (string-downcase (string key))) value)))
(make-xml-tag (xml-tag-name tag)
:attributes attr
:children (xml-tag-children tag))))