inkhaven 1.2.3

Inkhaven — TUI literary work editor for Typst books
//! Static keybinding tables for the Ctrl+H quick reference. Layout is
//! produced at render time; entries here are just pairs of (key, action).

use super::focus::Focus;

#[derive(Debug, Clone, Copy)]
pub struct Entry {
    pub key: &'static str,
    pub desc: &'static str,
    /// Section heading (no description).
    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("")); // blank spacer
    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"),
    ]
}