Correct-ish implementation with binary search

This commit is contained in:
Wojciech Kozlowski 2024-02-11 16:54:48 +01:00
parent 0b697f5484
commit aca4628594

View File

@ -192,26 +192,42 @@ impl ArtistSelection {
} }
} }
// FIXME: think about converting punctuation characters to some common character. fn normalize_search_string(search: &str, lowercase: bool) -> String {
let normalized = if lowercase {
search.to_lowercase()
} else {
search.to_owned()
};
// Unlikely that this covers all possible strings, but it should at least cover strings
// relevant for music (at least in English). The list of characters handled is based on
// https://wiki.musicbrainz.org/User:Yurim/Punctuation_and_Special_Characters.
normalized
.replace("", "-") // U+2010 hyphen
.replace("", "-") // U+2012 figure dash
.replace("", "-") // U+2013 en dash
.replace("", "-") // U+2014 em dash
.replace("", "-") // U+2015 horizontal bar
.replace("", "'") // U+2018
.replace("", "'") // U+2019
.replace("", "\"") // U+201C
.replace("", "\"") // U+201D
.replace("", "...") // U+2026
.replace("", "-") // U+2212 minus sign
}
fn incremental_search(&mut self, artists: &[Artist], artist_name: &str) { fn incremental_search(&mut self, artists: &[Artist], artist_name: &str) {
if let Some(index) = self.state.list.selected() { if let Some(index) = self.state.list.selected() {
let case_sensitive = artist_name let case_sensitive = artist_name
.chars() .chars()
.any(|ch| !(ch.is_lowercase() || ch.is_whitespace() || ch.is_ascii_punctuation())); .any(|ch| ch.is_alphabetic() && ch.is_uppercase());
let search_name = Self::normalize_search_string(artist_name, !case_sensitive);
let slice = &artists[index..]; let slice = &artists[index..];
let result = if case_sensitive { let result = slice.binary_search_by(|probe| {
slice.binary_search_by(|probe| probe.get_sort_key().name.as_str().cmp(artist_name)) Self::normalize_search_string(&probe.get_sort_key().name, !case_sensitive)
} else { .cmp(&search_name)
slice.binary_search_by(|probe| { });
probe
.get_sort_key()
.name
.to_lowercase()
.as_str()
.cmp(artist_name)
})
};
let new_index = match result { let new_index = match result {
Ok(slice_index) | Err(slice_index) => index + slice_index, Ok(slice_index) | Err(slice_index) => index + slice_index,