style(app): support colors for the tree output

This commit is contained in:
Orhun Parmaksız 2021-12-17 02:52:03 +03:00
parent 21db751458
commit 1f71a6d085
No known key found for this signature in database
GPG key ID: F83424824B3E4B90
3 changed files with 68 additions and 31 deletions

View file

@ -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::<Vec<&str>>();
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<String> {
let section_color = *(config
.section_colors
.get(&self.section)
.unwrap_or(&config.default_color));
let mut components = self
.name
.split('.')
.map(String::from)
.collect::<Vec<String>>();
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<W: Write>(&self, config: &Config, output: &mut W) -> Result<()> {
match config.display_type {

View file

@ -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<bool>,
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<Output: Write>(&self, output: &mut Output, connectors: &[bool]) -> IoResult<()> {
fn print_line<Output: Write>(
&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<Output: Write>(&self, out: &mut Output) -> IoResult<()> {
pub fn print<Output: Write>(&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);
}

View file

@ -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::<Vec<String>>();
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)