Skip to content

diff: add a true in-place "inline" overlay (virtual text) as the future layout = "inline" #294

Description

@ThomasK33

Summary

Follow-up to #293 / #195. The diff_opts.layout = "unified" option (renamed from "inline" before v0.4.0) renders a unified diff in a separate vsplit pane — a single read-only buffer with interleaved red/green lines. This issue tracks adding a true in-place inline overlay: the diff shown as virtual text layered onto the file in the same window, the way users typically picture a "VS Code-style inline" diff (cf. mini.diff, gitsigns preview, sidekick NES, Cursor inline edits).

When implemented, this mode is the one that should claim layout = "inline" — which is exactly why we reserved that name in #293.

"unified" vs the proposed "inline"

  • "unified" (shipped): single read-only buffer in a rightbelow vsplit, deleted (red/strikethrough) + added (green) lines interleaved. Compact, but it's a separate pane and not editable before accept.
  • "inline" (this issue): no extra window — proposed changes rendered in place over the real file.

Suggested approach (keeps pre-accept editability)

The unified/read-only path forfeits editing the proposal before accepting. A prototype pattern that keeps it (the codecompanion/sidekick model):

  • Proposed/added lines = real, editable buffer lines, highlighted (e.g. ClaudeCodeInlineDiffAdd) with a + sign.
  • Deleted lines = virtual text via nvim_buf_set_extmark virt_lines (strikethrough/red), so they're visible but not part of the editable content.
  • On accept, the buffer content already is the new file (deleted lines were never real text), so edits made during review are captured. On reject, clear the extmarks / restore.

A pure-Lua, zero-dependency engine (not mini.diff/diffview — see #169) keeps this aligned with the project's philosophy. Bonus: a single-buffer extmark view sets no &diff windows, which sidesteps the closeAllDiffTabs foreign-diff class (#277) and the stale-diff repaint issues (#205).

Notes

Refs #293, #195, #82

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Fields

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions