Comprehensive command registry system for managing collections of commands in desktop-like web applications
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Advanced keyboard shortcut system with context-aware matching, chord sequences, and platform-specific key mappings. Key bindings connect keyboard events to command execution with fine-grained control over when and where shortcuts are active.
Add keyboard shortcuts that trigger commands in specific contexts.
/**
* Add a key binding to the registry.
* @param options - The options for creating the key binding
* @returns A disposable which removes the added key binding
*/
addKeyBinding(options: CommandRegistry.IKeyBindingOptions): IDisposable;
/**
* A read-only array of the key bindings in the registry.
*/
get keyBindings(): ReadonlyArray<CommandRegistry.IKeyBinding>;Configuration for creating key bindings with platform-specific overrides and context matching.
interface IKeyBindingOptions {
/** The default key sequence for the key binding (required) */
keys: string[];
/** The CSS selector for the key binding (required) */
selector: string;
/** The id of the command to execute when the binding is matched (required) */
command: string;
/** The arguments for the command, if necessary */
args?: ReadonlyPartialJSONObject;
/** The key sequence to use when running on Windows */
winKeys?: string[];
/** The key sequence to use when running on Mac */
macKeys?: string[];
/** The key sequence to use when running on Linux */
linuxKeys?: string[];
/** Whether to prevent default action of the keyboard events during sequence matching */
preventDefault?: boolean;
}Immutable key binding object created by the registry.
interface IKeyBinding {
/** The key sequence for the binding */
readonly keys: ReadonlyArray<string>;
/** The CSS selector for the binding */
readonly selector: string;
/** The command executed when the binding is matched */
readonly command: string;
/** The arguments for the command */
readonly args: ReadonlyPartialJSONObject;
/** Whether to prevent default action of the keyboard events during sequence matching */
readonly preventDefault?: boolean;
}Process keyboard events to match and execute key bindings.
/**
* Process a 'keydown' event and invoke a matching key binding.
* @param event - The event object for a 'keydown' event
*/
processKeydownEvent(event: KeyboardEvent): void;
/**
* Process a 'keyup' event to clear the timer on the modifier, if it exists.
* @param event - The event object for a 'keyup' event
*/
processKeyupEvent(event: KeyboardEvent): void;
/**
* Delay the execution of any command matched against the given 'keydown' event
* until the permission to execute is granted.
* @param event - The event object for a 'keydown' event
* @param permission - The promise with value indicating whether to proceed with the execution
*/
holdKeyBindingExecution(event: KeyboardEvent, permission: Promise<boolean>): void;Utilities for working with keystroke strings and keyboard events.
interface IKeystrokeParts {
/** Whether 'Cmd' appears in the keystroke */
cmd: boolean;
/** Whether 'Ctrl' appears in the keystroke */
ctrl: boolean;
/** Whether 'Alt' appears in the keystroke */
alt: boolean;
/** Whether 'Shift' appears in the keystroke */
shift: boolean;
/** The primary key for the keystroke */
key: string;
}
/**
* Parse a keystroke into its constituent components.
* @param keystroke - The keystroke of interest
* @returns The parsed components of the keystroke
*/
function parseKeystroke(keystroke: string): IKeystrokeParts;
/**
* Normalize a keystroke into a canonical representation.
* @param keystroke - The keystroke of interest
* @returns The normalized representation of the keystroke
*/
function normalizeKeystroke(keystroke: string): string;
/**
* Get the platform-specific normalized keys for an options object.
* @param options - The options for the key binding
* @returns Array of combined, normalized keys
*/
function normalizeKeys(options: IKeyBindingOptions): string[];
/**
* Format keystrokes for display on the local system.
* @param keystroke - The keystrokes to format
* @returns The keystrokes representation
*/
function formatKeystroke(keystroke: string | readonly string[]): string;
/**
* Check if 'keydown' event is caused by pressing a modifier key that should be ignored.
* @param event - The event object for a 'keydown' event
* @returns true if modifier key was pressed, false otherwise
*/
function isModifierKeyPressed(event: KeyboardEvent): boolean;
/**
* Create a normalized keystroke for a 'keydown' event.
* @param event - The event object for a 'keydown' event
* @returns A normalized keystroke, or an empty string if the event does not represent a valid keystroke
*/
function keystrokeForKeydownEvent(event: KeyboardEvent): string;import { CommandRegistry } from "@lumino/commands";
const registry = new CommandRegistry();
// Add a command
registry.addCommand("save-file", {
execute: () => console.log("Saving file..."),
label: "Save File"
});
// Add a key binding
const binding = registry.addKeyBinding({
keys: ["Ctrl S"],
selector: "body",
command: "save-file"
});
// Set up event processing
document.addEventListener("keydown", (event) => {
registry.processKeydownEvent(event);
});
// Clean up
binding.dispose();import { CommandRegistry } from "@lumino/commands";
const registry = new CommandRegistry();
registry.addCommand("copy", {
execute: () => console.log("Copying..."),
label: "Copy"
});
// Different key combinations for different platforms
registry.addKeyBinding({
keys: ["Ctrl C"], // Default
macKeys: ["Cmd C"], // Mac-specific
winKeys: ["Ctrl C"], // Windows-specific
linuxKeys: ["Ctrl C"], // Linux-specific
selector: ".editable",
command: "copy"
});import { CommandRegistry } from "@lumino/commands";
const registry = new CommandRegistry();
registry.addCommand("delete-item", {
execute: (args) => console.log("Deleting item:", args.itemId),
label: "Delete Item"
});
// Key binding only active within list containers
registry.addKeyBinding({
keys: ["Delete"],
selector: ".item-list .item",
command: "delete-item",
args: { context: "list" }
});
// Different behavior in tree views
registry.addKeyBinding({
keys: ["Delete"],
selector: ".tree-view .node",
command: "delete-item",
args: { context: "tree" }
});import { CommandRegistry } from "@lumino/commands";
const registry = new CommandRegistry();
registry.addCommand("goto-line", {
execute: () => console.log("Opening goto line dialog..."),
label: "Go to Line"
});
// Multi-key chord sequence
registry.addKeyBinding({
keys: ["Ctrl G", "Ctrl L"], // Press Ctrl+G, then Ctrl+L
selector: ".editor",
command: "goto-line"
});
// Set up event processing with proper timing
document.addEventListener("keydown", (event) => {
registry.processKeydownEvent(event);
});
document.addEventListener("keyup", (event) => {
registry.processKeyupEvent(event);
});import { CommandRegistry } from "@lumino/commands";
// Parse keystroke components
const parts = CommandRegistry.parseKeystroke("Ctrl Alt Shift F12");
console.log(parts); // { ctrl: true, alt: true, shift: true, cmd: false, key: "F12" }
// Normalize keystroke
const normalized = CommandRegistry.normalizeKeystroke("alt shift ctrl f12");
console.log(normalized); // "Ctrl Alt Shift F12"
// Format for display
const formatted = CommandRegistry.formatKeystroke(["Ctrl G", "Ctrl L"]);
console.log(formatted); // "Ctrl+G, Ctrl+L" (on Windows/Linux) or "⌃G, ⌃L" (on Mac)
// Handle keyboard events
document.addEventListener("keydown", (event) => {
const keystroke = CommandRegistry.keystrokeForKeydownEvent(event);
console.log("Keystroke:", keystroke);
if (!CommandRegistry.isModifierKeyPressed(event)) {
// Process non-modifier keys
registry.processKeydownEvent(event);
}
});import { CommandRegistry } from "@lumino/commands";
const registry = new CommandRegistry();
registry.addCommand("dangerous-action", {
execute: () => console.log("Performing dangerous action..."),
label: "Dangerous Action"
});
registry.addKeyBinding({
keys: ["Ctrl Shift Delete"],
selector: "body",
command: "dangerous-action"
});
// Set up event processing with permission control
document.addEventListener("keydown", async (event) => {
// Hold execution pending user confirmation
const confirmPromise = new Promise<boolean>((resolve) => {
if (event.ctrlKey && event.shiftKey && event.key === "Delete") {
const confirmed = confirm("Are you sure you want to perform this dangerous action?");
resolve(confirmed);
} else {
resolve(true);
}
});
registry.holdKeyBindingExecution(event, confirmPromise);
registry.processKeydownEvent(event);
});import { CommandRegistry } from "@lumino/commands";
const registry = new CommandRegistry();
// Listen for key binding changes
registry.keyBindingChanged.connect((sender, args) => {
console.log(`Key binding ${args.type}:`, args.binding);
updateUI();
});
function updateUI() {
// Display current key bindings
const bindings = registry.keyBindings;
console.log("Current key bindings:", bindings.map(b => ({
keys: b.keys,
command: b.command,
selector: b.selector
})));
}
// Add key bindings
const binding1 = registry.addKeyBinding({
keys: ["F1"],
selector: "body",
command: "help"
});
const binding2 = registry.addKeyBinding({
keys: ["Escape"],
selector: ".modal",
command: "close-modal"
});
// Remove key bindings
binding1.dispose(); // Triggers keyBindingChanged signal