[PR] Auto detect light/dark mode, changing the theme accordingly (#380)
* disable clippy lint * fmt * move detect bg into a function * auto detect light/dark opt * auto detect dark cli opt * optional light-dark * cli opt * nicer looking output * [-] Revert code style changes * [-] Revert code style changes * [-] Revert code style changes * [-] Revert * make the default theme dark --------- Co-authored-by: Azalea <22280294+hykilpikonna@users.noreply.github.com>
This commit is contained in:
parent
8a536c30f0
commit
0cc6ddbca8
4 changed files with 51 additions and 23 deletions
|
|
@ -87,7 +87,16 @@ fn main() -> Result<()> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let color_mode = options.mode.unwrap_or(config.mode);
|
let color_mode = options.mode.unwrap_or(config.mode);
|
||||||
let theme = config.light_dark;
|
let auto_detect_light_dark = options
|
||||||
|
.auto_detect_light_dark
|
||||||
|
.unwrap_or_else(|| config.auto_detect_light_dark.unwrap_or(false));
|
||||||
|
let theme = if auto_detect_light_dark {
|
||||||
|
let res = det_bg();
|
||||||
|
res?.map(|bg| bg.theme())
|
||||||
|
.unwrap_or(config.light_dark.unwrap_or_default())
|
||||||
|
} else {
|
||||||
|
config.light_dark.unwrap_or_default()
|
||||||
|
};
|
||||||
|
|
||||||
// Check if it's June (pride month)
|
// Check if it's June (pride month)
|
||||||
let now =
|
let now =
|
||||||
|
|
@ -131,7 +140,12 @@ fn main() -> Result<()> {
|
||||||
} else if let Some(lightness) = options.lightness {
|
} else if let Some(lightness) = options.lightness {
|
||||||
color_profile.with_lightness(AssignLightness::Replace(lightness))
|
color_profile.with_lightness(AssignLightness::Replace(lightness))
|
||||||
} else {
|
} else {
|
||||||
color_profile.with_lightness_adaptive(config.lightness(), theme)
|
color_profile.with_lightness_adaptive(
|
||||||
|
config
|
||||||
|
.lightness
|
||||||
|
.unwrap_or_else(|| Config::default_lightness(theme)),
|
||||||
|
theme,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
debug!(?color_profile, "lightened color profile");
|
debug!(?color_profile, "lightened color profile");
|
||||||
|
|
||||||
|
|
@ -187,6 +201,22 @@ fn load_config(path: &PathBuf) -> Result<Option<Config>> {
|
||||||
Ok(Some(config))
|
Ok(Some(config))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn det_bg() -> Result<Option<Srgb<u8>>, terminal_colorsaurus::Error> {
|
||||||
|
if !io::stdout().is_terminal() {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
background_color(QueryOptions::default())
|
||||||
|
.map(|terminal_colorsaurus::Color { r, g, b }| Some(Srgb::new(r, g, b).into_format()))
|
||||||
|
.or_else(|err| {
|
||||||
|
if matches!(err, terminal_colorsaurus::Error::UnsupportedTerminal) {
|
||||||
|
Ok(None)
|
||||||
|
} else {
|
||||||
|
Err(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates config interactively.
|
/// Creates config interactively.
|
||||||
///
|
///
|
||||||
/// The config is automatically stored to file.
|
/// The config is automatically stored to file.
|
||||||
|
|
@ -197,21 +227,10 @@ fn create_config(
|
||||||
backend: Backend,
|
backend: Backend,
|
||||||
debug_mode: bool,
|
debug_mode: bool,
|
||||||
) -> Result<Config> {
|
) -> Result<Config> {
|
||||||
// Detect terminal environment (doesn't work for all terminal emulators,
|
let det_bg = det_bg()?;
|
||||||
// especially on Windows)
|
|
||||||
let det_bg = if io::stdout().is_terminal() {
|
|
||||||
match background_color(QueryOptions::default()) {
|
|
||||||
Ok(bg) => Some(Srgb::<u16>::new(bg.r, bg.g, bg.b).into_format::<u8>()),
|
|
||||||
Err(terminal_colorsaurus::Error::UnsupportedTerminal) => None,
|
|
||||||
Err(err) => {
|
|
||||||
return Err(err).context("failed to get terminal background color");
|
|
||||||
},
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
debug!(?det_bg, "detected background color");
|
debug!(?det_bg, "detected background color");
|
||||||
let det_ansi = supports_color::on(supports_color::Stream::Stdout).map(|color_level| {
|
let det_ansi = supports_color::on(supports_color::Stream::Stdout).map(|color_level| {
|
||||||
|
#[allow(clippy::if_same_then_else)]
|
||||||
if color_level.has_16m {
|
if color_level.has_16m {
|
||||||
AnsiMode::Rgb
|
AnsiMode::Rgb
|
||||||
} else if color_level.has_256 {
|
} else if color_level.has_256 {
|
||||||
|
|
@ -230,7 +249,7 @@ fn create_config(
|
||||||
|
|
||||||
let asc = get_distro_ascii(distro, backend).context("failed to get distro ascii")?;
|
let asc = get_distro_ascii(distro, backend).context("failed to get distro ascii")?;
|
||||||
let asc = asc.to_normalized().context("failed to normalize ascii")?;
|
let asc = asc.to_normalized().context("failed to normalize ascii")?;
|
||||||
let theme = det_bg.map(|bg| bg.theme()).unwrap_or(TerminalTheme::Light);
|
let theme = det_bg.map(|bg| bg.theme()).unwrap_or_default();
|
||||||
let color_mode = det_ansi.unwrap_or(AnsiMode::Ansi256);
|
let color_mode = det_ansi.unwrap_or(AnsiMode::Ansi256);
|
||||||
let mut title = format!(
|
let mut title = format!(
|
||||||
"Welcome to {logo} Let's set up some colors first.",
|
"Welcome to {logo} Let's set up some colors first.",
|
||||||
|
|
@ -1002,7 +1021,8 @@ fn create_config(
|
||||||
let config = Config {
|
let config = Config {
|
||||||
preset,
|
preset,
|
||||||
mode: color_mode,
|
mode: color_mode,
|
||||||
light_dark: theme,
|
light_dark: Some(theme),
|
||||||
|
auto_detect_light_dark: Some(det_bg.is_some()),
|
||||||
lightness: Some(lightness),
|
lightness: Some(lightness),
|
||||||
color_align,
|
color_align,
|
||||||
backend,
|
backend,
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ pub struct Options {
|
||||||
pub print_font_logo: bool,
|
pub print_font_logo: bool,
|
||||||
pub test_print: bool,
|
pub test_print: bool,
|
||||||
pub ask_exit: bool,
|
pub ask_exit: bool,
|
||||||
|
pub auto_detect_light_dark: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn options() -> OptionParser<Options> {
|
pub fn options() -> OptionParser<Options> {
|
||||||
|
|
@ -170,6 +171,10 @@ BACKEND={{{backends}}}",
|
||||||
.help("Ask for input before exiting")
|
.help("Ask for input before exiting")
|
||||||
.switch()
|
.switch()
|
||||||
.hide();
|
.hide();
|
||||||
|
let auto_detect_light_dark = long("auto-detect-light-dark")
|
||||||
|
.help("Enables hyfetch to detect light/dark terminal background in runtime")
|
||||||
|
.argument("BOOL")
|
||||||
|
.optional();
|
||||||
|
|
||||||
construct!(Options {
|
construct!(Options {
|
||||||
config,
|
config,
|
||||||
|
|
@ -188,6 +193,7 @@ BACKEND={{{backends}}}",
|
||||||
// hidden
|
// hidden
|
||||||
test_print,
|
test_print,
|
||||||
ask_exit,
|
ask_exit,
|
||||||
|
auto_detect_light_dark,
|
||||||
})
|
})
|
||||||
.to_options()
|
.to_options()
|
||||||
.header(
|
.header(
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ use crate::types::{AnsiMode, Backend, TerminalTheme};
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub preset: Preset,
|
pub preset: Preset,
|
||||||
pub mode: AnsiMode,
|
pub mode: AnsiMode,
|
||||||
pub light_dark: TerminalTheme,
|
pub auto_detect_light_dark: Option<bool>,
|
||||||
|
pub light_dark: Option<TerminalTheme>,
|
||||||
pub lightness: Option<Lightness>,
|
pub lightness: Option<Lightness>,
|
||||||
pub color_align: ColorAlignment,
|
pub color_align: ColorAlignment,
|
||||||
pub backend: Backend,
|
pub backend: Backend,
|
||||||
|
|
@ -31,11 +32,6 @@ impl Config {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lightness(&self) -> Lightness {
|
|
||||||
self.lightness
|
|
||||||
.unwrap_or_else(|| Self::default_lightness(self.light_dark))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mod args_serde {
|
mod args_serde {
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,12 @@ pub enum TerminalTheme {
|
||||||
Dark,
|
Dark,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for TerminalTheme {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Dark
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Copy,
|
Copy,
|
||||||
Clone,
|
Clone,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue