Fix multi-action form.
[clinton/lisp-on-lines.git] / src / display.lisp
CommitLineData
e7c5f95a 1(in-package :lisp-on-lines)
2
4358148e 3(defvar *description*)
e7c5f95a 4(defvar *display*)
6de8d300 5(defvar *object* nil)
6
4358148e 7
8(deflayer display-layer)
e7c5f95a 9
10(define-layered-function display-using-description (description display object &rest args)
11 (:documentation
12 "Displays OBJECT via description using/in/with/on display"))
13
4271ab0b 14(defun display (display object &rest args &key attributes )
15 (let ((*display-attributes* attributes))
6de8d300 16 (apply #'display-using-description (description-of object) display object args)))
e7c5f95a 17
18(define-layered-method display-using-description
19 :around (description display object &rest args)
4358148e 20 (declare (ignorable args))
21 (let ((*description* description)
22 (*display* display)
e7c5f95a 23 (*object* object))
e8d4fa45 24 (dletf (((described-object description) object))
6de8d300 25 (contextl::funcall-with-special-initargs
26 (loop
27 :for (key val) :on args :by #'cddr
28 :collect (list (find key (description-attributes description)
29 :key #'attribute-keyword)
30 :value val))
31 (lambda ()
32 (contextl::funcall-with-special-initargs
33 (let ((attribute (find-attribute description 'active-attributes)))
34 (when attribute
e8d4fa45 35 (loop for spec in (attribute-value attribute)
6de8d300 36 if (listp spec)
37 collect (cons (or
38 (find-attribute description (car spec))
39 (error "No attribute matching ~A" (car spec)))
40 (cdr spec)))))
41 (lambda ()
e8d4fa45 42 (call-next-method))))))))
6de8d300 43
44
e7c5f95a 45
4271ab0b 46(defun display/d (&rest args)
47 (apply #'display-using-description args))
48
e7c5f95a 49(define-layered-method display-using-description (description display object &rest args)
50 (error "No DISPLAY-USING-DESCRIPTION methods are specified for: ~% DESCRIPTION: ~A ~% DISPLAY: ~A ~% OBJECT: ~A ~% ARGS: ~S
51
52OMGWTF! If you didn't do this, it's a bug!" description display object args))
53
e7c5f95a 54(defmacro define-display (&body body)
4358148e 55 (loop with in-descriptionp = (eq (car body) :in-description)
56 with description = (if in-descriptionp (cadr body) 't)
57 for tail on (if in-descriptionp (cddr body) body)
e7c5f95a 58 until (listp (car tail))
59 collect (car tail) into qualifiers
60 finally
4358148e 61 (when (member :in-description qualifiers)
62 (error "Incorrect occurrence of :in-description in defdisplay. Must occur before qualifiers."))
e7c5f95a 63 (return
64 (destructuring-bind (description-spec &optional (display-spec (gensym)) (object-spec (gensym)))
65 (car tail)
66 `(define-layered-method
67 display-using-description
4358148e 68 :in-layer ,(if (eq t description)
69 t
70 (defining-description description))
e7c5f95a 71 ,@qualifiers
72 (,(if (listp description-spec)
73 (list (first description-spec)
74 (if (eq 'description (second description-spec))
75 'description
76 (defining-description (second description-spec)))))
77 ,display-spec
78 ,object-spec &rest args)
79 (declare (ignorable args))
80 ,@(cdr tail))))))
81
82
83
84