Editor Integration
Polyfont supports multiple editors through different integration mechanisms. The level of support depends on the editor's ability to apply per-token font styling.
Editor Compatibility Matrix
| Editor | Support Level | Mechanism | Font Family | Weight | Style | Size |
|---|---|---|---|---|---|---|
| VSCode 1.97+ | FULL | textMateRules fontFamily |
Yes | Yes | Yes | No |
| Neovim (Goneovim) | PARTIAL | Highlight groups + font metadata | Yes | Limited | Yes | No |
| Neovim (Neovide) | PARTIAL | Bold/italic via highlight groups | Requires patching | Bold only | Yes | No |
| Kitty terminal | PARTIAL | symbol_map + PUA ranges |
Config-level | No | No | No |
| Zed | PARTIAL | text_style_overrides |
Yes | Yes | Yes | No |
| Helix + Kitty | LIMITED | Kitty symbol_map approximation |
Unicode ranges only | No | No | No |
| Sublime Text | PARTIAL | .sublime-theme font.face |
Yes | Yes | Yes | No |
| Terminal (generic) | LIMITED | Bold/italic/underline only | No | Bold only | Yes | No |
VSCode
VSCode 1.97 (December 2025) added native fontFamily support in textMateRules, which provides the cleanest integration path for per-token font styling.
How it works
Polyfont generates editor.tokenColorCustomizations.textMateRules entries where each rule includes:
scope-- the TextMate scope selectorsettings.fontFamily-- font family string with fallbackssettings.fontWeight-- CSS font weight (when not regular)settings.fontStyle-- font style (when not normal)
Setup
Option A: CLI-generated settings (recommended)
# Print to stdout
polyfont vscode
# Write to .vscode/settings.json (merges with existing)
polyfont vscode -o .vscode/settings.json
The generated JSON looks like:
{
"editor.tokenColorCustomizations": {
"textMateRules": [
{
"scope": "keyword",
"settings": {
"fontFamily": "Maple Mono",
"fontWeight": "bold"
}
},
{
"scope": "comment",
"settings": {
"fontFamily": "IBM Plex Mono",
"fontStyle": "italic"
}
}
]
}
}
Option B: VSCode extension
cd editors/vscode
npm install
npm run build
# Install as development extension or package as .vsix
Requirements
- VSCode 1.97 or later
- Font families must be installed on the system
- The
editor.fontFamilysetting should include your default font as a baseline
Troubleshooting
| Problem | Solution |
|---|---|
| Fonts not applying | Verify the font family name matches exactly what the OS reports. Use polyfont check to verify availability. |
| Some scopes not styled | Check that the scope in .polyfont.toml matches the TextMate scope used by the language grammar. Use "Developer: Inspect Editor Tokens and Scopes" from the command palette. |
| Settings not updating | Reload the VSCode window after changing settings.json (Ctrl+Shift+P then "Reload Window"). |
| Conflicting theme rules | Polyfont rules only set font properties. If your theme sets fontStyle, the theme may override. Ensure no theme rules set fontStyle for the same scopes. |
Neovim
Neovim integration uses Tree-sitter for syntax parsing and highlight groups for font application. Font family changes require a GUI client.
Plugin setup
Using lazy.nvim:
{
"WyattAu/polyfont",
dir = "/path/to/polyfont/editors/neovim",
config = function()
require("polyfont").setup()
end,
}
CLI-generated config
polyfont neovim
Outputs Lua code that sets highlight groups:
vim.o.guifont = 'Fira Code'
vim.api.nvim_set_hl(0, '@keyword', { font = 'Maple Mono:bold' })
vim.api.nvim_set_hl(0, '@comment', { font = 'IBM Plex Mono:italic' })
vim.api.nvim_set_hl(0, '@entity_name_function', { font = 'Monaspace Argon:h:semi-bold' })
Tree-sitter highlight groups
Neovim uses Tree-sitter highlight group names that map to TextMate scopes. Common mappings:
| Tree-sitter Group | TextMate Scope |
|---|---|
@keyword | keyword |
@keyword.control | keyword.control |
@comment | comment |
@string | string |
@function | entity.name.function |
@type | entity.name.type |
@variable | variable |
@variable.parameter | variable.parameter |
@constant | constant |
@number | constant.numeric |
@function.call | support.function |
@punctuation | punctuation |
@operator | keyword.operator |
@tag | entity.name.tag |
@attribute | entity.other.attribute-name |
GUI support
Font family assignment in Neovim highlight groups requires a GUI that supports the font key in nvim_set_hl:
| GUI Client | Font Family | Bold | Italic | Notes |
|---|---|---|---|---|
| Goneovim | Yes | Yes | Yes | Best Neovim GUI for polyfont. |
| Neovide | Partial | Yes | Yes | Font family per group may require patching. |
| Neovim in terminal | No | Yes | Yes | Only bold/italic styling available. |
| NVIM-Qt | No | Yes | Yes | No per-group font family support. |
Kitty Terminal
Kitty supports mapping Unicode ranges to specific fonts via symbol_map. This is a config-level mechanism, not runtime.
Setup
polyfont kitty >> ~/.config/kitty/kitty.conf
Generated output
The CLI generates symbol_map entries with comments indicating the scope mapping:
# polyfont kitty configuration
# Generated by polyfont-cli
#
# Note: Kitty uses symbol_map for unicode ranges, not TextMate scopes.
# Adjust the unicode ranges below to match your needs.
# scope: keyword -> Maple Mono (weight: bold, style: normal)
# symbol_map U+XXXX-U+YYYY Maple Mono
Limitations
Kitty's symbol_map works with Unicode codepoint ranges, not syntax scopes. To use this effectively, you need to map fonts to specific Unicode ranges (such as Private Use Area characters, mathematical symbols, or box-drawing characters). This is not a replacement for scope-based font assignment in editors.
Zed
Zed supports per-scope font styling through text_style_overrides in settings. The extension reads .polyfont.toml and generates the appropriate Zed theme entries.
Setup
polyfont zed >> ~/.config/zed/settings.json
Generated output
{
"text_style_overrides": {
"keyword": {
"font_family": "Maple Mono",
"font_weight": "Bold"
},
"comment": {
"font_family": "IBM Plex Mono",
"font_italic": true
}
}
}
Limitations
- Zed's
text_style_overridesmay not cover all TextMate scopes. - Font family support is a relatively new Zed feature; verify with your version.
Helix
Helix runs in the terminal and does not support per-token font switching natively. The integration generates Kitty symbol_map configuration that approximates per-scope font differentiation.
Setup
polyfont helix >> ~/.config/kitty/kitty.conf
Limitations
- This is an approximation, not true per-scope rendering.
- Same character in different scopes renders with the same font.
- Requires Kitty terminal; other terminals may not support
symbol_map.
Sublime Text
Sublime Text supports per-scope font settings via the font.face key in .sublime-theme files. The integration reads .polyfont.toml and generates theme override entries.
Setup
polyfont sublime -o ~/.config/sublime-text/Packages/User/polyfont.hidden-tmTheme
Generated output
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>settings</key>
<array>
<dict>
<key>scope</key>
<string>keyword</string>
<key>settings</key>
<dict>
<key>font.face</key>
<string>Maple Mono Bold</string>
</dict>
</dict>
</array>
</dict>
</plist>
Limitations
- Sublime Text applies theme overrides at the file level; conflicting themes may override polyfont settings.
- The
font.facekey requires Sublime Text 4+.
Known Limitations
VSCode
- Font size per scope is not supported by the
textMateRulesAPI. - The
fontFamilyproperty intextMateRuleswas added in VSCode 1.97. Earlier versions will ignore it silently. - Themes that set
fontStyleon the same scopes may conflict with Polyfont rules. - Ligatures are controlled by the base
editor.fontFamilysetting; per-token ligature control is not available.
Neovim
- Per-token font family changes require a GUI client (Goneovim recommended). Terminal Neovim cannot change fonts per character.
- Tree-sitter highlight groups do not map 1:1 to TextMate scopes. Some manual mapping is required.
- Bold and italic are widely supported, but fine-grained weight control (semi-bold, light, etc.) depends on the GUI client.
- The
fontkey innvim_set_hlis a Neovim 0.9+ feature.
Kitty
symbol_mapoperates on Unicode codepoint ranges, not syntax scopes. Direct scope-to-font mapping is not possible.- Configuration is static; changes require restarting Kitty or reloading the config.
- No font weight or style control per range.
General
- Font availability depends on system installation. Use
polyfont checkto verify. - Mixed font rendering may cause alignment issues when fonts have different metrics (x-height, ascender, descender). Choose fonts with similar metrics for best results.
- The LSP server provides basic line-level token classification; full token-level resolution requires the editor extension to provide its own tokenizer.