Something went wrong. Try again.
more up to date at codeberg https://codeberg.org/cowie/tau.git
Something went wrong. Try again.
2.5 kB · 80 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081import { Editor, type EditorOptions, type EditorTheme, type TUI } from "@earendil-works/pi-tui";import type { AppKeybinding, KeybindingsManager } from "../../../core/keybindings.ts";
/** * Custom editor that handles app-level keybindings for coding-agent. */export class CustomEditor extends Editor { private keybindings: KeybindingsManager; public actionHandlers: Map<AppKeybinding, () => void> = new Map();
// Special handlers that can be dynamically replaced public onEscape?: () => void; public onCtrlD?: () => void; public onPasteImage?: () => void; /** Handler for extension-registered shortcuts. Returns true if handled. */ public onExtensionShortcut?: (data: string) => boolean;
constructor(tui: TUI, theme: EditorTheme, keybindings: KeybindingsManager, options?: EditorOptions) { super(tui, theme, options); this.keybindings = keybindings; }
/** * Register a handler for an app action. */ onAction(action: AppKeybinding, handler: () => void): void { this.actionHandlers.set(action, handler); }
handleInput(data: string): void { // Check extension-registered shortcuts first if (this.onExtensionShortcut?.(data)) { return; }
// Check for paste image keybinding if (this.keybindings.matches(data, "app.clipboard.pasteImage")) { this.onPasteImage?.(); return; }
// Check app keybindings first
// Escape/interrupt - only if autocomplete is NOT active if (this.keybindings.matches(data, "app.interrupt")) { if (!this.isShowingAutocomplete()) { // Use dynamic onEscape if set, otherwise registered handler const handler = this.onEscape ?? this.actionHandlers.get("app.interrupt"); if (handler) { handler(); return; } } // Let parent handle escape for autocomplete cancellation super.handleInput(data); return; }
// Exit (Ctrl+D) - only when editor is empty if (this.keybindings.matches(data, "app.exit")) { if (this.getText().length === 0) { const handler = this.onCtrlD ?? this.actionHandlers.get("app.exit"); if (handler) handler(); return; } // Fall through to editor handling for delete-char-forward when not empty }
// Check all other app actions for (const [action, handler] of this.actionHandlers) { if (action !== "app.interrupt" && action !== "app.exit" && this.keybindings.matches(data, action)) { handler(); return; } }
// Pass to parent for editor handling super.handleInput(data); }}