project-compass 2.8.0 → 2.8.2

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/package.json +1 -1
  2. package/src/cli.js +23 -20
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-compass",
3
- "version": "2.8.0",
3
+ "version": "2.8.2",
4
4
  "description": "Ink-based project explorer that detects local repos and lets you build/test/run them without memorizing commands.",
5
5
  "main": "src/cli.js",
6
6
  "type": "module",
package/src/cli.js CHANGED
@@ -6,7 +6,7 @@ import fs from 'fs';
6
6
  import kleur from 'kleur';
7
7
  import {execa} from 'execa';
8
8
  import {discoverProjects, SCHEMA_GUIDE, checkBinary} from './projectDetection.js';
9
- import {CONFIG_PATH, PLUGIN_FILE, ensureConfigDir} from './configPaths.js';
9
+ import {CONFIG_PATH, ensureConfigDir} from './configPaths.js';
10
10
 
11
11
  const create = React.createElement;
12
12
  const DEFAULT_CONFIG = {customCommands: {}};
@@ -17,7 +17,6 @@ const OUTPUT_WINDOW_HEIGHT = OUTPUT_WINDOW_SIZE + 2;
17
17
  const PROJECTS_MIN_WIDTH = 32;
18
18
  const DETAILS_MIN_WIDTH = 44;
19
19
  const HELP_CARD_MIN_WIDTH = 28;
20
- const RECENT_RUN_LIMIT = 5;
21
20
  const ACTION_MAP = {
22
21
  b: 'build',
23
22
  t: 'test',
@@ -175,7 +174,6 @@ function Compass({rootPath, initialView = 'navigator'}) {
175
174
  const [tasks, setTasks] = useState([]);
176
175
  const [activeTaskId, setActiveTaskId] = useState(null);
177
176
  const [logOffset, setLogOffset] = useState(0);
178
- const [lastAction, setLastAction] = useState(null);
179
177
  const [customMode, setCustomMode] = useState(false);
180
178
  const [customInput, setCustomInput] = useState('');
181
179
  const [customCursor, setCustomCursor] = useState(0);
@@ -185,7 +183,6 @@ function Compass({rootPath, initialView = 'navigator'}) {
185
183
  const [stdinBuffer, setStdinBuffer] = useState('');
186
184
  const [stdinCursor, setStdinCursor] = useState(0);
187
185
  const [showHelp, setShowHelp] = useState(false);
188
- const [recentRuns, setRecentRuns] = useState([]);
189
186
  const selectedProject = projects[selectedIndex] || null;
190
187
  const runningProcessMap = useRef(new Map());
191
188
  const lastCommandRef = useRef(null);
@@ -232,12 +229,6 @@ function Compass({rootPath, initialView = 'navigator'}) {
232
229
  setTasks(prev => [...prev, newTask]);
233
230
  setActiveTaskId(taskId);
234
231
  lastCommandRef.current = {project, commandMeta};
235
- setLastAction(newTask.name);
236
-
237
- setRecentRuns((prev) => {
238
- const entry = {project: project.name, command: commandLabel, time: new Date().toLocaleTimeString()};
239
- return [entry, ...prev].slice(0, RECENT_RUN_LIMIT);
240
- });
241
232
 
242
233
  try {
243
234
  const subprocess = execa(commandMeta.command[0], commandMeta.command.slice(1), {
@@ -341,7 +332,15 @@ function Compass({rootPath, initialView = 'navigator'}) {
341
332
  if (shiftCombo('x')) { setTasks(prev => prev.map(t => t.id === activeTaskId ? {...t, logs: []} : t)); setLogOffset(0); return; }
342
333
  if (shiftCombo('e')) { exportLogs(); return; }
343
334
  if (shiftCombo('d')) { setActiveTaskId(null); return; }
344
- if (shiftCombo('t')) { setMainView('tasks'); return; }
335
+
336
+ if (shiftCombo('t')) {
337
+ setMainView((prev) => {
338
+ if (prev === 'tasks') return 'navigator';
339
+ if (tasks.length > 0 && !activeTaskId) setActiveTaskId(tasks[0].id);
340
+ return 'tasks';
341
+ });
342
+ return;
343
+ }
345
344
 
346
345
  const scrollLogs = (delta) => {
347
346
  setLogOffset((prev) => {
@@ -351,6 +350,15 @@ function Compass({rootPath, initialView = 'navigator'}) {
351
350
  });
352
351
  };
353
352
 
353
+ if (mainView === 'tasks') {
354
+ if (tasks.length > 0) {
355
+ if (key.upArrow) { setActiveTaskId(prev => tasks[(tasks.findIndex(t => t.id === prev) - 1 + tasks.length) % tasks.length]?.id); return; }
356
+ if (key.downArrow) { setActiveTaskId(prev => tasks[(tasks.findIndex(t => t.id === prev) + 1) % tasks.length]?.id); return; }
357
+ }
358
+ if (key.return) { setMainView('navigator'); return; }
359
+ return;
360
+ }
361
+
354
362
  if (running && activeTaskId && runningProcessMap.current.has(activeTaskId)) {
355
363
  const proc = runningProcessMap.current.get(activeTaskId);
356
364
  if (key.ctrl && input === 'c') { proc.kill('SIGINT'); setStdinBuffer(''); setStdinCursor(0); return; }
@@ -377,13 +385,6 @@ function Compass({rootPath, initialView = 'navigator'}) {
377
385
  if (normalizedInput === '?') { setShowHelp((prev) => !prev); return; }
378
386
  if (shiftCombo('l') && lastCommandRef.current) { runProjectCommand(lastCommandRef.current.commandMeta, lastCommandRef.current.project); return; }
379
387
 
380
- if (mainView === 'tasks') {
381
- if (key.upArrow) { setActiveTaskId(prev => tasks[(tasks.findIndex(t => t.id === prev) - 1 + tasks.length) % tasks.length]?.id); return; }
382
- if (key.downArrow) { setActiveTaskId(prev => tasks[(tasks.findIndex(t => t.id === prev) + 1) % tasks.length]?.id); return; }
383
- if (key.return || shiftCombo('t')) { setMainView('navigator'); return; }
384
- return;
385
- }
386
-
387
388
  if (key.upArrow && !key.shift && projects.length > 0) { setSelectedIndex((prev) => (prev - 1 + projects.length) % projects.length); return; }
388
389
  if (key.downArrow && !key.shift && projects.length > 0) { setSelectedIndex((prev) => (prev + 1) % projects.length); return; }
389
390
  if (key.return) {
@@ -405,6 +406,8 @@ function Compass({rootPath, initialView = 'navigator'}) {
405
406
  }
406
407
  });
407
408
 
409
+ const projectCountLabel = `${projects.length} project${projects.length === 1 ? '' : 's'}`;
410
+
408
411
  if (mainView === 'studio') return create(Studio);
409
412
 
410
413
  if (mainView === 'tasks') {
@@ -419,7 +422,7 @@ function Compass({rootPath, initialView = 'navigator'}) {
419
422
  create(Text, {color: t.id === activeTaskId ? 'cyan' : 'white', bold: t.id === activeTaskId}, `${t.id === activeTaskId ? '→' : ' '} [${t.status.toUpperCase()}] ${t.name}`)
420
423
  )),
421
424
  !tasks.length && create(Text, {dimColor: true}, 'No active or background tasks.'),
422
- create(Text, {marginTop: 1, dimColor: true}, 'Press Enter/Shift+T to return to Navigator, Up/Down to switch focus.')
425
+ create(Text, {marginTop: 1, dimColor: true}, 'Press Enter or Shift+T to return to Navigator, Up/Down to switch focus.')
423
426
  );
424
427
  }
425
428
 
@@ -530,7 +533,7 @@ function Compass({rootPath, initialView = 'navigator'}) {
530
533
  create(Box, {flexDirection: 'row', justifyContent: 'space-between'}, create(Text, {bold: true, color: 'yellow'}, `Output: ${activeTask?.name || 'None'}`), create(Text, {dimColor: true}, logOffset ? `Scrolled ${logOffset} lines` : 'Live log view')),
531
534
  create(Box, {flexDirection: 'column', borderStyle: 'round', borderColor: 'yellow', padding: 1, minHeight: OUTPUT_WINDOW_HEIGHT, maxHeight: OUTPUT_WINDOW_HEIGHT, height: OUTPUT_WINDOW_HEIGHT, overflow: 'hidden'}, ...logNodes),
532
535
  create(Box, {marginTop: 1, flexDirection: 'row', justifyContent: 'space-between'}, create(Text, {dimColor: true}, running ? 'Type to feed stdin; Enter: submit, Ctrl+C: abort.' : 'Run a command or press Shift+T to switch tasks.'), create(Text, {dimColor: true}, `${toggleHint}, Shift+S: Structure Guide`)),
533
- create(Box, {marginTop: 1, flexDirection: 'row', borderStyle: 'round', borderColor: running ? 'green' : 'gray', paddingX: 1}, create(Text, {bold: true, color: running ? 'green' : 'white'}, running ? ' Stdin buffer ' : ' Input ready '), create(Box, {marginLeft: 1}, create(CursorText, {value: stdinBuffer || (running ? '' : 'Start a command to feed stdin'), cursorIndex: stdinCursor, active: running})))
536
+ create(Box, {marginTop: 1, flexDirection: 'row', borderStyle: 'round', borderColor: running ? 'green' : 'gray', paddingX: 1}, create(Text, {bold: true, color: 'green'}, running ? ' Stdin buffer ' : ' Input ready '), create(Box, {marginLeft: 1}, create(CursorText, {value: stdinBuffer || (running ? '' : 'Start a command to feed stdin'), cursorIndex: stdinCursor, active: running})))
534
537
  ),
535
538
  showHelpCards && create(Box, {marginTop: 1, flexDirection: 'row', justifyContent: 'space-between', flexWrap: 'wrap'}, ...helpCards.map((card, idx) => create(Box, {key: card.label, flexGrow: 1, flexBasis: 0, minWidth: HELP_CARD_MIN_WIDTH, marginRight: idx < 2 ? 1 : 0, marginBottom: 1, borderStyle: 'round', borderColor: card.color, padding: 1, flexDirection: 'column'}, create(Text, {color: card.color, bold: true, marginBottom: 1}, card.label), ...card.body.map((line, lidx) => create(Text, {key: lidx, dimColor: card.color === 'yellow'}, line))))),
536
539
  showStructureGuide && create(Box, {flexDirection: 'column', borderStyle: 'round', borderColor: 'blue', marginTop: 1, padding: 1}, create(Text, {color: 'cyan', bold: true}, 'Structure guide · press Shift+S to hide'), ...SCHEMA_GUIDE.map(e => create(Text, {key: e.type, dimColor: true}, `• ${e.icon} ${e.label}: ${e.files.join(', ')}`))),