/
index.js
126 lines (101 loc) 路 2.8 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
const pico = require('picocolors')
const { isTTY, symbols } = require('./consts')
const { green, red, yellow } = 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',
spinning = false,
lines = 0,
timer
let spinner = {
reset() {
current = 0
lines = 0
spinning = false
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()
spinning = true
return spinner.update({ text: opts.text, color: opts.color }).loop()
},
stop(opts = {}) {
timer = clearTimeout(timer)
spinning = false
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 })
},
warn(opts = {}) {
let mark = yellow(symbols.warn)
return spinner.stop({ mark, ...opts })
},
isSpinning() {
return spinning
},
}
return spinner
}
module.exports = {
createSpinner,
}