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

EditorSupport LevelMechanismFont FamilyWeightStyleSize
VSCode 1.97+ FULL textMateRules fontFamily YesYesYesNo
Neovim (Goneovim) PARTIAL Highlight groups + font metadata YesLimitedYesNo
Neovim (Neovide) PARTIAL Bold/italic via highlight groups Requires patchingBold onlyYesNo
Kitty terminal PARTIAL symbol_map + PUA ranges Config-levelNoNoNo
Zed PARTIAL text_style_overrides YesYesYesNo
Helix + Kitty LIMITED Kitty symbol_map approximation Unicode ranges onlyNoNoNo
Sublime Text PARTIAL .sublime-theme font.face YesYesYesNo
Terminal (generic) LIMITED Bold/italic/underline only NoBold onlyYesNo

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 selector
  • settings.fontFamily -- font family string with fallbacks
  • settings.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.fontFamily setting should include your default font as a baseline

Troubleshooting

ProblemSolution
Fonts not applyingVerify the font family name matches exactly what the OS reports. Use polyfont check to verify availability.
Some scopes not styledCheck 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 updatingReload the VSCode window after changing settings.json (Ctrl+Shift+P then "Reload Window").
Conflicting theme rulesPolyfont 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 GroupTextMate Scope
@keywordkeyword
@keyword.controlkeyword.control
@commentcomment
@stringstring
@functionentity.name.function
@typeentity.name.type
@variablevariable
@variable.parametervariable.parameter
@constantconstant
@numberconstant.numeric
@function.callsupport.function
@punctuationpunctuation
@operatorkeyword.operator
@tagentity.name.tag
@attributeentity.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 ClientFont FamilyBoldItalicNotes
GoneovimYesYesYesBest Neovim GUI for polyfont.
NeovidePartialYesYesFont family per group may require patching.
Neovim in terminalNoYesYesOnly bold/italic styling available.
NVIM-QtNoYesYesNo 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_overrides may 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.face key requires Sublime Text 4+.

Known Limitations

VSCode

  • Font size per scope is not supported by the textMateRules API.
  • The fontFamily property in textMateRules was added in VSCode 1.97. Earlier versions will ignore it silently.
  • Themes that set fontStyle on the same scopes may conflict with Polyfont rules.
  • Ligatures are controlled by the base editor.fontFamily setting; 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 font key in nvim_set_hl is a Neovim 0.9+ feature.

Kitty

  • symbol_map operates 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 check to 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.