Remove tp-name from direct property setting, keep for layer stack and reactive
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
This commit is contained in:
parent
42c436494f
commit
aafbeff1a4
165
tp-tests.el
165
tp-tests.el
@ -253,10 +253,15 @@
|
||||
'(face underline)))))
|
||||
|
||||
(ert-deftest tp-test-layer-props ()
|
||||
"Test tp-layer-props returns properties with tp-name."
|
||||
"Test tp-layer-props returns properties, and tp-name when requested."
|
||||
(tp-test-with-temp-buffer
|
||||
(tp-define-layer 'my-layer '(face bold))
|
||||
;; Without tp-name (default for direct property setting)
|
||||
(let ((props (tp-layer-props 'my-layer)))
|
||||
(should (eq (plist-get props 'face) 'bold))
|
||||
(should-not (plist-get props 'tp-name)))
|
||||
;; With tp-name (for layer stack functions)
|
||||
(let ((props (tp-layer-props 'my-layer t)))
|
||||
(should (eq (plist-get props 'face) 'bold))
|
||||
(should (eq (plist-get props 'tp-name) 'my-layer)))))
|
||||
|
||||
@ -2036,7 +2041,8 @@ Returns list of (START END VALUE) intervals."
|
||||
;;; ============================================================
|
||||
|
||||
(ert-deftest tp-test-set-with-layer-name ()
|
||||
"Test tp-set accepts a layer name defined by define-tp."
|
||||
"Test tp-set accepts a layer name defined by tp-define-layer.
|
||||
When using tp-set (direct property setting), tp-name is NOT added."
|
||||
(tp-test-with-temp-buffer
|
||||
(insert "Hello World")
|
||||
(tp-define-layer 'my-style '(face bold help-echo "tip"))
|
||||
@ -2044,19 +2050,20 @@ Returns list of (START END VALUE) intervals."
|
||||
(tp-set 1 6 'my-style)
|
||||
(should (eq (tp-at 1 'face) 'bold))
|
||||
(should (equal (tp-at 1 'help-echo) "tip"))
|
||||
;; tp-name should be preserved for reactive text property support
|
||||
(should (eq (tp-at 1 'tp-name) 'my-style))))
|
||||
;; tp-name should NOT be set for direct property setting
|
||||
(should-not (tp-at 1 'tp-name))))
|
||||
|
||||
(ert-deftest tp-test-set-with-layer-name-on-string ()
|
||||
"Test tp-set accepts a layer name on string."
|
||||
"Test tp-set accepts a layer name on string.
|
||||
When using tp-set (direct property setting), tp-name is NOT added."
|
||||
(let ((str (copy-sequence "Hello World")))
|
||||
(setq tp-layer-alist nil)
|
||||
(setq tp-layer-groups nil)
|
||||
(tp-define-layer 'my-style '(face italic))
|
||||
(tp-set 0 5 'my-style str)
|
||||
(should (eq (get-text-property 0 'face str) 'italic))
|
||||
;; tp-name should be preserved for reactive text property support
|
||||
(should (eq (get-text-property 0 'tp-name str) 'my-style))))
|
||||
;; tp-name should NOT be set for direct property setting
|
||||
(should-not (get-text-property 0 'tp-name str))))
|
||||
|
||||
(ert-deftest tp-test-set-entire-string-with-layer-name ()
|
||||
"Test tp-set with layer name on entire string (string form).
|
||||
@ -2073,7 +2080,8 @@ incorrectly generate an anonymous tp-name instead of using the layer name."
|
||||
(should (equal (plist-get (get-text-property 0 'face str) :background) "blue")))))
|
||||
|
||||
(ert-deftest tp-test-reset-with-layer-name ()
|
||||
"Test tp-reset accepts a layer name defined by define-tp."
|
||||
"Test tp-reset accepts a layer name defined by tp-define-layer.
|
||||
When using tp-reset (direct property setting), tp-name is NOT added."
|
||||
(tp-test-with-temp-buffer
|
||||
(insert "Hello World")
|
||||
(tp-set 1 6 '(mouse-face highlight))
|
||||
@ -2082,11 +2090,12 @@ incorrectly generate an anonymous tp-name instead of using the layer name."
|
||||
(tp-reset 1 6 'my-style)
|
||||
(should (eq (tp-at 1 'face) 'underline))
|
||||
(should (null (tp-at 1 'mouse-face)))
|
||||
;; tp-name should be preserved
|
||||
(should (eq (tp-at 1 'tp-name) 'my-style))))
|
||||
;; tp-name should NOT be set for direct property setting
|
||||
(should-not (tp-at 1 'tp-name))))
|
||||
|
||||
(ert-deftest tp-test-add-with-layer-name ()
|
||||
"Test tp-add accepts a layer name defined by define-tp."
|
||||
"Test tp-add accepts a layer name defined by tp-define-layer.
|
||||
When using tp-add (direct property setting), tp-name is NOT added."
|
||||
(tp-test-with-temp-buffer
|
||||
(insert "Hello World")
|
||||
(tp-set 1 6 '(help-echo "existing"))
|
||||
@ -2095,11 +2104,12 @@ incorrectly generate an anonymous tp-name instead of using the layer name."
|
||||
(tp-add 1 6 'my-style)
|
||||
(should (eq (tp-at 1 'face) 'bold))
|
||||
(should (equal (tp-at 1 'help-echo) "existing"))
|
||||
;; tp-name should be preserved
|
||||
(should (eq (tp-at 1 'tp-name) 'my-style))))
|
||||
;; tp-name should NOT be set for direct property setting
|
||||
(should-not (tp-at 1 'tp-name))))
|
||||
|
||||
(ert-deftest tp-test-match-set-with-layer-name ()
|
||||
"Test tp-match-set accepts a layer name."
|
||||
"Test tp-match-set accepts a layer name.
|
||||
When using tp-match-set (direct property setting), tp-name is NOT added."
|
||||
(tp-test-with-temp-buffer
|
||||
(insert "Hello World Hello")
|
||||
(tp-define-layer 'match-style '(face bold help-echo "matched"))
|
||||
@ -2107,11 +2117,12 @@ incorrectly generate an anonymous tp-name instead of using the layer name."
|
||||
(should (eq (tp-at 1 'face) 'bold))
|
||||
(should (equal (tp-at 1 'help-echo) "matched"))
|
||||
(should (eq (tp-at 13 'face) 'bold))
|
||||
;; tp-name should be preserved
|
||||
(should (eq (tp-at 1 'tp-name) 'match-style))))
|
||||
;; tp-name should NOT be set for direct property setting
|
||||
(should-not (tp-at 1 'tp-name))))
|
||||
|
||||
(ert-deftest tp-test-match-set-with-layer-name-on-string ()
|
||||
"Test tp-match-set accepts a layer name on string."
|
||||
"Test tp-match-set accepts a layer name on string.
|
||||
When using tp-match-set (direct property setting), tp-name is NOT added."
|
||||
(let ((str (copy-sequence "Hello World Hello")))
|
||||
(setq tp-layer-alist nil)
|
||||
(setq tp-layer-groups nil)
|
||||
@ -2119,8 +2130,8 @@ incorrectly generate an anonymous tp-name instead of using the layer name."
|
||||
(tp-match-set "Hello" 'match-style str)
|
||||
(should (eq (get-text-property 0 'face str) 'italic))
|
||||
(should (eq (get-text-property 12 'face str) 'italic))
|
||||
;; tp-name should be preserved
|
||||
(should (eq (get-text-property 0 'tp-name str) 'match-style))))
|
||||
;; tp-name should NOT be set for direct property setting
|
||||
(should-not (get-text-property 0 'tp-name str))))
|
||||
|
||||
(ert-deftest tp-test-match-reset-with-layer-name ()
|
||||
"Test tp-match-reset accepts a layer name."
|
||||
@ -2173,7 +2184,8 @@ incorrectly generate an anonymous tp-name instead of using the layer name."
|
||||
(should (null (tp-at 5 'mouse-face)))))
|
||||
|
||||
(ert-deftest tp-test-regexp-add-with-layer-name ()
|
||||
"Test tp-regexp-add accepts a layer name."
|
||||
"Test tp-regexp-add accepts a layer name.
|
||||
When using tp-regexp-add (direct property setting), tp-name is NOT added."
|
||||
(tp-test-with-temp-buffer
|
||||
(insert "abc 123 def 456")
|
||||
(tp-set 5 8 '(help-echo "original"))
|
||||
@ -2181,42 +2193,44 @@ incorrectly generate an anonymous tp-name instead of using the layer name."
|
||||
(tp-regexp-add "[0-9]+" 'number-style)
|
||||
(should (eq (tp-at 5 'face) 'bold))
|
||||
(should (equal (tp-at 5 'help-echo) "original"))
|
||||
;; tp-name should be preserved
|
||||
(should (eq (tp-at 5 'tp-name) 'number-style))))
|
||||
;; tp-name should NOT be set for direct property setting
|
||||
(should-not (tp-at 5 'tp-name))))
|
||||
|
||||
(ert-deftest tp-test-set-with-group-name ()
|
||||
"Test tp-set accepts a group name defined by define-tp-group."
|
||||
"Test tp-set accepts a group name defined by define-tp-group.
|
||||
When using tp-set (direct property setting), tp-name is NOT added."
|
||||
(tp-test-with-temp-buffer
|
||||
(insert "Hello World")
|
||||
(tp-define-layer-group 'my-group
|
||||
'("style" . (face bold help-echo "grouped")))
|
||||
;; Use group name - should include tp-name for top layer
|
||||
;; Use group name
|
||||
(tp-set 1 6 'my-group)
|
||||
(should (eq (tp-at 1 'face) 'bold))
|
||||
(should (equal (tp-at 1 'help-echo) "grouped"))
|
||||
;; tp-name should be preserved for the top layer
|
||||
(should (eq (tp-at 1 'tp-name) 'my-group-style))))
|
||||
;; tp-name should NOT be set for direct property setting
|
||||
(should-not (tp-at 1 'tp-name))))
|
||||
|
||||
(ert-deftest tp-test-set-with-group-name-multiple-layers ()
|
||||
"Test tp-set with group containing multiple layers preserves tp-layers."
|
||||
"Test tp-set with group containing multiple layers.
|
||||
When using tp-set (direct property setting), tp-name and tp-layers are NOT added.
|
||||
Only the first layer's properties are applied."
|
||||
(tp-test-with-temp-buffer
|
||||
(insert "Hello World")
|
||||
(tp-define-layer-group 'my-group
|
||||
'("first" . (face bold))
|
||||
'("second" . (face italic)))
|
||||
;; Use group name - should include tp-layers for multiple layers
|
||||
;; Use group name - only first layer is applied (no layer stacking for direct setting)
|
||||
(tp-set 1 6 'my-group)
|
||||
;; First layer is on top
|
||||
;; First layer's properties are applied
|
||||
(should (eq (tp-at 1 'face) 'bold))
|
||||
(should (eq (tp-at 1 'tp-name) 'my-group-first))
|
||||
;; tp-layers should contain the second layer
|
||||
(let ((layers (tp-at 1 'tp-layers)))
|
||||
(should layers)
|
||||
(should (= (length layers) 1))
|
||||
(should (eq (plist-get (car layers) 'tp-name) 'my-group-second)))))
|
||||
;; tp-name should NOT be set for direct property setting
|
||||
(should-not (tp-at 1 'tp-name))
|
||||
;; tp-layers should NOT be set for direct property setting
|
||||
(should-not (tp-at 1 'tp-layers))))
|
||||
|
||||
(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."
|
||||
(tp-test-with-temp-buffer
|
||||
(insert "Hello World Hello")
|
||||
(tp-define-layer-group 'my-group
|
||||
@ -2224,8 +2238,8 @@ incorrectly generate an anonymous tp-name instead of using the layer name."
|
||||
(tp-match-set "Hello" 'my-group)
|
||||
(should (eq (tp-at 1 'face) 'italic))
|
||||
(should (eq (tp-at 13 'face) 'italic))
|
||||
;; tp-name should be preserved
|
||||
(should (eq (tp-at 1 'tp-name) 'my-group-style))))
|
||||
;; tp-name should NOT be set for direct property setting
|
||||
(should-not (tp-at 1 'tp-name))))
|
||||
|
||||
(ert-deftest tp-test-resolve-props-returns-nil-for-unknown ()
|
||||
"Test tp--resolve-props returns nil for unknown layer name."
|
||||
@ -2285,15 +2299,16 @@ preserving the native text property behavior."
|
||||
(makunbound 'tp-test-anon-color))))
|
||||
|
||||
(ert-deftest tp-test-set-anonymous-layer-preserves-existing-tp-name ()
|
||||
"Test that tp-set with anonymous plist preserves existing tp-name."
|
||||
"Test that tp-set with anonymous plist preserves existing tp-name property."
|
||||
(tp-test-with-temp-buffer
|
||||
(insert "Hello World")
|
||||
;; First set with a layer name
|
||||
;; First set with a layer name - this does NOT set tp-name
|
||||
(tp-define-layer 'my-existing-layer '(face bold))
|
||||
(tp-set 1 6 'my-existing-layer)
|
||||
(should (eq (tp-at 1 'tp-name) 'my-existing-layer))
|
||||
;; Now set with anonymous plist that already has tp-name
|
||||
(should-not (tp-at 1 'tp-name)) ; no tp-name for direct setting
|
||||
;; Now set with anonymous plist that has explicit tp-name
|
||||
(tp-set 1 6 '(face italic tp-name my-custom-name))
|
||||
;; Explicit tp-name in plist should be preserved
|
||||
(should (eq (tp-at 1 'tp-name) 'my-custom-name))))
|
||||
|
||||
(ert-deftest tp-test-match-set-anonymous-reactive-layer ()
|
||||
@ -3134,24 +3149,26 @@ the inserted text should be that string, not the source text."
|
||||
(should (equal (eval (cadr entry)) '(face bold))))))
|
||||
|
||||
(ert-deftest tp-test-define-tp-non-parameterized-usage-string ()
|
||||
"Test non-parameterized layer usage with string: (tp-set string 'layer-name t)."
|
||||
"Test non-parameterized layer usage with string: (tp-set string 'layer-name t).
|
||||
When using tp-set (direct property setting), tp-name is NOT added."
|
||||
(tp-test-with-temp-buffer
|
||||
(define-tp tp-bold ()
|
||||
'(face bold))
|
||||
(let ((result (tp-set "emacs" 'tp-bold t)))
|
||||
;; Result should have the correct properties
|
||||
(should (eq (get-text-property 0 'tp-name result) 'tp-bold))
|
||||
(should-not (get-text-property 0 'tp-name result)) ; no tp-name for direct setting
|
||||
(should (eq (get-text-property 0 'face result) 'bold)))))
|
||||
|
||||
(ert-deftest tp-test-define-tp-non-parameterized-usage-region ()
|
||||
"Test non-parameterized layer usage with region: (tp-set start end '(layer-name t))."
|
||||
"Test non-parameterized layer usage with region: (tp-set start end '(layer-name t)).
|
||||
When using tp-set (direct property setting), tp-name is NOT added."
|
||||
(tp-test-with-temp-buffer
|
||||
(insert "emacs")
|
||||
(define-tp tp-bold ()
|
||||
'(face bold))
|
||||
(tp-set 1 6 '(tp-bold t))
|
||||
;; Check properties in buffer
|
||||
(should (eq (tp-at 1 'tp-name) 'tp-bold))
|
||||
(should-not (tp-at 1 'tp-name)) ; no tp-name for direct setting
|
||||
(should (eq (tp-at 1 'face) 'bold))))
|
||||
|
||||
(ert-deftest tp-test-define-tp-parameterized ()
|
||||
@ -3168,33 +3185,36 @@ the inserted text should be that string, not the source text."
|
||||
(should (equal (car entry) '(pixel))))))
|
||||
|
||||
(ert-deftest tp-test-define-tp-parameterized-usage-string ()
|
||||
"Test parameterized layer usage with string: (tp-set string 'layer-name arg)."
|
||||
"Test parameterized layer usage with string: (tp-set string 'layer-name arg).
|
||||
When using tp-set (direct property setting), tp-name is NOT added."
|
||||
(tp-test-with-temp-buffer
|
||||
(define-tp tp-space (pixel)
|
||||
(list 'display (list 'space :width (list pixel))))
|
||||
(let ((result (tp-set "emacs" 'tp-space 2)))
|
||||
;; Result should have the correct properties
|
||||
(should (eq (get-text-property 0 'tp-name result) 'tp-space))
|
||||
(should-not (get-text-property 0 'tp-name result)) ; no tp-name for direct setting
|
||||
(should (equal (get-text-property 0 'display result) '(space :width (2)))))))
|
||||
|
||||
(ert-deftest tp-test-define-tp-parameterized-usage-region ()
|
||||
"Test parameterized layer usage with region: (tp-set start end '(layer-name arg))."
|
||||
"Test parameterized layer usage with region: (tp-set start end '(layer-name arg)).
|
||||
When using tp-set (direct property setting), tp-name is NOT added."
|
||||
(tp-test-with-temp-buffer
|
||||
(insert "emacs")
|
||||
(define-tp tp-space (pixel)
|
||||
(list 'display (list 'space :width (list pixel))))
|
||||
(tp-set 1 6 '(tp-space 5))
|
||||
;; Check properties in buffer
|
||||
(should (eq (tp-at 1 'tp-name) 'tp-space))
|
||||
(should-not (tp-at 1 'tp-name)) ; no tp-name for direct setting
|
||||
(should (equal (tp-at 1 'display) '(space :width (5))))))
|
||||
|
||||
(ert-deftest tp-test-define-tp-parameterized-backquote ()
|
||||
"Test parameterized layer with backquote syntax."
|
||||
"Test parameterized layer with backquote syntax.
|
||||
When using tp-set (direct property setting), tp-name is NOT added."
|
||||
(tp-test-with-temp-buffer
|
||||
(define-tp tp-test-space (pixel)
|
||||
`(display (space :width (,pixel))))
|
||||
(let ((result (tp-set "emacs" 'tp-test-space 10)))
|
||||
(should (eq (get-text-property 0 'tp-name result) 'tp-test-space))
|
||||
(should-not (get-text-property 0 'tp-name result)) ; no tp-name for direct setting
|
||||
(should (equal (get-text-property 0 'display result) '(space :width (10)))))))
|
||||
|
||||
(ert-deftest tp-test-define-tp-parameterized-undefine ()
|
||||
@ -3217,55 +3237,58 @@ the inserted text should be that string, not the source text."
|
||||
(should-not tp-layer-alist)))
|
||||
|
||||
(ert-deftest tp-test-layer-with-extra-props-string ()
|
||||
"Test layer with extra native properties on string."
|
||||
"Test layer with extra native properties on string.
|
||||
When using tp-set (direct property setting), tp-name is NOT added."
|
||||
(tp-test-with-temp-buffer
|
||||
(define-tp tp-bold ()
|
||||
'(face bold))
|
||||
;; Non-parameterized layer with extra props
|
||||
(let ((result (tp-set "emacs" 'tp-bold t 'face '(:foreground "green"))))
|
||||
(should (eq (get-text-property 0 'tp-name result) 'tp-bold))
|
||||
(should-not (get-text-property 0 'tp-name result)) ; no tp-name for direct setting
|
||||
;; Should have both face values in the plist
|
||||
(let ((props (text-properties-at 0 result)))
|
||||
(should (member 'face props))
|
||||
(should (eq (plist-get props 'tp-name) 'tp-bold))))))
|
||||
(should (member 'face props))))))
|
||||
|
||||
(ert-deftest tp-test-parameterized-layer-with-extra-props-string ()
|
||||
"Test parameterized layer with extra native properties on string."
|
||||
"Test parameterized layer with extra native properties on string.
|
||||
When using tp-set (direct property setting), tp-name is NOT added."
|
||||
(tp-test-with-temp-buffer
|
||||
(define-tp tp-space (pixel)
|
||||
`(display (space :width (,pixel))))
|
||||
;; Parameterized layer with extra props
|
||||
(let ((result (tp-set "emacs" 'tp-space 6 'face '(:foreground "green"))))
|
||||
(should (eq (get-text-property 0 'tp-name result) 'tp-space))
|
||||
(should-not (get-text-property 0 'tp-name result)) ; no tp-name for direct setting
|
||||
(should (equal (get-text-property 0 'display result) '(space :width (6))))
|
||||
(should (equal (get-text-property 0 'face result) '(:foreground "green"))))))
|
||||
|
||||
(ert-deftest tp-test-layer-with-extra-props-region ()
|
||||
"Test layer with extra native properties on region."
|
||||
"Test layer with extra native properties on region.
|
||||
When using tp-set (direct property setting), tp-name is NOT added."
|
||||
(tp-test-with-temp-buffer
|
||||
(define-tp tp-bold ()
|
||||
'(face bold))
|
||||
;; Region form with extra props
|
||||
(let ((result (tp-set 0 5 '(tp-bold t face (:foreground "green")) "emacs")))
|
||||
(should (eq (get-text-property 0 'tp-name result) 'tp-bold))
|
||||
(should-not (get-text-property 0 'tp-name result)) ; no tp-name for direct setting
|
||||
;; Should have both face values in the plist
|
||||
(let ((props (text-properties-at 0 result)))
|
||||
(should (member 'face props))
|
||||
(should (eq (plist-get props 'tp-name) 'tp-bold))))))
|
||||
(should (member 'face props))))))
|
||||
|
||||
(ert-deftest tp-test-parameterized-layer-with-extra-props-region ()
|
||||
"Test parameterized layer with extra native properties on region."
|
||||
"Test parameterized layer with extra native properties on region.
|
||||
When using tp-set (direct property setting), tp-name is NOT added."
|
||||
(tp-test-with-temp-buffer
|
||||
(define-tp tp-space (pixel)
|
||||
`(display (space :width (,pixel))))
|
||||
;; Region form with extra props
|
||||
(let ((result (tp-set 0 5 '(tp-space 6 face (:foreground "green")) "emacs")))
|
||||
(should (eq (get-text-property 0 'tp-name result) 'tp-space))
|
||||
(should-not (get-text-property 0 'tp-name result)) ; no tp-name for direct setting
|
||||
(should (equal (get-text-property 0 'display result) '(space :width (6))))
|
||||
(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."
|
||||
"Test layer properties can be at any position in string form.
|
||||
When using tp-set (direct property setting), tp-name is NOT added."
|
||||
(tp-test-with-temp-buffer
|
||||
(define-tp tp-space (pixel)
|
||||
`(display (space :width (,pixel))))
|
||||
@ -3274,25 +3297,27 @@ the inserted text should be that string, not the source text."
|
||||
'face '(:foreground "green")
|
||||
'tp-space 6
|
||||
'test "test")))
|
||||
(should (eq (get-text-property 0 'tp-name result) 'tp-space))
|
||||
(should-not (get-text-property 0 'tp-name result)) ; no tp-name for direct setting
|
||||
(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."
|
||||
"Test layer properties can be at any position in region form.
|
||||
When using tp-set (direct property setting), tp-name is NOT added."
|
||||
(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-not (get-text-property 0 'tp-name result)) ; no tp-name for direct setting
|
||||
(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."
|
||||
"Test non-parameterized layer at any position.
|
||||
When using tp-set (direct property setting), tp-name is NOT added."
|
||||
(tp-test-with-temp-buffer
|
||||
(define-tp tp-bold ()
|
||||
'(face bold))
|
||||
@ -3301,7 +3326,7 @@ the inserted text should be that string, not the source text."
|
||||
'test1 "value1"
|
||||
'tp-bold t
|
||||
'test2 "value2")))
|
||||
(should (eq (get-text-property 0 'tp-name result) 'tp-bold))
|
||||
(should-not (get-text-property 0 'tp-name result)) ; no tp-name for direct setting
|
||||
(should (equal (get-text-property 0 'test1 result) "value1"))
|
||||
(should (equal (get-text-property 0 'test2 result) "value2")))))
|
||||
|
||||
|
||||
120
tp.el
120
tp.el
@ -319,6 +319,13 @@ Only the reactive portions of the properties are stored for each variable."
|
||||
(tp--unregister-layer-computed layer-name)
|
||||
(tp--unregister-layer-data layer-name))
|
||||
|
||||
(defun tp--layer-has-reactive-deps-p (layer-name)
|
||||
"Return non-nil if LAYER-NAME has reactive dependencies registered.
|
||||
Layers with reactive deps need tp-name for reactive tracking."
|
||||
(cl-some (lambda (dep)
|
||||
(assoc layer-name (cdr dep)))
|
||||
tp-reactive-deps))
|
||||
|
||||
(defun tp--reactive-variable-watcher (symbol newval operation where)
|
||||
"Watcher function called when a reactive variable changes.
|
||||
SYMBOL is the variable that changed.
|
||||
@ -539,7 +546,7 @@ Re-applies the layer properties using tp-search-map and tp-add.
|
||||
WHERE specifies which buffers to update:
|
||||
- If WHERE is a buffer, only update that buffer (setq-local case).
|
||||
- If WHERE is nil, update all buffers that have the text property (setq case)."
|
||||
(let ((props (tp-layer-props layer-name)))
|
||||
(let ((props (tp-layer-props layer-name t))) ; include tp-name for reactive tracking
|
||||
(when props
|
||||
;; Callback for tp-search-map: applies props to matched region.
|
||||
;; _TEXT is unused (the matched text), START and END are buffer positions.
|
||||
@ -603,7 +610,7 @@ This is called when a reactive variable bound to tp-text changes.
|
||||
WHERE specifies which buffers to update:
|
||||
- If WHERE is a buffer, only update that buffer (setq-local case).
|
||||
- If WHERE is nil, update all buffers that have the text property (setq case)."
|
||||
(let ((props (tp-layer-props layer-name)))
|
||||
(let ((props (tp-layer-props layer-name t))) ; include tp-name for reactive tracking
|
||||
(when props
|
||||
(let ((new-text (plist-get props 'tp-text)))
|
||||
(when (and new-text (stringp new-text))
|
||||
@ -2418,33 +2425,41 @@ This is an internal function used by group definition macros."
|
||||
(setf (cdr (assoc group-name tp-layer-groups)) layer-names)
|
||||
(push (cons group-name layer-names) tp-layer-groups)))
|
||||
|
||||
(defun tp-layer-props (layer-name)
|
||||
(defun tp-layer-props (layer-name &optional include-tp-name)
|
||||
"Return properties for layer LAYER-NAME from `tp-layer-alist'.
|
||||
Appends 'tp-name property to identify the layer.
|
||||
If INCLUDE-TP-NAME is non-nil, appends 'tp-name property to identify the layer.
|
||||
Also includes tp-name automatically if the layer has reactive dependencies registered.
|
||||
Handles two storage formats:
|
||||
1. Old format (from tp--set-layer-props): (LAYER-NAME . PLIST) - flat plist
|
||||
2. Unified format (from define-tp): (LAYER-NAME ARGLIST BODY-FORM)
|
||||
For parameterized layers (ARGLIST non-nil), returns nil - use `tp-layer-props-with-arg'."
|
||||
(when-let ((entry (cdr (assoc layer-name tp-layer-alist))))
|
||||
(cond
|
||||
;; Unified format: entry is (ARGLIST BODY-FORM) where first elem is nil or a list
|
||||
;; Check: exactly 2 elements and first is nil or a list of symbols
|
||||
((and (= (length entry) 2)
|
||||
(or (null (car entry))
|
||||
(and (listp (car entry))
|
||||
(cl-every #'symbolp (car entry)))))
|
||||
(let ((arglist (car entry))
|
||||
(body (cadr entry)))
|
||||
(if arglist
|
||||
;; Parameterized - needs argument, return nil
|
||||
nil
|
||||
;; Non-parameterized - evaluate body and return props
|
||||
(let ((plist (eval body)))
|
||||
(when plist
|
||||
(append plist (list 'tp-name layer-name)))))))
|
||||
;; Old format: entry is just a flat plist
|
||||
(t
|
||||
(append entry (list 'tp-name layer-name))))))
|
||||
;; Auto-include tp-name for layers with reactive deps
|
||||
(let ((needs-tp-name (or include-tp-name
|
||||
(tp--layer-has-reactive-deps-p layer-name))))
|
||||
(cond
|
||||
;; Unified format: entry is (ARGLIST BODY-FORM) where first elem is nil or a list
|
||||
;; Check: exactly 2 elements and first is nil or a list of symbols
|
||||
((and (= (length entry) 2)
|
||||
(or (null (car entry))
|
||||
(and (listp (car entry))
|
||||
(cl-every #'symbolp (car entry)))))
|
||||
(let ((arglist (car entry))
|
||||
(body (cadr entry)))
|
||||
(if arglist
|
||||
;; Parameterized - needs argument, return nil
|
||||
nil
|
||||
;; Non-parameterized - evaluate body and return props
|
||||
(let ((plist (eval body)))
|
||||
(when plist
|
||||
(if needs-tp-name
|
||||
(append plist (list 'tp-name layer-name))
|
||||
plist))))))
|
||||
;; Old format: entry is just a flat plist
|
||||
(t
|
||||
(if needs-tp-name
|
||||
(append entry (list 'tp-name layer-name))
|
||||
entry))))))
|
||||
|
||||
(defun tp-layer-parameterized-p (layer-name)
|
||||
"Return non-nil if LAYER-NAME is a parameterized layer.
|
||||
@ -2458,10 +2473,10 @@ where ARGLIST is a non-nil list of argument symbols."
|
||||
(not (null (car entry)))
|
||||
(cl-every #'symbolp (car entry)))))
|
||||
|
||||
(defun tp-layer-props-with-arg (layer-name arg)
|
||||
(defun tp-layer-props-with-arg (layer-name arg &optional include-tp-name)
|
||||
"Return properties for parameterized layer LAYER-NAME with ARG.
|
||||
Evaluates the body form with the argument bound to the parameter.
|
||||
Appends 'tp-name property to identify the layer."
|
||||
If INCLUDE-TP-NAME is non-nil, appends 'tp-name property to identify the layer."
|
||||
(when-let ((entry (cdr (assoc layer-name tp-layer-alist))))
|
||||
;; entry is (ARGLIST BODY-FORM)
|
||||
(let ((arglist (car entry))
|
||||
@ -2471,13 +2486,16 @@ Appends 'tp-name property to identify the layer."
|
||||
;; Evaluate the body with the argument bound
|
||||
(plist (eval `(let ((,arg-sym ',arg)) ,body))))
|
||||
(when plist
|
||||
(append plist (list 'tp-name layer-name))))))))
|
||||
(if include-tp-name
|
||||
(append plist (list 'tp-name layer-name))
|
||||
plist)))))))
|
||||
|
||||
(defun tp-group-props (group-name)
|
||||
"Return list of properties for all layers in GROUP-NAME."
|
||||
(defun tp-group-props (group-name &optional include-tp-name)
|
||||
"Return list of properties for all layers in GROUP-NAME.
|
||||
If INCLUDE-TP-NAME is non-nil, each layer's props will include tp-name."
|
||||
(when-let ((layers (cdr (assoc group-name tp-layer-groups))))
|
||||
(mapcar (lambda (layer)
|
||||
(tp-layer-props layer))
|
||||
(tp-layer-props layer include-tp-name))
|
||||
layers)))
|
||||
|
||||
(defun tp--is-layer-name-p (sym)
|
||||
@ -2490,6 +2508,7 @@ Appends 'tp-name property to identify the layer."
|
||||
"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.
|
||||
Does NOT add tp-name - this is for direct property setting (tp-set/add/reset).
|
||||
Returns the expanded plist."
|
||||
(let ((result nil)
|
||||
(remaining props))
|
||||
@ -2503,14 +2522,17 @@ Returns the expanded plist."
|
||||
(cond
|
||||
;; Parameterized layer - evaluate with the argument (val)
|
||||
((tp-layer-parameterized-p key)
|
||||
(tp-layer-props-with-arg key val))
|
||||
(tp-layer-props-with-arg key val nil)) ; no tp-name
|
||||
;; Non-parameterized layer - val should be t
|
||||
((assoc key tp-layer-alist)
|
||||
(tp-layer-props key))
|
||||
;; Layer group
|
||||
(tp-layer-props key nil)) ; no tp-name
|
||||
;; Layer group - merge all layers' properties for direct setting
|
||||
((assoc key tp-layer-groups)
|
||||
(when-let ((layer-props-list (tp-group-props key)))
|
||||
(tp--build-layer-props layer-props-list))))))
|
||||
;; For direct property setting, merge all layers' properties
|
||||
;; without the tp-layers structure.
|
||||
;; Reverse so first layer's properties are applied last (take precedence)
|
||||
(apply #'append (reverse layer-props-list)))))))
|
||||
(when layer-props
|
||||
(setq result (append result layer-props)))))
|
||||
;; Regular property - keep as-is
|
||||
@ -2569,15 +2591,18 @@ For group names, includes `tp-layers' property with the full layer stack."
|
||||
(cond
|
||||
;; Parameterized layer - evaluate with the argument
|
||||
((tp-layer-parameterized-p first-elem)
|
||||
(tp-layer-props-with-arg first-elem second-elem))
|
||||
(tp-layer-props-with-arg first-elem second-elem nil)) ; no tp-name
|
||||
;; Non-parameterized layer - arg should be t, return the layer props
|
||||
;; (silently ignore non-t values for flexibility)
|
||||
((assoc first-elem tp-layer-alist)
|
||||
(tp-layer-props first-elem))
|
||||
;; Layer group
|
||||
(tp-layer-props first-elem nil)) ; no tp-name
|
||||
;; Layer group - merge all layers' properties for direct setting
|
||||
((assoc first-elem tp-layer-groups)
|
||||
(when-let ((layer-props-list (tp-group-props first-elem)))
|
||||
(tp--build-layer-props layer-props-list))))))
|
||||
;; For direct property setting, merge all layers' properties
|
||||
;; without the tp-layers structure.
|
||||
;; 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)
|
||||
(if (and layer-props extra-props)
|
||||
(let ((resolved-extra (tp--expand-layer-in-plist extra-props)))
|
||||
@ -2614,7 +2639,7 @@ For group names, includes `tp-layers' property with the full layer stack."
|
||||
(tp--set-layer-props layer-name resolved-props)
|
||||
;; Register reactive dependencies with the original props
|
||||
(tp--register-reactive-deps layer-name reactive-syms props)
|
||||
;; Return resolved props with tp-name
|
||||
;; Return resolved props with tp-name for reactive tracking
|
||||
(append resolved-props (list 'tp-name layer-name)))
|
||||
;; No reactive symbols - return props as-is (no tp-name needed)
|
||||
;; This preserves the native text property behavior for non-reactive plists
|
||||
@ -2625,14 +2650,16 @@ For group names, includes `tp-layers' property with the full layer stack."
|
||||
;; Parameterized layer without argument - cannot resolve, return nil
|
||||
((tp-layer-parameterized-p props)
|
||||
nil)
|
||||
;; Check layer - use tp-layer-props which adds tp-name
|
||||
;; Check layer - get props without tp-name for direct property setting
|
||||
((assoc props tp-layer-alist)
|
||||
(tp-layer-props props))
|
||||
;; Check group - build layer stack with tp-layers
|
||||
(tp-layer-props props nil)) ; no tp-name
|
||||
;; Check group - merge all layers' properties for direct setting
|
||||
((assoc props tp-layer-groups)
|
||||
(when-let ((layer-props-list (tp-group-props props)))
|
||||
;; Build the layer stack: first layer on top, rest in tp-layers
|
||||
(tp--build-layer-props layer-props-list)))
|
||||
;; For direct property setting, merge all layers' properties
|
||||
;; without the tp-layers structure.
|
||||
;; Reverse so first layer's properties are applied last (take precedence)
|
||||
(apply #'append (reverse layer-props-list))))
|
||||
;; Not found - return nil (let caller decide how to handle)
|
||||
(t nil)))
|
||||
(t nil)))
|
||||
@ -2705,11 +2732,12 @@ Returns a list of (START END PROPERTIES) for matching intervals."
|
||||
;;; --- Layer Stack Utilities ---
|
||||
|
||||
(defun tp--normalize-layer-spec (layer-spec)
|
||||
"Normalize LAYER-SPEC to a plist with tp-name."
|
||||
"Normalize LAYER-SPEC to a plist with tp-name.
|
||||
Used by layer stack functions that need tp-name for identification."
|
||||
(cond
|
||||
;; Symbol - look up in tp-layer-alist
|
||||
((symbolp layer-spec)
|
||||
(or (tp-layer-props layer-spec)
|
||||
(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)
|
||||
((and (listp layer-spec)
|
||||
@ -2827,7 +2855,7 @@ OBJECT defaults to current buffer for region form."
|
||||
;; Check if it's a group name
|
||||
((and (symbolp layer-spec)
|
||||
(assoc layer-spec tp-layer-groups))
|
||||
(tp-group-props layer-spec))
|
||||
(tp-group-props layer-spec t)) ; include tp-name for layer stack
|
||||
;; Single layer spec
|
||||
((or (symbolp layer-spec)
|
||||
(and (listp layer-spec)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user