Add more scaffolding
This commit is contained in:
parent
475b10ba07
commit
59213687fb
6 changed files with 119 additions and 28 deletions
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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)),
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue