Support layer properties at any position in plist
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
This commit is contained in:
parent
e4729668ed
commit
c701a1ca75
41
tp-tests.el
41
tp-tests.el
@ -3258,5 +3258,46 @@ the inserted text should be that string, not the source text."
|
|||||||
(should (equal (get-text-property 0 'display result) '(space :width (6))))
|
(should (equal (get-text-property 0 'display result) '(space :width (6))))
|
||||||
(should (equal (get-text-property 0 'face result) '(:foreground "green"))))))
|
(should (equal (get-text-property 0 'face result) '(:foreground "green"))))))
|
||||||
|
|
||||||
|
(ert-deftest tp-test-layer-at-any-position-string ()
|
||||||
|
"Test layer properties can be at any position in string form."
|
||||||
|
(tp-test-with-temp-buffer
|
||||||
|
(define-tp tp-space (pixel)
|
||||||
|
`(display (space :width (,pixel))))
|
||||||
|
;; Layer in the middle of the plist
|
||||||
|
(let ((result (tp-set "emacs"
|
||||||
|
'face '(:foreground "green")
|
||||||
|
'tp-space 6
|
||||||
|
'test "test")))
|
||||||
|
(should (eq (get-text-property 0 'tp-name result) 'tp-space))
|
||||||
|
(should (equal (get-text-property 0 'display result) '(space :width (6))))
|
||||||
|
(should (equal (get-text-property 0 'face result) '(:foreground "green")))
|
||||||
|
(should (equal (get-text-property 0 'test result) "test")))))
|
||||||
|
|
||||||
|
(ert-deftest tp-test-layer-at-any-position-region ()
|
||||||
|
"Test layer properties can be at any position in region form."
|
||||||
|
(tp-test-with-temp-buffer
|
||||||
|
(define-tp tp-space (pixel)
|
||||||
|
`(display (space :width (,pixel))))
|
||||||
|
;; Layer in the middle of the plist
|
||||||
|
(let ((result (tp-set 0 5 '(face (:foreground "green") tp-space 6 test "test") "emacs")))
|
||||||
|
(should (eq (get-text-property 0 'tp-name result) 'tp-space))
|
||||||
|
(should (equal (get-text-property 0 'display result) '(space :width (6))))
|
||||||
|
(should (equal (get-text-property 0 'face result) '(:foreground "green")))
|
||||||
|
(should (equal (get-text-property 0 'test result) "test")))))
|
||||||
|
|
||||||
|
(ert-deftest tp-test-non-param-layer-at-any-position ()
|
||||||
|
"Test non-parameterized layer at any position."
|
||||||
|
(tp-test-with-temp-buffer
|
||||||
|
(define-tp tp-bold ()
|
||||||
|
'(face bold))
|
||||||
|
;; Layer in the middle of the plist
|
||||||
|
(let ((result (tp-set "emacs"
|
||||||
|
'test1 "value1"
|
||||||
|
'tp-bold t
|
||||||
|
'test2 "value2")))
|
||||||
|
(should (eq (get-text-property 0 'tp-name result) 'tp-bold))
|
||||||
|
(should (equal (get-text-property 0 'test1 result) "value1"))
|
||||||
|
(should (equal (get-text-property 0 'test2 result) "value2")))))
|
||||||
|
|
||||||
(provide 'tp-ert-tests)
|
(provide 'tp-ert-tests)
|
||||||
;;; tp-ert-tests.el ends here
|
;;; tp-ert-tests.el ends here
|
||||||
|
|||||||
63
tp.el
63
tp.el
@ -2452,6 +2452,46 @@ Appends 'tp-name property to identify the layer."
|
|||||||
(tp-layer-props layer))
|
(tp-layer-props layer))
|
||||||
layers)))
|
layers)))
|
||||||
|
|
||||||
|
(defun tp--is-layer-name-p (sym)
|
||||||
|
"Return non-nil if SYM is a defined layer, parameterized layer, or group name."
|
||||||
|
(and (symbolp sym)
|
||||||
|
(or (assoc sym tp-layer-alist)
|
||||||
|
(assoc sym tp-layer-params)
|
||||||
|
(assoc sym tp-layer-groups))))
|
||||||
|
|
||||||
|
(defun tp--expand-layer-in-plist (props)
|
||||||
|
"Expand any layer names found in PROPS plist.
|
||||||
|
Scans through PROPS treating it as a plist (key value pairs).
|
||||||
|
When a key is a layer/group name, expands it with its properties.
|
||||||
|
Returns the expanded plist."
|
||||||
|
(let ((result nil)
|
||||||
|
(remaining props))
|
||||||
|
(while remaining
|
||||||
|
(let ((key (car remaining))
|
||||||
|
(val (cadr remaining)))
|
||||||
|
(cond
|
||||||
|
;; Key is a layer/parameterized layer/group name - expand it
|
||||||
|
((tp--is-layer-name-p key)
|
||||||
|
(let ((layer-props
|
||||||
|
(cond
|
||||||
|
;; Parameterized layer - evaluate with the argument (val)
|
||||||
|
((tp-layer-parameterized-p key)
|
||||||
|
(tp-layer-props-with-arg key val))
|
||||||
|
;; Non-parameterized layer - val should be t
|
||||||
|
((assoc key tp-layer-alist)
|
||||||
|
(tp-layer-props key))
|
||||||
|
;; Layer group
|
||||||
|
((assoc key tp-layer-groups)
|
||||||
|
(when-let ((layer-props-list (tp-group-props key)))
|
||||||
|
(tp--build-layer-props layer-props-list))))))
|
||||||
|
(when layer-props
|
||||||
|
(setq result (append result layer-props)))))
|
||||||
|
;; Regular property - keep as-is
|
||||||
|
(t
|
||||||
|
(setq result (append result (list key val)))))
|
||||||
|
(setq remaining (cddr remaining))))
|
||||||
|
result))
|
||||||
|
|
||||||
(defun tp--resolve-props (props)
|
(defun tp--resolve-props (props)
|
||||||
"Resolve PROPS to a property list with layer metadata.
|
"Resolve PROPS to a property list with layer metadata.
|
||||||
PROPS can be:
|
PROPS can be:
|
||||||
@ -2461,6 +2501,7 @@ PROPS can be:
|
|||||||
for parameterized layers
|
for parameterized layers
|
||||||
- A list starting with (LAYER-NAME ARG EXTRA-PROPS...) where extra properties
|
- A list starting with (LAYER-NAME ARG EXTRA-PROPS...) where extra properties
|
||||||
are merged with the layer properties
|
are merged with the layer properties
|
||||||
|
- A plist with layer names at any position - they will be expanded inline
|
||||||
- A plist (handles anonymous layers with reactive variables)
|
- A plist (handles anonymous layers with reactive variables)
|
||||||
|
|
||||||
If PROPS is a symbol:
|
If PROPS is a symbol:
|
||||||
@ -2472,6 +2513,10 @@ If PROPS is (LAYER-NAME ARG) or (LAYER-NAME ARG EXTRA-PROPS...):
|
|||||||
- For parameterized layers: evaluates the body with ARG and returns the result
|
- For parameterized layers: evaluates the body with ARG and returns the result
|
||||||
- Extra properties after ARG are appended to the layer properties
|
- Extra properties after ARG are appended to the layer properties
|
||||||
|
|
||||||
|
If PROPS is a plist with layer names at any position:
|
||||||
|
- Layer names are expanded inline with their properties
|
||||||
|
- Other properties are preserved in order
|
||||||
|
|
||||||
If PROPS is a plist:
|
If PROPS is a plist:
|
||||||
- If it contains reactive variables ($...), generates a UUID for `tp-name',
|
- If it contains reactive variables ($...), generates a UUID for `tp-name',
|
||||||
registers reactive dependencies, and returns the resolved props with `tp-name'.
|
registers reactive dependencies, and returns the resolved props with `tp-name'.
|
||||||
@ -2489,13 +2534,10 @@ For group names, includes `tp-layers' property with the full layer stack."
|
|||||||
(second-elem (cadr props))
|
(second-elem (cadr props))
|
||||||
(extra-props (cddr props)))
|
(extra-props (cddr props)))
|
||||||
(cond
|
(cond
|
||||||
;; Handle (layer-name arg ...) format for defined layers
|
;; Handle (layer-name arg ...) format for defined layers at the START
|
||||||
;; This includes both (layer-name arg) and (layer-name arg extra-prop val ...)
|
;; This includes both (layer-name arg) and (layer-name arg extra-prop val ...)
|
||||||
((and (>= (length props) 2)
|
((and (>= (length props) 2)
|
||||||
(symbolp first-elem)
|
(tp--is-layer-name-p first-elem))
|
||||||
(or (assoc first-elem tp-layer-alist)
|
|
||||||
(assoc first-elem tp-layer-params)
|
|
||||||
(assoc first-elem tp-layer-groups)))
|
|
||||||
(let ((layer-props
|
(let ((layer-props
|
||||||
(cond
|
(cond
|
||||||
;; Parameterized layer - evaluate with the argument
|
;; Parameterized layer - evaluate with the argument
|
||||||
@ -2509,9 +2551,10 @@ For group names, includes `tp-layers' property with the full layer stack."
|
|||||||
((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)))
|
||||||
(tp--build-layer-props layer-props-list))))))
|
(tp--build-layer-props layer-props-list))))))
|
||||||
;; Append extra properties if any
|
;; Recursively resolve extra properties (they may also contain layer names)
|
||||||
(if (and layer-props extra-props)
|
(if (and layer-props extra-props)
|
||||||
(append layer-props extra-props)
|
(let ((resolved-extra (tp--expand-layer-in-plist extra-props)))
|
||||||
|
(append layer-props resolved-extra))
|
||||||
layer-props)))
|
layer-props)))
|
||||||
|
|
||||||
;; Handle single-element list containing a layer/group name symbol.
|
;; Handle single-element list containing a layer/group name symbol.
|
||||||
@ -2524,6 +2567,12 @@ For group names, includes `tp-layers' property with the full layer stack."
|
|||||||
;; It's a layer/group name wrapped in a list - recurse with the symbol
|
;; It's a layer/group name wrapped in a list - recurse with the symbol
|
||||||
(tp--resolve-props first-elem))
|
(tp--resolve-props first-elem))
|
||||||
|
|
||||||
|
;; Check if any key in the plist is a layer name (layer at any position)
|
||||||
|
((cl-some #'tp--is-layer-name-p
|
||||||
|
(cl-loop for (key _val) on props by #'cddr collect key))
|
||||||
|
;; Expand all layer names in the plist
|
||||||
|
(tp--expand-layer-in-plist props))
|
||||||
|
|
||||||
;; Normal plist processing
|
;; Normal plist processing
|
||||||
(t
|
(t
|
||||||
(let* ((existing-tp-name (plist-get props 'tp-name))
|
(let* ((existing-tp-name (plist-get props 'tp-name))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user