Skip to content

Bound the prompt panel's bar by wrapped rows #453

Closed

Description

@a1exk-dev

Parent

Spec: bound the prompt panel's bar by wrapped rows, not characters

What to build

ctui draws the person's own prompts as a panel with a thin ┃ bar down its left edge, built as one ┃ per character of the prompt plus three. A 20,000-character paste therefore builds a 20,000-row text element for a panel a few dozen rows tall, rebuilt on every transcript draw.

After this ticket the panel looks exactly as it does today — the bar still reaches the bottom of every prompt, long or short, and the row still clips — but the bar is only as long as the prompt can possibly be once wrapped.

The bound is the wrapped row count per line against a quarter of the inner width, which is the pessimistic cells-per-row figure once wide characters and long unbreakable words are in play, clamped so it can never exceed today's character count:

cells   = max(1, floor(inner / 4))
rows    = sum over the prompt's lines of max(1, ceil(line length / cells)) + 3
length  = min(rows, character count + 3)      // never longer than today

The inner width is derived, not measured: the transcript's column count less the panel's five cells of chrome less the gap a docked Sidebar takes, floored at one. The rewrite takes the viewport's column count as a new optional input, passed from the render event for the person's own prompts; given none, the bar keeps today's character-count length.

Note the naive ceil(length / inner) is a lower bound and would stop the bar partway down the panel. Ships on bugfix/plugin-authoring-review.

Acceptance criteria

  • A long single-line prompt with a viewport draws a bar far shorter than its character count, and long enough to reach the bottom of the panel at that width.
  • A prompt of many short lines counts each line's own wrap.
  • The bar is never longer than today's character count plus three, at any width.
  • With no viewport, the bar is today's character-count length, unchanged.
  • The docked gap is accounted for in the inner width, and no new dock argument is introduced: the gap the rewrite already receives is the Sidebar's.
  • The panel's look is untouched: margin, padding, overflow, background, the bar's colour, the removal of paste tags and edge newlines, and which prompt origins ctui rewrites at all.
  • Held by unit tests at the existing mount seam for transcript rewrites, one mount with a viewport and one without.
  • node scripts/check.ts exits 0.

Activity

  1. a1exk-dev commented on Oct 24, 2026

    @a1exk-dev
    OwnerAuthor

    Two formulas, both sound — pick one in the ticket rather than at the keyboard. This ticket writes the bound as cells = max(1, floor(inner / 4)) then rows = Σ max(1, ceil(line length / cells)) + 3. #443's decision wrote it as Σ 4 × ceil(line length / inner) + 1, then clamped.

    Both are valid upper bounds on the rows greedy word wrap can take, and this ticket's is the tighter of the two (ceil(4L/inner) ≤ 4·ceil(L/inner)), so it is the better one to build. Flagged only so the difference from the decision ticket is deliberate and nobody has to work out which to trust mid-change. The clamp to today's character count, and the no-viewport fallback, are identical in both.

  2. a1exk-dev commented on Oct 24, 2026

    @a1exk-dev
    OwnerAuthor

    Shipped in #470.

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions