Typing a zero-width space in TERMINAL emacs shows an underscore-ish character. How to make it showing nothing?
2 Answers
Refer to C-hig (elisp)Glyphless Chars
By default the zero-width characters are displayed using the thin-space
display method which will "Display a thin space, 1-pixel wide on graphical displays, or 1-character wide on text terminals"; also noting that "The ‘thin-space’, ‘empty-box’, ‘hex-code’, and ASCII string display methods are drawn with the ‘glyphless-char’ face" which by default inherits from the underline
face.
This default ensures that these (potentially-confusing) characters are not 100% invisible to the user, and can easily be made much more visible if desired; but there is also a zero-width
display method which you can use to truly hide them from display:
(set-char-table-range glyphless-char-display
(char-from-name "ZERO WIDTH SPACE") 'zero-width)
Personally I want these things to be as visible as possible -- I've encountered a situation where I was unwittingly copying and pasting zero-width joiners between visible characters, and I created a mess because I never knew they were there. To make sure they are apparent to me (as I don't expect such things to normally be in the text I edit), I use this:
(set-face-background 'glyphless-char "red")
(If you want to see how that looks, copy this sentence into Emacs and configure that background.)
To hide such chars for a particular mode only, you could make the char table buffer-local in that mode.
;; Make glyphless chars highly visible.
(set-face-background 'glyphless-char "red")
;; Hide ZERO WIDTH chars completely in `org-mode'.
(add-hook 'org-mode-hook #'my-hide-zero-width-chars)
(defun my-hide-zero-width-chars ()
"Make ZERO WIDTH characters completely invisible."
(setq-local glyphless-char-display
my-zero-width-glyphless-char-display))
(defvar my-zero-width-glyphless-char-display
(let ((table (copy-sequence glyphless-char-display))
(charnames (list "ZERO WIDTH SPACE"
"ZERO WIDTH NO-BREAK SPACE"
"ZERO WIDTH JOINER"
"ZERO WIDTH NON-JOINER")))
(dolist (name charnames)
(set-char-table-range table (char-from-name name) 'zero-width))
table)
"Variant of `glyphless-char-display' which hides ZERO WIDTH chars.")
-
Thanks for the answer. I also want to know what setting makes the zero width space become an underscore like thing. Commented Jun 1, 2021 at 23:54
-
-
n.b. I've updated the answer with all of the additional information and responses from my earlier comments.– philsCommented Jun 30, 2021 at 2:23
-
Not working for me. I run that code. In an org buffer I can confirm it partially worked, because if I eval
(aref glyphless-char-display (char-from-name "ZERO WIDTH SPACE"))
I getzero-width
. But if I then insert that character in my org buffer, I still see an red underscore.– Rob NCommented May 4, 2023 at 17:44 -
1I can't reproduce your issue: for me, in a GUI emacs frame, the narrow no-break space is narrow (tested with
emacs -Q
for both Emacs 27 and 28). I only have "wide narrow glyphs" in terminal frames (which is expected). If you're not already getting narrow glyphs, I'm not sure whether this answer could help; you'd need to play with the code to find out.– philsCommented Jun 14, 2023 at 23:23
Related to the above answer: in emacs 29, there's glyphless-display-mode. That shows big boxes for such characters.
That's not what you're asking for, but if you've turned that mode on, you certainly won't be hiding zero-width spaces and similar things. It's also an arguably simpler way to accomplish the red highlighting in the above answer -- and the boxes have the character abbreviations, such as "ZWSP", "ZWJ", "ZWNJ", and so on, which are nice. (Although of course there's describe-char
.)