Implement step back

This commit is contained in:
Wojciech Kozlowski 2024-02-12 23:09:19 +01:00
parent 488d20273e
commit a29a3fa3ce
3 changed files with 30 additions and 19 deletions

View File

@ -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<MH: IMusicHoard> {
state: AppState<(), (), (), String, String, String>,
// FIXME: is it possible to use a wrapper struct? - when state() is called return a wrapper
// around App<MH> which will contain App.
memo: Vec<Option<usize>>,
orig: Option<usize>,
memo: Vec<(Option<usize>, bool)>,
}
impl<MH: IMusicHoard> App<MH> {
@ -157,6 +158,7 @@ impl<MH: IMusicHoard> App<MH> {
music_hoard,
selection,
state,
orig: None,
memo: vec![],
}
}
@ -248,7 +250,8 @@ impl<MH: IMusicHoard> IAppInteractBrowse for App<MH> {
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<MH: IMusicHoard> IAppInteractReloadPrivate for App<MH> {
}
}
// 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<MH: IMusicHoard> IAppInteractSearch for App<MH> {
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();
if let Some((prev, pop_char)) = self.memo.pop() {
if pop_char {
let search = self.state.as_mut().unwrap_search();
if search.pop().is_some() {
let prev = self.memo.pop().unwrap();
search.pop();
}
self.selection.select_artist(collection, prev);
}
}

View File

@ -110,7 +110,8 @@ impl Selection {
artist_name: &str,
next: bool,
) -> Option<usize> {
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<usize>) {
to = to.map(|i| cmp::min(i, artists.len() - 1));
self.state.list.select(to);
fn select(&mut self, artists: &[Artist], to: Option<usize>) {
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) {

View File

@ -159,7 +159,7 @@ impl<APP: IAppInteract> IEventHandlerPrivate<APP> 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.