refactor: extracted padding logic into reusable utility function with optimized buffer allocation

- Extracted manual space padding logic into a reusable `padding()` utility function across all UI components and utilities.
- Optimized padding operations by introducing a pre-allocated 512-space buffer in the `padding()` function to reduce repeated string allocations.
- Updated all imports across 30 files to use the new `padding()` function from pi-tui instead of inline `' '.repeat()` calls.
- Renamed local variables from `padding` to `pad`, `padSize`, `indent`, or `linePad` to avoid naming conflicts with the imported `padding()` function.
- Exported the `padding()` utility function from the tui package index for public use.
This commit is contained in:
can1357
2026-01-31 13:36:54 +01:00
parent 9a22622f9c
commit cc90ed37f8
30 changed files with 121 additions and 92 deletions
@@ -1,7 +1,7 @@
/**
* Armin says hi! A fun easter egg with animated XBM art.
*/
import type { Component, TUI } from "@oh-my-pi/pi-tui";
import { type Component, padding, type TUI } from "@oh-my-pi/pi-tui";
import { theme } from "../../modes/theme/theme";
// XBM image: 31x36 pixels, LSB first, 1=background, 0=foreground
@@ -87,20 +87,20 @@ export class ArminComponent implements Component {
return this.cachedLines;
}
const padding = 1;
const availableWidth = width - padding;
const indent = 1;
const availableWidth = width - indent;
this.cachedLines = this.currentGrid.map(row => {
// Clip row to available width before applying color
const clipped = row.slice(0, availableWidth).join("");
const padRight = Math.max(0, width - padding - clipped.length);
return ` ${theme.fg("accent", clipped)}${" ".repeat(padRight)}`;
const padRight = Math.max(0, width - indent - clipped.length);
return ` ${theme.fg("accent", clipped)}${padding(padRight)}`;
});
// Add "ARMIN SAYS HI" at the end
const message = "ARMIN SAYS HI";
const msgPadRight = Math.max(0, width - padding - message.length);
this.cachedLines.push(` ${theme.fg("accent", message)}${" ".repeat(msgPadRight)}`);
const msgPadRight = Math.max(0, width - indent - message.length);
this.cachedLines.push(` ${theme.fg("accent", message)}${padding(msgPadRight)}`);
this.cachedWidth = width;
this.cachedVersion = this.gridVersion;
@@ -11,7 +11,16 @@
* - Space: Toggle selected item (or master switch)
* - Esc: Close dashboard (clears search first if active)
*/
import { type Component, Container, matchesKey, Spacer, Text, truncateToWidth, visibleWidth } from "@oh-my-pi/pi-tui";
import {
type Component,
Container,
matchesKey,
padding,
Spacer,
Text,
truncateToWidth,
visibleWidth,
} from "@oh-my-pi/pi-tui";
import type { SettingsManager } from "../../../config/settings-manager";
import { DynamicBorder } from "../../../modes/components/dynamic-border";
import { theme } from "../../../modes/theme/theme";
@@ -296,7 +305,7 @@ class TwoColumnBody implements Component {
for (let i = 0; i < numLines; i++) {
const left = truncateToWidth(leftLines[i] ?? "", leftWidth);
const leftPadded = left + " ".repeat(Math.max(0, leftWidth - visibleWidth(left)));
const leftPadded = left + padding(Math.max(0, leftWidth - visibleWidth(left)));
const right = truncateToWidth(rightLines[i] ?? "", rightWidth);
combined.push(leftPadded + separator + right);
}
@@ -5,7 +5,7 @@
* that toggles the entire provider. All items below are dimmed when the
* master switch is off.
*/
import { type Component, matchesKey, truncateToWidth, visibleWidth } from "@oh-my-pi/pi-tui";
import { type Component, matchesKey, padding, truncateToWidth, visibleWidth } from "@oh-my-pi/pi-tui";
import { isProviderEnabled } from "../../../discovery";
import { theme } from "../../../modes/theme/theme";
import { applyFilter } from "./state-manager";
@@ -272,7 +272,7 @@ export class ExtensionList implements Component {
if (width >= targetWidth) {
return truncateToWidth(text, targetWidth);
}
return text + " ".repeat(targetWidth - width);
return text + padding(targetWidth - width);
}
private rebuildList(): void {
@@ -1,7 +1,7 @@
import * as fs from "node:fs";
import * as path from "node:path";
import type { AssistantMessage } from "@oh-my-pi/pi-ai";
import { type Component, truncateToWidth, visibleWidth } from "@oh-my-pi/pi-tui";
import { type Component, padding, truncateToWidth, visibleWidth } from "@oh-my-pi/pi-tui";
import { isEnoent } from "@oh-my-pi/pi-utils";
import { theme } from "../../modes/theme/theme";
import type { AgentSession } from "../../session/agent-session";
@@ -283,8 +283,8 @@ export class FooterComponent implements Component {
let statsLine: string;
if (totalNeeded <= width) {
// Both fit - add padding to right-align model
const padding = " ".repeat(width - statsLeftWidth - rightSideWidth);
statsLine = statsLeft + padding + rightSide;
const pad = padding(width - statsLeftWidth - rightSideWidth);
statsLine = statsLeft + pad + rightSide;
} else {
// Need to truncate right side
const availableForRight = width - statsLeftWidth - minPadding;
@@ -293,8 +293,8 @@ export class FooterComponent implements Component {
const plainRightSide = rightSide.replace(/\x1b\[[0-9;]*m/g, "");
const truncatedPlain = plainRightSide.substring(0, availableForRight);
// For simplicity, just use plain truncated version (loses color, but fits)
const padding = " ".repeat(width - statsLeftWidth - truncatedPlain.length);
statsLine = statsLeft + padding + truncatedPlain;
const pad = padding(width - statsLeftWidth - truncatedPlain.length);
statsLine = statsLeft + pad + truncatedPlain;
} else {
// Not enough space for right side at all
statsLine = statsLeft;
@@ -3,6 +3,7 @@ import {
Container,
Input,
matchesKey,
padding,
Spacer,
Text,
truncateToWidth,
@@ -50,7 +51,7 @@ class HistoryResultsList implements Component {
const cursorSymbol = `${theme.nav.cursor} `;
const cursorWidth = visibleWidth(cursorSymbol);
const cursor = isSelected ? theme.fg("accent", cursorSymbol) : " ".repeat(cursorWidth);
const cursor = isSelected ? theme.fg("accent", cursorSymbol) : padding(cursorWidth);
const maxWidth = width - cursorWidth;
const normalized = entry.prompt.replace(/\s+/g, " ").trim();
@@ -2,7 +2,7 @@
* Generic selector component for hooks.
* Displays a list of string options with keyboard navigation.
*/
import { Container, matchesKey, Spacer, Text, type TUI, visibleWidth } from "@oh-my-pi/pi-tui";
import { Container, matchesKey, padding, Spacer, Text, type TUI, visibleWidth } from "@oh-my-pi/pi-tui";
import { theme } from "../../modes/theme/theme";
import { CountdownTimer } from "./countdown-timer";
import { DynamicBorder } from "./dynamic-border";
@@ -29,7 +29,7 @@ class OutlinedList extends Container {
const innerWidth = Math.max(1, width - 2);
const content = this.lines.map(line => {
const pad = Math.max(0, innerWidth - visibleWidth(line));
return `${borderColor(theme.boxSharp.vertical)}${line}${" ".repeat(pad)}${borderColor(theme.boxSharp.vertical)}`;
return `${borderColor(theme.boxSharp.vertical)}${line}${padding(pad)}${borderColor(theme.boxSharp.vertical)}`;
});
return [horizontal, ...content, horizontal];
}
@@ -3,6 +3,7 @@ import {
Container,
Input,
matchesKey,
padding,
Spacer,
Text,
truncateToWidth,
@@ -122,7 +123,7 @@ class SessionList implements Component {
// First line: cursor + title (or first message if no title)
const cursorSymbol = `${theme.nav.cursor} `;
const cursorWidth = visibleWidth(cursorSymbol);
const cursor = isSelected ? theme.fg("accent", cursorSymbol) : " ".repeat(cursorWidth);
const cursor = isSelected ? theme.fg("accent", cursorSymbol) : padding(cursorWidth);
const maxWidth = width - cursorWidth; // Account for cursor width
if (session.title) {
@@ -8,7 +8,7 @@
* - Shift+J/K: Reorder segment within column
* - Live preview shown in the actual status line above
*/
import { Container, matchesKey } from "@oh-my-pi/pi-tui";
import { Container, matchesKey, padding } from "@oh-my-pi/pi-tui";
import type { StatusLineSegmentId } from "../../config/settings-manager";
import { theme } from "../../modes/theme/theme";
import { ALL_SEGMENT_IDS } from "./status-line/segments";
@@ -351,7 +351,7 @@ export class StatusLineSegmentEditorComponent extends Container {
}
// Pad to column width (accounting for ANSI codes)
const padding = colWidth - label.length - 1;
return text + " ".repeat(Math.max(0, padding));
const padSize = colWidth - label.length - 1;
return text + padding(Math.max(0, padSize));
}
}
@@ -1,7 +1,7 @@
import * as fs from "node:fs";
import * as path from "node:path";
import type { AssistantMessage } from "@oh-my-pi/pi-ai";
import { type Component, truncateToWidth, visibleWidth } from "@oh-my-pi/pi-tui";
import { type Component, padding, truncateToWidth, visibleWidth } from "@oh-my-pi/pi-tui";
import { $ } from "bun";
import type { StatusLineSegmentOptions, StatusLineSettings } from "../../config/settings-manager";
import { theme } from "../../modes/theme/theme";
@@ -378,7 +378,7 @@ export class StatusLineComponent implements Component {
leftWidth = groupWidth(left, leftCapWidth, leftSepWidth);
rightWidth = groupWidth(right, rightCapWidth, rightSepWidth);
const gapWidth = Math.max(1, topFillWidth - leftWidth - rightWidth);
return leftGroup + " ".repeat(gapWidth) + rightGroup;
return leftGroup + padding(gapWidth) + rightGroup;
}
getTopBorder(width: number): { content: string; width: number } {
@@ -1,4 +1,4 @@
import { type Component, truncateToWidth, visibleWidth } from "@oh-my-pi/pi-tui";
import { type Component, padding, truncateToWidth, visibleWidth } from "@oh-my-pi/pi-tui";
import { APP_NAME } from "../../config";
import { theme } from "../../modes/theme/theme";
@@ -169,7 +169,7 @@ export class WelcomeComponent implements Component {
}
const leftPad = Math.floor((width - visLen) / 2);
const rightPad = width - visLen - leftPad;
return " ".repeat(leftPad) + text + " ".repeat(rightPad);
return padding(leftPad) + text + padding(rightPad);
}
/** Apply magenta→cyan gradient to a string */
@@ -224,6 +224,6 @@ export class WelcomeComponent implements Component {
}
return `${truncated}${ellipsis}`;
}
return str + " ".repeat(width - visLen);
return str + padding(width - visLen);
}
}
@@ -2,7 +2,7 @@ import * as fs from "node:fs/promises";
import * as os from "node:os";
import * as path from "node:path";
import type { UsageLimit, UsageReport } from "@oh-my-pi/pi-ai";
import { Loader, Markdown, Spacer, Text, visibleWidth } from "@oh-my-pi/pi-tui";
import { Loader, Markdown, padding, Spacer, Text, visibleWidth } from "@oh-my-pi/pi-tui";
import { $ } from "bun";
import { nanoid } from "nanoid";
import { loadCustomShare } from "../../export/custom-share";
@@ -773,7 +773,7 @@ function formatAccountHeader(limit: UsageLimit, report: UsageReport, index: numb
function padColumn(text: string, width: number): string {
const visible = visibleWidth(text);
if (visible >= width) return text;
return `${text}${" ".repeat(width - visible)}`;
return `${text}${padding(width - visible)}`;
}
function resolveAggregateStatus(limits: UsageLimit[]): UsageLimit["status"] {