Skip to content

Add Emacs/readline editing mode#4270

Closed
colonelpanic8 wants to merge 18 commits into
pingdotgg:mainfrom
colonelpanic8:t3code/add-emacs-readline-mode
Closed

Add Emacs/readline editing mode#4270
colonelpanic8 wants to merge 18 commits into
pingdotgg:mainfrom
colonelpanic8:t3code/add-emacs-readline-mode

Conversation

@colonelpanic8

@colonelpanic8 colonelpanic8 commented Jul 22, 2026

Copy link
Copy Markdown

Summary

  • add a persisted client-local keyboard editing mode with Browser default and Emacs / readline options
  • support common readline movement, deletion, kill/yank, transpose, and word-navigation bindings across text inputs and contenteditable editors
  • make Control-N and Control-P navigate command palettes, comboboxes, selects, menus, and other candidate lists while the mode is active
  • preserve terminal-native key handling

Why

Browser text controls do not consistently provide Emacs/readline editing shortcuts across platforms, and candidate-selection surfaces only respond to arrow keys. This mode provides a consistent opt-in editing experience throughout T3 Code.

Validation

  • vp test run packages/contracts/src/settings.test.ts apps/web/src/emacsReadlineBindings.test.ts apps/web/src/AppRoot.test.tsx (39 tests)
  • targeted contracts and web type checks
  • targeted formatter and lint checks
  • isolated live web verification of mode persistence, Control-A, Control-E, Control-W, Control-Y, and Control-N/Control-P command-palette navigation

Exact-head evidence

Revalidated at 4189d3c on current main (9a0a071): focused tests, vp check, and vp run typecheck passed. The capture uses only disposable local projects.

Emacs readline editing mode enabled in General settings


Note

Medium Risk
Global capture-phase key handling can shadow browser or app shortcuts when emacs mode is on; composer Lexical mutations add regression surface for chips and prompt sync.

Overview
Adds an opt-in keyboard editing mode (default | emacs) on client settings, with a General settings control and restore-defaults support.

When Emacs / readline is enabled, a capture-phase EmacsReadlineBindings host applies readline chords to plain inputs, generic contenteditables, and the Lexical composer via ComposerEmacsReadlinePlugin, including kill/yank that keeps mention/skill chips and terminal context placeholders. Ctrl-N / Ctrl-P move focus in open candidate surfaces (composer command menu, comboboxes, etc.) instead of only arrow keys; terminals and keybinding-capture fields are excluded.

Keybindings gain optional source (default | user) through contracts, server persistence, and compilation. resolveCustomShortcutCommand lets readline consume chords that match built-in defaults while still yielding to custom or explicitly user shortcuts (with when context from terminal/preview/model picker state). Settings reset/save paths pass source so default vs custom rows stay accurate.

Reviewed by Cursor Bugbot for commit 4401e9d. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add Emacs/readline editing mode to the composer and global keybinding system

  • Adds a new EmacsReadlineBindings component (mounted in AppRoot) that intercepts keydown events globally and applies Emacs/readline chords (Ctrl-A/E/B/F/K/U/W/Y, Alt-B/F/D, transpose-chars, etc.) to focused inputs, textareas, and contenteditables.
  • Adds a ComposerEmacsReadlinePlugin inside the rich-text composer that maps readline actions onto Lexical nodes, preserving mention/skill chips and terminal context placeholders during kill/yank and movement.
  • Adds a keyboardEditingMode setting ('default' | 'emacs') to ClientSettings and exposes a selector in the General settings panel so users can enable or reset the mode.
  • Extends keybinding rules with an optional source field ('default' | 'user') across contracts, server persistence, and runtime compilation, enabling resolveCustomShortcutCommand to skip defaults when checking for application-shortcut precedence over readline chords.
  • Behavioral Change: when emacs mode is enabled, many Ctrl/Alt key combinations are consumed by the readline handler before reaching the browser or application, which may shadow OS-level or application shortcuts not explicitly registered as custom bindings.

Macroscope summarized 4401e9d.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b140e949-c43d-4879-9e3d-8673cfea7600

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Jul 22, 2026
Comment thread apps/web/src/emacsReadlineBindings.ts
Comment thread apps/web/src/emacsReadlineBindings.ts
Comment thread apps/web/src/emacsReadlineBindings.ts
Comment thread apps/web/src/emacsReadlineBindings.ts
Comment thread apps/web/src/emacsReadlineBindings.ts
Comment thread apps/web/src/emacsReadlineBindings.ts
Comment thread apps/web/src/emacsReadlineBindings.ts
Comment thread apps/web/src/emacsReadlineBindings.ts
@macroscopeapp

macroscopeapp Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing feature (Emacs/readline editing mode) with ~2500 lines of new code across multiple new files, new keyboard event handling, and new settings. New capabilities of this scope warrant human review.

You can customize Macroscope's approvability policy. Learn more.

Comment thread apps/web/src/emacsReadlineBindings.ts
Comment thread apps/web/src/emacsReadlineBindings.ts
Comment thread apps/web/src/components/ComposerPromptEditor.tsx Outdated
Comment thread apps/web/src/emacsReadlineBindings.ts Outdated
Comment thread apps/web/src/emacsReadlineBindings.ts
Comment thread apps/web/src/emacsReadlineBindings.ts
Comment thread apps/web/src/components/ComposerPromptEditor.tsx Outdated
Comment thread apps/web/src/components/EmacsReadlineBindings.tsx
Comment thread apps/web/src/components/EmacsReadlineBindings.tsx
@colonelpanic8
colonelpanic8 force-pushed the t3code/add-emacs-readline-mode branch from ad28130 to 3d358f3 Compare July 22, 2026 14:50
@github-actions github-actions Bot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Jul 22, 2026
Comment thread apps/web/src/components/ComposerPromptEditor.tsx
Comment thread apps/web/src/keybindings.ts
Comment thread apps/web/src/emacsReadlineBindings.ts Outdated
Comment thread apps/web/src/components/ComposerPromptEditor.tsx Outdated
Comment thread apps/web/src/components/ComposerPromptEditor.tsx
Comment thread apps/web/src/components/ComposerPromptEditor.tsx
Comment thread apps/web/src/emacsReadlineBindings.ts
Comment thread apps/web/src/emacsReadlineBindings.ts Outdated
Comment thread apps/web/src/composerEmacsReadline.ts
Comment thread apps/web/src/components/ComposerPromptEditor.tsx
Comment thread apps/web/src/components/ComposerPromptEditor.tsx
Comment thread apps/web/src/components/ComposerPromptEditor.tsx
@colonelpanic8
colonelpanic8 force-pushed the t3code/add-emacs-readline-mode branch from 66b4b63 to 2fefbf3 Compare July 22, 2026 15:45
Comment thread apps/web/src/components/ComposerPromptEditor.tsx
Comment thread apps/web/src/components/ComposerPromptEditor.tsx Outdated
Comment thread apps/web/src/emacsReadlineBindings.ts
Comment thread apps/web/src/emacsReadlineBindings.ts
@colonelpanic8
colonelpanic8 force-pushed the t3code/add-emacs-readline-mode branch from d3bfe6c to 048b91d Compare July 22, 2026 16:15
Comment thread apps/web/src/emacsReadlineBindings.ts
Comment thread apps/web/src/emacsReadlineBindings.ts
Comment thread apps/web/src/composerEmacsReadline.ts
Comment thread apps/web/src/keybindings.ts
@colonelpanic8
colonelpanic8 force-pushed the t3code/add-emacs-readline-mode branch from 4189d3c to cdb8647 Compare July 22, 2026 23:38
Comment thread apps/web/src/components/EmacsReadlineBindings.tsx
Comment thread apps/web/src/emacsReadlineBindings.ts
Comment thread apps/web/src/components/ComposerPromptEditor.tsx
Comment thread apps/server/src/keybindings.ts
Comment thread apps/server/src/keybindings.ts Outdated
Comment thread apps/server/src/keybindings.ts
@colonelpanic8
colonelpanic8 force-pushed the t3code/add-emacs-readline-mode branch from 85d1678 to d897c39 Compare July 23, 2026 16:15
Comment thread apps/web/src/emacsReadlineBindings.ts
Comment thread apps/web/src/emacsReadlineBindings.ts
@colonelpanic8
colonelpanic8 force-pushed the t3code/add-emacs-readline-mode branch from 6df7aa7 to cf68c34 Compare July 23, 2026 16:57
Comment thread apps/web/src/composerEmacsReadline.ts
Comment thread apps/server/src/keybindings.ts Outdated
@colonelpanic8
colonelpanic8 force-pushed the t3code/add-emacs-readline-mode branch from 25dd0ec to 4401e9d Compare July 23, 2026 20:22

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4401e9d. Configure here.

$isRangeSelection(selection) && getSelectionRangeForComposerOffsets(selection) !== null;
});
}
rootElement?.toggleAttribute("data-emacs-readline-ready", ready);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Composer readiness uses stale root

Medium Severity

ComposerEmacsReadlinePlugin captures editor.getRootElement() once and writes data-emacs-readline-ready on that snapshot, without registerRootListener (used elsewhere in this file). If the root is null at effect time or later replaced, readiness never attaches. Capture then sees a managed host that is not ready and returns without handling, so composer-focused readline chords fall through to app shortcuts.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 4401e9d. Configure here.

'[data-slot="select-popup"]',
'[data-slot="menu-popup"]',
'[role="listbox"]',
].join(",");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Model picker list not selected

Medium Severity

CANDIDATE_SURFACE_SELECTOR matches portaled combobox-popup and command-list, but the model picker’s inline list only exposes data-slot="combobox-list". Candidate detection then depends solely on a generic role="listbox" match. If that role is absent or hidden, Control-N/P are applied as line motion on the single-line search input, consumed, and never move the model highlight.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 4401e9d. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant