use justerm_core::{Engine, TermEvent, Terminator};
fn answer(e: &mut Engine, ev: &TermEvent) {
match *ev {
TermEvent::QueryForeground { terminator } => {
e.report_foreground("rgb:ff/ff/ff", terminator)
}
TermEvent::QueryBackground { terminator } => {
e.report_background("rgb:1e/1e/2e", terminator)
}
TermEvent::QueryCursorColor { terminator } => {
e.report_cursor_color("rgb:ff/00/00", terminator)
}
TermEvent::QueryPaletteColor { index, terminator } => {
e.report_palette_color(index, "rgb:00/00/ff", terminator)
}
TermEvent::QueryClipboard { target, terminator } => {
e.report_clipboard(target, "hi", terminator)
}
ref other => panic!("not a query event: {other:?}"),
}
}
const FAMILIES: &[(&str, &str)] = &[
("\x1b]10;?", "\x1b]10;rgb:ff/ff/ff"),
("\x1b]11;?", "\x1b]11;rgb:1e/1e/2e"),
("\x1b]12;?", "\x1b]12;rgb:ff/00/00"),
("\x1b]4;5;?", "\x1b]4;5;rgb:00/00/ff"),
("\x1b]52;c;?", "\x1b]52;c;aGk="),
];
#[test]
fn a_bel_query_is_answered_bel_in_every_family() {
for (query, body) in FAMILIES {
let mut e = Engine::new(80, 24);
e.feed(format!("{query}\x07").as_bytes());
let events = e.drain_events();
assert_eq!(events.len(), 1, "one query expected for {query:?}");
answer(&mut e, &events[0]);
assert_eq!(
e.drain_replies(),
format!("{body}\x07").as_bytes(),
"BEL query {query:?} must be answered BEL",
);
}
}
#[test]
fn an_st_query_is_answered_st_in_every_family() {
for (query, body) in FAMILIES {
let mut e = Engine::new(80, 24);
e.feed(format!("{query}\x1b\\").as_bytes());
let events = e.drain_events();
assert_eq!(events.len(), 1, "one query expected for {query:?}");
answer(&mut e, &events[0]);
assert_eq!(
e.drain_replies(),
format!("{body}\x1b\\").as_bytes(),
"ST query {query:?} must be answered ST",
);
}
}
#[test]
fn two_outstanding_queries_each_get_their_own_terminator_back() {
let mut e = Engine::new(80, 24);
e.feed(b"\x1b]10;?\x07\x1b]11;?\x1b\\");
let events = e.drain_events();
assert_eq!(
events,
vec![
TermEvent::QueryForeground {
terminator: Terminator::Bel
},
TermEvent::QueryBackground {
terminator: Terminator::St
},
],
"both queries outstanding at once, each carrying what it arrived with"
);
answer(&mut e, &events[1]);
answer(&mut e, &events[0]);
assert_eq!(
e.drain_replies(),
b"\x1b]11;rgb:1e/1e/2e\x1b\\\x1b]10;rgb:ff/ff/ff\x07",
"the ST question gets ST and the BEL question gets BEL, whatever the answer order"
);
}
#[test]
fn every_slot_of_one_stacked_query_carries_that_sequences_terminator() {
let mut e = Engine::new(80, 24);
e.feed(b"\x1b]10;?;?;?\x07");
assert_eq!(
e.drain_events(),
vec![
TermEvent::QueryForeground {
terminator: Terminator::Bel
},
TermEvent::QueryBackground {
terminator: Terminator::Bel
},
TermEvent::QueryCursorColor {
terminator: Terminator::Bel
},
]
);
}
#[test]
fn a_query_ended_without_a_terminator_is_answered_st() {
for (label, stream) in [
("CAN", b"\x1b]11;?\x18".as_slice()),
("SUB", b"\x1b]11;?\x1a".as_slice()),
("bare ESC", b"\x1b]11;?\x1bc".as_slice()),
] {
let mut e = Engine::new(80, 24);
e.feed(stream);
let events = e.drain_events();
assert_eq!(
events,
vec![TermEvent::QueryBackground {
terminator: Terminator::St
}],
"{label}: the query is still relayed, carrying ST"
);
answer(&mut e, &events[0]);
assert_eq!(
e.drain_replies(),
b"\x1b]11;rgb:1e/1e/2e\x1b\\",
"{label}: answered ST"
);
}
}
#[test]
fn the_default_terminator_is_st() {
assert_eq!(Terminator::default(), Terminator::St);
let mut e = Engine::new(80, 24);
e.report_background("rgb:1e/1e/2e", Terminator::default());
assert_eq!(e.drain_replies(), b"\x1b]11;rgb:1e/1e/2e\x1b\\");
}