Use selected backend to get distro name
This commit is contained in:
parent
d79196a7fc
commit
d11f6f0a9f
6 changed files with 154 additions and 83 deletions
|
@ -12,7 +12,7 @@ use hyfetch::models::Config;
|
|||
use hyfetch::neofetch_util::ensure_git_bash;
|
||||
use hyfetch::neofetch_util::{self, ascii_size, get_distro_ascii, literal_input, ColorAlignment};
|
||||
use hyfetch::presets::{AssignLightness, ColorProfile, Preset};
|
||||
use hyfetch::types::{AnsiMode, LightDark};
|
||||
use hyfetch::types::{AnsiMode, Backend, TerminalTheme};
|
||||
use hyfetch::utils::get_cache_path;
|
||||
use palette::Srgb;
|
||||
use strum::{EnumCount, VariantArray, VariantNames};
|
||||
|
@ -28,34 +28,54 @@ fn main() -> Result<()> {
|
|||
|
||||
let options = options().run();
|
||||
|
||||
init_tracing_subsriber(options.debug).context("failed to init tracing subscriber")?;
|
||||
let debug_mode = options.debug;
|
||||
|
||||
init_tracing_subsriber(debug_mode).context("failed to init tracing subscriber")?;
|
||||
|
||||
debug!(?options, "CLI options");
|
||||
|
||||
// Use a custom distro
|
||||
let distro = options.distro.as_ref();
|
||||
|
||||
let backend = options.backend.unwrap_or(Backend::Neofetch);
|
||||
let use_overlay = options.overlay;
|
||||
|
||||
#[cfg(windows)]
|
||||
ensure_git_bash().context("failed to find git bash")?;
|
||||
|
||||
if options.test_print {
|
||||
let (asc, _) = get_distro_ascii(distro).context("failed to get distro ascii")?;
|
||||
let (asc, _) = get_distro_ascii(distro, backend).context("failed to get distro ascii")?;
|
||||
println!("{asc}");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let config = if options.config {
|
||||
create_config(distro, &options.config_file, options.overlay, options.debug)
|
||||
create_config(
|
||||
&options.config_file,
|
||||
distro,
|
||||
backend,
|
||||
use_overlay,
|
||||
debug_mode,
|
||||
)
|
||||
.context("failed to create config")?
|
||||
} else if let Some(config) =
|
||||
read_config(&options.config_file).context("failed to read config")?
|
||||
{
|
||||
config
|
||||
} else {
|
||||
create_config(distro, &options.config_file, options.overlay, options.debug)
|
||||
create_config(
|
||||
&options.config_file,
|
||||
distro,
|
||||
backend,
|
||||
use_overlay,
|
||||
debug_mode,
|
||||
)
|
||||
.context("failed to create config")?
|
||||
};
|
||||
|
||||
let color_mode = options.mode.unwrap_or(config.mode);
|
||||
let theme = config.light_dark;
|
||||
|
||||
// Check if it's June (pride month)
|
||||
let now =
|
||||
OffsetDateTime::now_local().context("failed to get current datetime in local timezone")?;
|
||||
|
@ -83,7 +103,6 @@ fn main() -> Result<()> {
|
|||
// 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());
|
||||
|
||||
|
@ -98,7 +117,7 @@ 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, options.overlay)
|
||||
color_profile.with_lightness_adaptive(config.lightness(), theme, use_overlay)
|
||||
};
|
||||
debug!(?color_profile, "lightened color profile");
|
||||
|
||||
|
@ -109,7 +128,7 @@ fn main() -> Result<()> {
|
|||
None,
|
||||
)
|
||||
} else {
|
||||
get_distro_ascii(distro).context("failed to get distro ascii")?
|
||||
get_distro_ascii(distro, backend).context("failed to get distro ascii")?
|
||||
};
|
||||
let color_align = if fore_back.is_some() {
|
||||
match config.color_align {
|
||||
|
@ -124,7 +143,7 @@ fn main() -> Result<()> {
|
|||
config.color_align
|
||||
};
|
||||
let asc = color_align
|
||||
.recolor_ascii(asc, color_profile, color_mode, config.light_dark)
|
||||
.recolor_ascii(asc, color_profile, color_mode, theme)
|
||||
.context("failed to recolor ascii")?;
|
||||
neofetch_util::run(asc, backend, args)?;
|
||||
|
||||
|
@ -174,8 +193,9 @@ fn read_config(path: &Path) -> Result<Option<Config>> {
|
|||
/// The config is automatically stored to file.
|
||||
#[tracing::instrument(level = "debug")]
|
||||
fn create_config(
|
||||
distro: Option<&String>,
|
||||
path: &Path,
|
||||
distro: Option<&String>,
|
||||
backend: Backend,
|
||||
use_overlay: bool,
|
||||
debug_mode: bool,
|
||||
) -> Result<Config> {
|
||||
|
@ -202,14 +222,15 @@ fn create_config(
|
|||
});
|
||||
debug!(?det_ansi, "detected color mode");
|
||||
|
||||
let (asc, fore_back) = get_distro_ascii(distro).context("failed to get distro ascii")?;
|
||||
let (asc, fore_back) =
|
||||
get_distro_ascii(distro, backend).context("failed to get distro ascii")?;
|
||||
let (asc_width, asc_lines) = ascii_size(asc);
|
||||
let theme = det_bg.map(|bg| bg.theme()).unwrap_or(LightDark::Light);
|
||||
let theme = det_bg.map(|bg| bg.theme()).unwrap_or(TerminalTheme::Light);
|
||||
let color_mode = det_ansi.unwrap_or(AnsiMode::Ansi256);
|
||||
let logo = color(
|
||||
match theme {
|
||||
LightDark::Light => "&l&bhyfetch&~&L",
|
||||
LightDark::Dark => "&l&bhy&ffetch&~&L",
|
||||
TerminalTheme::Light => "&l&bhyfetch&~&L",
|
||||
TerminalTheme::Dark => "&l&bhy&ffetch&~&L",
|
||||
},
|
||||
color_mode,
|
||||
)
|
||||
|
@ -280,9 +301,9 @@ fn create_config(
|
|||
};
|
||||
|
||||
//////////////////////////////
|
||||
// 2. Select light/dark mode
|
||||
// 2. Select theme (light/dark mode)
|
||||
|
||||
let select_light_dark = || -> Result<(LightDark, &str)> {
|
||||
let select_theme = || -> Result<(TerminalTheme, &str)> {
|
||||
if let Some(det_bg) = det_bg {
|
||||
return Ok((det_bg.theme(), "Detected background color"));
|
||||
}
|
||||
|
@ -294,11 +315,10 @@ fn create_config(
|
|||
};
|
||||
|
||||
let theme = {
|
||||
let (light_dark, ttl) =
|
||||
select_light_dark().context("failed to select light / dark mode")?;
|
||||
debug!(?light_dark, "selected theme");
|
||||
update_title(&mut title, &mut option_counter, ttl, light_dark.into());
|
||||
light_dark
|
||||
let (selected_theme, ttl) = select_theme().context("failed to select theme")?;
|
||||
debug!(?selected_theme, "selected theme");
|
||||
update_title(&mut title, &mut option_counter, ttl, selected_theme.into());
|
||||
selected_theme
|
||||
};
|
||||
|
||||
//////////////////////////////
|
||||
|
@ -400,7 +420,7 @@ fn create_config(
|
|||
let color_profile: ColorProfile;
|
||||
let preset_rainbow = Preset::Rainbow
|
||||
.color_profile()
|
||||
.with_lightness_dl(Config::default_lightness(theme), theme, use_overlay)
|
||||
.with_lightness_adaptive(Config::default_lightness(theme), theme, use_overlay)
|
||||
.color_text(
|
||||
"preset",
|
||||
color_mode,
|
||||
|
@ -421,7 +441,7 @@ fn create_config(
|
|||
opts.push("prev");
|
||||
}
|
||||
println!("Enter 'next' to go to the next page and 'prev' to go to the previous page.");
|
||||
let preset = literal_input(
|
||||
let selection = literal_input(
|
||||
format!("Which {preset_rainbow} do you want to use? "),
|
||||
&opts[..],
|
||||
Preset::Rainbow.into(),
|
||||
|
@ -429,18 +449,19 @@ fn create_config(
|
|||
color_mode,
|
||||
)
|
||||
.context("failed to select preset")?;
|
||||
if preset == "next" {
|
||||
if selection == "next" {
|
||||
page += 1;
|
||||
} else if preset == "prev" {
|
||||
} else if selection == "prev" {
|
||||
page -= 1;
|
||||
} else {
|
||||
let preset: Preset = preset.parse().expect("selected preset should be valid");
|
||||
debug!(?preset, "selected preset");
|
||||
color_profile = preset.color_profile();
|
||||
let selected_preset: Preset =
|
||||
selection.parse().expect("selected preset should be valid");
|
||||
debug!(?selected_preset, "selected preset");
|
||||
color_profile = selected_preset.color_profile();
|
||||
{
|
||||
let preset_name: &'static str = preset.into();
|
||||
let preset_name: &'static str = selected_preset.into();
|
||||
let preset_colored_name = color_profile
|
||||
.with_lightness_dl(Config::default_lightness(theme), theme, use_overlay)
|
||||
.with_lightness_adaptive(Config::default_lightness(theme), theme, use_overlay)
|
||||
.color_text(
|
||||
preset_name,
|
||||
color_mode,
|
||||
|
|
|
@ -11,7 +11,7 @@ use palette::{IntoColorMut, LinSrgb, Okhsl, Srgb};
|
|||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::types::{AnsiMode, LightDark};
|
||||
use crate::types::{AnsiMode, TerminalTheme};
|
||||
|
||||
const MINECRAFT_COLORS: [(&str, &str); 30] = [
|
||||
// Minecraft formatting codes
|
||||
|
@ -114,7 +114,7 @@ pub trait ToAnsiString {
|
|||
}
|
||||
|
||||
pub trait Theme {
|
||||
fn theme(&self) -> LightDark;
|
||||
fn theme(&self) -> TerminalTheme;
|
||||
}
|
||||
|
||||
impl Lightness {
|
||||
|
@ -227,16 +227,16 @@ impl ToAnsiString for Srgb<u8> {
|
|||
}
|
||||
|
||||
impl Theme for Srgb<u8> {
|
||||
fn theme(&self) -> LightDark {
|
||||
fn theme(&self) -> TerminalTheme {
|
||||
let mut rgb_f32_color: LinSrgb = self.into_linear();
|
||||
|
||||
{
|
||||
let okhsl_f32_color: &mut Okhsl = &mut rgb_f32_color.into_color_mut();
|
||||
|
||||
if okhsl_f32_color.lightness > 0.5 {
|
||||
LightDark::Light
|
||||
TerminalTheme::Light
|
||||
} else {
|
||||
LightDark::Dark
|
||||
TerminalTheme::Dark
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,13 @@ use serde::{Deserialize, Serialize};
|
|||
use crate::color_util::Lightness;
|
||||
use crate::neofetch_util::ColorAlignment;
|
||||
use crate::presets::Preset;
|
||||
use crate::types::{AnsiMode, Backend, LightDark};
|
||||
use crate::types::{AnsiMode, Backend, TerminalTheme};
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct Config {
|
||||
pub preset: Preset,
|
||||
pub mode: AnsiMode,
|
||||
pub light_dark: LightDark,
|
||||
pub light_dark: TerminalTheme,
|
||||
lightness: Option<Lightness>,
|
||||
pub color_align: ColorAlignment,
|
||||
pub backend: Backend,
|
||||
|
@ -21,12 +21,12 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn default_lightness(term: LightDark) -> Lightness {
|
||||
match term {
|
||||
LightDark::Dark => {
|
||||
pub fn default_lightness(theme: TerminalTheme) -> Lightness {
|
||||
match theme {
|
||||
TerminalTheme::Dark => {
|
||||
Lightness::new(0.65).expect("default lightness should not be invalid")
|
||||
},
|
||||
LightDark::Light => {
|
||||
TerminalTheme::Light => {
|
||||
Lightness::new(0.4).expect("default lightness should not be invalid")
|
||||
},
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ use crate::color_util::{
|
|||
};
|
||||
use crate::distros::Distro;
|
||||
use crate::presets::ColorProfile;
|
||||
use crate::types::{AnsiMode, Backend, LightDark};
|
||||
use crate::types::{AnsiMode, Backend, TerminalTheme};
|
||||
use crate::utils::{find_file, find_in_path, process_command_status};
|
||||
|
||||
const NEOFETCH_COLOR_PATTERNS: [&str; 6] = ["${c1}", "${c2}", "${c3}", "${c4}", "${c5}", "${c6}"];
|
||||
|
@ -84,7 +84,7 @@ impl ColorAlignment {
|
|||
asc: String,
|
||||
color_profile: ColorProfile,
|
||||
color_mode: AnsiMode,
|
||||
term: LightDark,
|
||||
theme: TerminalTheme,
|
||||
) -> Result<String> {
|
||||
let reset = color("&~&*", color_mode).expect("color reset should not be invalid");
|
||||
|
||||
|
@ -105,9 +105,9 @@ impl ColorAlignment {
|
|||
let asc = asc.replace(
|
||||
&format!("${{c{fore}}}"),
|
||||
&color(
|
||||
match term {
|
||||
LightDark::Light => "&0",
|
||||
LightDark::Dark => "&f",
|
||||
match theme {
|
||||
TerminalTheme::Light => "&0",
|
||||
TerminalTheme::Dark => "&f",
|
||||
},
|
||||
color_mode,
|
||||
)
|
||||
|
@ -466,14 +466,17 @@ pub fn ensure_git_bash() -> Result<PathBuf> {
|
|||
/// Gets the distro ascii of the current distro. Or if distro is specified, get
|
||||
/// the specific distro's ascii art instead.
|
||||
#[tracing::instrument(level = "debug")]
|
||||
pub fn get_distro_ascii<S>(distro: Option<S>) -> Result<(String, Option<ForeBackColorPair>)>
|
||||
pub fn get_distro_ascii<S>(
|
||||
distro: Option<S>,
|
||||
backend: Backend,
|
||||
) -> Result<(String, Option<ForeBackColorPair>)>
|
||||
where
|
||||
S: AsRef<str> + fmt::Debug,
|
||||
{
|
||||
let distro: Cow<_> = if let Some(distro) = distro.as_ref() {
|
||||
distro.as_ref().into()
|
||||
} else {
|
||||
get_distro_name()
|
||||
get_distro_name(backend)
|
||||
.context("failed to get distro name")?
|
||||
.into()
|
||||
};
|
||||
|
@ -500,6 +503,7 @@ where
|
|||
Ok((normalize_ascii(asc), None))
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(asc))]
|
||||
pub fn run(asc: String, backend: Backend, args: Option<&Vec<String>>) -> Result<()> {
|
||||
match backend {
|
||||
Backend::Neofetch => {
|
||||
|
@ -653,10 +657,60 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Runs fastfetch command, returning the piped stdout output.
|
||||
fn run_fastfetch_command_piped<S>(args: &[S]) -> Result<String>
|
||||
where
|
||||
S: AsRef<OsStr> + fmt::Debug,
|
||||
{
|
||||
let mut command = make_fastfetch_command(args)?;
|
||||
|
||||
let output = command
|
||||
.output()
|
||||
.context("failed to execute fastfetch as child process")?;
|
||||
debug!(?output, "fastfetch output");
|
||||
process_command_status(&output.status).context("fastfetch command exited with error")?;
|
||||
|
||||
let out = String::from_utf8(output.stdout)
|
||||
.context("failed to process fastfetch output as it contains invalid UTF-8")?
|
||||
.trim()
|
||||
.to_owned();
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn make_fastfetch_command<S>(args: &[S]) -> Result<Command>
|
||||
where
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
// Find fastfetch binary
|
||||
let fastfetch_path = fastfetch_path().context("failed to get fastfetch path")?;
|
||||
let fastfetch_path = fastfetch_path.context("fastfetch command not found")?;
|
||||
|
||||
debug!(?fastfetch_path, "fastfetch path");
|
||||
|
||||
let mut command = Command::new(fastfetch_path);
|
||||
command.args(args);
|
||||
Ok(command)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug")]
|
||||
fn get_distro_name() -> Result<String> {
|
||||
run_neofetch_command_piped(&["ascii_distro_name"])
|
||||
.context("failed to get distro name from neofetch")
|
||||
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"),
|
||||
Backend::Fastfetch | Backend::FastfetchOld => run_fastfetch_command_piped(&[
|
||||
"--logo",
|
||||
"none",
|
||||
"-s",
|
||||
"OS",
|
||||
"--disable-linewrap",
|
||||
"--os-key",
|
||||
" ",
|
||||
])
|
||||
.context("failed to get distro name from fastfetch"),
|
||||
Backend::Qwqfetch => {
|
||||
todo!()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs neofetch with colors.
|
||||
|
@ -676,21 +730,18 @@ fn run_neofetch(asc: String, args: Option<&Vec<String>>) -> Result<()> {
|
|||
// Call neofetch with the temp file
|
||||
let temp_file_path = temp_file.into_temp_path();
|
||||
let args = {
|
||||
let mut v = vec![
|
||||
"--ascii",
|
||||
"--source",
|
||||
temp_file_path
|
||||
.to_str()
|
||||
.expect("temp file path should not contain invalid UTF-8"),
|
||||
"--ascii-colors",
|
||||
let mut v: Vec<Cow<OsStr>> = vec![
|
||||
OsStr::new("--ascii").into(),
|
||||
OsStr::new("--source").into(),
|
||||
OsStr::new(&temp_file_path).into(),
|
||||
OsStr::new("--ascii-colors").into(),
|
||||
];
|
||||
if let Some(args) = args {
|
||||
let args: Vec<_> = args.iter().map(|s| &**s).collect();
|
||||
v.extend(args);
|
||||
v.extend(args.iter().map(|arg| OsStr::new(arg).into()));
|
||||
}
|
||||
v
|
||||
};
|
||||
let mut command = make_neofetch_command(&args)?;
|
||||
let mut command = make_neofetch_command(&args[..])?;
|
||||
|
||||
debug!(?command, "neofetch command");
|
||||
|
||||
|
@ -761,12 +812,6 @@ fn fastfetch_path() -> Result<Option<PathBuf>> {
|
|||
/// Runs fastfetch with colors.
|
||||
#[tracing::instrument(level = "debug", skip(asc))]
|
||||
fn run_fastfetch(asc: String, args: Option<&Vec<String>>, legacy: bool) -> Result<()> {
|
||||
// Find fastfetch binary
|
||||
let fastfetch_path = fastfetch_path().context("failed to get fastfetch path")?;
|
||||
let fastfetch_path = fastfetch_path.context("fastfetch command not found")?;
|
||||
|
||||
debug!(?fastfetch_path, "fastfetch path");
|
||||
|
||||
// Write temp file
|
||||
let mut temp_file =
|
||||
NamedTempFile::with_prefix("ascii.txt").context("failed to create temp file for ascii")?;
|
||||
|
@ -776,12 +821,17 @@ fn run_fastfetch(asc: String, args: Option<&Vec<String>>, legacy: bool) -> Resul
|
|||
|
||||
// Call fastfetch with the temp file
|
||||
let temp_file_path = temp_file.into_temp_path();
|
||||
let mut command = Command::new(fastfetch_path);
|
||||
command.arg(if legacy { "--raw" } else { "--file-raw" });
|
||||
command.arg(&temp_file_path);
|
||||
let args = {
|
||||
let mut v: Vec<Cow<OsStr>> = vec![
|
||||
OsStr::new(if legacy { "--raw" } else { "--file-raw" }).into(),
|
||||
OsStr::new(&temp_file_path).into(),
|
||||
];
|
||||
if let Some(args) = args {
|
||||
command.args(args);
|
||||
v.extend(args.iter().map(|arg| OsStr::new(arg).into()));
|
||||
}
|
||||
v
|
||||
};
|
||||
let mut command = make_fastfetch_command(&args[..])?;
|
||||
|
||||
debug!(?command, "fastfetch command");
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use tracing::debug;
|
|||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use crate::color_util::{ForegroundBackground, Lightness, ToAnsiString};
|
||||
use crate::types::{AnsiMode, LightDark};
|
||||
use crate::types::{AnsiMode, TerminalTheme};
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
|
@ -639,20 +639,20 @@ impl ColorProfile {
|
|||
}
|
||||
|
||||
/// Creates a new color profile, with the colors set to the specified
|
||||
/// [`Okhsl`] lightness value, with respect to dark/light terminals.
|
||||
pub fn with_lightness_dl(
|
||||
/// [`Okhsl`] lightness value, adapted to the terminal theme.
|
||||
pub fn with_lightness_adaptive(
|
||||
&self,
|
||||
lightness: Lightness,
|
||||
term: LightDark,
|
||||
theme: TerminalTheme,
|
||||
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)),
|
||||
match theme {
|
||||
TerminalTheme::Dark => self.with_lightness(AssignLightness::ClampMin(lightness)),
|
||||
TerminalTheme::Light => self.with_lightness(AssignLightness::ClampMax(lightness)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ pub enum AnsiMode {
|
|||
)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
pub enum LightDark {
|
||||
pub enum TerminalTheme {
|
||||
Light,
|
||||
Dark,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue