startall 0.0.22 → 0.0.23
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/README.md +2 -0
- package/index.js +83 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,6 +43,7 @@ Traditional solutions fall short:
|
|
|
43
43
|
- Per-process visibility toggles (`Space` or `1-9`)
|
|
44
44
|
- Per-pane filters (different views in each pane)
|
|
45
45
|
- **Custom pane naming**: Label panes for easier identification (`n`)
|
|
46
|
+
- **Column view**: Instant one-pane-per-script layout with `=` key (toggle back to restore your layout)
|
|
46
47
|
- **Persistent layouts**: Your pane configuration is saved between sessions
|
|
47
48
|
- **Process-specific views**: Show/hide specific processes in each pane
|
|
48
49
|
- **Colored output**: Each process gets unique color-coded output
|
|
@@ -122,6 +123,7 @@ That's it! The TUI will:
|
|
|
122
123
|
- `\` - Open command palette
|
|
123
124
|
- `|` - Split pane vertically (left/right)
|
|
124
125
|
- `_` - Split pane horizontally (top/bottom)
|
|
126
|
+
- `=` - Toggle column view (one column per script, auto-generated)
|
|
125
127
|
- `x` - Close current pane (if >1 pane exists)
|
|
126
128
|
- `Tab` - Next pane
|
|
127
129
|
- `Shift+Tab` - Previous pane
|
package/index.js
CHANGED
|
@@ -606,6 +606,10 @@ class ProcessManager {
|
|
|
606
606
|
this.paneLineCount = new Map(); // Track how many lines we've rendered per pane
|
|
607
607
|
this.uiJustRebuilt = false; // Flag to skip redundant render after buildRunningUI
|
|
608
608
|
|
|
609
|
+
// Column view state (one pane per script, side by side)
|
|
610
|
+
this.isColumnView = false; // Whether column view is active
|
|
611
|
+
this.savedPaneRoot = null; // Saved pane tree to restore when toggling back
|
|
612
|
+
|
|
609
613
|
// Copy mode state (select text to copy)
|
|
610
614
|
this.isCopyMode = false; // Whether in copy/select mode
|
|
611
615
|
this.copyModeCursor = 0; // Current cursor line index within visible lines
|
|
@@ -842,14 +846,17 @@ class ProcessManager {
|
|
|
842
846
|
this.buildRunningUI();
|
|
843
847
|
} else if (keyName === '|') {
|
|
844
848
|
// Quick vertical split
|
|
849
|
+
this.exitColumnViewMode();
|
|
845
850
|
this.splitCurrentPane('vertical');
|
|
846
851
|
this.buildRunningUI();
|
|
847
852
|
} else if (keyName === '_') {
|
|
848
853
|
// Quick horizontal split
|
|
854
|
+
this.exitColumnViewMode();
|
|
849
855
|
this.splitCurrentPane('horizontal');
|
|
850
856
|
this.buildRunningUI();
|
|
851
857
|
} else if (keyName === 'x' && getAllPaneIds(this.paneRoot).length > 1) {
|
|
852
858
|
// Close current pane (only if more than one)
|
|
859
|
+
this.exitColumnViewMode();
|
|
853
860
|
this.closeCurrentPane();
|
|
854
861
|
this.buildRunningUI();
|
|
855
862
|
} else if (keyName === 'space') {
|
|
@@ -985,6 +992,9 @@ class ProcessManager {
|
|
|
985
992
|
} else if (keyName === 'y') {
|
|
986
993
|
// Enter copy mode (select text to copy)
|
|
987
994
|
this.enterCopyMode();
|
|
995
|
+
} else if (keyName === '=') {
|
|
996
|
+
// Toggle column view (one pane per script)
|
|
997
|
+
this.toggleColumnView();
|
|
988
998
|
} else if (keyName === 'g' && IS_GIT_REPO) {
|
|
989
999
|
// Open git modal (commit & push)
|
|
990
1000
|
this.openGitModal();
|
|
@@ -1674,6 +1684,67 @@ class ProcessManager {
|
|
|
1674
1684
|
}
|
|
1675
1685
|
}
|
|
1676
1686
|
|
|
1687
|
+
// Generate a column view pane tree: one pane per running script, side by side
|
|
1688
|
+
generateColumnViewPaneTree() {
|
|
1689
|
+
// Get the scripts that are currently selected/running
|
|
1690
|
+
const runningScripts = this.scripts.filter(s => {
|
|
1691
|
+
const proc = this.processes.get(s.name);
|
|
1692
|
+
return proc && (proc.status === 'running' || proc.status === 'crashed' || proc.status === 'exited');
|
|
1693
|
+
});
|
|
1694
|
+
|
|
1695
|
+
if (runningScripts.length === 0) {
|
|
1696
|
+
return createPane([]);
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
if (runningScripts.length === 1) {
|
|
1700
|
+
return createPane([runningScripts[0].name]);
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1703
|
+
// Create a vertical split with one pane per script
|
|
1704
|
+
const panes = runningScripts.map(s => {
|
|
1705
|
+
const pane = createPane([s.name]);
|
|
1706
|
+
pane.name = s.displayName;
|
|
1707
|
+
return pane;
|
|
1708
|
+
});
|
|
1709
|
+
|
|
1710
|
+
return createSplit('vertical', panes);
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
// Toggle between column view (one pane per script) and the normal saved layout
|
|
1714
|
+
toggleColumnView() {
|
|
1715
|
+
if (this.isColumnView) {
|
|
1716
|
+
// Restore the saved pane tree
|
|
1717
|
+
if (this.savedPaneRoot) {
|
|
1718
|
+
this.paneRoot = this.savedPaneRoot;
|
|
1719
|
+
this.savedPaneRoot = null;
|
|
1720
|
+
} else {
|
|
1721
|
+
this.paneRoot = createPane([]);
|
|
1722
|
+
}
|
|
1723
|
+
this.isColumnView = false;
|
|
1724
|
+
} else {
|
|
1725
|
+
// Save current pane tree and switch to column view
|
|
1726
|
+
this.savedPaneRoot = this.paneRoot;
|
|
1727
|
+
this.paneRoot = this.generateColumnViewPaneTree();
|
|
1728
|
+
this.isColumnView = true;
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1731
|
+
// Focus the first pane in the new tree
|
|
1732
|
+
const allPanes = getAllPaneIds(this.paneRoot);
|
|
1733
|
+
if (allPanes.length > 0) {
|
|
1734
|
+
this.focusedPaneId = allPanes[0];
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
this.buildRunningUI();
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
// Exit column view mode without restoring saved layout (e.g. user manually split/closed a pane)
|
|
1741
|
+
exitColumnViewMode() {
|
|
1742
|
+
if (this.isColumnView) {
|
|
1743
|
+
this.isColumnView = false;
|
|
1744
|
+
this.savedPaneRoot = null;
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1677
1748
|
// Move the currently selected process to the focused pane
|
|
1678
1749
|
moveProcessToCurrentPane() {
|
|
1679
1750
|
const scriptName = this.scripts[this.selectedIndex]?.name;
|
|
@@ -1760,6 +1831,8 @@ class ProcessManager {
|
|
|
1760
1831
|
|
|
1761
1832
|
// Save the current pane layout to config (debounced to avoid excessive disk writes)
|
|
1762
1833
|
savePaneLayout() {
|
|
1834
|
+
// Don't save the auto-generated column view layout - it's transient
|
|
1835
|
+
if (this.isColumnView) return;
|
|
1763
1836
|
this.config.paneLayout = serializePaneTree(this.paneRoot);
|
|
1764
1837
|
debouncedSaveConfig(this.config);
|
|
1765
1838
|
}
|
|
@@ -4176,6 +4249,15 @@ class ProcessManager {
|
|
|
4176
4249
|
});
|
|
4177
4250
|
leftSide.add(statusIndicator);
|
|
4178
4251
|
|
|
4252
|
+
// Column view indicator
|
|
4253
|
+
if (this.isColumnView) {
|
|
4254
|
+
const columnIndicator = new TextRenderable(this.renderer, {
|
|
4255
|
+
id: 'column-view-indicator',
|
|
4256
|
+
content: t`${fg(COLORS.cyan)('COLUMNS')}`,
|
|
4257
|
+
});
|
|
4258
|
+
leftSide.add(columnIndicator);
|
|
4259
|
+
}
|
|
4260
|
+
|
|
4179
4261
|
// Git branch indicator
|
|
4180
4262
|
if (IS_GIT_REPO) {
|
|
4181
4263
|
const branch = this.gitBranch || getGitBranch();
|
|
@@ -4286,6 +4368,7 @@ class ProcessManager {
|
|
|
4286
4368
|
// Pane & navigation
|
|
4287
4369
|
[
|
|
4288
4370
|
{ key: '\\', desc: 'panes', color: COLORS.cyan },
|
|
4371
|
+
{ key: '=', desc: this.isColumnView ? 'merged' : 'columns', color: COLORS.cyan },
|
|
4289
4372
|
{ key: '1-9', desc: 'toggle', color: COLORS.success },
|
|
4290
4373
|
],
|
|
4291
4374
|
// Process control
|