project-compass 3.3.4 → 3.3.6

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 +40 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-compass",
3
- "version": "3.3.4",
3
+ "version": "3.3.6",
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
@@ -248,20 +248,33 @@ function Compass({rootPath, initialView = 'navigator'}) {
248
248
  });
249
249
  }, []);
250
250
 
251
- const detailedIndexed = useMemo(() => buildDetailCommands(selectedProject, config).map((command, index) => ({
252
- ...command,
253
- shortcut: `${index + 1}`
254
- })), [selectedProject, config]);
251
+ const detailedIndexed = useMemo(() => buildDetailCommands(selectedProject, config).map((command, index) => {
252
+ const isOver9 = index >= 9;
253
+ const shortcut = isOver9 ? `S+${String.fromCharCode(65 + index - 9)}` : `${index + 1}`;
254
+ return { ...command, shortcut };
255
+ }), [selectedProject, config]);
255
256
 
256
257
  const detailShortcutMap = useMemo(() => {
257
258
  const map = new Map();
258
- detailedIndexed.forEach((cmd) => map.set(cmd.shortcut, cmd));
259
+ detailedIndexed.forEach((cmd) => {
260
+ if (cmd.shortcut.startsWith('S+')) {
261
+ map.set(cmd.shortcut.slice(2).toLowerCase(), cmd);
262
+ } else {
263
+ map.set(cmd.shortcut, cmd);
264
+ }
265
+ });
259
266
  return map;
260
267
  }, [detailedIndexed]);
261
268
 
262
269
  const killAllTasks = useCallback(() => {
263
270
  runningProcessMap.current.forEach((proc) => {
264
- try { proc.kill('SIGKILL'); } catch { /* ignore */ }
271
+ try {
272
+ if (process.platform === 'win32') {
273
+ execa('taskkill', ['/pid', proc.pid, '/f', '/t']);
274
+ } else {
275
+ process.kill(-proc.pid, 'SIGKILL');
276
+ }
277
+ } catch { /* ignore */ }
265
278
  });
266
279
  runningProcessMap.current.clear();
267
280
  }, []);
@@ -290,6 +303,7 @@ function Compass({rootPath, initialView = 'navigator'}) {
290
303
  cwd: project.path,
291
304
  env: process.env,
292
305
  stdin: 'pipe',
306
+ detached: process.platform !== 'win32',
293
307
  cleanup: true
294
308
  });
295
309
  runningProcessMap.current.set(taskId, subprocess);
@@ -316,12 +330,23 @@ function Compass({rootPath, initialView = 'navigator'}) {
316
330
  const handleKillTask = useCallback((taskId) => {
317
331
  const proc = runningProcessMap.current.get(taskId);
318
332
  if (proc) {
319
- proc.kill('SIGKILL');
333
+ addLogToTask(taskId, kleur.yellow('! Force killing process group...'));
334
+ try {
335
+ if (process.platform === 'win32') {
336
+ execa('taskkill', ['/pid', proc.pid, '/f', '/t']);
337
+ } else if (proc.pid) {
338
+ process.kill(-proc.pid, 'SIGKILL');
339
+ } else {
340
+ proc.kill('SIGKILL');
341
+ }
342
+ } catch (e) {
343
+ addLogToTask(taskId, kleur.red(`✗ Kill failed: ${e.message}`));
344
+ }
320
345
  } else {
321
346
  setTasks(prev => prev.filter(t => t.id !== taskId));
322
347
  if (activeTaskId === taskId) setActiveTaskId(null);
323
348
  }
324
- }, [activeTaskId]);
349
+ }, [activeTaskId, addLogToTask]);
325
350
 
326
351
  const exportLogs = useCallback(() => {
327
352
  const taskToExport = tasks.find(t => t.id === activeTaskId);
@@ -465,9 +490,11 @@ function Compass({rootPath, initialView = 'navigator'}) {
465
490
  }
466
491
 
467
492
  if (running && activeTaskId && runningProcessMap.current.has(activeTaskId)) {
468
- const proc = runningProcessMap.current.get(activeTaskId);
469
- if (key.ctrl && input === 'c') { proc.kill('SIGKILL'); setStdinBuffer(''); setStdinCursor(0); return; }
470
- if (key.return) { proc.stdin?.write(stdinBuffer + '\n'); setStdinBuffer(''); setStdinCursor(0); return; }
493
+ if (key.ctrl && input === 'c') { handleKillTask(activeTaskId); setStdinBuffer(''); setStdinCursor(0); return; }
494
+ if (key.return) {
495
+ const proc = runningProcessMap.current.get(activeTaskId);
496
+ proc?.stdin?.write(stdinBuffer + '\n'); setStdinBuffer(''); setStdinCursor(0); return;
497
+ }
471
498
  if (key.backspace || key.delete) {
472
499
  if (stdinCursor > 0) {
473
500
  setStdinBuffer(prev => prev.slice(0, stdinCursor - 1) + prev.slice(stdinCursor));
@@ -591,7 +618,7 @@ function Compass({rootPath, initialView = 'navigator'}) {
591
618
 
592
619
  const helpCards = [
593
620
  {label: 'Navigation', color: 'magenta', body: ['↑ / ↓ move focus, Enter: details', 'Shift+↑ / ↓ scroll output', 'Shift+H toggle help cards', 'Shift+D detach from task']},
594
- {label: 'Commands', color: 'cyan', body: ['B / T / R build/test/run', '1-9 run detail commands', 'Shift+L rerun last command', 'Shift+X clear / Shift+E export']},
621
+ {label: 'Commands', color: 'cyan', body: ['B / T / R build/test/run', '1-9 / S+A-Z numbered commands', 'Shift+L rerun last command', 'Shift+X clear / Shift+E export']},
595
622
  {label: 'Orbit & Studio', color: 'yellow', body: ['Shift+T task manager', 'Shift+A studio / Shift+B art board', 'Shift+S structure / Shift+Q quit']}
596
623
  ];
597
624
 
@@ -678,7 +705,7 @@ async function main() {
678
705
  console.log('');
679
706
  console.log(kleur.bold('Execution shortcuts:'));
680
707
  console.log(' B / T / R Quick run: Build / Test / Run');
681
- console.log(' 1-9 Run numbered commands in detail view');
708
+ console.log(' 1-9 / S+A-Z Run numbered commands in detail view');
682
709
  console.log(' Shift+L Rerun the last executed command');
683
710
  console.log(' Shift+C Add a custom command (in detail view)');
684
711
  console.log('');