From 9e1abe5a973eef5d598231505dbbd4237a93b1a1 Mon Sep 17 00:00:00 2001 From: Nathaniel Ledford Date: Fri, 9 Oct 2026 14:50:13 -0400 Subject: [PATCH] LRC-LIB-KEYWORDS: typing suggests keywords no photo has yet Suggestions came from the photos' keywords only, so a keyword created in the Keyword List was never offered while typing. Those only the list has are suggested too. Co-Authored-By: Claude Opus 5.5 --- crates/catalog/src/keywords.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/crates/catalog/src/keywords.rs b/crates/catalog/src/keywords.rs index a266e6c64..b79d245ac 100644 --- a/crates/catalog/src/keywords.rs +++ b/crates/catalog/src/keywords.rs @@ -498,7 +498,13 @@ impl Catalog { /// appear together with `current` on other photos, then the most used ones. Most frequent /// first, at most `n`, never one of `current`. pub fn keyword_suggestions(&self, current: &[String], prefix: &str, n: usize) -> Vec { - let all = self.keywords(); + // the photos' keywords with their counts, and those only the list has (none) + let mut all = self.keywords(); + for l in self.keyword_list.values() { + if !all.iter().any(|(k, _)| same(k, &l.path)) { + all.push((l.path.clone(), 0)); + } + } let has = |k: &str| current.iter().any(|c| same(c, k)); let q = prefix.trim().to_lowercase(); let mut scored: Vec<(i64, String)> = if !q.is_empty() { @@ -997,6 +1003,15 @@ mod tests { assert!(listed(&c).is_empty()); } + /// Typing suggests keywords no photo has yet too (created in the Keyword List). + #[test] + fn suggestions_include_keywords_without_photos() { + let (mut c, _) = lib(&[&["beach"]]); + c.apply(Op::SetKeyword { path: "Events|Weddings".into(), info: Some(KeywordInfo::default()) }).unwrap(); + assert_eq!(c.keyword_suggestions(&[], "wed", 5), ["Events|Weddings"]); + assert!(!c.keyword_suggestions(&["events|weddings".into()], "wed", 5).contains(&"Events|Weddings".to_string()), "not one it has"); + } + #[test] fn suggestions_rank_co_occurrence_and_prefixes() { let (c, _) = lib(&[&["dog", "park"], &["dog", "park", "ball"], &["dog", "beach"], &["cat"], &["cat"], &["cat"], &["parade"], &["eagle"]]);