Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/prompt_toolkit/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -1066,7 +1066,7 @@ def paste_clipboard_data(
)

new_cursor_position = self.cursor_position + len(data.text) * count
if before:
if before and data.text:
new_cursor_position -= 1

elif data.type == SelectionType.LINES:
Expand Down
13 changes: 13 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,19 @@ def test_vi_character_paste():
assert result.cursor_position == 2


@pytest.mark.parametrize("paste", ["P", "3P"])
def test_vi_paste_before_with_empty_clipboard(paste):
feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI)

result, cli = feed(f"abcd\x1b{paste}\r")
assert result.text == "abcd"
assert result.cursor_position == 3

# A subsequent command should still act on the original character.
result, cli = feed(f"abcd\x1b{paste}x\r")
assert result.text == "abc"


def test_vi_temp_navigation_mode():
"""
Test c-o binding: go for one action into navigation mode.
Expand Down
30 changes: 30 additions & 0 deletions tests/test_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

import pytest

from prompt_toolkit.clipboard import ClipboardData
from prompt_toolkit.document import Document
from prompt_toolkit.selection import PasteMode, SelectionType


@pytest.fixture
Expand Down Expand Up @@ -79,3 +81,31 @@ def test_get_word_before_cursor_with_whitespace_and_pattern():

_FIND_WORD_RE = re.compile(r"([a-zA-Z0-9_]+|[^a-zA-Z0-9_\s]+)")
assert document.get_word_before_cursor(pattern=_FIND_WORD_RE) == ""


@pytest.mark.parametrize(
"text,cursor_position", [("", 0), ("abcd", 0), ("abcd", 2), ("abcd", 4)]
)
@pytest.mark.parametrize(
"paste_mode", [PasteMode.EMACS, PasteMode.VI_BEFORE, PasteMode.VI_AFTER]
)
def test_paste_empty_character_data(text, cursor_position, paste_mode):
document = Document(text, cursor_position)

result = document.paste_clipboard_data(ClipboardData(), paste_mode=paste_mode)

assert result.text == text
assert result.cursor_position == cursor_position


@pytest.mark.parametrize(
"paste_mode,text,cursor_position",
[(PasteMode.VI_BEFORE, "\nabc", 0), (PasteMode.VI_AFTER, "abc\n", 4)],
)
def test_paste_empty_line_data(paste_mode, text, cursor_position):
result = Document("abc", 1).paste_clipboard_data(
ClipboardData("", SelectionType.LINES), paste_mode=paste_mode
)

assert result.text == text
assert result.cursor_position == cursor_position