Something went wrong. Try again.
Monorepo for the nibling.run platform
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748import { commands as defaultCommands, type ShellCommand } from "../commands.ts";import type { Unsubscribe, Workbench } from "../workbench.ts";
/** The command tables bound on this page, so a view that reads every key can leave theirs alone. */const bound = new Set<readonly ShellCommand[]>();
const isMac = () => /Mac|iPhone|iPad/.test(navigator.platform);
/** Runs shell commands from their keybindings. */export function bindKeys(target: Window, workbench: Workbench, commands: readonly ShellCommand[] = defaultCommands): Unsubscribe { const mac = isMac(); const onKey = (event: KeyboardEvent) => { const match = commands.find((c) => c.keys && matches(c.keys, event, mac)); if (!match) return; event.preventDefault(); match.run(workbench); }; target.addEventListener("keydown", onKey); bound.add(commands); return () => { target.removeEventListener("keydown", onKey); bound.delete(commands); };}
/** Whether `event` is a bound command's keybinding. */export function isBound(event: KeyboardEvent): boolean { const mac = isMac(); for (const commands of bound) if (commands.some((c) => c.keys && matches(c.keys, event, mac))) return true; return false;}
/** Matches `Mod+Shift+E` against a key event by physical key, so Alt and Shift don't change the letter. */export function matches(keys: string, event: Pick<KeyboardEvent, "code" | "metaKey" | "ctrlKey" | "altKey" | "shiftKey">, mac: boolean): boolean { const parts = keys.split("+"); const key = parts.pop()!; const mods = new Set(parts.map((m) => (m === "Mod" ? (mac ? "Meta" : "Ctrl") : m))); if (mods.has("Meta") !== event.metaKey || mods.has("Ctrl") !== event.ctrlKey) return false; if (mods.has("Alt") !== event.altKey || mods.has("Shift") !== event.shiftKey) return false; return event.code === codeOf(key);}
function codeOf(key: string): string { if (/^[A-Z]$/i.test(key)) return `Key${key.toUpperCase()}`; if (/^\d$/.test(key)) return `Digit${key}`; return { "\\": "Backslash", "`": "Backquote", "/": "Slash", ",": "Comma", ".": "Period" }[key] ?? key;}