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 (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)
|
||||
;;; tp-ert-tests.el ends here
|
||||
|
||||
17
tp.el
17
tp.el
@ -1055,11 +1055,10 @@ Supports multiple calling conventions:
|
||||
(null rest))
|
||||
(setq props (list end-or-prop)))
|
||||
;; 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
|
||||
(setq props (if end-or-prop
|
||||
(if props-or-val
|
||||
(cons end-or-prop (cons props-or-val rest))
|
||||
(list end-or-prop))
|
||||
(cons end-or-prop (cons props-or-val rest))
|
||||
nil)))))
|
||||
;; First arg is a number - region convention
|
||||
((numberp start-or-string)
|
||||
@ -3924,11 +3923,9 @@ Returns the modified object (string) or nil for buffer operations."
|
||||
start 0
|
||||
end (length start-or-string))
|
||||
;; 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
|
||||
(setq plist (cons end-or-plist
|
||||
(if plist-or-object
|
||||
(cons plist-or-object rest)
|
||||
rest)))))
|
||||
(setq plist (cons end-or-plist (cons plist-or-object rest)))))
|
||||
;; Region form: (tp-add-to-layers ids start end plist object)
|
||||
((numberp start-or-string)
|
||||
(setq start start-or-string
|
||||
@ -3996,11 +3993,9 @@ Returns the modified object (string) or nil for buffer operations."
|
||||
start 0
|
||||
end (length start-or-string))
|
||||
;; 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
|
||||
(setq plist (cons end-or-plist
|
||||
(if plist-or-object
|
||||
(cons plist-or-object rest)
|
||||
rest)))))
|
||||
(setq plist (cons end-or-plist (cons plist-or-object rest)))))
|
||||
;; Region form: (tp-add-to-all-layers start end plist object)
|
||||
((numberp start-or-string)
|
||||
(setq start start-or-string
|
||||
|
||||
Loading…
Reference in New Issue
Block a user