Add performant ANSI module
This commit is contained in:
parent
e925828328
commit
bcdbf8f7c6
131
src/lib/util/ansi.ts
Normal file
131
src/lib/util/ansi.ts
Normal file
@ -0,0 +1,131 @@
|
||||
import { tryCatch, type Result } from '@maxmorozoff/try-catch-tuple';
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
|
||||
export const ANSI = {
|
||||
// Text Styles
|
||||
RESET: '\x1B[0m',
|
||||
BOLD: '\x1B[1m',
|
||||
DIM: '\x1B[2m',
|
||||
ITALIC: '\x1B[3m',
|
||||
UNDERLINE: '\x1B[4m',
|
||||
BLINK: '\x1B[5m',
|
||||
REVERSE: '\x1B[7m',
|
||||
HIDDEN: '\x1B[8m',
|
||||
|
||||
// Foreground Colors
|
||||
BLACK: '\x1B[30m',
|
||||
RED: '\x1B[31m',
|
||||
GREEN: '\x1B[32m',
|
||||
YELLOW: '\x1B[33m',
|
||||
BLUE: '\x1B[34m',
|
||||
MAGENTA: '\x1B[35m',
|
||||
CYAN: '\x1B[36m',
|
||||
WHITE: '\x1B[37m',
|
||||
|
||||
// Background Colors
|
||||
BG_BLACK: '\x1B[40m',
|
||||
BG_RED: '\x1B[41m',
|
||||
BG_GREEN: '\x1B[42m',
|
||||
BG_YELLOW: '\x1B[43m',
|
||||
BG_BLUE: '\x1B[44m',
|
||||
BG_MAGENTA: '\x1B[45m',
|
||||
BG_CYAN: '\x1B[46m',
|
||||
BG_WHITE: '\x1B[47m',
|
||||
|
||||
// Cursor Control
|
||||
SAVE_CURSOR: '\x1B[s',
|
||||
RESTORE_CURSOR: '\x1B[u',
|
||||
CURSOR_TO: (x: number, y: number) => `\x1B[${y};${x}H`,
|
||||
CURSOR_UP: (n = 1) => `\x1B[${n}A`,
|
||||
CURSOR_DOWN: (n = 1) => `\x1B[${n}B`,
|
||||
CURSOR_FORWARD: (n = 1) => `\x1B[${n}C`,
|
||||
CURSOR_BACK: (n = 1) => `\x1B[${n}D`,
|
||||
|
||||
// Screen Control
|
||||
CLEAR_SCREEN: '\x1B[2J',
|
||||
CLEAR_LINE: '\x1B[2K',
|
||||
CLEAR_END_LINE: '\x1B[0K',
|
||||
CLEAR_START_LINE: '\x1B[1K',
|
||||
CLEAR_BELOW: '\x1B[J',
|
||||
};
|
||||
|
||||
export const ANSI_BUFFERS = {
|
||||
// Static code buffers
|
||||
RESET: encoder.encode(ANSI.RESET),
|
||||
BOLD: encoder.encode(ANSI.BOLD),
|
||||
DIM: encoder.encode(ANSI.DIM),
|
||||
ITALIC: encoder.encode(ANSI.ITALIC),
|
||||
UNDERLINE: encoder.encode(ANSI.UNDERLINE),
|
||||
BLINK: encoder.encode(ANSI.BLINK),
|
||||
REVERSE: encoder.encode(ANSI.REVERSE),
|
||||
HIDDEN: encoder.encode(ANSI.HIDDEN),
|
||||
|
||||
// Colors
|
||||
BLACK: encoder.encode(ANSI.BLACK),
|
||||
RED: encoder.encode(ANSI.RED),
|
||||
GREEN: encoder.encode(ANSI.GREEN),
|
||||
YELLOW: encoder.encode(ANSI.YELLOW),
|
||||
BLUE: encoder.encode(ANSI.BLUE),
|
||||
MAGENTA: encoder.encode(ANSI.MAGENTA),
|
||||
CYAN: encoder.encode(ANSI.CYAN),
|
||||
WHITE: encoder.encode(ANSI.WHITE),
|
||||
|
||||
// Backgrounds
|
||||
BG_BLACK: encoder.encode(ANSI.BG_BLACK),
|
||||
BG_RED: encoder.encode(ANSI.BG_RED),
|
||||
BG_GREEN: encoder.encode(ANSI.BG_GREEN),
|
||||
BG_YELLOW: encoder.encode(ANSI.BG_YELLOW),
|
||||
BG_BLUE: encoder.encode(ANSI.BG_BLUE),
|
||||
BG_MAGENTA: encoder.encode(ANSI.BG_MAGENTA),
|
||||
BG_CYAN: encoder.encode(ANSI.BG_CYAN),
|
||||
BG_WHITE: encoder.encode(ANSI.BG_WHITE),
|
||||
|
||||
// Cursor Control
|
||||
SAVE_CURSOR: encoder.encode(ANSI.SAVE_CURSOR),
|
||||
RESTORE_CURSOR: encoder.encode(ANSI.RESTORE_CURSOR),
|
||||
CLEAR_SCREEN: encoder.encode(ANSI.CLEAR_SCREEN),
|
||||
CLEAR_LINE: encoder.encode(ANSI.CLEAR_LINE),
|
||||
CLEAR_BELOW: encoder.encode(ANSI.CLEAR_BELOW),
|
||||
};
|
||||
|
||||
type AnsiBufferKey = keyof typeof ANSI_BUFFERS;
|
||||
|
||||
export async function writeAnsi(
|
||||
codes: AnsiBufferKey[],
|
||||
text?: string,
|
||||
autoReset: boolean = true
|
||||
): Promise<Result<number, Error>> {
|
||||
const buffers: Uint8Array[] = [];
|
||||
|
||||
// Add requested ANSI codes
|
||||
for (const code of codes) {
|
||||
buffers.push(ANSI_BUFFERS[code]);
|
||||
}
|
||||
|
||||
// Add optional text
|
||||
if (text) {
|
||||
buffers.push(encoder.encode(text));
|
||||
}
|
||||
|
||||
// Auto-reset if requested
|
||||
if (autoReset && !codes.includes('RESET')) {
|
||||
buffers.push(ANSI_BUFFERS.RESET);
|
||||
}
|
||||
|
||||
// Combine all buffers into single write
|
||||
const combined = new Uint8Array(
|
||||
buffers.reduce((acc, buf) => acc + buf.length, 0)
|
||||
);
|
||||
|
||||
let offset = 0;
|
||||
for (const buf of buffers) {
|
||||
combined.set(buf, offset);
|
||||
offset += buf.length;
|
||||
}
|
||||
|
||||
return tryCatch(() => Bun.write(Bun.stdout, combined));
|
||||
}
|
||||
|
||||
// For CommonJS compatibility
|
||||
export default { ANSI, ANSI_BUFFERS, writeAnsi };
|
||||
Loading…
Reference in New Issue
Block a user