From ec5630e08f711c434cdd61c04eb87dbeedcc30cb Mon Sep 17 00:00:00 2001 From: Leonardo Ponzoni Date: Mon, 24 Apr 2023 23:24:45 -0300 Subject: [PATCH 1/7] Allow for jumping backwards. Creates a jumpstack that allows for forward and backwards. --- src/main.rs | 10 ++++++++++ src/view.rs | 8 ++++++++ 2 files changed, 18 insertions(+) diff --git a/src/main.rs b/src/main.rs index 57aa177..81fe148 100644 --- a/src/main.rs +++ b/src/main.rs @@ -95,6 +95,7 @@ pub struct Bk<'a> { line: usize, mark: HashMap, links: HashMap, + return_stack: Vec<(usize, usize)>, // layout colors: Colors, cols: u16, @@ -137,6 +138,7 @@ impl Bk<'_> { line: 0, mark: HashMap::new(), links: epub.links, + return_stack: Vec::with_capacity(5), colors: args.colors, cols, rows: rows as usize, @@ -236,6 +238,14 @@ impl Bk<'_> { self.chapter = c; self.line = l; } + fn jump_back(&mut self) { + let (c, l) = self.return_stack.pop().expect("Call jump_back only with elements inside"); + self.chapter = c; + self.line = l; + } + fn save_jump(&mut self) { + self.return_stack.push((self.chapter, self.line)); + } 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..813722b 100644 --- a/src/view.rs +++ b/src/view.rs @@ -100,6 +100,7 @@ PageDown Right Space f l Page Down N Repeat search backward mx Set mark x 'x Jump to mark x + Backspace Return from clicked link. "#; text.lines().map(String::from).collect() @@ -244,10 +245,16 @@ impl Page { if let Ok(i) = r { let url = &c.links[i].2; let &(c, byte) = bk.links.get(url).unwrap(); + bk.save_jump(); bk.mark('\''); bk.jump_byte(c, byte); } } + fn undo_click(&self, bk: &mut Bk){ + if !bk.return_stack.is_empty(){ + bk.jump_back(); + } + } fn start_search(&self, bk: &mut Bk, dir: Direction) { bk.mark('\''); bk.query.clear(); @@ -308,6 +315,7 @@ 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), _ => (), } } From ab51b1b2044f7d63c9770fb3a89d6d6afabd768f Mon Sep 17 00:00:00 2001 From: lsponzoni Date: Tue, 25 Apr 2023 03:33:58 -0300 Subject: [PATCH 2/7] Removal of space reserve in return_stack --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 81fe148..10b347c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -138,7 +138,7 @@ impl Bk<'_> { line: 0, mark: HashMap::new(), links: epub.links, - return_stack: Vec::with_capacity(5), + return_stack: Vec::new(), colors: args.colors, cols, rows: rows as usize, From 88b9060164c786ad0257881c45e6f19b15e5cd41 Mon Sep 17 00:00:00 2001 From: lsponzoni Date: Tue, 25 Apr 2023 11:43:01 -0300 Subject: [PATCH 3/7] Jump forward added. This lets the jump stack be traversed as a double linked list jump 1 <-> jump 2 <-> jump 3 <- Last jump This is implemented by adding a int that points to the top of array. stack_pointer Array elements are always picked one less than the top. The destination of the last jump destination is not in the stack. So jump forward can't really move to it. But the jump n - 1 should point to the link that you press to make it. When you click a link and stack_pointer is pointing to last jump 1 <-> jump 2 <-> jump 3 *stack_pointer jump 1 <-> jump 2 <-> jump 3 <-> jump 4 *stack_pointer + 1 However, when clicking a link on a stack_pointer pointing before that: jump 1 <-> jump 2 <-> jump 3 <-> jump 4 *stack_pointer jump 1 <-> jump 2 <-> new jump 3 *stack_pointer --- src/main.rs | 25 +++++++++++++++++++------ src/view.rs | 11 +++++++---- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/main.rs b/src/main.rs index 10b347c..3df9a21 100644 --- a/src/main.rs +++ b/src/main.rs @@ -95,7 +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, @@ -139,6 +141,7 @@ impl Bk<'_> { mark: HashMap::new(), links: epub.links, return_stack: Vec::new(), + stack_pointer: 0, colors: args.colors, cols, rows: rows as usize, @@ -234,16 +237,26 @@ impl Bk<'_> { } } fn jump_reset(&mut self) { - let &(c, l) = self.mark.get(&'\'').unwrap(); - self.chapter = c; - self.line = l; + let &to = self.mark.get(&'\'').unwrap(); + self.jump(to); + } + 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) { - let (c, l) = self.return_stack.pop().expect("Call jump_back only with elements inside"); - self.chapter = c; - self.line = l; + if self.stack_pointer > 0 { + 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); + self.stack_pointer += 1; self.return_stack.push((self.chapter, self.line)); } fn mark(&mut self, c: char) { diff --git a/src/view.rs b/src/view.rs index 813722b..7f8a077 100644 --- a/src/view.rs +++ b/src/view.rs @@ -100,7 +100,8 @@ PageDown Right Space f l Page Down N Repeat search backward mx Set mark x 'x Jump to mark x - Backspace Return from clicked link. + Backspace Undo one jump back. + Enter Redo one jump. "#; text.lines().map(String::from).collect() @@ -251,9 +252,10 @@ impl Page { } } fn undo_click(&self, bk: &mut Bk){ - if !bk.return_stack.is_empty(){ - bk.jump_back(); - } + bk.jump_back(); + } + fn redo_click(&self, bk: &mut Bk){ + bk.jump_forward(); } fn start_search(&self, bk: &mut Bk, dir: Direction) { bk.mark('\''); @@ -316,6 +318,7 @@ impl View for Page { Char('[') => self.prev_chapter(bk), Char(']') => self.next_chapter(bk), Backspace => self.undo_click(bk), + Enter => self.redo_click(bk), _ => (), } } From e9e1d5aa9c984b693d93bc10507faa666a07f6a5 Mon Sep 17 00:00:00 2001 From: lsponzoni Date: Tue, 25 Apr 2023 12:55:27 -0300 Subject: [PATCH 4/7] Jump forward traverses from last return point. Now jump forward can traverse back and forth from all positions, not just where last link was. a: link b b: link c c: link d d: From here Jump forward can go to b c d and backward go c b a. This was a small change that jump back now saves where it is before jumping back. --- src/main.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main.rs b/src/main.rs index 3df9a21..7ab6b82 100644 --- a/src/main.rs +++ b/src/main.rs @@ -249,6 +249,9 @@ impl Bk<'_> { } 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); From a194d53698e90ee6bd0cd4f619acf58f19854267 Mon Sep 17 00:00:00 2001 From: lsponzoni Date: Tue, 25 Apr 2023 13:45:25 -0300 Subject: [PATCH 5/7] Remove the need for mark('\'') to track backing Almost all current use of '' could be remapped to backspace 1 time. I've kept marks unrelated from jump list. And mark jumping is not part of the jump list. * jump_reset uses are changed to jump_back * Almost all mark('\'') can be safely removed. --- src/main.rs | 2 +- src/view.rs | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index 7ab6b82..33d09f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -155,7 +155,7 @@ impl Bk<'_> { bk.jump_byte(args.chapter, args.byte); bk.mark('\''); - + bk.save_jump(); bk } fn run(&mut self) -> io::Result<()> { diff --git a/src/view.rs b/src/view.rs index 7f8a077..f08cb4b 100644 --- a/src/view.rs +++ b/src/view.rs @@ -145,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; } @@ -246,8 +246,8 @@ impl Page { if let Ok(i) = r { let url = &c.links[i].2; let &(c, byte) = bk.links.get(url).unwrap(); - bk.save_jump(); bk.mark('\''); + bk.save_jump(); bk.jump_byte(c, byte); } } @@ -259,6 +259,7 @@ impl Page { } fn start_search(&self, bk: &mut Bk, dir: Direction) { bk.mark('\''); + bk.save_jump(); bk.query.clear(); bk.dir = dir; bk.view = &Search; @@ -278,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; } @@ -301,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), @@ -408,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; } @@ -417,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, @@ -430,7 +434,7 @@ impl View for Search { skip: false, }; if !bk.search(args) { - bk.jump_reset(); + bk.jump_back(); } } _ => (), From 6da009a87f42d354e1122530f61e937372ab246d Mon Sep 17 00:00:00 2001 From: lsponzoni Date: Tue, 25 Apr 2023 13:58:51 -0300 Subject: [PATCH 6/7] Don't save a jump to the same line in sequence. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change save_jump so that when the stack top is the same as the item added, it does not push the jump. Jump 1, Jump 1 ❌ Jump 1 ✓ --- src/main.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 33d09f5..d1535ad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -236,7 +236,7 @@ impl Bk<'_> { Err(n) => n - 1, } } - fn jump_reset(&mut self) { + fn jump_reset(&mut self) { // Dead code let &to = self.mark.get(&'\'').unwrap(); self.jump(to); } @@ -259,8 +259,12 @@ impl Bk<'_> { } fn save_jump(&mut self) { self.return_stack.truncate(self.stack_pointer); - self.stack_pointer += 1; - self.return_stack.push((self.chapter, self.line)); + 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)); From 7719e976043d0260d4117f1e95a58b0fa9f20cc2 Mon Sep 17 00:00:00 2001 From: lsponzoni Date: Tue, 25 Apr 2023 14:27:14 -0300 Subject: [PATCH 7/7] Remove jump_reset and its not used warning --- src/main.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index d1535ad..54fe7ce 100644 --- a/src/main.rs +++ b/src/main.rs @@ -236,10 +236,6 @@ impl Bk<'_> { Err(n) => n - 1, } } - fn jump_reset(&mut self) { // Dead code - let &to = self.mark.get(&'\'').unwrap(); - self.jump(to); - } fn jump_forward(&mut self) { if self.stack_pointer + 1 < self.return_stack.len() { self.stack_pointer += 1;