Skip to content

Commit c928b53

Browse files
authored
Merge pull request #101 from unsecretised/searching-optimisations
Searching optimisations
2 parents c355085 + e544e4b commit c928b53

File tree

4 files changed

+50
-49
lines changed

4 files changed

+50
-49
lines changed

src/app.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ pub enum Page {
2626
#[allow(dead_code)]
2727
#[derive(Debug, Clone)]
2828
pub enum ArrowKey {
29-
ArrowUp,
30-
ArrowDown,
31-
ArrowLeft,
32-
ArrowRight,
29+
Up,
30+
Down,
31+
Left,
32+
Right,
3333
}
3434

3535
#[derive(Debug, Clone)]

src/app/tile.rs

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22
mod elm;
33
mod update;
44

5-
use crate::app::apps::{App, AppCommand};
5+
use crate::app::apps::App;
66
use crate::app::tile::elm::default_app_paths;
77
use crate::app::{ArrowKey, Message, Move, Page};
88
use crate::clipboard::ClipBoardContentType;
9-
use crate::commands::Function;
109
use crate::config::Config;
1110
use crate::utils::open_settings;
1211

@@ -28,6 +27,7 @@ use objc2_app_kit::NSRunningApplication;
2827
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
2928
use tray_icon::TrayIcon;
3029

30+
use std::collections::BTreeMap;
3131
use std::fs;
3232
use std::path::PathBuf;
3333
use 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.

src/app/tile/elm.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rayon::{
1616
};
1717

1818
use crate::app::apps::AppCommand;
19+
use crate::app::tile::AppIndex;
1920
use crate::config::Theme;
2021
use crate::{
2122
app::{Message, Page, apps::App, default_settings, tile::Tile},
@@ -59,12 +60,12 @@ pub fn new(hotkey: HotKey, config: &Config) -> (Tile, Task<Message>) {
5960
options.extend(config.shells.iter().map(|x| x.to_app()));
6061
options.extend(App::basic_apps());
6162
options.par_sort_by_key(|x| x.name.len());
63+
let options = AppIndex::from_apps(options);
6264

6365
(
6466
Tile {
6567
query: String::new(),
6668
query_lc: String::new(),
67-
prev_query_lc: String::new(),
6869
focus_id: 0,
6970
results: vec![],
7071
options,
@@ -119,11 +120,12 @@ pub fn view(tile: &Tile, wid: window::Id) -> Element<'_, Message> {
119120
let results = match tile.page {
120121
Page::Main => {
121122
let mut search_results = Column::new();
122-
let mut i = 0_u32;
123-
for result in &tile.results {
124-
search_results =
125-
search_results.push(result.render(&tile.config.theme, i, tile.focus_id));
126-
i += 1;
123+
for (i, result) in tile.results.iter().enumerate() {
124+
search_results = search_results.push(result.render(
125+
&tile.config.theme,
126+
i as u32,
127+
tile.focus_id,
128+
));
127129
}
128130
search_results
129131
}

src/app/tile/update.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::app::apps::App;
2323
use crate::app::apps::AppCommand;
2424
use crate::app::default_settings;
2525
use crate::app::menubar::menu_icon;
26+
use crate::app::tile::AppIndex;
2627
use crate::app::tile::elm::default_app_paths;
2728
use crate::calculator::Expression;
2829
use crate::commands::Function;
@@ -190,7 +191,7 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
190191
height: ((max_elem * 55) + DEFAULT_WINDOW_HEIGHT as usize) as f32,
191192
},
192193
),
193-
Task::done(Message::ChangeFocus(ArrowKey::ArrowLeft)),
194+
Task::done(Message::ChangeFocus(ArrowKey::Left)),
194195
])
195196
} else if tile.page == Page::ClipboardHistory {
196197
let element_count = min(tile.clipboard_content.len(), 5);
@@ -216,8 +217,8 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
216217
let u32_len = tile.results.len() as u32;
217218
if u32_len > 0 {
218219
match key {
219-
ArrowKey::ArrowDown => tile.focus_id = (tile.focus_id + 1) % u32_len,
220-
ArrowKey::ArrowUp => tile.focus_id = (tile.focus_id + u32_len - 1) % u32_len,
220+
ArrowKey::Down => tile.focus_id = (tile.focus_id + 1) % u32_len,
221+
ArrowKey::Up => tile.focus_id = (tile.focus_id + u32_len - 1) % u32_len,
221222
_ => {}
222223
}
223224

@@ -263,8 +264,7 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
263264

264265
tile.theme = new_config.theme.to_owned().into();
265266
tile.config = new_config;
266-
tile.options = new_options;
267-
267+
tile.options = AppIndex::from_apps(new_options);
268268
Task::none()
269269
}
270270

0 commit comments

Comments
 (0)