use anstyle::{AnsiColor, Style};
use crate::providers::ReviewState;
pub const BRANCH: Style = AnsiColor::Cyan.on_default();
pub const CURRENT: Style = AnsiColor::Green.on_default().bold();
pub const DIM: Style = Style::new().dimmed();
pub const HINT: Style = AnsiColor::Cyan.on_default();
pub const WARN: Style = AnsiColor::Yellow.on_default();
pub const OPEN: Style = AnsiColor::Green.on_default();
pub const MERGED: Style = AnsiColor::Magenta.on_default();
pub const CLOSED: Style = AnsiColor::Red.on_default();
pub fn paint(style: Style, text: &str) -> String {
format!("{style}{text}{style:#}")
}
pub fn branch(name: &str) -> String {
paint(BRANCH, name)
}
pub fn dim(text: &str) -> String {
paint(DIM, text)
}
pub fn success(text: &str) -> String {
paint(OPEN, text)
}
pub fn warn(text: &str) -> String {
paint(WARN, text)
}
pub fn hint_prefix() -> String {
paint(HINT, "hint:")
}
pub fn state(state: &ReviewState) -> String {
let style = match state {
ReviewState::Open => OPEN,
ReviewState::Merged => MERGED,
ReviewState::Closed => CLOSED,
ReviewState::Unknown(_) => DIM,
};
paint(style, &state.to_string())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn paint_wraps_text_in_escape_codes() {
let painted = paint(BRANCH, "feature/a");
assert!(painted.contains("feature/a"));
assert!(painted.starts_with('\u{1b}'));
assert!(painted.ends_with('m'));
}
#[test]
fn state_uses_the_ledger_palette() {
assert!(state(&ReviewState::Open).contains("open"));
assert!(state(&ReviewState::Merged).contains("merged"));
assert!(state(&ReviewState::Closed).contains("closed"));
assert_ne!(
state(&ReviewState::Open),
state(&ReviewState::Merged),
"states should not share a style"
);
}
}