(in-package #:oh-ducks) (defclass css-selector-template (unify::expression-template) ((parser :initarg :parser :initform nil) ;; subtype generally determines parser (specifiers :reader specifiers) ;; list of (specifier . variable) and (specifier . template) )) (defvar *model-handler-map* nil "A mapping between model types and handler functions.") (defun add-handler (model handler) (push (cons model handler) *model-handler-map*)) (defun get-handler-for-model (model) (let ((handler (cdr (assoc model *model-handler-map*)))) (typecase handler (null nil) (function (funcall handler)) (symbol (funcall (symbol-function handler))) (t handler)))) (defvar *default-parser* nil "Determines the default parser when none is specified.") (defun %spec-includes-opts (spec) (keywordp (first (second spec)))) (defun combine-selectors (selector parent) (let ((combinator (car (last selector)))) (cond ((null parent) selector) ((combinator-p combinator) (setf (slot-value combinator 'matcher) parent) selector) (t (nconc selector (list (make-instance 'descendant-combinator :matcher parent))))))) (defun parse-specifiers (specs template parent) (loop :for (css-specifier . rest) :in specs :for selector = (combine-selectors (parse-selector css-specifier) parent) :collect (cons selector (cond ((unify::template-p rest) rest) ((unify::variablep rest) rest) ((consp rest) (make-instance (class-of template) :spec (list* (first (template-spec template)) rest) :css-specifiers rest :parent selector)))))) (defmethod initialize-instance :after ((template css-selector-template) &key css-specifiers parent) (let* ((spec (template-spec template)) (specifiers-and-vars (or css-specifiers (if (%spec-includes-opts spec) (cddr spec) (rest spec))))) (setf (slot-value template 'specifiers) (parse-specifiers specifiers-and-vars template parent)))) ;; Don't bother trying to save :parser when compiling (defmethod make-load-form ((object css-selector-template) &optional env) (declare (ignore env)) `(make-template ',(first (template-spec object)) ',(template-spec object)))