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.

3
  • 2
    Did you try (set-fontset-font t nil MY-FONT) where MY-FONT is the name of your font?
    – user227
    Commented Dec 23, 2014 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
    Commented Dec 23, 2014 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). Commented May 25, 2021 at 13:48

1 Answer 1

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.

7
  • 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
    Commented Dec 26, 2014 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
    Commented Dec 26, 2014 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
    Commented Dec 26, 2014 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
    Commented Dec 27, 2014 at 19:40
  • 1
    That last update gave me everything I wanted---marked as solved. Thanks for your help.
    – karl
    Commented Dec 28, 2014 at 21:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.