summaryrefslogtreecommitdiffstats
path: root/src/config.rs
diff options
context:
space:
mode:
authorAnomalocaridid <29845794+Anomalocaridid@users.noreply.github.com>2022-09-27 17:08:52 -0400
committerGitHub <noreply@github.com>2022-09-27 23:08:52 +0200
commitd93074d0569db4bafb1788aa3f39136b734b5370 (patch)
tree28c4b9e543fc43ef5a43c9b1213de7806546fb30 /src/config.rs
parentf9947d9f140397853b06d4605c2887f961a37ad6 (diff)
feat: add user-defined color palette (#4209)
* docs(config): add color palette to docs * feat: add user-defined color palette * fix: update config schema * refactor: apply suggestions from code review Co-authored-by: David Knaack <davidkna@users.noreply.github.com> * fix: update new test * feat: add support for multiple palettes * docs(config): update docs for multiple color palettes * docs(config): fix formatting * test: test overriding a predefined color with itself * docs: mention palettes cannot reference themselves * refactor: warn when using a nonexistent palette * test: test retrieving a nonexistent color palette * fix: fix issues with palette log messages * fix: update config schema * fix: skip serializing palette if none * refactor: change nonexistent palette message to warning * fix: update config schema Co-authored-by: David Knaack <davidkna@users.noreply.github.com>
Diffstat (limited to 'src/config.rs')
-rw-r--r--src/config.rs127
1 files changed, 122 insertions, 5 deletions
diff --git a/src/config.rs b/src/config.rs
index 5f4ead789..7a44a3115 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,3 +1,5 @@
+use crate::configs::Palette;
+use crate::context::Context;
use crate::serde_utils::ValueDeserializer;
use crate::utils;
use nu_ansi_term::Color;
@@ -7,6 +9,7 @@ use serde::{
use std::borrow::Cow;
use std::clone::Clone;
+use std::collections::HashMap;
use std::io::ErrorKind;
use std::env;
@@ -260,7 +263,7 @@ where
D: Deserializer<'de>,
{
Cow::<'_, str>::deserialize(de).and_then(|s| {
- parse_style_string(s.as_ref()).ok_or_else(|| D::Error::custom("Invalid style string"))
+ parse_style_string(s.as_ref(), None).ok_or_else(|| D::Error::custom("Invalid style string"))
})
}
@@ -275,7 +278,10 @@ where
- 'blink'
- '<color>' (see the `parse_color_string` doc for valid color strings)
*/
-pub fn parse_style_string(style_string: &str) -> Option<nu_ansi_term::Style> {
+pub fn parse_style_string(
+ style_string: &str,
+ context: Option<&Context>,
+) -> Option<nu_ansi_term::Style> {
style_string
.split_whitespace()
.fold(Some(nu_ansi_term::Style::new()), |maybe_style, token| {
@@ -308,7 +314,15 @@ pub fn parse_style_string(style_string: &str) -> Option<nu_ansi_term::Style> {
None // fg:none yields no style.
} else {
// Either bg or valid color or both.
- let parsed = parse_color_string(color_string);
+ let parsed = parse_color_string(
+ color_string,
+ context.and_then(|x| {
+ get_palette(
+ &x.root_config.palettes,
+ x.root_config.palette.as_deref(),
+ )
+ }),
+ );
// bg + invalid color = reset the background to default.
if !col_fg && parsed.is_none() {
let mut new_style = style;
@@ -335,9 +349,12 @@ pub fn parse_style_string(style_string: &str) -> Option<nu_ansi_term::Style> {
There are three valid color formats:
- #RRGGBB (a hash followed by an RGB hex)
- u8 (a number from 0-255, representing an ANSI color)
- - colstring (one of the 16 predefined color strings)
+ - colstring (one of the 16 predefined color strings or a custom user-defined color)
*/
-fn parse_color_string(color_string: &str) -> Option<nu_ansi_term::Color> {
+fn parse_color_string(
+ color_string: &str,
+ palette: Option<&Palette>,
+) -> Option<nu_ansi_term::Color> {
// Parse RGB hex values
log::trace!("Parsing color_string: {}", color_string);
if color_string.starts_with('#') {
@@ -362,6 +379,16 @@ fn parse_color_string(color_string: &str) -> Option<nu_ansi_term::Color> {
return Some(Color::Fixed(ansi_color_num));
}
+ // Check palette for a matching user-defined color
+ if let Some(palette_color) = palette.as_ref().and_then(|x| x.get(color_string)) {
+ log::trace!(
+ "Read user-defined color string: {} defined as {}",
+ color_string,
+ palette_color
+ );
+ return parse_color_string(palette_color, None);
+ }
+
// Check for any predefined color strings
// There are no predefined enums for bright colors, so we use Color::Fixed
let predefined_color = match color_string.to_lowercase().as_str() {
@@ -392,6 +419,24 @@ fn parse_color_string(color_string: &str) -> Option<nu_ansi_term::Color> {
predefined_color
}
+fn get_palette<'a>(
+ palettes: &'a HashMap<String, Palette>,
+ palette_name: Option<&str>,
+) -> Option<&'a Palette> {
+ if let Some(palette_name) = palette_name {
+ let palette = palettes.get(palette_name);
+ if palette.is_some() {
+ log::trace!("Found color palette: {}", palette_name);
+ } else {
+ log::warn!("Could not find color palette: {}", palette_name);
+ }
+ palette
+ } else {
+ log::trace!("No color palette specified, using defaults");
+ None
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -778,4 +823,76 @@ mod tests {
Style::new().fg(Color::Fixed(125)).on(Color::Fixed(127))
);
}
+
+ #[test]
+ fn table_get_colors_palette() {
+ // Test using colors defined in palette
+ let mut palette = Palette::new();
+ palette.insert("mustard".to_string(), "#af8700".to_string());
+ palette.insert("sky-blue".to_string(), "51".to_string());
+ palette.insert("red".to_string(), "#d70000".to_string());
+ palette.insert("blue".to_string(), "17".to_string());
+ palette.insert("green".to_string(), "green".to_string());
+
+ assert_eq!(
+ parse_color_string("mustard", Some(&palette)),
+ Some(Color::Rgb(175, 135, 0))
+ );
+ assert_eq!(
+ parse_color_string("sky-blue", Some(&palette)),
+ Some(Color::Fixed(51))
+ );
+
+ // Test overriding predefined colors
+ assert_eq!(
+ parse_color_string("red", Some(&palette)),
+ Some(Color::Rgb(215, 0, 0))
+ );
+ assert_eq!(
+ parse_color_string("blue", Some(&palette)),
+ Some(Color::Fixed(17))
+ );
+
+ // Test overriding a predefined color with itself
+ assert_eq!(
+ parse_color_string("green", Some(&palette)),
+ Some(Color::Green)
+ )
+ }
+
+ #[test]
+ fn table_get_palette() {
+ // Test retrieving color palette by name
+ let mut palette1 = Palette::new();
+ palette1.insert("test-color".to_string(), "123".to_string());
+
+ let mut palette2 = Palette::new();
+ palette2.insert("test-color".to_string(), "#ABCDEF".to_string());
+
+ let mut palettes = HashMap::<String, Palette>::new();
+ palettes.insert("palette1".to_string(), palette1);
+ palettes.insert("palette2".to_string(), palette2);
+
+ assert_eq!(
+ get_palette(&palettes, Some("palette1"))
+ .unwrap()
+ .get("test-color")
+ .unwrap(),
+ "123"
+ );
+
+ assert_eq!(
+ get_palette(&palettes, Some("palette2"))
+ .unwrap()
+ .get("test-color")
+ .unwrap(),
+ "#ABCDEF"
+ );
+
+ // Test retrieving nonexistent color palette
+ assert!(get_palette(&palettes, Some("palette3")).is_none());
+
+ // Test default behavior
+ assert!(get_palette(&palettes, None).is_none());
+ }
}