56 lines
1.7 KiB
TypeScript
56 lines
1.7 KiB
TypeScript
#!/usr/bin/env bun
|
|
|
|
export type CursorPosition = { row: number; col: number };
|
|
|
|
export const TerminalUtils = {
|
|
clear: {
|
|
screen: () => process.stdout.write('\x1Bc'),
|
|
content: () => process.stdout.write('\x1B[2J'),
|
|
cursorHome: () => process.stdout.write('\x1B[H'),
|
|
line: () => process.stdout.write('\x1B[K'),
|
|
below: () => process.stdout.write('\x1B[J'),
|
|
above: () => process.stdout.write('\x1B[1J'),
|
|
clear: () => console.clear(),
|
|
},
|
|
|
|
cursor: {
|
|
/** Move cursor to a specific row & column */
|
|
moveCursor: (row: number, col: number) =>
|
|
process.stdout.write(`\x1B[${row};${col}H`),
|
|
|
|
/** Queries the terminal for the current cursor position */
|
|
async getCursorPosition(): Promise<CursorPosition> {
|
|
return new Promise((resolve, reject) => {
|
|
if (!process.stdin.isTTY || !process.stdout.isTTY)
|
|
reject(new Error('Not running in a terminal environment!'));
|
|
|
|
const stdin = process.stdin;
|
|
stdin.setRawMode(true);
|
|
stdin.resume();
|
|
stdin.setEncoding('utf8');
|
|
|
|
stdin.once('data', (data) => {
|
|
const match = /\[(\d+);(\d+)R/.exec(data.toString());
|
|
resolve({
|
|
row: parseInt(match?.[1] ?? '0', 10),
|
|
col: parseInt(match?.[2] ?? '0', 10),
|
|
});
|
|
stdin.setRawMode(false);
|
|
stdin.pause();
|
|
});
|
|
|
|
process.stdout.write('\x1B[6n'); // Ask terminal for cursor position
|
|
});
|
|
},
|
|
|
|
/** Stores detected cursor position in a constant */
|
|
async storePosition(): Promise<CursorPosition> {
|
|
return TerminalUtils.cursor.getCursorPosition();
|
|
},
|
|
|
|
/** Restores the passed cursor position */
|
|
restorePosition: (pos: CursorPosition) =>
|
|
TerminalUtils.cursor.moveCursor(pos.row, pos.col),
|
|
},
|
|
};
|