From 59213687fb04e5ac740f78ee7600f94521553223 Mon Sep 17 00:00:00 2001 From: Teoh Han Hui Date: Wed, 3 Jul 2024 23:53:25 +0800 Subject: [PATCH] Add more scaffolding --- crates/hyfetch/src/bin/hyfetch.rs | 36 +++++++++++++++--- crates/hyfetch/src/cli_options.rs | 4 +- crates/hyfetch/src/models.rs | 58 +++++++++++++++++++++++------ crates/hyfetch/src/neofetch_util.rs | 28 +++++++++++--- crates/hyfetch/src/presets.rs | 11 +++++- crates/hyfetch/src/types.rs | 10 +++-- 6 files changed, 119 insertions(+), 28 deletions(-) diff --git a/crates/hyfetch/src/bin/hyfetch.rs b/crates/hyfetch/src/bin/hyfetch.rs index 2b1f8817..8bbf69d7 100644 --- a/crates/hyfetch/src/bin/hyfetch.rs +++ b/crates/hyfetch/src/bin/hyfetch.rs @@ -7,7 +7,7 @@ use anyhow::{Context, Result}; use chrono::Datelike; use hyfetch::cli_options::options; use hyfetch::models::Config; -use hyfetch::neofetch_util::get_distro_ascii; +use hyfetch::neofetch_util::{self, get_distro_ascii}; use hyfetch::presets::AssignLightness; use hyfetch::utils::get_cache_path; use tracing::debug; @@ -21,10 +21,15 @@ fn main() -> Result<()> { // TODO + // Use a custom distro + let distro = options.distro.as_ref(); + + // TODO + if options.test_print { println!( "{}", - get_distro_ascii(options.distro.as_ref()).context("failed to get distro ascii")? + get_distro_ascii(distro).context("failed to get distro ascii")? ); return Ok(()); } @@ -63,7 +68,12 @@ fn main() -> Result<()> { } } - // TODO + // Use a custom distro + let distro = options.distro.as_ref().or(config.distro.as_ref()); + + let color_mode = options.mode.unwrap_or(config.mode); + let backend = options.backend.unwrap_or(config.backend); + let args = options.args.as_ref().or(config.args.as_ref()); // Get preset let preset = options.preset.unwrap_or(config.preset); @@ -76,11 +86,27 @@ fn main() -> Result<()> { } else if let Some(lightness) = options.lightness { color_profile.with_lightness(AssignLightness::Replace(lightness)) } else { - color_profile.with_lightness_dl(config.lightness(), config.light_dark) + color_profile.with_lightness_dl(config.lightness(), config.light_dark, options.overlay) }; debug!(?color_profile, "lightened color profile"); - // TODO + let asc = if let Some(path) = options.ascii_file { + fs::read_to_string(&path).with_context(|| format!("failed to read ascii from {path:?}"))? + } else { + get_distro_ascii(distro).context("failed to get distro ascii")? + }; + let asc = config + .color_align + .recolor_ascii(asc, color_profile, color_mode, config.light_dark); + neofetch_util::run(asc, backend, args).context("failed to run")?; + + if options.ask_exit { + print!("Press any key to exit..."); + let mut buf = String::new(); + io::stdin() + .read_line(&mut buf) + .context("failed to read line from input")?; + } Ok(()) } diff --git a/crates/hyfetch/src/cli_options.rs b/crates/hyfetch/src/cli_options.rs index 84be8b82..bdeed573 100644 --- a/crates/hyfetch/src/cli_options.rs +++ b/crates/hyfetch/src/cli_options.rs @@ -19,7 +19,7 @@ pub struct Options { pub preset: Option, pub mode: Option, pub backend: Option, - pub args: Vec, + pub args: Option>, pub scale: Option, pub lightness: Option, pub overlay: bool, @@ -107,7 +107,7 @@ BACKEND={{{}}}", .help("Additional arguments pass-through to backend") .argument::("ARGS") .parse(|s| shell_words::split(&s).context("ARGS should be valid command-line arguments")) - .fallback(vec![]); + .optional(); let scale = long("c-scale") .help("Lighten colors by a multiplier") .argument("SCALE") diff --git a/crates/hyfetch/src/models.rs b/crates/hyfetch/src/models.rs index 58a749aa..6fd745b8 100644 --- a/crates/hyfetch/src/models.rs +++ b/crates/hyfetch/src/models.rs @@ -13,8 +13,9 @@ pub struct Config { lightness: Option, pub color_align: ColorAlignment, pub backend: Backend, + #[serde(default)] #[serde(with = "self::args_serde_with")] - pub args: Vec, + pub args: Option>, pub distro: Option, pub pride_month_disable: bool, } @@ -39,19 +40,27 @@ mod args_serde_with { use serde::de::{self, value, Deserialize, Deserializer, SeqAccess, Visitor}; use serde::ser::Serializer; - pub(super) fn serialize(value: &Vec, serializer: S) -> Result + pub(super) fn serialize( + value: &Option>, + serializer: S, + ) -> Result where S: Serializer, { - serializer.serialize_str(&shell_words::join(value)) + match value { + Some(value) => serializer.serialize_some(&shell_words::join(value)), + None => serializer.serialize_none(), + } } - pub(super) fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + pub(super) fn deserialize<'de, D>(deserializer: D) -> Result>, D::Error> where D: Deserializer<'de>, { struct StringOrVec; + struct OptionVisitor; + impl<'de> Visitor<'de> for StringOrVec { type Value = Vec; @@ -59,13 +68,6 @@ mod args_serde_with { formatter.write_str("string or list of strings") } - fn visit_unit(self) -> Result - where - E: de::Error, - { - Ok(vec![]) - } - fn visit_str(self, s: &str) -> Result where E: de::Error, @@ -81,6 +83,38 @@ mod args_serde_with { } } - deserializer.deserialize_any(StringOrVec) + impl<'de> Visitor<'de> for OptionVisitor { + type Value = Option>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("option") + } + + #[inline] + fn visit_unit(self) -> Result + where + E: de::Error, + { + Ok(None) + } + + #[inline] + fn visit_none(self) -> Result + where + E: de::Error, + { + Ok(None) + } + + #[inline] + fn visit_some(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_any(StringOrVec).map(Some) + } + } + + deserializer.deserialize_option(OptionVisitor) } } diff --git a/crates/hyfetch/src/neofetch_util.rs b/crates/hyfetch/src/neofetch_util.rs index c9be757a..979d2888 100644 --- a/crates/hyfetch/src/neofetch_util.rs +++ b/crates/hyfetch/src/neofetch_util.rs @@ -15,12 +15,15 @@ use tracing::debug; use crate::color_util::{NeofetchAsciiIndexedColor, PresetIndexedColor}; use crate::distros::Distro; +use crate::presets::ColorProfile; +use crate::types::{AnsiMode, Backend, LightDark}; -const NEOFETCH_COLOR_PATTERN: &str = r"\$\{c[0-9]\}"; +const NEOFETCH_COLOR_PATTERN: &str = r"\$\{c[0-6]\}"; static NEOFETCH_COLOR_RE: OnceLock = OnceLock::new(); #[derive(Clone, Eq, PartialEq, Debug, Deserialize, Serialize)] -#[serde(rename_all = "lowercase", tag = "mode")] +#[serde(tag = "mode")] +#[serde(rename_all = "lowercase")] pub enum ColorAlignment { Horizontal { fore_back: Option<(NeofetchAsciiIndexedColor, NeofetchAsciiIndexedColor)>, @@ -34,6 +37,19 @@ pub enum ColorAlignment { }, } +impl ColorAlignment { + /// Uses the color alignment to recolor an ascii art. + pub fn recolor_ascii( + &self, + asc: String, + color_profile: ColorProfile, + color_mode: AnsiMode, + term: LightDark, + ) -> String { + todo!() + } +} + /// Gets the absolute path of the neofetch command. pub fn get_command_path() -> Result { if let Ok(workspace_dir) = env::var("CARGO_WORKSPACE_DIR") { @@ -93,6 +109,10 @@ where todo!() } +pub fn run(asc: String, backend: Backend, args: Option<&Vec>) -> Result<()> { + todo!() +} + /// Gets distro ascii width and height, ignoring color code. pub fn ascii_size(asc: S) -> (u8, u8) where @@ -101,9 +121,7 @@ where let asc = asc.as_ref(); let Some(width) = NEOFETCH_COLOR_RE - .get_or_init(|| { - Regex::new(NEOFETCH_COLOR_PATTERN).expect("neofetch color regex should not be invalid") - }) + .get_or_init(|| Regex::new(NEOFETCH_COLOR_PATTERN).unwrap()) .replace_all(asc, "") .split('\n') .map(|line| line.len()) diff --git a/crates/hyfetch/src/presets.rs b/crates/hyfetch/src/presets.rs index a1f710d1..190b79bb 100644 --- a/crates/hyfetch/src/presets.rs +++ b/crates/hyfetch/src/presets.rs @@ -484,7 +484,16 @@ impl ColorProfile { /// Creates a new color profile, with the colors set to the specified HSL /// lightness value, with respect to dark/light terminals. - pub fn with_lightness_dl(&self, lightness: Lightness, term: LightDark) -> Self { + pub fn with_lightness_dl( + &self, + lightness: Lightness, + term: LightDark, + use_overlay: bool, + ) -> Self { + if use_overlay { + todo!() + } + match term { LightDark::Dark => self.with_lightness(AssignLightness::ClampMin(lightness)), LightDark::Light => self.with_lightness(AssignLightness::ClampMax(lightness)), diff --git a/crates/hyfetch/src/types.rs b/crates/hyfetch/src/types.rs index 49a40b73..7143d05f 100644 --- a/crates/hyfetch/src/types.rs +++ b/crates/hyfetch/src/types.rs @@ -1,7 +1,9 @@ use serde::{Deserialize, Serialize}; use strum::{EnumString, VariantNames}; -#[derive(Clone, Eq, PartialEq, Hash, Debug, Deserialize, EnumString, Serialize, VariantNames)] +#[derive( + Copy, Clone, Eq, PartialEq, Hash, Debug, Deserialize, EnumString, Serialize, VariantNames, +)] #[serde(rename_all = "lowercase")] #[strum(serialize_all = "lowercase")] pub enum AnsiMode { @@ -11,14 +13,16 @@ pub enum AnsiMode { Rgb, } -#[derive(Clone, Eq, PartialEq, Hash, Debug, Deserialize, Serialize)] +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] pub enum LightDark { Light, Dark, } -#[derive(Clone, Eq, PartialEq, Hash, Debug, Deserialize, EnumString, Serialize, VariantNames)] +#[derive( + Copy, Clone, Eq, PartialEq, Hash, Debug, Deserialize, EnumString, Serialize, VariantNames, +)] #[serde(rename_all = "kebab-case")] #[strum(serialize_all = "kebab-case")] pub enum Backend {