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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/progress-ui.js +87 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kodevu",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "type": "module",
5
5
  "description": "Poll SVN revisions or Git commits, send each change diff to a reviewer CLI, and write configurable review reports.",
6
6
  "bin": {
@@ -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
- const bar = buildBar(this.progress, this.barWidth);
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
- return `${spinner} ${this.label} ${bar} ${pct}% ${this.stage}`;
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
  }