Support parameterized and non-parameterized define-tp layers in tp-push-layer/tp-put-layer

Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2025-12-28 18:39:10 +00:00
parent aafbeff1a4
commit e9cb90cce7
2 changed files with 78 additions and 9 deletions

View File

@ -3330,5 +3330,46 @@ When using tp-set (direct property setting), tp-name is NOT added."
(should (equal (get-text-property 0 'test1 result) "value1"))
(should (equal (get-text-property 0 'test2 result) "value2")))))
;; Tests for tp-push-layer and tp-put-layer with define-tp layers
(ert-deftest tp-test-push-layer-non-parameterized ()
"Test tp-push-layer with non-parameterized define-tp layer."
(tp-test-with-temp-buffer
(define-tp tp-bold ()
'(face bold))
;; String form
(let ((result (tp-push-layer "emacs" 'tp-bold)))
(should (eq (get-text-property 0 'tp-name result) 'tp-bold))
(should (eq (get-text-property 0 'face result) 'bold)))))
(ert-deftest tp-test-push-layer-parameterized ()
"Test tp-push-layer with parameterized define-tp layer."
(tp-test-with-temp-buffer
(define-tp tp-space (pixel)
`(display (space :width (,pixel))))
;; String form with parameterized layer
(let ((result (tp-push-layer "emacs" '(tp-space 6))))
(should (eq (get-text-property 0 'tp-name result) 'tp-space))
(should (equal (get-text-property 0 'display result) '(space :width (6)))))))
(ert-deftest tp-test-put-layer-non-parameterized ()
"Test tp-put-layer with non-parameterized define-tp layer."
(tp-test-with-temp-buffer
(define-tp tp-italic ()
'(face italic))
;; String form
(let ((result (tp-put-layer "emacs" 'tp-italic 0)))
(should (eq (get-text-property 0 'tp-name result) 'tp-italic))
(should (eq (get-text-property 0 'face result) 'italic)))))
(ert-deftest tp-test-put-layer-parameterized ()
"Test tp-put-layer with parameterized define-tp layer."
(tp-test-with-temp-buffer
(define-tp tp-width (pixels)
`(display (space :width (,pixels))))
;; String form with parameterized layer
(let ((result (tp-put-layer "emacs" '(tp-width 10) 0)))
(should (eq (get-text-property 0 'tp-name result) 'tp-width))
(should (equal (get-text-property 0 'display result) '(space :width (10)))))))
(provide 'tp-ert-tests)
;;; tp-ert-tests.el ends here

42
tp.el
View File

@ -2733,20 +2733,48 @@ Returns a list of (START END PROPERTIES) for matching intervals."
(defun tp--normalize-layer-spec (layer-spec)
"Normalize LAYER-SPEC to a plist with tp-name.
Used by layer stack functions that need tp-name for identification."
Used by layer stack functions that need tp-name for identification.
LAYER-SPEC can be:
- A symbol (non-parameterized layer name from define-tp or tp-define-layer)
- A list (LAYER-NAME ARG) for parameterized layers from define-tp
- A plist for inline layer definition
- A list (NAME &rest PLIST) for named inline layer"
(cond
;; Symbol - look up in tp-layer-alist
;; Symbol - look up in tp-layer-alist (non-parameterized layer)
((symbolp layer-spec)
(cond
;; Parameterized layer symbol without arg - error
((tp-layer-parameterized-p layer-spec)
(error "Parameterized layer %S requires an argument, use '(%S arg)"
layer-spec layer-spec))
;; Non-parameterized layer or old-format layer
((assoc layer-spec tp-layer-alist)
(or (tp-layer-props layer-spec t) ; include tp-name for layer stack
(error "Layer %S not found in tp-layer-alist" layer-spec)))
;; List starting with symbol followed by plist - named inline layer (name &rest plist)
(t (error "Layer %S not found in tp-layer-alist" layer-spec))))
;; List starting with symbol - check if it's a parameterized layer
((and (listp layer-spec)
(symbolp (car layer-spec))
(not (keywordp (car layer-spec)))
(cdr layer-spec))
(not (keywordp (car layer-spec))))
(let ((name (car layer-spec))
(props (cdr layer-spec)))
(append props (list 'tp-name name))))
(rest (cdr layer-spec)))
(cond
;; Parameterized layer: (LAYER-NAME ARG)
((and (tp-layer-parameterized-p name)
(= (length rest) 1))
(or (tp-layer-props-with-arg name (car rest) t) ; include tp-name
(error "Failed to resolve parameterized layer %S with arg %S"
name (car rest))))
;; Named inline layer: (NAME &rest PLIST)
(rest
(append rest (list 'tp-name name)))
;; Just a symbol in a list - treat as non-parameterized layer
((null rest)
(or (tp-layer-props name t)
(error "Layer %S not found in tp-layer-alist" name))))))
;; Plist (starts with keyword or property name)
((and (listp layer-spec) layer-spec)
layer-spec)