From 71658df5fe131f17455b6987ab600aac4c6acc84 Mon Sep 17 00:00:00 2001 From: zegonix Date: Sun, 6 Jul 2025 21:20:59 +0200 Subject: [PATCH] implemented options to dedup/rotate stack --- README.md | 4 ++-- src/config.rs | 8 ++++++++ src/main.rs | 9 +++++++-- src/stack.rs | 40 +++++++++++++++++++++++++++++++++++++--- 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index dca10c6..f95510c 100644 --- a/README.md +++ b/README.md @@ -60,8 +60,8 @@ Style settings accept styles and one color in the following formats: - [x] `show-bookmarks-on-book` - [x] setting for separator string when displaying stack/bookmarks - [x] color option for punctuation (mostly '/') - - [ ] option to dedup stack entries - - [ ] option for behaviour when jumping to stack entry via `push =` + - [x] option to dedup stack entries + - [x] option for behaviour when jumping to stack entry via `push =` - [x] bookmarks - [x] do not resolve links in bookmarks - [x] option to show invalid paths diff --git a/src/config.rs b/src/config.rs index fecb9ac..a6fe7d2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -25,6 +25,14 @@ pub struct Config { #[derive(Debug, Clone, Default, ConfigParser)] pub struct GeneralSettings { + /// (bool) delete all older occurences of paths in the stack + #[default_value(false)] + pub dedup_stack: bool, + + /// (bool) rotate stack to chosen path when jumping to stack entry + #[default_value(false)] + pub rotate_stack_on_jump_to_entry: bool, + /// (bool) show stack when pushing a path to the stack #[default_value(false)] pub show_stack_on_push: bool, diff --git a/src/main.rs b/src/main.rs index 09edc60..3da7acc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -58,7 +58,7 @@ fn main() -> Result<()> { return Ok(()); } }; - let mut stack = match Stack::new(args.pid) { + let mut stack = match Stack::new(&config, args.pid) { Ok(stack) => stack, Err(_) => { output.push_error(&"-- failed to build stack".to_string()); @@ -104,7 +104,12 @@ fn handle_push(args: &PushArgs, config: &Config, stack: &mut Stack, output: &mut Ok(value) => value, Err(_) => return Err(Error::other("-- push : failed to convert path argument to number")), }; - stack.get_entry_by_number(number)?.to_path_buf() + let path = stack.get_entry_by_number(number)?.to_path_buf(); + if config.general.rotate_stack_on_jump_to_entry { + stack.rotate_stack(number)?; + } + _ = stack.pop_entry(None); + path } else { match PathBuf::from_str(&path_string) { Ok(value) => value, diff --git a/src/stack.rs b/src/stack.rs index e02529d..3a49b14 100644 --- a/src/stack.rs +++ b/src/stack.rs @@ -21,13 +21,13 @@ pub struct Stack { impl Stack { const STACK_FILE_DIRECTORY: &str = "/tmp/navigate/"; - pub fn new(process_id: u32) -> Result { + pub fn new(config: &Config, process_id: u32) -> Result { let mut stack: Stack = Stack { pid: process_id, path: PathBuf::new(), stack: Vec::::new(), }; - stack.build_stack()?; + stack.build_stack(config)?; Ok(stack) } @@ -138,8 +138,25 @@ impl Stack { } } + /// rotate stack so that the is the latest + /// entry (first to be popped) + pub fn rotate_stack(&mut self, entry_number: usize) -> Result<()> { + if 0 == entry_number { + return Ok(()); + } else if self.stack.len() <= entry_number { + return Err(Error::other("-- number to rotate is greater than the stacks length")); + } + + let mut rotated_stack: Vec = self.stack.drain(self.stack.len() - entry_number..).collect(); + + rotated_stack.extend(self.stack.drain(..)); + self.stack = rotated_stack; + + Ok(()) + } + /// clean up dead stack files, parse and build stack - fn build_stack(&mut self) -> Result<()> { + fn build_stack(&mut self, config: &Config) -> Result<()> { let stack_dir: PathBuf = match PathBuf::from_str(Self::STACK_FILE_DIRECTORY) { Ok(value) => value, Err(_) => { @@ -187,6 +204,10 @@ impl Stack { } self.cleanup_stack(); + if config.general.dedup_stack { + self.dedup_stack(); + } + Ok(()) } @@ -208,6 +229,19 @@ impl Stack { } } + /// keep only the newest occurence of a path + fn dedup_stack(&mut self) { + let mut deduped_stack: Vec = Vec::new(); + while !self.stack.is_empty() { + let entry: PathBuf = self.stack.remove(0); + if !self.stack.contains(&entry) { + deduped_stack.push(entry); + } + } + + self.stack = deduped_stack; + } + /// write stack current stack to file to save it for next execution fn write_stack_file(&mut self) -> Result<()> { let mut output = Vec::<&str>::new();