@nmakarov/cli-toolkit 0.81.0 → 0.82.0

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/dist/index.js CHANGED
@@ -1020,9 +1020,44 @@ var init_follow_scroll = __esm({
1020
1020
  }
1021
1021
  });
1022
1022
 
1023
- // src/screen/scrollable-text.js
1024
- import { useState as useState3, useEffect as useEffect2, useMemo, useRef as useRef2, createElement as createElement2 } from "react";
1025
- import { Box as Box4, Text as Text5 } from "ink";
1023
+ // src/screen/visible-text.js
1024
+ function stripAnsi(text) {
1025
+ return String(text ?? "").replace(ANSI_RE, "");
1026
+ }
1027
+ function visibleWidth(text) {
1028
+ return [...stripAnsi(text)].length;
1029
+ }
1030
+ function sliceVisible(text, cols) {
1031
+ const w = Math.max(0, Math.floor(Number(cols) || 0));
1032
+ const s = String(text ?? "");
1033
+ if (w === 0) return "";
1034
+ let vis = 0;
1035
+ let out = "";
1036
+ let i = 0;
1037
+ while (i < s.length && vis < w) {
1038
+ ANSI_RE.lastIndex = i;
1039
+ const m = ANSI_RE.exec(s);
1040
+ if (m && m.index === i) {
1041
+ out += m[0];
1042
+ i += m[0].length;
1043
+ continue;
1044
+ }
1045
+ const cp3 = s.codePointAt(i);
1046
+ const ch = String.fromCodePoint(cp3);
1047
+ out += ch;
1048
+ i += ch.length;
1049
+ vis += 1;
1050
+ }
1051
+ return out;
1052
+ }
1053
+ function padEndVisible(text, cols) {
1054
+ const w = Math.max(0, Math.floor(Number(cols) || 0));
1055
+ const s = String(text ?? "");
1056
+ const vis = visibleWidth(s);
1057
+ if (vis === w) return s;
1058
+ if (vis > w) return sliceVisible(s, w);
1059
+ return s + " ".repeat(w - vis);
1060
+ }
1026
1061
  function wrapTextLines(text, cols) {
1027
1062
  const w = Math.max(1, Math.floor(Number(cols) || 1));
1028
1063
  const out = [];
@@ -1031,20 +1066,30 @@ function wrapTextLines(text, cols) {
1031
1066
  out.push("");
1032
1067
  continue;
1033
1068
  }
1069
+ if (visibleWidth(raw) <= w) {
1070
+ out.push(raw);
1071
+ continue;
1072
+ }
1034
1073
  let rest = raw;
1035
- while (rest.length > w) {
1036
- out.push(rest.slice(0, w));
1037
- rest = rest.slice(w);
1074
+ while (visibleWidth(rest) > w) {
1075
+ const head = sliceVisible(rest, w);
1076
+ out.push(head);
1077
+ rest = rest.slice(head.length);
1038
1078
  }
1039
1079
  if (rest.length > 0) out.push(rest);
1040
1080
  }
1041
1081
  return out;
1042
1082
  }
1043
- function padEndVisible(s, w) {
1044
- const t = String(s ?? "");
1045
- if (t.length >= w) return t.slice(0, w);
1046
- return t + " ".repeat(w - t.length);
1047
- }
1083
+ var ANSI_RE;
1084
+ var init_visible_text = __esm({
1085
+ "src/screen/visible-text.js"() {
1086
+ ANSI_RE = /\u001b(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g;
1087
+ }
1088
+ });
1089
+
1090
+ // src/screen/scrollable-text.js
1091
+ import { useState as useState3, useEffect as useEffect2, useMemo, useRef as useRef2, createElement as createElement2 } from "react";
1092
+ import { Box as Box4, Text as Text5 } from "ink";
1048
1093
  function ScrollableText({
1049
1094
  ctx,
1050
1095
  text = "",
@@ -1112,14 +1157,17 @@ function ScrollableText({
1112
1157
  }, [ctx, bindKeys, followBottom]);
1113
1158
  const status = allLines.length === 0 ? "empty" : `lines ${clamped + 1}-${Math.min(clamped + visible.length, allLines.length)} of ${allLines.length}` + (needsBar ? " \xB7 \u2325\u2191/\u2193 or PgUp/Dn page" : "") + (followBottom && following ? " \xB7 follow" : followBottom ? " \xB7 follow off" : "");
1114
1159
  const rowNodes = visible.map((line, i) => {
1115
- const body = padEndVisible(line, textWidth);
1116
1160
  const glyph = bar ? bar[i] ?? BAR_TRACK : showScrollbar ? " " : "";
1117
1161
  const isThumb = glyph === BAR_THUMB;
1118
1162
  return h5(
1119
- Text5,
1120
- { key: `L${clamped + i}` },
1121
- body,
1122
- glyph ? h5(Text5, { color: isThumb ? "cyan" : "gray" }, glyph) : null
1163
+ Box4,
1164
+ { key: `L${clamped + i}`, flexDirection: "row", width: contentCols, flexShrink: 0 },
1165
+ h5(
1166
+ Box4,
1167
+ { width: textWidth, flexShrink: 0 },
1168
+ h5(Text5, { wrap: "truncate" }, padEndVisible(line, textWidth))
1169
+ ),
1170
+ showScrollbar ? h5(Box4, { width: 1, flexShrink: 0 }, h5(Text5, { color: isThumb ? "cyan" : "gray" }, glyph)) : null
1123
1171
  );
1124
1172
  });
1125
1173
  if (bar && visible.length < viewportRows) {
@@ -1127,10 +1175,10 @@ function ScrollableText({
1127
1175
  const glyph = bar[i] ?? BAR_TRACK;
1128
1176
  rowNodes.push(
1129
1177
  h5(
1130
- Text5,
1131
- { key: `pad${i}` },
1132
- padEndVisible("", textWidth),
1133
- h5(Text5, { color: glyph === BAR_THUMB ? "cyan" : "gray" }, glyph)
1178
+ Box4,
1179
+ { key: `pad${i}`, flexDirection: "row", width: contentCols, flexShrink: 0 },
1180
+ h5(Box4, { width: textWidth, flexShrink: 0 }, h5(Text5, {}, padEndVisible("", textWidth))),
1181
+ h5(Box4, { width: 1, flexShrink: 0 }, h5(Text5, { color: glyph === BAR_THUMB ? "cyan" : "gray" }, glyph))
1134
1182
  )
1135
1183
  );
1136
1184
  }
@@ -1149,7 +1197,9 @@ var init_scrollable_text = __esm({
1149
1197
  init_components();
1150
1198
  init_scrollbar();
1151
1199
  init_follow_scroll();
1200
+ init_visible_text();
1152
1201
  init_scrollbar();
1202
+ init_visible_text();
1153
1203
  h5 = createElement2;
1154
1204
  SCROLL_KEYS = [
1155
1205
  { key: "upArrow", caption: "scroll", action: "scrollUp", order: 0 },
@@ -1307,6 +1357,7 @@ var init_screen = __esm({
1307
1357
  init_components();
1308
1358
  init_ui_elements();
1309
1359
  init_scrollable_text();
1360
+ init_visible_text();
1310
1361
  init_follow_scroll();
1311
1362
  init_scrollbar();
1312
1363
  init_key_bindings();
@@ -10252,6 +10303,7 @@ export {
10252
10303
  npmEnv,
10253
10304
  npmInstallEnv,
10254
10305
  organizeFooterMessages,
10306
+ padEndVisible,
10255
10307
  parseGitHost,
10256
10308
  parsePm2Jlist,
10257
10309
  prepareGitHost,
@@ -10297,9 +10349,11 @@ export {
10297
10349
  showMultiColumnListWithPreviewScreen,
10298
10350
  showScreen,
10299
10351
  showWordGridScreen,
10352
+ sliceVisible,
10300
10353
  sshRun,
10301
10354
  startPm2,
10302
10355
  stopPm2,
10356
+ stripAnsi,
10303
10357
  syncEnv,
10304
10358
  taskHistoryInsertFromQueueRow,
10305
10359
  timeMatcher,
@@ -10316,6 +10370,7 @@ export {
10316
10370
  useMemo2 as useMemo,
10317
10371
  useRef3 as useRef,
10318
10372
  useState4 as useState,
10373
+ visibleWidth,
10319
10374
  waitForTaskResult,
10320
10375
  waitPm2,
10321
10376
  wrapTextLines,