fix(cli): stop hijacking ControlJ for Shift+Enter, it breaks Enter on WSL
Keys.ControlJ is also the literal LF byte ("\x0a") that some terminals send
for a plain Enter keypress -- prompt_toolkit's own default bindings handle
this by re-feeding it as ControlM/submit, and calls out WSL by name as the
case that needs it. Binding our Shift+Enter handler to ControlJ shadowed
that default, so on any terminal sending LF for Enter, pressing Enter only
ever inserted a newline and the prompt could never be submitted.
Register the CSI-u Shift+Enter sequences against Keys.ControlF3 instead: an
enum member prompt_toolkit declares but never wires to a default ANSI
sequence or key binding, so it's only reachable through our own mapping.
Also add a regression test that drives a real PromptSession/Vt100Parser
with a raw LF byte -- the existing key-binding test invoked handlers
directly against a mocked buffer, which exercises the handler logic but not
prompt_toolkit's key-resolution precedence, so it couldn't have caught this.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
committed by
Xubin Ren
co-authored by
Claude Opus 4.8
parent
18a230de75
commit
ea0516e655
@@ -319,14 +319,18 @@ def _build_cli_key_bindings() -> KeyBindings:
|
||||
which case Alt+Enter is the fallback.
|
||||
"""
|
||||
# prompt_toolkit has no symbolic Keys.ShiftEnter and @kb.add() rejects raw
|
||||
# escape strings, so register the CSI-u Shift+Enter sequences against a
|
||||
# spare key symbol (ControlJ) and bind that. Terminals that never emit
|
||||
# these sequences simply won't trigger the binding.
|
||||
# escape strings, so register the CSI-u Shift+Enter sequences against
|
||||
# Keys.ControlF3 -- an enum member prompt_toolkit declares but never wires
|
||||
# to a default ANSI sequence or key binding, unlike e.g. Keys.ControlJ,
|
||||
# which is also the literal LF byte ("\x0a") that some terminals (WSL is
|
||||
# the case prompt_toolkit itself calls out) send for a plain Enter
|
||||
# keypress. Aliasing to ControlJ made Enter stop submitting there, since
|
||||
# our handler shadowed prompt_toolkit's own "treat \n as \r" fallback.
|
||||
with suppress(Exception):
|
||||
from prompt_toolkit.input import ansi_escape_sequences as _aes
|
||||
|
||||
for _seq in ("\x1b[13;2u", "\x1b[27;2;13~"):
|
||||
_aes.ANSI_SEQUENCES.setdefault(_seq, Keys.ControlJ)
|
||||
_aes.ANSI_SEQUENCES.setdefault(_seq, Keys.ControlF3)
|
||||
|
||||
kb = KeyBindings()
|
||||
|
||||
@@ -338,7 +342,7 @@ def _build_cli_key_bindings() -> KeyBindings:
|
||||
def _(event):
|
||||
event.current_buffer.insert_text("\n")
|
||||
|
||||
@kb.add(Keys.ControlJ) # Shift+Enter on CSI-u capable terminals
|
||||
@kb.add(Keys.ControlF3) # Shift+Enter on CSI-u capable terminals
|
||||
def _(event):
|
||||
event.current_buffer.insert_text("\n")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user