feat(sysctl): print the parameters with their section colors

This commit is contained in:
Orhun Parmaksız 2021-10-31 16:26:27 +03:00
parent 14abb58f17
commit 783320c276
No known key found for this signature in database
GPG key ID: F83424824B3E4B90
7 changed files with 126 additions and 7 deletions

23
Cargo.lock generated
View file

@ -11,6 +11,17 @@ dependencies = [
"memchr",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.0.1"
@ -44,6 +55,17 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "colored"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd"
dependencies = [
"atty",
"lazy_static",
"winapi",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.1"
@ -324,6 +346,7 @@ dependencies = [
name = "systeroid-core"
version = "0.1.0"
dependencies = [
"colored",
"lazy_static",
"rayon",
"sysctl",

View file

@ -9,6 +9,7 @@ sysctl = "0.4.2"
thiserror = "1.0.29"
lazy_static = "1.4.0"
rayon = "1.5.1"
colored = "2.0.0"
[dependencies.systeroid-parser]
version = "0.1.0"

View file

@ -0,0 +1,46 @@
use crate::sysctl::Section;
use colored::Color;
use std::collections::HashMap;
/* Macro for the concise initialization of HashMap */
macro_rules! map {
($( $key: expr => $val: expr ),*) => {{
let mut map = ::std::collections::HashMap::new();
$( map.insert($key, $val); )*
map
}}
}
/// General configuration.
#[derive(Debug, Default)]
pub struct Config {
/// Sysctl configuration.
pub sysctl: SysctlConfig,
}
/// Sysctl configuration.
#[derive(Debug)]
pub struct SysctlConfig {
/// Sections and the corresponding colors.
pub section_colors: HashMap<Section, Color>,
/// Default color for the output
pub default_color: Color,
}
impl Default for SysctlConfig {
fn default() -> Self {
Self {
section_colors: map! {
Section::Abi => Color::Red,
Section::Fs => Color::Green,
Section::Kernel => Color::Magenta,
Section::Net => Color::Blue,
Section::Sunrpc => Color::Yellow,
Section::User => Color::Cyan,
Section::Vm => Color::BrightRed,
Section::Unknown => Color::BrightBlack
},
default_color: Color::BrightBlack,
}
}
}

View file

@ -13,3 +13,6 @@ pub mod error;
/// Parsers for the kernel documentation.
pub mod parsers;
/// Configuration.
pub mod config;

View file

@ -1,5 +1,7 @@
use crate::config::SysctlConfig;
use crate::error::Result;
use crate::parsers::parse_kernel_docs;
use colored::*;
use rayon::prelude::*;
use std::fmt::{self, Display, Formatter};
use std::io::Write;
@ -9,7 +11,7 @@ use sysctl::{CtlFlags, CtlIter, Sysctl as SysctlImpl};
use systeroid_parser::document::Document;
/// Sections of the sysctl documentation.
#[derive(Clone, Copy, Debug, PartialEq)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Section {
/// Documentation for `/proc/sys/abi/*`
Abi,
@ -87,16 +89,44 @@ pub struct Parameter {
pub document: Option<Document>,
}
impl Parameter {
/// Returns the parameter name with corresponding section colors.
pub fn colored_name(&self, config: &SysctlConfig) -> String {
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),
".".color(config.default_color)
);
} else {
result += v;
}
result
})
}
}
/// Sysctl wrapper for managing the kernel parameters.
#[derive(Debug)]
pub struct Sysctl {
/// Available kernel parameters.
pub parameters: Vec<Parameter>,
/// Configuration.
pub config: SysctlConfig,
}
impl Sysctl {
/// Constructs a new instance by fetching the available kernel parameters.
pub fn init() -> Result<Self> {
pub fn init(config: SysctlConfig) -> Result<Self> {
let mut parameters = Vec::new();
for ctl in CtlIter::root().filter_map(StdResult::ok).filter(|ctl| {
ctl.flags()
@ -111,7 +141,7 @@ impl Sysctl {
document: None,
});
}
Ok(Self { parameters })
Ok(Self { parameters, config })
}
/// Updates the descriptions of the kernel parameters.
@ -146,9 +176,19 @@ impl Sysctl {
}
/// Prints the available kernel parameters to the given output.
pub fn print_all<W: Write>(&self, output: &mut W) -> Result<()> {
pub fn print_all<W: Write>(&self, output: &mut W, colored: bool) -> Result<()> {
for parameter in &self.parameters {
writeln!(output, "{} = {}", parameter.name, parameter.value)?;
if colored {
writeln!(
output,
"{} {} {}",
parameter.colored_name(&self.config),
"=".color(self.config.default_color),
parameter.value.bold(),
)?;
} else {
writeln!(output, "{} = {}", parameter.name, parameter.value)?;
}
}
Ok(())
}

View file

@ -19,6 +19,8 @@ pub struct Args {
pub kernel_docs: Option<PathBuf>,
/// Display all of the kernel parameters.
pub all: bool,
/// Disable colored output.
pub no_color: bool,
}
impl Args {
@ -28,6 +30,7 @@ impl Args {
opts.optflag("h", "help", "display this help and exit");
opts.optflag("V", "version", "output version information and exit");
opts.optflag("a", "all", "display all variables");
opts.optflag("", "no-color", "disable colored output");
opts.optopt(
"d",
"docs",
@ -55,6 +58,7 @@ impl Args {
Some(Args {
kernel_docs: matches.opt_str("d").map(PathBuf::from),
all: matches.opt_present("a"),
no_color: matches.opt_present("no-color"),
})
}
}

View file

@ -7,20 +7,22 @@ pub mod args;
use crate::args::Args;
use std::io;
use systeroid_core::config::Config;
use systeroid_core::error::Result;
use systeroid_core::sysctl::Sysctl;
/// Runs `systeroid`.
pub fn run(args: Args) -> Result<()> {
let config = Config::default();
let mut stdout = io::stdout();
let mut sysctl = Sysctl::init()?;
let mut sysctl = Sysctl::init(config.sysctl)?;
if let Some(kernel_docs) = args.kernel_docs {
sysctl.update_docs(&kernel_docs)?;
}
if args.all {
sysctl.print_all(&mut stdout)?;
sysctl.print_all(&mut stdout, !args.no_color)?;
}
Ok(())