#![deny(clippy::all)]
#![deny(warnings)]
#![deny(rust_2018_idioms, unsafe_code)]
mod args;
mod loader;
mod family;
mod rasterizer;
mod one_char;
mod preview;
use std::{
io::{Read, Write},
net::SocketAddr,
};
use args::Args;
use family::Family;
use preview::{browser::ServerBuilder as PreviewServerBuilder, terminal::ui::UI};
fn init(arg: &Args) {
#[cfg(feature = "log-output")]
{
env_logger::Builder::from_env(
env_logger::Env::default().default_filter_or(env!("CARGO_PKG_NAME")),
)
.format_timestamp_micros()
.init();
}
log::info!("Start with argument: {:?}", arg);
loader::init(!arg.no_system, &arg.custom_font_paths);
}
fn main() {
let argument = args::get();
init(&argument);
let font_set = loader::query(argument.char.0);
let families = family::group_by_family_sort_by_name(&font_set);
if families.is_empty() {
eprintln!(
"No font support this character {}.",
argument.char.description()
);
return;
}
if argument.tui {
let ui = UI::new(families).expect("family length checked before, must not empty");
if let Err(err) = ui.show() {
eprintln!("{:?}", err);
};
} else {
let builder = if argument.preview {
Some(PreviewServerBuilder::from_iter(families.iter()))
} else {
None
};
println!(
"Font(s) support the character {}:",
argument.char.description()
);
show_font_list(families, argument.verbose);
if let Some(builder) = builder {
builder
.build_for(argument.char.0)
.run_until(show_preview_addr_and_wait);
}
}
}
fn show_preview_addr_and_wait(addr: SocketAddr) {
println!("{}", "-".repeat(40));
println!("Please visit http://{}/ in your browser for preview", addr);
print!("And press Enter after your finish...");
std::io::stdout()
.flush()
.expect("flush stdout should not fail");
let _ = std::io::stdin()
.read(&mut [0u8])
.expect("read from stdout should not fail");
}
fn show_font_list(families: Vec<Family<'_>>, verbose: u8) {
let max_len = if verbose > 0 {
0
} else {
families
.iter()
.map(|f| f.default_name_width)
.max()
.unwrap_or_default()
};
families.into_iter().for_each(|family| {
if verbose > 0 {
println!("{}", family.name);
for face in family.faces {
print!("\t{}", face.name);
if verbose > 1 {
print!("\t{}:{}", face.path.to_string_lossy(), face.index)
}
println!()
}
} else {
println!(
"{:<family_name_length$} with {} style{}",
family.name,
family.styles_count(),
if family.styles_count() > 1 { "s" } else { "" },
family_name_length = max_len,
);
}
});
}