From 9fc463b3da9c70f6aec6194979d99ebe916dc59b Mon Sep 17 00:00:00 2001 From: llama Date: Sat, 19 Jul 2025 08:44:25 +0800 Subject: [PATCH] prioritise prefix matches in tag autocomplete results --- rslib/src/tags/complete.rs | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/rslib/src/tags/complete.rs b/rslib/src/tags/complete.rs index 1093017b0..0708a51f5 100644 --- a/rslib/src/tags/complete.rs +++ b/rslib/src/tags/complete.rs @@ -12,14 +12,20 @@ impl Collection { .map(component_to_regex) .collect::>()?; let mut tags = vec![]; + let mut priority = vec![]; self.storage.get_tags_by_predicate(|tag| { - if tags.len() <= limit && filters_match(&filters, tag) { - tags.push(tag.to_string()); + if priority.len() + tags.len() <= limit { + match filters_match(&filters, tag) { + Some(true) => priority.push(tag.to_string()), + Some(_) => tags.push(tag.to_string()), + _ => {} + } } // we only need the tag name false })?; - Ok(tags) + priority.append(&mut tags); + Ok(priority) } } @@ -27,20 +33,25 @@ fn component_to_regex(component: &str) -> Result { Regex::new(&format!("(?i){}", regex::escape(component))).map_err(Into::into) } -fn filters_match(filters: &[Regex], tag: &str) -> bool { +/// Returns None if tag wasn't a match, otherwise whether it was a consecutive prefix match +fn filters_match(filters: &[Regex], tag: &str) -> Option { let mut remaining_tag_components = tag.split("::"); + let mut is_prefix = true; 'outer: for filter in filters { loop { if let Some(component) = remaining_tag_components.next() { - if filter.is_match(component) { + if let Some(m) = filter.find(component) { + is_prefix &= m.start() == 0; continue 'outer; + } else { + is_prefix = false; } } else { - return false; + return None; } } } - true + Some(is_prefix) } #[cfg(test)]