1use once_cell::sync::Lazy;
2
3#[derive(Clone, Copy, Debug)]
5pub struct SlashCommandInfo {
6 pub name: &'static str,
7 pub description: &'static str,
8}
9
10pub static SLASH_COMMANDS: Lazy<Vec<SlashCommandInfo>> = Lazy::new(|| {
12 vec![
13 SlashCommandInfo {
14 name: "init",
15 description: "Create vtcode.toml and index the workspace (usage: /init [--force])",
16 },
17 SlashCommandInfo {
18 name: "config",
19 description: "View the effective vtcode.toml configuration",
20 },
21 SlashCommandInfo {
22 name: "theme",
23 description: "Switch UI theme (usage: /theme <theme-id>)",
24 },
25 SlashCommandInfo {
26 name: "list-themes",
27 description: "List all available UI themes",
28 },
29 SlashCommandInfo {
30 name: "command",
31 description: "Run a terminal command (usage: /command <program> [args...])",
32 },
33 SlashCommandInfo {
34 name: "sessions",
35 description: "List recent archived sessions (usage: /sessions [limit])",
36 },
37 SlashCommandInfo {
38 name: "help",
39 description: "Show slash command help",
40 },
41 SlashCommandInfo {
42 name: "exit",
43 description: "Exit the session",
44 },
45 ]
46});
47
48pub fn suggestions_for(prefix: &str) -> Vec<&'static SlashCommandInfo> {
50 if prefix.is_empty() {
51 return SLASH_COMMANDS.iter().collect();
52 }
53 let query = prefix.to_ascii_lowercase();
54 let mut matches: Vec<&SlashCommandInfo> = SLASH_COMMANDS
55 .iter()
56 .filter(|info| info.name.starts_with(&query))
57 .collect();
58 if matches.is_empty() {
59 SLASH_COMMANDS.iter().collect()
60 } else {
61 matches.sort_by(|a, b| a.name.cmp(b.name));
62 matches
63 }
64}