Files
paseo/packages/app/src/utils/terminal-output-buffer.ts
T

96 lines
2.2 KiB
TypeScript

export interface TerminalOutputBuffer {
segments: string[];
startIndex: number;
totalChars: number;
}
const COMPACT_SEGMENT_THRESHOLD = 256;
export function createTerminalOutputBuffer(): TerminalOutputBuffer {
return {
segments: [],
startIndex: 0,
totalChars: 0,
};
}
function normalizeMaxChars(input: { maxChars: number }): number {
if (!Number.isFinite(input.maxChars)) {
return 0;
}
return Math.max(0, Math.floor(input.maxChars));
}
function compactTerminalOutputBuffer(input: { buffer: TerminalOutputBuffer }): void {
const { buffer } = input;
if (buffer.startIndex <= COMPACT_SEGMENT_THRESHOLD) {
return;
}
buffer.segments = buffer.segments.slice(buffer.startIndex);
buffer.startIndex = 0;
}
function trimTerminalOutputBufferToMax(input: {
buffer: TerminalOutputBuffer;
maxChars: number;
}): void {
const { buffer } = input;
const maxChars = normalizeMaxChars({ maxChars: input.maxChars });
while (buffer.totalChars > maxChars) {
const leadingSegment = buffer.segments[buffer.startIndex];
if (!leadingSegment) {
buffer.segments = [];
buffer.startIndex = 0;
buffer.totalChars = 0;
return;
}
const overflowChars = buffer.totalChars - maxChars;
if (leadingSegment.length <= overflowChars) {
buffer.startIndex += 1;
buffer.totalChars -= leadingSegment.length;
continue;
}
buffer.segments[buffer.startIndex] = leadingSegment.slice(overflowChars);
buffer.totalChars -= overflowChars;
break;
}
compactTerminalOutputBuffer({ buffer });
}
export function appendTerminalOutputBuffer(input: {
buffer: TerminalOutputBuffer;
text: string;
maxChars: number;
}): void {
if (!input.text) {
return;
}
input.buffer.segments.push(input.text);
input.buffer.totalChars += input.text.length;
trimTerminalOutputBufferToMax({
buffer: input.buffer,
maxChars: input.maxChars,
});
}
export function readTerminalOutputBuffer(input: {
buffer: TerminalOutputBuffer;
}): string {
const { buffer } = input;
if (buffer.totalChars <= 0) {
return "";
}
if (buffer.startIndex === 0) {
return buffer.segments.join("");
}
return buffer.segments.slice(buffer.startIndex).join("");
}