Fix "Odd length text property list" error when property value is nil
The bug occurred because tp--parse-args was incorrectly omitting nil values from the property list, producing (face) instead of (face nil). Fixed the same bug pattern in: - tp--parse-args (used by tp-set, tp-reset, tp-add) - tp-add-to-layers - tp-add-to-all-layers Added 6 new regression tests for nil property values. Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
This commit is contained in:
parent
4cca06dedc
commit
d11d109f7b
54
tp-tests.el
54
tp-tests.el
@ -3766,5 +3766,59 @@ internally, and the final result should have face properties, not tp-palette."
|
|||||||
(should (listp mouse-face-prop))
|
(should (listp mouse-face-prop))
|
||||||
(should (memq 'highlight mouse-face-prop))))))
|
(should (memq 'highlight mouse-face-prop))))))
|
||||||
|
|
||||||
|
;;; ============================================================
|
||||||
|
;;; Nil Value Property Tests (Issue: "Odd length text property list")
|
||||||
|
;;; ============================================================
|
||||||
|
|
||||||
|
(ert-deftest tp-test-set-with-nil-value ()
|
||||||
|
"Test tp-set with nil value produces valid property list.
|
||||||
|
Regression test for: (tp-set \"emacs\" 'face nil) erroring with
|
||||||
|
\"Odd length text property list\"."
|
||||||
|
(tp-test-with-temp-buffer
|
||||||
|
(let ((result (tp-set "emacs" 'face nil)))
|
||||||
|
;; Result should be #("emacs" 0 5 (face nil))
|
||||||
|
(should (stringp result))
|
||||||
|
(should (eq (get-text-property 0 'face result) nil))
|
||||||
|
;; Verify the property list is valid (has even length)
|
||||||
|
(let ((props (text-properties-at 0 result)))
|
||||||
|
(should (= (% (length props) 2) 0))))))
|
||||||
|
|
||||||
|
(ert-deftest tp-test-set-with-nil-value-in-middle ()
|
||||||
|
"Test tp-set with nil value in middle of property list."
|
||||||
|
(tp-test-with-temp-buffer
|
||||||
|
(let ((result (tp-set "emacs" 'face 'bold 'help-echo nil 'display "test")))
|
||||||
|
;; Result should have face=bold, help-echo=nil, display="test"
|
||||||
|
(should (eq (get-text-property 0 'face result) 'bold))
|
||||||
|
(should (eq (get-text-property 0 'help-echo result) nil))
|
||||||
|
(should (equal (get-text-property 0 'display result) "test")))))
|
||||||
|
|
||||||
|
(ert-deftest tp-test-set-with-multiple-nil-values ()
|
||||||
|
"Test tp-set with multiple nil values."
|
||||||
|
(tp-test-with-temp-buffer
|
||||||
|
(let ((result (tp-set "emacs" 'face nil 'help-echo nil)))
|
||||||
|
(should (eq (get-text-property 0 'face result) nil))
|
||||||
|
(should (eq (get-text-property 0 'help-echo result) nil)))))
|
||||||
|
|
||||||
|
(ert-deftest tp-test-reset-with-nil-value ()
|
||||||
|
"Test tp-reset with nil value works correctly."
|
||||||
|
(tp-test-with-temp-buffer
|
||||||
|
(let ((result (tp-reset "emacs" 'face nil)))
|
||||||
|
;; Result should have face=nil
|
||||||
|
(should (eq (get-text-property 0 'face result) nil)))))
|
||||||
|
|
||||||
|
(ert-deftest tp-test-add-with-nil-value ()
|
||||||
|
"Test tp-add with nil value works correctly."
|
||||||
|
(tp-test-with-temp-buffer
|
||||||
|
(let ((result (tp-add "emacs" 'face nil)))
|
||||||
|
;; Result should have face=nil
|
||||||
|
(should (eq (get-text-property 0 'face result) nil)))))
|
||||||
|
|
||||||
|
(ert-deftest tp-test-set-nil-value-in-buffer ()
|
||||||
|
"Test tp-set with nil value in buffer region."
|
||||||
|
(tp-test-with-temp-buffer
|
||||||
|
(insert "emacs")
|
||||||
|
(tp-set 1 6 '(face nil))
|
||||||
|
(should (eq (tp-at 1 'face) nil))))
|
||||||
|
|
||||||
(provide 'tp-ert-tests)
|
(provide 'tp-ert-tests)
|
||||||
;;; tp-ert-tests.el ends here
|
;;; tp-ert-tests.el ends here
|
||||||
|
|||||||
15
tp.el
15
tp.el
@ -1055,11 +1055,10 @@ Supports multiple calling conventions:
|
|||||||
(null rest))
|
(null rest))
|
||||||
(setq props (list end-or-prop)))
|
(setq props (list end-or-prop)))
|
||||||
;; Standard flat plist: (tp-set "str" 'prop1 val1 'prop2 val2 ...)
|
;; Standard flat plist: (tp-set "str" 'prop1 val1 'prop2 val2 ...)
|
||||||
|
;; Always include props-or-val even if it's nil, to handle (tp-set "str" 'prop nil)
|
||||||
(t
|
(t
|
||||||
(setq props (if end-or-prop
|
(setq props (if end-or-prop
|
||||||
(if props-or-val
|
|
||||||
(cons end-or-prop (cons props-or-val rest))
|
(cons end-or-prop (cons props-or-val rest))
|
||||||
(list end-or-prop))
|
|
||||||
nil)))))
|
nil)))))
|
||||||
;; First arg is a number - region convention
|
;; First arg is a number - region convention
|
||||||
((numberp start-or-string)
|
((numberp start-or-string)
|
||||||
@ -3924,11 +3923,9 @@ Returns the modified object (string) or nil for buffer operations."
|
|||||||
start 0
|
start 0
|
||||||
end (length start-or-string))
|
end (length start-or-string))
|
||||||
;; Construct plist from end-or-plist, plist-or-object, and rest
|
;; Construct plist from end-or-plist, plist-or-object, and rest
|
||||||
|
;; Always include plist-or-object even if nil, to handle (... 'prop nil)
|
||||||
(when end-or-plist
|
(when end-or-plist
|
||||||
(setq plist (cons end-or-plist
|
(setq plist (cons end-or-plist (cons plist-or-object rest)))))
|
||||||
(if plist-or-object
|
|
||||||
(cons plist-or-object rest)
|
|
||||||
rest)))))
|
|
||||||
;; Region form: (tp-add-to-layers ids start end plist object)
|
;; Region form: (tp-add-to-layers ids start end plist object)
|
||||||
((numberp start-or-string)
|
((numberp start-or-string)
|
||||||
(setq start start-or-string
|
(setq start start-or-string
|
||||||
@ -3996,11 +3993,9 @@ Returns the modified object (string) or nil for buffer operations."
|
|||||||
start 0
|
start 0
|
||||||
end (length start-or-string))
|
end (length start-or-string))
|
||||||
;; Construct plist from end-or-plist, plist-or-object, and rest
|
;; Construct plist from end-or-plist, plist-or-object, and rest
|
||||||
|
;; Always include plist-or-object even if nil, to handle (... 'prop nil)
|
||||||
(when end-or-plist
|
(when end-or-plist
|
||||||
(setq plist (cons end-or-plist
|
(setq plist (cons end-or-plist (cons plist-or-object rest)))))
|
||||||
(if plist-or-object
|
|
||||||
(cons plist-or-object rest)
|
|
||||||
rest)))))
|
|
||||||
;; Region form: (tp-add-to-all-layers start end plist object)
|
;; Region form: (tp-add-to-all-layers start end plist object)
|
||||||
((numberp start-or-string)
|
((numberp start-or-string)
|
||||||
(setq start start-or-string
|
(setq start start-or-string
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user