use super::Editor;
impl Editor {
pub(crate) fn push_jump(&mut self) {
if self.docs.is_empty() {
return;
}
let pos = (self.current(), self.head());
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.head()));
let Some(pos) = self.jumplist_past.pop() else {
self.jumplist_future.pop();
self.message = "no jumps".into();
return;
};
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.head()));
self.jump_to(pos);
}
fn jump_to(&mut self, (buffer, offset): (strop_core::id::DocumentId, usize)) {
if self.docs.get(buffer).is_none() {
return; }
if buffer != self.current() {
self.switch_to(buffer);
self.discover_git();
}
self.set_head(
self.buf()
.clamp_boundary(offset.min(self.buf().len_bytes())),
);
self.clamp_cursor();
self.flash(strop_core::Range::charwise(self.head(), self.head()));
}
}
#[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.head()), 2);
e.jump_back();
assert_eq!(e.buf().line_of(e.head()), 1, "ctrl-o back to line 2");
e.jump_forward();
assert_eq!(e.buf().line_of(e.head()), 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.head()), 1, "landed on the match");
e.feed(crate::editor::Key::CtrlO);
assert_eq!(e.buf().line_of(e.head()), 0, "ctrl-o back to the top");
e.feed(crate::editor::Key::Tab); assert_eq!(e.buf().line_of(e.head()), 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.head()), 1, "landed on the match");
assert_eq!(e.jumplist_past.len(), 1, "the jump was recorded");
}
}