mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-06 17:38:35 +00:00
fix(cli): make the xterm modifyOtherKeys Shift+Enter encoding insert a newline
"\x1b[27;2;13~" (the older xterm modifyOtherKeys / rxvt encoding of Shift+Enter) is already registered by prompt_toolkit by default -- as Keys.ControlM, i.e. plain Enter/submit. The previous `setdefault()` call was therefore a silent no-op against it: this Shift+Enter variant kept behaving like a submit instead of inserting a newline, even after the ControlJ/WSL fix, since setdefault only sets missing keys. Assign directly to override that default for both known Shift+Enter sequences, since inserting a newline is the whole point of the binding. Add a regression test driving a real PromptSession/parser with this exact sequence, since a mocked-buffer test can't observe prompt_toolkit's default ANSI_SEQUENCES entries taking priority. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ea0516e655
commit
25a477050d
@ -326,11 +326,19 @@ def _build_cli_key_bindings() -> KeyBindings:
|
|||||||
# the case prompt_toolkit itself calls out) send for a plain Enter
|
# the case prompt_toolkit itself calls out) send for a plain Enter
|
||||||
# keypress. Aliasing to ControlJ made Enter stop submitting there, since
|
# keypress. Aliasing to ControlJ made Enter stop submitting there, since
|
||||||
# our handler shadowed prompt_toolkit's own "treat \n as \r" fallback.
|
# our handler shadowed prompt_toolkit's own "treat \n as \r" fallback.
|
||||||
|
#
|
||||||
|
# "\x1b[27;2;13~" (the older xterm modifyOtherKeys / rxvt encoding of
|
||||||
|
# Shift+Enter) is already registered by prompt_toolkit by default -- as
|
||||||
|
# Keys.ControlM, i.e. plain Enter/submit. A plain setdefault() would be a
|
||||||
|
# no-op against that existing entry, silently leaving this Shift+Enter
|
||||||
|
# variant behaving like a submit instead of inserting a newline. Assign
|
||||||
|
# directly to override it, since inserting a newline is the whole point
|
||||||
|
# of a Shift+Enter binding here.
|
||||||
with suppress(Exception):
|
with suppress(Exception):
|
||||||
from prompt_toolkit.input import ansi_escape_sequences as _aes
|
from prompt_toolkit.input import ansi_escape_sequences as _aes
|
||||||
|
|
||||||
for _seq in ("\x1b[13;2u", "\x1b[27;2;13~"):
|
for _seq in ("\x1b[13;2u", "\x1b[27;2;13~"):
|
||||||
_aes.ANSI_SEQUENCES.setdefault(_seq, Keys.ControlF3)
|
_aes.ANSI_SEQUENCES[_seq] = Keys.ControlF3
|
||||||
|
|
||||||
kb = KeyBindings()
|
kb = KeyBindings()
|
||||||
|
|
||||||
|
|||||||
@ -118,6 +118,28 @@ async def test_raw_lf_enter_still_submits_like_wsl_terminals():
|
|||||||
assert result == "hello"
|
assert result == "hello"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_xterm_modifyotherkeys_shift_enter_inserts_newline():
|
||||||
|
""""\\x1b[27;2;13~" (the older xterm modifyOtherKeys/rxvt encoding of
|
||||||
|
Shift+Enter) is registered by prompt_toolkit *by default* as plain
|
||||||
|
Enter/submit, so a `setdefault()`-based override would silently no-op
|
||||||
|
against it. This must actually insert a newline like the kitty CSI-u
|
||||||
|
encoding does, which only a real PromptSession/parser can confirm.
|
||||||
|
"""
|
||||||
|
from prompt_toolkit.application import create_app_session
|
||||||
|
from prompt_toolkit.input import create_pipe_input
|
||||||
|
from prompt_toolkit.output import DummyOutput
|
||||||
|
|
||||||
|
with create_pipe_input() as pipe_input:
|
||||||
|
with create_app_session(input=pipe_input, output=DummyOutput()):
|
||||||
|
commands._init_prompt_session()
|
||||||
|
session = commands._PROMPT_SESSION
|
||||||
|
pipe_input.send_text("foo\x1b[27;2;13~bar\r")
|
||||||
|
result = await session.prompt_async("> ")
|
||||||
|
|
||||||
|
assert result == "foo\nbar"
|
||||||
|
|
||||||
|
|
||||||
def test_thinking_spinner_pause_stops_and_restarts():
|
def test_thinking_spinner_pause_stops_and_restarts():
|
||||||
"""Pause should stop the active spinner and restart it afterward."""
|
"""Pause should stop the active spinner and restart it afterward."""
|
||||||
spinner = MagicMock()
|
spinner = MagicMock()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user