1use crate::state::{AppState, DialogOption, SelectKind};
2
3const KEYS: &[(&str, &str)] = &[
4 ("Enter", "Submit message"),
5 ("Esc", "Vim normal mode / 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 ("/quit, /exit", "Exit session"),
27 ("/version", "Show version"),
28 ("/model [name]", "Switch model"),
29 ("/mode", "Cycle permission mode"),
30 ("/think", "Toggle extended thinking"),
31 ("/effort low|medium|high|max", "Set effort level"),
32 ("/fast", "Toggle fast mode"),
33 ("/plan [task]", "Toggle plan mode"),
34 ("/compact", "Compact context"),
35 ("/cost", "Show usage and cost"),
36 ("/diff", "Show git diff"),
37 ("/status", "Show git status"),
38 ("/review", "Review current diff"),
39 ("/commit", "Generate commit message"),
40 ("/memory", "Show CLAUDE.md"),
41 ("/init", "Create / update CLAUDE.md"),
42 ("/add <path>", "Pin a file to every message"),
43 ("/files", "List pinned files"),
44 ("/skills", "List available skills"),
45 ("/session", "Manage sessions"),
46 ("/rewind [n]", "Remove last n exchanges"),
47 ("/export", "Export conversation"),
48 ("/copy", "Copy last response"),
49 ("/undo [n]", "Restore last n file edits"),
50 ("/config", "Show merged config"),
51 ("/permissions", "Show allow / deny rules"),
52];
53
54pub fn open_help(state: &mut AppState, skills: &[(String, String)]) {
55 let mut options: Vec<DialogOption> = Vec::new();
56 for (key, desc) in KEYS {
57 options.push(
58 DialogOption::new(format!("k:{key}"), key.to_string())
59 .with_description(desc.to_string())
60 .with_category("Keyboard"),
61 );
62 }
63 for (cmd, desc) in SLASH {
64 options.push(
65 DialogOption::new(format!("s:{cmd}"), cmd.to_string())
66 .with_description(desc.to_string())
67 .with_category("Slash"),
68 );
69 }
70 for (name, desc) in skills {
71 options.push(
72 DialogOption::new(format!("sk:{name}"), format!("/{name}"))
73 .with_description(desc.clone())
74 .with_category("Skills"),
75 );
76 }
77 state.modal.open_select(
78 SelectKind::Help,
79 "Help",
80 options,
81 None,
82 Some("type to filter".to_string()),
83 );
84}