1use crate::state::{AppState, DialogOption, SelectKind};
2
3const KEYS: &[(&str, &str)] = &[
4 ("Enter", "Submit message"),
5 ("Esc", "Interrupt / close modal"),
6 ("Shift+Tab", "Cycle permission mode"),
7 ("Ctrl+C", "Quit"),
8 ("Ctrl+P", "Command palette"),
9 ("Ctrl+S", "Session list"),
10 ("Ctrl+M", "Model picker"),
11 ("Ctrl+B", "Toggle sidebar"),
12 ("PgUp / PgDn", "Scroll messages by page"),
13 ("Shift+↑ / Shift+↓", "Scroll messages by line"),
14 ("Ctrl+Alt+u / Ctrl+Alt+d", "Scroll messages by half page"),
15 ("Tab", "Accept input suggestion"),
16 ("Ctrl+U", "Clear input"),
17 ("Ctrl+W", "Delete previous word"),
18 ("Ctrl+A / Home", "Cursor to line start"),
19 ("Ctrl+E / End", "Cursor to line end"),
20 ("Alt+← / Alt+→", "Word jump"),
21];
22
23const SLASH: &[(&str, &str)] = &[
24 ("/help", "Show this help"),
25 ("/intern <task>", "Delegate task to intern model (DeepSeek)"),
26 ("/intern-bench [name]", "Benchmark & rank interns by capability"),
27 ("/quit, /exit", "Exit session"),
28 ("/version", "Show version"),
29 ("/model [name]", "Switch model"),
30 ("/mode", "Cycle permission mode"),
31 ("/think", "Toggle extended thinking"),
32 ("/effort low|medium|high|max", "Set effort level"),
33 ("/fast", "Toggle fast mode"),
34 ("/plan [task]", "Toggle plan mode"),
35 ("/compact", "Compact context"),
36 ("/cost", "Show usage and cost"),
37 ("/diff", "Show git diff"),
38 ("/status", "Show git status"),
39 ("/review", "Review current diff"),
40 ("/commit", "Generate commit message"),
41 ("/memory", "Show CLAUDE.md"),
42 ("/init", "Create / update CLAUDE.md"),
43 ("/add <path>", "Pin a file to every message"),
44 ("/files", "List pinned files"),
45 ("/skills", "List available skills"),
46 ("/session", "Manage sessions"),
47 ("/rewind [n]", "Remove last n exchanges"),
48 ("/export", "Export conversation"),
49 ("/copy", "Copy last response"),
50 ("/undo [n]", "Restore last n file edits"),
51 ("/config", "Show merged config"),
52 ("/permissions", "Show allow / deny rules"),
53];
54
55pub fn open_help(state: &mut AppState, skills: &[(String, String)]) {
56 let mut options: Vec<DialogOption> = Vec::new();
57 for (key, desc) in KEYS {
58 options.push(
59 DialogOption::new(format!("k:{key}"), key.to_string())
60 .with_description(desc.to_string())
61 .with_category("Keyboard"),
62 );
63 }
64 for (cmd, desc) in SLASH {
65 options.push(
66 DialogOption::new(format!("s:{cmd}"), cmd.to_string())
67 .with_description(desc.to_string())
68 .with_category("Slash"),
69 );
70 }
71 for (name, desc) in skills {
72 options.push(
73 DialogOption::new(format!("sk:{name}"), format!("/{name}"))
74 .with_description(desc.clone())
75 .with_category("Skills"),
76 );
77 }
78 state.modal.open_select(
79 SelectKind::Help,
80 "Help",
81 options,
82 None,
83 Some("type to filter".to_string()),
84 );
85}