Skip to content

Conversation

@sinelaw
Copy link
Owner

@sinelaw sinelaw commented Dec 31, 2025

No description provided.

@sinelaw sinelaw force-pushed the claude/research-multi-buffer-diff-7b1we branch 2 times, most recently from 1f594f3 to 8302855 Compare January 1, 2026 09:23
claude added 28 commits January 4, 2026 13:17
Research feasibility of displaying multiple buffers within a single
visual pane (tab) for side-by-side diff, unified diff, and 3-way
merge views.

Key findings:
- Existing COMPOSITE_BUFFER_ARCHITECTURE.md provides solid foundation
- Proposes phased approach: enhanced virtual buffers → multi-source
  tokens → full composite buffers with editing
- Documents design options, trade-offs, and mapping to existing arch
Full specification for displaying multiple buffers in a single tab:

Core data structures:
- CompositeBuffer: References multiple source buffers
- LineAlignment: Maps display rows to source lines with padding
- CompositeViewState: Per-split state with unified scrolling

Rendering pipeline:
- CompositeRenderer: Handles side-by-side, stacked, unified layouts
- Automatic line alignment with padding for diff views
- Focus indicator for active pane

Input routing:
- CompositeInputRouter: Routes events to focused pane's source buffer
- Coordinate mapping from display to source positions
- Scroll events affect entire composite view

Plugin API:
- createCompositeBuffer(): Full configuration for layouts
- updateCompositeAlignment(): Live refresh on source changes
- setCompositeFocus(): Switch between panes

Includes complete diff_view.ts plugin example.
Implements the foundation for multi-buffer single-tab views:

- src/model/composite_buffer.rs: CompositeBuffer, SourcePane, PaneStyle,
  LineAlignment with support for diff hunks, and RowType for styling
- src/view/composite_view.rs: CompositeViewState with pane focus,
  unified scrolling, and per-pane cursor tracking
- src/view/composite_renderer.rs: CompositeRenderer with side-by-side,
  stacked, and unified layout modes

The composite buffer system enables displaying multiple source buffers
within a single tab, supporting use cases like side-by-side diff,
unified diff, and 3-way merge views.
Implements CompositeInputRouter for handling keyboard input in
composite buffer views:

- Scroll navigation (j/k, arrows, page up/down, g/G)
- Pane switching (Tab, h/l)
- Hunk navigation (n/p, [/])
- Edit routing to source buffers (respects read-only panes)
- Display-to-source coordinate mapping
- Click-to-pane detection

The router translates composite-level input into specific actions
that can be applied to the composite view or routed to source buffers.
- Add composite_buffers and composite_view_states fields to Editor
- Create separate composite_buffer_actions.rs for management methods
- Add methods: create_composite_buffer, close_composite_buffer,
  get_composite_view_state, composite_scroll, composite_next/prev_hunk
- Update get_buffer_display_name to handle composite buffers
Add PluginCommand variants for creating, updating, and closing
composite buffers. This enables TypeScript plugins to create
side-by-side diff views and other multi-buffer layouts.

- Add CreateCompositeBuffer, UpdateCompositeAlignment, CloseCompositeBuffer commands
- Add CompositeLayoutConfig, CompositeSourceConfig, CompositePaneStyle types
- Add handler methods in composite_buffer_actions.rs
- Route new commands in Editor::handle_plugin_command
Add op functions and editor methods for creating and managing
composite buffers from TypeScript plugins:

- createCompositeBuffer(options): Create a multi-buffer view
- updateCompositeAlignment(bufferId, hunks): Update diff alignment
- closeCompositeBuffer(bufferId): Close a composite buffer

This enables plugins to create side-by-side diff views and
other multi-buffer layouts within a single tab.
Add a diff view plugin that demonstrates the composite buffer
infrastructure:

- Compare current file with git HEAD
- Side-by-side view with line alignment
- Keybindings for hunk navigation (n/N, [c/]c)
- Tab to switch between panes
- q/Escape to close

This plugin uses createCompositeBuffer() to create a multi-buffer
view within a single tab.
Replace the split-based side-by-side diff with composite buffers:

- `side_by_side_diff_current_file` now uses createCompositeBuffer
- `review_drill_down` now uses createCompositeBuffer
- Add activeCompositeDiffState for tracking composite diff views
- Proper cleanup on buffer close
- Remove separate diff_view.ts (functionality merged into audit_mode)

Benefits of composite buffers:
- Single tab instead of two splits
- Line alignment handled by infrastructure
- Synchronized scrolling built-in
- Proper OLD|NEW ordering (left=old, right=new)
Connect composite buffers to the main render path:

- Add is_composite_buffer flag to EditorState
- Register composite buffers with split_view_states for tabs
- Add composite_buffers parameter to render_content
- Add render_composite_buffer for side-by-side pane rendering
- Render each pane with header label and buffer content

This enables composite buffers to actually display in the editor
instead of showing empty buffers.
- Add event_logs entry for composite buffers to fix panic on 'g' key
- Route scroll/movement actions through handle_composite_action
- Add cursor_row field to CompositeViewState with movement methods
- Highlight current line in composite pane rendering
- Fix plugin keybindings: "close_buffer" -> "close", add h/l keys
- Pass composite_view_states to render functions for scroll sync
…ring

- Add diff_add_bg, diff_remove_bg, diff_modify_bg colors to Theme struct
- Add serde defaults for backwards-compatible theme file parsing
- Update all 4 built-in themes (dark, light, high_contrast, nostalgia)
- Refactor render_composite_buffer to use LineAlignment for proper diff display
- Style rows based on RowType (Addition, Deletion, Modification, etc.)
…r view

- Add render_composite_scrollbar() for visual scroll position feedback
- Pass CompositeViewState to render_composite_buffer for state access
- Add cursor_column tracking to CompositeViewState
- Add cursor column movement methods (left/right/home/end) with auto-scroll
- Render cursor as inverted character at cursor position
- Apply horizontal scrolling per-pane using PaneViewport.left_column
- Pad content to fill width for consistent diff backgrounds
Create PLAN_composite_rendering_reuse.md documenting:
- Current architecture and its coupling to byte-based contexts
- Proposed LineRenderer abstraction for per-line rendering
- Implementation steps for proper code reuse
- Benefits and estimated effort
Updated PLAN_composite_rendering_reuse.md with clean architecture:
- Bridge line numbers (composite) to byte offsets (normal pipeline)
- build_view_line_from_line() - builds ViewLine from source line number
- get_line_highlights() - queries highlighter for line's byte range
- render_composite_view_line() - renders with full styling
- Reuses: ViewLineIterator, compute_char_style logic, Highlighter, Theme
- CompositeBuffer wraps full EditorStates, not custom rendering
- Each pane uses existing render_buffer_in_split() for all features
- Chunk-based alignment with markers at boundaries only
- Markers auto-adjust on edit, context chunks update line_count
- Hunks marked dirty for localized recomputation
- Diff highlighting via overlays on pane EditorStates
- Unified scroll_display_row derived to per-pane top_byte
- Input routing to focused pane's EditorState
The CompositeRenderer struct was defined but never used anywhere in the
codebase. The actual composite buffer rendering is done in
split_rendering.rs via render_composite_buffer(). This removes dead code
as part of the architecture cleanup.
Merged the following fragmented docs into docs/internal/DIFF_VIEW.md:
- PLAN_composite_rendering_reuse.md
- DIFF_BRANCH_CONTINUATION.md
- docs/REVIEW_DIFF_FEATURE.md
- docs/COMPOSITE_BUFFER_ARCHITECTURE.md
- docs/MULTI_BUFFER_SINGLE_TAB_RESEARCH.md

The new document has two parts:
1. UX Design - keyboard shortcuts, visual layout, comment system
2. Architecture/Implementation - dual-mode rendering decision,
   ChunkAlignment with markers, render_aligned_view_lines design

Key design decision: Option E (Dual-Mode Rendering) chosen over
full pipeline reuse because aligned diff views need gaps that
consecutive line rendering cannot provide.
Refactored render_composite_buffer to use the ViewLine pipeline for
proper syntax highlighting in diff views. Key changes:

- Build ViewData per pane using build_view_data() to get syntax-highlighted
  ViewLines with proper token styles
- Create source_line -> ViewLine index mapping for each pane
- New render_view_line_content() helper that renders ViewLine with:
  - Per-character syntax highlighting from char_styles
  - Horizontal scroll support
  - Cursor rendering
  - Style accumulation for efficient span generation
- Fallback to direct buffer read if ViewLine not found

This implements the dual-mode rendering design from DIFF_VIEW.md where
composite buffers reuse the ViewLine building infrastructure while having
their own aligned rendering loop for gaps.
Fix language detection for virtual buffer names like "*OLD:test_diff.ts*"
by stripping surrounding * characters and extracting the actual filename
after prefixes like "OLD:" or "NEW:".

This enables syntax highlighting in composite/diff views where source
buffers are created with decorated names.
- Add visual_mode, selection_anchor_row/column to CompositeViewState
- Add selection helpers (start_visual_selection, is_row_selected, etc.)
- Add SelectionAction enum to composite router
- Handle SelectDown/SelectUp/Copy actions in handle_composite_action
- Render selection highlighting with theme.selection_bg
- Add selection and copy keybindings to diff-view mode (Shift+j/k, y, Ctrl+c)
- Fix keybinding syntax for diff-view mode (use "J", "K", "C-c", "S-Down")
- Route Action::Copy to handle_composite_action for composite buffers
- Ensures copy in diff view uses the composite-specific selection logic
claude added 4 commits January 4, 2026 13:19
Added modifications to test the side-by-side diff functionality:
- Modified scrollTest5 with additional text
- Added new comment at end of file
…osite view

- Simplified diff-view mode to inherit from "normal" mode
- Forward navigation/selection actions to focused source buffer instead of
  reimplementing them in handle_composite_action
- Removed duplicate navigation logic, leveraging action_to_events
- Only special handling for Copy (needs aligned row mapping) and Close
The previous attempt to forward actions to source buffers didn't work
because the composite view needs its own cursor/scroll state for aligned
row navigation. Restored explicit handling for:

- Arrow key navigation (MoveDown/Up/Left/Right)
- Page navigation (MovePageDown/Up)
- Document start/end
- Scroll actions
- Selection with Shift+arrows

The diff-view mode still inherits from "normal" for keybindings, but
the BufferMode registry doesn't have a "normal" mode defined - this
needs to be addressed by explicitly defining keybindings in diff-view.
…play

- Add composite_view field to SplitViewState for future view-layer refactoring
- Update navigation actions (MoveDown/Up/Left/Right) to sync cursor position
  with the fake EditorState's primary_cursor_line_number
- Update selection actions (SelectDown/Up/Left/Right) similarly
- This fixes the status bar showing "Ln 1, Col 1" when navigating in diff view
@sinelaw sinelaw force-pushed the claude/research-multi-buffer-diff-7b1we branch from 185c151 to 924e3d0 Compare January 4, 2026 11:21
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.

3 participants