abmux 0.0.6 → 0.0.8
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/dist/cli/index.js +154 -70
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -532,7 +532,12 @@ var createManagerUsecase = (context) => {
|
|
|
532
532
|
const { tmux, sessionDetection } = context.services;
|
|
533
533
|
const windowTarget = (up) => `${up.pane.sessionName}:${String(up.pane.windowIndex)}`;
|
|
534
534
|
return {
|
|
535
|
-
createSession: async ({
|
|
535
|
+
createSession: async ({
|
|
536
|
+
sessionName,
|
|
537
|
+
cwd,
|
|
538
|
+
prompt,
|
|
539
|
+
worktree
|
|
540
|
+
}) => {
|
|
536
541
|
const exists2 = await context.infra.tmuxCli.hasSession(sessionName);
|
|
537
542
|
if (!exists2) {
|
|
538
543
|
await context.infra.tmuxCli.newSession({ name: sessionName, cwd });
|
|
@@ -544,7 +549,8 @@ var createManagerUsecase = (context) => {
|
|
|
544
549
|
const target = sessionPanes[0]?.paneId;
|
|
545
550
|
if (!target) return;
|
|
546
551
|
const escapedPrompt = escapeShellArg(prompt);
|
|
547
|
-
|
|
552
|
+
const worktreeFlag = worktree ? " -w" : "";
|
|
553
|
+
await tmux.sendCommand({ target, command: `claude${worktreeFlag} -- ${escapedPrompt}` });
|
|
548
554
|
},
|
|
549
555
|
list: async () => {
|
|
550
556
|
const panes = await tmux.listPanes();
|
|
@@ -597,7 +603,7 @@ var createUsecases = (context) => ({
|
|
|
597
603
|
// package.json
|
|
598
604
|
var package_default = {
|
|
599
605
|
name: "abmux",
|
|
600
|
-
version: "0.0.
|
|
606
|
+
version: "0.0.8",
|
|
601
607
|
repository: {
|
|
602
608
|
type: "git",
|
|
603
609
|
url: "https://github.com/cut0/abmux.git"
|
|
@@ -667,8 +673,8 @@ import { createElement } from "react";
|
|
|
667
673
|
|
|
668
674
|
// src/components/ManagerView.tsx
|
|
669
675
|
import { basename as basename2 } from "node:path";
|
|
670
|
-
import { Box as Box11 } from "ink";
|
|
671
|
-
import { useCallback as
|
|
676
|
+
import { Box as Box11, useInput as useInput7 } from "ink";
|
|
677
|
+
import { useCallback as useCallback5, useMemo as useMemo7, useRef as useRef3, useState as useState7 } from "react";
|
|
672
678
|
|
|
673
679
|
// src/components/shared/Header.tsx
|
|
674
680
|
import { Box, Text } from "ink";
|
|
@@ -769,10 +775,12 @@ var SessionListPanel = ({
|
|
|
769
775
|
onSelect,
|
|
770
776
|
onCursorChange,
|
|
771
777
|
onDeleteSession,
|
|
772
|
-
onAddSession
|
|
778
|
+
onAddSession,
|
|
779
|
+
initialCursor,
|
|
780
|
+
cursorRef
|
|
773
781
|
}) => {
|
|
774
782
|
const { exit } = useApp();
|
|
775
|
-
const [cursor, setCursor] = useState(0);
|
|
783
|
+
const [cursor, setCursor] = useState(initialCursor ?? 0);
|
|
776
784
|
const sortedSessions = useMemo3(
|
|
777
785
|
() => sortSessions(sessions, currentSession),
|
|
778
786
|
[sessions, currentSession]
|
|
@@ -782,6 +790,7 @@ var SessionListPanel = ({
|
|
|
782
790
|
if (clampedCursor !== cursor) {
|
|
783
791
|
setCursor(clampedCursor);
|
|
784
792
|
}
|
|
793
|
+
if (cursorRef) cursorRef.current = clampedCursor;
|
|
785
794
|
const reservedLines = 1;
|
|
786
795
|
const { scrollOffset, visibleCount } = useScroll(
|
|
787
796
|
clampedCursor,
|
|
@@ -902,16 +911,19 @@ var PaneListView = ({
|
|
|
902
911
|
onUnhighlight,
|
|
903
912
|
onBack,
|
|
904
913
|
onNewSession,
|
|
905
|
-
onKillPane
|
|
914
|
+
onKillPane,
|
|
915
|
+
initialCursor,
|
|
916
|
+
cursorRef
|
|
906
917
|
}) => {
|
|
907
918
|
const { exit } = useApp2();
|
|
908
|
-
const [cursor, setCursor] = useState2(0);
|
|
919
|
+
const [cursor, setCursor] = useState2(initialCursor ?? 0);
|
|
909
920
|
const highlightedRef = useRef(void 0);
|
|
910
921
|
const panes = useMemo4(() => group.tabs.flatMap((t) => t.panes), [group]);
|
|
911
922
|
const clampedCursor = cursor >= panes.length ? Math.max(0, panes.length - 1) : cursor;
|
|
912
923
|
if (clampedCursor !== cursor) {
|
|
913
924
|
setCursor(clampedCursor);
|
|
914
925
|
}
|
|
926
|
+
if (cursorRef) cursorRef.current = clampedCursor;
|
|
915
927
|
const reservedLines = 1;
|
|
916
928
|
const { scrollOffset, visibleCount } = useScroll(
|
|
917
929
|
clampedCursor,
|
|
@@ -1023,7 +1035,9 @@ var PaneListPanel = ({
|
|
|
1023
1035
|
onUnhighlight,
|
|
1024
1036
|
onBack,
|
|
1025
1037
|
onNewSession,
|
|
1026
|
-
onKillPane
|
|
1038
|
+
onKillPane,
|
|
1039
|
+
initialCursor,
|
|
1040
|
+
cursorRef
|
|
1027
1041
|
}) => {
|
|
1028
1042
|
if (!selectedSession) {
|
|
1029
1043
|
return /* @__PURE__ */ jsx6(Box6, { paddingLeft: 1, children: /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "No session selected" }) });
|
|
@@ -1040,7 +1054,9 @@ var PaneListPanel = ({
|
|
|
1040
1054
|
onUnhighlight,
|
|
1041
1055
|
onBack,
|
|
1042
1056
|
onNewSession,
|
|
1043
|
-
onKillPane
|
|
1057
|
+
onKillPane,
|
|
1058
|
+
initialCursor,
|
|
1059
|
+
cursorRef
|
|
1044
1060
|
},
|
|
1045
1061
|
selectedSession
|
|
1046
1062
|
);
|
|
@@ -1058,10 +1074,12 @@ var SessionOverviewPanel = ({
|
|
|
1058
1074
|
isLoading,
|
|
1059
1075
|
isFocused,
|
|
1060
1076
|
availableRows,
|
|
1061
|
-
onBack
|
|
1077
|
+
onBack,
|
|
1078
|
+
initialCursor,
|
|
1079
|
+
cursorRef
|
|
1062
1080
|
}) => {
|
|
1063
1081
|
const { exit } = useApp3();
|
|
1064
|
-
const [cursor, setCursor] = useState3(0);
|
|
1082
|
+
const [cursor, setCursor] = useState3(initialCursor ?? 0);
|
|
1065
1083
|
const lines = useMemo5(() => {
|
|
1066
1084
|
const summaryLines = overallSummary ? [
|
|
1067
1085
|
{ key: "summary", type: "summary", text: overallSummary },
|
|
@@ -1094,9 +1112,7 @@ var SessionOverviewPanel = ({
|
|
|
1094
1112
|
return [...summaryLines, ...sessionLines];
|
|
1095
1113
|
}, [overallSummary, items, groups]);
|
|
1096
1114
|
const clampedCursor = cursor >= lines.length ? Math.max(0, lines.length - 1) : cursor;
|
|
1097
|
-
if (
|
|
1098
|
-
setCursor(clampedCursor);
|
|
1099
|
-
}
|
|
1115
|
+
if (cursorRef) cursorRef.current = clampedCursor;
|
|
1100
1116
|
const reservedLines = 3;
|
|
1101
1117
|
const { scrollOffset, visibleCount } = useScroll(
|
|
1102
1118
|
clampedCursor,
|
|
@@ -1173,6 +1189,7 @@ var SessionOverviewPanel = ({
|
|
|
1173
1189
|
|
|
1174
1190
|
// src/components/ConfirmView.tsx
|
|
1175
1191
|
import { Box as Box8, Text as Text8, useInput as useInput4 } from "ink";
|
|
1192
|
+
import { useCallback as useCallback4, useState as useState5 } from "react";
|
|
1176
1193
|
|
|
1177
1194
|
// src/hooks/use-terminal-size.ts
|
|
1178
1195
|
import { useStdout } from "ink";
|
|
@@ -1202,20 +1219,35 @@ var useTerminalSize = () => {
|
|
|
1202
1219
|
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1203
1220
|
var ConfirmView = ({ selectedDir, prompt, onConfirm, onCancel }) => {
|
|
1204
1221
|
const { rows } = useTerminalSize();
|
|
1222
|
+
const [worktree, setWorktree] = useState5(true);
|
|
1205
1223
|
const previewLines = prompt.split("\n");
|
|
1206
|
-
const maxPreview = Math.min(previewLines.length, rows -
|
|
1224
|
+
const maxPreview = Math.min(previewLines.length, rows - 7);
|
|
1225
|
+
const handleToggleWorktree = useCallback4(() => {
|
|
1226
|
+
setWorktree((prev) => !prev);
|
|
1227
|
+
}, []);
|
|
1207
1228
|
useInput4((_input, key) => {
|
|
1208
1229
|
if (key.return) {
|
|
1209
|
-
onConfirm();
|
|
1230
|
+
onConfirm({ worktree });
|
|
1210
1231
|
return;
|
|
1211
1232
|
}
|
|
1212
1233
|
if (key.escape) {
|
|
1213
1234
|
onCancel();
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1237
|
+
if (key.tab) {
|
|
1238
|
+
handleToggleWorktree();
|
|
1214
1239
|
}
|
|
1215
1240
|
});
|
|
1216
1241
|
return /* @__PURE__ */ jsxs6(Box8, { flexDirection: "column", height: rows, children: [
|
|
1217
1242
|
/* @__PURE__ */ jsx8(Header, { title: `${APP_TITLE} \u2014 ${selectedDir}` }),
|
|
1218
|
-
/* @__PURE__ */
|
|
1243
|
+
/* @__PURE__ */ jsxs6(Box8, { marginBottom: 1, gap: 2, children: [
|
|
1244
|
+
/* @__PURE__ */ jsx8(Text8, { bold: true, children: "New Claude session:" }),
|
|
1245
|
+
/* @__PURE__ */ jsxs6(Text8, { color: worktree ? "green" : "gray", children: [
|
|
1246
|
+
"worktree: [",
|
|
1247
|
+
worktree ? "ON" : "OFF",
|
|
1248
|
+
"]"
|
|
1249
|
+
] })
|
|
1250
|
+
] }),
|
|
1219
1251
|
/* @__PURE__ */ jsxs6(Box8, { flexDirection: "column", flexGrow: 1, overflow: "hidden", paddingLeft: 2, children: [
|
|
1220
1252
|
previewLines.slice(0, maxPreview).map((line, i) => /* @__PURE__ */ jsx8(Text8, { color: "white", children: line }, i)),
|
|
1221
1253
|
previewLines.length > maxPreview && /* @__PURE__ */ jsxs6(Text8, { dimColor: true, children: [
|
|
@@ -1226,6 +1258,7 @@ var ConfirmView = ({ selectedDir, prompt, onConfirm, onCancel }) => {
|
|
|
1226
1258
|
] }),
|
|
1227
1259
|
/* @__PURE__ */ jsxs6(Box8, { gap: 2, children: [
|
|
1228
1260
|
/* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "Enter confirm" }),
|
|
1261
|
+
/* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "Tab worktree" }),
|
|
1229
1262
|
/* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "Esc cancel" })
|
|
1230
1263
|
] })
|
|
1231
1264
|
] });
|
|
@@ -1269,7 +1302,7 @@ var DeleteSessionView = ({ sessionName, paneCount, onConfirm, onCancel }) => {
|
|
|
1269
1302
|
|
|
1270
1303
|
// src/components/DirectorySearchView.tsx
|
|
1271
1304
|
import { Box as Box10, Text as Text10, useInput as useInput6 } from "ink";
|
|
1272
|
-
import { useMemo as useMemo6, useState as
|
|
1305
|
+
import { useMemo as useMemo6, useState as useState6 } from "react";
|
|
1273
1306
|
import { basename } from "node:path";
|
|
1274
1307
|
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1275
1308
|
var formatPath = (path) => {
|
|
@@ -1281,8 +1314,8 @@ var formatPath = (path) => {
|
|
|
1281
1314
|
};
|
|
1282
1315
|
var DirectorySearchView = ({ directories, onSelect, onCancel }) => {
|
|
1283
1316
|
const { rows } = useTerminalSize();
|
|
1284
|
-
const [query, setQuery] =
|
|
1285
|
-
const [cursor, setCursor] =
|
|
1317
|
+
const [query, setQuery] = useState6("");
|
|
1318
|
+
const [cursor, setCursor] = useState6(0);
|
|
1286
1319
|
const filtered = useMemo6(() => {
|
|
1287
1320
|
if (!query) return directories;
|
|
1288
1321
|
const lower = query.toLowerCase();
|
|
@@ -1403,25 +1436,34 @@ var ManagerView = ({
|
|
|
1403
1436
|
directories,
|
|
1404
1437
|
restoredPrompt,
|
|
1405
1438
|
restoredSession,
|
|
1406
|
-
restoredCwd
|
|
1439
|
+
restoredCwd,
|
|
1440
|
+
snapshotRef,
|
|
1441
|
+
restoredState
|
|
1407
1442
|
}) => {
|
|
1408
1443
|
const { rows, columns } = useTerminalSize();
|
|
1409
|
-
const [sessionsState, setSessionsState] =
|
|
1444
|
+
const [sessionsState, setSessionsState] = useState7({
|
|
1410
1445
|
sessions: [],
|
|
1411
1446
|
isLoading: true
|
|
1412
1447
|
});
|
|
1413
|
-
const [mode, setMode] =
|
|
1414
|
-
const [focus, setFocus] =
|
|
1415
|
-
const [selectedSession, setSelectedSession] =
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
const [
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1448
|
+
const [mode, setMode] = useState7(restoredPrompt ? MODE.confirm : MODE.split);
|
|
1449
|
+
const [focus, setFocus] = useState7(restoredState?.focus ?? FOCUS.left);
|
|
1450
|
+
const [selectedSession, setSelectedSession] = useState7(
|
|
1451
|
+
restoredSession ?? restoredState?.selectedSession
|
|
1452
|
+
);
|
|
1453
|
+
const [pendingPrompt, setPendingPrompt] = useState7(restoredPrompt ?? "");
|
|
1454
|
+
const [pendingDeleteSession, setPendingDeleteSession] = useState7(void 0);
|
|
1455
|
+
const [overviewResult, setOverviewResult] = useState7(
|
|
1456
|
+
restoredState?.overviewResult ?? { overallSummary: "", sessions: [] }
|
|
1457
|
+
);
|
|
1458
|
+
const [overviewLoading, setOverviewLoading] = useState7(
|
|
1459
|
+
restoredState?.overviewResult ? false : true
|
|
1460
|
+
);
|
|
1423
1461
|
const overviewInFlightRef = useRef3(false);
|
|
1424
|
-
const
|
|
1462
|
+
const sessionCursorRef = useRef3(restoredState?.sessionListCursor ?? 0);
|
|
1463
|
+
const paneCursorRef = useRef3(restoredState?.paneListCursor ?? 0);
|
|
1464
|
+
const overviewCursorRef = useRef3(restoredState?.overviewCursor ?? 0);
|
|
1465
|
+
const paneRestoredRef = useRef3(false);
|
|
1466
|
+
const refresh = useCallback5(async () => {
|
|
1425
1467
|
try {
|
|
1426
1468
|
const fetched = await actions.fetchSessions();
|
|
1427
1469
|
setSessionsState((prev) => {
|
|
@@ -1440,7 +1482,6 @@ var ManagerView = ({
|
|
|
1440
1482
|
() => {
|
|
1441
1483
|
if (overviewInFlightRef.current) return;
|
|
1442
1484
|
overviewInFlightRef.current = true;
|
|
1443
|
-
setOverviewLoading(true);
|
|
1444
1485
|
void actions.fetchOverview(sessionsState.sessions).then((result) => {
|
|
1445
1486
|
setOverviewResult(result);
|
|
1446
1487
|
}).catch(() => {
|
|
@@ -1452,7 +1493,29 @@ var ManagerView = ({
|
|
|
1452
1493
|
OVERVIEW_POLL_INTERVAL,
|
|
1453
1494
|
!sessionsState.isLoading
|
|
1454
1495
|
);
|
|
1496
|
+
useInput7(
|
|
1497
|
+
(_input, key) => {
|
|
1498
|
+
if (key.tab) {
|
|
1499
|
+
setFocus((prev) => {
|
|
1500
|
+
if (prev === FOCUS.left) return FOCUS.right;
|
|
1501
|
+
if (prev === FOCUS.right) return FOCUS.bottom;
|
|
1502
|
+
return FOCUS.left;
|
|
1503
|
+
});
|
|
1504
|
+
}
|
|
1505
|
+
},
|
|
1506
|
+
{ isActive: mode === MODE.split }
|
|
1507
|
+
);
|
|
1455
1508
|
const resolvedSession = selectedSession ?? sessionsState.sessions[0]?.name;
|
|
1509
|
+
const paneInitialCursor = !paneRestoredRef.current && restoredState?.selectedSession === resolvedSession ? restoredState?.paneListCursor : void 0;
|
|
1510
|
+
if (paneInitialCursor !== void 0) paneRestoredRef.current = true;
|
|
1511
|
+
snapshotRef.current = {
|
|
1512
|
+
focus,
|
|
1513
|
+
selectedSession: resolvedSession,
|
|
1514
|
+
sessionListCursor: sessionCursorRef.current,
|
|
1515
|
+
paneListCursor: paneCursorRef.current,
|
|
1516
|
+
overviewCursor: overviewCursorRef.current,
|
|
1517
|
+
overviewResult
|
|
1518
|
+
};
|
|
1456
1519
|
const selectedManagedSession = useMemo7(
|
|
1457
1520
|
() => sessionsState.sessions.find((s) => s.name === resolvedSession),
|
|
1458
1521
|
[sessionsState.sessions, resolvedSession]
|
|
@@ -1472,14 +1535,15 @@ var ManagerView = ({
|
|
|
1472
1535
|
() => allGroups.flatMap((g) => g.tabs).flatMap((t) => t.panes).filter((p) => p.kind === "claude" && p.claudeStatus).reduce((acc, p) => {
|
|
1473
1536
|
const s = p.claudeStatus;
|
|
1474
1537
|
if (!s) return acc;
|
|
1475
|
-
|
|
1538
|
+
acc[s] = (acc[s] ?? 0) + 1;
|
|
1539
|
+
return acc;
|
|
1476
1540
|
}, {}),
|
|
1477
1541
|
[allGroups]
|
|
1478
1542
|
);
|
|
1479
|
-
const handleOpenAddSession =
|
|
1543
|
+
const handleOpenAddSession = useCallback5(() => {
|
|
1480
1544
|
setMode(MODE.addSession);
|
|
1481
1545
|
}, []);
|
|
1482
|
-
const handleAddSessionSelect =
|
|
1546
|
+
const handleAddSessionSelect = useCallback5((path) => {
|
|
1483
1547
|
const name = basename2(path);
|
|
1484
1548
|
setSessionsState((prev) => {
|
|
1485
1549
|
const exists2 = prev.sessions.some((s) => s.name === name);
|
|
@@ -1492,14 +1556,14 @@ var ManagerView = ({
|
|
|
1492
1556
|
setSelectedSession(name);
|
|
1493
1557
|
setMode(MODE.split);
|
|
1494
1558
|
}, []);
|
|
1495
|
-
const handleCancelAddSession =
|
|
1559
|
+
const handleCancelAddSession = useCallback5(() => {
|
|
1496
1560
|
setMode(MODE.split);
|
|
1497
1561
|
}, []);
|
|
1498
|
-
const handleDeleteSession =
|
|
1562
|
+
const handleDeleteSession = useCallback5((name) => {
|
|
1499
1563
|
setPendingDeleteSession(name);
|
|
1500
1564
|
setMode(MODE.deleteSession);
|
|
1501
1565
|
}, []);
|
|
1502
|
-
const handleConfirmDelete =
|
|
1566
|
+
const handleConfirmDelete = useCallback5(() => {
|
|
1503
1567
|
if (!pendingDeleteSession) return;
|
|
1504
1568
|
const session = sessionsState.sessions.find((s) => s.name === pendingDeleteSession);
|
|
1505
1569
|
setSessionsState((prev) => ({
|
|
@@ -1518,11 +1582,11 @@ var ManagerView = ({
|
|
|
1518
1582
|
setPendingDeleteSession(void 0);
|
|
1519
1583
|
setMode(MODE.split);
|
|
1520
1584
|
}, [pendingDeleteSession, resolvedSession, sessionsState.sessions, actions, refresh]);
|
|
1521
|
-
const handleCancelDelete =
|
|
1585
|
+
const handleCancelDelete = useCallback5(() => {
|
|
1522
1586
|
setPendingDeleteSession(void 0);
|
|
1523
1587
|
setMode(MODE.split);
|
|
1524
1588
|
}, []);
|
|
1525
|
-
const handleNewSession =
|
|
1589
|
+
const handleNewSession = useCallback5(
|
|
1526
1590
|
(sessionName) => {
|
|
1527
1591
|
const cwd = selectedManagedSession?.path;
|
|
1528
1592
|
if (!cwd) return;
|
|
@@ -1530,48 +1594,51 @@ var ManagerView = ({
|
|
|
1530
1594
|
},
|
|
1531
1595
|
[actions, selectedManagedSession]
|
|
1532
1596
|
);
|
|
1533
|
-
const handleConfirmNew =
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1597
|
+
const handleConfirmNew = useCallback5(
|
|
1598
|
+
({ worktree }) => {
|
|
1599
|
+
if (!resolvedSession) return;
|
|
1600
|
+
const cwd = restoredCwd ?? selectedManagedSession?.path;
|
|
1601
|
+
if (!cwd) return;
|
|
1602
|
+
void actions.createSession(resolvedSession, cwd, pendingPrompt, worktree).then(() => void refresh());
|
|
1603
|
+
setPendingPrompt("");
|
|
1604
|
+
setMode(MODE.split);
|
|
1605
|
+
},
|
|
1606
|
+
[resolvedSession, restoredCwd, selectedManagedSession, pendingPrompt, actions, refresh]
|
|
1607
|
+
);
|
|
1608
|
+
const handleCancelConfirm = useCallback5(() => {
|
|
1542
1609
|
setPendingPrompt("");
|
|
1543
1610
|
setMode(MODE.split);
|
|
1544
1611
|
}, []);
|
|
1545
|
-
const handleSessionSelect =
|
|
1612
|
+
const handleSessionSelect = useCallback5((name) => {
|
|
1546
1613
|
setSelectedSession(name);
|
|
1547
1614
|
setFocus(FOCUS.right);
|
|
1548
1615
|
}, []);
|
|
1549
|
-
const handleSessionCursorChange =
|
|
1616
|
+
const handleSessionCursorChange = useCallback5((name) => {
|
|
1550
1617
|
setSelectedSession(name);
|
|
1551
1618
|
}, []);
|
|
1552
|
-
const handleNavigate =
|
|
1619
|
+
const handleNavigate = useCallback5(
|
|
1553
1620
|
(up) => {
|
|
1554
1621
|
void actions.navigateToPane(up);
|
|
1555
1622
|
},
|
|
1556
1623
|
[actions]
|
|
1557
1624
|
);
|
|
1558
|
-
const handleBack =
|
|
1625
|
+
const handleBack = useCallback5(() => {
|
|
1559
1626
|
setFocus(FOCUS.left);
|
|
1560
1627
|
}, []);
|
|
1561
|
-
const handleKillPane =
|
|
1628
|
+
const handleKillPane = useCallback5(
|
|
1562
1629
|
async (paneId) => {
|
|
1563
1630
|
await swallow(() => actions.killPane(paneId));
|
|
1564
1631
|
void refresh();
|
|
1565
1632
|
},
|
|
1566
1633
|
[actions, refresh]
|
|
1567
1634
|
);
|
|
1568
|
-
const handleHighlight =
|
|
1635
|
+
const handleHighlight = useCallback5(
|
|
1569
1636
|
async (up) => {
|
|
1570
1637
|
await swallow(() => actions.highlightWindow(up));
|
|
1571
1638
|
},
|
|
1572
1639
|
[actions]
|
|
1573
1640
|
);
|
|
1574
|
-
const handleUnhighlight =
|
|
1641
|
+
const handleUnhighlight = useCallback5(
|
|
1575
1642
|
async (up) => {
|
|
1576
1643
|
await swallow(() => actions.unhighlightWindow(up));
|
|
1577
1644
|
},
|
|
@@ -1646,7 +1713,9 @@ var ManagerView = ({
|
|
|
1646
1713
|
onSelect: handleSessionSelect,
|
|
1647
1714
|
onCursorChange: handleSessionCursorChange,
|
|
1648
1715
|
onDeleteSession: handleDeleteSession,
|
|
1649
|
-
onAddSession: handleOpenAddSession
|
|
1716
|
+
onAddSession: handleOpenAddSession,
|
|
1717
|
+
initialCursor: restoredState?.sessionListCursor,
|
|
1718
|
+
cursorRef: sessionCursorRef
|
|
1650
1719
|
}
|
|
1651
1720
|
)
|
|
1652
1721
|
}
|
|
@@ -1670,7 +1739,9 @@ var ManagerView = ({
|
|
|
1670
1739
|
onUnhighlight: handleUnhighlight,
|
|
1671
1740
|
onBack: handleBack,
|
|
1672
1741
|
onNewSession: handleNewSession,
|
|
1673
|
-
onKillPane: handleKillPane
|
|
1742
|
+
onKillPane: handleKillPane,
|
|
1743
|
+
initialCursor: paneInitialCursor,
|
|
1744
|
+
cursorRef: paneCursorRef
|
|
1674
1745
|
}
|
|
1675
1746
|
)
|
|
1676
1747
|
}
|
|
@@ -1685,13 +1756,15 @@ var ManagerView = ({
|
|
|
1685
1756
|
isLoading: overviewLoading,
|
|
1686
1757
|
isFocused: focus === FOCUS.bottom,
|
|
1687
1758
|
availableRows: bottomHeight,
|
|
1688
|
-
onBack: handleBack
|
|
1759
|
+
onBack: handleBack,
|
|
1760
|
+
initialCursor: restoredState?.overviewCursor,
|
|
1761
|
+
cursorRef: overviewCursorRef
|
|
1689
1762
|
}
|
|
1690
1763
|
),
|
|
1691
1764
|
/* @__PURE__ */ jsx11(
|
|
1692
1765
|
StatusBar,
|
|
1693
1766
|
{
|
|
1694
|
-
message: focus === FOCUS.left ? "\u2191/\u2193 move Enter/\u2192 select n add d delete q quit" : focus === FOCUS.right ? "\u2191/\u2193 move Enter focus n new d kill Esc/\u2190 back q quit" : "\u2191/\u2193 scroll Esc/\u2190 back q quit",
|
|
1767
|
+
message: focus === FOCUS.left ? "\u2191/\u2193 move Enter/\u2192 select Tab next n add d delete q quit" : focus === FOCUS.right ? "\u2191/\u2193 move Enter focus Tab next n new d kill Esc/\u2190 back q quit" : "\u2191/\u2193 scroll Tab next Esc/\u2190 back q quit",
|
|
1695
1768
|
statusCounts
|
|
1696
1769
|
}
|
|
1697
1770
|
)
|
|
@@ -1705,6 +1778,8 @@ var createTuiCommand = ({ usecases, services, infra }) => async () => {
|
|
|
1705
1778
|
let pendingPrompt;
|
|
1706
1779
|
let pendingSession;
|
|
1707
1780
|
let pendingCwd;
|
|
1781
|
+
const snapshotRef = { current: void 0 };
|
|
1782
|
+
let restoredState;
|
|
1708
1783
|
const actions = {
|
|
1709
1784
|
fetchSessions: async () => {
|
|
1710
1785
|
const result = await usecases.manager.list();
|
|
@@ -1738,8 +1813,8 @@ var createTuiCommand = ({ usecases, services, infra }) => async () => {
|
|
|
1738
1813
|
const groups = sessions.flatMap((s) => s.groups);
|
|
1739
1814
|
return await usecases.manager.fetchOverview(groups);
|
|
1740
1815
|
},
|
|
1741
|
-
createSession: async (sessionName, cwd, prompt) => {
|
|
1742
|
-
await usecases.manager.createSession({ sessionName, cwd, prompt });
|
|
1816
|
+
createSession: async (sessionName, cwd, prompt, worktree) => {
|
|
1817
|
+
await usecases.manager.createSession({ sessionName, cwd, prompt, worktree });
|
|
1743
1818
|
},
|
|
1744
1819
|
killSession: async (sessionName) => {
|
|
1745
1820
|
await usecases.manager.killSession(sessionName);
|
|
@@ -1754,6 +1829,7 @@ var createTuiCommand = ({ usecases, services, infra }) => async () => {
|
|
|
1754
1829
|
await usecases.manager.unhighlightWindow(up);
|
|
1755
1830
|
},
|
|
1756
1831
|
openEditor: (sessionName, cwd) => {
|
|
1832
|
+
restoredState = snapshotRef.current;
|
|
1757
1833
|
instance.unmount();
|
|
1758
1834
|
const prompt = infra.editor.open();
|
|
1759
1835
|
pendingPrompt = prompt;
|
|
@@ -1766,6 +1842,7 @@ var createTuiCommand = ({ usecases, services, infra }) => async () => {
|
|
|
1766
1842
|
const target = `${up.pane.sessionName}:${String(up.pane.windowIndex)}`;
|
|
1767
1843
|
await infra.tmuxCli.selectWindow(target);
|
|
1768
1844
|
await infra.tmuxCli.selectPane(up.pane.paneId);
|
|
1845
|
+
restoredState = snapshotRef.current;
|
|
1769
1846
|
instance.unmount();
|
|
1770
1847
|
await infra.tmuxCli.attachSession(up.pane.sessionName);
|
|
1771
1848
|
instance = renderApp();
|
|
@@ -1775,9 +1852,12 @@ var createTuiCommand = ({ usecases, services, infra }) => async () => {
|
|
|
1775
1852
|
const prompt = pendingPrompt;
|
|
1776
1853
|
const session = pendingSession;
|
|
1777
1854
|
const cwd = pendingCwd;
|
|
1855
|
+
const snapshot = restoredState;
|
|
1778
1856
|
pendingPrompt = void 0;
|
|
1779
1857
|
pendingSession = void 0;
|
|
1780
1858
|
pendingCwd = void 0;
|
|
1859
|
+
restoredState = void 0;
|
|
1860
|
+
snapshotRef.current = void 0;
|
|
1781
1861
|
const rawCwd = process.cwd();
|
|
1782
1862
|
const currentSession = basename3(findMatchingDirectory(rawCwd, directories) ?? rawCwd);
|
|
1783
1863
|
return render(
|
|
@@ -1787,7 +1867,9 @@ var createTuiCommand = ({ usecases, services, infra }) => async () => {
|
|
|
1787
1867
|
directories,
|
|
1788
1868
|
restoredPrompt: prompt,
|
|
1789
1869
|
restoredSession: session,
|
|
1790
|
-
restoredCwd: cwd
|
|
1870
|
+
restoredCwd: cwd,
|
|
1871
|
+
snapshotRef,
|
|
1872
|
+
restoredState: snapshot
|
|
1791
1873
|
}),
|
|
1792
1874
|
{ concurrent: true }
|
|
1793
1875
|
);
|
|
@@ -1803,18 +1885,20 @@ var createNewCommand = ({ usecases }) => async (args) => {
|
|
|
1803
1885
|
const { values, positionals } = parseArgs({
|
|
1804
1886
|
args,
|
|
1805
1887
|
options: {
|
|
1806
|
-
dir: { type: "string" }
|
|
1888
|
+
dir: { type: "string" },
|
|
1889
|
+
worktree: { type: "boolean", default: true }
|
|
1807
1890
|
},
|
|
1808
1891
|
allowPositionals: true
|
|
1809
1892
|
});
|
|
1810
1893
|
const prompt = positionals[0];
|
|
1811
1894
|
if (!prompt) {
|
|
1812
|
-
console.error("Usage: abmux new <prompt> [--dir <path>]");
|
|
1895
|
+
console.error("Usage: abmux new <prompt> [--dir <path>] [--no-worktree]");
|
|
1813
1896
|
process.exit(1);
|
|
1814
1897
|
}
|
|
1815
1898
|
const dir = values.dir ?? process.cwd();
|
|
1816
1899
|
const sessionName = basename4(dir);
|
|
1817
|
-
|
|
1900
|
+
const worktree = values.worktree ?? true;
|
|
1901
|
+
await usecases.manager.createSession({ sessionName, cwd: dir, prompt, worktree });
|
|
1818
1902
|
console.log(`Session "${sessionName}" created.`);
|
|
1819
1903
|
};
|
|
1820
1904
|
|