Skip to content

Commit a273333

Browse files
committed
Working math
1 parent 30b2eba commit a273333

8 files changed

Lines changed: 147 additions & 48 deletions

File tree

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ edition = "2024"
55

66
[dependencies]
77
dirs = "6.0.0"
8+
evalexpr = "13.1.0"
89
freedesktop-desktop-entry = { version = "0.7.13", default-features = false }
910
freedesktop-icons = "0.4.0"
1011
gpui = { git = "https://github.com/zed-industries/zed", default-features = false, features = ["wayland"] }

src/finder/desktop/entry.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use std::path::PathBuf;
33
use std::process::{Command, Stdio};
44
use std::rc::Rc;
55

6-
use freedesktop_icons::lookup;
76
use gpui::{App, Resource, SharedString};
87
use nucleo_matcher::Utf32String;
98

@@ -23,24 +22,20 @@ pub struct DesktopEntry {
2322
}
2423

2524
impl Entry for DesktopEntry {
26-
fn id(&self) -> &SharedString {
27-
&self.id
25+
fn id(&self) -> SharedString {
26+
self.id.clone()
2827
}
2928

30-
fn text(&self) -> &SharedString {
31-
&self.name
29+
fn text(&self) -> SharedString {
30+
self.name.clone()
3231
}
3332

34-
fn description(&self) -> Option<&SharedString> {
35-
self.description.as_ref()
33+
fn description(&self) -> Option<SharedString> {
34+
self.description.clone()
3635
}
3736

38-
fn icon(&self) -> Option<&Resource> {
39-
self.icon.as_ref()
40-
}
41-
42-
fn haystack(&self) -> nucleo_matcher::Utf32Str<'_> {
43-
self.haystack.slice(..)
37+
fn icon(&self) -> Option<Resource> {
38+
self.icon.clone()
4439
}
4540

4641
fn can_favorite(&self) -> bool {
@@ -49,7 +44,7 @@ impl Entry for DesktopEntry {
4944

5045
fn execute(&self, cx: &mut App) -> EntryExecuteResult {
5146
cx.global_mut::<SearchEntries>()
52-
.increment_frequency(self.id());
47+
.increment_frequency(&self.id);
5348

5449
let config = cx.global::<Config>();
5550
let mut cmd = if self.open_in_terminal {
@@ -110,7 +105,12 @@ impl DesktopEntry {
110105
.map(|description| SharedString::from(description.into_owned()));
111106
let icon = entry
112107
.icon()
113-
.and_then(|icon| lookup(icon).with_cache().with_size(28).find())
108+
.and_then(|icon| {
109+
freedesktop_icons::lookup(icon)
110+
.with_cache()
111+
.with_size(28)
112+
.find()
113+
})
114114
.map(|path| Resource::Path(path.into()));
115115
let haystack = Utf32String::from(match description {
116116
Some(ref d) => name.to_string() + " " + d.as_str(),

src/finder/desktop/mod.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ impl SearchEntries {
4242
pub fn favorites(&self) -> Vec<Rc<dyn Entry>> {
4343
self.favorites
4444
.iter()
45-
.filter_map(|id| self.entries.iter().find(|entry| entry.id() == id))
45+
.filter_map(|id| self.entries.iter().find(|entry| entry.id == *id))
4646
.map(|e| e.clone() as Rc<dyn Entry>)
4747
.collect()
4848
}
@@ -70,15 +70,20 @@ impl Finder for SearchEntries {
7070
}
7171
}
7272

73-
fn default_entries(&self) -> impl Iterator<Item = Rc<dyn Entry>> {
74-
self.entries.iter().map(|e| e.clone() as Rc<dyn Entry>)
73+
fn default_entries(&self) -> Option<Vec<Rc<dyn Entry>>> {
74+
Some(
75+
self.entries
76+
.iter()
77+
.map(|e| e.clone() as Rc<dyn Entry>)
78+
.collect(),
79+
)
7580
}
7681

7782
fn filtered_entries(
7883
&self,
7984
matcher: &mut nucleo_matcher::Matcher,
8085
search_term: &str,
81-
) -> impl Iterator<Item = Rc<dyn Entry>> {
86+
) -> Option<Vec<Rc<dyn Entry>>> {
8287
let search_pattern = Pattern::new(
8388
search_term,
8489
CaseMatching::Ignore,
@@ -92,14 +97,18 @@ impl Finder for SearchEntries {
9297
.enumerate()
9398
.filter_map(|(idx, entry)| {
9499
search_pattern
95-
.score(entry.haystack(), matcher)
100+
.score(entry.haystack.slice(..), matcher)
96101
.map(|score| (idx, score))
97102
})
98103
.collect();
99104
result.sort_by_key(|(_, score)| Reverse(*score));
100-
result
101-
.into_iter()
102-
.map(|(i, _)| self.entries[i].clone() as Rc<dyn Entry>)
105+
106+
Some(
107+
result
108+
.into_iter()
109+
.map(|(i, _)| self.entries[i].clone() as Rc<dyn Entry>)
110+
.collect(),
111+
)
103112
}
104113
}
105114

src/finder/math/entry.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use gpui::{App, Resource, SharedString};
2+
3+
use crate::finder::{Entry, EntryExecuteResult};
4+
5+
pub struct MathEntry {
6+
pub result: SharedString,
7+
}
8+
9+
impl Entry for MathEntry {
10+
fn id(&self) -> SharedString {
11+
self.result.clone()
12+
}
13+
14+
fn text(&self) -> SharedString {
15+
self.result.clone()
16+
}
17+
18+
fn description(&self) -> Option<SharedString> {
19+
None
20+
}
21+
22+
fn icon(&self) -> Option<Resource> {
23+
None
24+
}
25+
26+
fn can_favorite(&self) -> bool {
27+
false
28+
}
29+
30+
fn execute(&self, cx: &mut App) -> EntryExecuteResult {
31+
cx.write_to_clipboard(self.result.to_string().into());
32+
EntryExecuteResult::CloseWindow
33+
}
34+
}

src/finder/math/mod.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use std::rc::Rc;
2+
3+
use crate::finder::{Entry, Finder, math::entry::MathEntry};
4+
5+
mod entry;
6+
7+
pub struct MathFinder {}
8+
9+
impl Finder for MathFinder {
10+
fn new() -> Self {
11+
Self {}
12+
}
13+
14+
fn default_entries(&self) -> Option<Vec<Rc<dyn Entry>>> {
15+
None
16+
}
17+
18+
fn filtered_entries(
19+
&self,
20+
_matcher: &mut nucleo_matcher::Matcher,
21+
search_term: &str,
22+
) -> Option<Vec<Rc<dyn Entry>>> {
23+
let search_term = search_term.strip_prefix('=')?;
24+
let value = evalexpr::eval(search_term).ok()?;
25+
26+
Some(vec![Rc::new(MathEntry {
27+
result: value.to_string().into(),
28+
})])
29+
}
30+
}

src/finder/mod.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,44 @@ use std::rc::Rc;
22

33
use gpui::{App, Resource, SharedString};
44

5+
use crate::finder::desktop::SearchEntries;
6+
use crate::finder::math::MathFinder;
7+
58
pub mod desktop;
9+
pub mod math;
10+
11+
pub fn default_finders() -> Vec<Box<dyn Finder>> {
12+
vec![Box::new(SearchEntries::new()), Box::new(MathFinder::new())]
13+
}
614

715
pub trait Finder {
8-
fn new() -> Self;
16+
fn new() -> Self
17+
where
18+
Self: Sized;
919

1020
/// Returns the entries when no search is performed.
11-
fn default_entries(&self) -> impl Iterator<Item = Rc<dyn Entry>>;
21+
fn default_entries(&self) -> Option<Vec<Rc<dyn Entry>>>;
1222

1323
/// Returns the entries that match the given pattern.
1424
fn filtered_entries(
1525
&self,
1626
matcher: &mut nucleo_matcher::Matcher,
1727
search_term: &str,
18-
) -> impl Iterator<Item = Rc<dyn Entry>>;
28+
) -> Option<Vec<Rc<dyn Entry>>>;
1929
}
2030

2131
pub trait Entry {
2232
/// Get a unique identifier for this entry.
23-
fn id(&self) -> &SharedString;
33+
fn id(&self) -> SharedString;
2434

2535
/// Get the main text of this entry.
26-
fn text(&self) -> &SharedString;
36+
fn text(&self) -> SharedString;
2737

2838
/// Get the subtle description of this entry.
29-
fn description(&self) -> Option<&SharedString>;
39+
fn description(&self) -> Option<SharedString>;
3040

3141
/// Get the icon of this entry.
32-
fn icon(&self) -> Option<&Resource>;
33-
34-
/// Get the text to use for searching this entry.
35-
fn haystack(&self) -> nucleo_matcher::Utf32Str<'_>;
42+
fn icon(&self) -> Option<Resource>;
3643

3744
/// If this entry can be favorited.
3845
fn can_favorite(&self) -> bool;

src/ui/waystart.rs

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use gpui::{
1010

1111
use crate::config::Config;
1212
use crate::finder::desktop::SearchEntries;
13-
use crate::finder::{Entry, EntryExecuteResult, Finder};
13+
use crate::finder::{Entry, EntryExecuteResult, Finder, default_finders};
1414
use crate::ui::actions::{Close, ExecuteEntry, SelectNextEntry, SelectPrevEntry, ToggleFavorite};
1515
use crate::ui::elements::{EntryButton, Icon, PowerOptions, Separator, Shortcut, TextInput};
1616

@@ -34,6 +34,8 @@ pub struct Waystart {
3434
list_scroll_handle: UniformListScrollHandle,
3535
search_bar: Entity<TextInput>,
3636
selected: usize,
37+
38+
finders: Vec<Box<dyn Finder>>,
3739
matcher: RefCell<nucleo_matcher::Matcher>,
3840
}
3941

@@ -51,10 +53,12 @@ impl Waystart {
5153

5254
Self {
5355
focus_handle,
54-
entries: cx.global::<SearchEntries>().default_entries().collect(),
56+
entries: cx.global::<SearchEntries>().default_entries().unwrap(),
5557
list_scroll_handle: UniformListScrollHandle::new(),
5658
search_bar,
5759
selected: 0,
60+
61+
finders: default_finders(),
5862
matcher: RefCell::new(nucleo_matcher::Matcher::default()),
5963
}
6064
}
@@ -66,21 +70,28 @@ impl Waystart {
6670
}
6771

6872
fn filter_results(&mut self, cx: &mut Context<Self>) {
69-
if let Some(entries) = cx.try_global::<SearchEntries>() {
70-
self.entries.clear();
71-
let search_term = self.search_bar.read(cx).content().trim();
73+
self.entries.clear();
74+
let search_term = self.search_bar.read(cx).content().trim();
7275

73-
if search_term.is_empty() {
74-
self.entries.extend(entries.default_entries());
75-
} else {
76-
let mut matcher = self.matcher.borrow_mut();
77-
self.entries
78-
.extend(entries.filtered_entries(&mut matcher, search_term));
79-
}
80-
81-
self.selected = 0;
82-
cx.notify();
76+
if search_term.is_empty() {
77+
self.entries.extend(
78+
self.finders
79+
.iter()
80+
.filter_map(|finder| finder.default_entries())
81+
.flatten(),
82+
);
83+
} else {
84+
let mut matcher = self.matcher.borrow_mut();
85+
self.entries.extend(
86+
self.finders
87+
.iter()
88+
.filter_map(|finder| finder.filtered_entries(&mut matcher, search_term))
89+
.flatten(),
90+
);
8391
}
92+
93+
self.selected = 0;
94+
cx.notify();
8495
}
8596

8697
fn on_close(_: &Close, window: &mut Window, _cx: &mut App) {

0 commit comments

Comments
 (0)