diff --git a/src/main.rs b/src/main.rs index 57aa177..54fe7ce 100644 --- a/src/main.rs +++ b/src/main.rs @@ -95,6 +95,9 @@ pub struct Bk<'a> { line: usize, mark: HashMap, links: HashMap, + //Link + return_stack: Vec<(usize, usize)>, + stack_pointer: usize, // layout colors: Colors, cols: u16, @@ -137,6 +140,8 @@ impl Bk<'_> { line: 0, mark: HashMap::new(), links: epub.links, + return_stack: Vec::new(), + stack_pointer: 0, colors: args.colors, cols, rows: rows as usize, @@ -150,7 +155,7 @@ impl Bk<'_> { bk.jump_byte(args.chapter, args.byte); bk.mark('\''); - + bk.save_jump(); bk } fn run(&mut self) -> io::Result<()> { @@ -231,10 +236,31 @@ impl Bk<'_> { Err(n) => n - 1, } } - fn jump_reset(&mut self) { - let &(c, l) = self.mark.get(&'\'').unwrap(); - self.chapter = c; - self.line = l; + fn jump_forward(&mut self) { + if self.stack_pointer + 1 < self.return_stack.len() { + self.stack_pointer += 1; + let to = self.return_stack.get(self.stack_pointer).expect("Error: Stack pointer moving forward"); + self.jump(*to); + } + } + fn jump_back(&mut self) { + if self.stack_pointer > 0 { + if self.stack_pointer == self.return_stack.len(){ + self.save_jump(); + } + self.stack_pointer -= 1; + let to = self.return_stack.get(self.stack_pointer).expect("Error: Stack Pointer moving backward"); + self.jump(*to); + } + } + fn save_jump(&mut self) { + self.return_stack.truncate(self.stack_pointer); + let bookmark = (self.chapter, self.line); + // if the stack top is different from + if self.return_stack.is_empty() || self.return_stack[self.stack_pointer - 1] != bookmark { + self.stack_pointer += 1; + self.return_stack.push(bookmark); + } } fn mark(&mut self, c: char) { self.mark.insert(c, (self.chapter, self.line)); diff --git a/src/view.rs b/src/view.rs index 8194132..f08cb4b 100644 --- a/src/view.rs +++ b/src/view.rs @@ -100,6 +100,8 @@ PageDown Right Space f l Page Down N Repeat search backward mx Set mark x 'x Jump to mark x + Backspace Undo one jump back. + Enter Redo one jump. "#; text.lines().map(String::from).collect() @@ -143,7 +145,7 @@ impl View for Toc { fn on_key(&self, bk: &mut Bk, kc: KeyCode) { match kc { Esc | Tab | Left | Char('h' | 'q') => { - bk.jump_reset(); + bk.jump_back(); bk.cursor = 0; bk.view = &Page; } @@ -245,11 +247,19 @@ impl Page { let url = &c.links[i].2; let &(c, byte) = bk.links.get(url).unwrap(); bk.mark('\''); + bk.save_jump(); bk.jump_byte(c, byte); } } + fn undo_click(&self, bk: &mut Bk){ + bk.jump_back(); + } + fn redo_click(&self, bk: &mut Bk){ + bk.jump_forward(); + } fn start_search(&self, bk: &mut Bk, dir: Direction) { bk.mark('\''); + bk.save_jump(); bk.query.clear(); bk.dir = dir; bk.view = &Search; @@ -269,6 +279,7 @@ impl View for Page { Esc | Char('q') => bk.quit = true, Tab => { bk.mark('\''); + bk.save_jump(); Toc.cursor(bk); bk.view = &Toc; } @@ -292,10 +303,12 @@ impl View for Page { } End | Char('G') => { bk.mark('\''); + bk.save_jump(); bk.line = bk.chapters[bk.chapter].lines.len().saturating_sub(bk.rows); } Home | Char('g') => { bk.mark('\''); + bk.save_jump(); bk.line = 0; } Char('d') => self.scroll_down(bk, bk.rows / 2), @@ -308,6 +321,8 @@ impl View for Page { Right | PageDown | Char('f' | 'l' | ' ') => self.scroll_down(bk, bk.rows), Char('[') => self.prev_chapter(bk), Char(']') => self.next_chapter(bk), + Backspace => self.undo_click(bk), + Enter => self.redo_click(bk), _ => (), } } @@ -397,7 +412,7 @@ impl View for Search { fn on_key(&self, bk: &mut Bk, kc: KeyCode) { match kc { Esc => { - bk.jump_reset(); + bk.jump_back(); bk.query.clear(); bk.view = &Page; } @@ -406,7 +421,7 @@ impl View for Search { } Backspace => { bk.query.pop(); - bk.jump_reset(); + bk.jump_back(); bk.search(SearchArgs { dir: bk.dir.clone(), skip: false, @@ -419,7 +434,7 @@ impl View for Search { skip: false, }; if !bk.search(args) { - bk.jump_reset(); + bk.jump_back(); } } _ => (),