Update: You can redefine the setf
capability of substringsubstring
to add properties from the original string to the new string. This is a lightly adapted version of code from line 616 in cl-lib.elcl-lib.el
(gv-define-expander substring
(lambda (do place from &optional to)
(gv-letplace (getter setter) place
(macroexp-let2* nil ((start from) (end to))
(funcall do `(substring ,getter ,start ,end)
(lambda (v)
(funcall setter
`(apply 'propertize (cl--set-substring
,getter ,start ,end ,v)
(text-properties-at 0 ,getter)))))))))
;; example use, returns original string and new string
(let ((s (propertize "testing" 'property1 "this is property1" 'property2 "this is property2")))
(list s
(setf (substring s 0 (length s)) "mystring")))
(#("testing" 0 7
(property2 "this is property2" property1 "this is property1"))
#("mystring" 0 8
(property2 "this is property2" property1 "this is property1")))
(gv-define-expander substring
(lambda (do place from &optional to)
(gv-letplace (getter setter) place
(macroexp-let2* nil ((start from) (end to))
(funcall do `(substring ,getter ,start ,end)
(lambda (v)
(funcall setter
`(apply 'propertize (cl--set-substring
,getter ,start ,end ,v)
(text-properties-at 0 ,getter)))))))))
;; example use, returns original string and new string
(let ((s (propertize "testing" 'property1 "this is property1" 'property2 "this is property2")))
(list s
(setf (substring s 0 (length s)) "mystring")))
(#("testing" 0 7
(property2 "this is property2" property1 "this is property1"))
#("mystring" 0 8
(property2 "this is property2" property1 "this is property1")))