use crate::mode::Mode;
use crate::privmode::PrivateMode;
use crate::color::Color;
use crate::sgr::SGR;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum CSI<'a> {
CUU(u16),
CUD(u16),
CUF(u16),
CUB(u16),
CNL(u16),
CPL(u16),
CHA(u16),
CUP(u16, u16),
ED(u16),
EL(u16),
#[allow(dead_code)]
SM(Mode),
#[allow(dead_code)]
RM(Mode),
#[allow(dead_code)]
PSM(PrivateMode),
#[allow(dead_code)]
PRM(PrivateMode),
SGR(&'a [SGR]),
LxULColor(Color),
LxDimColor(Color),
LxDefColor,
LxScreenBlankTimeout(u16),
LxBellFrequency(u16),
LxBellDuration(u16),
LxActivateConsole(u8),
LxUnblankScreen,
LxVESAPowerdownInterval(u16),
LxActivatePreviousConsole,
LxSetCursorBlinkInterval(u16),
}
fn csi(attr: &[u16], ch: char) -> String {
format!("\x1b[{}{}", attr.iter().map(|a| a.to_string()).collect::<Vec<_>>().join(";"), ch)
}
fn decpm(p: u16, ch: char) -> String {
format!("\x1b[?{}{}", p, ch)
}
fn sgr(attr: &[SGR]) -> Vec<u16> {
attr.iter()
.flat_map::<Vec<u16>, _>(|a| (*a).into())
.collect()
}
impl<'a> std::fmt::Display for CSI<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", match *self {
CSI::CUU(n) => csi(&[n], 'A'),
CSI::CUD(n) => csi(&[n], 'B'),
CSI::CUF(n) => csi(&[n], 'C'),
CSI::CUB(n) => csi(&[n], 'D'),
CSI::CNL(n) => csi(&[n], 'E'),
CSI::CPL(n) => csi(&[n], 'F'),
CSI::CHA(n) => csi(&[n], 'G'),
CSI::CUP(r, c) => csi(&[r, c], 'H'),
CSI::ED(m) if m <= 3 => csi(&[m], 'J'),
CSI::ED(x) => panic!("illegal ED mode {}", x),
CSI::EL(m) if m <= 2 => csi(&[m], 'K'),
CSI::EL(x) => panic!("illegal EL mode {}", x),
CSI::SM(m) => csi(&[m.into()], 'h'),
CSI::RM(m) => csi(&[m.into()], 'l'),
CSI::PSM(m) => decpm(m.into(), 'h'),
CSI::PRM(m) => decpm(m.into(), 'l'),
CSI::SGR(attr) => csi(&sgr(attr), 'm'),
CSI::LxULColor(c) => csi(&[1, c.into()], ']'),
CSI::LxDimColor(c) => csi(&[2, c.into()], ']'),
CSI::LxDefColor => csi(&[8], ']'),
CSI::LxScreenBlankTimeout(n) => csi(&[9, n], ']'),
CSI::LxBellFrequency(n) => csi(&[10, n], ']'),
CSI::LxBellDuration(t) => csi(&[11, t], ']'),
CSI::LxActivateConsole(n) => csi(&[12, n as u16], ']'),
CSI::LxUnblankScreen => csi(&[13], ']'),
CSI::LxVESAPowerdownInterval(n) => csi(&[14, n], ']'),
CSI::LxActivatePreviousConsole => csi(&[15], ']'),
CSI::LxSetCursorBlinkInterval(n) => csi(&[16, n], ']'),
})
}
}
#[cfg(test)]
mod test {
use super::CSI;
use crate::sgr::SGR;
use crate::color::Color;
#[test]
fn test_eq() {
let a = CSI::CUU(3);
let b = CSI::CUU(3);
assert!(a == b);
}
#[test]
fn test_neq() {
let a = CSI::CUU(3);
let b = CSI::CUD(3);
assert!(a != b);
}
#[test]
fn test_clone() {
let a = CSI::CUU(3);
let b = a.clone();
assert!(a == b);
}
#[test]
fn test_copy() {
let a = CSI::SGR(&[SGR::FG(Color::Red)]);
let b = a;
assert!(a == b);
}
}