Skip to content

Instantly share code, notes, and snippets.

@intrnl
Created Jun 30, 2022
Embed
What would you like to do?
import * as tty from 'node:tty';
const isTTY = tty.isatty(1) && process.env.TERM !== 'dumb' && !('CI' in process.env);
export function createLogger (options = {}) {
let { text = '', interval = 50, stream = process.stdout, hideCursor = false } = options;
let rows = 0;
let timer;
const instance = {
reset () {
rows = 0;
timer = clearInterval(timer);
},
start () {
timer && instance.reset();
instance._loop();
},
log (str) {
if (timer) {
instance._clear();
}
instance._write(`${str}\n`);
if (timer) {
instance._render();
}
},
stop () {
timer = clearTimeout(timer);
instance._clear();
if (isTTY && hideCursor) {
instance._write(`\x1b[?25h`);
}
},
end (next) {
timer = clearTimeout(timer);
instance._write(`${next}\n`, true);
if (isTTY && hideCursor) {
instance._write(`\x1b[?25h`);
}
},
update (next) {
text = next;
},
_write (str, clear = false) {
if (clear && isTTY) {
instance._clear();
}
stream.write(str);
},
_loop () {
if (isTTY) {
timer = setTimeout(() => instance._loop(), interval);
}
instance._render();
},
_clear () {
instance._write('\x1b[1G')
for (let i = 0; i < rows; i++) {
if (i > 0) {
instance._write('\x1b[1A');
}
instance._write('\x1b[2K\x1b[1G');
}
rows = 0
},
_render () {
let str = text;
if (isTTY) {
if (hideCursor) {
instance._write(`\x1b[?25l`);
}
}
else {
str += '\n';
}
instance._write(str, true);
if (isTTY) {
rows = getRows(str, stream.columns);
}
},
};
return instance;
}
function getRows (str = '', width = 80) {
const lines = str.replace(/\u001b[^m]*?m/g, '').split('\n');
let rows = 0;
for (let idx = 0, len = lines.length; idx < len; idx++) {
const line = lines[idx];
rows += Math.max(1, Math.ceil(line.length / width));
}
return rows;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment