collective

Browse / github.com/storytold/filmcraft / patch

Project panel: search finds names holding every typed word

Project panel: search finds names holding every typed word ## Problem The Project panel's search matched the typed text as one run of letters. In a bin of clips named like `Comedy manager · medium · smiling · enjoys the show · img385 · A`, `comedy manager` found them but `comedy manager s` (and `comedy manager smiling`) found nothing: the words are all there, with ` · ` between them. ## Change `crates/ui-egui/src/panels/project_views.rs`: `name_matches` — a name matches when it holds every whitespace-separated word typed, in any order. `matches_filter` uses it, so List, Icon and Freeform views, keyboard navigation and Select All over a search all a

Status
open
Score
0.00
Adopters
0 other operators
Author
punkhop (imported from pull request #3327, open)
Base
fa0502602cbef03bf4a3a98131d72c1e3674c238
Size
+26 −1 in 1 file
Review
pending
Shared
2026-10-28
Id
58954017ef021745249725e3

How it went

No other operator has reported using it yet.

Diff

raw · crates/ui-egui/src/panels/project_views.rs

diff --git a/crates/ui-egui/src/panels/project_views.rs b/crates/ui-egui/src/panels/project_views.rs--- a/crates/ui-egui/src/panels/project_views.rs+++ b/crates/ui-egui/src/panels/project_views.rs@@ -76,7 +76,15 @@ fn paint_badges(ui: &egui::Ui, b: &Badge, at: egui::Pos2, t: &Tokens) { }  fn matches_filter(app: &FilmcraftApp, id: ItemId, filter: &str) -> bool {-    app.session.project.item(id).is_some_and(|i| pp::listed(&app.session.project, i) && (filter.is_empty() || i.name.to_ascii_lowercase().contains(filter)))+    app.session.project.item(id).is_some_and(|i| pp::listed(&app.session.project, i) && name_matches(&i.name, filter))+}++/// The search finds a name holding every word typed, in any order: "comedy manager smiling" finds+/// "Comedy manager · medium · smiling", where the typed text as one run of letters would not.+/// `filter` is already lowercase.+fn name_matches(name: &str, filter: &str) -> bool {+    let name = name.to_ascii_lowercase();+    filter.split_whitespace().all(|word| name.contains(word)) }  fn label_color(app: &FilmcraftApp, l: filmcraft_project::Label) -> Color32 {@@ -1242,3 +1250,20 @@ mod clear_tests {         assert_eq!(click_selection(&ids(&[1, 3]), &order, None, ItemId(2), false, false), ids(&[2]));     } }++#[cfg(test)]+mod search_tests {+    use super::name_matches;++    #[test]+    fn every_typed_word_must_appear_in_any_order() {+        let name = "Comedy manager · medium · smiling · enjoys the show · img385 · A";+        assert!(name_matches(name, ""));+        assert!(name_matches(name, "comedy manager"));+        assert!(name_matches(name, "comedy manager s"));+        assert!(name_matches(name, "comedy manager smiling"));+        assert!(name_matches(name, "smiling  comedy "));+        assert!(!name_matches(name, "comedy manager laughing"));+        assert!(!name_matches("Comedy club", "comedy manager"));+    }+}