Fix missing `without-special-symbol-access' in `funcall-with-attribute-context'
[clinton/lisp-on-lines.git] / src / standard-descriptions / edit.lisp
CommitLineData
4358148e 1(in-package :lisp-on-lines)
2
4358148e 3(define-description editable ()
4 ()
5 (:mixinp t))
6
eeed4326 7(define-layered-class define-description-attribute
f4efa7ff 8 :in-layer #.(defining-description 'editable)
9 ()
10 ((edit-attribute-p
11 :initform :inherit
12 :layered-accessor attribute-editp
13 :initarg :editp
eeed4326 14 :layered t
15 :special t)
f4efa7ff 16 (setter
17 :initarg :setter
18 :layered t
eeed4326 19 :layered-accessor attribute-setter
f4efa7ff 20 :initform nil)
21 (attribute-editor
2548f054 22 :initarg :editor
f4efa7ff 23 :layered t
24 :accessor attribute-editor
2548f054 25 :initform (make-instance 'attribute-editor)
f4efa7ff 26 :documentation "This ones a bit odd")))
27
eeed4326 28(define-layered-method attribute-setter (object)
29 nil)
30
2548f054 31(defmethod shared-initialize :after ((object standard-attribute)
32 slots &rest args &key input &allow-other-keys)
33
34 (when input
35 (setf (attribute-editor object)
36 (apply #'make-instance (find-editor-class input)
37 input))))
38
39
40(defun find-editor-class (spec)
41 (let ((class (getf spec :class))
42 (type (getf spec :type)))
43 (or class (when
44 (and type (symbolp type))
45 (let ((name (format nil "~A-~A" type 'attribute-editor)))
ec6dde1e 46 (or (unless (eq (find-package :cl)
47 (symbol-package type))
48 (find-class (intern name (symbol-package type)) nil))
2548f054 49 (find-class (intern name) nil)
ec6dde1e 50 (find-class (intern name :lol) nil)
2548f054 51 'string-attribute-editor))))))
f4efa7ff 52
53(defclass attribute-editor ()
a5a635a2 54 ((class :initarg :class)
55 (type :initarg :type
2548f054 56 :initform 'string
57 :accessor attribute-editor-type)
f4efa7ff 58 (parser :initarg :parse-using
59 :initform 'identity
60 :accessor attribute-editor-parsing-function)
e8fd1a9a 61 (attributes :initarg :attributes
62 :initform nil
63 :accessor attribute-editor-attributes)
f4efa7ff 64 (prompt :initarg :prompt
2548f054 65 :initform nil)
66 (unbound-value
67 :initarg :unbound-value
68 :initform "")))
69
70
f4efa7ff 71
72(defclass string-attribute-editor (attribute-editor) ())
73(defclass text-attribute-editor (string-attribute-editor) ())
2548f054 74
75(deftype password () 'string)
76
f4efa7ff 77(defclass password-attribute-editor (string-attribute-editor) ())
78
79(defclass number-attribute-editor (attribute-editor) ()
80 (:default-initargs
81 :parse-using 'parse-number:PARSE-NUMBER
82 :type 'number))
83
84(defun parse-attribute-value (attribute value)
85 (funcall (attribute-editor-parsing-function
86 (attribute-editor attribute))
87 value))
88
89(define-layered-function display-attribute-editor (attribute)
90 (:method (attribute)
91 (setf (attribute-value attribute)
92 (funcall (attribute-editor-parsing-function
93 (attribute-editor attribute))
94 (read-line)))))
95
4358148e 96(define-description T ()
97 ((editp :label "Edit by Default?"
98 :value nil
99 :editp nil)
100 (identity :editp nil)
101 (type :editp nil)
102 (class :editp nil))
103 (:in-description editable))
104
b7657b86 105(define-layered-method (setf attribute-value-using-object)
106 :in-layer #.(defining-description 'editable)(value object attribute)
107
108 (let ((setter (attribute-setter attribute)))
109 (if setter
110 (funcall setter value object)
111 (error "No setter in ~A for ~A" attribute object))))
4358148e 112
4358148e 113
f4efa7ff 114(define-layered-function attribute-editp (attribute)
115 (:method (attribute) nil))
4358148e 116
117(define-layered-method attribute-editp
118 :in-layer #.(defining-description 'editable)
f4efa7ff 119 ((attribute standard-attribute))
2548f054 120 (let ((value (attribute-value attribute)))
eeed4326 121 (unless (or (unbound-slot-value-p value)
122 (typep value
2548f054 123 (attribute-editor-type
124 (attribute-editor attribute))))
eeed4326 125 (return-from attribute-editp nil)))
f4efa7ff 126 (let ((edit? (call-next-method)))
eeed4326 127
f4efa7ff 128 (if (eq :inherit edit?)
129 (attribute-value (find-attribute
130 (attribute-description attribute)
131 'editp))
132 edit?)))
4358148e 133
134
f4efa7ff 135(define-layered-method display-attribute-value
4358148e 136 :in-layer #.(defining-description 'editable)
f4efa7ff 137 ((attribute standard-attribute))
138 (if (attribute-editp attribute)
139 (display-attribute-editor attribute)
e8d4fa45 140 (call-next-method)))
4358148e 141
142
f4efa7ff 143
144
145
4358148e 146