# tui/set-font
Apply a monospaced font live — the workspace grid, popped panel
windows, and surface text all re-render at the chosen face and size on
the next host frame.
## Syntax
[tui/set-font "JetBrains Mono"] # family name [tui/set-font "JetBrains Mono" 16] # family + size [tui/set-font "/usr/share/fonts/x/x.ttf"] # exact file path [tui/set-font %{:family "JetBrains Mono" :cut :bold :size 16}] [tui/set-font %{:path "/home/u/.fonts/x.ttf" :size 16}] [tui/set-font %{:size 20}] # size-only — keeps the font
## Parameters
- `spec` — a string or a map:
- string — an existing font file path (absolute or relative to
the working directory) is used verbatim; anything else is treated
as a family name and resolved by scanning the font
directories.
- map — `:family` with an optional `:cut` (portable; tried
first), and/or `:path` (exact file; fallback when the family is
absent or doesn't resolve) and/or `:size`. A `:size`-only map
keeps the current font.
- `cut` — how `:family` picks the style face: `:regular` (default),
`:bold`, `:italic`, or `:bold-italic` (`:oblique` aliases italic;
case/space/hyphen-insensitive).
- `size` (optional second positional arg) — pixel size; a missing
size keeps the current one.
## Resolution
Family names scan the directories the system's fontconfig configuration
declares (the `<dir>` entries in `$FONTCONFIG_FILE` when set, else
`~/.config/fontconfig/fonts.conf` and `/etc/fonts/fonts.conf` plus its
`conf.d/*.conf` snippets — this is how X11 subdirs, Flatpak exports and
Nix store fonts are found) along with `$XDG_DATA_DIRS` entries; user
dirs (`$XDG_DATA_HOME/fonts` else `~/.local/share/fonts`, `~/.fonts`)
are searched first, and `/usr/local/share/fonts`/`/usr/share/fonts` are
the fixed fallbacks. The scan is recursive (`.ttf`/`.otf`/`.ttc`) and
matches normalised file stems: the requested `:cut` wins, then "Regular"
cuts, then shorter stems (a family without the requested cut falls back
with a warning). Every candidate must be effectively monospaced —
declared fixed-width, or with uniform glyph advances (Google's Noto
Mono TTFs declare neither flag nor advance in the usual way; the probe
catches them). Proportional fonts are rejected.
`:size` clamps to 6–128. A failed resolution returns `false` and logs
a diagnosis to stderr (`font: no font matching family "..."`, `font:`
file is not fixed-width: ...`).`
## Returns
`true` when the change was queued (the rebuild lands on the next host
frame), `false` when the resolution failed or no workspace is attached.
## Notes
- Applies live. The atlas + cell grid rebuild on the main thread —
the grid re-layouts, popped panel windows re-atlas under their own GL
contexts, and surface text follows. Nothing restarts.
- GL hosts only. `tui/set-font` returns `false` on the ANSI host
(`retra` renders through the terminal emulator's font) and on
hosts with no workspace.
- A successful apply moves the Ctrl+0 zoom-reset base to the chosen
size (interactive zoom: Ctrl+= / Ctrl+- / Ctrl+0, browser-style).
- Session-only — like the Ctrl+=/- zoom, an apply is not persisted.
Set the project default with `:font` in the prelude
(`.deft/prelude.dft`): `:font %{:family "JetBrains Mono" :cut :regular :size 16}`.
`[tui/save]` records the applied face in the workspace spec as
`:family` + `:cut`, so saved workspaces stay portable across distros
(paths are only written for faces that report no family).
- Applies the primary face and size. The prelude `:font :fallback`
faces and `:ranges` pre-rasterization stay in effect across applies
(they're prelude-configured) — see the prelude manual. Glyph coverage
itself is dynamic: characters outside the startup set rasterize on
demand, so switching fonts never loses scripts.
## Example — a font picker
# Combined with dialog/search (see tui/font-list): set chosen [dialog/search "Font" [tui/font-list]] if ($chosen != nil) { [tui/set-font $chosen 16] }
## See Also
`tui/font`, `tui/font-list`, `tui/cell-size`