diff --git a/src/tui/app/app.rs b/src/tui/app/app.rs index e0223da..8dc5f41 100644 --- a/src/tui/app/app.rs +++ b/src/tui/app/app.rs @@ -109,7 +109,7 @@ pub trait IAppInteractReload { pub trait IAppInteractSearch { fn append_character(&mut self, ch: char); fn search_next(&mut self); - fn remove_character(&mut self); + fn step_back(&mut self); fn finish_search(&mut self); } @@ -142,7 +142,8 @@ pub struct App { state: AppState<(), (), (), String, String, String>, // FIXME: is it possible to use a wrapper struct? - when state() is called return a wrapper // around App which will contain App. - memo: Vec>, + orig: Option, + memo: Vec<(Option, bool)>, } impl App { @@ -157,6 +158,7 @@ impl App { music_hoard, selection, state, + orig: None, memo: vec![], } } @@ -248,7 +250,8 @@ impl IAppInteractBrowse for App { assert!(self.state.is_browse()); 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.orig = self.selection.selected_artist(); + self.memo = vec![]; self.selection .reset_artist(self.music_hoard.get_collection()); } @@ -298,31 +301,36 @@ impl IAppInteractReloadPrivate for App { } } -// 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 -// a character, a character should be removed. When in doubt see how Emacs's isearch works. // FIXME: Also add a `cancel_search` which returns to the previous selection. impl IAppInteractSearch for App { fn append_character(&mut self, ch: char) { let collection = self.music_hoard.get_collection(); let search = self.state.as_mut().unwrap_search(); search.push(ch); - let prev = self.selection.incremental_artist_search(collection, search, false); - self.memo.push(prev); + let prev = self + .selection + .incremental_artist_search(collection, search, false); + self.memo.push((prev, true)); } 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); + if !search.is_empty() { + let prev = self + .selection + .incremental_artist_search(collection, search, true); + self.memo.push((prev, false)); + } } - fn remove_character(&mut self) { + fn step_back(&mut self) { let collection = self.music_hoard.get_collection(); - let search = self.state.as_mut().unwrap_search(); - if search.pop().is_some() { - let prev = self.memo.pop().unwrap(); + if let Some((prev, pop_char)) = self.memo.pop() { + if pop_char { + let search = self.state.as_mut().unwrap_search(); + search.pop(); + } self.selection.select_artist(collection, prev); } } diff --git a/src/tui/app/selection.rs b/src/tui/app/selection.rs index be5136c..dc598b8 100644 --- a/src/tui/app/selection.rs +++ b/src/tui/app/selection.rs @@ -110,7 +110,8 @@ impl Selection { artist_name: &str, next: bool, ) -> Option { - self.artist.incremental_search(collection, artist_name, next) + self.artist + .incremental_search(collection, artist_name, next) } pub fn increment_selection(&mut self, collection: &Collection, delta: Delta) { @@ -196,9 +197,11 @@ impl ArtistSelection { } } - fn select(&mut self, artists: &[Artist], mut to: Option) { - to = to.map(|i| cmp::min(i, artists.len() - 1)); - self.state.list.select(to); + fn select(&mut self, artists: &[Artist], to: Option) { + match to { + Some(to) => self.select_to(artists, to), + None => self.state.list.select(None), + } } fn select_to(&mut self, artists: &[Artist], mut to: usize) { diff --git a/src/tui/handler.rs b/src/tui/handler.rs index 687baf2..e52e9cb 100644 --- a/src/tui/handler.rs +++ b/src/tui/handler.rs @@ -159,7 +159,7 @@ impl IEventHandlerPrivate for EventHandler { match key_event.code { // Add/remove character to search. KeyCode::Char(ch) => app.append_character(ch), - KeyCode::Backspace => app.remove_character(), + KeyCode::Backspace => app.step_back(), // Return. KeyCode::Esc | KeyCode::Enter => app.finish_search(), // Othey keys.