From 8fe5fbabb32829d3b7d61d0b9a3a5b37544a81ed Mon Sep 17 00:00:00 2001 From: Dang Pham Date: Mon, 31 Aug 2026 12:52:29 +0700 Subject: [PATCH 1/4] test: cover Ctrl-Y yank in Vi insert mode --- tests/test_vi_insert_bindings.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/test_vi_insert_bindings.py diff --git a/tests/test_vi_insert_bindings.py b/tests/test_vi_insert_bindings.py new file mode 100644 index 000000000..f43525619 --- /dev/null +++ b/tests/test_vi_insert_bindings.py @@ -0,0 +1,19 @@ +from prompt_toolkit.clipboard import InMemoryClipboard +from prompt_toolkit.enums import EditingMode +from prompt_toolkit.input.defaults import create_pipe_input +from prompt_toolkit.output import DummyOutput +from prompt_toolkit.shortcuts import PromptSession + + +def test_ctrl_y_yanks_text_killed_by_ctrl_u_in_vi_insert_mode(): + with create_pipe_input() as inp: + inp.send_text("hello\x15\x19\r") + session = PromptSession( + input=inp, + output=DummyOutput(), + editing_mode=EditingMode.VI, + clipboard=InMemoryClipboard(), + ) + result = session.prompt() + + assert result == "hello" From 6b9c26c8a83da37e89dd266847563ef8d8ec766f Mon Sep 17 00:00:00 2001 From: Dang Pham Date: Mon, 31 Aug 2026 12:58:39 +0700 Subject: [PATCH 2/4] test: preserve Ctrl-Y completion behavior in Vi mode --- tests/test_vi_insert_bindings.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/tests/test_vi_insert_bindings.py b/tests/test_vi_insert_bindings.py index f43525619..0ec2e2a3b 100644 --- a/tests/test_vi_insert_bindings.py +++ b/tests/test_vi_insert_bindings.py @@ -1,4 +1,7 @@ -from prompt_toolkit.clipboard import InMemoryClipboard +from prompt_toolkit.buffer import CompletionState +from prompt_toolkit.clipboard import ClipboardData, InMemoryClipboard +from prompt_toolkit.completion import Completion +from prompt_toolkit.document import Document from prompt_toolkit.enums import EditingMode from prompt_toolkit.input.defaults import create_pipe_input from prompt_toolkit.output import DummyOutput @@ -17,3 +20,30 @@ def test_ctrl_y_yanks_text_killed_by_ctrl_u_in_vi_insert_mode(): result = session.prompt() assert result == "hello" + + +def test_ctrl_y_still_accepts_active_completion_in_vi_insert_mode(): + clipboard = InMemoryClipboard(ClipboardData("clipboard text")) + + with create_pipe_input() as inp: + inp.send_text("\x19\r") + session = PromptSession( + input=inp, + output=DummyOutput(), + editing_mode=EditingMode.VI, + clipboard=clipboard, + ) + + def activate_completion() -> None: + buffer = session.default_buffer + buffer.document = Document("he", 2) + buffer.complete_state = CompletionState( + buffer.document, + [Completion("hello", start_position=-2)], + ) + buffer.go_to_completion(0) + + result = session.prompt(pre_run=activate_completion) + + assert result == "hello" + assert clipboard.get_data().text == "clipboard text" From 242b868b5f1b71c0d32642a79df9ef99243ee92b Mon Sep 17 00:00:00 2001 From: Dang Pham Date: Mon, 31 Aug 2026 13:24:38 +0700 Subject: [PATCH 3/4] test: preserve custom Ctrl-Y bindings in Vi mode --- tests/test_vi_insert_bindings.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/test_vi_insert_bindings.py b/tests/test_vi_insert_bindings.py index 0ec2e2a3b..0f1aca0ac 100644 --- a/tests/test_vi_insert_bindings.py +++ b/tests/test_vi_insert_bindings.py @@ -4,6 +4,7 @@ from prompt_toolkit.document import Document from prompt_toolkit.enums import EditingMode from prompt_toolkit.input.defaults import create_pipe_input +from prompt_toolkit.key_binding import KeyBindings from prompt_toolkit.output import DummyOutput from prompt_toolkit.shortcuts import PromptSession @@ -47,3 +48,23 @@ def activate_completion() -> None: assert result == "hello" assert clipboard.get_data().text == "clipboard text" + + +def test_custom_ctrl_y_binding_overrides_vi_default(): + bindings = KeyBindings() + + @bindings.add("c-y") + def custom_ctrl_y(event): + event.current_buffer.insert_text("CUSTOM") + + with create_pipe_input() as inp: + inp.send_text("\x19\r") + session = PromptSession( + input=inp, + output=DummyOutput(), + editing_mode=EditingMode.VI, + key_bindings=bindings, + ) + result = session.prompt() + + assert result == "CUSTOM" From f169827167bc83336af8e3033adf233c8d8043c3 Mon Sep 17 00:00:00 2001 From: Dang Pham <26757735+PNHD@users.noreply.github.com> Date: Mon, 31 Aug 2026 06:29:46 +0000 Subject: [PATCH 4/4] fix: restore Ctrl-Y yank in Vi insert mode --- src/prompt_toolkit/key_binding/bindings/vi.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/prompt_toolkit/key_binding/bindings/vi.py b/src/prompt_toolkit/key_binding/bindings/vi.py index e3fca1b98..0451a8e31 100644 --- a/src/prompt_toolkit/key_binding/bindings/vi.py +++ b/src/prompt_toolkit/key_binding/bindings/vi.py @@ -544,13 +544,22 @@ def _complete_prev(event: E) -> None: b.start_completion(select_last=True) @handle("c-g", filter=vi_insert_mode) - @handle("c-y", filter=vi_insert_mode) def _accept_completion(event: E) -> None: """ Accept current completion. """ event.current_buffer.complete_state = None + @handle("c-y", filter=vi_insert_mode) + def _accept_completion_or_yank(event: E) -> None: + """ + Accept current completion, or yank when no completion is active. + """ + if event.current_buffer.complete_state is None: + get_by_name("yank").handler(event) + else: + event.current_buffer.complete_state = None + @handle("c-e", filter=vi_insert_mode) def _cancel_completion(event: E) -> None: """