Skip to content

Align corresponding rows between From and To (filler lines) - #16

Merged
ryutaro-asada merged 1 commit into
mainfrom
feat/align-rows
Oct 22, 2026
Merged

ryutaro-asada merged 1 commit into
mainfrom
feat/align-rows

Conversation

@ryutaro-asada

Copy link
Copy Markdown
Owner

Closes #10. Stacked on #15 (based on its branch because both change highlight_line); merge #15 first.

Summary

scrollbind/cursorbind only mirror scroll offsets, so with insertions/deletions the two sides drifted apart. With the new diff.align (default true), the scratch buffers are rewritten with real filler rows, so line N on the left always corresponds to line N on the right. Scrolling and cursor movement stay aligned, like diff mode.

 4    { id: 2,  name: "Americano",  price: 350 },   │ 4    { id: 2,  name: "Americano",  price: 350 },
    ---------------------------------------------   │ 5    { id: 6,  name: "Macchiato",  price: 400 },  ↑ moved from line 8
    ---------------------------------------------   │ 6    { id: 7,  name: "Flat White", price: 440 },
 5    { id: 3,  name: "Cappuccino", price: 420 },   │ 9    { id: 3,  name: "Cappuccino", price: 420 },
 ...
 8    { id: 6,  name: "Macchiato",  price: 400 },  ↓│    ---------------------------------------------

(excerpt of a headless screen dump of test/demo.rb)

  • M.align_lines() is a pure function that builds the aligned contents and the original-line → buffer-row maps from vscode-diff's change blocks. The shorter side of a block is padded at the end of the block.
  • All line/char/move highlights are still computed on original line numbers and placed through the row maps. Move markers keep original line numbers.
  • Filler rows use a new PartialDiffFiller group (links to DiffDelete, configurable as highlights.filler) and the 'fillchars' diff character, fixed to the window so it doesn't scroll horizontally.
  • Windows that show line numbers get a statuscolumn with original line numbers (blank on filler rows). It is reset if the view closes as the last tab.
  • diff.align = false keeps the buffers verbatim (old behavior).
  • The built-in diff fallback is unchanged (diff mode already aligns).

Approach as discussed in #10. Rejected: diff mode for alignment (its own diff can disagree with vscode-diff) and virt_lines filler (scrollbind doesn't count virtual lines).

Testing

  • make test: 55/55 pass locally (Neovim 0.11.1).
  • New spec/align_spec.lua (14 cases):
    • align_lines on insertions, deletions, uneven modified blocks, and multiple blocks.
    • Equal row counts; unchanged lines on the same row on both sides; filler highlight.
    • Highlights land on the shifted rows.
    • Original line labels; statuscolumn set only where numbers are shown.
    • Move markers keep original line numbers and sit on the right row.
    • align = false keeps the buffers verbatim.
    • A screen test that redraws and reads the number column.
  • That screen test caught a bug during development: the statuscolumn callback assumed g:statusline_winid, which isn't set inside %{} items. It errored on every redraw. Fixed, and the test fails without the fix.
  • Existing move tests now look rows up through the alignment map.
  • Manually checked a headless screen dump of test/demo.rb with number on: filler rows, original line numbers, cursor stays on the same row after 6j in one window.
  • CI (0.10.4 / stable): see checks.

Behavior change

Alignment is on by default. Copying text out of the diff buffers now includes empty filler rows; set diff.align = false to get verbatim copies.

scrollbind/cursorbind only mirror scroll offsets, so with insertions or
deletions the two sides drifted apart. With diff.align (default true) the
scratch buffers are rewritten with real filler rows from vscode-diff's
change blocks, so line N on the left corresponds to line N on the right
and scrolling/cursor stay aligned like diff mode.

- M.align_lines(): pure function building the aligned contents and
  original-line -> buffer-row maps; the shorter side of a block is padded
  at the end of the block.
- All line/char/move highlights are computed on original line numbers and
  placed through the row maps; move markers keep original line numbers.
- Filler rows use the new PartialDiffFiller group (links to DiffDelete)
  and the 'fillchars' diff character, fixed to the window.
- Windows that show line numbers get a statuscolumn with original line
  numbers (blank on filler rows); reset when the view closes as the last
  tab.
- diff.align = false keeps the buffers verbatim.

Closes #10
@ryutaro-asada
ryutaro-asada changed the base branch from fix/line-add-delete-highlights to main October 22, 2026 23:36
@ryutaro-asada
ryutaro-asada merged commit e95e7f6 into main Oct 22, 2026
2 checks passed
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.

Align corresponding rows between From and To (filler lines)

1 participant