Moar CSS selectors, fewer explicit lambdas
Thu Nov 19 06:25:36 UTC 2009 pix@kepibu.org
* Moar CSS selectors, fewer explicit lambdas
diff -rN -u old-Oh, Ducks!/notes new-Oh, Ducks!/notes
--- old-Oh, Ducks!/notes 2015-10-28 20:17:16.000000000 +0000
+++ new-Oh, Ducks!/notes 2015-10-28 20:17:16.000000000 +0000
@@ -3,8 +3,26 @@
** working lhtml/xmls support
** write documentation
** improve selector support
-*** :nth-child
-*** :first-child
-*** :last-child
-*** universal selector (*)
+*** positional selectors
+ * [ ] :nth-child
+ * [ ] :nth-last-child
+ * [ ] :first-child
+ * [ ] :last-child
+ * [ ] :nth-of-type
+ * [ ] :nth-last-of-type
+ * [ ] :first-of-type
+ * [ ] :last-of-type
+ * [ ] :only-child
+ * [ ] :only-of-type
+ * [ ] :empty
+*** attribute selectors
+ * [ ] attribute-present [att]
+ * [ ] attribute-equal [att=val]
+ * [ ] attribute-member [att~=val]
+ * [ ] attribute-lang [att|=val]
+ * [ ] attribute-begins [att^=val]
+ * [ ] attribute-ends [att$=val]
+ * [ ] attribute-contains [att*=val]
+*** :not(...)
*** any others?
+** namespace support(?)
diff -rN -u old-Oh, Ducks!/oh-ducks.asd new-Oh, Ducks!/oh-ducks.asd
--- old-Oh, Ducks!/oh-ducks.asd 2015-10-28 20:17:16.000000000 +0000
+++ new-Oh, Ducks!/oh-ducks.asd 2015-10-28 20:17:16.000000000 +0000
@@ -20,7 +20,7 @@
;; TODO: submit a patch for cl-unification to use
;; asdf-system-connections. Getting an unmodified version of
;; cl-unification to load the cl-ppcre stuff is a PITA.
- :depends-on (:cl-unification :cl-ppcre :split-sequence)
+ :depends-on (:cl-unification :cl-ppcre :split-sequence :alexandria)
:serial t
:components ((:file "package")
(:file "regexp-template")
diff -rN -u old-Oh, Ducks!/package.lisp new-Oh, Ducks!/package.lisp
--- old-Oh, Ducks!/package.lisp 2015-10-28 20:17:16.000000000 +0000
+++ new-Oh, Ducks!/package.lisp 2015-10-28 20:17:16.000000000 +0000
@@ -12,6 +12,10 @@
(defpackage #:oh-ducks
(:use #:cl #:unify #:oh-ducks.traversal)
+ (:import-from #:alexandria
+ #:compose
+ #:curry
+ #:rcurry)
(:export ;; template machinery
#:*default-parser*
#:html
diff -rN -u old-Oh, Ducks!/selectors.lisp new-Oh, Ducks!/selectors.lisp
--- old-Oh, Ducks!/selectors.lisp 2015-10-28 20:17:16.000000000 +0000
+++ new-Oh, Ducks!/selectors.lisp 2015-10-28 20:17:16.000000000 +0000
@@ -29,7 +29,6 @@
(defclass adjacent-combinator (combinator) ())
(defclass sibling-combinator (combinator) ())
-#+FIXME ; is this the right name?
(defclass universal-selector (simple-selector) ())
(defclass type-selector (simple-selector) ())
(defclass id-selector (simple-selector) ())
@@ -43,24 +42,24 @@
(defun parse-selector (selector)
(match-case (selector)
;; combinators
+ #+TODO (#T(regexp$ "[ ]*[~][ ]*" ()) (list (make-instance 'sibling-combinator :matcher (parse-selector &rest))))
+ #+TODO (#T(regexp$ "[ ]*[+][ ]*" ()) (list (make-instance 'adjacent-combinator :matcher (parse-selector &rest))))
(#T(regexp$ "[ ]*[>][ ]*" ()) (list (make-instance 'child-combinator :matcher (parse-selector &rest))))
(#T(regexp$ "[ ]+" ()) (list (make-instance 'descendant-combinator :matcher (parse-selector &rest))))
;; simple selector
(#T(regexp$ "[#](\\w+)" (?id)) (cons (make-instance 'id-selector :arg id) (parse-selector &rest)))
(#T(regexp$ "[\\.](\\w+)" (?class)) (cons (make-instance 'class-selector :arg class) (parse-selector &rest)))
(#T(regexp$ "(\\w+)" (?type)) (cons (make-instance 'type-selector :arg type) (parse-selector &rest)))
- #+TODO
(#T(regexp$ "\\*" ()) (cons (make-instance 'universal-selector) (parse-selector &rest)))))
(defgeneric find-matching-elements (selector elements))
(defmethod find-matching-elements (selector (elements list))
(nconc
- (remove-if-not (lambda (el) (element-matches-p el selector)) elements)
+ (remove-if-not (rcurry #'element-matches-p selector) elements)
(reduce #'nconc
- (remove-if #'null
- (mapcar (lambda (element) (find-matching-elements selector (element-children element)))
- elements)))))
+ (mapcar (compose (curry #'find-matching-elements selector) #'element-children)
+ elements))))
(defmethod find-matching-elements (selector (elements t))
(find-matching-elements selector (list elements)))
@@ -78,11 +77,22 @@
(element-classes element)
:test #'string=))
+(defmethod element-matches-p (element (selector universal-selector))
+ t)
+
(defmethod element-matches-p (element (selector list))
- (every (lambda (s) (element-matches-p element s)) selector))
+ (every (curry #'element-matches-p element) selector))
(defmethod element-matches-p (element (selector child-combinator))
(element-matches-p (element-parent element) (matcher selector)))
(defmethod element-matches-p (element (selector descendant-combinator))
- (some (lambda (a) (element-matches-p a (matcher selector))) (element-ancestors element)))
+ (some (rcurry #'element-matches-p (matcher selector)) (element-ancestors element)))
+
+#+TODO
+(defmethod element-matches-p (element (selector adjacent-combinator))
+ ...)
+
+#+TODO
+(defmethod element-matches-p (element (selector sibling-combinator))
+ ...)
diff -rN -u old-Oh, Ducks!/templates.lisp new-Oh, Ducks!/templates.lisp
--- old-Oh, Ducks!/templates.lisp 2015-10-28 20:17:16.000000000 +0000
+++ new-Oh, Ducks!/templates.lisp 2015-10-28 20:17:16.000000000 +0000
@@ -23,6 +23,7 @@
(:method ((parser t) spec)
(make-instance 'css-selector-template :parser parser :spec spec))
(:method ((parser null) spec)
+ (declare (ignore parser spec))
(error "No parser specified.")))
(defun %spec-includes-opts (spec)