From 1f71a6d0859eebe6db8e5a86dc3cafc044524bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orhun=20Parmaks=C4=B1z?= Date: Fri, 17 Dec 2021 02:52:03 +0300 Subject: [PATCH] style(app): support colors for the tree output --- systeroid-core/src/sysctl/parameter.rs | 40 +++++++++++++++++++++++--- systeroid-core/src/tree.rs | 37 +++++++++++++++--------- systeroid/src/app.rs | 22 ++++++-------- 3 files changed, 68 insertions(+), 31 deletions(-) diff --git a/systeroid-core/src/sysctl/parameter.rs b/systeroid-core/src/sysctl/parameter.rs index ec3910e..240db5d 100644 --- a/systeroid-core/src/sysctl/parameter.rs +++ b/systeroid-core/src/sysctl/parameter.rs @@ -51,16 +51,16 @@ impl Parameter { /// Returns the parameter name with corresponding section colors. pub fn colored_name(&self, config: &Config) -> String { + let section_color = *(config + .section_colors + .get(&self.section) + .unwrap_or(&config.default_color)); let fields = self.name.split('.').collect::>(); fields .iter() .enumerate() .fold(String::new(), |mut result, (i, v)| { if i != fields.len() - 1 { - let section_color = *(config - .section_colors - .get(&self.section) - .unwrap_or(&config.default_color)); result += &format!( "{}{}", v.color(section_color), @@ -73,6 +73,38 @@ impl Parameter { }) } + /// Returns the components of the parameter to contruct a [`Tree`]. + /// + /// [`Tree`]: crate::tree::Tree + pub fn get_tree_components(&self, config: &Config) -> Vec { + let section_color = *(config + .section_colors + .get(&self.section) + .unwrap_or(&config.default_color)); + let mut components = self + .name + .split('.') + .map(String::from) + .collect::>(); + let total_components = components.len(); + components + .iter_mut() + .enumerate() + .for_each(|(i, component)| { + if i != total_components - 1 { + *component = component.color(section_color).to_string(); + } else { + *component = format!( + "{} {} {}", + component, + "=".color(config.default_color), + self.value.replace('\n', " ").bold() + ); + } + }); + components + } + /// Prints the kernel parameter to given output. pub fn display_value(&self, config: &Config, output: &mut W) -> Result<()> { match config.display_type { diff --git a/systeroid-core/src/tree.rs b/systeroid-core/src/tree.rs index 81518df..a1d085e 100644 --- a/systeroid-core/src/tree.rs +++ b/systeroid-core/src/tree.rs @@ -1,8 +1,9 @@ +use colored::*; use std::fmt::Display; use std::io::{Result as IoResult, Write}; -/// Vertical character for connecting sequential nodes. -const VERTICAL_CHAR: char = '│'; +/// Vertical connector. +const VERTICAL_STR: &str = "│"; /// Horizontal connector. const HORIZONTAL_STR: &str = "├──"; /// Horizontal connector for the last node. @@ -47,8 +48,9 @@ impl TreeNode { &self, out: &mut Output, connectors: &mut Vec, + connector_color: Color, ) -> IoResult<()> { - self.print_line(out, &connectors[..])?; + self.print_line(out, &connectors[..], connector_color)?; connectors.push(false); for (i, child) in self.childs.iter().enumerate() { if self.childs.len() == i + 1 { @@ -56,22 +58,31 @@ impl TreeNode { *last_connector = true; } } - child.print(out, connectors)?; + child.print(out, connectors, connector_color)?; } connectors.pop(); Ok(()) } /// Prints a single line with the given connectors. - fn print_line(&self, output: &mut Output, connectors: &[bool]) -> IoResult<()> { + fn print_line( + &self, + output: &mut Output, + connectors: &[bool], + connector_color: Color, + ) -> IoResult<()> { if let Some(last_connector) = connectors.last() { for last in &connectors[..connectors.len() - 1] { - write!(output, "{} ", if *last { ' ' } else { VERTICAL_CHAR })?; + write!( + output, + "{} ", + if *last { " " } else { VERTICAL_STR }.color(connector_color) + )?; } if *last_connector { - write!(output, "{} ", LAST_HORIZONTAL_STR)?; + write!(output, "{} ", LAST_HORIZONTAL_STR.color(connector_color))?; } else { - write!(output, "{} ", HORIZONTAL_STR)?; + write!(output, "{} ", HORIZONTAL_STR.color(connector_color))?; } } writeln!(output, "{}", self.value)?; @@ -107,9 +118,9 @@ impl Tree { } /// Prints the full tree to the given output. - pub fn print(&self, out: &mut Output) -> IoResult<()> { + pub fn print(&self, out: &mut Output, connector_color: Color) -> IoResult<()> { for node in &self.nodes { - node.print(out, &mut Vec::new())?; + node.print(out, &mut Vec::new(), connector_color)?; } Ok(()) } @@ -214,7 +225,7 @@ mod tests { value: value.to_string(), childs: Vec::new(), } - .print_line(&mut output, &[]) + .print_line(&mut output, &[], Color::White) .unwrap(); assert_eq!(b"abc\ndef\n", &*output); @@ -223,7 +234,7 @@ mod tests { value: value.to_string(), childs: Vec::new(), } - .print_line(&mut output, &[true, false, true]) + .print_line(&mut output, &[true, false, true], Color::White) .unwrap(); assert_eq!(" │ └── abc\ndef\n".as_bytes(), &*output); @@ -232,7 +243,7 @@ mod tests { value: value.to_string(), childs: Vec::new(), } - .print_line(&mut output, &[true, false, false]) + .print_line(&mut output, &[true, false, false], Color::White) .unwrap(); assert_eq!(" │ ├── abc\ndef\n".as_bytes(), &*output); } diff --git a/systeroid/src/app.rs b/systeroid/src/app.rs index 22f95d6..a57b4fd 100644 --- a/systeroid/src/app.rs +++ b/systeroid/src/app.rs @@ -57,21 +57,15 @@ impl<'a> App<'a> { if tree_output { let mut root_node = TreeNode::default(); parameters.for_each(|parameter| { - let mut components = parameter - .name - .split('.') - .map(String::from) - .collect::>(); - if let Some(last_component) = components.last_mut() { - *last_component = format!( - "{} = {}", - last_component, - parameter.value.replace('\n', " ") - ); - } - root_node.add(&mut components.iter().map(|v| v.as_ref())); + root_node.add( + &mut parameter + .get_tree_components(&self.sysctl.config) + .iter() + .map(|v| v.as_ref()), + ); }); - Tree::new(root_node.childs).print(&mut self.stdout)?; + Tree::new(root_node.childs) + .print(&mut self.stdout, self.sysctl.config.default_color)?; } else { parameters.try_for_each(|parameter| { parameter.display_value(&self.sysctl.config, &mut self.stdout)