Skip to content

Commit 435d102

Browse files
authored
Merge pull request #676 from multiplex55/codex/refactor-help-window-and-command-examples
Make Command Help data-driven from plugin commands and remove dashboard tip
2 parents e2b048e + e7a3324 commit 435d102

1 file changed

Lines changed: 76 additions & 109 deletions

File tree

src/help_window.rs

Lines changed: 76 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
use crate::actions::Action;
12
use crate::gui::LauncherApp;
23
use eframe::egui;
4+
use std::collections::HashSet;
35

46
#[derive(Default)]
57
pub struct HelpWindow {
@@ -70,12 +72,6 @@ impl HelpWindow {
7072
.show(ctx, |ui| {
7173
ui.vertical_centered(|ui| ui.heading("Available commands"));
7274
ui.separator();
73-
ui.label(
74-
"Tip: Settings \u{2192} Dashboard \u{2192} Customize Dashboard... opens the \
75-
widget editor where you can configure plugin-aware defaults for notes, todos \
76-
or weather.",
77-
);
78-
ui.separator();
7975
if ui
8076
.checkbox(&mut self.show_examples, "Show examples")
8177
.changed()
@@ -90,27 +86,47 @@ impl HelpWindow {
9086
ui.text_edit_singleline(&mut self.filter);
9187
});
9288
ui.separator();
89+
let mut command_map = std::collections::HashMap::new();
90+
for plugin in app.plugins.iter() {
91+
command_map.insert(plugin.name().to_string(), plugin.commands());
92+
}
9393
let mut infos = app.plugins.plugin_infos();
9494
infos.sort_by(|a, b| a.0.cmp(&b.0));
9595
let area_height = ui.available_height();
9696
egui::ScrollArea::vertical()
9797
.max_height(area_height)
9898
.show(ui, |ui| {
9999
let filt = self.filter.to_lowercase();
100-
for (name, desc, _) in infos {
101-
if !filt.is_empty()
102-
&& !name.to_lowercase().contains(&filt)
103-
&& !desc.to_lowercase().contains(&filt)
104-
{
100+
for (name, desc, capabilities) in infos {
101+
let commands = command_map.get(&name).cloned().unwrap_or_default();
102+
if !matches_filter(&filt, &name, &desc, &capabilities, &commands) {
105103
continue;
106104
}
105+
let prefixes = command_prefixes(&commands);
107106
ui.label(egui::RichText::new(&name).strong());
108107
ui.label(desc);
109-
if self.show_examples {
110-
if let Some(examples) = example_queries(&name) {
111-
for ex in examples {
112-
ui.monospace(format!(" {ex}"));
113-
}
108+
if capabilities.is_empty() {
109+
ui.label("Capabilities: none");
110+
} else {
111+
ui.label(format!("Capabilities: {}", capabilities.join(", ")));
112+
}
113+
if prefixes.is_empty() {
114+
ui.label("Prefixes: none");
115+
} else {
116+
ui.label(format!("Prefixes: {}", prefixes.join(", ")));
117+
}
118+
if commands.is_empty() {
119+
ui.label("Usage: none");
120+
} else {
121+
ui.label("Usage:");
122+
for command in &commands {
123+
ui.monospace(format!(" {}", command.label));
124+
}
125+
}
126+
if self.show_examples && !commands.is_empty() {
127+
ui.label("Examples:");
128+
for command in &commands {
129+
ui.monospace(format!(" {}", example_line(command)));
114130
}
115131
}
116132
ui.separator();
@@ -121,98 +137,49 @@ impl HelpWindow {
121137
}
122138
}
123139

124-
fn example_queries(name: &str) -> Option<&'static [&'static str]> {
125-
match name {
126-
"web_search" => Some(&["g rust"]),
127-
"runescape_search" => Some(&["rs dragon scimitar", "osrs agility guide"]),
128-
"youtube" => Some(&["yt rust"]),
129-
"reddit" => Some(&["red cats"]),
130-
"calculator" => Some(&["= 1+2", "= history"]),
131-
"unit_convert" => Some(&[
132-
"conv 10 km to mi",
133-
"conv 1 kwh to j",
134-
"conv 8 bit to byte",
135-
"conv 30 mpg to kpl",
136-
"conv 180 deg to rad",
137-
]),
138-
"base_convert" => Some(&[
139-
"conv 1010 bin to hex",
140-
"conv ff hex to bin",
141-
"conv \"hello\" text to hex",
142-
"conv 48656c6c6f hex to text",
143-
"conv 42 dec to bin",
144-
]),
145-
"clipboard" => Some(&["cb"]),
146-
"bookmarks" => Some(&["bm add https://example.com", "bm rm", "bm list"]),
147-
"folders" => Some(&["f add C:/path", "f rm docs"]),
148-
"shell" => Some(&["sh", "sh echo hello"]),
149-
"system" => Some(&["sys shutdown"]),
150-
"sysinfo" => Some(&["info", "info cpu", "info cpu list 5"]),
151-
"network" => Some(&["net"]),
152-
"weather" => Some(&["weather Berlin"]),
153-
"history" => Some(&["hi"]),
154-
"timer" => Some(&[
155-
"timer add <duration> [name]",
156-
"timer add 10s tea",
157-
"timer add 5m",
158-
"timer add 1:30",
159-
"durations: s/m/h or hh:mm:ss/mm:ss",
160-
"alarm <HH:MM> [name]",
161-
"alarm 07:30 wake up",
162-
"timer list # show active timers",
163-
"alarm list # show active alarms",
164-
"timer pause <id> # pause a timer",
165-
"timer resume <id> # resume a timer",
166-
"timer cancel # cancel timers/alarms",
167-
"timer rm # remove timers",
168-
]),
169-
"notes" => Some(&[
170-
"note",
171-
"note add buy milk",
172-
"note new buy milk",
173-
"note create buy milk",
174-
"note list",
175-
"note rm groceries",
176-
"notes unused",
177-
]),
178-
"volume" => Some(&["vol 50"]),
179-
"brightness" => Some(&["bright 50"]),
180-
"asciiart" => Some(&["ascii hello"]),
181-
"screenshot" => Some(&[
182-
"ss",
183-
"ss clip",
184-
"Editor: drag to crop, Shift+drag to annotate, use slider to zoom, then Save or Copy",
185-
]),
186-
"processes" => Some(&["ps", "ps firefox"]),
187-
"dropcalc" => Some(&["drop 1/128 25"]),
188-
"recycle" => Some(&["rec"]),
189-
"tempfile" => Some(&["tmp new", "tmp create"]),
190-
"timestamp" => Some(&[
191-
"ts 0",
192-
"ts 2024-05-01 12:00",
193-
"tsm 3600000",
194-
"tsm 01:00:00.500",
195-
]),
196-
"snippets" => Some(&["cs hello"]),
197-
"favorites" => Some(&["fav add mycmd", "fav list"]),
198-
"browser_tabs" => Some(&["tab", "tab cache"]),
199-
"emoji" => Some(&["emoji smile", "emoji list heart"]),
200-
"ip" => Some(&["ip", "ip public"]),
201-
"lorem" => Some(&["lorem w 5", "lorem s 2"]),
202-
"macros" => Some(&["macro list", "macro mymacro"]),
203-
"omni_search" => Some(&["o list", "o list docs"]),
204-
"random" => Some(&["rand number 10", "rand dice", "rand pw 8"]),
205-
"settings" => Some(&["settings"]),
206-
"stopwatch" => Some(&["sw start", "sw list"]),
207-
"task_manager" => Some(&["tm"]),
208-
"text_case" => Some(&["case snake Hello World"]),
209-
"todo" => Some(&[
210-
"todo add buy milk @home",
211-
"todo list",
212-
"todo list @testing @ui",
213-
]),
214-
"wikipedia" => Some(&["wiki rust"]),
215-
"help" => Some(&["help"]),
216-
_ => None,
140+
fn matches_filter(
141+
filter: &str,
142+
name: &str,
143+
desc: &str,
144+
capabilities: &[String],
145+
commands: &[Action],
146+
) -> bool {
147+
if filter.is_empty() {
148+
return true;
149+
}
150+
let filter = filter.to_lowercase();
151+
if name.to_lowercase().contains(&filter) || desc.to_lowercase().contains(&filter) {
152+
return true;
153+
}
154+
if capabilities
155+
.iter()
156+
.any(|cap| cap.to_lowercase().contains(&filter))
157+
{
158+
return true;
159+
}
160+
commands.iter().any(|command| {
161+
command.label.to_lowercase().contains(&filter)
162+
|| command.desc.to_lowercase().contains(&filter)
163+
|| command.action.to_lowercase().contains(&filter)
164+
})
165+
}
166+
167+
fn command_prefixes(commands: &[Action]) -> Vec<String> {
168+
let mut prefixes = HashSet::new();
169+
for command in commands {
170+
if let Some(prefix) = command.label.split_whitespace().next() {
171+
prefixes.insert(prefix.to_string());
172+
}
173+
}
174+
let mut out: Vec<String> = prefixes.into_iter().collect();
175+
out.sort();
176+
out
177+
}
178+
179+
fn example_line(command: &Action) -> String {
180+
if let Some(query) = command.action.strip_prefix("query:") {
181+
query.trim().to_string()
182+
} else {
183+
command.label.clone()
217184
}
218185
}

0 commit comments

Comments
 (0)