Merge pull request #14 from teohhanhui/riir

Add more scaffolding
This commit is contained in:
Teoh Han Hui 2024-07-03 23:57:18 +08:00 committed by GitHub
commit ff46c8f4ca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 119 additions and 28 deletions

View file

@ -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(())
}

View file

@ -19,7 +19,7 @@ pub struct Options {
pub preset: Option<Preset>,
pub mode: Option<AnsiMode>,
pub backend: Option<Backend>,
pub args: Vec<String>,
pub args: Option<Vec<String>>,
pub scale: Option<f32>,
pub lightness: Option<Lightness>,
pub overlay: bool,
@ -107,7 +107,7 @@ BACKEND={{{}}}",
.help("Additional arguments pass-through to backend")
.argument::<String>("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")

View file

@ -13,8 +13,9 @@ pub struct Config {
lightness: Option<Lightness>,
pub color_align: ColorAlignment,
pub backend: Backend,
#[serde(default)]
#[serde(with = "self::args_serde_with")]
pub args: Vec<String>,
pub args: Option<Vec<String>>,
pub distro: Option<String>,
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<S>(value: &Vec<String>, serializer: S) -> Result<S::Ok, S::Error>
pub(super) fn serialize<S>(
value: &Option<Vec<String>>,
serializer: S,
) -> Result<S::Ok, S::Error>
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<Vec<String>, D::Error>
pub(super) fn deserialize<'de, D>(deserializer: D) -> Result<Option<Vec<String>>, D::Error>
where
D: Deserializer<'de>,
{
struct StringOrVec;
struct OptionVisitor;
impl<'de> Visitor<'de> for StringOrVec {
type Value = Vec<String>;
@ -59,13 +68,6 @@ mod args_serde_with {
formatter.write_str("string or list of strings")
}
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(vec![])
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
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<Vec<String>>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("option")
}
#[inline]
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(None)
}
#[inline]
fn visit_none<E>(self) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(None)
}
#[inline]
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(StringOrVec).map(Some)
}
}
deserializer.deserialize_option(OptionVisitor)
}
}

View file

@ -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<Regex> = 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<PathBuf> {
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<String>>) -> Result<()> {
todo!()
}
/// Gets distro ascii width and height, ignoring color code.
pub fn ascii_size<S>(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())

View file

@ -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)),

View file

@ -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 {