Skip to content

feat(comment): opt-in vim modal editing in the review comment box#430

Merged
agavra merged 3 commits into
agavra:mainfrom
thiblahute:comment-vim
Jun 25, 2026
Merged

feat(comment): opt-in vim modal editing in the review comment box#430
agavra merged 3 commits into
agavra:mainfrom
thiblahute:comment-vim

Conversation

@thiblahute

Copy link
Copy Markdown
Contributor

What

Adds opt-in vim-style modal editing to the review comment text box, backed by the edtui crate (used as the editing model + input engine only — the existing comment-panel rendering is reused).

  • New comment_vim config key (default false).
  • :vim command (plus :set vim / :set novim) to toggle at runtime.
  • Header shows the current mode ([NORMAL]/[INSERT]/[VISUAL]).

When off, the box keeps its current emacs/readline bindings unchanged — zero behavior change for existing users.

Design

comment_buffer / comment_cursor stay canonical (rendering and all read-sites consume them). When vim is on, an edtui overlay is built lazily on the first key in comment mode and synced back into the buffer/cursor after each event, with UTF-8-aware Index2 ↔ byte-offset conversion. This keeps the inline-in-diff preview and IME cursor positioning working with no renderer changes.

App-level keys keep their semantics: Ctrl-S/Ctrl-Enter save, Tab/Shift-Tab cycle the comment type, Ctrl-C cancels; from Normal mode Esc cancels and Enter saves. Everything else drives the modal editor (hjkl, w/b/e, dd/D/ciw/x, u/Ctrl-r, visual v+y/d/p).

Known limitation

edtui's vim mode binds a fixed set of key sequences rather than a full operator+motion grammar, so combos like dw/de/cw/d$ are not supported yet (use dd/D/ciw/x). Upstream edtui#63 adds dw/dW/diw; once released, a dependency bump picks it up. We chose not to work around it locally.

Testing

  • cargo build, cargo clippy --all-targets (0 warnings), cargo test (full suite green).
  • New unit tests in src/comment_vim.rs: UTF-8 Index2↔byte round-trips (CJK/emoji) and integration tests driving real key events through the editor (insert typing, Esc→Normal, x, dd).

Add a `comment_vim` config flag (default off) plus a `:vim`/`:novim` runtime
toggle that switch the review comment box to vim-style modal editing, backed by
the `edtui` crate used as the editing model + input engine only — the existing
comment-panel rendering is reused.

- `comment_buffer`/`comment_cursor` stay canonical for rendering; an edtui
  overlay is built lazily on first key and synced back after each event
  (UTF-8-aware Index2<->byte conversion).
- Normal/Insert/Visual editing; `:w`/`:q` command-line; double `Enter` saves and
  `Esc`/`q` cancels, with the first press arming the action and a red confirm
  hint shown in the header; `Ctrl-S`/`Ctrl-Enter` also save.
- `Tab` cycles the comment type in Normal mode and inserts `comment_tab_width`
  spaces (default 4) in Insert mode.

When off, the box keeps its default emacs/readline bindings.
`i` enters edit mode for the comment at the diff cursor with the text cursor at
the start of the current comment line; `A` (vim mode only) enters with the
cursor at its end. Non-vim `i` keeps placing the cursor at the end of the buffer.

For multi-line comments the cursor lands on the line the diff cursor is actually
pointing at: `comment_block_start` finds the comment's first annotation row and
`comment_current_line_cursor` maps that row to the logical line's start/end byte
offset (accounting for wrapped segments and the box borders).
…yed comments

Render review comment text as colored markdown — both the in-progress editor box
and saved comments — using the project's existing syntect highlighter with the
Markdown grammar. Colors come from the active syntect theme (matching diff code
highlighting), so there are no new theme fields or dependencies.

- syntax: add `highlight_markdown_lines` (sibling of `highlight_file_lines`,
  sharing a new `highlight_lines_with` helper) selecting the `md` grammar.
- comment_panel: the editor box and `format_comment_lines` emit highlighted
  spans per wrapped segment via `highlighted_window_spans` / `markdown_body_lines`,
  byte-window sliced so wrapping and multibyte stay correct; the cursor cell is
  spliced into the highlighted runs.

Remote (read-only) forge threads keep their muted palette.

@agavra agavra left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

heh this is pretty cool! thanks @thiblahute

@agavra
agavra merged commit ce3c62b into agavra:main Jun 25, 2026
4 checks passed
joaomendoncaa pushed a commit to joaomendoncaa/tuicr that referenced this pull request Jun 26, 2026
…avra#430)

* feat(comment): opt-in vim modal editing in the review comment box

Add a `comment_vim` config flag (default off) plus a `:vim`/`:novim` runtime
toggle that switch the review comment box to vim-style modal editing, backed by
the `edtui` crate used as the editing model + input engine only — the existing
comment-panel rendering is reused.

- `comment_buffer`/`comment_cursor` stay canonical for rendering; an edtui
  overlay is built lazily on first key and synced back after each event
  (UTF-8-aware Index2<->byte conversion).
- Normal/Insert/Visual editing; `:w`/`:q` command-line; double `Enter` saves and
  `Esc`/`q` cancels, with the first press arming the action and a red confirm
  hint shown in the header; `Ctrl-S`/`Ctrl-Enter` also save.
- `Tab` cycles the comment type in Normal mode and inserts `comment_tab_width`
  spaces (default 4) in Insert mode.

When off, the box keeps its default emacs/readline bindings.

* feat(comment): edit the comment under the cursor with i/A

`i` enters edit mode for the comment at the diff cursor with the text cursor at
the start of the current comment line; `A` (vim mode only) enters with the
cursor at its end. Non-vim `i` keeps placing the cursor at the end of the buffer.

For multi-line comments the cursor lands on the line the diff cursor is actually
pointing at: `comment_block_start` finds the comment's first annotation row and
`comment_current_line_cursor` maps that row to the logical line's start/end byte
offset (accounting for wrapped segments and the box borders).

* feat(comment): markdown syntax coloring in the comment box and displayed comments

Render review comment text as colored markdown — both the in-progress editor box
and saved comments — using the project's existing syntect highlighter with the
Markdown grammar. Colors come from the active syntect theme (matching diff code
highlighting), so there are no new theme fields or dependencies.

- syntax: add `highlight_markdown_lines` (sibling of `highlight_file_lines`,
  sharing a new `highlight_lines_with` helper) selecting the `md` grammar.
- comment_panel: the editor box and `format_comment_lines` emit highlighted
  spans per wrapped segment via `highlighted_window_spans` / `markdown_body_lines`,
  byte-window sliced so wrapping and multibyte stay correct; the cursor cell is
  spliced into the highlighted runs.

Remote (read-only) forge threads keep their muted palette.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants