Skip to content

feat(core): add ctrl+n/ctrl+p keybindings for navigation#559

Open
rafa-thayto wants to merge 1 commit into
bombshell-dev:mainfrom
rafa-thayto:feat/ctrl-n-ctrl-p-navigation
Open

feat(core): add ctrl+n/ctrl+p keybindings for navigation#559
rafa-thayto wants to merge 1 commit into
bombshell-dev:mainfrom
rafa-thayto:feat/ctrl-n-ctrl-p-navigation

Conversation

@rafa-thayto

Copy link
Copy Markdown

Summary

Adds emacs-style ctrl+n / ctrl+p keybindings as default aliases for down / up navigation, alongside the existing vim j / k aliases.

  • settings.ts — registers '\x10'up (ctrl+p) and '\x0e'down (ctrl+n) in the default alias table under an // emacs support block; adds a getActionForControlKey(char, key) helper (sibling of isActionKey) that resolves control chords, guarded on key.ctrl so typed letters can never alias navigation in text inputs.
  • prompt.ts — the cursor-alias lookup in onKeypress now checks [char, key.name, key.sequence] instead of key.name only, mirroring how the pre-existing '\x03' (ctrl+c) cancel alias is matched. Control chords report key.name as the bare letter ('n'), so the raw sequence is the only safe key to match on.
  • autocomplete.tsctrl+n/ctrl+p navigate the option list (the prompt tracks text input, so it reads key.name === 'up'/'down' directly and needed explicit chord resolution).
  • multi-line.tsctrl+n/ctrl+p move the cursor between lines; previously the raw \x0e/\x10 bytes were inserted into the user's text.

Every cursor-driven prompt (select, multi-select, group-multiselect, date, confirm) picks the aliases up automatically through the existing cursor-event system, and updateSettings({ aliases }) keeps working unchanged for user-defined sequences.

Test plan

  • New unit tests: cursor events emitted for ctrl+p/ctrl+n (and not for plain n/p), autocomplete list navigation, multi-line cursor movement without text mutation.
  • New integration tests with snapshots: select responds to ctrl+n/ctrl+p.
  • Full suite green: 144 core + 587 prompts tests; biome check and tsc --noEmit clean.
  • Changeset included (@clack/core minor).

Add emacs-style ctrl+n (down) and ctrl+p (up) as default aliases,
matching the existing vim j/k aliases. Control chords arrive as raw
bytes ('\x0e'/'\x10'), so the cursor-alias lookup in Prompt.onKeypress
now checks char and key.sequence alongside key.name, mirroring how the
'\x03' cancel alias is matched.

Cursor-driven prompts (select, multi-select, group-multiselect, date,
confirm) pick the aliases up through the existing cursor-event system.
Autocomplete and multi-line resolve control chords explicitly via the
new getActionForControlKey helper, guarded on key.ctrl so typed letters
(like the j/k aliases) never hijack text input. In multi-line this also
stops the raw control bytes from being inserted into the text.
@changeset-bot

changeset-bot Bot commented Jun 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 90c2c27

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@clack/core Minor
@clack/prompts Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@rafa-thayto

Copy link
Copy Markdown
Author

I was implementing this on my CLI, but I thought it would probably be a better idea to implement it directly here!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant