use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(tag = "type", content = "data")]
pub enum RenderItem {
Text(String),
Icon(String),
Foreground(Color),
ForegroundAnsi(AnsiColor),
Background(Color),
BackgroundAnsi(AnsiColor),
Bold,
Italic,
Underline(UnderlineStyle),
Strikethrough,
ResetAttributes,
ResetForeground,
ResetBackground,
Spacer,
Padding(u8),
Separator(String),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(tag = "type", content = "value")]
pub enum Color {
Rgb(u8, u8, u8),
Hex(String),
Named(String),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AnsiColor {
Black,
Red,
Green,
Yellow,
Blue,
Magenta,
Cyan,
White,
BrightBlack,
BrightRed,
BrightGreen,
BrightYellow,
BrightBlue,
BrightMagenta,
BrightCyan,
BrightWhite,
}
impl AnsiColor {
pub fn to_rgb(&self) -> (u8, u8, u8) {
match self {
AnsiColor::Black => (0, 0, 0),
AnsiColor::Red => (128, 0, 0),
AnsiColor::Green => (0, 128, 0),
AnsiColor::Yellow => (128, 128, 0),
AnsiColor::Blue => (0, 0, 128),
AnsiColor::Magenta => (128, 0, 128),
AnsiColor::Cyan => (0, 128, 128),
AnsiColor::White => (192, 192, 192),
AnsiColor::BrightBlack => (128, 128, 128),
AnsiColor::BrightRed => (255, 0, 0),
AnsiColor::BrightGreen => (0, 255, 0),
AnsiColor::BrightYellow => (255, 255, 0),
AnsiColor::BrightBlue => (0, 0, 255),
AnsiColor::BrightMagenta => (255, 0, 255),
AnsiColor::BrightCyan => (0, 255, 255),
AnsiColor::BrightWhite => (255, 255, 255),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum UnderlineStyle {
Single,
Double,
Curly,
Dotted,
Dashed,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum StatusBarSide {
Left,
Right,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct StatusBarUpdate {
pub window_id: u64,
pub side: StatusBarSide,
pub items: Vec<RenderItem>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ansi_color_to_rgb() {
assert_eq!(AnsiColor::Black.to_rgb(), (0, 0, 0));
assert_eq!(AnsiColor::Red.to_rgb(), (128, 0, 0));
assert_eq!(AnsiColor::BrightRed.to_rgb(), (255, 0, 0));
assert_eq!(AnsiColor::BrightWhite.to_rgb(), (255, 255, 255));
}
#[test]
fn test_render_item_serialization() {
let item = RenderItem::Text("Hello".to_string());
let json = serde_json::to_string(&item).unwrap();
let deserialized: RenderItem = serde_json::from_str(&json).unwrap();
match deserialized {
RenderItem::Text(s) => assert_eq!(s, "Hello"),
_ => panic!("Expected Text variant"),
}
}
#[test]
fn test_color_serialization() {
let color = Color::Rgb(255, 128, 64);
let json = serde_json::to_string(&color).unwrap();
let deserialized: Color = serde_json::from_str(&json).unwrap();
match deserialized {
Color::Rgb(r, g, b) => {
assert_eq!(r, 255);
assert_eq!(g, 128);
assert_eq!(b, 64);
}
_ => panic!("Expected Rgb variant"),
}
}
#[test]
fn test_status_bar_update() {
let update = StatusBarUpdate {
window_id: 42,
side: StatusBarSide::Left,
items: vec![RenderItem::Bold, RenderItem::Text("Test".to_string())],
};
assert_eq!(update.window_id, 42);
assert_eq!(update.items.len(), 2);
}
#[test]
fn test_complex_status_bar_styling() {
let items = vec![
RenderItem::Foreground(Color::Hex("#7aa2f7".to_string())),
RenderItem::Text("~/project".to_string()),
RenderItem::ResetForeground,
RenderItem::Separator(" | ".to_string()),
RenderItem::Bold,
RenderItem::Foreground(Color::Named("green".to_string())),
RenderItem::Text("100%".to_string()),
RenderItem::ResetAttributes,
];
assert_eq!(items.len(), 8);
match &items[0] {
RenderItem::Foreground(Color::Hex(s)) => assert_eq!(s, "#7aa2f7"),
_ => panic!("Expected Foreground item"),
}
}
}