Skip to content

fix: expand copy-mode word-end window past a final wide glyph - #2145

Open
kiakiraki wants to merge 1 commit into
herdrdev:masterfrom
kiakiraki:fix/copy-mode-word-end-wide-char
Open

fix: expand copy-mode word-end window past a final wide glyph#2145
kiakiraki wants to merge 1 commit into
herdrdev:masterfrom
kiakiraki:fix/copy-mode-word-end-wide-char

Conversation

@kiakiraki

Copy link
Copy Markdown

What happens

Copy mode e (next word end) stops at the read window boundary instead of the real end of the word. It triggers on a line that soft-wraps over more than 64 rows, with a wide (CJK) glyph as the last cell in the read window. The same case works fine with narrow characters.

In practice you hit this with a long CJK log line or a JSON blob that wraps as one logical line. A minimal repro is a 2-column pane with written 66 times: pressing e from the top should land on row 65, but it stops at row 63.

Why

RetainedTextBuffer::point_is_final_atom compared an atom's end column against the word-motion target's start column. Narrow cells have end_col == start.col, so it matched by accident. Wide cells have end_col == start.col + 1, so it never matched.

The only caller is needs_more_future in word_motion_target, which decides "the target landed on the last atom in the window, so double the window and look further". With a wide glyph that never fired, and the window was returned unexpanded.

clippy::suspicious_operation_groupings flags this line on its own too. Its suggested point.end_col does not compile, though — TerminalTextPoint only has row and col.

The fix

Word-motion targets are always atom start points, given how previous_point and next_point are written, so compare against the final atom's start point directly.

Narrow cells behave exactly as before. end_col == start.col makes the new expression equivalent to the old one, the SpacerHead atom (end_col: col) is the same, and the hard-line-break atom is dropped by find because its point is None. There is also no case where only the old expression matched: a wide cell's start.col + 1 is the spacer tail position, and no atom starts there.

Termination is unchanged. window_rows saturates at total_rows, and at that point either ends_in_continuation goes false or reached_edge goes true.

Testing

Added live_terminal_word_end_expands_through_a_long_wide_soft_wrap, the wide-glyph twin of the adjacent live_terminal_word_end_expands_through_a_long_soft_wrap. Before the fix the motion returns row 63 and the test fails; after the fix it passes.

just check passes.

Docs

The only user-visible change is that something broken starts working, and the copy-mode section in keyboard.mdx says nothing about wide characters, so I don't think this needs a docs update.

Related

#1000 is also copy mode and full-width characters, but it is a different bug (single-cell h/l movement stopping mid-glyph) and this PR does not fix it.

point_is_final_atom compared an atom's terminating column against a
word-motion target's starting column. The two are equal for narrow
cells but never for wide ones, so the read window stopped expanding
and copy-mode `e` halted at the soft-wrap boundary on CJK text.
@kangal-bot kangal-bot added the ai-review Trigger automated AI reviews for pull requests admitted by the PR gate label Aug 1, 2026
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The terminal pane now detects the final atom by its start point. A regression test covers NextEnd word motion across soft-wrapped wide glyphs.

Changes

Wide Glyph Word Motion

Layer / File(s) Summary
Final atom detection and regression coverage
src/pane/terminal.rs
point_is_final_atom compares the requested point with the final atom’s start point. A regression test validates NextEnd across a long soft-wrapped sequence of wide glyphs.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the fix to copy-mode word-end motion for a final wide glyph.
Description check ✅ Passed The description accurately explains the bug, root cause, fix, regression test, and validation for the changeset.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 1, 2026

Copy link
Copy Markdown

Greptile Summary

The PR corrects copy-mode next-word-end motion when a long soft-wrapped read window ends on a wide glyph.

  • Compares the target with the final atom’s start point rather than its end column.
  • Adds a regression test covering a 66-character CJK word wrapped in a two-column terminal.

Confidence Score: 5/5

The PR appears safe to merge, with the corrected comparison matching the start-point representation used by word-motion targets.

The sole final-atom check receives atom start points, and the new equality correctly handles both narrow and wide atoms while preserving behavior for spacer heads and excluding point-less line-break atoms.

Important Files Changed

Filename Overview
src/pane/terminal.rs Corrects final-atom detection for wide glyphs and adds a focused regression test without changing narrow-cell behavior.

Reviews (1): Last reviewed commit: "fix: expand copy-mode word-end window pa..." | Re-trigger Greptile

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

Labels

ai-review Trigger automated AI reviews for pull requests admitted by the PR gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants