T10: find reads the grid as it shows, through Ely's find_all: combining marks, hidden cells blank, wrapped rows joined, Unicode words; new output, a resize and a settings change search again, and the current match follows its line text; a full reset replays the title through set_options
CI / platforms (windows-latest) (push) Failing after 8s
CI / macos (push) Failing after 8m31s
CI / platforms (ubuntu-24.04) (push) Canceled after 0s

This commit is contained in:
ZacharyZhang-NY committed 2026-10-14 16:57:09 -04:00
1 parent 4d8788ff22
commit 1c21dfd197
10 files changed
+335 -103

No files matched your search

+155
View File
@@ -0,0 +1,155 @@
use alacritty_terminal::{
event::VoidListener,
term::{Config, test::TermSize},
vte::ansi::Processor,
};
use super::*;
const PLAIN: FindOptions = FindOptions {
case: false,
word: false,
regex: false,
};
fn term(bytes: &str, columns: usize, lines: usize, history: usize) -> Term<VoidListener> {
let config = Config {
scrolling_history: history,
..Config::default()
};
let mut term = Term::new(config, &TermSize::new(columns, lines), VoidListener);
feed(&mut term, bytes);
term
}
fn feed(term: &mut Term<VoidListener>, bytes: &str) {
let mut parser: Processor = Processor::new();
parser.advance(term, bytes.as_bytes());
}
fn found(term: &Term<VoidListener>, query: &str, options: FindOptions) -> Found {
Found::search(term, query, options).expect("a pattern")
}
fn at(line: i32, column: usize) -> Point {
Point::new(Line(line), Column(column))
}
#[test]
fn find_takes_case_words_and_patterns() {
let term = term("one two One\r\nthree phone one", 20, 3, 10);
let count =
|query: &str, options| Found::search(&term, query, options).map(|found| found.hits.len());
assert_eq!(count("one", PLAIN), Ok(4));
assert_eq!(
count(
"One",
FindOptions {
case: true,
..PLAIN
}
),
Ok(1)
);
let word = FindOptions {
word: true,
..PLAIN
};
assert_eq!(count("one", word), Ok(3), "phone holds no whole word");
let regex = FindOptions {
regex: true,
..PLAIN
};
assert_eq!(count("t[wh]", regex), Ok(2));
assert_eq!(count("one$", regex), Ok(2), "a line ends after its text");
assert_eq!(count("(", PLAIN), Ok(0), "plain text is escaped");
assert!(count("(", regex).is_err());
}
#[test]
fn marks_wide_cells_and_unicode_words_are_found_where_they_show() {
let shown = "cafe\u{301} caf\u{e9} \u{4e2d}\u{6587} \x1b[8msecret\x1b[0m";
let line = term(shown, 30, 2, 10);
let hits = |query: &str, options| found(&line, query, options).hits;
assert_eq!(
hits("cafe\u{301}", PLAIN),
[at(0, 0)..=at(0, 3)],
"a mark rides its cell"
);
let word = FindOptions {
word: true,
..PLAIN
};
assert_eq!(hits("caf\u{e9}", word), [at(0, 5)..=at(0, 8)]);
assert_eq!(hits("\u{4e2d}\u{6587}", word), [at(0, 10)..=at(0, 12)]);
assert!(hits("secret", PLAIN).is_empty(), "hidden text stays hidden");
let after = term("\u{4e2d}x", 10, 2, 10);
let x = found(&after, "x", PLAIN).hits;
assert_eq!(
x,
[at(0, 2)..=at(0, 2)],
"a wide cell's spacer holds no text"
);
}
#[test]
fn a_wrapped_line_is_one_line_mapped_back_to_its_cells() {
let term = term("12345678needle", 10, 3, 10);
assert_eq!(found(&term, "needle", PLAIN).hits, [at(0, 8)..=at(1, 3)]);
let regex = FindOptions {
regex: true,
..PLAIN
};
assert_eq!(found(&term, "needle$", regex).hits.len(), 1);
}
#[test]
fn the_current_match_follows_its_line() {
let mut erased = term("needle OLD\r\nneedle KEEP\r\nneedle LAST", 20, 4, 10);
let then = found(&erased, "needle", PLAIN);
feed(&mut erased, "\x1b[1;1H\x1b[2K");
let now = found(&erased, "needle", PLAIN);
assert_eq!(now.follow(&then, 1), Some(0), "KEEP, though OLD is gone");
let mut ring = term("n 1\r\nn 2\r\nn 3\r\nn 4\r\nn 5", 10, 3, 2);
let then = found(&ring, "n", PLAIN);
feed(&mut ring, "\r\nn 6");
let now = found(&ring, "n", PLAIN);
assert_eq!(
now.follow(&then, 2),
Some(1),
"n 3, a line up, though n 1 left"
);
let mut same = term("n\r\nn\r\nn", 10, 3, 10);
let then = found(&same, "n", PLAIN);
feed(&mut same, "\r\nx\r\nx");
let now = found(&same, "n", PLAIN);
assert_eq!(
now.follow(&then, 1),
Some(1),
"of like lines, the one that scrolled"
);
let mut gone = term("needle A\r\nneedle B\r\n\r\nneedle C", 20, 5, 10);
let then = found(&gone, "needle", PLAIN);
feed(&mut gone, "\x1b[2;1H\x1b[2K");
let now = found(&gone, "needle", PLAIN);
assert_eq!(now.follow(&then, 1), Some(0), "B is gone: A is nearest");
let mut wide = term(&format!("{}needle", "x".repeat(15)), 12, 4, 10);
let then = found(&wide, "needle", PLAIN);
wide.resize(TermSize::new(30, 4));
let now = found(&wide, "needle", PLAIN);
assert_eq!(now.follow(&then, 0), Some(0));
assert_eq!(now.hits[0].start().column, Column(15), "the reflowed cells");
assert_ne!(now.hits[0].start(), then.hits[0].start());
}
#[test]
fn steps_go_round_the_ends() {
assert_eq!(stepped(Some(0), 3, false), Some(2));
assert_eq!(stepped(Some(2), 3, true), Some(0));
assert_eq!(stepped(Some(1), 3, false), Some(0));
assert_eq!(stepped(None, 0, true), None);
}