9

I'm using GNU Emacs 24.4.1 in a GUI on OS X. I want to force every character to be displayed using just a single font rather than allowing Emacs to choose a supposedly most appropriate. I understand that no font will include every glyph, but I use a limited subset of unicode which many good fonts cover satisfactorily.

I've seen a lot of talk about using the unicode-fonts package to set fonts for ranges of characters, but I don't want to have a thousand extra lines in my config to set every block separately.

How can I simply stop Emacs from automatically mapping different glyphs to different fonts?

Thanks.

karl
  • 257
  • 1
  • 4
  • 2
    Did you try `(set-fontset-font t nil MY-FONT)` where `MY-FONT` is the name of your font? –  Dec 23 '14 at 19:44
  • @lunaryorn Thanks for the suggestion. I tried that just now and I still get different fonts for different characters. I tried setting my font to Pragmata Pro and end up getting Menlo unicode glyphs (as verified by `describe-char`). – karl Dec 23 '14 at 20:58
  • @user227's answer worked for me. l just wanted to use Terminus in Emacs in GUI mode and prevent Emacs from using glyphs for quotes that had larger widths. I added this to my init file: `(set-fontset-font t nil "fontset-default")`. P.S.: It's necessary to set the `default` face (Menu bar: `Options > Set Default Font... > {choose font}` then `Options > Save Options`). – Rafael Beirigo May 25 '21 at 13:48

1 Answers1

8

Playing with Emacs’ fontsets definitions should be the answer.

After reading

The startup fontset will use the font that you specify, or a variant with a different registry and encoding, for all the characters that are supported by that font, and fallback on ‘fontset-default’ for other characters.

If some characters appear on the screen as empty boxes or hex codes, this means that the fontset in use for them has no font for those characters.

  • set-fontset-font description:

TARGET may be a cons; (FROM . TO), where FROM and TO are characters. In that case, use FONT-SPEC for all characters in the range FROM and TO (inclusive).

TARGET may be a script name symbol. In that case, use FONT-SPEC for all characters that belong to the script.

TARGET may be a charset. In that case, use FONT-SPEC for all characters in the charset.

TARGET may be nil. In that case, use FONT-SPEC for any characters for that no FONT-SPEC is specified.

There are two commands that can be used to obtain information about charsets. The command M-x list-charset-chars prompts for a charset name, and displays all the characters in that character set. The command M-x describe-character-set prompts for a charset name, and displays information about that charset, including its internal representation within Emacs.

To find out which charset a character in the buffer belongs to, put point before it and type C-u C-x =

In our init file we should be able to set one font for full range of characters:

 (let ((my-font "DejaVu Sans Mono-14"))
  (set-fontset-font "fontset-startup" '(#x000000 . #x3FFFFF) my-font)
  (set-fontset-font "fontset-default" '(#x000000 . #x3FFFFF) my-font)
  (set-fontset-font "fontset-standard" '(#x000000 . #x3FFFFF) my-font))

But to set a font for a range of characters and force it as a fallback font for characters not supported by it we also must add nil as a target:

(let ((my-font "DejaVu Sans Mono-14")
      (font-sets '("fontset-default"
                   "fontset-standard"
                   "fontset-startup")))
  (mapcar
   (lambda (font-set)
     ;; all the characters in that range (which is the full possible range)
     (set-fontset-font font-set '(#x000000 . #x3FFFFF) my-font)

     ;; for all characters without font specification
     ;; in another words it is a setting for lack of fallback font
     ;; if e.g. ℕ called DOUBLE-STRUCK CAPITAL N is not covered by our font
     ;; it will be displayed as placeholder-box,
     ;; because fallback for our font is now... our font :)
     (set-fontset-font font-set nil my-font))
   font-sets))

Now as we can see under point (cursor) with C-u C-x = or M-x describe-char:

             position: 1430 of 1954 (73%), column: 16
            character: ℕ (displayed as ℕ) (codepoint 8469, #o20425, #x2115)
    preferred charset: unicode (Unicode (ISO10646))
code point in charset: 0x2115
               script: symbol
               syntax: w    which means: word
             category: .:Base, L:Left-to-right (strong)
             to input: type "C-x 8 RET HEX-CODEPOINT" or "C-x 8 RET NAME"
          buffer code: #xE2 #x84 #x95
            file code: #xE2 #x84 #x95 (encoded by coding system utf-8-unix)
              display: no font available

Character code properties: customize what to show
  name: DOUBLE-STRUCK CAPITAL N
  old-name: DOUBLE-STRUCK N
  general-category: Lu (Letter, Uppercase)
  decomposition: (font 78) (font 'N')

Important part: display: no font available.

It should be possible to set that in our .Xresources file:

With the X resource ‘Emacs.Font’, you can specify a fontset name just like an actual font name.

I do not know what is a proper syntax for that though.

Before that change I was able to see a lot of unicode glyphs not supported by my font of choice. After that change — I can only see one font in my Emacs and empty boxes-placeholders for glyphs not supported by it.

It works in my system and should be enough for now before someone else give you a detailed, technical and correct answer.

kmicu
  • 2,395
  • 1
  • 15
  • 15
  • Your explanation makes good sense, but the actual suggestion configuration doesn't seem to work. I can't try using the Xresources approach because I'm using the Cocoa build of Emacs on OS X, but setting the fontset fonts as you suggested seems to have no effect. If I `list-fontsets` after putting your code in my init file, I see four listed and only one is related to the font I set. – karl Dec 26 '14 at 15:08
  • 1
    I should clarify: this mysteriously seems to fix the problem for a chunk of glyphs, but not all of them. I get probably 75% of characters in the font I want, but still a fallback for a select few. – karl Dec 26 '14 at 15:22
  • Yes, that is only valid for *'unicode* range. If you want more encodings covered then you should also change fontsets for them. I will update my answer, but this is probably some hackery. We need to wait for an answer from the Elders of Emacs. :) – kmicu Dec 26 '14 at 19:18
  • I really appreciate the help so far and am close to marking your answer as accepted, save one final problem. The main character I keep noticing that this doesn't work for, even after the helpful modification, is the "double struck capital N" used to denote the set of natural numbers. If I examine it with `describe-char` it seems to be unicode with a code point in the range you've used, but it still displays with a different font. – karl Dec 27 '14 at 19:40
  • I tested ℕ symbol (with *name: DOUBLE-STRUCK CAPITAL N* as showed by inspecting that character with `C-u C-x =`) and I was able to eliminate it. We need to add *nil* target to our rules. Check my update. Cheers. – kmicu Dec 28 '14 at 17:38
  • In other words we need to say — use my font for the whole range of characters, **but if my font does not support a character, then do not fallback to another font, but also use my font**. ;) – kmicu Dec 28 '14 at 18:29
  • 1
    That last update gave me everything I wanted---marked as solved. Thanks for your help. – karl Dec 28 '14 at 21:06