Skip to content

feat(vim): add configurable two-key escape sequence#190

Merged
leohenon merged 5 commits into
leohenon:ocvfrom
semi710:ocv
Jun 29, 2026
Merged

feat(vim): add configurable two-key escape sequence#190
leohenon merged 5 commits into
leohenon:ocvfrom
semi710:ocv

Conversation

@semi710

@semi710 semi710 commented Jun 14, 2026

Copy link
Copy Markdown

Add vim_escape_sequence config option to tui.json for exiting vim insert mode with a two-character sequence (e.g., 'jk').

  • Add vim_escape_sequence to TUI config schema (exactly 2 chars)
  • Thread config through prompt component to vim handler
  • Implement 300ms pending state with proper deleteRange cleanup
  • Falls back to default Escape key when unset

Example tui.json:
{"vim_escape_sequence": "jk"}

@semi710

semi710 commented Jun 24, 2026

Copy link
Copy Markdown
Author

@leohenon Are you considering this PR? I was thinking about adding a feature that allows mapping scrolling in popups to C-j, C-k or even adding Vim mode directly there, but I believe that should be a separate PR.

@leohenon

Copy link
Copy Markdown
Owner

@leohenon Are you considering this PR? I was thinking about adding a feature that allows mapping scrolling in popups to C-j, C-k or even adding Vim mode directly there, but I believe that should be a separate PR.

Still getting around to reviewing this.

I addressed c-j/k in #193.

I’d be open to vim mode for dialog text inputs if it reuses vim state/handler, keeps only a small subset, and keeps dialog submit/cancel plus undo working correctly. It should stay narrow to avoid becoming too involved.

I would prefer both as separate PRs.

@leohenon leohenon left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Since this touches core prompt input handling and adds pending/timer state, could you add tests for:

  • jk exits insert mode and removes the typed j
  • jx stays in insert mode and keeps both chars
  • j followed by timeout stays as normal input
  • j then ctrl+k does not complete the sequence

semi710 and others added 3 commits June 29, 2026 17:46
Add vim_escape_sequence config option to tui.json for exiting
vim insert mode with a two-character sequence (e.g., 'jk').

- Add vim_escape_sequence to TUI config schema (exactly 2 chars)
- Thread config through prompt component to vim handler
- Implement 300ms pending state with proper deleteRange cleanup
- Falls back to default Escape key when unset

Example tui.json:
  {"vim_escape_sequence": "jk"}
The first key of a two-key escape sequence checked !hasModifier(event)
but the second key did not. Typing j then Ctrl+k would incorrectly
complete the sequence and trigger escape instead of letting the modified
key through.
Cover jk exit, jx non-match, timeout expiry, and Ctrl+k modifier
guard. Thread vimEscapeSequence through the createHandler test helper.
@semi710

semi710 commented Jun 29, 2026

Copy link
Copy Markdown
Author

@leohenon made the changes, and also rebased the PR.

return true
// Two-key escape sequence support (e.g., "jk" to exit insert mode)
if (escapeSeq) {
const key = normalizedKeyName(langmapped(event))

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Should this avoid langmap and match raw keys instead?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

only had QWERTY in mind when writing this. normalizedKeyName(event) is the right approach, Will push
a commit for this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

pushed the change.

// Two-key escape sequence support (e.g., "jk" to exit insert mode)
if (escapeSeq) {
const key = normalizedKeyName(langmapped(event))
if (escapePending) {

@leohenon leohenon Jun 29, 2026

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Escape key while this is pending will returns before the normal escape handling below. Can we make the escape key take priority here and add a small test?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Pushed the change. Now, pressing j<esc> in Insert mode switches back to Normal mode.

semi710 and others added 2 commits June 29, 2026 20:14
Escape sequence now uses normalizedKeyName(event) instead of
langmapped(event) so it matches raw physical keys, consistent with
insert mode skipping langmap. Escape key now takes priority over a
pending escape sequence so it always exits insert mode.
@leohenon

Copy link
Copy Markdown
Owner

Looks good, thanks!

@leohenon leohenon merged commit 4e54ffb into leohenon:ocv Jun 29, 2026
1 check passed
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.

2 participants