Provide search functionality through the TUI #134

Merged
wojtek merged 35 commits from 24---provide-search-functionality-through-the-tui into main 2024-02-18 22:12:42 +01:00
3 changed files with 32 additions and 5 deletions
Showing only changes of commit 488d20273e - Show all commits

View File

@ -108,6 +108,7 @@ pub trait IAppInteractReload {
pub trait IAppInteractSearch { pub trait IAppInteractSearch {
fn append_character(&mut self, ch: char); fn append_character(&mut self, ch: char);
fn search_next(&mut self);
fn remove_character(&mut self); fn remove_character(&mut self);
fn finish_search(&mut self); fn finish_search(&mut self);
} }
@ -246,6 +247,7 @@ impl<MH: IMusicHoard> IAppInteractBrowse for App<MH> {
fn begin_search(&mut self) { fn begin_search(&mut self) {
assert!(self.state.is_browse()); assert!(self.state.is_browse());
self.state = AppState::Search(String::new()); self.state = AppState::Search(String::new());
// FIXME: this should be the entire selection - not just the artist.
self.memo = vec![self.selection.selected_artist()]; self.memo = vec![self.selection.selected_artist()];
self.selection self.selection
.reset_artist(self.music_hoard.get_collection()); .reset_artist(self.music_hoard.get_collection());
@ -296,7 +298,6 @@ impl<MH: IMusicHoard> IAppInteractReloadPrivate for App<MH> {
} }
} }
// FIXME: add `search_next` to find next match
// FIXME: once `search_next` is added, backspace should step back. If the previous action was // FIXME: once `search_next` is added, backspace should step back. If the previous action was
// `search_next` then no character should be removed. If the previous action was to append // `search_next` then no character should be removed. If the previous action was to append
// a character, a character should be removed. When in doubt see how Emacs's isearch works. // a character, a character should be removed. When in doubt see how Emacs's isearch works.
@ -306,7 +307,14 @@ impl<MH: IMusicHoard> IAppInteractSearch for App<MH> {
let collection = self.music_hoard.get_collection(); let collection = self.music_hoard.get_collection();
let search = self.state.as_mut().unwrap_search(); let search = self.state.as_mut().unwrap_search();
search.push(ch); search.push(ch);
let prev = self.selection.incremental_artist_search(collection, search); let prev = self.selection.incremental_artist_search(collection, search, false);
self.memo.push(prev);
}
fn search_next(&mut self) {
let collection = self.music_hoard.get_collection();
let search = self.state.as_mut().unwrap_search();
let prev = self.selection.incremental_artist_search(collection, search, true);
self.memo.push(prev); self.memo.push(prev);
} }

View File

@ -108,8 +108,9 @@ impl Selection {
&mut self, &mut self,
collection: &Collection, collection: &Collection,
artist_name: &str, artist_name: &str,
next: bool,
) -> Option<usize> { ) -> Option<usize> {
self.artist.incremental_search(collection, artist_name) self.artist.incremental_search(collection, artist_name, next)
} }
pub fn increment_selection(&mut self, collection: &Collection, delta: Delta) { pub fn increment_selection(&mut self, collection: &Collection, delta: Delta) {
@ -265,14 +266,22 @@ impl ArtistSelection {
result result
} }
fn incremental_search(&mut self, artists: &[Artist], artist_name: &str) -> Option<usize> { fn incremental_search(
&mut self,
artists: &[Artist],
artist_name: &str,
next: bool,
) -> Option<usize> {
let previous = self.state.list.selected(); let previous = self.state.list.selected();
if let Some(index) = self.state.list.selected() { if let Some(mut index) = self.state.list.selected() {
let case_sensitive = Self::is_case_sensitive(artist_name); let case_sensitive = Self::is_case_sensitive(artist_name);
let char_sensitive = Self::is_char_sensitive(artist_name); let char_sensitive = Self::is_char_sensitive(artist_name);
let search = Self::normalize_search(artist_name, !case_sensitive, !char_sensitive); let search = Self::normalize_search(artist_name, !case_sensitive, !char_sensitive);
if next && ((index + 1) < artists.len()) {
index += 1;
}
let slice = &artists[index..]; let slice = &artists[index..];
let result = slice.iter().position(|probe| { let result = slice.iter().position(|probe| {

View File

@ -146,6 +146,16 @@ impl<APP: IAppInteract> IEventHandlerPrivate<APP> for EventHandler {
} }
fn handle_search_key_event(app: &mut <APP as IAppInteract>::SS, key_event: KeyEvent) { fn handle_search_key_event(app: &mut <APP as IAppInteract>::SS, key_event: KeyEvent) {
if key_event.modifiers == KeyModifiers::CONTROL {
match key_event.code {
KeyCode::Char('s') | KeyCode::Char('S') => {
app.search_next();
},
_ => {}
}
return;
}
match key_event.code { match key_event.code {
// Add/remove character to search. // Add/remove character to search.
KeyCode::Char(ch) => app.append_character(ch), KeyCode::Char(ch) => app.append_character(ch),