[PR] #370 from teohhanhui/rust-catchup
Port missed changes from the Python version
This commit is contained in:
commit
7a42824883
9 changed files with 301 additions and 154 deletions
|
|
@ -29,6 +29,7 @@ use hyfetch::presets::{AssignLightness, Preset};
|
|||
use hyfetch::pride_month;
|
||||
use hyfetch::types::{AnsiMode, Backend, TerminalTheme};
|
||||
use hyfetch::utils::{get_cache_path, input};
|
||||
use hyfetch::font_logo::get_font_logo;
|
||||
use indexmap::{IndexMap, IndexSet};
|
||||
use itertools::Itertools as _;
|
||||
use palette::{LinSrgb, Srgb};
|
||||
|
|
@ -79,6 +80,12 @@ fn main() -> Result<()> {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
if options.print_font_logo {
|
||||
let logo = get_font_logo(backend).context("failed to get font logo")?;
|
||||
writeln!(io::stdout(), "{}", logo).context("failed to write logo to stdout")?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let config = if options.config {
|
||||
create_config(&options.config_file, distro, backend, debug_mode)
|
||||
.context("failed to create config")?
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use std::iter;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr as _;
|
||||
|
||||
|
|
@ -6,7 +7,8 @@ use anyhow::Context as _;
|
|||
use bpaf::ShellComp;
|
||||
use bpaf::{construct, long, OptionParser, Parser as _};
|
||||
use directories::BaseDirs;
|
||||
use strum::VariantNames as _;
|
||||
use itertools::Itertools as _;
|
||||
use strum::{VariantArray, VariantNames};
|
||||
|
||||
use crate::color_util::{color, Lightness};
|
||||
use crate::presets::Preset;
|
||||
|
|
@ -26,6 +28,7 @@ pub struct Options {
|
|||
pub debug: bool,
|
||||
pub distro: Option<String>,
|
||||
pub ascii_file: Option<PathBuf>,
|
||||
pub print_font_logo: bool,
|
||||
pub test_print: bool,
|
||||
pub ask_exit: bool,
|
||||
}
|
||||
|
|
@ -53,19 +56,36 @@ pub fn options() -> OptionParser<Options> {
|
|||
.help(&*format!(
|
||||
"Use preset
|
||||
PRESET={{{presets}}}",
|
||||
presets = Preset::VARIANTS.join(",")
|
||||
presets = <Preset as VariantNames>::VARIANTS
|
||||
.iter()
|
||||
.chain(iter::once(&"random"))
|
||||
.join(",")
|
||||
))
|
||||
.argument::<String>("PRESET");
|
||||
#[cfg(feature = "autocomplete")]
|
||||
let preset = preset.complete(complete_preset);
|
||||
let preset = preset
|
||||
.parse(|s| {
|
||||
Preset::from_str(&s).with_context(|| {
|
||||
format!(
|
||||
"PRESET should be one of {{{presets}}}",
|
||||
presets = Preset::VARIANTS.join(",")
|
||||
)
|
||||
})
|
||||
Preset::from_str(&s)
|
||||
.or_else(|e| {
|
||||
if s == "random" {
|
||||
let mut rng = fastrand::Rng::new();
|
||||
Ok(*rng
|
||||
.choice(<Preset as VariantArray>::VARIANTS)
|
||||
.expect("preset iterator should not be empty"))
|
||||
} else {
|
||||
Err(e)
|
||||
}
|
||||
})
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"PRESET should be one of {{{presets}}}",
|
||||
presets = <Preset as VariantNames>::VARIANTS
|
||||
.iter()
|
||||
.chain(iter::once(&"random"))
|
||||
.join(",")
|
||||
)
|
||||
})
|
||||
})
|
||||
.optional();
|
||||
let mode = long("mode")
|
||||
|
|
@ -138,6 +158,10 @@ BACKEND={{{backends}}}",
|
|||
#[cfg(feature = "autocomplete")]
|
||||
let ascii_file = ascii_file.complete_shell(ShellComp::Nothing);
|
||||
let ascii_file = ascii_file.optional();
|
||||
let print_font_logo = long("print-font-logo")
|
||||
.help("Print the Font Logo / Nerd Font icon of your distro and exit")
|
||||
.switch();
|
||||
// hidden
|
||||
let test_print = long("test-print")
|
||||
.help("Print the ascii distro and exit")
|
||||
.switch()
|
||||
|
|
@ -160,6 +184,7 @@ BACKEND={{{backends}}}",
|
|||
debug,
|
||||
distro,
|
||||
ascii_file,
|
||||
print_font_logo,
|
||||
// hidden
|
||||
test_print,
|
||||
ask_exit,
|
||||
|
|
@ -177,8 +202,9 @@ BACKEND={{{backends}}}",
|
|||
|
||||
#[cfg(feature = "autocomplete")]
|
||||
fn complete_preset(input: &String) -> Vec<(String, Option<String>)> {
|
||||
Preset::VARIANTS
|
||||
<Preset as VariantNames>::VARIANTS
|
||||
.iter()
|
||||
.chain(iter::once(&"random"))
|
||||
.filter_map(|&name| {
|
||||
if name.starts_with(input) {
|
||||
Some((name.to_owned(), None))
|
||||
|
|
|
|||
47
crates/hyfetch/src/font_logo.rs
Normal file
47
crates/hyfetch/src/font_logo.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
use crate::neofetch_util::get_distro_name;
|
||||
use crate::types::Backend;
|
||||
use crate::utils::get_cache_path;
|
||||
use anyhow::{Context, Result};
|
||||
use std::collections::HashMap;
|
||||
use std::fs::{self, File};
|
||||
use std::io::{Read, Write};
|
||||
|
||||
const FONT_LOGOS: &str = r#"{"Alma":"","Alpine":"","AOSC OS":"","Apple":"","Archcraft":"","ArchLabs":"","Arch":"","Arco":"","Arduino":"","Artix":"","Awesome WM":"","Big":"","bspwm":"","Budgie":"","CentOS":"","Cinnamon":"","Codeberg":"","CoreOS":"","Crystal":"","Debian":"","Deepin":"","Devuan":"","Docker":"","dwm":"","elementary OS":"","Endeavour OS":"","Enlightenment":"","F-droid":"","Fedora":"","Fedora (inverse)":"","Ferris":"","Flathub":"","Fluxbox":"","Forgejo":"","FOSDEM":"","FreeBSD":"","FreeCAD":"","freedesktop.org":"","Garuda":"","Gentoo":"","GIMP":"","Gitea":"","GNOME":"","GNU Guix":"","GTK":"","Hyperbola -libre":"","Hyprland":"","i3":"","illumos":"","Inkscape":"","JWM":"","Kali":"","KDE":"","KDE Neon":"","KDE Plasma":"","Kdenlive":"","KiCad":"","Krita":"","Kubuntu":"","Kubuntu (inverse)":"","Mint":"","Mint (inverse)":"","Loc-OS":"","LXDE":"","LXLE":"","LXQt":"","Mageia":"","Mandriva":"","Manjaro":"","MATE":"","mpv":"","MX":"","Neovim":"","NixOS":"","Octoprint":"","OpenBSD":"","OpenSCAD":"","OpenSUSE":"","OSH":"","OSHWA":"","OSI":"","Parabola -libre":"","Parrot OS":"","Pop!_OS":"","PostmarketOS":"","Prusa Slicer":"","Puppy":"","Qt":"","Qtile":"","QubesOS":"","Raspberry pi":"","Red Hat":"","RepRap":"","RISC-V":"","Rocky":"","Sabayon":"","Slackware":"","Slackware (inverse)":"","Snappy":"","Solus":"","Sway":"","Tails":"","Thunderbird":"","Tor Browser":"","Trisquel":"","Tux":"","Ubuntu":"","Ubuntu (inverse)":"","Vanilla OS":"","Void":"","VS Codium":"","Wayland":"","Wikimedia":"","Xero":"","XFCE":"","Xmonad":"","Xorg":"","Zorin OS":"","Windows":""}"#;
|
||||
|
||||
pub fn get_font_logo(backend: Backend) -> Result<String> {
|
||||
// Check if the cache file exists and return its contents if it does
|
||||
let cache_path = get_cache_path().context("Failed to get cache path")?.join("font_logo");
|
||||
if cache_path.exists() {
|
||||
let mut cached_logo = String::new();
|
||||
File::open(cache_path).context("Failed to open cache file")?
|
||||
.read_to_string(&mut cached_logo).context("Failed to read from cache file")?;
|
||||
return Ok(cached_logo);
|
||||
}
|
||||
|
||||
// Deserialize the JSON into a HashMap
|
||||
let font_logos: HashMap<String, String> = serde_json::from_str::<HashMap<String, String>>(FONT_LOGOS)
|
||||
.context("Failed to deserialize font logos JSON file")?
|
||||
.into_iter().map(|(k, v)| (k.to_lowercase(), v)).collect();
|
||||
|
||||
// Get the distro name
|
||||
let distro = get_distro_name(backend).context("Failed to get distro name")?.to_lowercase();
|
||||
|
||||
// Find the most likely matching distro from font_logos
|
||||
let matched_distro = font_logos.keys().find(|&k| distro.contains(k))
|
||||
.or_else(|| font_logos.keys().find(|k| k.contains(&distro)))
|
||||
.or_else(|| font_logos.keys().find(|k| k.split_whitespace().any(|part| distro.contains(part))))
|
||||
.ok_or_else(|| anyhow::anyhow!("No font logo found for distro: {distro}. The supported logos are in https://github.com/Lukas-W/font-logos"))?;
|
||||
|
||||
let logo = font_logos.get(matched_distro).unwrap();
|
||||
|
||||
// Create parent directories for the cache if they don't exist
|
||||
if let Some(parent) = cache_path.parent() {
|
||||
fs::create_dir_all(parent).context("Failed to create cache directory")?;
|
||||
}
|
||||
|
||||
// Write the logo to the cache file
|
||||
let mut cache_file = File::create(cache_path).context("Failed to create cache file")?;
|
||||
cache_file.write_all(logo.as_bytes()).context("Failed to write logo to cache file")?;
|
||||
|
||||
Ok(logo.clone())
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ pub mod ascii;
|
|||
pub mod cli_options;
|
||||
pub mod color_util;
|
||||
pub mod distros;
|
||||
pub mod font_logo;
|
||||
pub mod models;
|
||||
pub mod neofetch_util;
|
||||
pub mod presets;
|
||||
|
|
|
|||
|
|
@ -595,7 +595,7 @@ where
|
|||
}
|
||||
|
||||
#[tracing::instrument(level = "debug")]
|
||||
fn get_distro_name(backend: Backend) -> Result<String> {
|
||||
pub(crate) fn get_distro_name(backend: Backend) -> Result<String> {
|
||||
match backend {
|
||||
Backend::Neofetch => run_neofetch_command_piped(&["ascii_distro_name"])
|
||||
.context("failed to get distro name from neofetch"),
|
||||
|
|
|
|||
|
|
@ -119,6 +119,11 @@ pub enum Preset {
|
|||
|
||||
Pangender,
|
||||
|
||||
/// High-contrast version of pangender flag
|
||||
#[serde(rename = "pangender.contrast")]
|
||||
#[strum(serialize = "pangender.contrast")]
|
||||
PangenderContrast,
|
||||
|
||||
#[serde(rename = "gendernonconforming1")]
|
||||
#[strum(serialize = "gendernonconforming1")]
|
||||
GenderNonconforming1,
|
||||
|
|
@ -143,10 +148,23 @@ pub enum Preset {
|
|||
|
||||
NonhumanUnity,
|
||||
|
||||
/// For all the dogs
|
||||
Caninekin,
|
||||
|
||||
Plural,
|
||||
|
||||
Fraysexual,
|
||||
|
||||
Bear,
|
||||
|
||||
Butch,
|
||||
|
||||
Leather,
|
||||
|
||||
Otter,
|
||||
|
||||
Twink,
|
||||
|
||||
Kenochoric,
|
||||
|
||||
Veldian,
|
||||
|
|
@ -192,6 +210,8 @@ pub enum Preset {
|
|||
Burger,
|
||||
|
||||
/// Meme flag
|
||||
#[serde(rename = "throatlozenges")]
|
||||
#[strum(serialize = "throatlozenges")]
|
||||
ThroatLozenges,
|
||||
|
||||
/// Colors from Gilbert Baker's original 1978 flag design
|
||||
|
|
@ -427,6 +447,11 @@ impl Preset {
|
|||
"#FFF798", "#FEDDCD", "#FFEBFB", "#FFFFFF", "#FFEBFB", "#FEDDCD", "#FFF798",
|
||||
]),
|
||||
|
||||
// high-contrast version of pangender flag
|
||||
Self::PangenderContrast => ColorProfile::from_hex_colors(vec![
|
||||
"#ffe87f", "#fcbaa6", "#fbc9f3", "#FFFFFF", "#fbc9f3", "#fcbaa6", "#ffe87f",
|
||||
]),
|
||||
|
||||
Self::GenderNonconforming1 => ColorProfile::from_hex_colors(vec![
|
||||
"#50284d", "#96467b", "#5c96f7", "#ffe6f7", "#5c96f7", "#96467b", "#50284d",
|
||||
])
|
||||
|
|
@ -474,6 +499,11 @@ impl Preset {
|
|||
ColorProfile::from_hex_colors(vec!["#177B49", "#FFFFFF", "#593C90"])
|
||||
},
|
||||
|
||||
// used https://www.tumblr.com/zombpawcoins/745062851267493888/caninekin-canine-therian-flag
|
||||
Self::Caninekin => ColorProfile::from_hex_colors(vec![
|
||||
"#2d2822", "#543d25", "#9c754d", "#e8dac2", "#cfad8c", "#b77b55", "#954e31",
|
||||
]),
|
||||
|
||||
// used https://pluralpedia.org/w/Plurality#/media/File:Plural-Flag-1.jpg as source and colorpicked
|
||||
Self::Plural => ColorProfile::from_hex_colors(vec![
|
||||
"#2D0625", "#543475", "#7675C3", "#89C7B0", "#F3EDBD",
|
||||
|
|
@ -484,6 +514,30 @@ impl Preset {
|
|||
ColorProfile::from_hex_colors(vec!["#226CB5", "#94E7DD", "#FFFFFF", "#636363"])
|
||||
},
|
||||
|
||||
// sourced from https://commons.wikimedia.org/wiki/File:Bear_Brotherhood_flag.svg
|
||||
Self::Bear => ColorProfile::from_hex_colors(vec![
|
||||
"#623804", "#D56300", "#FEDD63", "#FEE6B8", "#FFFFFF", "#555555",
|
||||
]),
|
||||
|
||||
// colorpicked from https://commons.wikimedia.org/wiki/File:Butch_Flag.png
|
||||
Self::Butch => ColorProfile::from_hex_colors(vec![
|
||||
"#D72800", "#F17623", "#FF9C56", "#FFFDF6", "#FFCE89", "#FEAF02", "#A37000",
|
||||
]),
|
||||
|
||||
// colorpicked from https://commons.wikimedia.org/wiki/File:Leather,_Latex,_and_BDSM_pride_-_Light.svg
|
||||
Self::Leather => ColorProfile::from_hex_colors(vec![
|
||||
"#000000", "#252580", "#000000", "#252580", "#FFFFFF", "#252580", "#000000",
|
||||
"#252580", "#000000",
|
||||
]),
|
||||
|
||||
// colorpicked from https://commons.wikimedia.org/wiki/File:Official_Otter_Pride_Flag_by_Bearbackgear.jpg
|
||||
Self::Otter => ColorProfile::from_hex_colors(vec![
|
||||
"#263881", "#5C9DC9", "#FFFFFF", "#3A291D", "#5C9DC9", "#263881",
|
||||
]),
|
||||
|
||||
// colorpicked from https://commons.wikimedia.org/wiki/File:Twink_Pride_Flag_(proposed).svg
|
||||
Self::Twink => ColorProfile::from_hex_colors(vec!["#FFB2FF", "#FFFFFF", "#FFFF81"]),
|
||||
|
||||
Self::Kenochoric => {
|
||||
ColorProfile::from_hex_colors(vec!["#000000", "#2E1569", "#824DB7", "#C7A1D6"])
|
||||
},
|
||||
|
|
@ -570,7 +624,7 @@ impl Preset {
|
|||
]),
|
||||
|
||||
Self::ThroatLozenges => ColorProfile::from_hex_colors(vec![
|
||||
"#2759DA", "#03940D", "#F5F100", "#F59B00", "#B71212"
|
||||
"#2759DA", "#03940D", "#F5F100", "#F59B00", "#B71212",
|
||||
]),
|
||||
|
||||
// used https://gilbertbaker.com/rainbow-flag-color-meanings/ as source and colorpicked
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ pub(crate) mod index_map_serde {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'de, K> Visitor<'de> for KeySeed<K>
|
||||
impl<K> Visitor<'_> for KeySeed<K>
|
||||
where
|
||||
K: FromStr,
|
||||
K::Err: fmt::Display,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue