kodevu 0.1.14 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/progress-ui.js +87 -8
package/package.json
CHANGED
package/src/progress-ui.js
CHANGED
|
@@ -26,6 +26,22 @@ function buildBar(progress, width) {
|
|
|
26
26
|
return `[${"=".repeat(Math.max(filled - 1, 0))}>${" ".repeat(width - filled)}]`;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
function truncateLine(line, maxWidth) {
|
|
30
|
+
if (!Number.isFinite(maxWidth) || maxWidth <= 0) {
|
|
31
|
+
return "";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (line.length <= maxWidth) {
|
|
35
|
+
return line;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (maxWidth <= 3) {
|
|
39
|
+
return ".".repeat(maxWidth);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return `${line.slice(0, maxWidth - 3)}...`;
|
|
43
|
+
}
|
|
44
|
+
|
|
29
45
|
class ProgressItem {
|
|
30
46
|
constructor(display, label, options = {}) {
|
|
31
47
|
this.display = display;
|
|
@@ -81,18 +97,45 @@ class ProgressItem {
|
|
|
81
97
|
this.progress = clampProgress(progress);
|
|
82
98
|
this.active = false;
|
|
83
99
|
this.display.stopIfIdle();
|
|
84
|
-
this.display.writeStaticLine(
|
|
85
|
-
`${prefix} ${this.label} ${buildBar(this.progress, this.barWidth)} ${Math.round(this.progress * 100)
|
|
86
|
-
.toString()
|
|
87
|
-
.padStart(3, " ")}% ${message}`
|
|
88
|
-
);
|
|
100
|
+
this.display.writeStaticLine(this.buildLine(prefix, message));
|
|
89
101
|
}
|
|
90
102
|
|
|
91
103
|
renderLine(frameIndex) {
|
|
92
104
|
const spinner = SPINNER_FRAMES[frameIndex];
|
|
93
|
-
|
|
105
|
+
return this.buildLine(spinner, this.stage);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
buildLine(prefix, suffix) {
|
|
109
|
+
const availableWidth = this.display.getAvailableWidth();
|
|
94
110
|
const pct = `${Math.round(this.progress * 100)}`.padStart(3, " ");
|
|
95
|
-
|
|
111
|
+
const parts = [prefix, this.label];
|
|
112
|
+
const suffixText = suffix ? ` ${suffix}` : "";
|
|
113
|
+
|
|
114
|
+
if (availableWidth < 10) {
|
|
115
|
+
return truncateLine(`${prefix} ${pct}%`, availableWidth);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const fullReservedWidth = prefix.length + this.label.length + pct.length + suffixText.length + 4;
|
|
119
|
+
const fullBarWidth = availableWidth - fullReservedWidth;
|
|
120
|
+
|
|
121
|
+
if (fullBarWidth >= 4) {
|
|
122
|
+
return truncateLine(
|
|
123
|
+
`${parts.join(" ")} ${buildBar(this.progress, Math.min(this.barWidth, fullBarWidth))} ${pct}%${suffixText}`,
|
|
124
|
+
availableWidth
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const compactReservedWidth = prefix.length + pct.length + suffixText.length + 4;
|
|
129
|
+
const compactBarWidth = availableWidth - compactReservedWidth;
|
|
130
|
+
|
|
131
|
+
if (compactBarWidth >= 4) {
|
|
132
|
+
return truncateLine(
|
|
133
|
+
`${prefix} ${buildBar(this.progress, compactBarWidth)} ${pct}%${suffixText}`,
|
|
134
|
+
availableWidth
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return truncateLine(`${prefix} ${pct}%${suffixText}`, availableWidth);
|
|
96
139
|
}
|
|
97
140
|
|
|
98
141
|
writeFallback(line) {
|
|
@@ -113,6 +156,7 @@ export class ProgressDisplay {
|
|
|
113
156
|
this.timer = null;
|
|
114
157
|
this.items = [];
|
|
115
158
|
this.renderedLineCount = 0;
|
|
159
|
+
this.handleResize = this.handleResize.bind(this);
|
|
116
160
|
}
|
|
117
161
|
|
|
118
162
|
createItem(label, options = {}) {
|
|
@@ -126,6 +170,8 @@ export class ProgressDisplay {
|
|
|
126
170
|
return;
|
|
127
171
|
}
|
|
128
172
|
|
|
173
|
+
this.attachResizeHandler();
|
|
174
|
+
|
|
129
175
|
this.timer = setInterval(() => {
|
|
130
176
|
this.frameIndex = (this.frameIndex + 1) % SPINNER_FRAMES.length;
|
|
131
177
|
this.render();
|
|
@@ -150,7 +196,7 @@ export class ProgressDisplay {
|
|
|
150
196
|
}
|
|
151
197
|
|
|
152
198
|
this.clearRender();
|
|
153
|
-
this.stream.write(`${message}\n`);
|
|
199
|
+
this.stream.write(`${truncateLine(message, this.getAvailableWidth())}\n`);
|
|
154
200
|
this.render();
|
|
155
201
|
}
|
|
156
202
|
|
|
@@ -202,5 +248,38 @@ export class ProgressDisplay {
|
|
|
202
248
|
clearInterval(this.timer);
|
|
203
249
|
this.timer = null;
|
|
204
250
|
}
|
|
251
|
+
|
|
252
|
+
this.detachResizeHandler();
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
getAvailableWidth() {
|
|
256
|
+
const columns = this.stream.columns || 80;
|
|
257
|
+
return Math.max(columns - 1, 1);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
handleResize() {
|
|
261
|
+
if (!this.enabled) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
this.render();
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
attachResizeHandler() {
|
|
269
|
+
if (typeof this.stream.on !== "function" || this.resizeAttached) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
this.stream.on("resize", this.handleResize);
|
|
274
|
+
this.resizeAttached = true;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
detachResizeHandler() {
|
|
278
|
+
if (typeof this.stream.off !== "function" || !this.resizeAttached) {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
this.stream.off("resize", this.handleResize);
|
|
283
|
+
this.resizeAttached = false;
|
|
205
284
|
}
|
|
206
285
|
}
|