use tess::line_index::LineIndex;
use tess::render::Cell;
use tess::source::{MockSource, Source};
use tess::viewport::{CaseMode, Viewport};
fn grep_source() -> MockSource {
let s = MockSource::new();
s.append(b"DROP a\n");
s.append(b"KEEP one\n");
s.append(b"DROP b\n");
let mut long = b"KEEP".to_vec();
long.extend_from_slice(&[b'x'; 52]);
long.extend_from_slice(b"END");
long.push(b'\n');
s.append(&long);
s.finish();
s
}
fn hide_viewport(cols: u16, rows: u16) -> Viewport {
let mut v = Viewport::new(cols, rows, "mock".to_string());
v.set_grep(Some(
tess::grep::GrepPredicate::compile(&["^KEEP".to_string()], CaseMode::Sensitive).unwrap(),
));
v
}
fn body_text(viewport: &mut Viewport, src: &dyn Source) -> Vec<String> {
let mut idx = LineIndex::new();
let frame = viewport.frame(src, &mut idx);
frame
.body
.iter()
.map(|row| {
let mut s = String::new();
for c in row {
match c {
Cell::Char { ch, .. } => s.push(*ch),
Cell::Continuation => {}
Cell::Empty => s.push(' '),
}
}
s.trim_end().to_string()
})
.collect()
}
#[test]
fn hide_goto_bottom_shows_tail_of_tall_matching_line() {
let src = grep_source();
let mut idx = LineIndex::new();
let mut v = hide_viewport(10, 4); idx.notice_new_bytes(&src);
v.extend_visible_lines(&idx, &src);
v.goto_bottom(&src, &mut idx);
let body = body_text(&mut v, &src);
assert_eq!(
body.last().unwrap(),
"xxxxxxEND",
"goto_bottom must anchor the matching line's END at the bottom, got {body:?}"
);
assert!(v.is_at_bottom(&src, &idx));
}
#[test]
fn hide_scroll_walks_wrap_rows_then_clamps() {
let src = grep_source();
let mut idx = LineIndex::new();
let mut v = hide_viewport(10, 4); idx.notice_new_bytes(&src);
v.extend_visible_lines(&idx, &src);
v.scroll_lines(1, &src, &mut idx); let b1 = body_text(&mut v, &src);
assert_eq!(b1[0], "KEEPxxxxxx", "first row should be the long match's row 0");
v.scroll_lines(100, &src, &mut idx);
let b2 = body_text(&mut v, &src);
assert_eq!(b2.last().unwrap(), "xxxxxxEND");
assert!(v.is_at_bottom(&src, &idx));
let before = b2.clone();
v.scroll_lines(5, &src, &mut idx);
assert_eq!(body_text(&mut v, &src), before, "must not scroll past the bottom");
}
#[test]
fn hide_scroll_up_snaps_within_wraps() {
let src = grep_source();
let mut idx = LineIndex::new();
let mut v = hide_viewport(10, 4); idx.notice_new_bytes(&src);
v.extend_visible_lines(&idx, &src);
v.goto_bottom(&src, &mut idx); let bottom = body_text(&mut v, &src);
v.scroll_lines(-1, &src, &mut idx);
let up = body_text(&mut v, &src);
assert_ne!(up, bottom, "scrolling up one row must change the view");
assert!(!v.is_at_bottom(&src, &idx), "after scrolling up we are no longer at the bottom");
}