22mod elm;
33mod update;
44
5- use crate :: app:: apps:: { App , AppCommand } ;
5+ use crate :: app:: apps:: App ;
66use crate :: app:: tile:: elm:: default_app_paths;
77use crate :: app:: { ArrowKey , Message , Move , Page } ;
88use crate :: clipboard:: ClipBoardContentType ;
9- use crate :: commands:: Function ;
109use crate :: config:: Config ;
1110use crate :: utils:: open_settings;
1211
@@ -28,6 +27,7 @@ use objc2_app_kit::NSRunningApplication;
2827use rayon:: iter:: { IntoParallelRefIterator , ParallelIterator } ;
2928use tray_icon:: TrayIcon ;
3029
30+ use std:: collections:: BTreeMap ;
3131use std:: fs;
3232use std:: path:: PathBuf ;
3333use std:: time:: Duration ;
@@ -41,6 +41,29 @@ impl Drop for ExtSender {
4141 fn drop ( & mut self ) { }
4242}
4343
44+ #[ derive( Clone , Debug ) ]
45+ struct AppIndex {
46+ by_name : BTreeMap < String , App > ,
47+ }
48+
49+ impl AppIndex {
50+ fn search_prefix < ' a > ( & ' a self , prefix : & ' a str ) -> impl Iterator < Item = & ' a App > + ' a {
51+ self . by_name
52+ . range ( prefix. to_string ( ) ..) // start at prefix
53+ . take_while ( move |( k, _) | k. starts_with ( prefix) )
54+ . map ( |( _, v) | v)
55+ }
56+
57+ pub fn from_apps ( options : Vec < App > ) -> Self {
58+ let mut bmap = BTreeMap :: new ( ) ;
59+ for app in options {
60+ bmap. insert ( app. name_lc . clone ( ) , app) ;
61+ }
62+
63+ AppIndex { by_name : bmap }
64+ }
65+ }
66+
4467/// This is the base window, and its a "Tile"
4568/// Its fields are:
4669/// - Theme ([`iced::Theme`])
@@ -62,9 +85,8 @@ pub struct Tile {
6285 focus_id : u32 ,
6386 query : String ,
6487 query_lc : String ,
65- prev_query_lc : String ,
6688 results : Vec < App > ,
67- options : Vec < App > ,
89+ options : AppIndex ,
6890 visible : bool ,
6991 focused : bool ,
7092 frontmost : Option < Retained < NSRunningApplication > > ,
@@ -124,10 +146,10 @@ impl Tile {
124146 return Some ( Message :: KeyPressed ( 65598 ) ) ;
125147 }
126148 keyboard:: Key :: Named ( Named :: ArrowUp ) => {
127- return Some ( Message :: ChangeFocus ( ArrowKey :: ArrowUp ) ) ;
149+ return Some ( Message :: ChangeFocus ( ArrowKey :: Up ) ) ;
128150 }
129151 keyboard:: Key :: Named ( Named :: ArrowDown ) => {
130- return Some ( Message :: ChangeFocus ( ArrowKey :: ArrowDown ) ) ;
152+ return Some ( Message :: ChangeFocus ( ArrowKey :: Down ) ) ;
131153 }
132154 keyboard:: Key :: Character ( chr) => {
133155 if modifiers. command ( ) && chr. to_string ( ) . to_lowercase ( ) == "r" {
@@ -173,37 +195,14 @@ impl Tile {
173195 /// should be separated out to make it easier to test. This function is called by the `update`
174196 /// function to handle the search query changed event.
175197 pub fn handle_search_query_changed ( & mut self ) {
176- let filter_vec: & Vec < App > = if self . query_lc . starts_with ( & self . prev_query_lc ) {
177- self . prev_query_lc = self . query_lc . to_owned ( ) ;
178- & self . results
179- } else {
180- & self . options
181- } ;
182-
183198 let query = self . query_lc . clone ( ) ;
184-
185- let mut exact: Vec < App > = filter_vec
186- . par_iter ( )
187- . filter ( |x| match & x. open_command {
188- & AppCommand :: Function ( Function :: RunShellCommand ( _, _) ) => x
189- . name_lc
190- . starts_with ( query. split_once ( " " ) . unwrap_or ( ( & query, "" ) ) . 0 ) ,
191- _ => x. name_lc == query,
192- } )
193- . cloned ( )
194- . collect ( ) ;
195-
196- let mut prefix: Vec < App > = filter_vec
197- . par_iter ( )
198- . filter ( |x| match x. open_command {
199- AppCommand :: Function ( Function :: RunShellCommand ( _, _) ) => false ,
200- _ => x. name_lc != query && x. name_lc . starts_with ( & query) ,
201- } )
202- . cloned ( )
199+ let results: Vec < App > = self
200+ . options
201+ . search_prefix ( & query)
202+ . map ( |x| x. to_owned ( ) )
203203 . collect ( ) ;
204204
205- exact. append ( & mut prefix) ;
206- self . results = exact;
205+ self . results = results;
207206 }
208207
209208 /// Gets the frontmost application to focus later.
0 commit comments