Files
ghostty-rs/crates/ghostty-cli/src/list_fonts.rs
T
ddidderr 126da77a37 style: apply nightly rustfmt import grouping across the workspace
rustfmt.toml sets group_imports, imports_granularity and imports_layout,
which are nightly-only; agents formatted with stable rustfmt, which
ignored them. This is a formatting-only pass with `cargo +nightly fmt`.

Test Plan:
- cargo clippy --workspace --all-targets -- -D warnings
- cargo test --workspace
2026-10-12 05:03:37 +02:00

121 lines
4.0 KiB
Rust

//! `+list-fonts` (ZIG/src/cli/list_fonts.zig).
use ghostty_config::config_struct;
use crate::error::Error;
config_struct! {
pub struct Options {
/// The font family to search for. If this is set, then only fonts
/// matching this family will be listed.
"family" => family: Option<String> = None,
/// The style name to search for.
"style" => style: Option<String> = None,
/// Font styles to search for. If this is set, then only fonts that
/// match the given styles will be listed.
"bold" => bold: bool = false,
"italic" => italic: bool = false,
}
}
cli_options!(Options, help);
/// The `list-fonts` command is used to list all the available fonts for
/// Ghostty. This uses the exact same font discovery mechanism Ghostty uses to
/// find fonts to use.
///
/// When executed with no arguments, this will list all available fonts, sorted
/// by family name, then font name. If a family name is given with `--family`,
/// the sorting will be disabled and the results instead will be shown in the
/// same priority order Ghostty would use to pick a font.
///
/// Flags:
///
/// * `--bold`: Filter results to specific bold styles. It is not guaranteed
/// that only those styles are returned. They are only prioritized.
///
/// * `--italic`: Filter results to specific italic styles. It is not guaranteed
/// that only those styles are returned. They are only prioritized.
///
/// * `--style`: Filter results based on the style string advertised by a font.
/// It is not guaranteed that only those styles are returned. They are only
/// prioritized.
///
/// * `--family`: Filter results to a specific font family. The family handling
/// is identical to the `font-family` set of Ghostty configuration values, so
/// this can be used to debug why your desired font may not be loading.
pub fn run(args: &[String]) -> Result<u8, Error> {
let mut opts = Options::default();
crate::parse_options(&mut opts, args)?;
use std::{collections::HashMap, io::Write};
// We'll be putting our fonts into a list categorized by family
// so it is easier to read the output.
let mut families: Vec<String> = Vec::new();
let mut map: HashMap<String, Vec<String>> = HashMap::new();
// Look up all available fonts
let disco = ghostty_font::Discover::init();
let desc = ghostty_font::Descriptor {
monospace: opts.family.is_none(),
family: opts.family.clone(),
style: opts.style.clone(),
bold: opts.bold,
italic: opts.italic,
..ghostty_font::Descriptor::default()
};
let mut it = disco
.discover(&desc)
.map_err(|e| Error::Other(e.to_string()))?;
while let Some(face) = it.next().map_err(|e| Error::Other(e.to_string()))? {
let family = match face.family_name() {
Ok(v) => v,
Err(err) => {
log::error!("failed to get font family name: {err}");
continue;
}
};
let full_name = match face.name() {
Ok(v) => v,
Err(err) => {
log::error!("failed to get font name: {err}");
continue;
}
};
let list = map.entry(family.clone()).or_insert_with(|| {
families.push(family);
Vec::new()
});
list.push(full_name);
}
// Sort our keys.
if opts.family.is_none() {
families.sort_unstable();
}
// Output each
let mut stdout = std::io::BufWriter::new(std::io::stdout().lock());
for family in &families {
let Some(list) = map.get_mut(family) else {
continue;
};
if list.is_empty() {
continue;
}
if opts.family.is_none() {
list.sort_unstable();
}
writeln!(stdout, "{family}")?;
for item in list.iter() {
writeln!(stdout, " {item}")?;
}
writeln!(stdout)?;
}
stdout.flush()?;
Ok(0)
}