const REPORTS: u16 = 1004;
const GAINED: &[u8] = b"\x1b[I";
const LOST: &[u8] = b"\x1b[O";
#[derive(Debug, Default)]
pub(crate) struct Focus {
reporting: bool,
}
impl Focus {
pub(crate) fn report(&self, gained: bool) -> Option<&'static [u8]> {
self.reporting.then_some(if gained { GAINED } else { LOST })
}
pub(crate) fn reporting(&self) -> bool {
self.reporting
}
pub(crate) fn csi(&mut self, marker: Option<u8>, params: &[&[u16]], end: char) {
if marker != Some(b'?') || !matches!(end, 'h' | 'l') {
return;
}
if params.iter().any(|param| param.first() == Some(&REPORTS)) {
self.reporting = end == 'h';
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn nothing_is_reported_until_a_program_asks() {
let focus = Focus::default();
assert_eq!(focus.report(true), None);
assert_eq!(focus.report(false), None);
}
#[test]
fn the_mode_says_which_way_the_focus_went() {
let mut focus = Focus::default();
focus.csi(Some(b'?'), &[&[REPORTS]], 'h');
assert_eq!(focus.report(true), Some(&b"\x1b[I"[..]));
assert_eq!(focus.report(false), Some(&b"\x1b[O"[..]));
focus.csi(Some(b'?'), &[&[REPORTS]], 'l');
assert_eq!(focus.report(true), None, "and off again");
}
#[test]
fn the_mode_is_found_among_the_others_of_one_sequence() {
let mut focus = Focus::default();
focus.csi(Some(b'?'), &[&[1], &[REPORTS], &[1049]], 'h');
assert_eq!(focus.report(true), Some(&b"\x1b[I"[..]));
focus.csi(Some(b'?'), &[&[1], &[1049]], 'l');
assert_eq!(focus.report(true), Some(&b"\x1b[I"[..]), "a sequence without it leaves it alone");
focus.csi(Some(b'?'), &[&[1], &[REPORTS], &[1049]], 'l');
assert_eq!(focus.report(true), None, "and naming it in the same sequence turns it off");
}
#[test]
fn other_sequences_are_left_alone() {
let reports: &[&[u16]] = &[&[REPORTS]];
let mouse: &[&[u16]] = &[&[1002]];
let empty: &[&[u16]] = &[&[]];
let mut focus = Focus::default();
let others = [
(None, reports, 'h'),
(Some(b'>'), reports, 'h'),
(Some(b'?'), reports, 'u'),
(Some(b'?'), mouse, 'h'),
(Some(b'?'), empty, 'h'),
];
for (marker, params, end) in others {
focus.csi(marker, params, end);
assert_eq!(focus.report(true), None, "{marker:?} {params:?} {end}");
}
}
}