fix(status): full-width tables + better diagnosis
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { visibleWidth } from "./ansi.js";
|
||||
import { renderTable } from "./table.js";
|
||||
|
||||
describe("renderTable", () => {
|
||||
@@ -16,4 +17,19 @@ describe("renderTable", () => {
|
||||
expect(out).toContain("Dashboard");
|
||||
expect(out).toMatch(/│ Dashboard\s+│/);
|
||||
});
|
||||
|
||||
it("expands flex columns to fill available width", () => {
|
||||
const width = 60;
|
||||
const out = renderTable({
|
||||
width,
|
||||
columns: [
|
||||
{ key: "Item", header: "Item", minWidth: 10 },
|
||||
{ key: "Value", header: "Value", flex: true, minWidth: 24 },
|
||||
],
|
||||
rows: [{ Item: "OS", Value: "macos 26.2 (arm64)" }],
|
||||
});
|
||||
|
||||
const firstLine = out.trimEnd().split("\n")[0] ?? "";
|
||||
expect(visibleWidth(firstLine)).toBe(width);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -196,6 +196,39 @@ export function renderTable(opts: RenderTableOptions): string {
|
||||
shrink(nonFlexOrder, absoluteMinWidths);
|
||||
}
|
||||
|
||||
// If we have room and any flex columns, expand them to fill the available width.
|
||||
// This keeps tables from looking "clipped" and reduces wrapping in wide terminals.
|
||||
if (maxWidth) {
|
||||
const sepCount = columns.length + 1;
|
||||
const currentTotal = widths.reduce((a, b) => a + b, 0) + sepCount;
|
||||
let extra = maxWidth - currentTotal;
|
||||
if (extra > 0) {
|
||||
const flexCols = columns
|
||||
.map((c, i) => ({ c, i }))
|
||||
.filter(({ c }) => Boolean(c.flex))
|
||||
.map(({ i }) => i);
|
||||
if (flexCols.length > 0) {
|
||||
const caps = columns.map((c) =>
|
||||
typeof c.maxWidth === "number" && c.maxWidth > 0
|
||||
? Math.floor(c.maxWidth)
|
||||
: Number.POSITIVE_INFINITY,
|
||||
);
|
||||
while (extra > 0) {
|
||||
let progressed = false;
|
||||
for (const i of flexCols) {
|
||||
if ((widths[i] ?? 0) >= (caps[i] ?? Number.POSITIVE_INFINITY))
|
||||
continue;
|
||||
widths[i] = (widths[i] ?? 0) + 1;
|
||||
extra -= 1;
|
||||
progressed = true;
|
||||
if (extra <= 0) break;
|
||||
}
|
||||
if (!progressed) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const box =
|
||||
border === "ascii"
|
||||
? {
|
||||
|
||||
Reference in New Issue
Block a user