numux 1.10.2 → 1.10.4
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/numux.js +94 -53
- package/package.json +1 -1
package/dist/numux.js
CHANGED
|
@@ -22,7 +22,7 @@ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports,
|
|
|
22
22
|
var require_package = __commonJS((exports, module) => {
|
|
23
23
|
module.exports = {
|
|
24
24
|
name: "numux",
|
|
25
|
-
version: "1.10.
|
|
25
|
+
version: "1.10.4",
|
|
26
26
|
description: "Terminal multiplexer with dependency orchestration",
|
|
27
27
|
type: "module",
|
|
28
28
|
license: "MIT",
|
|
@@ -608,6 +608,24 @@ function detectPackageManager(pkgJson, cwd) {
|
|
|
608
608
|
function isGlobPattern(name) {
|
|
609
609
|
return /[*?[]/.test(name);
|
|
610
610
|
}
|
|
611
|
+
function deriveShortName(pattern, scriptName) {
|
|
612
|
+
let prefixEnd = 0;
|
|
613
|
+
while (prefixEnd < pattern.length && !"*?[".includes(pattern[prefixEnd])) {
|
|
614
|
+
prefixEnd++;
|
|
615
|
+
}
|
|
616
|
+
let suffixStart = pattern.length;
|
|
617
|
+
while (suffixStart > 0 && !"*?[".includes(pattern[suffixStart - 1])) {
|
|
618
|
+
suffixStart--;
|
|
619
|
+
}
|
|
620
|
+
const prefix = pattern.slice(0, prefixEnd);
|
|
621
|
+
const suffix = pattern.slice(suffixStart);
|
|
622
|
+
let short = scriptName;
|
|
623
|
+
if (prefix && short.startsWith(prefix))
|
|
624
|
+
short = short.slice(prefix.length);
|
|
625
|
+
if (suffix && short.endsWith(suffix))
|
|
626
|
+
short = short.slice(0, short.length - suffix.length);
|
|
627
|
+
return short || scriptName;
|
|
628
|
+
}
|
|
611
629
|
function splitPatternArgs(raw) {
|
|
612
630
|
const i = raw.indexOf(" ");
|
|
613
631
|
if (i === -1)
|
|
@@ -652,12 +670,13 @@ function expandScriptPatterns(config, cwd) {
|
|
|
652
670
|
const singleColor = typeof template.color === "string" ? template.color : undefined;
|
|
653
671
|
for (let i = 0;i < matches.length; i++) {
|
|
654
672
|
const scriptName = matches[i];
|
|
655
|
-
|
|
673
|
+
const displayName = deriveShortName(globPattern, scriptName);
|
|
674
|
+
if (expanded[displayName]) {
|
|
656
675
|
throw new Error(`"${name}": expanded script "${scriptName}" collides with an existing process name`);
|
|
657
676
|
}
|
|
658
677
|
const color = colors ? colors[i % colors.length] : singleColor;
|
|
659
678
|
const { color: _color, ...rest } = template;
|
|
660
|
-
expanded[
|
|
679
|
+
expanded[displayName] = {
|
|
661
680
|
...rest,
|
|
662
681
|
command: `${pm} run ${scriptName}${extraArgs}`,
|
|
663
682
|
...color ? { color } : {}
|
|
@@ -2100,6 +2119,37 @@ var STATUS_ICON_HEX = {
|
|
|
2100
2119
|
skipped: "#888888"
|
|
2101
2120
|
};
|
|
2102
2121
|
var TERMINAL_STATUSES = new Set(["finished", "stopped", "failed", "skipped"]);
|
|
2122
|
+
function formatTab(name, status) {
|
|
2123
|
+
return `${STATUS_ICONS[status]} ${name}`;
|
|
2124
|
+
}
|
|
2125
|
+
function formatDescription(status, exitCode, restartCount) {
|
|
2126
|
+
let desc = status;
|
|
2127
|
+
if ((status === "failed" || status === "stopped") && exitCode != null && exitCode !== 0) {
|
|
2128
|
+
desc = `exit ${exitCode}`;
|
|
2129
|
+
}
|
|
2130
|
+
if (restartCount && restartCount > 0) {
|
|
2131
|
+
desc += ` \xD7${restartCount}`;
|
|
2132
|
+
}
|
|
2133
|
+
return desc;
|
|
2134
|
+
}
|
|
2135
|
+
function getDisplayOrder(originalNames, statuses) {
|
|
2136
|
+
const active = originalNames.filter((n) => !TERMINAL_STATUSES.has(statuses.get(n)));
|
|
2137
|
+
const terminal = originalNames.filter((n) => TERMINAL_STATUSES.has(statuses.get(n)));
|
|
2138
|
+
return [...active, ...terminal];
|
|
2139
|
+
}
|
|
2140
|
+
function resolveOptionColors(names, statuses, processColors, inputWaiting, erroredProcesses) {
|
|
2141
|
+
return names.map((name) => {
|
|
2142
|
+
const status = statuses.get(name);
|
|
2143
|
+
const waiting = inputWaiting.has(name);
|
|
2144
|
+
const errored = erroredProcesses.has(name);
|
|
2145
|
+
const statusHex = waiting ? "#ffaa00" : errored ? "#ff5555" : STATUS_ICON_HEX[status];
|
|
2146
|
+
const processHex = processColors.get(name);
|
|
2147
|
+
return {
|
|
2148
|
+
iconHex: statusHex ?? processHex ?? "#888888",
|
|
2149
|
+
nameHex: processHex ?? null
|
|
2150
|
+
};
|
|
2151
|
+
});
|
|
2152
|
+
}
|
|
2103
2153
|
|
|
2104
2154
|
class ColoredSelectRenderable extends SelectRenderable {
|
|
2105
2155
|
_optionColors = [];
|
|
@@ -2107,12 +2157,11 @@ class ColoredSelectRenderable extends SelectRenderable {
|
|
|
2107
2157
|
this._optionColors = colors;
|
|
2108
2158
|
this.requestRender();
|
|
2109
2159
|
}
|
|
2110
|
-
renderSelf(
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
if (
|
|
2114
|
-
this.
|
|
2115
|
-
}
|
|
2160
|
+
renderSelf(_buffer, _deltaTime) {
|
|
2161
|
+
if (!(this.visible && this.frameBuffer))
|
|
2162
|
+
return;
|
|
2163
|
+
if (this.isDirty)
|
|
2164
|
+
this.renderOptions();
|
|
2116
2165
|
}
|
|
2117
2166
|
onMouseEvent(event) {
|
|
2118
2167
|
if (event.type === "down") {
|
|
@@ -2125,28 +2174,45 @@ class ColoredSelectRenderable extends SelectRenderable {
|
|
|
2125
2174
|
}
|
|
2126
2175
|
}
|
|
2127
2176
|
}
|
|
2128
|
-
|
|
2177
|
+
renderOptions() {
|
|
2178
|
+
if (!this.frameBuffer || this.options.length === 0)
|
|
2179
|
+
return;
|
|
2129
2180
|
const fb = this.frameBuffer;
|
|
2181
|
+
const bgColor = this._focused ? this._focusedBackgroundColor : this._backgroundColor;
|
|
2182
|
+
fb.clear(bgColor);
|
|
2130
2183
|
const scrollOffset = this.scrollOffset;
|
|
2131
2184
|
const maxVisibleItems = this.maxVisibleItems;
|
|
2132
2185
|
const linesPerItem = this.linesPerItem;
|
|
2186
|
+
const fontHeight = this.fontHeight;
|
|
2133
2187
|
const selectedIndex = this.getSelectedIndex();
|
|
2134
|
-
const
|
|
2135
|
-
const visibleCount = Math.min(maxVisibleItems, options.length - scrollOffset);
|
|
2188
|
+
const showDescription = this._showDescription;
|
|
2136
2189
|
const baseTextColor = this._focused ? this._focusedTextColor : this._textColor;
|
|
2137
2190
|
const selectedTextColor = this._selectedTextColor;
|
|
2138
|
-
const
|
|
2191
|
+
const descColor = this._descriptionColor;
|
|
2192
|
+
const selectedDescColor = this._selectedDescriptionColor;
|
|
2193
|
+
const selectedBgColor = this._selectedBackgroundColor;
|
|
2194
|
+
const itemSpacing = this._itemSpacing;
|
|
2195
|
+
const visibleCount = Math.min(maxVisibleItems, this.options.length - scrollOffset);
|
|
2139
2196
|
for (let i = 0;i < visibleCount; i++) {
|
|
2140
2197
|
const actualIndex = scrollOffset + i;
|
|
2141
|
-
const
|
|
2142
|
-
const optName = options[actualIndex].name;
|
|
2198
|
+
const option = this.options[actualIndex];
|
|
2143
2199
|
const isSelected = actualIndex === selectedIndex;
|
|
2144
|
-
const
|
|
2200
|
+
const itemY = i * linesPerItem;
|
|
2201
|
+
if (itemY + linesPerItem - 1 >= this.height)
|
|
2202
|
+
break;
|
|
2203
|
+
if (isSelected) {
|
|
2204
|
+
fb.fillRect(0, itemY, this.width, linesPerItem - itemSpacing, selectedBgColor);
|
|
2205
|
+
}
|
|
2145
2206
|
const colors = this._optionColors[actualIndex];
|
|
2146
|
-
const
|
|
2147
|
-
|
|
2207
|
+
const defaultColor = isSelected ? selectedTextColor : baseTextColor;
|
|
2208
|
+
const nameColor = colors?.name ?? defaultColor;
|
|
2209
|
+
fb.drawText(option.name, 1, itemY, nameColor);
|
|
2148
2210
|
if (colors?.icon) {
|
|
2149
|
-
fb.drawText(
|
|
2211
|
+
fb.drawText(option.name.charAt(0), 1, itemY, colors.icon);
|
|
2212
|
+
}
|
|
2213
|
+
if (showDescription && itemY + fontHeight < this.height) {
|
|
2214
|
+
const dc = isSelected ? selectedDescColor : descColor;
|
|
2215
|
+
fb.drawText(option.description, 3, itemY + fontHeight, dc);
|
|
2150
2216
|
}
|
|
2151
2217
|
}
|
|
2152
2218
|
}
|
|
@@ -2172,7 +2238,7 @@ class TabBar {
|
|
|
2172
2238
|
width: "100%",
|
|
2173
2239
|
height: "100%",
|
|
2174
2240
|
options: names.map((n) => ({
|
|
2175
|
-
name:
|
|
2241
|
+
name: formatTab(n, "pending"),
|
|
2176
2242
|
description: "pending"
|
|
2177
2243
|
})),
|
|
2178
2244
|
selectedBackgroundColor: "#334455",
|
|
@@ -2195,7 +2261,7 @@ class TabBar {
|
|
|
2195
2261
|
}
|
|
2196
2262
|
updateStatus(name, status, exitCode, restartCount) {
|
|
2197
2263
|
this.statuses.set(name, status);
|
|
2198
|
-
this.baseDescriptions.set(name,
|
|
2264
|
+
this.baseDescriptions.set(name, formatDescription(status, exitCode, restartCount));
|
|
2199
2265
|
if (TERMINAL_STATUSES.has(status) || status === "stopping") {
|
|
2200
2266
|
this.inputWaiting.delete(name);
|
|
2201
2267
|
}
|
|
@@ -2227,9 +2293,9 @@ class TabBar {
|
|
|
2227
2293
|
refreshOptions() {
|
|
2228
2294
|
const currentIdx = this.renderable.getSelectedIndex();
|
|
2229
2295
|
const currentName = this.names[currentIdx];
|
|
2230
|
-
this.names = this.
|
|
2296
|
+
this.names = getDisplayOrder(this.originalNames, this.statuses);
|
|
2231
2297
|
this.renderable.options = this.names.map((n) => ({
|
|
2232
|
-
name:
|
|
2298
|
+
name: formatTab(n, this.statuses.get(n)),
|
|
2233
2299
|
description: this.getDescription(n)
|
|
2234
2300
|
}));
|
|
2235
2301
|
const newIdx = this.names.indexOf(currentName);
|
|
@@ -2238,11 +2304,6 @@ class TabBar {
|
|
|
2238
2304
|
}
|
|
2239
2305
|
this.updateOptionColors();
|
|
2240
2306
|
}
|
|
2241
|
-
getDisplayOrder() {
|
|
2242
|
-
const active = this.originalNames.filter((n) => !TERMINAL_STATUSES.has(this.statuses.get(n)));
|
|
2243
|
-
const terminal = this.originalNames.filter((n) => TERMINAL_STATUSES.has(this.statuses.get(n)));
|
|
2244
|
-
return [...active, ...terminal];
|
|
2245
|
-
}
|
|
2246
2307
|
getDescription(name) {
|
|
2247
2308
|
if (this.inputWaiting.has(name))
|
|
2248
2309
|
return "awaiting input";
|
|
@@ -2251,33 +2312,13 @@ class TabBar {
|
|
|
2251
2312
|
return this.baseDescriptions.get(name) ?? "pending";
|
|
2252
2313
|
}
|
|
2253
2314
|
updateOptionColors() {
|
|
2254
|
-
const
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
const processHex = this.processColors.get(name);
|
|
2260
|
-
return {
|
|
2261
|
-
icon: parseColor(statusHex ?? processHex ?? "#888888"),
|
|
2262
|
-
name: processHex ? parseColor(processHex) : null
|
|
2263
|
-
};
|
|
2264
|
-
});
|
|
2315
|
+
const resolved = resolveOptionColors(this.names, this.statuses, this.processColors, this.inputWaiting, this.erroredProcesses);
|
|
2316
|
+
const colors = resolved.map((c) => ({
|
|
2317
|
+
icon: parseColor(c.iconHex),
|
|
2318
|
+
name: c.nameHex ? parseColor(c.nameHex) : null
|
|
2319
|
+
}));
|
|
2265
2320
|
this.renderable.setOptionColors(colors);
|
|
2266
2321
|
}
|
|
2267
|
-
formatDescription(status, exitCode, restartCount) {
|
|
2268
|
-
let desc = status;
|
|
2269
|
-
if ((status === "failed" || status === "stopped") && exitCode != null && exitCode !== 0) {
|
|
2270
|
-
desc = `exit ${exitCode}`;
|
|
2271
|
-
}
|
|
2272
|
-
if (restartCount && restartCount > 0) {
|
|
2273
|
-
desc += ` \xD7${restartCount}`;
|
|
2274
|
-
}
|
|
2275
|
-
return desc;
|
|
2276
|
-
}
|
|
2277
|
-
formatTab(name, status) {
|
|
2278
|
-
const icon = STATUS_ICONS[status];
|
|
2279
|
-
return `${icon} ${name}`;
|
|
2280
|
-
}
|
|
2281
2322
|
getSelectedIndex() {
|
|
2282
2323
|
return this.renderable.getSelectedIndex();
|
|
2283
2324
|
}
|