use serde::{Deserialize, Serialize};
use crate::color_util::Lightness;
use crate::neofetch_util::ColorAlignment;
use crate::types::{AnsiMode, Backend, TerminalTheme};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Config {
pub preset: String,
pub mode: AnsiMode,
pub auto_detect_light_dark: Option<bool>,
pub light_dark: Option<TerminalTheme>,
pub lightness: Option<Lightness>,
pub color_align: ColorAlignment,
pub backend: Backend,
#[serde(default)]
#[serde(with = "self::args_serde")]
pub args: Option<Vec<String>>,
pub distro: Option<String>,
pub pride_month_disable: bool,
pub custom_ascii_path: Option<String>,
}
impl Config {
pub fn default_lightness(theme: TerminalTheme) -> Lightness {
match theme {
TerminalTheme::Dark => {
Lightness::new(0.65).expect("default lightness should not be invalid")
},
TerminalTheme::Light => {
Lightness::new(0.4).expect("default lightness should not be invalid")
},
}
}
}
mod args_serde {
use std::fmt;
use serde::de::{self, value, Deserialize, Deserializer, SeqAccess, Visitor};
use serde::ser::Serializer;
type Value = Option<Vec<String>>;
pub(super) fn serialize<S>(value: &Value, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match value {
Some(value) => serializer.serialize_some(&shell_words::join(value)),
None => serializer.serialize_none(),
}
}
pub(super) fn deserialize<'de, D>(deserializer: D) -> Result<Value, D::Error>
where
D: Deserializer<'de>,
{
struct StringOrVec;
struct OptionVisitor;
impl<'de> Visitor<'de> for StringOrVec {
type Value = Vec<String>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("string or list of strings")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
shell_words::split(s).map_err(de::Error::custom)
}
fn visit_seq<S>(self, seq: S) -> Result<Self::Value, S::Error>
where
S: SeqAccess<'de>,
{
Deserialize::deserialize(value::SeqAccessDeserializer::new(seq))
}
}
impl<'de> Visitor<'de> for OptionVisitor {
type Value = Value;
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)
}
}