From e277b1e999f7c292027770b3c646518c596168d3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 4 Jan 2026 12:01:26 +0000 Subject: [PATCH] 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> --- tp.el | 57 +++++++++------------------------------------------------ 1 file changed, 9 insertions(+), 48 deletions(-) diff --git a/tp.el b/tp.el index 886e2ef..a9ea86c 100644 --- a/tp.el +++ b/tp.el @@ -2444,7 +2444,7 @@ The layer is stored in `tp-layer-alist'." (defmacro define-tp (name arglist &rest body) "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): (define-tp tp-bold () @@ -2454,7 +2454,7 @@ Format 2 - Parameterized simple (single argument, simple body): (define-tp tp-space (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 () :props \\='(face (:foreground $my-color)) :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!\")))) :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: (tp-set \"emacs\" \\='tp-bold t) (tp-set 0 5 \\='(tp-bold t) \"emacs\") @@ -2480,7 +2474,7 @@ ARGLIST must be either: BODY is either: - A single property list expression (simple format) - 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', `display', `invisible', etc. See `tp--builtin-text-properties' for the @@ -2495,13 +2489,9 @@ complete list of reserved names." (let ((first-elem (car body))) (if (and (keywordp first-elem) (memq first-elem '(:props :data :compute :watch :transform))) - ;; Reactive format + ;; Reactive format - only allowed for non-parameterized layers (if arglist - ;; Parameterized reactive: store as function that calls tp--define-layer-internal - (let ((arg (car arglist))) - `(tp--define-layer-parameterized-reactive - ',name ',arglist - (lambda (,arg) (list ,@body)))) + (error "define-tp: reactive keywords (:props, :data, :compute, :watch, :transform) are only supported for non-parameterized layers (empty arglist)") ;; Non-parameterized reactive: use tp--define-layer-internal directly `(tp--define-layer-internal ',name ,@body)) ;; Simple format (original behavior) @@ -2517,19 +2507,6 @@ complete list of reserved names." (t (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) "Define a layer NAME with ARGLIST and BODY using unified structure. 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. 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. -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" +Recursively expands any nested layer names in the returned plist." (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)) (body (cadr entry))) (when arglist ; Only for parameterized layers (let* ((arg-sym (car arglist)) - ;; Check if body is a function (reactive parameterized layer) - (result (if (functionp 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))) + ;; Evaluate the body with the argument bound + (plist (eval `(let ((,arg-sym ',arg)) ,body)))) (when plist ;; Recursively expand nested layer names (when (tp--plist-has-layer-key-p plist)