feat(ui): sync fold open/close across diff panes in compact mode (#171)#409
Merged
Conversation
Replicates Vim's native diff-mode fold sync (src/nvim/fold.c setManualFold): when the user opens or closes a fold in one pane, the same action is applied to the corresponding region on the partner pane. Closes #171. Approach mirrors Neovim's C-level algorithm: 1. Apply the fold action in the current window. 2. For each other diff pane, map the cursor line to that pane's coordinate space via the diff hunk data. 3. Apply the same fold action there. Because our diff buffers use foldmethod=expr (not diff), Neovim's C-level sync is bypassed. We replicate it in Lua via buffer-local keymap wraps on zo/zO/zc/zC/za/zA/zv/zx/zX/zM/zR. New config: compact_sync_folds = true (default on). Inline mode is a no-op (single pane). Cursor is saved/restored so the partner pane doesn't visibly jump. _syncing recursion guard breaks the bounce-back loop. Tests: 9 unit tests for compute_corresponding_lnum + 5 integration tests including end-to-end verification that pressing zc on one pane closes the matching fold on the other. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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
Closes #171. In compact mode, folds in the two panes were applied independently — the user had to manually
zo/zcon each side to keep them aligned. This PR adds fold synchronization that mirrors Vim's nativediff-mode behavior: opening or closing a fold in one pane applies the same action to the corresponding region on the partner pane.Implementation
Mirrors Neovim's
setManualFoldalgorithm, which propagates fold actions to other diff windows:Because codediff's diff buffers use
foldmethod=expr(notdiff), Neovim's C-level sync is bypassed. We replicate it in Lua via buffer-local keymap wraps onzo/zO/zc/zC/za/zA/zv/zx/zX/zM/zR.Key design choices:
zo/zcbehavior is preserved.3zapropagates as3za._syncingflag prevents the propagated action from triggering another sync cycle.New config
Test plan
compute_corresponding_lnum(identity, no changes, before/after change, inside change, multi-change delta accumulation, negative delta, pure insertion, reverse direction).zcpropagation across panes.zcon pane A at line 20 closes the fold at lines 14-23 on both panes (matching Vim diff-mode behavior).Known gaps (out of scope for v1)
These bypass keymaps and would need a
CursorMovedsnapshot+delta fallback to catch. Native Vim diff sync catches them because it hooks at the C-level fold operation::foldopen/:foldcloseex-commandsnvim_set_option_value("foldlevel", ...)from a pluginvim.fn.foldopen()calls bypassing the keymapThe keymap-wrap covers the user-facing common case (the keys); the fallback can be added later if anyone reports a gap.
Compatibility
Non-breaking. Feature is opt-in via compact mode (
gc), which is itself opt-in. Default behavior unchanged. Config flagcompact_sync_folds = truedefaults to on — matches what the issue reporter expects ("just like Vim's diff mode").🤖 Generated with Claude Code