numux 1.10.3 → 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.
Files changed (2) hide show
  1. package/dist/numux.js +73 -51
  2. 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.3",
25
+ version: "1.10.4",
26
26
  description: "Terminal multiplexer with dependency orchestration",
27
27
  type: "module",
28
28
  license: "MIT",
@@ -2119,6 +2119,37 @@ var STATUS_ICON_HEX = {
2119
2119
  skipped: "#888888"
2120
2120
  };
2121
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
+ }
2122
2153
 
2123
2154
  class ColoredSelectRenderable extends SelectRenderable {
2124
2155
  _optionColors = [];
@@ -2126,12 +2157,11 @@ class ColoredSelectRenderable extends SelectRenderable {
2126
2157
  this._optionColors = colors;
2127
2158
  this.requestRender();
2128
2159
  }
2129
- renderSelf(buffer, deltaTime) {
2130
- const wasDirty = this.isDirty;
2131
- super.renderSelf(buffer, deltaTime);
2132
- if (wasDirty && this.frameBuffer && this._optionColors.length > 0) {
2133
- this.colorizeOptions();
2134
- }
2160
+ renderSelf(_buffer, _deltaTime) {
2161
+ if (!(this.visible && this.frameBuffer))
2162
+ return;
2163
+ if (this.isDirty)
2164
+ this.renderOptions();
2135
2165
  }
2136
2166
  onMouseEvent(event) {
2137
2167
  if (event.type === "down") {
@@ -2144,28 +2174,45 @@ class ColoredSelectRenderable extends SelectRenderable {
2144
2174
  }
2145
2175
  }
2146
2176
  }
2147
- colorizeOptions() {
2177
+ renderOptions() {
2178
+ if (!this.frameBuffer || this.options.length === 0)
2179
+ return;
2148
2180
  const fb = this.frameBuffer;
2181
+ const bgColor = this._focused ? this._focusedBackgroundColor : this._backgroundColor;
2182
+ fb.clear(bgColor);
2149
2183
  const scrollOffset = this.scrollOffset;
2150
2184
  const maxVisibleItems = this.maxVisibleItems;
2151
2185
  const linesPerItem = this.linesPerItem;
2186
+ const fontHeight = this.fontHeight;
2152
2187
  const selectedIndex = this.getSelectedIndex();
2153
- const options = this.options;
2154
- const visibleCount = Math.min(maxVisibleItems, options.length - scrollOffset);
2188
+ const showDescription = this._showDescription;
2155
2189
  const baseTextColor = this._focused ? this._focusedTextColor : this._textColor;
2156
2190
  const selectedTextColor = this._selectedTextColor;
2157
- const lineWidth = fb.width;
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);
2158
2196
  for (let i = 0;i < visibleCount; i++) {
2159
2197
  const actualIndex = scrollOffset + i;
2160
- const itemY = i * linesPerItem;
2161
- const optName = options[actualIndex].name;
2198
+ const option = this.options[actualIndex];
2162
2199
  const isSelected = actualIndex === selectedIndex;
2163
- const defaultColor = isSelected ? selectedTextColor : baseTextColor;
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
+ }
2164
2206
  const colors = this._optionColors[actualIndex];
2165
- const textColor = colors?.name ?? defaultColor;
2166
- fb.drawText(optName.padEnd(lineWidth), 1, itemY, textColor);
2207
+ const defaultColor = isSelected ? selectedTextColor : baseTextColor;
2208
+ const nameColor = colors?.name ?? defaultColor;
2209
+ fb.drawText(option.name, 1, itemY, nameColor);
2167
2210
  if (colors?.icon) {
2168
- fb.drawText(optName.charAt(0), 1, itemY, colors.icon);
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);
2169
2216
  }
2170
2217
  }
2171
2218
  }
@@ -2191,7 +2238,7 @@ class TabBar {
2191
2238
  width: "100%",
2192
2239
  height: "100%",
2193
2240
  options: names.map((n) => ({
2194
- name: this.formatTab(n, "pending"),
2241
+ name: formatTab(n, "pending"),
2195
2242
  description: "pending"
2196
2243
  })),
2197
2244
  selectedBackgroundColor: "#334455",
@@ -2214,7 +2261,7 @@ class TabBar {
2214
2261
  }
2215
2262
  updateStatus(name, status, exitCode, restartCount) {
2216
2263
  this.statuses.set(name, status);
2217
- this.baseDescriptions.set(name, this.formatDescription(status, exitCode, restartCount));
2264
+ this.baseDescriptions.set(name, formatDescription(status, exitCode, restartCount));
2218
2265
  if (TERMINAL_STATUSES.has(status) || status === "stopping") {
2219
2266
  this.inputWaiting.delete(name);
2220
2267
  }
@@ -2246,9 +2293,9 @@ class TabBar {
2246
2293
  refreshOptions() {
2247
2294
  const currentIdx = this.renderable.getSelectedIndex();
2248
2295
  const currentName = this.names[currentIdx];
2249
- this.names = this.getDisplayOrder();
2296
+ this.names = getDisplayOrder(this.originalNames, this.statuses);
2250
2297
  this.renderable.options = this.names.map((n) => ({
2251
- name: this.formatTab(n, this.statuses.get(n)),
2298
+ name: formatTab(n, this.statuses.get(n)),
2252
2299
  description: this.getDescription(n)
2253
2300
  }));
2254
2301
  const newIdx = this.names.indexOf(currentName);
@@ -2257,11 +2304,6 @@ class TabBar {
2257
2304
  }
2258
2305
  this.updateOptionColors();
2259
2306
  }
2260
- getDisplayOrder() {
2261
- const active = this.originalNames.filter((n) => !TERMINAL_STATUSES.has(this.statuses.get(n)));
2262
- const terminal = this.originalNames.filter((n) => TERMINAL_STATUSES.has(this.statuses.get(n)));
2263
- return [...active, ...terminal];
2264
- }
2265
2307
  getDescription(name) {
2266
2308
  if (this.inputWaiting.has(name))
2267
2309
  return "awaiting input";
@@ -2270,33 +2312,13 @@ class TabBar {
2270
2312
  return this.baseDescriptions.get(name) ?? "pending";
2271
2313
  }
2272
2314
  updateOptionColors() {
2273
- const colors = this.names.map((name) => {
2274
- const status = this.statuses.get(name);
2275
- const waiting = this.inputWaiting.has(name);
2276
- const errored = this.erroredProcesses.has(name);
2277
- const statusHex = waiting ? "#ffaa00" : errored ? "#ff5555" : STATUS_ICON_HEX[status];
2278
- const processHex = this.processColors.get(name);
2279
- return {
2280
- icon: parseColor(statusHex ?? processHex ?? "#888888"),
2281
- name: processHex ? parseColor(processHex) : null
2282
- };
2283
- });
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
+ }));
2284
2320
  this.renderable.setOptionColors(colors);
2285
2321
  }
2286
- formatDescription(status, exitCode, restartCount) {
2287
- let desc = status;
2288
- if ((status === "failed" || status === "stopped") && exitCode != null && exitCode !== 0) {
2289
- desc = `exit ${exitCode}`;
2290
- }
2291
- if (restartCount && restartCount > 0) {
2292
- desc += ` \xD7${restartCount}`;
2293
- }
2294
- return desc;
2295
- }
2296
- formatTab(name, status) {
2297
- const icon = STATUS_ICONS[status];
2298
- return `${icon} ${name}`;
2299
- }
2300
2322
  getSelectedIndex() {
2301
2323
  return this.renderable.getSelectedIndex();
2302
2324
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "numux",
3
- "version": "1.10.3",
3
+ "version": "1.10.4",
4
4
  "description": "Terminal multiplexer with dependency orchestration",
5
5
  "type": "module",
6
6
  "license": "MIT",