use super::*;
#[test]
fn mode_2027_set_reset_query() {
let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
process(&mut parser, b"\x1b[?2027$p");
assert_eq!(
drain_replies(&mut parser),
b"\x1b[?2027;2$y",
"mode 2027 must report 'reset' (state 2) before any explicit set",
);
process(&mut parser, b"\x1b[?2027h");
process(&mut parser, b"\x1b[?2027$p");
assert_eq!(
drain_replies(&mut parser),
b"\x1b[?2027;1$y",
"after DECSET 2027 the DECRQM reply must report 'set' (state 1)",
);
process(&mut parser, b"\x1b[?2027l");
process(&mut parser, b"\x1b[?2027$p");
assert_eq!(
drain_replies(&mut parser),
b"\x1b[?2027;2$y",
"after DECRST 2027 the DECRQM reply must report 'reset' (state 2)",
);
}
#[test]
fn mode_2027_reset_by_ris() {
let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
process(&mut parser, b"\x1b[?2027h");
process(&mut parser, b"\x1bc"); process(&mut parser, b"\x1b[?2027$p");
assert_eq!(drain_replies(&mut parser), b"\x1b[?2027;2$y");
}
#[test]
fn grapheme_combining_accent() {
let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
process(&mut parser, b"\x1b[?2027h");
process(&mut parser, "e\u{0301}X".as_bytes());
let screen = parser.screen();
assert_eq!(screen.cell(0, 0).unwrap().contents(), "e\u{0301}");
assert!(!screen.cell(0, 0).unwrap().is_wide());
assert_eq!(screen.cell(0, 1).unwrap().contents(), "X");
assert_eq!(screen.cursor(), Position { row: 0, col: 2 });
}
#[test]
fn grapheme_zwj_family_emoji() {
let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
process(&mut parser, b"\x1b[?2027h");
let family = "\u{1F468}\u{200D}\u{1F469}\u{200D}\u{1F467}\u{200D}\u{1F466}";
process(&mut parser, format!("{family}X").as_bytes());
let screen = parser.screen();
let c0 = screen.cell(0, 0).unwrap();
assert!(c0.is_wide(), "ZWJ family should be wide");
assert!(
screen.cell(0, 1).unwrap().is_wide_continuation(),
"col 1 should be continuation"
);
assert_eq!(screen.cell(0, 2).unwrap().contents(), "X");
}
#[test]
fn grapheme_vs16_emoji() {
let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
process(&mut parser, b"\x1b[?2027h");
process(&mut parser, "\u{2603}\u{FE0F}X".as_bytes());
let screen = parser.screen();
let c0 = screen.cell(0, 0).unwrap();
assert!(c0.is_wide(), "snowman+VS16 should be wide");
assert!(c0.contents().contains('\u{FE0F}'));
assert!(screen.cell(0, 1).unwrap().is_wide_continuation());
assert_eq!(screen.cell(0, 2).unwrap().contents(), "X");
}
#[test]
fn grapheme_vs15_text_presentation() {
let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
process(&mut parser, b"\x1b[?2027h");
process(&mut parser, "\u{2603}\u{FE0E}X".as_bytes());
let screen = parser.screen();
let c0 = screen.cell(0, 0).unwrap();
assert!(!c0.is_wide(), "snowman+VS15 should NOT be wide");
assert_eq!(screen.cell(0, 1).unwrap().contents(), "X");
}
#[test]
fn grapheme_flag_emoji() {
let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
process(&mut parser, b"\x1b[?2027h");
process(&mut parser, "\u{1F1E9}\u{1F1EA}X".as_bytes());
let screen = parser.screen();
let c0 = screen.cell(0, 0).unwrap();
assert!(c0.is_wide(), "flag emoji should be wide");
assert!(screen.cell(0, 1).unwrap().is_wide_continuation());
assert_eq!(screen.cell(0, 2).unwrap().contents(), "X");
}
#[test]
fn grapheme_skin_tone() {
let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
process(&mut parser, b"\x1b[?2027h");
process(&mut parser, "\u{1F44B}\u{1F3FD}X".as_bytes());
let screen = parser.screen();
let c0 = screen.cell(0, 0).unwrap();
assert!(c0.is_wide(), "skin-toned wave should be wide");
assert!(screen.cell(0, 1).unwrap().is_wide_continuation());
assert_eq!(screen.cell(0, 2).unwrap().contents(), "X");
}
#[test]
fn grapheme_mode_off_no_regression() {
let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
process(&mut parser, "Hi".as_bytes());
let screen = parser.screen();
assert_eq!(screen.cell(0, 0).unwrap().contents(), "H");
assert_eq!(screen.cell(0, 1).unwrap().contents(), "i");
assert_eq!(screen.cursor(), Position { row: 0, col: 2 });
}
#[test]
fn grapheme_flush_on_control() {
let mut parser = crate::Parser::new(TerminalSize { rows: 24, cols: 80 }, 0);
process(&mut parser, b"\x1b[?2027h");
process(&mut parser, b"AB\rX");
let screen = parser.screen();
assert_eq!(screen.cell(0, 0).unwrap().contents(), "X");
assert_eq!(screen.cell(0, 1).unwrap().contents(), "B");
}