Skip to content

Minimap: VS Code-consistent width, stop rebuilding the whole buffer every frame, and stop overdrawing the status line #728

Description

@JDonaghy

Summary

Four minimap defects from one operator smoke against VS Code, all reproduced on develop @ e02a824, built from source (not a stale binary).

1. Width — about 120px, not 15% of the pane

MINIMAP_WIDTH_FRACTION = 0.15 with a 240px cap (src/render.rs:4362, 4397) makes the strip roughly twice VS Code's. VS Code derives its width from minimap.maxColumn (120) times 1px per column.

Spec: width = min(120 * scale, pane-fraction cap), keeping the MINIMAP_MIN_TEXT_COLS suppression and the per-pane keying from #722. This lines up exactly with quadraui's own colour-bar heuristic, which already assumes 120 columns (ASSUMED_WIDE_LINE_CHARS) — at 120px that is precisely 1px per column.

2. Performance — O(buffer) per frame, per pane

Wheel-scrolling a 10,000-line file is unusable until :set nominimap. build_minimap_data allocates a String for every line in the buffer, every frame:

// src/render.rs:4504
let owned: Vec<String> = (0..total_buffer_lines).map(|i| ...to_string()).collect();

then sample_lines clones again the ~400 it actually keeps. And there is no frame-to-frame reuse to fall back on: render_content writes cached_screen_layout at src/gtk/mod.rs:8404 on every draw and never reads it back across frames, so every wheel tick pays the full cost.

Fix: choose the sampled line indices first, then fetch only those lines from the rope — the stride is known before any text is needed. sample_lines takes &[&str], so this needs either a sibling entry point that takes an index-and-fetch closure or an index-only variant in quadraui; either is acceptable, but stop materialising the buffer.

Secondary, same function: to_col (src/render.rs:4548) does a chars().count() prefix scan per span, which is quadratic on a long line. Fix it while you are there.

Acceptance here is a measurement, not a claim. There is no bench harness in this repo (no benches/, no criterion). Add one, or a timed test, and report before/after frame cost for a 10,000-line file under sustained wheel scroll. A fix without a number is not done.

3. The strip overdraws the status line

build_screen_layout reserves a status row only when per_window_status && !separate_status (src/render.rs:6925), while h_scrollbar_geometry answers the very same question with a different predicateengine.settings.window_status_line && !engine.terminal_maximized (src/gtk/mod.rs:10313). Two independent answers to "is a per-window status line painted here" is the defect; one of them is wrong in at least one configuration.

Reconcile them behind a single helper, and assert the strip's painted rect never intersects the status row across all combinations of window_status_line / status_line_above_terminal / bottom-panel-open / terminal_maximized.

4. Fixed row pitch, once quadraui lands it

Pass quadraui's MinimapSizing::FixedPitch (quadraui#667) and stop deriving target_lines from display_rows * MINIMAP_LINES_PER_ROW on GTK, so the row count follows the strip and the pitch rather than the file's length. Needs the pin bump — sequence this after quadraui#667.

Not in this issue

The missing scrollbar is #723, reopened: it still reproduces on its own fix.

Files

  • src/render.rsMINIMAP_WIDTH_FRACTION and caps, build_minimap_data, status-row reservation, to_col
  • src/gtk/mod.rs — status-row predicate reconciliation
  • src/quadraui_pin.rs — pin bump
  • benches/ (new) or a timed test

Surfaced by

Operator smoke against VS Code, 2026-09-01.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    coordTracked by coord-tui pipelineenhancementNew feature or requeststatus:readyRefined and ready to enter the work pipelineuiUI/rendering

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions