Remove support for parameterized reactive layers (Format 4), only allow :props/:data etc with $-prefixed variables
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
This commit is contained in:
parent
c7db648e85
commit
e277b1e999
57
tp.el
57
tp.el
@ -2444,7 +2444,7 @@ The layer is stored in `tp-layer-alist'."
|
|||||||
(defmacro define-tp (name arglist &rest body)
|
(defmacro define-tp (name arglist &rest body)
|
||||||
"Define a text property layer named NAME.
|
"Define a text property layer named NAME.
|
||||||
|
|
||||||
This macro supports four formats:
|
This macro supports three formats:
|
||||||
|
|
||||||
Format 1 - Non-parameterized simple (empty arglist, simple body):
|
Format 1 - Non-parameterized simple (empty arglist, simple body):
|
||||||
(define-tp tp-bold ()
|
(define-tp tp-bold ()
|
||||||
@ -2454,7 +2454,7 @@ Format 2 - Parameterized simple (single argument, simple body):
|
|||||||
(define-tp tp-space (pixel)
|
(define-tp tp-space (pixel)
|
||||||
\\=`(display (space :width (,pixel))))
|
\\=`(display (space :width (,pixel))))
|
||||||
|
|
||||||
Format 3 - Non-parameterized with reactive features:
|
Format 3 - Non-parameterized with reactive features (requires $-prefixed variables):
|
||||||
(define-tp my-layer ()
|
(define-tp my-layer ()
|
||||||
:props \\='(face (:foreground $my-color))
|
:props \\='(face (:foreground $my-color))
|
||||||
:data \\='((my-color . \"red\"))
|
:data \\='((my-color . \"red\"))
|
||||||
@ -2462,12 +2462,6 @@ Format 3 - Non-parameterized with reactive features:
|
|||||||
:watch \\='((my-color (lambda (new old layer) (message \"Color changed!\"))))
|
:watch \\='((my-color (lambda (new old layer) (message \"Color changed!\"))))
|
||||||
:transform (lambda (text) (upcase text)))
|
:transform (lambda (text) (upcase text)))
|
||||||
|
|
||||||
Format 4 - Parameterized with reactive features:
|
|
||||||
(define-tp my-color-layer (color)
|
|
||||||
:props \\=`(face (:foreground ,color))
|
|
||||||
:data \\='((my-var . \"value\"))
|
|
||||||
:compute ...)
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
(tp-set \"emacs\" \\='tp-bold t)
|
(tp-set \"emacs\" \\='tp-bold t)
|
||||||
(tp-set 0 5 \\='(tp-bold t) \"emacs\")
|
(tp-set 0 5 \\='(tp-bold t) \"emacs\")
|
||||||
@ -2480,7 +2474,7 @@ ARGLIST must be either:
|
|||||||
BODY is either:
|
BODY is either:
|
||||||
- A single property list expression (simple format)
|
- A single property list expression (simple format)
|
||||||
- Keyword arguments starting with :props, :data, :compute, :watch, or :transform
|
- Keyword arguments starting with :props, :data, :compute, :watch, or :transform
|
||||||
(reactive format)
|
(reactive format - only for non-parameterized layers with $-prefixed variables)
|
||||||
|
|
||||||
Note: NAME cannot be a built-in Emacs text property name like `face',
|
Note: NAME cannot be a built-in Emacs text property name like `face',
|
||||||
`display', `invisible', etc. See `tp--builtin-text-properties' for the
|
`display', `invisible', etc. See `tp--builtin-text-properties' for the
|
||||||
@ -2495,13 +2489,9 @@ complete list of reserved names."
|
|||||||
(let ((first-elem (car body)))
|
(let ((first-elem (car body)))
|
||||||
(if (and (keywordp first-elem)
|
(if (and (keywordp first-elem)
|
||||||
(memq first-elem '(:props :data :compute :watch :transform)))
|
(memq first-elem '(:props :data :compute :watch :transform)))
|
||||||
;; Reactive format
|
;; Reactive format - only allowed for non-parameterized layers
|
||||||
(if arglist
|
(if arglist
|
||||||
;; Parameterized reactive: store as function that calls tp--define-layer-internal
|
(error "define-tp: reactive keywords (:props, :data, :compute, :watch, :transform) are only supported for non-parameterized layers (empty arglist)")
|
||||||
(let ((arg (car arglist)))
|
|
||||||
`(tp--define-layer-parameterized-reactive
|
|
||||||
',name ',arglist
|
|
||||||
(lambda (,arg) (list ,@body))))
|
|
||||||
;; Non-parameterized reactive: use tp--define-layer-internal directly
|
;; Non-parameterized reactive: use tp--define-layer-internal directly
|
||||||
`(tp--define-layer-internal ',name ,@body))
|
`(tp--define-layer-internal ',name ,@body))
|
||||||
;; Simple format (original behavior)
|
;; Simple format (original behavior)
|
||||||
@ -2517,19 +2507,6 @@ complete list of reserved names."
|
|||||||
(t
|
(t
|
||||||
(error "define-tp ARGLIST must be empty or contain exactly one symbol")))))))
|
(error "define-tp ARGLIST must be empty or contain exactly one symbol")))))))
|
||||||
|
|
||||||
(defun tp--define-layer-parameterized-reactive (name arglist body-fn)
|
|
||||||
"Define a parameterized layer NAME with ARGLIST and reactive BODY-FN.
|
|
||||||
BODY-FN is a function that takes the parameter and returns a keyword plist
|
|
||||||
like (:props ... :data ... :compute ... :watch ... :transform ...).
|
|
||||||
The layer is stored and evaluated when tp-layer-props-with-arg is called."
|
|
||||||
;; Store the parameterized reactive definition
|
|
||||||
;; Format: (ARGLIST BODY-FN) where BODY-FN returns keyword plist
|
|
||||||
(let ((entry (list arglist body-fn)))
|
|
||||||
(if (assoc name tp-layer-alist)
|
|
||||||
(setf (cdr (assoc name tp-layer-alist)) entry)
|
|
||||||
(push (cons name entry) tp-layer-alist)))
|
|
||||||
(assoc name tp-layer-alist))
|
|
||||||
|
|
||||||
(defun tp--define-layer-unified (name arglist body)
|
(defun tp--define-layer-unified (name arglist body)
|
||||||
"Define a layer NAME with ARGLIST and BODY using unified structure.
|
"Define a layer NAME with ARGLIST and BODY using unified structure.
|
||||||
For non-parameterized layers, ARGLIST is nil and BODY is the evaluated plist.
|
For non-parameterized layers, ARGLIST is nil and BODY is the evaluated plist.
|
||||||
@ -2900,31 +2877,15 @@ where ARGLIST is a non-nil list of argument symbols."
|
|||||||
"Return properties for parameterized layer LAYER-NAME with ARG.
|
"Return properties for parameterized layer LAYER-NAME with ARG.
|
||||||
Evaluates the body form with the argument bound to the parameter.
|
Evaluates the body form with the argument bound to the parameter.
|
||||||
If INCLUDE-TP-NAME is non-nil, appends 'tp-name property to identify the layer.
|
If INCLUDE-TP-NAME is non-nil, appends 'tp-name property to identify the layer.
|
||||||
Recursively expands any nested layer names in the returned plist.
|
Recursively expands any nested layer names in the returned plist."
|
||||||
|
|
||||||
Handles two storage formats:
|
|
||||||
1. Simple parameterized: (ARGLIST BODY-FORM) - evaluate BODY-FORM with arg bound
|
|
||||||
2. Reactive parameterized: (ARGLIST FUNCTION) - call FUNCTION with arg to get keyword plist"
|
|
||||||
(when-let ((entry (cdr (assoc layer-name tp-layer-alist))))
|
(when-let ((entry (cdr (assoc layer-name tp-layer-alist))))
|
||||||
;; entry is (ARGLIST BODY-FORM) or (ARGLIST FUNCTION)
|
;; entry is (ARGLIST BODY-FORM)
|
||||||
(let ((arglist (car entry))
|
(let ((arglist (car entry))
|
||||||
(body (cadr entry)))
|
(body (cadr entry)))
|
||||||
(when arglist ; Only for parameterized layers
|
(when arglist ; Only for parameterized layers
|
||||||
(let* ((arg-sym (car arglist))
|
(let* ((arg-sym (car arglist))
|
||||||
;; Check if body is a function (reactive parameterized layer)
|
;; Evaluate the body with the argument bound
|
||||||
(result (if (functionp body)
|
(plist (eval `(let ((,arg-sym ',arg)) ,body))))
|
||||||
;; Reactive parameterized: call the function with arg
|
|
||||||
(funcall body arg)
|
|
||||||
;; Simple parameterized: evaluate with arg bound
|
|
||||||
(eval `(let ((,arg-sym ',arg)) ,body))))
|
|
||||||
;; For reactive parameterized, result is (:props ... :data ...), extract :props
|
|
||||||
(plist (if (and (listp result)
|
|
||||||
(keywordp (car result))
|
|
||||||
(eq (car result) :props))
|
|
||||||
;; It's a reactive keyword plist - get the :props value
|
|
||||||
(plist-get result :props)
|
|
||||||
;; It's already a direct plist
|
|
||||||
result)))
|
|
||||||
(when plist
|
(when plist
|
||||||
;; Recursively expand nested layer names
|
;; Recursively expand nested layer names
|
||||||
(when (tp--plist-has-layer-key-p plist)
|
(when (tp--plist-has-layer-key-p plist)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user