96 lines
2.2 KiB
TypeScript
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("");
|
|
}
|