Skip to content
MeanderingProgrammer edited this page Nov 6, 2024 · 29 revisions

Fonts

Preface

I am no expert on font rendering and some of the details below are likely oversimplified. If you find anything to be inaccurate or misleading please let me know!

The goal here is to give someone relatively new to neovim / working in the terminal a decent background and concrete steps to get the kind of experience they want out of their editor. This document is focused entirely on working in the terminal, if you use a GUI then some information may still be helpful, but not as targeted.

If you don't care for any Background skip the next section and look over Solution and if you run into problems checkout Troubleshooting.

Background

So you've downloaded neovim and picked up a few plugins, nice! Then you open up your new file tree from neo-tree.nvim or take a look at your status line from lualine.nvim or an awesome markdown renderer :) and you notice the dreaded �, what's going on?

Well, like most people, up until now, you've only ever needed your terminal to display letters, numbers, and the basic symbols you find on your keyboard. So your font, which likely only implements these basic characters was never a problem. Now you want to display complex glyphs / icons, leading to this problem. When your font doesn't implement a particular icon, your terminal emulator (WezTerm, kitty, Alacritty, iTerm2, etc.) doesn't know what to do, so as a last resort will show you the �. You might have some questions so:

Why doesn't my font have these icons?

This is a very niche problem that most fonts don't need to solve. These missing icons are most likely what are referred to as nerd font icons, and there are over 10,000 of them.

The idea of every font shipping with implementations for all these icons is crazy if you think about it. Who out there using Comic Sans in Word is trying to inline the GitHub logo as text? If font authors went through the trouble of making unique icons it would be an insane amount of work for a tiny portion of users. If they shared the same icons and kept the font part unique all fonts would grow many times in size. Maybe not much of a problem now but still wasteful and extra effort.

GUI applications do not come with the same set of limitations as a terminal. They can render an image no problem. Terminals on the other hand are a fixed size grid where we can paint some pixels in each cell. We've essentially taken some UTF-8 encodings and mapped them to icons using the power fonts.

But I didn't add any icons?

Well maybe not directly, but the plugin you're using did. Somewhere in the code for the plugin you'll find the UTF-8 encoded character that represents the icon your font is missing.

Why do we need fancy icons, this is a terminal?

You're technically correct, we do it for the aesthetic :P I'll add that icons, when used effectively, can give you a lot of information at a glance. With file trees for instance they will tell you what's a folder and the type of each file, once you know what you're looking at. It's likely a bit of both and it's totally reasonable to want things to look nice in an environment you spend hours a day in.

The purist may disagree, and the purist is free to use something else or write it themselves.

Solution

1) Download a Nerd Font

A popular one is JetBrainsMono Nerd Font but any of them should work, pick the one you like. You can do this using:

  • homebrew
  • Your favorite package manager, instructions vary, please Google / LLM
  • website

2) Install the Font

This varies depending on your OS and could involve moving the asset to a specific directory, running some command, or is already handled by your package manager like with homebrew. You just need the font to be visible, apply Google / LLM.

3) Use the Font

Set the font as your terminal emulator's font. How depends on the exact terminal emulator and could be under a settings panel or done through a configuration file. A Google for " font config" should get you there.

If you like the results then you're done, woo! Feel free to try other nerd fonts and find what you like.

If you don't like the result then unfortunately things get more complicated as it will require some Deeper Understanding.

Deeper Understanding

How fonts are rendered by your terminal emulator depends on the 2 things you would expect, the font and the terminal emulator. This means the same font used by different terminal emulators will look different. Think of this as the font providing the raw data and the terminal emulator using the data to create an image. We'll cover these 2 sides separately.

Fonts

The fonts suggested in the previous section are commonly known as "patched nerd fonts".

These fonts are generated by taking some existing base font, like JetBrains Mono, and filling all the "gaps" with a set of common icons. This creates a new font with a name like JetBrainsMono Nerd Font, this kind of naming convention is used for most patched nerd fonts.

You may come across information saying you should not use these fonts and they're "bad practice" or "harmful". These are opinions with some legitimate reasons behind them. My stance that you will need to read further to understand is that if you can avoid using a patched nerd font then you should not use one. However there are situations where there are no other options and they are the only solution.

You may be wondering, well if these fonts are "bad" then what do I use, there doesn't even seem to be an alternative. This is where we get into the terminal emulator side.

Terminal Emulators

In the most basic case you set a font for your terminal emulator, it looks up some UTF-8 to get information on how to render the character and if it's missing then you get some default like �. If this is the case for your terminal emulator then you need to use a patched nerd font to render icons, there is no alternative.

However many terminal emulators, especially more recent ones, can take advantage of multiple fonts using what is called font fallback. Essentially you set a preferred font, and if an icon is missing, rather than giving up, the terminal emulator will go through some process to look at other available fonts and find one that does know how to render the icon. Available fonts can mean fonts on your system but also fonts that are bundled with the terminal emulator directly by the author. For these terminal emulators they will often come with a "symbols only" font which is essentially just the icons and non of the standard letters / numbers, instead those are provided by your preferred font, which can now be anything, including Comic Sans. The behavior of the fallback will depend on the terminal emulator's implementation.

Terminal Emulator Font Fallback Issue
WezTerm N/A
kitty N/A
Alacritty #957

If you are using a supported terminal emulator then in theory you should never see a �. You should also avoid using a patched nerd font and instead use the base font directly and allow the fallback to handle symbols. The reason to not use a patched font is that, as far as I know, letting the terminal emulator handles this leads to more consistent behaviors, i.e. symbols all being pulled from a single font.

Troubleshooting

I see icons but they're the wrong size

TODO

FAQs

Can I use different font sizes for different parts?

No, this is just not possible in any terminal emulator. The grid base of all terminal emulators relies on fixed size cells. If you make a font larger it gets taller and wider meaning the cells become different sizes and you no longer have a grid.

Clone this wiki locally