Improve tp--apply-props-to-string to handle partial range correctly

Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-01-07 03:26:47 +00:00
parent 6392be848e
commit 347abb601e
2 changed files with 18 additions and 4 deletions

View File

@ -4060,7 +4060,12 @@ Regression test for: (tp-set \"emacs\" 'face nil) erroring with
(ert-deftest tp-test-set-preserves-text-property-intervals ()
"Test that tp-set preserves text property intervals when adding new properties.
When a string has different properties at different positions, adding a new
property should preserve the original interval structure."
property should preserve the original interval structure.
Test string: \" button \" (8 characters, positions 0-7)
- Position 0-1: display property (first space character)
- Position 1-7: no display property (text \"button \")
- Position 7-8: display property (last space character)"
(let ((original #(" button " 0 1 (display (space :width (4)))
7 8 (display (space :width (4))))))
(let ((result (tp-set original 'face '(:foreground "red"))))

15
tp.el
View File

@ -1316,7 +1316,7 @@ Supports multiple calling conventions:
(defun tp--apply-props-to-string (str start end props &optional merge-mode)
"Apply PROPS to string STR from START to END, returning a NEW string.
This function does not modify the original string.
Preserves the original text property intervals by using `propertize'.
Preserves the original text property intervals.
MERGE-MODE controls how properties are applied:
nil or :set - Set properties, preserving existing unspecified ones
@ -1352,9 +1352,18 @@ Returns a new propertized string."
(put-text-property pos next-change key new-val result)
(setq pos next-change)))))
result))
;; nil/:set - use propertize which creates a new copy and preserves existing properties
;; nil/:set - set properties while preserving existing ones
;; If applying to the entire string, use propertize for efficiency
;; Otherwise, use copy-sequence + put-text-property to apply to specific range
(t
(apply #'propertize str props)))))
(if (and (= start 0) (= end len))
;; Entire string: use propertize which creates a new copy and preserves existing properties
(apply #'propertize str props)
;; Partial range: copy string and apply properties to the range
(let ((result (copy-sequence str)))
(cl-loop for (key val) on props by #'cddr
do (put-text-property start end key val result))
result))))))
;;;============================================================================
;;; Layer 2: Core Property Functions - Set/Reset/Add