Subject: bug#77381: [PATCH] extend tex--prettify-symbols-alist

From: "Paul D. Nelson" <[email-masked]>
Date: Sun, 30 Mar 2025 19:47:47 +0200

>> > Ideally, we should only add those which can be displayed.  The
>> > function char-displayable-p should be able to tell.  Would it be
>> > possible to change the code such that only the symbols that pass that
>> > test are added?
>> 
>> (...)
>
> For a GUI frame, if char-displayable-p returns a symbol, the character
> is not displayable.  Characters that can be displayed on a GUI frame
> should cause char-displayable-p to return a string, the name of the
> font suitable for the character.

Thanks.  With the attached patch, prettify-symbols-mode filters
prettify-symbols-alist to those entries that are displayable in the
following sense:

  (let ((display-capability (char-displayable-p char)))
    (if (display-graphic-p)
        (or (eq display-capability t)
            (fontp display-capability))
      display-capability))

I've tested it in tex-mode, with GUI and terminal Emacs, using the
examples from this thread.  Any feedback or other suggestions would be
welcome.

>From 0789b3bd3f2e8dc7ecc35d9acff55de5a6af9131 Mon Sep 17 00:00:00 2001
From: Paul Nelson <[email-masked]>
Date: Sun, 30 Mar 2025 19:10:38 +0200
Subject: [PATCH] Restrict symbol prettification to displayable ones

* lisp/progmodes/prog-mode.el
(prettify-symbols--char-displayable-p)
(prettify-symbols--composition-displayable-p): New functions
used to restrict to displayable prettification symbols.  This
prevents issues with missing characters appearing as boxes.
(prettify-symbols--make-keywords): Use them.
---
 lisp/progmodes/prog-mode.el | 45 +++++++++++++++++++++++++++++++++++--
 1 file changed, 43 insertions(+), 2 deletions(-)

diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el
index 77724e04f11..e2f0d511449 100644
--- a/lisp/progmodes/prog-mode.el
+++ b/lisp/progmodes/prog-mode.el
@@ -230,10 +230,51 @@ prettify-symbols--compose-symbol
   ;; Return nil because we're not adding any face property.
   nil)
 
+(defun prettify-symbols--char-displayable-p (char)
+  "Return non-nil if CHAR can be displayed with the current font.
+A character is considered displayable:
+
+- on a graphical display, if `char-displayable-p' returns either t or a
+  font object, and
+
+- on a non-graphical display, if `char-displayable-p' returns non-nil."
+  (let ((display-capability (char-displayable-p char)))
+    (if (display-graphic-p)
+        (or (eq display-capability t)
+            (fontp display-capability))
+      display-capability)))
+
+(defun prettify-symbols--composition-displayable-p (composition)
+  "Return non-nil if COMPOSITION can be displayed with the current fonts.
+COMPOSITION can be a single character, a string, or a sequence (vector or
+list) of characters and composition rules as described in the documentation
+of `prettify-symbols-alist' and `compose-region'."
+  (cond
+   ((characterp composition)
+    (prettify-symbols--char-displayable-p composition))
+   ((stringp composition)
+    (seq-every-p #'prettify-symbols--char-displayable-p composition))
+   ((seqp composition)
+    ;; check that every even-indexed element is displayable
+    (seq-every-p
+     (lambda (idx-elt)
+       (if (evenp (car idx-elt))
+           (prettify-symbols--char-displayable-p (cdr idx-elt))
+         t))
+     (seq-map-indexed #'cons composition)))
+   (t
+    ;; silently ignore invalid compositions
+    t)))
+
 (defun prettify-symbols--make-keywords ()
   (if prettify-symbols-alist
-      `((,(regexp-opt (mapcar 'car prettify-symbols-alist) t)
-         (0 (prettify-symbols--compose-symbol ',prettify-symbols-alist))))
+      (let ((filtered-alist
+             (seq-filter
+              (lambda (elt)
+                (prettify-symbols--composition-displayable-p (cdr elt)))
+              prettify-symbols-alist)))
+        `((,(regexp-opt (mapcar 'car filtered-alist) t)
+           (0 (prettify-symbols--compose-symbol ',filtered-alist)))))
     nil))
 
 (defvar-local prettify-symbols--keywords nil)
-- 
2.39.3 (Apple Git-145)