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 decrqss_sgr_default() {
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    // Query current SGR with default attrs
    process(&mut parser, b"\x1bP$qm\x1b\\");
    assert_eq!(drain_replies(&mut parser), b"\x1bP1$r0m\x1b\\");
}

#[test]
fn decrqss_sgr_bold() {
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    process(&mut parser, b"\x1b[1m\x1bP$qm\x1b\\");
    assert_eq!(drain_replies(&mut parser), b"\x1bP1$r1m\x1b\\");
}

#[test]
fn decrqss_sgr_combined() {
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    // Set bold + italic + red fg
    process(&mut parser, b"\x1b[1;3;31m\x1bP$qm\x1b\\");
    assert_eq!(drain_replies(&mut parser), b"\x1bP1$r1;3;31m\x1b\\");
}

#[test]
fn decrqss_sgr_curly_underline() {
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    process(&mut parser, b"\x1b[4:3m\x1bP$qm\x1b\\");
    assert_eq!(drain_replies(&mut parser), b"\x1bP1$r4:3m\x1b\\");
}

#[test]
fn decrqss_sgr_underline_color() {
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    process(&mut parser, b"\x1b[4m\x1b[58;2;255;0;0m\x1bP$qm\x1b\\");
    assert_eq!(drain_replies(&mut parser), b"\x1bP1$r4;58;2;255;0;0m\x1b\\");
}

#[test]
fn decrqss_sgr_underline_color_with_colorspace() {
    // Scoutty's exact probe: set underline color via 58:2::170:170:170, then DECRQSS
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    process(&mut parser, b"\x1b[58:2::170:170:170m\x1bP$qm\x1b\\\x1b[0m");
    let resp = String::from_utf8(drain_replies(&mut parser)).unwrap();
    assert!(
        resp.contains("170"),
        "DECRQSS response should contain underline color value '170', got: {resp:?}"
    );
}

#[test]
fn decrqss_sgr_overline_and_blink() {
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    process(&mut parser, b"\x1b[53;5m\x1bP$qm\x1b\\");
    assert_eq!(drain_replies(&mut parser), b"\x1bP1$r5;53m\x1b\\");
}

#[test]
fn decrqss_cursor_style() {
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    // Set blinking bar (5)
    process(&mut parser, b"\x1b[5 q\x1bP$q q\x1b\\");
    assert_eq!(drain_replies(&mut parser), b"\x1bP1$r5 q\x1b\\");
}

#[test]
fn decrqss_cursor_style_default() {
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    process(&mut parser, b"\x1bP$q q\x1b\\");
    assert_eq!(drain_replies(&mut parser), b"\x1bP1$r0 q\x1b\\");
}

#[test]
fn decrqss_unknown_query() {
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    // Query something we don't recognize
    process(&mut parser, b"\x1bP$qx\x1b\\");
    assert_eq!(drain_replies(&mut parser), b"\x1bP0$r\x1b\\");
}

#[test]
fn decrqss_split_across_process_calls() {
    // DCS sequence split across two process() calls. The DCS state
    // must persist in Screen, not in the ephemeral PerformScreen.
    let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
    process(&mut parser, b"\x1b[1m"); // set bold
    // Split the DCS $ q m ST across two calls
    process(&mut parser, b"\x1bP$q"); // DCS hook + partial query
    process(&mut parser, b"m\x1b\\"); // rest of query + ST
    assert_eq!(drain_replies(&mut parser), b"\x1bP1$r1m\x1b\\");
}