## What changed
Return the initial wrapping ranges directly when the composer input produces a
single line and its byte length is less than the available width. This avoids
the additional grapheme and word-boundary pass for input that cannot wrap.
GitOrigin-RevId: 55d990a354fcc61e9a90d5796b4b39d16742cc50
## What changed
- Add the configurable `vim_normal.replace_char` action, bound to `r` by default, to replace the grapheme under the cursor while remaining in normal mode.
- Support change-operator motions such as `cw`, `c$`, `cj`, and `ck`, plus the repeated `cc` command for changing the current line.
- Let `Esc` cancel a pending replacement before it reaches composer-level handling.
- Preserve existing custom Vim bindings and chord prefixes when introducing the new default.
## Testing
- Cover replacement, grapheme boundaries, remapping and unbinding, change motions, cancellation, keymap conflicts, and keymap picker snapshots.
GitOrigin-RevId: 98feb4eeb57142c37adb73abfe58d1f703b9270d
## Why
Keeping overflowing separators with the following word can add whitespace-only
rows and make composer wrapping differ from the queued-input preview.
## What changed
- Hang breakable whitespace from the preceding visual row at soft word breaks
while preserving the underlying editable text.
- Keep indentation, trailing whitespace, mandatory breaks, and nonbreaking spaces
visible and editable according to their existing semantics.
- Align cursor placement, scrolling, vertical navigation, masked rendering, and
styled overlays with the visible wrapped content, including after resizes.
## Testing
Add focused wrapping, rendering, cursor, editing, scrolling, navigation, Unicode
separator, long whitespace-run, and resize coverage.
GitOrigin-RevId: 7fbdb0a4bf33cfee20c4c19dca5aee74df4f892c
## Why
Overflowing whitespace in the TUI composer could occupy a separate blank row
instead of remaining attached to the text that follows it.
## What changed
- Add composer-specific, grapheme-safe wrapping that keeps breakable Unicode
whitespace with the following word while preserving semantic breakpoints such
as hyphens and nonbreaking spaces.
- Preserve cursor insertion rows and positions as content reflows, including
across full lines and wrapped fragments.
- Keep wrapping linear for maximum-length unbroken input.
## Testing
Add focused rendering and cursor tests for ASCII and Unicode whitespace,
hyphenated words, reflowed fragments, and maximum-length input.
GitOrigin-RevId: fb7713e33bfddf37460b6c2f6f0c9700f31d86bf
## Why
Vim mode currently supports some normal-mode operators and motions, but
common text-object combinations like `ciw`, `daw`, `di(`, and
quote/bracket variants are still missing. That makes the composer feel
incomplete for users who expect operator + text object editing to work
inside prompts.
Closes#21383.
## What Changed
- Add Vim pending-state support for operator/text-object sequences.
- Add `c` as a normal-mode operator for text objects, so combinations
like `ciw` delete the object and enter insert mode.
- Support word, WORD, delimiter, and quote text objects:
- `iw`, `aw`, `iW`, `aW`
- `i(`, `a(`, `i)`, `a)`, `ib`, `ab`
- `i[`, `a[`, `i]`, `a]`
- `i{`, `a{`, `i}`, `a}`, `iB`, `aB`
- `i"`, `a"`, `i'`, `a'`, `i\``, `a\``
- Add configurable keymap entries and keymap picker coverage for the new
Vim text-object context.
- Regenerate the config schema and update keymap picker snapshots.
## How to Test
Manual smoke test:
1. Start Codex with Vim composer mode enabled.
2. Type a draft such as:
```text
alpha beta gamma
call(foo[bar], {"x": "hello world"})
say "one \"two\" three" now
```
3. Put the cursor on `beta`, press `ciw`, and confirm `beta` is removed
and the composer enters insert mode.
4. Escape back to normal mode, put the cursor on `gamma`, press `daw`,
and confirm `gamma` plus surrounding whitespace is removed.
5. Put the cursor inside `foo[bar]`, press `di[`, and confirm only `bar`
is removed.
6. Put the cursor inside `call(...)`, press `da(`, and confirm the whole
parenthesized section is removed.
7. Put the cursor inside the quoted text, press `ci"`, and confirm the
quote contents are removed and insert mode starts.
8. Verify cancellation does not edit text: press `d` then `Esc`, and
press `d` then `i` then `Esc`.
Targeted tests:
- `cargo test -p codex-tui --lib vim_`
- `cargo nextest run -p codex-tui keymap_setup::tests`
Additional local checks:
- `just write-config-schema`
- `just fmt`
- `just fix -p codex-tui`
- `git diff --check`
- `cargo insta pending-snapshots --manifest-path tui/Cargo.toml`
Local full-suite note: `just test -p codex-tui` ran to completion. The
keymap snapshot failures were expected and accepted. Two unrelated
guardian feature-flag tests still fail locally:
-
`app::tests::update_feature_flags_disabling_guardian_clears_review_policy_and_restores_default`
-
`app::tests::update_feature_flags_disabling_guardian_clears_manual_review_policy_without_history`
`just argument-comment-lint` is currently blocked locally by Bazel
analysis before the lint runs because `compiler-rt` has an empty
`include/sanitizer/*.h` glob in the local Bazel cache. The touched Rust
diff was manually inspected for opaque positional literals.