use justerm_core::{Engine, SelectionSpan, SelectionType, Side};
fn grid() -> Engine {
let mut e = Engine::new(4, 3);
e.feed(b"abcd\r\nefgh\r\nijkl");
e
}
#[test]
fn an_out_of_range_anchor_column_does_not_delete_the_anchor_row() {
let mut term = grid();
term.selection_begin(0, 80, Side::Left, SelectionType::Char);
term.selection_extend(2, 3, Side::Right);
assert_eq!(term.selection_text().as_deref(), Some("d\nefgh\nijkl"));
assert_eq!(
term.selection_range().first(),
Some(&SelectionSpan {
row: 0,
left: 3,
right: 3
}),
"the anchor row must still be in the projection, starting at the last column"
);
assert_eq!(term.selection_range().len(), 3, "no row may be dropped");
}
#[test]
fn an_out_of_range_focus_column_does_not_select_one_cell_too_many() {
let mut term = grid();
term.selection_begin(0, 0, Side::Left, SelectionType::Char);
term.selection_extend(2, 80, Side::Left);
assert_eq!(term.selection_text().as_deref(), Some("abcd\nefgh\nijk"));
}
#[test]
fn block_range_and_text_agree_on_an_out_of_range_column() {
let mut term = grid();
term.selection_begin(0, 80, Side::Left, SelectionType::Block);
term.selection_extend(2, 81, Side::Right);
assert_eq!(term.selection_text().as_deref(), Some("d\nh\nl"));
assert_eq!(
term.selection_range(),
vec![
SelectionSpan {
row: 0,
left: 3,
right: 3
},
SelectionSpan {
row: 1,
left: 3,
right: 3
},
SelectionSpan {
row: 2,
left: 3,
right: 3
},
]
);
}
#[test]
fn the_largest_column_resolves_instead_of_overflowing() {
for ty in [SelectionType::Char, SelectionType::Block] {
let mut term = grid();
term.selection_begin(0, 0, Side::Left, ty);
term.selection_extend(2, usize::MAX, Side::Right);
assert_eq!(term.selection_text().as_deref(), Some("abcd\nefgh\nijkl"));
assert_eq!(term.selection_range().len(), 3);
}
}
#[test]
fn the_largest_column_resolves_as_an_anchor_too() {
let mut term = grid();
term.selection_begin(2, usize::MAX, Side::Right, SelectionType::Char);
term.selection_extend(0, 0, Side::Left);
assert_eq!(term.selection_text().as_deref(), Some("abcd\nefgh\nijkl"));
}
#[test]
fn side_right_out_of_range_is_unchanged() {
let mut anchor = grid();
anchor.selection_begin(0, 80, Side::Right, SelectionType::Char);
anchor.selection_extend(2, 3, Side::Right);
assert_eq!(anchor.selection_text().as_deref(), Some("efgh\nijkl"));
let mut focus = grid();
focus.selection_begin(0, 0, Side::Left, SelectionType::Char);
focus.selection_extend(2, 80, Side::Right);
assert_eq!(focus.selection_text().as_deref(), Some("abcd\nefgh\nijkl"));
}
#[test]
fn an_in_range_right_edge_anchor_still_starts_on_the_next_row() {
let mut term = grid();
term.selection_begin(0, 3, Side::Right, SelectionType::Char);
term.selection_extend(2, 3, Side::Right);
assert_eq!(term.selection_text().as_deref(), Some("efgh\nijkl"));
assert_eq!(term.selection_range().len(), 2);
}
#[test]
fn the_bound_is_the_grid_width_not_the_line_length() {
let mut term = Engine::new(4, 3);
term.feed(b"ab\r\ncdef");
term.selection_begin(0, 80, Side::Left, SelectionType::Block);
term.selection_extend(1, 80, Side::Right);
assert_eq!(term.selection_text().as_deref(), Some("\nf"));
}
fn a_real_screen_keeps_its_anchor_row(capture: &[u8], label: &str) {
let mut t = Engine::new(80, 24);
t.feed(capture);
assert_eq!(t.grid().cols(), 80, "fixture: {label} is 80 columns wide");
let mut inrange = Engine::new(80, 24);
inrange.feed(capture);
inrange.selection_begin(3, 79, Side::Left, SelectionType::Char);
inrange.selection_extend(5, 79, Side::Right);
let expected = inrange.selection_text();
t.selection_begin(3, 200, Side::Left, SelectionType::Char); t.selection_extend(5, 79, Side::Right);
assert_eq!(
t.selection_text(),
expected,
"{label}: an out-of-range anchor column must resolve to the last column, not \
delete its own row"
);
assert_eq!(
t.selection_range().first().map(|s| s.row),
Some(3),
"{label}: the anchor row must still be in the projection"
);
}
#[test]
fn a_real_vim_screen_keeps_its_anchor_row() {
a_real_screen_keeps_its_anchor_row(include_bytes!("fixtures/alt_resize_vim.pre.raw"), "vim");
}
#[test]
fn a_real_htop_screen_keeps_its_anchor_row() {
a_real_screen_keeps_its_anchor_row(include_bytes!("fixtures/alt_resize_htop.pre.raw"), "htop");
}