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

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

> I think this function should be in mule.el (under a different name),
> and it should accept a frame as an additional argument, for which to
> call display-graphic-p.
>
> Otherwise, LGTM, thanks.

Thanks, please see attached.

>From 2b32cd6a8028b34a02e7c22427cb86a75891f008 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/international/mule.el (char-graphically-displayable-p):
New function used to determine more reliably whether a character
can be meaningfully displayed.
* lisp/progmodes/prog-mode.el
(prettify-symbols--composition-displayable-p): New function used
to restrict to displayable prettification symbols.  This
prevents issues with missing characters appearing as boxes.
(prettify-symbols--make-keywords): Use it.
---
 lisp/international/mule.el  | 17 +++++++++++++++++
 lisp/progmodes/prog-mode.el | 31 +++++++++++++++++++++++++++++--
 2 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/lisp/international/mule.el b/lisp/international/mule.el
index f72cc815287..ac562341f1a 100644
--- a/lisp/international/mule.el
+++ b/lisp/international/mule.el
@@ -528,6 +528,23 @@ char-displayable-p
                                    (throw 'tag3 charset)))
 			     charset-list)
 		       nil)))))))))))
+
+(defun char-graphically-displayable-p (char &optional frame)
+  "Return non-nil if CHAR can be graphically displayed in FRAME.
+FRAME nil or omitted means use the selected frame.
+
+This function provides a more reliable test than `char-displayable-p'
+for determining if a character will display properly.
+
+A character is considered graphically 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 frame)
+        (or (eq display-capability t)
+            (fontp display-capability))
+      display-capability)))
 
 ;; Save the ASCII case table in case we need it later.  Some locales
 ;; (such as Turkish) modify the case behavior of ASCII characters,
diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el
index 77724e04f11..35765579642 100644
--- a/lisp/progmodes/prog-mode.el
+++ b/lisp/progmodes/prog-mode.el
@@ -230,10 +230,37 @@ prettify-symbols--compose-symbol
   ;; Return nil because we're not adding any face property.
   nil)
 
+(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)
+    (char-graphically-displayable-p composition))
+   ((stringp composition)
+    (seq-every-p #'char-graphically-displayable-p composition))
+   ((seqp composition)
+    ;; check that every even-indexed element is displayable
+    (seq-every-p
+     (lambda (idx-elt)
+       (if (evenp (car idx-elt))
+           (char-graphically-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)