fix(editor): scroll jumps to end after IME commit (Pinyin / Rime)#1019
Merged
fix(editor): scroll jumps to end after IME commit (Pinyin / Rime)#1019
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #1012. Typing a Chinese word (Pinyin or Rime) in the SQL editor scrolled to the end of the script after committing the candidate. Same shape happens for any IME-backed input: option-e then é, Japanese kana, etc.
TextView.insertText(_:replacementRange:)was doing two edits per IME commit:unmarkText()→replaceCharacters(in: markedRanges, with: "")to wipe the marked text._insertText→replaceCharacters(in: replacementRange, with: "测试")with the same range AppKit had supplied at commit time.By the time edit #2 ran, the document had shrunk by
markedRanges.totalLength. The range AppKit gave us pointed at characters that no longer existed:imeCommitInTheMiddleDoesNotCorruptTextreproduces: typed marked "ceshi" at offset 6 of "alpha\n\nbeta" then committed "测试" →stringcame out as"alpha\\n测试"instead of"alpha\\n测试\\nbeta"(the\\nbetaportion was eaten).TextStoryraisedRange invalid for string. The test runner caught it as a fatal error. In the released app the failure mode is "cursor lands atdocumentLength, scroll jumps there" — same root cause.insertTextnow resolves the effective range(s) before clearing marked-text bookkeeping and performs onereplaceCharacterscall. Multi-cursor IME (where each cursor gets its own marked range) replaces every range in one pass.Latent bug exposed by the fix
TextSelectionManager.didReplaceCharactershad the wrongdeltaformula:```swift
let delta = replacementLength == 0 ? -range.length : replacementLength // before
let delta = replacementLength - range.length // after
```
Selections at offsets past
range.maxshift bydelta. The old formula dropped the chars-removed term, so a same-length replace (e.g. "´" → "é" in the multi-cursor IME path) over-shifted later selections byrange.length. The unmark-then-insert flow happened to mask this because all of its replaces hadreplacementLength == 0. With the single-edit IME path, the bug surfaced and broke the existingtest_markedTextMultipleSelection. Same-length replaces now leave selections past the replace point unchanged.Test plan
IMEInputTests— 5 cases covering middle-of-doc commit, end-of-doc commit, NSNotFound replacement range, marked-state cleanup, and the plain Latin path. All fail on `main`; all pass on this branch.MarkedTextTests(multi-cursor IME) still pass.