kodevu 0.1.17 → 0.1.18

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 +78 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kodevu",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
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": {
@@ -1,6 +1,7 @@
1
1
  import readline from "node:readline";
2
2
 
3
3
  const SPINNER_FRAMES = ["|", "/", "-", "\\"];
4
+ const ELLIPSIS = "...";
4
5
 
5
6
  function clampProgress(value) {
6
7
  if (!Number.isFinite(value)) {
@@ -10,12 +11,53 @@ function clampProgress(value) {
10
11
  return Math.max(0, Math.min(1, value));
11
12
  }
12
13
 
14
+ function getCharacterWidth(character) {
15
+ const codePoint = character.codePointAt(0);
16
+
17
+ if (!codePoint || codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f)) {
18
+ return 0;
19
+ }
20
+
21
+ if (
22
+ codePoint >= 0x1100 &&
23
+ (
24
+ codePoint <= 0x115f ||
25
+ codePoint === 0x2329 ||
26
+ codePoint === 0x232a ||
27
+ (codePoint >= 0x2e80 && codePoint <= 0xa4cf && codePoint !== 0x303f) ||
28
+ (codePoint >= 0xac00 && codePoint <= 0xd7a3) ||
29
+ (codePoint >= 0xf900 && codePoint <= 0xfaff) ||
30
+ (codePoint >= 0xfe10 && codePoint <= 0xfe19) ||
31
+ (codePoint >= 0xfe30 && codePoint <= 0xfe6f) ||
32
+ (codePoint >= 0xff00 && codePoint <= 0xff60) ||
33
+ (codePoint >= 0xffe0 && codePoint <= 0xffe6) ||
34
+ (codePoint >= 0x1f300 && codePoint <= 0x1f64f) ||
35
+ (codePoint >= 0x1f900 && codePoint <= 0x1f9ff) ||
36
+ (codePoint >= 0x20000 && codePoint <= 0x3fffd)
37
+ )
38
+ ) {
39
+ return 2;
40
+ }
41
+
42
+ return 1;
43
+ }
44
+
45
+ function getDisplayWidth(text) {
46
+ let width = 0;
47
+
48
+ for (const character of text) {
49
+ width += getCharacterWidth(character);
50
+ }
51
+
52
+ return width;
53
+ }
54
+
13
55
  function truncateLine(line, maxWidth) {
14
56
  if (!Number.isFinite(maxWidth) || maxWidth <= 0) {
15
57
  return "";
16
58
  }
17
59
 
18
- if (line.length <= maxWidth) {
60
+ if (getDisplayWidth(line) <= maxWidth) {
19
61
  return line;
20
62
  }
21
63
 
@@ -23,7 +65,22 @@ function truncateLine(line, maxWidth) {
23
65
  return ".".repeat(maxWidth);
24
66
  }
25
67
 
26
- return `${line.slice(0, maxWidth - 3)}...`;
68
+ const targetWidth = maxWidth - getDisplayWidth(ELLIPSIS);
69
+ let result = "";
70
+ let width = 0;
71
+
72
+ for (const character of line) {
73
+ const nextWidth = width + getCharacterWidth(character);
74
+
75
+ if (nextWidth > targetWidth) {
76
+ break;
77
+ }
78
+
79
+ result += character;
80
+ width = nextWidth;
81
+ }
82
+
83
+ return `${result}${ELLIPSIS}`;
27
84
  }
28
85
 
29
86
  class ProgressItem {
@@ -117,6 +174,7 @@ export class ProgressDisplay {
117
174
  this.items = [];
118
175
  this.currentItem = null;
119
176
  this.statusVisible = false;
177
+ this.lastStatusWidth = 0;
120
178
  this.resizeAttached = false;
121
179
  this.handleResize = this.handleResize.bind(this);
122
180
  }
@@ -185,8 +243,10 @@ export class ProgressDisplay {
185
243
  }
186
244
 
187
245
  this.clearStatusLine();
188
- this.stream.write(this.currentItem.renderLine(this.frameIndex));
246
+ const line = this.currentItem.renderLine(this.frameIndex);
247
+ this.stream.write(line);
189
248
  this.statusVisible = true;
249
+ this.lastStatusWidth = getDisplayWidth(line);
190
250
  }
191
251
 
192
252
  clearStatusLine() {
@@ -194,9 +254,23 @@ export class ProgressDisplay {
194
254
  return;
195
255
  }
196
256
 
197
- readline.clearLine(this.stream, 0);
257
+ const rows = Math.max(1, Math.ceil(this.lastStatusWidth / Math.max(this.stream.columns || 1, 1)));
258
+
259
+ readline.moveCursor(this.stream, 0, -Math.max(rows - 1, 0));
260
+
261
+ for (let index = 0; index < rows; index += 1) {
262
+ readline.clearLine(this.stream, 0);
263
+ readline.cursorTo(this.stream, 0);
264
+
265
+ if (index < rows - 1) {
266
+ readline.moveCursor(this.stream, 0, 1);
267
+ }
268
+ }
269
+
270
+ readline.moveCursor(this.stream, 0, -Math.max(rows - 1, 0));
198
271
  readline.cursorTo(this.stream, 0);
199
272
  this.statusVisible = false;
273
+ this.lastStatusWidth = 0;
200
274
  }
201
275
 
202
276
  stopIfIdle() {