tastty-core 0.1.0

Sans-IO core of the tastty terminal session library: VT parser, screen buffer, and byte encoders.
use super::*;

#[test]
fn mouse_mode_flags() {
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    assert!(!parser.screen().mode(TerminalMode::MouseReportClick));
    assert!(!parser.screen().mode(TerminalMode::SgrMouse));
    process(&mut parser, b"\x1b[?1000h\x1b[?1006h");
    assert!(parser.screen().mode(TerminalMode::MouseReportClick));
    assert!(parser.screen().mode(TerminalMode::SgrMouse));
    process(&mut parser, b"\x1b[?1000l");
    assert!(!parser.screen().mode(TerminalMode::MouseReportClick));
    assert!(
        parser.screen().mode(TerminalMode::SgrMouse),
        "disabling mode 1000 should not also clear the independent SGR mouse mode 1006",
    );
}

#[test]
fn decset_alt_scroll_set_and_clear() {
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    assert!(!parser.screen().mode(TerminalMode::AlternateScroll));

    process(&mut parser, b"\x1b[?1007h");
    assert!(parser.screen().mode(TerminalMode::AlternateScroll));

    process(&mut parser, b"\x1b[?1007l");
    assert!(!parser.screen().mode(TerminalMode::AlternateScroll));
}

#[test]
fn decset_alt_scroll_emits_mode_changed() {
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    parser.screen_mut().drain_events();

    process(&mut parser, b"\x1b[?1007h");
    let events = parser.screen_mut().drain_events();
    assert!(
        events.contains(&ScreenEvent::ModeChanged {
            mode: TerminalMode::AlternateScroll,
            enabled: true,
        }),
        "DECSET 1007 must emit ModeChanged{{AlternateScroll, true}}; got {events:?}",
    );

    process(&mut parser, b"\x1b[?1007l");
    let events = parser.screen_mut().drain_events();
    assert!(
        events.contains(&ScreenEvent::ModeChanged {
            mode: TerminalMode::AlternateScroll,
            enabled: false,
        }),
        "DECRST 1007 must emit ModeChanged{{AlternateScroll, false}}; got {events:?}",
    );
}

#[test]
fn decset_alt_scroll_idempotent_no_event() {
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    process(&mut parser, b"\x1b[?1007h");
    parser.screen_mut().drain_events();

    process(&mut parser, b"\x1b[?1007h");
    let events = parser.screen_mut().drain_events();
    assert!(
        !events.iter().any(|e| matches!(
            e,
            ScreenEvent::ModeChanged {
                mode: TerminalMode::AlternateScroll,
                ..
            }
        )),
        "redundant DECSET 1007 must not emit a ModeChanged event; got {events:?}",
    );
}

#[test]
fn decset_x10_mouse_set_and_clear() {
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    assert!(!parser.screen().mode(TerminalMode::MouseReportX10));

    process(&mut parser, b"\x1b[?9h");
    assert!(parser.screen().mode(TerminalMode::MouseReportX10));

    process(&mut parser, b"\x1b[?9l");
    assert!(!parser.screen().mode(TerminalMode::MouseReportX10));
}

#[test]
fn decset_x10_mouse_emits_mode_changed() {
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    parser.screen_mut().drain_events();

    process(&mut parser, b"\x1b[?9h");
    let events = parser.screen_mut().drain_events();
    assert!(
        events.contains(&ScreenEvent::ModeChanged {
            mode: TerminalMode::MouseReportX10,
            enabled: true,
        }),
        "DECSET 9 must emit ModeChanged{{MouseReportX10, true}}; got {events:?}",
    );

    process(&mut parser, b"\x1b[?9l");
    let events = parser.screen_mut().drain_events();
    assert!(
        events.contains(&ScreenEvent::ModeChanged {
            mode: TerminalMode::MouseReportX10,
            enabled: false,
        }),
        "DECRST 9 must emit ModeChanged{{MouseReportX10, false}}; got {events:?}",
    );
}

#[test]
fn decset_x10_mouse_idempotent_no_event() {
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    process(&mut parser, b"\x1b[?9h");
    parser.screen_mut().drain_events();

    process(&mut parser, b"\x1b[?9h");
    let events = parser.screen_mut().drain_events();
    assert!(
        !events.iter().any(|e| matches!(
            e,
            ScreenEvent::ModeChanged {
                mode: TerminalMode::MouseReportX10,
                ..
            }
        )),
        "redundant DECSET 9 must not emit a ModeChanged event; got {events:?}",
    );
}