diff options
| author | pablu <me@pablu.de> | 2026-05-07 14:34:40 +0200 |
|---|---|---|
| committer | pablu <me@pablu.de> | 2026-05-07 14:34:40 +0200 |
| commit | 673853a8857c06a1b3e38122818e4eb0a3a77bb6 (patch) | |
| tree | f0ba92453891d55af50faff2552fc6e8b9e39436 | |
| parent | cc8e924ce828d237d7cdd245b794c532a4ee80d8 (diff) | |
searching list instead of only one
| -rw-r--r-- | src/app.rs | 77 | ||||
| -rw-r--r-- | src/event.rs | 3 | ||||
| -rw-r--r-- | src/ui.rs | 26 |
3 files changed, 90 insertions, 16 deletions
@@ -11,6 +11,9 @@ pub struct App<'a> { pub showing_search_window: bool, pub textarea: TextArea<'a>, pub search_found: Option<bool>, + search_indexes: Option<Vec<usize>>, + pub search_indexes_len: Option<usize>, + pub current_search_index: Option<usize>, } #[allow(dead_code)] @@ -22,6 +25,9 @@ impl<'a> App<'a> { showing_search_window: false, textarea: TextArea::default(), search_found: None, + search_indexes: None, + current_search_index: None, + search_indexes_len: None, } } @@ -36,17 +42,74 @@ impl<'a> App<'a> { } pub fn search(&mut self) -> bool { - let index = self.portage.installed_packages.iter().position(|s| { - s.name - .to_lowercase() - .contains(&self.textarea.lines()[0].to_lowercase()) - }); + let indexes: Vec<usize> = self + .portage + .installed_packages + .iter() + .enumerate() + .filter(|(_, s)| { + s.name + .to_lowercase() + .contains(&self.textarea.lines()[0].to_lowercase()) + }) + .map(|(i, _)| i) + .collect(); - if let Some(index) = index { - self.list_state.select(Some(index)); + if let Some(index) = indexes.first() { + self.list_state.select(Some(index.clone())); + self.search_indexes_len = Some(indexes.len()); + self.search_indexes = Some(indexes); + self.current_search_index = Some(0); return true; } + self.search_indexes = None; return false; } + + pub fn next_search(&mut self) { + let mut current_index = match self.current_search_index { + Some(i) => i, + None => return, + }; + + let search_indexes = match &self.search_indexes { + Some(i) => i, + None => return, + }; + + if current_index + 1 >= search_indexes.len() { + current_index = 0; + } else { + current_index += 1; + } + + let list_index = search_indexes[current_index]; + + self.list_state.select(Some(list_index)); + self.current_search_index = Some(current_index) + } + + pub fn prev_search(&mut self) { + let mut current_index = match self.current_search_index { + Some(i) => i, + None => return, + }; + + let search_indexes = match &self.search_indexes { + Some(i) => i, + None => return, + }; + + if current_index == 0 { + current_index = search_indexes.len() - 1; + } else { + current_index -= 1; + } + + let list_index = search_indexes[current_index]; + + self.list_state.select(Some(list_index)); + self.current_search_index = Some(current_index) + } } diff --git a/src/event.rs b/src/event.rs index 52013a5..530e244 100644 --- a/src/event.rs +++ b/src/event.rs @@ -12,6 +12,9 @@ pub fn handle_event(app: &mut App) -> io::Result<bool> { KeyCode::Char('j') => app.list_state.select_next(), KeyCode::Char('k') => app.list_state.select_previous(), KeyCode::Char('/') => app.toggle_search_window(), + KeyCode::Char('n') => app.next_search(), + KeyCode::Char('N') => app.prev_search(), + _ => return Ok(false), } } else { @@ -22,17 +22,25 @@ pub fn ui(frame: &mut Frame, app: &mut App) { render_packages(frame, split[0], app); render_use_flags(frame, split[1], app); - let key_hint = match app.showing_search_window { - false => Span::styled( - "(q) to quit | (/) to search | (j) down | (k) up", - Style::default().fg(Color::Yellow), - ), - true => Span::styled( - "(esc) to quit search | (enter) to search", - Style::default().fg(Color::Yellow), - ), + let text = match app.showing_search_window { + false => { + let mut main_key_hint = "(q) to quit | (j) down | (k) up | (/) to search".to_string(); + if let (Some(current), Some(total)) = (app.current_search_index, app.search_indexes_len) + { + main_key_hint.push_str(&format!( + " | (n) for next search | (N) for previous search | Searches found: {} / {}", + current + 1, + total + )); + } + + main_key_hint + } + true => "(esc) to quit search | (enter) to search".to_string(), }; + let key_hint = Span::styled(text, Style::default().fg(Color::Yellow)); + let key_notes_footer = Paragraph::new(Line::from(key_hint)).block(Block::default().borders(Borders::ALL)); frame.render_widget(key_notes_footer, bottom); |
