const shortcuts = [
["General", ":", "Open the command palette and fuzzy-search commands; recently run commands appear first"],
["General", "?", "Open the live help reference"],
["General", "r", "Refresh dashboard data from GitHub"],
["General", "q / Ctrl+C", "Save UI state and quit"],
["General", "1 / 2 / 3 / 4", "Focus ghr, Sections, List, or Details"],
["General", "Tab / Shift+Tab", "Switch list/details focus, or move within focused ghr/Sections tabs"],
["General", "h / l / [ / ]", "Move within focused ghr or Sections tabs"],
["General", "j / k / n / p / Up / Down", "Move focus between ghr, Sections, and List"],
["General", "S", "Search pull requests and issues with remembered structured fields; Ctrl+S saves reusable conditions and Ctrl+U clears them"],
["General", "f", "Filter the current PR or issue section"],
["General", "o", "Open the selected item or PR changes page"],
["General", "m", "Toggle between TUI mouse controls and terminal text selection"],
["General", "i", "Ignore the selected pull request or issue"],
["List", "j / k / n / p / Up / Down", "Move list selection; k/p at first item returns to Sections"],
["List", "[ / ]", "Load previous or next GitHub result page"],
["List", "PgUp / PgDown or u / d", "Move list selection by a visible page"],
["List", "g / G", "Jump to first or last item"],
["List", "/", "Open repo search in PR/issue lists, or fuzzy filter other loaded lists"],
["List", "Tab / Shift+Tab", "Focus the Details pane"],
["List", "Enter", "Focus the Details pane"],
["List", "v", "Open pull request diff mode"],
["List", "e / T", "Edit selected issue or pull request fields"],
["Issue/PR", "a", "Add a normal issue or PR comment"],
["Issue/PR", "L", "Add a label"],
["Issue/PR", "N", "Create an issue, or create a PR from local_dir in PR lists"],
["Issue/PR", "+", "Add a reaction to the item or focused comment"],
["Issue/PR", "@ / -", "Assign or unassign assignees"],
["Issue/PR", "t", "Change or clear milestone"],
["Pull Request", "M", "Open merge confirmation"],
["Pull Request", "C", "Close or reopen"],
["Pull Request", "X", "Checkout PR locally with gh pr checkout"],
["Pull Request", "F", "Rerun failed checks"],
["Pull Request", "U", "Update PR branch"],
["Pull Request", "D", "Toggle draft or ready for review"],
["Pull Request", "E / O", "Enable or disable auto-merge"],
["Pull Request", "P / Y", "Request or remove requested reviewers"],
["Review", "s", "Submit a PR review summary as a comment"],
["Review", "A", "Approve through the review summary flow"],
["Review", "Ctrl+D", "Discard a pending PR review"],
["Merge Dialog", "m / s / r", "Choose merge, squash, or rebase"],
["Merge Dialog", "Tab", "Cycle merge method"],
["Dialog", "y / Enter", "Confirm the current action"],
["Editor", "Ctrl+Enter", "Send, update, create, or submit from editor dialogs"],
["Editor", "Ctrl+S / Cmd+S", "Save the current comment, issue, or pull request draft"],
["Editor", "Arrows", "Move the cursor by character or rendered line"],
["Editor", "Home / End", "Jump to the start or end of the current line"],
["Editor", "Ctrl+W / Alt+Backspace", "Delete the previous word"],
["Editor", "Alt+B / Alt+F / Alt+D", "Jump previous/next word, or delete the next word"],
["Editor", "Ctrl+U / Ctrl+K", "Delete to the start or end of the current line"],
["Editor", "Ctrl+X", "Delete the current line"],
["Editor", "Ctrl+Z / Cmd+Z", "Undo text edits"],
["Editor", "Ctrl+R / Cmd+Shift+Z", "Redo text edits"],
["Editor", "Esc", "Cancel or close the current dialog"],
["Details", "j / k / Up / Down", "Scroll conversation details or move diff cursor"],
["Details", "PgUp / PgDown or u / d", "Scroll details by page"],
["Details", "Tab / Shift+Tab", "Focus the list pane"],
["Details", "g / G", "Top clears comment focus; bottom focuses the last comment"],
["Details", "/", "Search loaded comments by keyword"],
["Details", "n / p", "Focus comments; p from the first comment returns to PR/issue details"],
["Details", "Enter", "Expand or collapse a long focused comment"],
["Details", "R", "Reply to the focused comment"],
["Details", "e", "Edit selected issue or pull request fields"],
["Details", "c / a", "Add a comment in conversation mode"],
["Diff", "q / Esc", "Return to the state before opening diff mode"],
["Diff", "Tab / Shift+Tab", "Switch focus between changed files and the file diff"],
["Diff Files", "j / k / Up / Down", "Choose a changed file"],
["Diff Files", "PgUp / PgDown or u / d", "Move by a visible file page"],
["Diff Files", "[ / ]", "Previous or next changed file"],
["Diff Files", "Enter / 4", "Focus the file diff"],
["Diff Details", "h / l", "Page down/up through the current file diff; at file edges, jump to the next/previous file"],
["Diff Details", "j / k", "Move selected diff line"],
["Diff Details", "m", "Begin a review range"],
["Diff Details", "e", "End the review range"],
["Diff Details", "c", "Add an inline review comment"],
["Diff Details", "single click", "Select one line, or end a pending range"],
["Diff Details", "double click", "Begin a review range"],
["Mouse", "click tabs / sections", "Switch view or section"],
["Mouse", "click list row", "Select item or diff file"],
["Mouse", "click descriptions/comments", "Focus the description or selected comment"],
["Mouse", "click editor text", "Move the editor cursor to that position"],
["Mouse", "click links/actions", "Open links, run visible actions, or copy code/quote blocks"],
["Mouse", "drag Details text", "Copy the rendered selection to the clipboard"],
["Mouse", "wheel", "Scroll list, details, or dialog under the pointer"],
["Mouse", "drag split border", "Resize list/details ratio"],
];
const commands = [
["Project", "Project Switch", "Filter configured repositories and switch tabs"],
["Project", "Project Add", "Add a repo project to config.toml"],
["Project", "Project Remove", "Remove a repo project from config.toml"],
["Navigation", "Recent Items", "Fuzzy search recently viewed PRs/issues, including linked inbox notifications, and jump back"],
["Search", "Saved Search Filter", "Pick a named saved PR/issue search from config.toml"],
["Theme", "Set Color Theme", "Choose auto or a fixed color theme and save config.toml"],
["Cache", "Clear Cache", "Choose which local cache layer to clear"],
["Inbox", "Mark Done", "Move the selected GitHub inbox notification out of inbox lists; future activity can still notify unless muted"],
["Inbox", "Mark All Read", "Mark every GitHub inbox notification as read"],
["Inbox", "Mute Thread", "Ignore future notifications for the selected inbox thread"],
["Inbox", "Subscribe Thread", "Subscribe to the selected inbox thread"],
["Inbox", "Unsubscribe Thread", "Unsubscribe from the selected inbox thread"],
["Details", "Subscribe Item", "Subscribe to the selected issue or pull request conversation"],
["Details", "Unsubscribe Item", "Unsubscribe from the selected issue or pull request conversation"],
["Clipboard", "Copy GitHub Link", "Copy selected comment link or issue/PR URL"],
["Clipboard", "Copy Content", "Copy selected comment body or issue/PR description"],
["Info", "Info", "Show version, paths, ghr process memory, UI state, and ignored/recent counts"],
];
const table = document.querySelector("#shortcut-table");
const commandTable = document.querySelector("#command-table");
const input = document.querySelector("#shortcut-filter");
function renderRows(tableNode, rows, emptyText) {
tableNode.replaceChildren();
if (rows.length === 0) {
const empty = document.createElement("div");
empty.className = "empty-state";
empty.textContent = emptyText;
tableNode.append(empty);
return;
}
for (const [scope, key, action] of rows) {
const row = document.createElement("div");
row.className = "shortcut-row";
row.innerHTML = `
<span class="shortcut-scope"></span>
<span class="shortcut-key"></span>
<span class="shortcut-action"></span>
`;
row.children[0].textContent = scope;
row.children[1].textContent = key;
row.children[2].textContent = action;
tableNode.append(row);
}
}
function filterRows(rows, query) {
const normalized = query.trim().toLowerCase();
return rows.filter(([scope, key, action]) => {
const text = `${scope} ${key} ${action}`.toLowerCase();
return !normalized || text.includes(normalized);
});
}
function renderShortcuts(query = "") {
renderRows(table, filterRows(shortcuts, query), "No keybindings match that filter.");
renderRows(commandTable, filterRows(commands, query), "No commands match that filter.");
}
input.addEventListener("input", (event) => renderShortcuts(event.target.value));
renderShortcuts();