mirror of
https://github.com/wez/wezterm.git
synced 2024-10-26 23:58:28 +03:00
Add wezterm ls-fonts
subcommand
At this time it just shows you the fonts that your config matches and where they came from: ``` ; wezterm -n ls-fonts Primary font: wezterm.font("JetBrains Mono", weight="Regular", stretch="Normal", italic=false) (/home/wez/.fonts/JetBrainsMono-Regular.ttf, FontConfig) wezterm.font("Noto Color Emoji", weight="Regular", stretch="Normal", italic=false) (/usr/share/fonts/google-noto-emoji/NotoColorEmoji.ttf, FontConfig) wezterm.font("Noto Color Emoji", weight="Regular", stretch="Normal", italic=false) (/home/wez/.fonts/NotoColorEmoji.ttf, FontConfig) wezterm.font("Last Resort High-Efficiency", weight="Regular", stretch="Normal", italic=false) (<built-in>, BuiltIn) When Italic=true: wezterm.font("JetBrains Mono", weight="Regular", stretch="Normal", italic=true) (/home/wez/.fonts/JetBrainsMono-Italic.ttf, FontConfig) wezterm.font("JetBrains Mono", weight="Regular", stretch="Normal", italic=false) (/home/wez/.fonts/JetBrainsMono-Regular.ttf, FontConfig) wezterm.font("Noto Color Emoji", weight="Regular", stretch="Normal", italic=false) (/usr/share/fonts/google-noto-emoji/NotoColorEmoji.ttf, FontConfig) wezterm.font("Noto Color Emoji", weight="Regular", stretch="Normal", italic=false) (/home/wez/.fonts/NotoColorEmoji.ttf, FontConfig) wezterm.font("Last Resort High-Efficiency", weight="Regular", stretch="Normal", italic=false) (<built-in>, BuiltIn) When Intensity=Bold: wezterm.font("JetBrains Mono", weight="Bold", stretch="Normal", italic=false) (/home/wez/.fonts/JetBrainsMono-Bold.ttf, FontConfig) wezterm.font("JetBrains Mono", weight="Regular", stretch="Normal", italic=false) (/home/wez/.fonts/JetBrainsMono-Regular.ttf, FontConfig) wezterm.font("Noto Color Emoji", weight="Regular", stretch="Normal", italic=false) (/usr/share/fonts/google-noto-emoji/NotoColorEmoji.ttf, FontConfig) wezterm.font("Noto Color Emoji", weight="Regular", stretch="Normal", italic=false) (/home/wez/.fonts/NotoColorEmoji.ttf, FontConfig) wezterm.font("Last Resort High-Efficiency", weight="Regular", stretch="Normal", italic=false) (<built-in>, BuiltIn) When Intensity=Bold Italic=true: wezterm.font("JetBrains Mono", weight="Bold", stretch="Normal", italic=true) (/home/wez/.fonts/JetBrainsMono-Bold-Italic.ttf, FontConfig) wezterm.font("JetBrains Mono", weight="Regular", stretch="Normal", italic=false) (/home/wez/.fonts/JetBrainsMono-Regular.ttf, FontConfig) wezterm.font("Noto Color Emoji", weight="Regular", stretch="Normal", italic=false) (/usr/share/fonts/google-noto-emoji/NotoColorEmoji.ttf, FontConfig) wezterm.font("Noto Color Emoji", weight="Regular", stretch="Normal", italic=false) (/home/wez/.fonts/NotoColorEmoji.ttf, FontConfig) wezterm.font("Last Resort High-Efficiency", weight="Regular", stretch="Normal", italic=false) (<built-in>, BuiltIn) ``` refs: #347
This commit is contained in:
parent
5ced58c37b
commit
2e34f1a8dd
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -4432,6 +4432,7 @@ dependencies = [
|
||||
"core-foundation 0.9.1",
|
||||
"core-text",
|
||||
"dwrote",
|
||||
"enum-display-derive",
|
||||
"euclid",
|
||||
"fontconfig",
|
||||
"freetype",
|
||||
|
@ -1,5 +1,11 @@
|
||||
[workspace]
|
||||
members = ["wezterm-mux-server", "wezterm", "wezterm-gui", "strip-ansi-escapes", "wezterm-ssh"]
|
||||
members = [
|
||||
"strip-ansi-escapes",
|
||||
"wezterm",
|
||||
"wezterm-gui",
|
||||
"wezterm-mux-server",
|
||||
"wezterm-ssh"
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
[profile.release]
|
||||
|
@ -10,6 +10,7 @@ edition = "2018"
|
||||
allsorts = { git = "https://github.com/yeslogic/allsorts.git", rev="3947164a201ab5e15d5f23204faaaaaad52531aa" }
|
||||
anyhow = "1.0"
|
||||
config = { path = "../config" }
|
||||
enum-display-derive = "0.1"
|
||||
euclid = "0.22"
|
||||
freetype = { path = "../deps/freetype" }
|
||||
harfbuzz = { path = "../deps/harfbuzz" }
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! A font-database to keep track of fonts that we've located
|
||||
|
||||
use crate::locator::FontDataSource;
|
||||
use crate::locator::{FontDataSource, FontOrigin};
|
||||
use crate::parser::{load_built_in_fonts, parse_and_collect_font_info, ParsedFont};
|
||||
use anyhow::Context;
|
||||
use config::{Config, FontAttributes};
|
||||
@ -38,7 +38,7 @@ impl FontDatabase {
|
||||
};
|
||||
|
||||
let source = FontDataSource::OnDisk(entry.path().to_path_buf());
|
||||
parse_and_collect_font_info(&source, &mut font_info)
|
||||
parse_and_collect_font_info(&source, &mut font_info, FontOrigin::FontDirs)
|
||||
.map_err(|err| {
|
||||
log::trace!("failed to read {:?}: {:#}", source, err);
|
||||
err
|
||||
|
@ -149,6 +149,7 @@ impl Face {
|
||||
source: self.source.source.clone(),
|
||||
index: self.source.index,
|
||||
variation: i,
|
||||
origin: self.source.origin,
|
||||
};
|
||||
res.push(ParsedFont::from_face(&self, source)?);
|
||||
}
|
||||
|
@ -142,6 +142,10 @@ impl LoadedFont {
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clone_handles(&self) -> Vec<ParsedFont> {
|
||||
self.handles.borrow().clone()
|
||||
}
|
||||
}
|
||||
|
||||
struct FontConfigInner {
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![cfg(target_os = "macos")]
|
||||
|
||||
use crate::locator::{FontDataSource, FontLocator};
|
||||
use crate::locator::{FontDataSource, FontLocator, FontOrigin};
|
||||
use crate::parser::ParsedFont;
|
||||
use config::{FontAttributes, FontStretch, FontWeight};
|
||||
use core_foundation::array::CFArray;
|
||||
@ -66,7 +66,11 @@ fn handles_from_descriptor(descriptor: &CTFontDescriptor) -> Vec<ParsedFont> {
|
||||
|
||||
let mut font_info = vec![];
|
||||
let source = FontDataSource::OnDisk(path);
|
||||
let _ = crate::parser::parse_and_collect_font_info(&source, &mut font_info);
|
||||
let _ = crate::parser::parse_and_collect_font_info(
|
||||
&source,
|
||||
&mut font_info,
|
||||
FontOrigin::CoreText,
|
||||
);
|
||||
|
||||
for parsed in font_info {
|
||||
if parsed.names().full_name == family_name || parsed.names().family == family_name {
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::fcwrap;
|
||||
use crate::locator::{FontDataHandle, FontDataSource, FontLocator};
|
||||
use crate::locator::{FontDataHandle, FontDataSource, FontLocator, FontOrigin};
|
||||
use crate::parser::ParsedFont;
|
||||
use anyhow::Context;
|
||||
use config::FontAttributes;
|
||||
@ -92,6 +92,7 @@ impl FontLocator for FontConfigFontLocator {
|
||||
source: FontDataSource::OnDisk(file.into()),
|
||||
index,
|
||||
variation,
|
||||
origin: FontOrigin::FontConfig,
|
||||
};
|
||||
|
||||
// fontconfig will give us a boatload of random fallbacks.
|
||||
@ -161,6 +162,7 @@ impl FontLocator for FontConfigFontLocator {
|
||||
source: FontDataSource::OnDisk(file.into()),
|
||||
index: pat.get_integer("index")?.try_into()?,
|
||||
variation: 0,
|
||||
origin: FontOrigin::FontConfig,
|
||||
};
|
||||
if let Ok(parsed) = crate::parser::ParsedFont::from_locator(&handle) {
|
||||
fonts.push(parsed);
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![cfg(windows)]
|
||||
|
||||
use crate::locator::{FontDataSource, FontLocator};
|
||||
use crate::locator::{FontDataSource, FontLocator, FontOrigin};
|
||||
use crate::parser::{best_matching_font, parse_and_collect_font_info, ParsedFont};
|
||||
use config::{FontAttributes, FontStretch as WTFontStretch, FontWeight as WTFontWeight};
|
||||
use dwrote::{FontDescriptor, FontStretch, FontStyle, FontWeight};
|
||||
@ -63,7 +63,7 @@ fn extract_font_data(font: HFONT, attr: &FontAttributes) -> anyhow::Result<Parse
|
||||
};
|
||||
|
||||
let mut font_info = vec![];
|
||||
parse_and_collect_font_info(&source, &mut font_info)?;
|
||||
parse_and_collect_font_info(&source, &mut font_info, FontOrigin::Gdi)?;
|
||||
let matches = ParsedFont::best_match(attr, font_info);
|
||||
|
||||
for m in matches {
|
||||
@ -146,7 +146,7 @@ fn handle_from_descriptor(
|
||||
|
||||
log::debug!("{} -> {}", family_name, path.display());
|
||||
let source = FontDataSource::OnDisk(path);
|
||||
match best_matching_font(&source, attr) {
|
||||
match best_matching_font(&source, attr, FontOrigin::DirectWrite) {
|
||||
Ok(Some(parsed)) => {
|
||||
return Some(parsed);
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
use crate::parser::ParsedFont;
|
||||
use config::FontAttributes;
|
||||
use enum_display_derive::Display;
|
||||
use std::borrow::Cow;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::Display;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
@ -11,6 +13,16 @@ pub mod core_text;
|
||||
pub mod font_config;
|
||||
pub mod gdi;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd, Display)]
|
||||
pub enum FontOrigin {
|
||||
FontConfig,
|
||||
CoreText,
|
||||
DirectWrite,
|
||||
Gdi,
|
||||
FontDirs,
|
||||
BuiltIn,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum FontDataSource {
|
||||
OnDisk(PathBuf),
|
||||
@ -101,6 +113,7 @@ pub struct FontDataHandle {
|
||||
pub source: FontDataSource,
|
||||
pub index: u32,
|
||||
pub variation: u32,
|
||||
pub origin: FontOrigin,
|
||||
}
|
||||
|
||||
impl FontDataHandle {
|
||||
@ -115,6 +128,23 @@ impl FontDataHandle {
|
||||
pub fn set_index(&mut self, idx: u32) {
|
||||
self.index = idx;
|
||||
}
|
||||
|
||||
pub fn diagnostic_string(&self) -> String {
|
||||
let source = match &self.source {
|
||||
FontDataSource::OnDisk(path) => format!("{}", path.display()),
|
||||
FontDataSource::BuiltIn { .. } => "<built-in>".to_string(),
|
||||
FontDataSource::Memory { .. } => "<imported to RAM>".to_string(),
|
||||
};
|
||||
|
||||
if self.index == 0 && self.variation == 0 {
|
||||
format!("{}, {}", source, self.origin)
|
||||
} else {
|
||||
format!(
|
||||
"{} index={} variation={}, {}",
|
||||
source, self.index, self.variation, self.origin
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FontLocator {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::locator::{FontDataHandle, FontDataSource};
|
||||
use crate::locator::{FontDataHandle, FontDataSource, FontOrigin};
|
||||
use crate::shaper::GlyphInfo;
|
||||
use config::FontAttributes;
|
||||
pub use config::{FontStretch, FontWeight};
|
||||
@ -368,6 +368,7 @@ pub(crate) fn load_built_in_fonts(font_info: &mut Vec<ParsedFont>) -> anyhow::Re
|
||||
source: FontDataSource::BuiltIn { data, name },
|
||||
index: 0,
|
||||
variation: 0,
|
||||
origin: FontOrigin::BuiltIn,
|
||||
};
|
||||
let face = lib.face_from_locator(&locator)?;
|
||||
let parsed = ParsedFont::from_face(&face, locator)?;
|
||||
@ -380,15 +381,17 @@ pub(crate) fn load_built_in_fonts(font_info: &mut Vec<ParsedFont>) -> anyhow::Re
|
||||
pub fn best_matching_font(
|
||||
source: &FontDataSource,
|
||||
font_attr: &FontAttributes,
|
||||
origin: FontOrigin,
|
||||
) -> anyhow::Result<Option<ParsedFont>> {
|
||||
let mut font_info = vec![];
|
||||
parse_and_collect_font_info(source, &mut font_info)?;
|
||||
parse_and_collect_font_info(source, &mut font_info, origin)?;
|
||||
Ok(ParsedFont::best_match(font_attr, font_info))
|
||||
}
|
||||
|
||||
pub(crate) fn parse_and_collect_font_info(
|
||||
source: &FontDataSource,
|
||||
font_info: &mut Vec<ParsedFont>,
|
||||
origin: FontOrigin,
|
||||
) -> anyhow::Result<()> {
|
||||
let lib = crate::ftwrap::Library::new()?;
|
||||
let num_faces = lib.query_num_faces(&source)?;
|
||||
@ -398,11 +401,13 @@ pub(crate) fn parse_and_collect_font_info(
|
||||
source: &FontDataSource,
|
||||
index: u32,
|
||||
font_info: &mut Vec<ParsedFont>,
|
||||
origin: FontOrigin,
|
||||
) -> anyhow::Result<()> {
|
||||
let locator = FontDataHandle {
|
||||
source: source.clone(),
|
||||
index,
|
||||
variation: 0,
|
||||
origin,
|
||||
};
|
||||
|
||||
let face = lib.face_from_locator(&locator)?;
|
||||
@ -418,7 +423,7 @@ pub(crate) fn parse_and_collect_font_info(
|
||||
}
|
||||
|
||||
for index in 0..num_faces {
|
||||
if let Err(err) = load_one(&lib, &source, index, font_info) {
|
||||
if let Err(err) = load_one(&lib, &source, index, font_info, origin) {
|
||||
log::trace!("error while parsing {:?} index {}: {}", source, index, err);
|
||||
}
|
||||
}
|
||||
|
@ -108,3 +108,6 @@ pub struct ConnectCommand {
|
||||
#[structopt(parse(from_os_str))]
|
||||
pub prog: Vec<OsString>,
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt, Clone)]
|
||||
pub struct LsFontsCommand {}
|
||||
|
@ -84,6 +84,9 @@ enum SubCommand {
|
||||
|
||||
#[structopt(name = "connect", about = "Connect to wezterm multiplexer")]
|
||||
Connect(ConnectCommand),
|
||||
|
||||
#[structopt(name = "ls-fonts", about = "Display information about fonts")]
|
||||
LsFonts(LsFontsCommand),
|
||||
}
|
||||
|
||||
async fn async_run_ssh(opts: SshCommand) -> anyhow::Result<()> {
|
||||
@ -410,6 +413,55 @@ fn maybe_show_configuration_error_window() {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_ls_fonts(config: config::ConfigHandle, _cmd: &LsFontsCommand) -> anyhow::Result<()> {
|
||||
let font_config = wezterm_font::FontConfiguration::new(Some(config.clone()))?;
|
||||
|
||||
println!("Primary font:");
|
||||
let default_font = font_config.default_font()?;
|
||||
for f in default_font.clone_handles() {
|
||||
println!(" {}", f.lua_name());
|
||||
println!(" ({})", f.handle.diagnostic_string());
|
||||
println!();
|
||||
}
|
||||
|
||||
for rule in &config.font_rules {
|
||||
println!();
|
||||
|
||||
let mut condition = "When".to_string();
|
||||
if let Some(intensity) = &rule.intensity {
|
||||
condition.push_str(&format!(" Intensity={:?}", intensity));
|
||||
}
|
||||
if let Some(underline) = &rule.underline {
|
||||
condition.push_str(&format!(" Underline={:?}", underline));
|
||||
}
|
||||
if let Some(italic) = &rule.italic {
|
||||
condition.push_str(&format!(" Italic={:?}", italic));
|
||||
}
|
||||
if let Some(blink) = &rule.blink {
|
||||
condition.push_str(&format!(" Blink={:?}", blink));
|
||||
}
|
||||
if let Some(rev) = &rule.reverse {
|
||||
condition.push_str(&format!(" Reverse={:?}", rev));
|
||||
}
|
||||
if let Some(strikethrough) = &rule.strikethrough {
|
||||
condition.push_str(&format!(" Strikethrough={:?}", strikethrough));
|
||||
}
|
||||
if let Some(invisible) = &rule.invisible {
|
||||
condition.push_str(&format!(" Invisible={:?}", invisible));
|
||||
}
|
||||
|
||||
println!("{}:", condition);
|
||||
let font = font_config.resolve_font(&rule.font)?;
|
||||
for f in font.clone_handles() {
|
||||
println!(" {}", f.lua_name());
|
||||
println!(" ({})", f.handle.diagnostic_string());
|
||||
println!();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
mod win_bindings {
|
||||
::windows::include_bindings!();
|
||||
@ -484,5 +536,6 @@ fn run() -> anyhow::Result<()> {
|
||||
SubCommand::Ssh(ssh) => run_ssh(ssh),
|
||||
SubCommand::Serial(serial) => run_serial(config, &serial),
|
||||
SubCommand::Connect(connect) => run_mux_client(config, &connect),
|
||||
SubCommand::LsFonts(cmd) => run_ls_fonts(config, &cmd),
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,9 @@ enum SubCommand {
|
||||
#[structopt(name = "connect", about = "Connect to wezterm multiplexer")]
|
||||
Connect(ConnectCommand),
|
||||
|
||||
#[structopt(name = "ls-fonts", about = "Display information about fonts")]
|
||||
LsFonts(LsFontsCommand),
|
||||
|
||||
#[structopt(name = "cli", about = "Interact with experimental mux server")]
|
||||
Cli(CliCommand),
|
||||
|
||||
@ -295,6 +298,7 @@ fn run() -> anyhow::Result<()> {
|
||||
.unwrap_or_else(|| SubCommand::Start(StartCommand::default()))
|
||||
{
|
||||
SubCommand::Start(_)
|
||||
| SubCommand::LsFonts(_)
|
||||
| SubCommand::Ssh(_)
|
||||
| SubCommand::Serial(_)
|
||||
| SubCommand::Connect(_) => delegate_to_gui(saver),
|
||||
|
Loading…
Reference in New Issue
Block a user