Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Merge branch 'worktree-agent-a39a116f38472effe' into claude/cool-newton-7nm8r9 | 1 | /** |
| 2 | * Drawing a long log a screenful at a time. A step's log past a few | |
| 3 | * thousand rows draws only the rows on screen and a few around them, with | |
| 4 | * space above and below standing in for the rest, so a 50,000-line log | |
| 5 | * opens, grows and scrolls as fast as a short one. Rows are one line high | |
| 6 | * until they are drawn and measured (a long line wraps), and the space | |
| 7 | * kept for them is corrected then. | |
| 8 | */ | |
| 9 | ||
| 10 | /** Past this many rows, a step's log draws only what is on screen. */ | |
| 11 | export const WINDOW_FROM = 2000; | |
| 12 | /** A row's height before it is measured: one line of `text-xs leading-5`. */ | |
| 13 | export const ROW_HEIGHT = 20; | |
| 14 | /** How far past the screen rows are drawn, above and below, in pixels. */ | |
| 15 | export const OVERSCAN = 800; | |
| 16 | ||
| 17 | /** | |
| 18 | * Where each row starts, from the top of the log: `starts[i]` for row `i`, | |
| 19 | * and `starts[rows]` for the log's whole height. `height(i)` is a row's | |
| 20 | * measured height, or undefined for the estimate. | |
| 21 | */ | |
| 22 | export function rowStarts(rows: number, height: (index: number) => number | undefined): Float64Array { | |
| 23 | const starts = new Float64Array(rows + 1); | |
| 24 | for (let i = 0; i < rows; i++) starts[i + 1] = starts[i]! + (height(i) ?? ROW_HEIGHT); | |
| 25 | return starts; | |
| 26 | } | |
| 27 | ||
| 28 | /** The first row that ends below `y`: the row at `y`, or the last. */ | |
| 29 | export function rowAt(starts: Float64Array, y: number): number { | |
| 30 | const rows = starts.length - 1; | |
| 31 | let low = 0; | |
| 32 | let high = rows; | |
| 33 | while (low < high) { | |
| 34 | const middle = (low + high) >> 1; | |
| 35 | if (starts[middle + 1]! <= y) low = middle + 1; | |
| 36 | else high = middle; | |
| 37 | } | |
| 38 | return Math.min(low, Math.max(0, rows - 1)); | |
| 39 | } | |
| 40 | ||
| 41 | /** | |
| 42 | * The rows to draw, `[from, to)`, for a view from `top` to `bottom` | |
| 43 | * (pixels from the top of the log; either may be past its ends), with | |
| 44 | * `overscan` pixels more either side. | |
| 45 | */ | |
| 46 | export function windowOf(starts: Float64Array, top: number, bottom: number, overscan = OVERSCAN): [number, number] { | |
| 47 | const rows = starts.length - 1; | |
| 48 | if (rows === 0) return [0, 0]; | |
| 49 | const total = starts[rows]!; | |
| 50 | const from = top - overscan; | |
| 51 | const to = bottom + overscan; | |
| 52 | if (to <= 0 || from >= total) { | |
| 53 | // Off screen: draw a few rows at the end nearest the view, so the | |
| 54 | // log has something to measure and its end can be followed. | |
| 55 | return from >= total ? [Math.max(0, rows - 20), rows] : [0, Math.min(rows, 20)]; | |
| 56 | } | |
| 57 | return [rowAt(starts, Math.max(0, from)), rowAt(starts, to) + 1]; | |
| 58 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.