startall 0.0.19 → 0.0.20

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/index.js +159 -66
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bun
2
2
 
3
- import { createCliRenderer, TextRenderable, BoxRenderable, ScrollBoxRenderable, t, fg } from '@opentui/core';
3
+ import { createCliRenderer, TextRenderable, BoxRenderable, ScrollBoxRenderable, ASCIIFontRenderable, t, fg, bold, dim, RGBA } from '@opentui/core';
4
4
  import { spawn, execSync, spawnSync } from 'child_process';
5
5
  import { readFileSync, writeFileSync, writeSync, existsSync } from 'fs';
6
6
  import { join } from 'path';
@@ -1956,7 +1956,7 @@ class ProcessManager {
1956
1956
  width: '100%',
1957
1957
  height: '100%',
1958
1958
  backgroundColor: COLORS.bg,
1959
- padding: 1,
1959
+ padding: 2,
1960
1960
  });
1961
1961
 
1962
1962
  // Header bar with title
@@ -1964,6 +1964,7 @@ class ProcessManager {
1964
1964
  id: 'header-bar',
1965
1965
  flexDirection: 'row',
1966
1966
  justifyContent: 'space-between',
1967
+ alignItems: 'center',
1967
1968
  width: '100%',
1968
1969
  border: ['bottom'],
1969
1970
  borderStyle: 'single',
@@ -1974,13 +1975,13 @@ class ProcessManager {
1974
1975
 
1975
1976
  const titleText = new TextRenderable(this.renderer, {
1976
1977
  id: 'title',
1977
- content: t`${fg(COLORS.accent)('# Settings')}`,
1978
+ content: t`${bold(fg(COLORS.accent)('Settings'))}`,
1978
1979
  });
1979
1980
  headerBar.add(titleText);
1980
1981
 
1981
1982
  const versionText = new TextRenderable(this.renderer, {
1982
1983
  id: 'version',
1983
- content: t`${fg(COLORS.textDim)(APP_VERSION)}`,
1984
+ content: t`${fg(COLORS.textDim)('startall')} ${fg(COLORS.textDim)('·')} ${fg(COLORS.textDim)(APP_VERSION)}`,
1984
1985
  });
1985
1986
  headerBar.add(versionText);
1986
1987
 
@@ -2121,40 +2122,42 @@ class ProcessManager {
2121
2122
  id: 'footer-bar',
2122
2123
  flexDirection: 'row',
2123
2124
  width: '100%',
2125
+ backgroundColor: COLORS.bgLight,
2124
2126
  border: ['top'],
2125
2127
  borderStyle: 'single',
2126
2128
  borderColor: COLORS.border,
2127
- paddingTop: 1,
2129
+ paddingLeft: 2,
2130
+ paddingRight: 2,
2128
2131
  marginTop: 1,
2129
- gap: 2,
2132
+ gap: 3,
2130
2133
  });
2131
2134
 
2132
2135
  let shortcuts;
2133
2136
  if (this.isAddingPattern) {
2134
2137
  shortcuts = [
2135
- { key: 'enter', desc: 'save' },
2136
- { key: 'esc', desc: 'cancel' },
2138
+ { key: 'enter', desc: 'save', color: COLORS.success },
2139
+ { key: 'esc', desc: 'cancel', color: COLORS.error },
2137
2140
  ];
2138
2141
  } else if (this.isAssigningShortcut) {
2139
2142
  shortcuts = [
2140
- { key: 'any key', desc: 'assign' },
2141
- { key: 'esc', desc: 'cancel' },
2143
+ { key: 'any key', desc: 'assign', color: COLORS.warning },
2144
+ { key: 'esc', desc: 'cancel', color: COLORS.error },
2142
2145
  ];
2143
2146
  } else {
2144
2147
  shortcuts = [
2145
- { key: 'tab', desc: 'section' },
2146
- { key: 'space', desc: this.settingsSection === 'shortcuts' ? 'assign' : 'toggle' },
2147
- { key: 'i', desc: 'add ignore' },
2148
- { key: 'n', desc: 'add include' },
2149
- { key: 'd', desc: 'delete' },
2150
- { key: 'esc', desc: 'back' },
2148
+ { key: 'tab', desc: 'section', color: COLORS.cyan },
2149
+ { key: 'space', desc: this.settingsSection === 'shortcuts' ? 'assign' : 'toggle', color: COLORS.success },
2150
+ { key: 'i', desc: 'add ignore', color: COLORS.error },
2151
+ { key: 'n', desc: 'add include', color: COLORS.success },
2152
+ { key: 'd', desc: 'delete', color: COLORS.error },
2153
+ { key: 'esc', desc: 'back', color: COLORS.textDim },
2151
2154
  ];
2152
2155
  }
2153
2156
 
2154
- shortcuts.forEach(({ key, desc }) => {
2157
+ shortcuts.forEach(({ key, desc, color }) => {
2155
2158
  const shortcut = new TextRenderable(this.renderer, {
2156
2159
  id: `shortcut-${key}`,
2157
- content: t`${fg(COLORS.textDim)(key)} ${fg(COLORS.text)(desc)}`,
2160
+ content: t`${fg(color || COLORS.accent)(key)} ${fg(COLORS.textDim)(desc)}`,
2158
2161
  });
2159
2162
  footerBar.add(shortcut);
2160
2163
  });
@@ -2424,17 +2427,49 @@ class ProcessManager {
2424
2427
  backgroundColor: COLORS.bg,
2425
2428
  });
2426
2429
 
2427
- // Scripts panel - compact with background for focused item
2430
+ // Content area (centered vertically, with padding)
2431
+ const contentArea = new BoxRenderable(this.renderer, {
2432
+ id: 'content-area',
2433
+ flexDirection: 'column',
2434
+ flexGrow: 1,
2435
+ padding: 2,
2436
+ paddingBottom: 0,
2437
+ gap: 1,
2438
+ });
2439
+
2440
+ // ASCII art title banner
2441
+ const asciiTitle = new ASCIIFontRenderable(this.renderer, {
2442
+ id: 'ascii-title',
2443
+ text: 'startall',
2444
+ font: 'tiny',
2445
+ color: RGBA.fromHex(COLORS.accent),
2446
+ });
2447
+ contentArea.add(asciiTitle);
2448
+
2449
+ // Subtitle with version
2450
+ const subtitle = new TextRenderable(this.renderer, {
2451
+ id: 'subtitle',
2452
+ content: t`${dim(fg(COLORS.textDim)(`${APP_VERSION} Process Manager`))}`,
2453
+ });
2454
+ contentArea.add(subtitle);
2455
+
2456
+ // Scripts panel in a bordered box
2428
2457
  const scriptsPanel = new BoxRenderable(this.renderer, {
2429
2458
  id: 'scripts-panel',
2430
2459
  flexDirection: 'column',
2431
2460
  flexGrow: 1,
2432
- paddingLeft: 1,
2433
- paddingTop: 1,
2461
+ border: true,
2462
+ borderStyle: 'rounded',
2463
+ borderColor: COLORS.border,
2464
+ title: ' Select Scripts ',
2465
+ titleAlignment: 'left',
2466
+ padding: 1,
2467
+ marginTop: 1,
2434
2468
  });
2435
2469
 
2436
2470
  // Track Y positions for mouse clicks
2437
- let currentY = 1; // start of scripts
2471
+ // ASCII title is ~3 lines, subtitle 1 line, margins/padding ~5 lines, border top 1 line
2472
+ let currentY = 10; // approximate start of scripts inside bordered box
2438
2473
  this.scriptLinePositions = [];
2439
2474
 
2440
2475
  this.scriptLines = this.scripts.map((script, index) => {
@@ -2450,17 +2485,21 @@ class ProcessManager {
2450
2485
  const numberLabel = index < 9 ? ` ${index + 1}` : ' ';
2451
2486
 
2452
2487
  // Build checkbox with colored brackets and checkmark
2488
+ const checkIcon = isSelected ? '✓' : ' ';
2489
+ const pointer = isFocused ? fg(COLORS.accent)('❯ ') : ' ';
2490
+
2453
2491
  let content;
2454
2492
  if (isSelected) {
2455
- content = t`${fg(numberColor)(numberLabel)} ${fg(bracketColor)('[')}${fg(COLORS.text)('✓')}${fg(bracketColor)(']')} ${fg(nameColor)(script.displayName)}`;
2493
+ content = t`${pointer}${fg(numberColor)(numberLabel)} ${fg(bracketColor)('[')}${fg(COLORS.success)(checkIcon)}${fg(bracketColor)(']')} ${fg(nameColor)(script.displayName)}`;
2456
2494
  } else {
2457
- content = t`${fg(numberColor)(numberLabel)} ${fg(bracketColor)('[ ]')} ${fg(nameColor)(script.displayName)}`;
2495
+ content = t`${pointer}${fg(numberColor)(numberLabel)} ${fg(bracketColor)('[ ]')} ${fg(nameColor)(script.displayName)}`;
2458
2496
  }
2459
2497
 
2460
2498
  const lineContainer = new BoxRenderable(this.renderer, {
2461
2499
  id: `script-box-${index}`,
2462
2500
  backgroundColor: bgColor,
2463
2501
  paddingLeft: 1,
2502
+ paddingRight: 1,
2464
2503
  width: '100%',
2465
2504
  });
2466
2505
 
@@ -2475,7 +2514,8 @@ class ProcessManager {
2475
2514
  return lineContainer;
2476
2515
  });
2477
2516
 
2478
- this.selectionContainer.add(scriptsPanel);
2517
+ contentArea.add(scriptsPanel);
2518
+ this.selectionContainer.add(contentArea);
2479
2519
 
2480
2520
  // Footer bar with title, countdown, and shortcuts
2481
2521
  const footerBar = new BoxRenderable(this.renderer, {
@@ -2484,11 +2524,14 @@ class ProcessManager {
2484
2524
  justifyContent: 'space-between',
2485
2525
  width: '100%',
2486
2526
  backgroundColor: COLORS.bgLight,
2487
- paddingLeft: 1,
2488
- paddingRight: 1,
2527
+ paddingLeft: 2,
2528
+ paddingRight: 2,
2529
+ border: ['top'],
2530
+ borderStyle: 'single',
2531
+ borderColor: COLORS.border,
2489
2532
  });
2490
2533
 
2491
- // Left side: title and countdown
2534
+ // Left side: countdown timer
2492
2535
  const leftSide = new BoxRenderable(this.renderer, {
2493
2536
  id: 'footer-left',
2494
2537
  flexDirection: 'row',
@@ -2497,7 +2540,7 @@ class ProcessManager {
2497
2540
 
2498
2541
  const titleText = new TextRenderable(this.renderer, {
2499
2542
  id: 'title',
2500
- content: t`${fg(COLORS.accent)('startall')} ${fg(COLORS.warning)(this.countdown + 's')}`,
2543
+ content: t`${fg(COLORS.accent)('startall')} ${fg(COLORS.textDim)('·')} ${fg(COLORS.warning)(`${this.countdown}s`)}`,
2501
2544
  });
2502
2545
  leftSide.add(titleText);
2503
2546
  this.headerText = titleText; // Save reference for countdown updates
@@ -2513,23 +2556,23 @@ class ProcessManager {
2513
2556
 
2514
2557
  footerBar.add(leftSide);
2515
2558
 
2516
- // Right side: shortcuts
2559
+ // Right side: shortcuts with visual badges
2517
2560
  const rightSide = new BoxRenderable(this.renderer, {
2518
2561
  id: 'footer-right',
2519
2562
  flexDirection: 'row',
2520
- gap: 2,
2563
+ gap: 3,
2521
2564
  });
2522
2565
 
2523
2566
  const shortcuts = [
2524
- { key: 'spc', desc: 'sel', color: COLORS.success },
2525
- { key: 'ret', desc: 'go', color: COLORS.accent },
2526
- { key: 'o', desc: 'cfg', color: COLORS.magenta },
2567
+ { key: 'space', desc: 'select', color: COLORS.success },
2568
+ { key: 'enter', desc: 'start', color: COLORS.accent },
2569
+ { key: 'o', desc: 'settings', color: COLORS.magenta },
2527
2570
  ];
2528
2571
 
2529
2572
  shortcuts.forEach(({ key, desc, color }) => {
2530
2573
  const shortcut = new TextRenderable(this.renderer, {
2531
2574
  id: `shortcut-${key}`,
2532
- content: t`${fg(color)(key)}${fg(COLORS.textDim)(':' + desc)}`,
2575
+ content: t`${fg(color)(key)} ${fg(COLORS.textDim)(desc)}`,
2533
2576
  });
2534
2577
  rightSide.add(shortcut);
2535
2578
  });
@@ -3207,11 +3250,20 @@ class ProcessManager {
3207
3250
  });
3208
3251
 
3209
3252
  // Footer hint
3253
+ const hintBar = new BoxRenderable(this.renderer, {
3254
+ id: 'menu-hint-bar',
3255
+ border: ['top'],
3256
+ borderStyle: 'single',
3257
+ borderColor: COLORS.border,
3258
+ paddingTop: 1,
3259
+ marginTop: 1,
3260
+ });
3210
3261
  const hint = new TextRenderable(this.renderer, {
3211
3262
  id: 'menu-hint',
3212
- content: t`${fg(COLORS.textDim)('Enter to select, Esc to close')}`,
3263
+ content: t`${fg(COLORS.accent)('enter')} ${fg(COLORS.textDim)('select')} ${fg(COLORS.accent)('esc')} ${fg(COLORS.textDim)('close')}`,
3213
3264
  });
3214
- overlay.add(hint);
3265
+ hintBar.add(hint);
3266
+ overlay.add(hintBar);
3215
3267
 
3216
3268
  parent.add(overlay);
3217
3269
  }
@@ -3455,7 +3507,12 @@ class ProcessManager {
3455
3507
  flexDirection: 'row',
3456
3508
  width: '100%',
3457
3509
  backgroundColor: COLORS.bgLight,
3458
- paddingLeft: 1,
3510
+ paddingLeft: 2,
3511
+ paddingRight: 2,
3512
+ gap: 1,
3513
+ border: ['bottom'],
3514
+ borderStyle: 'single',
3515
+ borderColor: COLORS.border,
3459
3516
  });
3460
3517
  this.processBarContainer = processBar; // Save reference for light updates
3461
3518
 
@@ -3513,15 +3570,18 @@ class ProcessManager {
3513
3570
 
3514
3571
  mainContainer.add(paneArea);
3515
3572
 
3516
- // Footer bar - compact style matching selection UI
3573
+ // Footer bar - polished with top border
3517
3574
  const footerBar = new BoxRenderable(this.renderer, {
3518
3575
  id: 'footer-bar',
3519
3576
  flexDirection: 'row',
3520
3577
  width: '100%',
3521
3578
  backgroundColor: COLORS.bgLight,
3522
- paddingLeft: 1,
3523
- paddingRight: 1,
3579
+ paddingLeft: 2,
3580
+ paddingRight: 2,
3524
3581
  justifyContent: 'space-between',
3582
+ border: ['top'],
3583
+ borderStyle: 'single',
3584
+ borderColor: COLORS.border,
3525
3585
  });
3526
3586
 
3527
3587
  // Left side: status indicator and filter
@@ -3632,47 +3692,80 @@ class ProcessManager {
3632
3692
  gap: 2,
3633
3693
  });
3634
3694
 
3635
- const shortcuts = [
3636
- { key: '\\', desc: 'panes', color: COLORS.cyan },
3637
- { key: 'e', desc: 'execute', color: COLORS.warning },
3638
- { key: '1-9', desc: 'toggle', color: COLORS.success },
3639
- { key: 'i', desc: 'input', color: COLORS.success },
3640
- { key: 'n', desc: 'name', color: COLORS.accent },
3641
- { key: 'y', desc: 'copy', color: COLORS.accent },
3642
- { key: 'p', desc: 'pause', color: COLORS.warning },
3643
- { key: '/', desc: 'filter', color: COLORS.cyan },
3644
- { key: 'c', desc: 'color', color: COLORS.magenta },
3645
- { key: 's', desc: 'stop', color: COLORS.error },
3646
- { key: 'r', desc: 'restart', color: COLORS.success },
3647
- { key: 'o', desc: 'settings', color: COLORS.magenta },
3648
- { key: 'q', desc: 'quit', color: COLORS.error },
3695
+ // Shortcut groups separated by dimmed pipe characters
3696
+ const shortcutGroups = [
3697
+ // Pane & navigation
3698
+ [
3699
+ { key: '\\', desc: 'panes', color: COLORS.cyan },
3700
+ { key: '1-9', desc: 'toggle', color: COLORS.success },
3701
+ ],
3702
+ // Process control
3703
+ [
3704
+ { key: 's', desc: 'stop', color: COLORS.error },
3705
+ { key: 'r', desc: 'restart', color: COLORS.success },
3706
+ { key: 'e', desc: 'execute', color: COLORS.warning },
3707
+ ],
3708
+ // View & edit
3709
+ [
3710
+ { key: 'p', desc: 'pause', color: COLORS.warning },
3711
+ { key: '/', desc: 'filter', color: COLORS.cyan },
3712
+ { key: 'c', desc: 'color', color: COLORS.magenta },
3713
+ { key: 'y', desc: 'copy', color: COLORS.accent },
3714
+ ],
3715
+ // Misc
3716
+ [
3717
+ { key: 'i', desc: 'input', color: COLORS.success },
3718
+ { key: 'n', desc: 'name', color: COLORS.accent },
3719
+ { key: 'o', desc: 'cfg', color: COLORS.magenta },
3720
+ { key: 'q', desc: 'quit', color: COLORS.error },
3721
+ ],
3649
3722
  ];
3650
3723
 
3651
- // Add configured quick command shortcuts
3724
+ // Add configured quick command shortcuts to the first group
3652
3725
  const configShortcuts = this.config.shortcuts || {};
3726
+ const customGroup = [];
3653
3727
  for (const [key, scriptName] of Object.entries(configShortcuts)) {
3654
- // Show first 3 shortcuts to avoid cluttering footer
3655
- if (Object.keys(configShortcuts).length <= 3 || shortcuts.length < 15) {
3728
+ if (customGroup.length < 3) {
3656
3729
  const script = this.allScripts.find(s => s.name === scriptName);
3657
3730
  if (script) {
3658
3731
  const shortDesc = script.displayName.length > 8 ? script.displayName.substring(0, 6) + '..' : script.displayName;
3659
- shortcuts.splice(2, 0, { key, desc: shortDesc, color: this.processColors.get(script.name) || COLORS.text });
3732
+ customGroup.push({ key, desc: shortDesc, color: this.processColors.get(script.name) || COLORS.text });
3660
3733
  }
3661
3734
  }
3662
3735
  }
3736
+ if (customGroup.length > 0) {
3737
+ shortcutGroups.splice(1, 0, customGroup);
3738
+ }
3663
3739
 
3664
- shortcuts.forEach(({ key, desc, color }) => {
3665
- const shortcut = new TextRenderable(this.renderer, {
3666
- id: `shortcut-${key}`,
3667
- content: t`${fg(color)(key)}${fg(COLORS.textDim)(':' + desc)}`,
3740
+ shortcutGroups.forEach((group, groupIdx) => {
3741
+ // Add separator between groups
3742
+ if (groupIdx > 0) {
3743
+ const sep = new TextRenderable(this.renderer, {
3744
+ id: `shortcut-sep-${groupIdx}`,
3745
+ content: t`${fg(COLORS.border)('│')}`,
3746
+ });
3747
+ rightSide.add(sep);
3748
+ }
3749
+
3750
+ group.forEach(({ key, desc, color }) => {
3751
+ const shortcut = new TextRenderable(this.renderer, {
3752
+ id: `shortcut-${key}`,
3753
+ content: t`${fg(color)(key)} ${fg(COLORS.textDim)(desc)}`,
3754
+ });
3755
+ rightSide.add(shortcut);
3668
3756
  });
3669
- rightSide.add(shortcut);
3670
3757
  });
3671
3758
 
3672
- // Title and version on far right
3759
+ // Title and version on far right, separated
3760
+ const titleSep = new TextRenderable(this.renderer, {
3761
+ id: 'footer-title-sep',
3762
+ content: t`${fg(COLORS.border)('│')}`,
3763
+ });
3764
+ rightSide.add(titleSep);
3765
+
3673
3766
  const titleText = new TextRenderable(this.renderer, {
3674
3767
  id: 'footer-title',
3675
- content: t`${fg(COLORS.accent)('running')} ${fg(COLORS.textDim)(APP_VERSION)}`,
3768
+ content: t`${fg(COLORS.accent)('startall')} ${fg(COLORS.textDim)(APP_VERSION)}`,
3676
3769
  });
3677
3770
  rightSide.add(titleText);
3678
3771
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "startall",
3
- "version": "0.0.19",
3
+ "version": "0.0.20",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {