Skip to content

Commit 51d2ec1

Browse files
no more hidden rows
1 parent 152c824 commit 51d2ec1

2 files changed

Lines changed: 23 additions & 123 deletions

File tree

src/unity-logging.ts

Lines changed: 9 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,10 @@ interface FormattedTableOutput {
5656

5757
const MAX_ERROR_DETAIL_COLUMN_WIDTH = 64;
5858
const TIMELINE_HEADING = '🔨 Unity Build Timeline';
59-
const MIN_TIMELINE_LINES = 8;
60-
const ERROR_DETAILS_OVERHEAD = 6;
6159
const MIN_DESCRIPTION_COLUMN_WIDTH = 16;
6260
const DEFAULT_TERMINAL_WIDTH = 120;
63-
const DEFAULT_TERMINAL_HEIGHT = 40;
6461
const TERMINAL_WIDTH_SAFETY_MARGIN = 2;
65-
const TERMINAL_HEIGHT_SAFETY_MARGIN = 1;
6662
const MIN_TERMINAL_WIDTH = 40;
67-
const MIN_TERMINAL_HEIGHT = 10;
6863
const extendedPictographicRegex = /\p{Extended_Pictographic}/u;
6964

7065
class ActionTelemetryAccumulator {
@@ -454,16 +449,8 @@ function buildBorderLine(columnWidths: number[], left: string, middle: string, r
454449
return result;
455450
}
456451

457-
export function formatActionTimelineTable(snapshot: ActionTableSnapshot, options?: { maxWidth?: number; maxHeight?: number }): FormattedTableOutput | undefined {
452+
export function formatActionTimelineTable(snapshot: ActionTableSnapshot, options?: { maxWidth?: number }): FormattedTableOutput | undefined {
458453
const showErrorsColumn = snapshot.totalErrorCount > 0;
459-
const sanitizedMaxHeight = options?.maxHeight && Number.isFinite(options.maxHeight) && options.maxHeight > 0
460-
? Math.floor(options.maxHeight)
461-
: undefined;
462-
463-
if (sanitizedMaxHeight !== undefined && sanitizedMaxHeight < MIN_TIMELINE_LINES) {
464-
const text = `${TIMELINE_HEADING}\nTerminal height is too small to display the Unity Build Timeline.\n\n`;
465-
return { text, lineCount: countLines(text) };
466-
}
467454

468455
interface TableRow {
469456
status: string;
@@ -472,7 +459,7 @@ export function formatActionTimelineTable(snapshot: ActionTableSnapshot, options
472459
errorsText?: string;
473460
}
474461

475-
const rows: TableRow[] = [];
462+
const tableRows: TableRow[] = [];
476463

477464
snapshot.pending.forEach(action => {
478465
const row: TableRow = {
@@ -483,7 +470,7 @@ export function formatActionTimelineTable(snapshot: ActionTableSnapshot, options
483470
if (showErrorsColumn) {
484471
row.errorsText = '';
485472
}
486-
rows.push(row);
473+
tableRows.push(row);
487474
});
488475

489476
snapshot.completed.forEach(action => {
@@ -495,60 +482,11 @@ export function formatActionTimelineTable(snapshot: ActionTableSnapshot, options
495482
if (showErrorsColumn) {
496483
row.errorsText = action.errors.length.toString();
497484
}
498-
rows.push(row);
485+
tableRows.push(row);
499486
});
500487

501-
if (rows.length === 0) {
502-
return undefined;
503-
}
504-
505-
const pendingCount = snapshot.pending.length;
506-
let tableRows: TableRow[] = rows;
507-
508-
if (sanitizedMaxHeight !== undefined) {
509-
const maxBodyRows = Math.max(0, sanitizedMaxHeight - MIN_TIMELINE_LINES);
510-
511-
if (rows.length > maxBodyRows) {
512-
if (maxBodyRows === 0) {
513-
const text = `${TIMELINE_HEADING}\nTerminal height is too small to display Unity Build Timeline rows.\n\n`;
514-
return { text, lineCount: countLines(text) };
515-
}
516-
517-
const includeIndicator = maxBodyRows >= 2;
518-
const dataSlots = includeIndicator ? maxBodyRows - 1 : maxBodyRows;
519-
const pendingRows = rows.slice(0, pendingCount);
520-
const completedRows = rows.slice(pendingCount);
521-
522-
const visiblePending = pendingRows.slice(0, Math.min(pendingRows.length, dataSlots));
523-
let remainingSlots = dataSlots - visiblePending.length;
524-
const visibleCompleted = remainingSlots > 0
525-
? completedRows.slice(Math.max(0, completedRows.length - remainingSlots))
526-
: [];
527-
528-
const hiddenPending = Math.max(0, pendingRows.length - visiblePending.length);
529-
const hiddenCompleted = Math.max(0, completedRows.length - visibleCompleted.length);
530-
531-
tableRows = [...visiblePending];
532-
if (includeIndicator && (hiddenPending > 0 || hiddenCompleted > 0)) {
533-
const parts: string[] = [];
534-
if (hiddenPending > 0) { parts.push(`${hiddenPending} pending`); }
535-
if (hiddenCompleted > 0) { parts.push(`${hiddenCompleted} completed`); }
536-
const indicatorRow: TableRow = {
537-
status: '⋯',
538-
description: `… ${parts.join(' + ')} hidden …`,
539-
durationText: '',
540-
};
541-
if (showErrorsColumn) {
542-
indicatorRow.errorsText = '';
543-
}
544-
tableRows.push(indicatorRow);
545-
}
546-
tableRows = [...tableRows, ...visibleCompleted];
547-
}
548-
}
549-
550488
if (tableRows.length === 0) {
551-
tableRows = rows.slice(-1);
489+
return undefined;
552490
}
553491

554492
const totalsRow: TableRow = {
@@ -618,41 +556,18 @@ export function formatActionTimelineTable(snapshot: ActionTableSnapshot, options
618556
output += `${bottomBorder}\n`;
619557

620558
if (showErrorsColumn && snapshot.totalErrorCount > 0) {
621-
const allErrorRows: Array<{ description: string; detail: string }> = [];
559+
const errorRows: Array<{ description: string; detail: string }> = [];
622560
snapshot.completed.forEach(action => {
623561
if (action.errors.length === 0) { return; }
624562
const description = truncate(action.description || '', MAX_ERROR_DETAIL_COLUMN_WIDTH);
625563
action.errors.forEach(err => {
626-
allErrorRows.push({
564+
errorRows.push({
627565
description,
628566
detail: truncate(err, MAX_ERROR_DETAIL_COLUMN_WIDTH),
629567
});
630568
});
631569
});
632570

633-
let errorRows = allErrorRows;
634-
if (sanitizedMaxHeight !== undefined && errorRows.length > 0) {
635-
const remainingLines = sanitizedMaxHeight - (tableRows.length + MIN_TIMELINE_LINES);
636-
if (remainingLines <= ERROR_DETAILS_OVERHEAD) {
637-
errorRows = [];
638-
} else {
639-
const maxRows = Math.min(errorRows.length, remainingLines - ERROR_DETAILS_OVERHEAD);
640-
if (maxRows <= 0) {
641-
errorRows = [];
642-
} else if (errorRows.length > maxRows) {
643-
if (maxRows === 1) {
644-
errorRows = errorRows.slice(-1);
645-
} else {
646-
const dataRows = errorRows.slice(-(maxRows - 1));
647-
const hiddenCount = errorRows.length - dataRows.length;
648-
errorRows = [{ description: '', detail: `… ${hiddenCount} more hidden …` }, ...dataRows];
649-
}
650-
} else {
651-
errorRows = errorRows.slice(-maxRows);
652-
}
653-
}
654-
}
655-
656571
if (errorRows.length > 0) {
657572
const errorDescriptionWidth = Math.max(stringDisplayWidth(descriptionHeader), ...errorRows.map(errRow => stringDisplayWidth(errRow.description)));
658573
const detailHeader = 'Error';
@@ -711,13 +626,7 @@ export class ActionTableRenderer {
711626
return;
712627
}
713628

714-
const formatOptions: { maxWidth: number; maxHeight?: number } = { maxWidth: this.getMaxWidth() };
715-
const maxHeight = this.getMaxHeight();
716-
if (maxHeight !== undefined) {
717-
formatOptions.maxHeight = maxHeight;
718-
}
719-
720-
const formatted = formatActionTimelineTable(snapshot, formatOptions);
629+
const formatted = formatActionTimelineTable(snapshot, { maxWidth: this.getMaxWidth() });
721630

722631
if (!formatted) {
723632
this.clearTimelineRegion();
@@ -747,7 +656,7 @@ export class ActionTableRenderer {
747656

748657
private rewindToAnchor(): void {
749658
// The TIMELINE_HEADING line is our anchor; rewind to it before clearing so updates stay in place.
750-
const linesToMove = Math.min(this.lastRenderLineCount, this.getMaxHeight() ?? this.lastRenderLineCount);
659+
const linesToMove = this.lastRenderLineCount;
751660
if (linesToMove <= 0) {
752661
return;
753662
}
@@ -760,15 +669,6 @@ export class ActionTableRenderer {
760669
return Math.max(MIN_TERMINAL_WIDTH, adjustedWidth);
761670
}
762671

763-
private getMaxHeight(): number | undefined {
764-
if (!this.canUpdateTerminal) {
765-
return undefined;
766-
}
767-
const detectedHeight = this.detectTerminalHeight();
768-
const adjustedHeight = detectedHeight - TERMINAL_HEIGHT_SAFETY_MARGIN;
769-
return Math.max(MIN_TIMELINE_LINES, adjustedHeight);
770-
}
771-
772672
private detectTerminalWidth(): number {
773673
const stdoutColumns = typeof process.stdout.columns === 'number' ? process.stdout.columns : undefined;
774674
if (stdoutColumns && stdoutColumns > 0) {
@@ -783,20 +683,6 @@ export class ActionTableRenderer {
783683
return DEFAULT_TERMINAL_WIDTH;
784684
}
785685

786-
private detectTerminalHeight(): number {
787-
const stdoutRows = typeof process.stdout.rows === 'number' ? process.stdout.rows : undefined;
788-
if (stdoutRows && stdoutRows > 0) {
789-
return stdoutRows;
790-
}
791-
792-
const envLines = Number(process.env.LINES);
793-
if (Number.isFinite(envLines) && envLines > 0) {
794-
return envLines;
795-
}
796-
797-
return DEFAULT_TERMINAL_HEIGHT;
798-
}
799-
800686
}
801687

802688
function toNumeric(value: unknown): number | undefined {

tests/unity-logging-renderer.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,18 @@ describe('ActionTableRenderer behavior (unit)', () => {
5050
const legacyAnchors = chunks.filter(chunk => chunk.includes('\u001b[s') || chunk.includes('\u001b[u'));
5151
expect(legacyAnchors.length).toBe(0);
5252
});
53+
54+
it('renders all rows even when terminal height is small', () => {
55+
(process.stdout as typeof process.stdout & { columns?: number; rows?: number }).columns = 80;
56+
(process.stdout as typeof process.stdout & { columns?: number; rows?: number }).rows = 10;
57+
58+
const renderer = new ActionTableRenderer(true);
59+
renderer.render(baseSnapshot);
60+
61+
const writeCalls = noopWrite.mock.calls as Array<unknown[]>;
62+
const chunks = writeCalls.map(call => call[0]).filter((chunk): chunk is string => typeof chunk === 'string');
63+
const joined = chunks.join('');
64+
expect(joined.includes('hidden')).toBe(false);
65+
expect(joined.includes('⋯')).toBe(false);
66+
});
5367
});

0 commit comments

Comments
 (0)