Fix define-tps to set multi-layer properties with tp-layers structure

Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-01-04 12:54:36 +00:00
parent a481327727
commit b58065293b
2 changed files with 34 additions and 38 deletions

View File

@ -2104,7 +2104,7 @@ When using tp-regexp-add (direct property setting), tp-name is NOT added."
(ert-deftest tp-test-set-with-group-name () (ert-deftest tp-test-set-with-group-name ()
"Test tp-set accepts a group name defined by define-tps. "Test tp-set accepts a group name defined by define-tps.
When using tp-set (direct property setting), tp-name is NOT added." When using tp-set with a group, layers are set with tp-name and tp-layers."
(tp-test-with-temp-buffer (tp-test-with-temp-buffer
(insert "Hello World") (insert "Hello World")
(define-tps my-group () (define-tps my-group ()
@ -2113,30 +2113,29 @@ When using tp-set (direct property setting), tp-name is NOT added."
(tp-set 1 6 'my-group) (tp-set 1 6 'my-group)
(should (eq (tp-at 1 'face) 'bold)) (should (eq (tp-at 1 'face) 'bold))
(should (equal (tp-at 1 'help-echo) "grouped")) (should (equal (tp-at 1 'help-echo) "grouped"))
;; tp-name should NOT be set for direct property setting ;; tp-name should be set for layer groups
(should-not (tp-at 1 'tp-name)))) (should (tp-at 1 'tp-name))))
(ert-deftest tp-test-set-with-group-name-multiple-layers () (ert-deftest tp-test-set-with-group-name-multiple-layers ()
"Test tp-set with group containing multiple layers. "Test tp-set with group containing multiple layers.
When using tp-set (direct property setting), tp-name and tp-layers are NOT added. When using tp-set with a group, all layers are set with tp-name and tp-layers."
Only the first layer's properties are applied."
(tp-test-with-temp-buffer (tp-test-with-temp-buffer
(insert "Hello World") (insert "Hello World")
(define-tps my-group () (define-tps my-group ()
'("first" . (face bold)) '("first" . (face bold))
'("second" . (face italic))) '("second" . (face italic)))
;; Use group name - only first layer is applied (no layer stacking for direct setting) ;; Use group name - all layers are applied with tp-layers structure
(tp-set 1 6 'my-group) (tp-set 1 6 'my-group)
;; First layer's properties are applied ;; First layer's properties are applied at top
(should (eq (tp-at 1 'face) 'bold)) (should (eq (tp-at 1 'face) 'bold))
;; tp-name should NOT be set for direct property setting ;; tp-name should be set for the top layer
(should-not (tp-at 1 'tp-name)) (should (tp-at 1 'tp-name))
;; tp-layers should NOT be set for direct property setting ;; tp-layers should contain the rest of the layers
(should-not (tp-at 1 'tp-layers)))) (should (tp-at 1 'tp-layers))))
(ert-deftest tp-test-match-set-with-group-name () (ert-deftest tp-test-match-set-with-group-name ()
"Test tp-match-set accepts a group name. "Test tp-match-set accepts a group name.
When using tp-match-set (direct property setting), tp-name is NOT added." When using tp-match-set with a group, layers are set with tp-name."
(tp-test-with-temp-buffer (tp-test-with-temp-buffer
(insert "Hello World Hello") (insert "Hello World Hello")
(define-tps my-group () (define-tps my-group ()
@ -2144,8 +2143,8 @@ When using tp-match-set (direct property setting), tp-name is NOT added."
(tp-match-set "Hello" 'my-group) (tp-match-set "Hello" 'my-group)
(should (eq (tp-at 1 'face) 'italic)) (should (eq (tp-at 1 'face) 'italic))
(should (eq (tp-at 13 'face) 'italic)) (should (eq (tp-at 13 'face) 'italic))
;; tp-name should NOT be set for direct property setting ;; tp-name should be set for layer groups
(should-not (tp-at 1 'tp-name)))) (should (tp-at 1 'tp-name))))
(ert-deftest tp-test-resolve-props-returns-nil-for-unknown () (ert-deftest tp-test-resolve-props-returns-nil-for-unknown ()
"Test tp--resolve-props returns nil for unknown layer name." "Test tp--resolve-props returns nil for unknown layer name."

45
tp.el
View File

@ -2994,16 +2994,14 @@ Returns the expanded plist."
(tp-layer-props key nil)) ; no tp-name (tp-layer-props key nil)) ; no tp-name
;; Parameterized layer group - evaluate with the argument (val) ;; Parameterized layer group - evaluate with the argument (val)
((tp-group-parameterized-p key) ((tp-group-parameterized-p key)
(when-let ((layer-props-list (tp-group-props-with-arg key val nil))) (when-let ((layer-props-list (tp-group-props-with-arg key val t)))
;; Merge all layers' properties (reverse so first layer wins) ;; Build layered structure: first layer at top, rest in tp-layers
(apply #'append (reverse layer-props-list)))) (tp--build-layer-props layer-props-list)))
;; Non-parameterized layer group - merge all layers' properties ;; Non-parameterized layer group - build layered structure
((assoc key tp-layer-groups) ((assoc key tp-layer-groups)
(when-let ((layer-props-list (tp-group-props key))) (when-let ((layer-props-list (tp-group-props key t)))
;; For direct property setting, merge all layers' properties ;; Build layered structure: first layer at top, rest in tp-layers
;; without the tp-layers structure. (tp--build-layer-props layer-props-list))))))
;; Reverse so first layer's properties are applied last (take precedence)
(apply #'append (reverse layer-props-list)))))))
(when layer-props (when layer-props
;; Recursively expand if the layer props contain more layer names ;; Recursively expand if the layer props contain more layer names
(when (tp--plist-has-layer-key-p layer-props) (when (tp--plist-has-layer-key-p layer-props)
@ -3076,16 +3074,14 @@ For group names, includes `tp-layers' property with the full layer stack."
(tp-layer-props first-elem nil)) ; no tp-name (tp-layer-props first-elem nil)) ; no tp-name
;; Parameterized layer group - evaluate with the argument ;; Parameterized layer group - evaluate with the argument
((tp-group-parameterized-p first-elem) ((tp-group-parameterized-p first-elem)
(when-let ((layer-props-list (tp-group-props-with-arg first-elem second-elem nil))) (when-let ((layer-props-list (tp-group-props-with-arg first-elem second-elem t)))
;; Merge all layers' properties (reverse so first layer wins) ;; Build layered structure: first layer at top, rest in tp-layers
(apply #'append (reverse layer-props-list)))) (tp--build-layer-props layer-props-list)))
;; Non-parameterized layer group - merge all layers' properties ;; Non-parameterized layer group - build layered structure
((assoc first-elem tp-layer-groups) ((assoc first-elem tp-layer-groups)
(when-let ((layer-props-list (tp-group-props first-elem))) (when-let ((layer-props-list (tp-group-props first-elem t)))
;; For direct property setting, merge all layers' properties ;; Build layered structure: first layer at top, rest in tp-layers
;; without the tp-layers structure. (tp--build-layer-props layer-props-list))))))
;; Reverse so first layer's properties are applied last (take precedence)
(apply #'append (reverse layer-props-list)))))))
;; Recursively resolve extra properties (they may also contain layer names) ;; Recursively resolve extra properties (they may also contain layer names)
(let ((expanded-props (let ((expanded-props
(if (and layer-props extra-props) (if (and layer-props extra-props)
@ -3174,13 +3170,14 @@ For group names, includes `tp-layers' property with the full layer stack."
;; Check layer - get props without tp-name for direct property setting ;; Check layer - get props without tp-name for direct property setting
((assoc props tp-layer-alist) ((assoc props tp-layer-alist)
(tp-layer-props props nil)) ; no tp-name (tp-layer-props props nil)) ; no tp-name
;; Check group - merge all layers' properties for direct setting ;; Check group - build layered structure with tp-layers
((assoc props tp-layer-groups) ((assoc props tp-layer-groups)
(when-let ((layer-props-list (tp-group-props props))) (when-let ((layer-props-list (tp-group-props props t))) ; include tp-name
;; For direct property setting, merge all layers' properties ;; Build layered structure: first layer at top, rest in tp-layers
;; without the tp-layers structure. (tp--build-layer-props layer-props-list)))
;; Reverse so first layer's properties are applied last (take precedence) ;; Parameterized group without argument - cannot resolve, return nil
(apply #'append (reverse layer-props-list)))) ((tp-group-parameterized-p props)
nil)
;; Not found - return nil (let caller decide how to handle) ;; Not found - return nil (let caller decide how to handle)
(t nil))) (t nil)))
(t nil))) (t nil)))