use super::Editor;
impl Editor {
pub(crate) fn push_jump(&mut self) {
if self.buffers.is_empty() {
return;
}
let pos = (self.current, self.cursor);
if self.jumplist_past.last() != Some(&pos) {
self.jumplist_past.push(pos);
}
self.jumplist_future.clear(); }
pub(crate) fn jump_back(&mut self) {
if self.jumplist_past.is_empty() {
self.message = "no jumps".into();
return;
}
self.jumplist_future.push((self.current, self.cursor));
let pos = self.jumplist_past.pop().unwrap_or((0, 0));
self.jump_to(pos);
}
pub(crate) fn jump_forward(&mut self) {
let Some(pos) = self.jumplist_future.pop() else {
self.message = "at newest jump".into();
return;
};
self.jumplist_past.push((self.current, self.cursor));
self.jump_to(pos);
}
fn jump_to(&mut self, (buffer, offset): (usize, usize)) {
if buffer >= self.buffers.len() {
return; }
if buffer != self.current {
self.current = buffer;
self.touch_mru(buffer);
self.discover_git();
}
self.cursor = self
.buf()
.clamp_boundary(offset.min(self.buf().len_bytes()));
self.clamp_cursor();
self.flash(strop_core::Range::charwise(self.cursor, self.cursor));
}
}
#[cfg(test)]
mod tests {
use super::*;
use strop_core::Buffer;
#[test]
fn jumplist_walks_back_and_forward_across_buffers() {
let mut e = Editor::new(Buffer::from_text("one\ntwo\nthree\n"));
e.feed_text("j"); e.push_jump();
e.feed_text("G"); assert_eq!(e.buf().line_of(e.cursor), 2);
e.jump_back();
assert_eq!(e.buf().line_of(e.cursor), 1, "ctrl-o back to line 2");
e.jump_forward();
assert_eq!(e.buf().line_of(e.cursor), 2, "ctrl-i forward again");
}
#[test]
fn new_jump_truncates_the_forward_path() {
let mut e = Editor::new(Buffer::from_text("a\nb\nc\nd\n"));
e.push_jump();
e.feed_text("jj");
e.push_jump();
e.feed_text("j"); e.jump_back(); e.push_jump();
e.feed_text("k"); assert!(e.jumplist_future.is_empty());
e.jump_forward();
assert!(e.message.contains("newest"));
}
#[test]
fn search_then_ctrl_o_ctrl_i() {
let mut e = Editor::new(Buffer::from_text("one\ntwo hone\nthree\n"));
e.feed_text("/hone\r");
assert_eq!(e.buf().line_of(e.cursor), 1, "landed on the match");
e.feed(crate::editor::Key::CtrlO);
assert_eq!(e.buf().line_of(e.cursor), 0, "ctrl-o back to the top");
e.feed(crate::editor::Key::Tab); assert_eq!(e.buf().line_of(e.cursor), 1, "ctrl-i forward again");
}
#[test]
fn search_lands_with_jump_recorded() {
let mut e = Editor::new(Buffer::from_text("one\ntwo hone\nthree\n"));
e.feed_text("/hone\r");
assert_eq!(e.buf().line_of(e.cursor), 1, "landed on the match");
assert_eq!(e.jumplist_past.len(), 1, "the jump was recorded");
}
}