114 lines
2.6 KiB
JavaScript
114 lines
2.6 KiB
JavaScript
const pico = require('picocolors')
|
|
|
|
const { isTTY, symbols } = require('./consts')
|
|
|
|
const { green, red } = pico
|
|
|
|
function getLines(str = '', width = 80) {
|
|
return str
|
|
.replace(/\u001b[^m]*?m/g, '')
|
|
.split('\n')
|
|
.reduce((col, line) => (col += Math.max(1, Math.ceil(line.length / width))), 0)
|
|
}
|
|
|
|
function createSpinner(text = '', opts = {}) {
|
|
let current = 0,
|
|
interval = opts.interval || 50,
|
|
stream = opts.stream || process.stderr,
|
|
frames = opts.frames && opts.frames.length ? opts.frames : symbols.frames,
|
|
color = opts.color || 'yellow',
|
|
lines = 0,
|
|
timer
|
|
|
|
let spinner = {
|
|
reset() {
|
|
current = 0
|
|
lines = 0
|
|
timer = clearTimeout(timer)
|
|
},
|
|
|
|
clear() {
|
|
spinner.write('\x1b[1G')
|
|
for (let i = 0; i < lines; i++) {
|
|
i > 0 && spinner.write('\x1b[1A')
|
|
spinner.write('\x1b[2K\x1b[1G')
|
|
}
|
|
lines = 0
|
|
|
|
return spinner
|
|
},
|
|
|
|
write(str, clear = false) {
|
|
if (clear && isTTY) {
|
|
spinner.clear()
|
|
}
|
|
|
|
stream.write(str)
|
|
return spinner
|
|
},
|
|
|
|
render() {
|
|
let mark = pico[color](frames[current])
|
|
let str = `${mark} ${text}`
|
|
isTTY ? spinner.write(`\x1b[?25l`) : (str += '\n')
|
|
spinner.write(str, true)
|
|
isTTY && (lines = getLines(str, stream.columns))
|
|
},
|
|
|
|
spin() {
|
|
spinner.render()
|
|
current = ++current % frames.length
|
|
return spinner
|
|
},
|
|
|
|
update(opts = {}) {
|
|
text = opts.text || text
|
|
frames = opts.frames && opts.frames.length ? opts.frames : frames
|
|
interval = opts.interval || interval
|
|
color = opts.color || color
|
|
|
|
if (frames.length - 1 < current) {
|
|
current = 0
|
|
}
|
|
|
|
return spinner
|
|
},
|
|
|
|
loop() {
|
|
isTTY && (timer = setTimeout(() => spinner.loop(), interval))
|
|
return spinner.spin()
|
|
},
|
|
|
|
start(opts = {}) {
|
|
timer && spinner.reset()
|
|
return spinner.update({ text: opts.text, color: opts.color }).loop()
|
|
},
|
|
|
|
stop(opts = {}) {
|
|
timer = clearTimeout(timer)
|
|
|
|
let mark = pico[opts.color || color](frames[current])
|
|
let optsMark = opts.mark && opts.color ? pico[opts.color](opts.mark) : opts.mark
|
|
spinner.write(`${optsMark || mark} ${opts.text || text}\n`, true)
|
|
|
|
return isTTY ? spinner.write(`\x1b[?25h`) : spinner
|
|
},
|
|
|
|
success(opts = {}) {
|
|
let mark = green(symbols.tick)
|
|
return spinner.stop({ mark, ...opts })
|
|
},
|
|
|
|
error(opts = {}) {
|
|
let mark = red(symbols.cross)
|
|
return spinner.stop({ mark, ...opts })
|
|
},
|
|
}
|
|
|
|
return spinner
|
|
}
|
|
|
|
module.exports = {
|
|
createSpinner,
|
|
}
|