use opseclint_core::Severity;
pub const RED: &str = "\x1b[38;2;247;118;142m"; pub const ORANGE: &str = "\x1b[38;2;255;158;100m"; pub const YELLOW: &str = "\x1b[38;2;224;175;104m"; pub const GREEN: &str = "\x1b[38;2;158;206;106m"; pub const CYAN: &str = "\x1b[38;2;125;207;255m"; pub const BLUE: &str = "\x1b[38;2;122;162;247m"; pub const PURPLE: &str = "\x1b[38;2;187;154;247m"; pub const FG: &str = "\x1b[38;2;192;202;245m"; pub const FG_DIM: &str = "\x1b[38;2;169;177;214m"; pub const COMMENT: &str = "\x1b[38;2;86;95;137m"; pub const RULE: &str = "\x1b[38;2;65;72;104m"; pub const BOLD: &str = "\x1b[1m";
pub const RESET: &str = "\x1b[0m";
pub fn severity_color(severity: Severity) -> &'static str {
match severity {
Severity::Low => CYAN,
Severity::Medium => YELLOW,
Severity::High => ORANGE,
Severity::Critical => RED,
}
}
pub struct Painter {
on: bool,
}
impl Painter {
pub fn new(on: bool) -> Self {
Painter { on }
}
pub fn paint(&self, code: &str, text: &str) -> String {
if self.on {
format!("{code}{text}{RESET}")
} else {
text.to_string()
}
}
pub fn bold(&self, code: &str, text: &str) -> String {
if self.on {
format!("{BOLD}{code}{text}{RESET}")
} else {
text.to_string()
}
}
pub fn rule(&self, width: usize) -> String {
self.paint(RULE, &"─".repeat(width))
}
}
pub fn banner(color: bool) -> String {
let p = Painter::new(color);
let ver = env!("CARGO_PKG_VERSION");
let eye = format!(
"{}{}{}",
p.paint(RED, "◖"),
p.paint(PURPLE, "●"),
p.paint(BLUE, "◗")
);
let mut s = String::new();
s.push('\n');
s.push_str(&format!(
" {} {} {}\n",
eye,
p.bold(FG, "opseclint"),
p.paint(COMMENT, &format!("v{ver} · Ezekiel Labs"))
));
s.push_str(&format!(
" {}\n\n",
p.paint(FG_DIM, "what would a defender see?")
));
s.push_str(&format!(
" {} {}\n",
p.paint(CYAN, "opseclint script.sh"),
p.paint(COMMENT, "· analyze a file, script, or playbook")
));
s.push_str(&format!(
" {} {}\n",
p.paint(CYAN, "opseclint -c '<cmd>'"),
p.paint(COMMENT, "· analyze a single command")
));
s.push_str(&format!(
" {}\n",
p.paint(COMMENT, "opseclint --help · every flag and mode")
));
s
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn banner_is_plain_without_color() {
let b = banner(false);
assert!(b.contains("opseclint"));
assert!(b.contains("what would a defender see?"));
assert!(!b.contains('\x1b'), "no ANSI escapes when color is off");
}
#[test]
fn banner_paints_when_color_on() {
assert!(banner(true).contains('\x1b'));
}
}