abmux 0.0.7 → 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 +152 -66
- 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,6 +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;
|
|
1115
|
+
if (cursorRef) cursorRef.current = clampedCursor;
|
|
1097
1116
|
const reservedLines = 3;
|
|
1098
1117
|
const { scrollOffset, visibleCount } = useScroll(
|
|
1099
1118
|
clampedCursor,
|
|
@@ -1170,6 +1189,7 @@ var SessionOverviewPanel = ({
|
|
|
1170
1189
|
|
|
1171
1190
|
// src/components/ConfirmView.tsx
|
|
1172
1191
|
import { Box as Box8, Text as Text8, useInput as useInput4 } from "ink";
|
|
1192
|
+
import { useCallback as useCallback4, useState as useState5 } from "react";
|
|
1173
1193
|
|
|
1174
1194
|
// src/hooks/use-terminal-size.ts
|
|
1175
1195
|
import { useStdout } from "ink";
|
|
@@ -1199,20 +1219,35 @@ var useTerminalSize = () => {
|
|
|
1199
1219
|
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1200
1220
|
var ConfirmView = ({ selectedDir, prompt, onConfirm, onCancel }) => {
|
|
1201
1221
|
const { rows } = useTerminalSize();
|
|
1222
|
+
const [worktree, setWorktree] = useState5(true);
|
|
1202
1223
|
const previewLines = prompt.split("\n");
|
|
1203
|
-
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
|
+
}, []);
|
|
1204
1228
|
useInput4((_input, key) => {
|
|
1205
1229
|
if (key.return) {
|
|
1206
|
-
onConfirm();
|
|
1230
|
+
onConfirm({ worktree });
|
|
1207
1231
|
return;
|
|
1208
1232
|
}
|
|
1209
1233
|
if (key.escape) {
|
|
1210
1234
|
onCancel();
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1237
|
+
if (key.tab) {
|
|
1238
|
+
handleToggleWorktree();
|
|
1211
1239
|
}
|
|
1212
1240
|
});
|
|
1213
1241
|
return /* @__PURE__ */ jsxs6(Box8, { flexDirection: "column", height: rows, children: [
|
|
1214
1242
|
/* @__PURE__ */ jsx8(Header, { title: `${APP_TITLE} \u2014 ${selectedDir}` }),
|
|
1215
|
-
/* @__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
|
+
] }),
|
|
1216
1251
|
/* @__PURE__ */ jsxs6(Box8, { flexDirection: "column", flexGrow: 1, overflow: "hidden", paddingLeft: 2, children: [
|
|
1217
1252
|
previewLines.slice(0, maxPreview).map((line, i) => /* @__PURE__ */ jsx8(Text8, { color: "white", children: line }, i)),
|
|
1218
1253
|
previewLines.length > maxPreview && /* @__PURE__ */ jsxs6(Text8, { dimColor: true, children: [
|
|
@@ -1223,6 +1258,7 @@ var ConfirmView = ({ selectedDir, prompt, onConfirm, onCancel }) => {
|
|
|
1223
1258
|
] }),
|
|
1224
1259
|
/* @__PURE__ */ jsxs6(Box8, { gap: 2, children: [
|
|
1225
1260
|
/* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "Enter confirm" }),
|
|
1261
|
+
/* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "Tab worktree" }),
|
|
1226
1262
|
/* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "Esc cancel" })
|
|
1227
1263
|
] })
|
|
1228
1264
|
] });
|
|
@@ -1266,7 +1302,7 @@ var DeleteSessionView = ({ sessionName, paneCount, onConfirm, onCancel }) => {
|
|
|
1266
1302
|
|
|
1267
1303
|
// src/components/DirectorySearchView.tsx
|
|
1268
1304
|
import { Box as Box10, Text as Text10, useInput as useInput6 } from "ink";
|
|
1269
|
-
import { useMemo as useMemo6, useState as
|
|
1305
|
+
import { useMemo as useMemo6, useState as useState6 } from "react";
|
|
1270
1306
|
import { basename } from "node:path";
|
|
1271
1307
|
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1272
1308
|
var formatPath = (path) => {
|
|
@@ -1278,8 +1314,8 @@ var formatPath = (path) => {
|
|
|
1278
1314
|
};
|
|
1279
1315
|
var DirectorySearchView = ({ directories, onSelect, onCancel }) => {
|
|
1280
1316
|
const { rows } = useTerminalSize();
|
|
1281
|
-
const [query, setQuery] =
|
|
1282
|
-
const [cursor, setCursor] =
|
|
1317
|
+
const [query, setQuery] = useState6("");
|
|
1318
|
+
const [cursor, setCursor] = useState6(0);
|
|
1283
1319
|
const filtered = useMemo6(() => {
|
|
1284
1320
|
if (!query) return directories;
|
|
1285
1321
|
const lower = query.toLowerCase();
|
|
@@ -1400,25 +1436,34 @@ var ManagerView = ({
|
|
|
1400
1436
|
directories,
|
|
1401
1437
|
restoredPrompt,
|
|
1402
1438
|
restoredSession,
|
|
1403
|
-
restoredCwd
|
|
1439
|
+
restoredCwd,
|
|
1440
|
+
snapshotRef,
|
|
1441
|
+
restoredState
|
|
1404
1442
|
}) => {
|
|
1405
1443
|
const { rows, columns } = useTerminalSize();
|
|
1406
|
-
const [sessionsState, setSessionsState] =
|
|
1444
|
+
const [sessionsState, setSessionsState] = useState7({
|
|
1407
1445
|
sessions: [],
|
|
1408
1446
|
isLoading: true
|
|
1409
1447
|
});
|
|
1410
|
-
const [mode, setMode] =
|
|
1411
|
-
const [focus, setFocus] =
|
|
1412
|
-
const [selectedSession, setSelectedSession] =
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
const [
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
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
|
+
);
|
|
1420
1461
|
const overviewInFlightRef = useRef3(false);
|
|
1421
|
-
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 () => {
|
|
1422
1467
|
try {
|
|
1423
1468
|
const fetched = await actions.fetchSessions();
|
|
1424
1469
|
setSessionsState((prev) => {
|
|
@@ -1437,7 +1482,6 @@ var ManagerView = ({
|
|
|
1437
1482
|
() => {
|
|
1438
1483
|
if (overviewInFlightRef.current) return;
|
|
1439
1484
|
overviewInFlightRef.current = true;
|
|
1440
|
-
setOverviewLoading(true);
|
|
1441
1485
|
void actions.fetchOverview(sessionsState.sessions).then((result) => {
|
|
1442
1486
|
setOverviewResult(result);
|
|
1443
1487
|
}).catch(() => {
|
|
@@ -1449,7 +1493,29 @@ var ManagerView = ({
|
|
|
1449
1493
|
OVERVIEW_POLL_INTERVAL,
|
|
1450
1494
|
!sessionsState.isLoading
|
|
1451
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
|
+
);
|
|
1452
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
|
+
};
|
|
1453
1519
|
const selectedManagedSession = useMemo7(
|
|
1454
1520
|
() => sessionsState.sessions.find((s) => s.name === resolvedSession),
|
|
1455
1521
|
[sessionsState.sessions, resolvedSession]
|
|
@@ -1474,10 +1540,10 @@ var ManagerView = ({
|
|
|
1474
1540
|
}, {}),
|
|
1475
1541
|
[allGroups]
|
|
1476
1542
|
);
|
|
1477
|
-
const handleOpenAddSession =
|
|
1543
|
+
const handleOpenAddSession = useCallback5(() => {
|
|
1478
1544
|
setMode(MODE.addSession);
|
|
1479
1545
|
}, []);
|
|
1480
|
-
const handleAddSessionSelect =
|
|
1546
|
+
const handleAddSessionSelect = useCallback5((path) => {
|
|
1481
1547
|
const name = basename2(path);
|
|
1482
1548
|
setSessionsState((prev) => {
|
|
1483
1549
|
const exists2 = prev.sessions.some((s) => s.name === name);
|
|
@@ -1490,14 +1556,14 @@ var ManagerView = ({
|
|
|
1490
1556
|
setSelectedSession(name);
|
|
1491
1557
|
setMode(MODE.split);
|
|
1492
1558
|
}, []);
|
|
1493
|
-
const handleCancelAddSession =
|
|
1559
|
+
const handleCancelAddSession = useCallback5(() => {
|
|
1494
1560
|
setMode(MODE.split);
|
|
1495
1561
|
}, []);
|
|
1496
|
-
const handleDeleteSession =
|
|
1562
|
+
const handleDeleteSession = useCallback5((name) => {
|
|
1497
1563
|
setPendingDeleteSession(name);
|
|
1498
1564
|
setMode(MODE.deleteSession);
|
|
1499
1565
|
}, []);
|
|
1500
|
-
const handleConfirmDelete =
|
|
1566
|
+
const handleConfirmDelete = useCallback5(() => {
|
|
1501
1567
|
if (!pendingDeleteSession) return;
|
|
1502
1568
|
const session = sessionsState.sessions.find((s) => s.name === pendingDeleteSession);
|
|
1503
1569
|
setSessionsState((prev) => ({
|
|
@@ -1516,11 +1582,11 @@ var ManagerView = ({
|
|
|
1516
1582
|
setPendingDeleteSession(void 0);
|
|
1517
1583
|
setMode(MODE.split);
|
|
1518
1584
|
}, [pendingDeleteSession, resolvedSession, sessionsState.sessions, actions, refresh]);
|
|
1519
|
-
const handleCancelDelete =
|
|
1585
|
+
const handleCancelDelete = useCallback5(() => {
|
|
1520
1586
|
setPendingDeleteSession(void 0);
|
|
1521
1587
|
setMode(MODE.split);
|
|
1522
1588
|
}, []);
|
|
1523
|
-
const handleNewSession =
|
|
1589
|
+
const handleNewSession = useCallback5(
|
|
1524
1590
|
(sessionName) => {
|
|
1525
1591
|
const cwd = selectedManagedSession?.path;
|
|
1526
1592
|
if (!cwd) return;
|
|
@@ -1528,48 +1594,51 @@ var ManagerView = ({
|
|
|
1528
1594
|
},
|
|
1529
1595
|
[actions, selectedManagedSession]
|
|
1530
1596
|
);
|
|
1531
|
-
const handleConfirmNew =
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
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(() => {
|
|
1540
1609
|
setPendingPrompt("");
|
|
1541
1610
|
setMode(MODE.split);
|
|
1542
1611
|
}, []);
|
|
1543
|
-
const handleSessionSelect =
|
|
1612
|
+
const handleSessionSelect = useCallback5((name) => {
|
|
1544
1613
|
setSelectedSession(name);
|
|
1545
1614
|
setFocus(FOCUS.right);
|
|
1546
1615
|
}, []);
|
|
1547
|
-
const handleSessionCursorChange =
|
|
1616
|
+
const handleSessionCursorChange = useCallback5((name) => {
|
|
1548
1617
|
setSelectedSession(name);
|
|
1549
1618
|
}, []);
|
|
1550
|
-
const handleNavigate =
|
|
1619
|
+
const handleNavigate = useCallback5(
|
|
1551
1620
|
(up) => {
|
|
1552
1621
|
void actions.navigateToPane(up);
|
|
1553
1622
|
},
|
|
1554
1623
|
[actions]
|
|
1555
1624
|
);
|
|
1556
|
-
const handleBack =
|
|
1625
|
+
const handleBack = useCallback5(() => {
|
|
1557
1626
|
setFocus(FOCUS.left);
|
|
1558
1627
|
}, []);
|
|
1559
|
-
const handleKillPane =
|
|
1628
|
+
const handleKillPane = useCallback5(
|
|
1560
1629
|
async (paneId) => {
|
|
1561
1630
|
await swallow(() => actions.killPane(paneId));
|
|
1562
1631
|
void refresh();
|
|
1563
1632
|
},
|
|
1564
1633
|
[actions, refresh]
|
|
1565
1634
|
);
|
|
1566
|
-
const handleHighlight =
|
|
1635
|
+
const handleHighlight = useCallback5(
|
|
1567
1636
|
async (up) => {
|
|
1568
1637
|
await swallow(() => actions.highlightWindow(up));
|
|
1569
1638
|
},
|
|
1570
1639
|
[actions]
|
|
1571
1640
|
);
|
|
1572
|
-
const handleUnhighlight =
|
|
1641
|
+
const handleUnhighlight = useCallback5(
|
|
1573
1642
|
async (up) => {
|
|
1574
1643
|
await swallow(() => actions.unhighlightWindow(up));
|
|
1575
1644
|
},
|
|
@@ -1644,7 +1713,9 @@ var ManagerView = ({
|
|
|
1644
1713
|
onSelect: handleSessionSelect,
|
|
1645
1714
|
onCursorChange: handleSessionCursorChange,
|
|
1646
1715
|
onDeleteSession: handleDeleteSession,
|
|
1647
|
-
onAddSession: handleOpenAddSession
|
|
1716
|
+
onAddSession: handleOpenAddSession,
|
|
1717
|
+
initialCursor: restoredState?.sessionListCursor,
|
|
1718
|
+
cursorRef: sessionCursorRef
|
|
1648
1719
|
}
|
|
1649
1720
|
)
|
|
1650
1721
|
}
|
|
@@ -1668,7 +1739,9 @@ var ManagerView = ({
|
|
|
1668
1739
|
onUnhighlight: handleUnhighlight,
|
|
1669
1740
|
onBack: handleBack,
|
|
1670
1741
|
onNewSession: handleNewSession,
|
|
1671
|
-
onKillPane: handleKillPane
|
|
1742
|
+
onKillPane: handleKillPane,
|
|
1743
|
+
initialCursor: paneInitialCursor,
|
|
1744
|
+
cursorRef: paneCursorRef
|
|
1672
1745
|
}
|
|
1673
1746
|
)
|
|
1674
1747
|
}
|
|
@@ -1683,13 +1756,15 @@ var ManagerView = ({
|
|
|
1683
1756
|
isLoading: overviewLoading,
|
|
1684
1757
|
isFocused: focus === FOCUS.bottom,
|
|
1685
1758
|
availableRows: bottomHeight,
|
|
1686
|
-
onBack: handleBack
|
|
1759
|
+
onBack: handleBack,
|
|
1760
|
+
initialCursor: restoredState?.overviewCursor,
|
|
1761
|
+
cursorRef: overviewCursorRef
|
|
1687
1762
|
}
|
|
1688
1763
|
),
|
|
1689
1764
|
/* @__PURE__ */ jsx11(
|
|
1690
1765
|
StatusBar,
|
|
1691
1766
|
{
|
|
1692
|
-
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",
|
|
1693
1768
|
statusCounts
|
|
1694
1769
|
}
|
|
1695
1770
|
)
|
|
@@ -1703,6 +1778,8 @@ var createTuiCommand = ({ usecases, services, infra }) => async () => {
|
|
|
1703
1778
|
let pendingPrompt;
|
|
1704
1779
|
let pendingSession;
|
|
1705
1780
|
let pendingCwd;
|
|
1781
|
+
const snapshotRef = { current: void 0 };
|
|
1782
|
+
let restoredState;
|
|
1706
1783
|
const actions = {
|
|
1707
1784
|
fetchSessions: async () => {
|
|
1708
1785
|
const result = await usecases.manager.list();
|
|
@@ -1736,8 +1813,8 @@ var createTuiCommand = ({ usecases, services, infra }) => async () => {
|
|
|
1736
1813
|
const groups = sessions.flatMap((s) => s.groups);
|
|
1737
1814
|
return await usecases.manager.fetchOverview(groups);
|
|
1738
1815
|
},
|
|
1739
|
-
createSession: async (sessionName, cwd, prompt) => {
|
|
1740
|
-
await usecases.manager.createSession({ sessionName, cwd, prompt });
|
|
1816
|
+
createSession: async (sessionName, cwd, prompt, worktree) => {
|
|
1817
|
+
await usecases.manager.createSession({ sessionName, cwd, prompt, worktree });
|
|
1741
1818
|
},
|
|
1742
1819
|
killSession: async (sessionName) => {
|
|
1743
1820
|
await usecases.manager.killSession(sessionName);
|
|
@@ -1752,6 +1829,7 @@ var createTuiCommand = ({ usecases, services, infra }) => async () => {
|
|
|
1752
1829
|
await usecases.manager.unhighlightWindow(up);
|
|
1753
1830
|
},
|
|
1754
1831
|
openEditor: (sessionName, cwd) => {
|
|
1832
|
+
restoredState = snapshotRef.current;
|
|
1755
1833
|
instance.unmount();
|
|
1756
1834
|
const prompt = infra.editor.open();
|
|
1757
1835
|
pendingPrompt = prompt;
|
|
@@ -1764,6 +1842,7 @@ var createTuiCommand = ({ usecases, services, infra }) => async () => {
|
|
|
1764
1842
|
const target = `${up.pane.sessionName}:${String(up.pane.windowIndex)}`;
|
|
1765
1843
|
await infra.tmuxCli.selectWindow(target);
|
|
1766
1844
|
await infra.tmuxCli.selectPane(up.pane.paneId);
|
|
1845
|
+
restoredState = snapshotRef.current;
|
|
1767
1846
|
instance.unmount();
|
|
1768
1847
|
await infra.tmuxCli.attachSession(up.pane.sessionName);
|
|
1769
1848
|
instance = renderApp();
|
|
@@ -1773,9 +1852,12 @@ var createTuiCommand = ({ usecases, services, infra }) => async () => {
|
|
|
1773
1852
|
const prompt = pendingPrompt;
|
|
1774
1853
|
const session = pendingSession;
|
|
1775
1854
|
const cwd = pendingCwd;
|
|
1855
|
+
const snapshot = restoredState;
|
|
1776
1856
|
pendingPrompt = void 0;
|
|
1777
1857
|
pendingSession = void 0;
|
|
1778
1858
|
pendingCwd = void 0;
|
|
1859
|
+
restoredState = void 0;
|
|
1860
|
+
snapshotRef.current = void 0;
|
|
1779
1861
|
const rawCwd = process.cwd();
|
|
1780
1862
|
const currentSession = basename3(findMatchingDirectory(rawCwd, directories) ?? rawCwd);
|
|
1781
1863
|
return render(
|
|
@@ -1785,7 +1867,9 @@ var createTuiCommand = ({ usecases, services, infra }) => async () => {
|
|
|
1785
1867
|
directories,
|
|
1786
1868
|
restoredPrompt: prompt,
|
|
1787
1869
|
restoredSession: session,
|
|
1788
|
-
restoredCwd: cwd
|
|
1870
|
+
restoredCwd: cwd,
|
|
1871
|
+
snapshotRef,
|
|
1872
|
+
restoredState: snapshot
|
|
1789
1873
|
}),
|
|
1790
1874
|
{ concurrent: true }
|
|
1791
1875
|
);
|
|
@@ -1801,18 +1885,20 @@ var createNewCommand = ({ usecases }) => async (args) => {
|
|
|
1801
1885
|
const { values, positionals } = parseArgs({
|
|
1802
1886
|
args,
|
|
1803
1887
|
options: {
|
|
1804
|
-
dir: { type: "string" }
|
|
1888
|
+
dir: { type: "string" },
|
|
1889
|
+
worktree: { type: "boolean", default: true }
|
|
1805
1890
|
},
|
|
1806
1891
|
allowPositionals: true
|
|
1807
1892
|
});
|
|
1808
1893
|
const prompt = positionals[0];
|
|
1809
1894
|
if (!prompt) {
|
|
1810
|
-
console.error("Usage: abmux new <prompt> [--dir <path>]");
|
|
1895
|
+
console.error("Usage: abmux new <prompt> [--dir <path>] [--no-worktree]");
|
|
1811
1896
|
process.exit(1);
|
|
1812
1897
|
}
|
|
1813
1898
|
const dir = values.dir ?? process.cwd();
|
|
1814
1899
|
const sessionName = basename4(dir);
|
|
1815
|
-
|
|
1900
|
+
const worktree = values.worktree ?? true;
|
|
1901
|
+
await usecases.manager.createSession({ sessionName, cwd: dir, prompt, worktree });
|
|
1816
1902
|
console.log(`Session "${sessionName}" created.`);
|
|
1817
1903
|
};
|
|
1818
1904
|
|