use super::focus::Focus;
#[derive(Debug, Clone, Copy)]
pub struct Entry {
pub key: &'static str,
pub desc: &'static str,
pub is_header: bool,
}
const fn entry(key: &'static str, desc: &'static str) -> Entry {
Entry {
key,
desc,
is_header: false,
}
}
const fn header(label: &'static str) -> Entry {
Entry {
key: label,
desc: "",
is_header: true,
}
}
pub fn entries_for(focus: Focus) -> Vec<Entry> {
let mut out: Vec<Entry> = Vec::new();
out.extend_from_slice(&global_entries());
out.push(header("")); match focus {
Focus::Tree | Focus::SearchBar => {
out.push(header("─── Tree ───"));
out.extend_from_slice(&tree_entries());
}
Focus::Editor => {
out.push(header("─── Editor ───"));
out.extend_from_slice(&editor_entries());
}
Focus::Ai | Focus::AiPrompt => {
out.push(header("─── AI ───"));
out.extend_from_slice(&ai_entries());
}
}
out
}
fn global_entries() -> [Entry; 27] {
[
header("─── Global ───"),
entry("Ctrl+Q", "Quit (autosaves dirty paragraph)"),
entry("Tab / Shift+Tab", "Cycle Tree → Editor → AI"),
entry("Ctrl+1/2/3/4/5", "Focus Editor/Tree/AI/Search/AI-prompt"),
entry("Ctrl+T", "Focus Tree (Ctrl+2 alternative)"),
entry("Ctrl+S", "Save current paragraph"),
entry("Ctrl+/", "Focus Search bar"),
entry("Ctrl+I", "Focus AI prompt"),
entry("Ctrl+B", "Meta prefix (next key = action)"),
entry("Ctrl+B H", "This Quick reference (works from every pane)"),
entry("Ctrl+B V", "Version, author, and component credits"),
entry("Ctrl+B I", "Current book info (paths · stats · PDF status)"),
entry("Ctrl+B L", "Switch LLM provider (writes to inkhaven.hjson)"),
entry("Ctrl+B E", "Toggle typewriter SFX (writes to inkhaven.hjson)"),
entry("Ctrl+B A", "Book assembly — emit a typst-compilable tree"),
entry("Ctrl+B B", "Build the book — assemble + typst compile"),
entry("Ctrl+B O", "Take the book — build + copy PDF to cwd"),
entry("Ctrl+B 1..7", "Scoped status filter — list paragraphs by status under tree cursor (r/-/Enter act on rows)"),
entry("Ctrl+B W", "Toggle full-screen typewriter mode (hides every other pane)"),
entry("Ctrl+B K", "Toggle full-screen AI mode (AI pane | chat history + AI prompt)"),
entry("Ctrl+F", "(in AI fullscreen) Search chat history — Ctrl+X for next (older) match"),
entry("Ctrl+C", "(in AI fullscreen) Selection mode — ↑↓ pick turn · c=copy · t=insert into editor"),
entry("F1", "Help-manual question (RAG over the Help book)"),
entry("F7", "Grammar check the open paragraph (→ AI pane)"),
entry("F9", "Cycle AI scope: None→Sel→Para→Sub→Chap→Book→None"),
entry("F10", "Toggle inference: Local↔Full (Help locked to Local)"),
entry("Esc", "Close overlay / cancel"),
]
}
fn tree_entries() -> [Entry; 35] {
[
entry("↑ / ↓ / Home / End", "Navigate"),
entry("PageUp / PageDown", "Jump by 10"),
entry("← / →", "Collapse / expand branch (← steps to parent)"),
entry("Enter", "Open paragraph (autosaves the previous one)"),
entry("F2", "Rename current node"),
entry("F3", "File picker — load file or import directory tree (progress splash)"),
header(""),
header("─ Hierarchy edits ─"),
entry("B / C / A / +", "Add book / chapter / subchapter / paragraph"),
entry("V / S / P", "Insert chapter / subchapter / paragraph after current"),
entry("D", "Delete branch at cursor (asks for confirmation)"),
entry("-", "Delete paragraph at cursor"),
header(""),
header("─ Reorder ─"),
entry("U", "Move current node up among siblings"),
entry("J", "Move current node down among siblings"),
header(""),
header("─ Folding ─"),
entry("← / →", "Collapse / expand cursor's branch"),
entry("Z", "Collapse cursor's enclosing subchapter"),
entry("X", "Collapse every expanded branch"),
header(""),
header("─ Tree meta (Ctrl+B …) ─"),
entry("Ctrl+B C/S/P", "Add chapter / subchapter / paragraph (plain B adds book)"),
entry("Ctrl+B D", "Delete cursor's node"),
entry("Ctrl+B ↑ / ↓", "Reorder within siblings (chord form of U / J)"),
entry("Ctrl+B H", "Open this Quick reference"),
entry("Ctrl+B V", "Version / author / credits panel"),
entry("Ctrl+B I", "Current book info (paths · stats · PDF status)"),
entry("Ctrl+B L", "Switch LLM provider (writes to inkhaven.hjson)"),
entry("Ctrl+B E", "Toggle typewriter SFX (writes to inkhaven.hjson)"),
entry("Ctrl+B A", "Book assembly — emit a typst-compilable tree"),
entry("Ctrl+B B", "Build the book (assemble + typst compile)"),
entry("Ctrl+B O", "Take the book — copy PDF to cwd"),
entry("q", "Quit (autosaves if dirty)"),
]
}
fn editor_entries() -> [Entry; 57] {
[
entry("arrows", "Move cursor"),
entry("Ctrl+← / →", "Word back / forward"),
entry("Ctrl+Home / End", "File top / bottom"),
entry("Home / End", "Start / end of line"),
entry("PageUp / PageDown", "By paragraph"),
entry("Shift+arrows", "Extend linear selection"),
entry("Ctrl+A", "Select all"),
entry("Esc", "Clear in-buffer search (first press); cycle to Tree"),
header(""),
header("─ Clipboard ─"),
entry("Ctrl+C", "Copy selection (system clipboard)"),
entry("Ctrl+K", "Cut selection"),
entry("Ctrl+P", "Paste at cursor"),
header(""),
header("─ Edit ─"),
entry("Ctrl+U", "Undo"),
entry("Ctrl+Y", "Redo"),
entry("Ctrl+D", "Delete current line"),
entry("Ctrl+E", "Delete cursor → end of line"),
entry("Ctrl+W", "Delete cursor → start of line"),
entry("Ctrl+Backspace", "Delete previous word"),
header(""),
header("─ Find / Replace (regex) ─"),
entry("Ctrl+F", "Open Find (regex)"),
entry("Ctrl+X", "Repeat — next match / replace+next"),
entry("Ctrl+R", "Open Replace · or replace all (while in replace mode)"),
header(""),
header("─ Block selection ─"),
entry("Alt+arrows", "Extend rectangular selection"),
entry("Alt+C", "Copy rectangular block"),
header(""),
header("─ Files & snapshots ─"),
entry("F3", "Load file → replace buffer (Ctrl+B F also toggles split)"),
entry("F4 / Ctrl+F4", "Toggle split / accept split snapshot"),
entry("F5", "Snapshot the current paragraph (== Ctrl+B N)"),
entry(
"F6",
"Snapshot picker — ↑↓ navigate · Enter load · D / Del delete · Esc close",
),
entry("Ctrl+H / Ctrl+J", "(split only) scroll lower pane up / down"),
header(""),
header("─ Editor meta (Ctrl+B …) ─"),
entry("Ctrl+B S", "Save (alternative to Ctrl+S)"),
entry("Ctrl+B N", "New snapshot of current paragraph"),
entry("Ctrl+B R", "Cycle paragraph status: None→Napkin→First→Second→Third→Final→Ready"),
entry("F6", "Snapshot history picker (was Ctrl+B R until 1.1)"),
entry("Ctrl+B F", "Typst function picker — type to filter, Enter inserts #name(…)"),
entry("Ctrl+B T", "Retitle paragraph from its first sentence"),
entry(
"Ctrl+B P",
"Inside #image(\"…\"): pick a sibling image — else Place RAG",
),
entry("Ctrl+B C", "Character RAG — selection → Characters book → AI pane"),
entry("Ctrl+B G", "Notes RAG — selection → Notes book → AI pane"),
entry("Ctrl+B Y", "Artefacts RAG — selection → Artefacts book → AI pane"),
entry("Ctrl+B H", "Open this Quick reference"),
entry("Ctrl+B V", "Version / author / credits panel"),
entry("Ctrl+B I", "Current book info (paths · stats · PDF status)"),
entry("Ctrl+B L", "Switch LLM provider (writes to inkhaven.hjson)"),
entry("Ctrl+B E", "Toggle typewriter SFX (writes to inkhaven.hjson)"),
entry("Ctrl+B A", "Book assembly — emit a typst-compilable tree"),
entry("Ctrl+B B", "Build the book (assemble + typst compile)"),
entry("Ctrl+B O", "Take the book — copy PDF to cwd"),
]
}
fn ai_entries() -> [Entry; 28] {
[
header("─ AI pane (apply a finished inference) ─"),
entry("r / R", "Replace editor selection with AI text"),
entry("i / I", "Insert AI text at cursor"),
entry("t / T", "Prepend AI text to top of paragraph"),
entry("g / G", "Grammar apply: extract corrected text, overwrite buffer"),
entry("b / B", "Append AI text to bottom"),
entry("c / C", "Copy AI text to clipboard"),
entry("Esc", "Bounce to AI prompt (mirror of AI prompt's Esc)"),
entry("q / Q", "Quit (autosaves if dirty)"),
header(""),
header("─ AI prompt input ─"),
entry("/", "Show prompt library picker (Tab / Enter to commit)"),
entry("Help! …", "Help-manual question (same as F1, RAG over Help)"),
entry("Enter", "Send (chat history is replayed automatically)"),
entry("Esc", "Bounce to AI pane to read the answer"),
header(""),
header("─ Chat session & meta (Ctrl+B …) ─"),
entry("F9", "Cycle scope: None / Sel / Para / Sub / Chap / Book"),
entry("F10", "Toggle inference: Local ↔ Full (Help locked to Local)"),
entry("Ctrl+B C", "Clear chat history + current inference"),
entry("Ctrl+B H", "Open this Quick reference"),
entry("Ctrl+B V", "Version / author / credits panel"),
entry("Ctrl+B I", "Current book info (paths · stats · PDF status)"),
entry("Ctrl+B L", "Switch LLM provider (writes to inkhaven.hjson)"),
entry("Ctrl+B E", "Toggle typewriter SFX (writes to inkhaven.hjson)"),
entry("Ctrl+B A", "Book assembly — emit a typst-compilable tree"),
entry("Ctrl+B B", "Build the book (assemble + typst compile)"),
entry("Ctrl+B O", "Take the book — copy PDF to cwd"),
]
}