use hjkl_buffer::{Edit, MotionKind, Position, View};
use hjkl_engine::{DefaultHost, Editor, Options};
fn editor(content: &str) -> Editor<View, DefaultHost> {
let mut e = Editor::new(View::new(), DefaultHost::new(), Options::default());
e.set_content(content);
e
}
fn pos(row: usize, col: usize) -> Position {
Position::new(row, col)
}
fn ten_lines() -> Editor<View, DefaultHost> {
editor("0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n")
}
#[test]
fn insert_above_shifts_fold_down() {
let mut e = ten_lines();
e.buffer_mut().add_fold(4, 6, true);
e.buffer_mut().set_cursor(pos(0, 0));
e.mutate_edit(Edit::InsertStr {
at: pos(0, 0),
text: "x\n".to_string(),
});
let folds = e.buffer().folds();
assert_eq!(folds.len(), 1);
assert_eq!((folds[0].start_row, folds[0].end_row), (5, 7));
}
#[test]
fn delete_above_shifts_fold_up() {
let mut e = ten_lines();
e.buffer_mut().add_fold(4, 6, true);
e.buffer_mut().set_cursor(pos(0, 0));
e.mutate_edit(Edit::DeleteRange {
start: pos(0, 0),
end: pos(0, 0),
kind: MotionKind::Line,
});
let folds = e.buffer().folds();
assert_eq!(folds.len(), 1);
assert_eq!((folds[0].start_row, folds[0].end_row), (3, 5));
}
#[test]
fn delete_overlapping_the_fold_drops_it() {
let mut e = ten_lines();
e.buffer_mut().add_fold(4, 6, true);
e.buffer_mut().set_cursor(pos(4, 0));
e.mutate_edit(Edit::DeleteRange {
start: pos(4, 0),
end: pos(6, 0),
kind: MotionKind::Line,
});
assert!(e.buffer().folds().is_empty());
}
#[test]
fn delete_overlapping_fold_tail_clips_it() {
let mut e = ten_lines();
e.buffer_mut().add_fold(4, 6, true);
e.buffer_mut().set_cursor(pos(6, 0));
e.mutate_edit(Edit::DeleteRange {
start: pos(6, 0),
end: pos(8, 0),
kind: MotionKind::Line,
});
let folds = e.buffer().folds();
assert_eq!(folds.len(), 1);
assert_eq!((folds[0].start_row, folds[0].end_row), (4, 5));
}
#[test]
fn edit_inside_a_fold_grows_its_end() {
let mut e = ten_lines();
e.buffer_mut().add_fold(4, 6, true);
e.buffer_mut().set_cursor(pos(5, 0));
e.mutate_edit(Edit::InsertStr {
at: pos(5, 0),
text: "x\n".to_string(),
});
let folds = e.buffer().folds();
assert_eq!(
folds.len(),
1,
"edit inside a fold must adjust it, not drop it"
);
assert_eq!((folds[0].start_row, folds[0].end_row), (4, 7));
}
#[test]
fn edit_inside_a_fold_shrinks_its_end_on_delete() {
let mut e = ten_lines();
e.buffer_mut().add_fold(4, 8, true);
e.buffer_mut().set_cursor(pos(5, 0));
e.mutate_edit(Edit::DeleteRange {
start: pos(5, 0),
end: pos(6, 0),
kind: MotionKind::Line,
});
let folds = e.buffer().folds();
assert_eq!(folds.len(), 1);
assert_eq!((folds[0].start_row, folds[0].end_row), (4, 6));
}
#[test]
fn fold_well_below_the_edit_is_untouched() {
let mut e = ten_lines();
e.buffer_mut().add_fold(1, 2, true);
e.buffer_mut().set_cursor(pos(8, 0));
e.mutate_edit(Edit::InsertStr {
at: pos(8, 0),
text: "x\n".to_string(),
});
let folds = e.buffer().folds();
assert_eq!(folds.len(), 1);
assert_eq!((folds[0].start_row, folds[0].end_row), (1, 2));
}