@nmakarov/cli-toolkit 0.80.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/cli-runner.cjs +132 -44
- package/dist/cli-runner.cjs.map +1 -1
- package/dist/cli-runner.js +134 -46
- package/dist/cli-runner.js.map +1 -1
- package/dist/index.cjs +140 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +134 -46
- package/dist/index.js.map +1 -1
- package/dist/init.cjs +132 -44
- package/dist/init.cjs.map +1 -1
- package/dist/init.js +134 -46
- package/dist/init.js.map +1 -1
- package/dist/screen.cjs +128 -44
- package/dist/screen.cjs.map +1 -1
- package/dist/screen.js +120 -44
- package/dist/screen.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1018,7 +1018,68 @@ var init_ui_elements = __esm({
|
|
|
1018
1018
|
}
|
|
1019
1019
|
});
|
|
1020
1020
|
|
|
1021
|
-
// src/screen/
|
|
1021
|
+
// src/screen/follow-scroll.js
|
|
1022
|
+
function clampScroll(scrollTop, maxScroll) {
|
|
1023
|
+
const max = Math.max(0, Number(maxScroll) || 0);
|
|
1024
|
+
const top = Number(scrollTop) || 0;
|
|
1025
|
+
return Math.min(Math.max(0, top), max);
|
|
1026
|
+
}
|
|
1027
|
+
function isScrolledToBottom(scrollTop, maxScroll) {
|
|
1028
|
+
return clampScroll(scrollTop, maxScroll) >= Math.max(0, Number(maxScroll) || 0);
|
|
1029
|
+
}
|
|
1030
|
+
function nextScrollAfterUserMove(scrollTop, maxScroll, delta) {
|
|
1031
|
+
const next = clampScroll((Number(scrollTop) || 0) + (Number(delta) || 0), maxScroll);
|
|
1032
|
+
return { scrollTop: next, following: isScrolledToBottom(next, maxScroll) };
|
|
1033
|
+
}
|
|
1034
|
+
function nextScrollAfterContentChange({ following, scrollTop, maxScroll }) {
|
|
1035
|
+
const max = Math.max(0, Number(maxScroll) || 0);
|
|
1036
|
+
if (following) return { scrollTop: max, following: true };
|
|
1037
|
+
const next = clampScroll(scrollTop, max);
|
|
1038
|
+
return { scrollTop: next, following: isScrolledToBottom(next, max) };
|
|
1039
|
+
}
|
|
1040
|
+
var init_follow_scroll = __esm({
|
|
1041
|
+
"src/screen/follow-scroll.js"() {
|
|
1042
|
+
}
|
|
1043
|
+
});
|
|
1044
|
+
|
|
1045
|
+
// src/screen/visible-text.js
|
|
1046
|
+
function stripAnsi(text) {
|
|
1047
|
+
return String(text ?? "").replace(ANSI_RE, "");
|
|
1048
|
+
}
|
|
1049
|
+
function visibleWidth(text) {
|
|
1050
|
+
return [...stripAnsi(text)].length;
|
|
1051
|
+
}
|
|
1052
|
+
function sliceVisible(text, cols) {
|
|
1053
|
+
const w = Math.max(0, Math.floor(Number(cols) || 0));
|
|
1054
|
+
const s = String(text ?? "");
|
|
1055
|
+
if (w === 0) return "";
|
|
1056
|
+
let vis = 0;
|
|
1057
|
+
let out = "";
|
|
1058
|
+
let i = 0;
|
|
1059
|
+
while (i < s.length && vis < w) {
|
|
1060
|
+
ANSI_RE.lastIndex = i;
|
|
1061
|
+
const m = ANSI_RE.exec(s);
|
|
1062
|
+
if (m && m.index === i) {
|
|
1063
|
+
out += m[0];
|
|
1064
|
+
i += m[0].length;
|
|
1065
|
+
continue;
|
|
1066
|
+
}
|
|
1067
|
+
const cp3 = s.codePointAt(i);
|
|
1068
|
+
const ch = String.fromCodePoint(cp3);
|
|
1069
|
+
out += ch;
|
|
1070
|
+
i += ch.length;
|
|
1071
|
+
vis += 1;
|
|
1072
|
+
}
|
|
1073
|
+
return out;
|
|
1074
|
+
}
|
|
1075
|
+
function padEndVisible(text, cols) {
|
|
1076
|
+
const w = Math.max(0, Math.floor(Number(cols) || 0));
|
|
1077
|
+
const s = String(text ?? "");
|
|
1078
|
+
const vis = visibleWidth(s);
|
|
1079
|
+
if (vis === w) return s;
|
|
1080
|
+
if (vis > w) return sliceVisible(s, w);
|
|
1081
|
+
return s + " ".repeat(w - vis);
|
|
1082
|
+
}
|
|
1022
1083
|
function wrapTextLines(text, cols) {
|
|
1023
1084
|
const w = Math.max(1, Math.floor(Number(cols) || 1));
|
|
1024
1085
|
const out = [];
|
|
@@ -1027,20 +1088,28 @@ function wrapTextLines(text, cols) {
|
|
|
1027
1088
|
out.push("");
|
|
1028
1089
|
continue;
|
|
1029
1090
|
}
|
|
1091
|
+
if (visibleWidth(raw) <= w) {
|
|
1092
|
+
out.push(raw);
|
|
1093
|
+
continue;
|
|
1094
|
+
}
|
|
1030
1095
|
let rest = raw;
|
|
1031
|
-
while (rest
|
|
1032
|
-
|
|
1033
|
-
|
|
1096
|
+
while (visibleWidth(rest) > w) {
|
|
1097
|
+
const head = sliceVisible(rest, w);
|
|
1098
|
+
out.push(head);
|
|
1099
|
+
rest = rest.slice(head.length);
|
|
1034
1100
|
}
|
|
1035
1101
|
if (rest.length > 0) out.push(rest);
|
|
1036
1102
|
}
|
|
1037
1103
|
return out;
|
|
1038
1104
|
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
}
|
|
1105
|
+
var ANSI_RE;
|
|
1106
|
+
var init_visible_text = __esm({
|
|
1107
|
+
"src/screen/visible-text.js"() {
|
|
1108
|
+
ANSI_RE = /\u001b(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g;
|
|
1109
|
+
}
|
|
1110
|
+
});
|
|
1111
|
+
|
|
1112
|
+
// src/screen/scrollable-text.js
|
|
1044
1113
|
function ScrollableText({
|
|
1045
1114
|
ctx,
|
|
1046
1115
|
text = "",
|
|
@@ -1050,9 +1119,11 @@ function ScrollableText({
|
|
|
1050
1119
|
showScrollbar = true,
|
|
1051
1120
|
showStatus = true,
|
|
1052
1121
|
bindKeys = true,
|
|
1053
|
-
header = null
|
|
1122
|
+
header = null,
|
|
1123
|
+
followBottom = false
|
|
1054
1124
|
}) {
|
|
1055
1125
|
const [scrollTop, setScrollTop] = (0, import_react5.useState)(0);
|
|
1126
|
+
const [following, setFollowing] = (0, import_react5.useState)(() => !!followBottom);
|
|
1056
1127
|
const [, bump] = (0, import_react5.useState)(0);
|
|
1057
1128
|
const termRows = process.stdout.rows || 24;
|
|
1058
1129
|
const viewportRows = Math.max(
|
|
@@ -1071,48 +1142,52 @@ function ScrollableText({
|
|
|
1071
1142
|
const clamped = Math.min(Math.max(0, scrollTop), maxScroll);
|
|
1072
1143
|
const visible = allLines.slice(clamped, clamped + viewportRows);
|
|
1073
1144
|
const bar = needsBar ? scrollbarGlyphs(viewportRows, allLines.length, clamped) : null;
|
|
1074
|
-
(0, import_react5.useEffect)(() => {
|
|
1075
|
-
setScrollTop((s) => Math.min(s, maxScroll));
|
|
1076
|
-
}, [maxScroll]);
|
|
1077
1145
|
const maxScrollRef = (0, import_react5.useRef)(maxScroll);
|
|
1078
1146
|
const pageSizeRef = (0, import_react5.useRef)(viewportRows);
|
|
1147
|
+
const scrollTopRef = (0, import_react5.useRef)(scrollTop);
|
|
1148
|
+
const followingRef = (0, import_react5.useRef)(following);
|
|
1079
1149
|
maxScrollRef.current = maxScroll;
|
|
1080
1150
|
pageSizeRef.current = viewportRows;
|
|
1151
|
+
scrollTopRef.current = scrollTop;
|
|
1152
|
+
followingRef.current = following;
|
|
1153
|
+
(0, import_react5.useEffect)(() => {
|
|
1154
|
+
const next = nextScrollAfterContentChange({
|
|
1155
|
+
following: followBottom && followingRef.current,
|
|
1156
|
+
scrollTop: scrollTopRef.current,
|
|
1157
|
+
maxScroll
|
|
1158
|
+
});
|
|
1159
|
+
if (next.scrollTop !== scrollTopRef.current) setScrollTop(next.scrollTop);
|
|
1160
|
+
if (followBottom && next.following !== followingRef.current) setFollowing(next.following);
|
|
1161
|
+
}, [maxScroll, followBottom]);
|
|
1162
|
+
const applyUserScroll = (delta) => {
|
|
1163
|
+
const next = nextScrollAfterUserMove(scrollTopRef.current, maxScrollRef.current, delta);
|
|
1164
|
+
setScrollTop(next.scrollTop);
|
|
1165
|
+
if (followBottom) setFollowing(next.following);
|
|
1166
|
+
bump((n) => n + 1);
|
|
1167
|
+
ctx?.update?.();
|
|
1168
|
+
};
|
|
1081
1169
|
(0, import_react5.useEffect)(() => {
|
|
1082
1170
|
if (!ctx || !bindKeys) return void 0;
|
|
1083
1171
|
ctx.setKeyBinding(SCROLL_KEYS);
|
|
1084
|
-
ctx.setAction("scrollUp", () =>
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
});
|
|
1089
|
-
ctx.setAction("scrollDown", () => {
|
|
1090
|
-
setScrollTop((s) => Math.min(maxScrollRef.current, s + 1));
|
|
1091
|
-
bump((n) => n + 1);
|
|
1092
|
-
ctx.update?.();
|
|
1093
|
-
});
|
|
1094
|
-
ctx.setAction("pageUp", () => {
|
|
1095
|
-
setScrollTop((s) => Math.max(0, s - pageSizeRef.current));
|
|
1096
|
-
bump((n) => n + 1);
|
|
1097
|
-
ctx.update?.();
|
|
1098
|
-
});
|
|
1099
|
-
ctx.setAction("pageDown", () => {
|
|
1100
|
-
setScrollTop((s) => Math.min(maxScrollRef.current, s + pageSizeRef.current));
|
|
1101
|
-
bump((n) => n + 1);
|
|
1102
|
-
ctx.update?.();
|
|
1103
|
-
});
|
|
1172
|
+
ctx.setAction("scrollUp", () => applyUserScroll(-1));
|
|
1173
|
+
ctx.setAction("scrollDown", () => applyUserScroll(1));
|
|
1174
|
+
ctx.setAction("pageUp", () => applyUserScroll(-pageSizeRef.current));
|
|
1175
|
+
ctx.setAction("pageDown", () => applyUserScroll(pageSizeRef.current));
|
|
1104
1176
|
return void 0;
|
|
1105
|
-
}, [ctx, bindKeys]);
|
|
1106
|
-
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" : "");
|
|
1177
|
+
}, [ctx, bindKeys, followBottom]);
|
|
1178
|
+
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" : "");
|
|
1107
1179
|
const rowNodes = visible.map((line, i) => {
|
|
1108
|
-
const body = padEndVisible(line, textWidth);
|
|
1109
1180
|
const glyph = bar ? bar[i] ?? BAR_TRACK : showScrollbar ? " " : "";
|
|
1110
1181
|
const isThumb = glyph === BAR_THUMB;
|
|
1111
1182
|
return h5(
|
|
1112
|
-
import_ink5.
|
|
1113
|
-
{ key: `L${clamped + i}
|
|
1114
|
-
|
|
1115
|
-
|
|
1183
|
+
import_ink5.Box,
|
|
1184
|
+
{ key: `L${clamped + i}`, flexDirection: "row", width: contentCols, flexShrink: 0 },
|
|
1185
|
+
h5(
|
|
1186
|
+
import_ink5.Box,
|
|
1187
|
+
{ width: textWidth, flexShrink: 0 },
|
|
1188
|
+
h5(import_ink5.Text, { wrap: "truncate" }, padEndVisible(line, textWidth))
|
|
1189
|
+
),
|
|
1190
|
+
showScrollbar ? h5(import_ink5.Box, { width: 1, flexShrink: 0 }, h5(import_ink5.Text, { color: isThumb ? "cyan" : "gray" }, glyph)) : null
|
|
1116
1191
|
);
|
|
1117
1192
|
});
|
|
1118
1193
|
if (bar && visible.length < viewportRows) {
|
|
@@ -1120,10 +1195,10 @@ function ScrollableText({
|
|
|
1120
1195
|
const glyph = bar[i] ?? BAR_TRACK;
|
|
1121
1196
|
rowNodes.push(
|
|
1122
1197
|
h5(
|
|
1123
|
-
import_ink5.
|
|
1124
|
-
{ key: `pad${i}
|
|
1125
|
-
padEndVisible("", textWidth),
|
|
1126
|
-
h5(import_ink5.Text, { color: glyph === BAR_THUMB ? "cyan" : "gray" }, glyph)
|
|
1198
|
+
import_ink5.Box,
|
|
1199
|
+
{ key: `pad${i}`, flexDirection: "row", width: contentCols, flexShrink: 0 },
|
|
1200
|
+
h5(import_ink5.Box, { width: textWidth, flexShrink: 0 }, h5(import_ink5.Text, {}, padEndVisible("", textWidth))),
|
|
1201
|
+
h5(import_ink5.Box, { width: 1, flexShrink: 0 }, h5(import_ink5.Text, { color: glyph === BAR_THUMB ? "cyan" : "gray" }, glyph))
|
|
1127
1202
|
)
|
|
1128
1203
|
);
|
|
1129
1204
|
}
|
|
@@ -1143,7 +1218,10 @@ var init_scrollable_text = __esm({
|
|
|
1143
1218
|
import_ink5 = require("ink");
|
|
1144
1219
|
init_components();
|
|
1145
1220
|
init_scrollbar();
|
|
1221
|
+
init_follow_scroll();
|
|
1222
|
+
init_visible_text();
|
|
1146
1223
|
init_scrollbar();
|
|
1224
|
+
init_visible_text();
|
|
1147
1225
|
h5 = import_react5.createElement;
|
|
1148
1226
|
SCROLL_KEYS = [
|
|
1149
1227
|
{ key: "upArrow", caption: "scroll", action: "scrollUp", order: 0 },
|
|
@@ -1298,6 +1376,8 @@ var init_screen = __esm({
|
|
|
1298
1376
|
init_components();
|
|
1299
1377
|
init_ui_elements();
|
|
1300
1378
|
init_scrollable_text();
|
|
1379
|
+
init_visible_text();
|
|
1380
|
+
init_follow_scroll();
|
|
1301
1381
|
init_scrollbar();
|
|
1302
1382
|
init_key_bindings();
|
|
1303
1383
|
init_utils();
|
|
@@ -1377,6 +1457,7 @@ __export(src_exports, {
|
|
|
1377
1457
|
buildDetailBreadcrumb: () => buildDetailBreadcrumb,
|
|
1378
1458
|
buildFooter: () => buildFooter,
|
|
1379
1459
|
bumpPatchVersion: () => bumpPatchVersion,
|
|
1460
|
+
clampScroll: () => clampScroll,
|
|
1380
1461
|
cloneRepo: () => cloneRepo,
|
|
1381
1462
|
coerceRuntimeValue: () => coerceRuntimeValue,
|
|
1382
1463
|
controlLaneTaskNames: () => controlLaneTaskNames,
|
|
@@ -1414,6 +1495,7 @@ __export(src_exports, {
|
|
|
1414
1495
|
ipcFileLogsTableNameForSourceResource: () => ipcFileLogsTableNameForSourceResource,
|
|
1415
1496
|
isFreshOnline: () => isFreshOnline,
|
|
1416
1497
|
isPidAlive: () => isPidAlive,
|
|
1498
|
+
isScrolledToBottom: () => isScrolledToBottom,
|
|
1417
1499
|
joiEdateType: () => joiEdateType,
|
|
1418
1500
|
joiStringArrayType: () => joiStringArrayType,
|
|
1419
1501
|
listAliveRunnerHeartbeats: () => listServicesRegistry,
|
|
@@ -1427,11 +1509,14 @@ __export(src_exports, {
|
|
|
1427
1509
|
memo: () => import_react6.memo,
|
|
1428
1510
|
mergeAllowedTasksWithServiceTasks: () => mergeAllowedTasksWithServiceTasks,
|
|
1429
1511
|
mergeRuntimeParamSpecs: () => mergeRuntimeParamSpecs,
|
|
1512
|
+
nextScrollAfterContentChange: () => nextScrollAfterContentChange,
|
|
1513
|
+
nextScrollAfterUserMove: () => nextScrollAfterUserMove,
|
|
1430
1514
|
nextTimeMatch: () => nextTimeMatch,
|
|
1431
1515
|
normalizeAllowedTasks: () => normalizeAllowedTasks,
|
|
1432
1516
|
npmEnv: () => npmEnv,
|
|
1433
1517
|
npmInstallEnv: () => npmInstallEnv,
|
|
1434
1518
|
organizeFooterMessages: () => organizeFooterMessages,
|
|
1519
|
+
padEndVisible: () => padEndVisible,
|
|
1435
1520
|
parseGitHost: () => parseGitHost,
|
|
1436
1521
|
parsePm2Jlist: () => parsePm2Jlist,
|
|
1437
1522
|
prepareGitHost: () => prepareGitHost,
|
|
@@ -1477,9 +1562,11 @@ __export(src_exports, {
|
|
|
1477
1562
|
showMultiColumnListWithPreviewScreen: () => showMultiColumnListWithPreviewScreen,
|
|
1478
1563
|
showScreen: () => showScreen,
|
|
1479
1564
|
showWordGridScreen: () => showWordGridScreen,
|
|
1565
|
+
sliceVisible: () => sliceVisible,
|
|
1480
1566
|
sshRun: () => sshRun,
|
|
1481
1567
|
startPm2: () => startPm2,
|
|
1482
1568
|
stopPm2: () => stopPm2,
|
|
1569
|
+
stripAnsi: () => stripAnsi,
|
|
1483
1570
|
syncEnv: () => syncEnv,
|
|
1484
1571
|
taskHistoryInsertFromQueueRow: () => taskHistoryInsertFromQueueRow,
|
|
1485
1572
|
timeMatcher: () => timeMatcher,
|
|
@@ -1496,6 +1583,7 @@ __export(src_exports, {
|
|
|
1496
1583
|
useMemo: () => import_react6.useMemo,
|
|
1497
1584
|
useRef: () => import_react6.useRef,
|
|
1498
1585
|
useState: () => import_react6.useState,
|
|
1586
|
+
visibleWidth: () => visibleWidth,
|
|
1499
1587
|
waitForTaskResult: () => waitForTaskResult,
|
|
1500
1588
|
waitPm2: () => waitPm2,
|
|
1501
1589
|
wrapTextLines: () => wrapTextLines,
|
|
@@ -10351,6 +10439,7 @@ var TasksManager = class _TasksManager {
|
|
|
10351
10439
|
buildDetailBreadcrumb,
|
|
10352
10440
|
buildFooter,
|
|
10353
10441
|
bumpPatchVersion,
|
|
10442
|
+
clampScroll,
|
|
10354
10443
|
cloneRepo,
|
|
10355
10444
|
coerceRuntimeValue,
|
|
10356
10445
|
controlLaneTaskNames,
|
|
@@ -10388,6 +10477,7 @@ var TasksManager = class _TasksManager {
|
|
|
10388
10477
|
ipcFileLogsTableNameForSourceResource,
|
|
10389
10478
|
isFreshOnline,
|
|
10390
10479
|
isPidAlive,
|
|
10480
|
+
isScrolledToBottom,
|
|
10391
10481
|
joiEdateType,
|
|
10392
10482
|
joiStringArrayType,
|
|
10393
10483
|
listAliveRunnerHeartbeats,
|
|
@@ -10401,11 +10491,14 @@ var TasksManager = class _TasksManager {
|
|
|
10401
10491
|
memo,
|
|
10402
10492
|
mergeAllowedTasksWithServiceTasks,
|
|
10403
10493
|
mergeRuntimeParamSpecs,
|
|
10494
|
+
nextScrollAfterContentChange,
|
|
10495
|
+
nextScrollAfterUserMove,
|
|
10404
10496
|
nextTimeMatch,
|
|
10405
10497
|
normalizeAllowedTasks,
|
|
10406
10498
|
npmEnv,
|
|
10407
10499
|
npmInstallEnv,
|
|
10408
10500
|
organizeFooterMessages,
|
|
10501
|
+
padEndVisible,
|
|
10409
10502
|
parseGitHost,
|
|
10410
10503
|
parsePm2Jlist,
|
|
10411
10504
|
prepareGitHost,
|
|
@@ -10451,9 +10544,11 @@ var TasksManager = class _TasksManager {
|
|
|
10451
10544
|
showMultiColumnListWithPreviewScreen,
|
|
10452
10545
|
showScreen,
|
|
10453
10546
|
showWordGridScreen,
|
|
10547
|
+
sliceVisible,
|
|
10454
10548
|
sshRun,
|
|
10455
10549
|
startPm2,
|
|
10456
10550
|
stopPm2,
|
|
10551
|
+
stripAnsi,
|
|
10457
10552
|
syncEnv,
|
|
10458
10553
|
taskHistoryInsertFromQueueRow,
|
|
10459
10554
|
timeMatcher,
|
|
@@ -10470,6 +10565,7 @@ var TasksManager = class _TasksManager {
|
|
|
10470
10565
|
useMemo,
|
|
10471
10566
|
useRef,
|
|
10472
10567
|
useState,
|
|
10568
|
+
visibleWidth,
|
|
10473
10569
|
waitForTaskResult,
|
|
10474
10570
|
waitPm2,
|
|
10475
10571
|
wrapTextLines,
|