Skip to content

gh-145448: Fix REPL tab completion cursor position in pending wrap state - #145727

Open
mvanhorn wants to merge 2 commits into
python:mainfrom
mvanhorn:osc/145448-fix-repl-tab-cursor
Open

mvanhorn wants to merge 2 commits into
python:mainfrom
mvanhorn:osc/145448-fix-repl-tab-cursor

Conversation

@mvanhorn

@mvanhorn mvanhorn commented Mar 10, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #145448

Summary

When the PyREPL's __write_changed_line writes to the last column of the terminal, the cursor enters "pending wrap" state - it physically stays at column width-1 but posxy was recording width. This caused subsequent CUB (Cursor Backward) escape sequences to overshoot by one cell, moving the cursor one position too far left.

Root cause: In unix_console.py, three code paths in __write_changed_line set posxy to the full line width without accounting for pending wrap state. When the cursor is later moved back (e.g., to return to the input line after showing "[ complete but not unique ]"), the CUB count is calculated as target_x - width instead of target_x - (width-1), producing one extra backward movement.

Fix: Cap posxy[0] at self.width - 1 when writing reaches the terminal edge. This matches the physical cursor position in pending wrap state, so CUB calculations produce the correct count.

Why Terminal.app isn't affected: Terminal.app compensates by subtracting 1 from CUB in pending wrap state. xterm and Ghostty do not compensate, matching the spec more strictly.

Test plan

  • All 244 test_pyrepl tests pass
  • NEWS entry added
  • Fix applied to all three posxy assignment paths in __write_changed_line

This contribution was developed with AI assistance (Claude Code).

…rap state

When __write_changed_line writes to the last column of the terminal,
the cursor enters "pending wrap" state where it physically stays at
width-1. However, posxy was recording width, causing subsequent CUB
(Cursor Backward) calculations to overshoot by one cell.

Cap posxy x-coordinate at width-1 to match the physical cursor
position in pending wrap state. This fixes the cursor moving backward
during tab completion in xterm and Ghostty.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented May 8, 2026

Copy link
Copy Markdown

This PR is stale because it has been open for 30 days with no activity.

@github-actions github-actions Bot added the stale Stale PR or inactive for long period of time. label May 8, 2026
…-tab-cursor

# Conflicts:
#	Lib/_pyrepl/unix_console.py
@mvanhorn

Copy link
Copy Markdown
Contributor Author

Main is merged in as of 34d2c34. The refresh code was restructured in gh-148105, so the old per-branch edits no longer applied. The same off-by-one is still there though: __apply_line_update sets posxy to start_x + char_width, which can equal the terminal width after writing into the last column. I moved the clamp to the end of __apply_line_update so it covers every update kind, and added test_write_to_last_column_records_pending_wrap_position. It fails on main and passes here; the rest of test_unix_console passes too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting review stale Stale PR or inactive for long period of time.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

REPL import tab completion moves cursor backward

1 participant