From 9a3e87f2cbaa8ca4b8dea41f4f56ff297e94bb1a Mon Sep 17 00:00:00 2001 From: Jovan Gerodetti Date: Fri, 28 Jun 2024 23:40:35 +0200 Subject: [PATCH] feat(color): add prev_fg and prev_bg as color specifiers based on the previous foreground/background colors respectively (#6017) feat(color): add prevfg,prevbg as color specifiers based on the previous foreground/background colors respectively Co-authored-by: Vladimir Lushnikov --- docs/advanced-config/README.md | 4 +- src/config.rs | 275 +++++++++++++++++++++++------- src/formatter/string_formatter.rs | 13 +- src/module.rs | 14 +- src/segment.rs | 38 ++--- 5 files changed, 250 insertions(+), 94 deletions(-) diff --git a/docs/advanced-config/README.md b/docs/advanced-config/README.md index f0efae1c..f102f5c6 100644 --- a/docs/advanced-config/README.md +++ b/docs/advanced-config/README.md @@ -358,7 +358,9 @@ Style strings are a list of words, separated by whitespace. The words are not ca - `` - `none` -where `` is a color specifier (discussed below). `fg:` and `` currently do the same thing, though this may change in the future. `inverted` swaps the background and foreground colors. The order of words in the string does not matter. +where `` is a color specifier (discussed below). `fg:` and `` currently do the same thing, though this may change in the future. +`` can also be set to `prev_fg` or `prev_bg` which evaluates to the previous item's foreground or background color respectively if available or `none` otherwise. +`inverted` swaps the background and foreground colors. The order of words in the string does not matter. The `none` token overrides all other tokens in a string if it is not part of a `bg:` specifier, so that e.g. `fg:red none fg:blue` will still create a string with no styling. `bg:none` sets the background to the default color so `fg:red bg:none` is equivalent to `red` or `fg:red` and `bg:green fg:red bg:none` is also equivalent to `fg:red` or `red`. It may become an error to use `none` in conjunction with other tokens in the future. diff --git a/src/config.rs b/src/config.rs index 9ff37f1d..6a710cc6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -261,7 +261,7 @@ impl StarshipConfig { } /// Deserialize a style string in the starship format with serde -pub fn deserialize_style<'de, D>(de: D) -> Result +pub fn deserialize_style<'de, D>(de: D) -> Result where D: Deserializer<'de>, { @@ -270,6 +270,88 @@ where }) } +#[derive(Clone, Copy, Debug, PartialEq)] +enum PrevColor { + Fg, + Bg, +} + +#[derive(Clone, Copy, Debug, Default, PartialEq)] +/// Wrapper for `nu_ansi_term::Style` that supports referencing the previous style's foreground/background color. +pub struct Style { + style: nu_ansi_term::Style, + bg: Option, + fg: Option, +} + +impl Style { + pub fn to_ansi_style(&self, prev: Option<&nu_ansi_term::Style>) -> nu_ansi_term::Style { + let Some(prev_style) = prev else { + return self.style; + }; + + let mut current = self.style; + + if let Some(prev_color) = self.bg { + match prev_color { + PrevColor::Fg => current.background = prev_style.foreground, + PrevColor::Bg => current.background = prev_style.background, + } + } + + if let Some(prev_color) = self.fg { + match prev_color { + PrevColor::Fg => current.foreground = prev_style.foreground, + PrevColor::Bg => current.foreground = prev_style.background, + } + } + + current + } + + fn map_style(&self, f: F) -> Self + where + F: FnOnce(&nu_ansi_term::Style) -> nu_ansi_term::Style, + { + Style { + style: f(&self.style), + ..*self + } + } + + fn fg(&self, prev_color: PrevColor) -> Self { + Self { + fg: Some(prev_color), + ..*self + } + } + + fn bg(&self, prev_color: PrevColor) -> Self { + Self { + bg: Some(prev_color), + ..*self + } + } +} + +impl From for Style { + fn from(value: nu_ansi_term::Style) -> Self { + Style { + style: value, + ..Default::default() + } + } +} + +impl From for Style { + fn from(value: nu_ansi_term::Color) -> Self { + Style { + style: value.into(), + ..Default::default() + } + } +} + /** Parse a style string which represents an ansi style. Valid tokens in the style string include the following: - 'fg:' (specifies that the color read should be a foreground color) @@ -279,15 +361,14 @@ where - 'italic' - 'inverted' - 'blink' + - 'prev_fg' (specifies the color should be the previous foreground color) + - 'prev_bg' (specifies the color should be the previous background color) - '' (see the `parse_color_string` doc for valid color strings) */ -pub fn parse_style_string( - style_string: &str, - context: Option<&Context>, -) -> Option { +pub fn parse_style_string(style_string: &str, context: Option<&Context>) -> Option