]> git.eshelyaron.com Git - emacs.git/commitdiff
Add new function 'add-display-text-property'
authorLars Ingebrigtsen <larsi@gnus.org>
Wed, 24 Nov 2021 18:38:41 +0000 (19:38 +0100)
committerLars Ingebrigtsen <larsi@gnus.org>
Wed, 24 Nov 2021 18:38:41 +0000 (19:38 +0100)
* doc/lispref/display.texi (Display Property): Document it.
* lisp/emacs-lisp/subr-x.el (add-display-text-property): New function.

doc/lispref/display.texi
etc/NEWS
lisp/emacs-lisp/subr-x.el
test/lisp/emacs-lisp/subr-x-tests.el

index fdebba939beb935f70cc3119bcb1de1bba258d5f..7204581e407793642fbd0d46e091ad423a6f7350 100644 (file)
@@ -4904,6 +4904,31 @@ with @code{get-char-property}, for instance (@pxref{Examining
 Properties}).
 @end defun
 
+@defun add-display-text-property start end prop value &optional append object
+Add @code{display} property @var{prop} of @var{value} to the text from
+@var{start} to @var{end}.
+
+If any text in the region has a non-@code{nil} @code{display}
+property, those properties are retained.  For instance:
+
+@lisp
+(add-display-text-property 4 8 'height 2.0)
+(add-display-text-property 2 12 'raise 0.5)
+@end lisp
+
+After doing this, the region from 2 to 4 will have the @code{raise}
+@code{display} property, the region from 4 to 8 will have both the
+@code{raise} and @code{height} @code{display} properties, and finally
+the region from 8 to 12 will only have the @code{raise} @code{display}
+property.
+
+If @var{append} is non-@code{nil}, append to the list of display
+properties; otherwise prepend.
+
+If @var{object} is non-@code{nil}, it should be a string or a buffer.
+If @code{nil}, this defaults to the current buffer.
+@end defun
+
 @cindex display property, unsafe evaluation
 @cindex security, and display specifications
   Some of the display specifications allow inclusion of Lisp forms,
index 24b8cb279615f40af5f932451f90b9f62ba576e1..8b7c2f78508322e41664b72ef3b0023df0579af4 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -676,10 +676,17 @@ Use 'exif-parse-file' and 'exif-field' instead.
 \f
 * Lisp Changes in Emacs 29.1
 
++++
 ** New function 'get-display-property'.
 This is like 'get-text-property', but works on the 'display' text
 property.
 
++++
+** New function 'add-text-display-property'.
+This is like 'put-text-property', but works on the 'display' text
+property.
+
++++
 ** New 'min-width' 'display' property.
 This allows setting a minimum display width for a region of text.
 
index 95254b946e5379c79683706045ef49eae0ee4aa6..3ec880f8b8f8c8dd088d48adaf07e36deccbcc75 100644 (file)
@@ -469,6 +469,51 @@ This takes into account combining characters and grapheme clusters."
         (setq start (1+ start))))
     (nreverse result)))
 
+;;;###autoload
+(defun add-display-text-property (start end prop value
+                                        &optional append object)
+  "Add display property PROP with VALUE to the text from START to END.
+If any text in the region has a non-nil `display' property, those
+properties are retained.
+
+If APPEND is non-nil, append to the list of display properties;
+otherwise prepend.
+
+If OBJECT is non-nil, it should be a string or a buffer.  If nil,
+this defaults to the current buffer."
+  (let ((sub-start start)
+        (sub-end 0)
+        disp)
+    (while (< sub-end end)
+      (setq sub-end (next-single-property-change sub-start 'display object
+                                                 (if (stringp object)
+                                                     (min (length object) end)
+                                                   (min end (point-max)))))
+      (if (not (setq disp (get-text-property sub-start 'display object)))
+          ;; No old properties in this range.
+          (put-text-property sub-start sub-end 'display (list prop value))
+        ;; We have old properties.
+        (let ((vector nil))
+          ;; Make disp into a list.
+          (setq disp
+                (cond
+                 ((vectorp disp)
+                  (setq vector t)
+                  (seq-into disp 'list))
+                 ((not (consp (car disp)))
+                  (list disp))
+                 (t
+                  disp)))
+          (setq disp
+                (if append
+                    (append disp (list (list prop value)))
+                  (append (list (list prop value)) disp)))
+          (when vector
+            (setq disp (seq-into disp 'vector)))
+          ;; Finally update the range.
+          (put-text-property sub-start sub-end 'display disp)))
+      (setq sub-start sub-end))))
+
 (provide 'subr-x)
 
 ;;; subr-x.el ends here
index f9cfea888c70590619074153242069d5d620e2ce..69d59e84f6d7f8d8ec7bc9aa1bf88ce4e7b509fb 100644 (file)
       (buffer-string))
     "foo\n")))
 
+(ert-deftest test-add-display-text-property ()
+  (with-temp-buffer
+    (insert "Foo bar zot gazonk")
+    (add-display-text-property 4 8 'height 2.0)
+    (add-display-text-property 2 12 'raise 0.5)
+    (should (equal (get-text-property 2 'display) '(raise 0.5)))
+    (should (equal (get-text-property 5 'display)
+                   '((raise 0.5) (height 2.0))))
+    (should (equal (get-text-property 9 'display) '(raise 0.5))))
+  (with-temp-buffer
+    (insert "Foo bar zot gazonk")
+    (put-text-property 4 8 'display [(height 2.0)])
+    (add-display-text-property 2 12 'raise 0.5)
+    (should (equal (get-text-property 2 'display) '(raise 0.5)))
+    (should (equal (get-text-property 5 'display)
+                   [(raise 0.5) (height 2.0)]))
+    (should (equal (get-text-property 9 'display) '(raise 0.5)))))
+
 (provide 'subr-x-tests)
 ;;; subr-x-tests.el ends here