From d8f039d76b29462d5e0188305955a06db862692e Mon Sep 17 00:00:00 2001 From: quak Date: Sun, 15 Dec 2024 23:30:36 +0100 Subject: [PATCH] implemented parsing of color settings of formats [named, numbered, rgb] (example ['red', 29, #12345F]) --- src/config.rs | 54 ++++++++++++++++++++++++++--------------- src/format.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/stack.rs | 2 +- 3 files changed, 102 insertions(+), 20 deletions(-) diff --git a/src/config.rs b/src/config.rs index 76f23b6..1c23282 100644 --- a/src/config.rs +++ b/src/config.rs @@ -94,9 +94,12 @@ impl Config { .push(format!("navigate/{}", Self::CONFIG_FILE_NAME)); // parse configuration file and populate config struct - config.build_settings()?; + let file_error = config.build_settings(); config.set_default_settings()?; - config.write_config_file()?; + if file_error.is_err() { + config.write_config_file()?; + } + config.parse_color_settings()?; Ok(config) } @@ -108,19 +111,12 @@ impl Config { Ok(buffer) } - /// write configuration file to save changed settings - pub fn write_config_file(&self) -> Result<()> { - let conf_str = match toml::to_string(&self.settings) { - Ok(value) => value, - Err(error) => return Err(Error::other(error.to_string())), - }; - fs::write(self.conf_file.clone(), conf_str) - } - /// reads and parses the configuration file fn build_settings(&mut self) -> Result<()> { if !self.conf_file.is_file() { - return Ok(()); + return Err(Error::other( + "-- config file `navigation.conf` does not exist", + )); } let config_str = match fs::read_to_string(&self.conf_file) { Ok(value) => value, @@ -130,19 +126,15 @@ impl Config { Ok(value) => value, Err(error) => return Err(Error::other(error.to_string())), }; - Ok(()) } /// sets defaults for settings not found in the configuration file fn set_default_settings(&mut self) -> Result<()> { let default_separator = " - ".to_owned(); - let default_number_color = - generate_style_sequence(None, Some(COLORS.fg.default), Some(COLORS.bg.default)); - let default_separator_color = - generate_style_sequence(None, Some(COLORS.fg.cyan), Some(COLORS.bg.default)); - let default_path_color = - generate_style_sequence(None, Some(COLORS.fg.default), Some(COLORS.bg.default)); + let default_number_color = "default".to_owned(); + let default_separator_color = "cyan".to_owned(); + let default_path_color = "default".to_owned(); if self.settings.format.stack_separator.is_empty() { self.settings.format.stack_separator = default_separator.clone(); @@ -172,4 +164,28 @@ impl Config { Ok(()) } + + /// write configuration file to save changed settings + pub fn write_config_file(&self) -> Result<()> { + let conf_str = match toml::to_string(&self.settings) { + Ok(value) => value, + Err(error) => return Err(Error::other(error.to_string())), + }; + fs::write(self.conf_file.clone(), conf_str) + } + + /// convert color settings to ansi escape sequences + pub fn parse_color_settings(&mut self) -> Result<()> { + self.settings.styles.stack_number = parse_color(self.settings.styles.stack_number.clone())?; + self.settings.styles.stack_separator = + parse_color(self.settings.styles.stack_separator.clone())?; + self.settings.styles.stack_path = parse_color(self.settings.styles.stack_path.clone())?; + self.settings.styles.bookmarks_name = + parse_color(self.settings.styles.bookmarks_name.clone())?; + self.settings.styles.bookmarks_seperator = + parse_color(self.settings.styles.bookmarks_seperator.clone())?; + self.settings.styles.bookmarks_path = + parse_color(self.settings.styles.bookmarks_path.clone())?; + Ok(()) + } } diff --git a/src/format.rs b/src/format.rs index 2c39fa6..6581a0c 100644 --- a/src/format.rs +++ b/src/format.rs @@ -1,5 +1,7 @@ #![allow(dead_code)] +use std::io::{Result, Error}; + pub const ESC: &str = "\x1B"; pub const PREFIX: &str = "\x1B["; pub const RESET_ARG: &str = "0"; @@ -187,3 +189,67 @@ pub fn make_padding_string(len: usize) -> String { // determine padding needed to align the paths String::from_utf8(vec![b' '; len]).unwrap() } + +/// convert color setting to ansi escape sequence +pub fn parse_color(color: String) -> Result { + // check for numbered color + if let Ok(numbered) = color.parse::() { + return Ok(generate_256color_sequence( + ColorContext::Foreground, + numbered, + )); + } + // check for rgb color + if color.as_bytes()[0] == b'#' && color.len() == 7 { + // match u8::from_str_radix(&color, 16) { + let red = match u8::from_str_radix(&color[1..=2], 16) { + Ok(value) => value, + Err(_) => { + return Err(Error::other(format!( + "-- failed to parse rgb color `{}` in config file", + color + ))) + } + }; + let green = match u8::from_str_radix(&color[3..=4], 16) { + Ok(value) => value, + Err(_) => { + return Err(Error::other(format!( + "-- failed to parse rgb color `{}` in config file", + color + ))) + } + }; + let blue = match u8::from_str_radix(&color[5..=6], 16) { + Ok(value) => value, + Err(_) => { + return Err(Error::other(format!( + "-- failed to parse rgb color `{}` in config file", + color + ))) + } + }; + return Ok(generate_rgb_sequence( + ColorContext::Foreground, + red, + green, + blue, + )); + } + // check for named color + match color.to_ascii_lowercase().as_str() { + "black" => Ok(generate_style_sequence(None, Some(COLORS.fg.black), None)), + "red" => Ok(generate_style_sequence(None, Some(COLORS.fg.red), None)), + "green" => Ok(generate_style_sequence(None, Some(COLORS.fg.green), None)), + "yellow" => Ok(generate_style_sequence(None, Some(COLORS.fg.yellow), None)), + "blue" => Ok(generate_style_sequence(None, Some(COLORS.fg.blue), None)), + "magenta" => Ok(generate_style_sequence(None, Some(COLORS.fg.magenta), None)), + "cyan" => Ok(generate_style_sequence(None, Some(COLORS.fg.cyan), None)), + "white" => Ok(generate_style_sequence(None, Some(COLORS.fg.white), None)), + "default" => Ok(generate_style_sequence(None, Some(COLORS.fg.default), None)), + _ => Err(Error::other(format!( + "-- could not parse color `{}` in config file", + color + ))), + } +} diff --git a/src/stack.rs b/src/stack.rs index 0f48a15..1dade72 100644 --- a/src/stack.rs +++ b/src/stack.rs @@ -30,7 +30,7 @@ impl Stack { Ok(stack) } - // formats and prints stack to string + /// formats and prints stack to string pub fn to_formatted_string(&self, config: &Settings) -> Result { let mut buffer: String = "".to_string();