| 1 | // Ported from DeepSeek Harness c291e7961a (MIT). |
| 2 | /** The head/tail split metrics for a capped list. */ |
| 3 | export interface HeadTailCap { |
| 4 | /** Rows beyond the cap (list length − maxLines); ≤ 0 means nothing is hidden. */ |
| 5 | hidden: number |
| 6 | /** Whether the list is over the cap and not expanded, so it shows a head/tail slice. */ |
| 7 | capped: boolean |
| 8 | /** Head-slice row count: `ceil(maxLines / 2)`. */ |
| 9 | headLines: number |
| 10 | /** Tail-slice row count: the remainder after the head. */ |
| 11 | tailLines: number |
| 12 | } |
| 13 | |
| 14 | /** |
| 15 | * Compute the head/tail cap metrics for a list of `total` rows against `maxLines`, |
| 16 | * given whether the surface is expanded. Pure arithmetic; the caller slices its |
| 17 | * own rows with `headLines`/`tailLines` so a block can layer its own concerns |
| 18 | * (SearchBlock restores a tail file header) on top. |
| 19 | * @param total - the list's row count. |
| 20 | * @param maxLines - the collapsed-height cap in rows. |
| 21 | * @param expanded - whether the surface is expanded (uncaps the list). |
| 22 | * @returns the split metrics. |
| 23 | */ |
| 24 | export function headTailCap(total: number, maxLines: number, expanded: boolean): HeadTailCap { |
| 25 | const hidden = total - maxLines |
| 26 | const headLines = Math.ceil(maxLines / 2) |
| 27 | return { hidden, capped: hidden > 0 && !expanded, headLines, tailLines: maxLines - headLines } |
| 28 | } |
| 29 |