@ogpoyraz/wtx 0.8.0 → 0.8.1
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.mjs +272 -64
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -15331,6 +15331,11 @@ function verbose(message, isVerbose) {
|
|
|
15331
15331
|
function indented(message) {
|
|
15332
15332
|
console.log(` ${message}`);
|
|
15333
15333
|
}
|
|
15334
|
+
function terminalLink(url2, text = url2, stream = process.stdout) {
|
|
15335
|
+
if (!stream.isTTY)
|
|
15336
|
+
return text;
|
|
15337
|
+
return `\x1B]8;;${url2}\x1B\\${text}\x1B]8;;\x1B\\`;
|
|
15338
|
+
}
|
|
15334
15339
|
var c, quietMode = false;
|
|
15335
15340
|
var init_log = __esm(() => {
|
|
15336
15341
|
init_source();
|
|
@@ -25410,6 +25415,28 @@ function sortRowsHierarchically(rows) {
|
|
|
25410
25415
|
function sortBlocks(blocks) {
|
|
25411
25416
|
return [...blocks].sort((a2, b) => a2.repoName.localeCompare(b.repoName));
|
|
25412
25417
|
}
|
|
25418
|
+
function wrapText(text, width) {
|
|
25419
|
+
const lines = [];
|
|
25420
|
+
for (const paragraph of text.split(`
|
|
25421
|
+
`)) {
|
|
25422
|
+
let current = "";
|
|
25423
|
+
for (const word of paragraph.split(/\s+/).filter(Boolean)) {
|
|
25424
|
+
if (!current) {
|
|
25425
|
+
current = word;
|
|
25426
|
+
} else if (current.length + 1 + word.length <= width) {
|
|
25427
|
+
current += ` ${word}`;
|
|
25428
|
+
} else {
|
|
25429
|
+
lines.push(current);
|
|
25430
|
+
current = word;
|
|
25431
|
+
}
|
|
25432
|
+
}
|
|
25433
|
+
lines.push(current);
|
|
25434
|
+
}
|
|
25435
|
+
return lines;
|
|
25436
|
+
}
|
|
25437
|
+
function isTapWithoutDrag(down, up) {
|
|
25438
|
+
return Math.abs(up.x - down.x) <= 1 && Math.abs(up.y - down.y) <= 1;
|
|
25439
|
+
}
|
|
25413
25440
|
function mergeBlocks(prev, next, scope) {
|
|
25414
25441
|
if (!scope)
|
|
25415
25442
|
return sortBlocks(next);
|
|
@@ -25568,9 +25595,91 @@ var init_theme = __esm(() => {
|
|
|
25568
25595
|
};
|
|
25569
25596
|
});
|
|
25570
25597
|
|
|
25598
|
+
// src/tui/hooks/use-tap.ts
|
|
25599
|
+
import { useRef as useRef2, useCallback as useCallback2 } from "react";
|
|
25600
|
+
function useTapHandler(onTap) {
|
|
25601
|
+
const down = useRef2(null);
|
|
25602
|
+
const onMouseDown = useCallback2((e) => {
|
|
25603
|
+
down.current = { x: e.x, y: e.y };
|
|
25604
|
+
}, []);
|
|
25605
|
+
const onMouseUp = useCallback2((e) => {
|
|
25606
|
+
const start = down.current;
|
|
25607
|
+
down.current = null;
|
|
25608
|
+
if (!start || !isTapWithoutDrag(start, e))
|
|
25609
|
+
return;
|
|
25610
|
+
onTap();
|
|
25611
|
+
}, [onTap]);
|
|
25612
|
+
return { onMouseDown, onMouseUp };
|
|
25613
|
+
}
|
|
25614
|
+
var init_use_tap = __esm(() => {
|
|
25615
|
+
init_utils();
|
|
25616
|
+
});
|
|
25617
|
+
|
|
25618
|
+
// src/tui/platform.ts
|
|
25619
|
+
function clipboardCandidatesFor(platform2, env2 = process.env) {
|
|
25620
|
+
if (platform2 === "darwin")
|
|
25621
|
+
return [{ cmd: "pbcopy", args: [] }];
|
|
25622
|
+
if (platform2 === "win32")
|
|
25623
|
+
return [{ cmd: "clip", args: [] }];
|
|
25624
|
+
const candidates = [];
|
|
25625
|
+
if (env2.WAYLAND_DISPLAY)
|
|
25626
|
+
candidates.push({ cmd: "wl-copy", args: [] });
|
|
25627
|
+
if (env2.DISPLAY) {
|
|
25628
|
+
candidates.push({ cmd: "xclip", args: ["-selection", "clipboard"] });
|
|
25629
|
+
candidates.push({ cmd: "xsel", args: ["--clipboard", "--input"] });
|
|
25630
|
+
}
|
|
25631
|
+
return candidates;
|
|
25632
|
+
}
|
|
25633
|
+
async function copyTextToClipboard(renderer, text) {
|
|
25634
|
+
if (!text)
|
|
25635
|
+
return false;
|
|
25636
|
+
const viaTerminal = renderer.copyToClipboardOSC52(text);
|
|
25637
|
+
let viaSystem = false;
|
|
25638
|
+
for (const candidate of clipboardCandidatesFor(process.platform)) {
|
|
25639
|
+
try {
|
|
25640
|
+
const proc = Bun.spawn([candidate.cmd, ...candidate.args], {
|
|
25641
|
+
stdin: "pipe",
|
|
25642
|
+
stdout: "ignore",
|
|
25643
|
+
stderr: "ignore"
|
|
25644
|
+
});
|
|
25645
|
+
proc.stdin.write(text);
|
|
25646
|
+
proc.stdin.end();
|
|
25647
|
+
if (await proc.exited === 0) {
|
|
25648
|
+
viaSystem = true;
|
|
25649
|
+
break;
|
|
25650
|
+
}
|
|
25651
|
+
} catch {}
|
|
25652
|
+
}
|
|
25653
|
+
return viaSystem || viaTerminal;
|
|
25654
|
+
}
|
|
25655
|
+
function browserCommandFor(platform2, url2) {
|
|
25656
|
+
if (!/^https?:\/\//.test(url2))
|
|
25657
|
+
return null;
|
|
25658
|
+
if (platform2 === "darwin")
|
|
25659
|
+
return { cmd: "open", args: [url2] };
|
|
25660
|
+
if (platform2 === "win32")
|
|
25661
|
+
return { cmd: "cmd", args: ["/c", "start", "", url2] };
|
|
25662
|
+
return { cmd: "xdg-open", args: [url2] };
|
|
25663
|
+
}
|
|
25664
|
+
async function openInBrowser(url2) {
|
|
25665
|
+
const command = browserCommandFor(process.platform, url2);
|
|
25666
|
+
if (!command)
|
|
25667
|
+
return false;
|
|
25668
|
+
try {
|
|
25669
|
+
const proc = Bun.spawn([command.cmd, ...command.args], {
|
|
25670
|
+
stdin: "ignore",
|
|
25671
|
+
stdout: "ignore",
|
|
25672
|
+
stderr: "ignore"
|
|
25673
|
+
});
|
|
25674
|
+
return await proc.exited === 0;
|
|
25675
|
+
} catch {
|
|
25676
|
+
return false;
|
|
25677
|
+
}
|
|
25678
|
+
}
|
|
25679
|
+
|
|
25571
25680
|
// src/tui/components/WorktreeTable.tsx
|
|
25572
|
-
import { useEffect as useEffect2, useRef as
|
|
25573
|
-
import { jsx, jsxs } from "@opentui/react/jsx-runtime";
|
|
25681
|
+
import { useEffect as useEffect2, useRef as useRef3 } from "react";
|
|
25682
|
+
import { jsx, jsxs, Fragment } from "@opentui/react/jsx-runtime";
|
|
25574
25683
|
function statusBadge(row) {
|
|
25575
25684
|
if (row.isMainCheckout)
|
|
25576
25685
|
return { text: "[main]", fg: tokens.accent };
|
|
@@ -25585,15 +25694,14 @@ function statusBadge(row) {
|
|
|
25585
25694
|
return { text: "clean", fg: tokens.dim };
|
|
25586
25695
|
}
|
|
25587
25696
|
function WorktreeItem({ row, isSelected, isMultiSelected, indicator, frame, id }) {
|
|
25697
|
+
const prTap = useTapHandler(() => {
|
|
25698
|
+
if (row.prUrl)
|
|
25699
|
+
openInBrowser(row.prUrl);
|
|
25700
|
+
});
|
|
25588
25701
|
const badge = indicator ? indicator.running ? { text: `${frame} ${indicator.verb}…`, fg: tokens.accent } : { text: `◌ ${indicator.verb}`, fg: tokens.dim } : row.isPendingCreate ? { text: `${frame} creating…`, fg: tokens.accent } : statusBadge(row);
|
|
25589
25702
|
const disabled = indicator !== undefined || row.isPendingCreate === true;
|
|
25590
25703
|
const primary = isSelected ? tokens.bright : disabled ? tokens.dim : tokens.fg;
|
|
25591
25704
|
const divergence = row.ahead !== null && row.behind !== null && (row.ahead > 0 || row.behind > 0) ? ` · ↑${row.ahead} ↓${row.behind}` : "";
|
|
25592
|
-
const prSegment = row.prNumber ? [
|
|
25593
|
-
`· #${row.prNumber}`,
|
|
25594
|
-
row.prState ?? "",
|
|
25595
|
-
row.prChecks ? `(${row.prChecks})` : ""
|
|
25596
|
-
].filter(Boolean).join(" ") : "";
|
|
25597
25705
|
const ownerSegment = row.owner ? ` · by ${row.owner}` : "";
|
|
25598
25706
|
const baseSegment = row.base ? ` · base ${row.base}` : "";
|
|
25599
25707
|
const rebaseSegment = !row.isMainCheckout && row.rebaseStatus && !row.isPrunable ? ` · ${row.rebaseStatus}` : "";
|
|
@@ -25603,7 +25711,6 @@ function WorktreeItem({ row, isSelected, isMultiSelected, indicator, frame, id }
|
|
|
25603
25711
|
const secondary = [
|
|
25604
25712
|
`${secondaryIndent}${row.commitShort}`,
|
|
25605
25713
|
divergence,
|
|
25606
|
-
prSegment,
|
|
25607
25714
|
ownerSegment,
|
|
25608
25715
|
baseSegment
|
|
25609
25716
|
].filter(Boolean).join(" ").trimEnd();
|
|
@@ -25638,11 +25745,36 @@ function WorktreeItem({ row, isSelected, isMultiSelected, indicator, frame, id }
|
|
|
25638
25745
|
]
|
|
25639
25746
|
}),
|
|
25640
25747
|
/* @__PURE__ */ jsxs("text", {
|
|
25748
|
+
...row.prUrl ? prTap : {},
|
|
25641
25749
|
children: [
|
|
25642
25750
|
/* @__PURE__ */ jsx("span", {
|
|
25643
25751
|
fg: tokens.dim,
|
|
25644
25752
|
children: secondary
|
|
25645
25753
|
}),
|
|
25754
|
+
row.prNumber !== null && /* @__PURE__ */ jsxs(Fragment, {
|
|
25755
|
+
children: [
|
|
25756
|
+
/* @__PURE__ */ jsx("span", {
|
|
25757
|
+
fg: tokens.dim,
|
|
25758
|
+
children: secondary ? " · " : ""
|
|
25759
|
+
}),
|
|
25760
|
+
/* @__PURE__ */ jsx("span", {
|
|
25761
|
+
fg: tokens.accent,
|
|
25762
|
+
children: `#${row.prNumber}`
|
|
25763
|
+
}),
|
|
25764
|
+
row.prState && /* @__PURE__ */ jsx("span", {
|
|
25765
|
+
fg: tokens.dim,
|
|
25766
|
+
children: ` ${row.prState}`
|
|
25767
|
+
}),
|
|
25768
|
+
row.prChecks && /* @__PURE__ */ jsx("span", {
|
|
25769
|
+
fg: tokens.dim,
|
|
25770
|
+
children: ` (${row.prChecks})`
|
|
25771
|
+
}),
|
|
25772
|
+
row.prUrl && /* @__PURE__ */ jsx("span", {
|
|
25773
|
+
fg: tokens.dim,
|
|
25774
|
+
children: " ↗"
|
|
25775
|
+
})
|
|
25776
|
+
]
|
|
25777
|
+
}),
|
|
25646
25778
|
baseChangedSegment && /* @__PURE__ */ jsx("span", {
|
|
25647
25779
|
fg: tokens.warning,
|
|
25648
25780
|
children: baseChangedSegment
|
|
@@ -25657,7 +25789,7 @@ function WorktreeItem({ row, isSelected, isMultiSelected, indicator, frame, id }
|
|
|
25657
25789
|
});
|
|
25658
25790
|
}
|
|
25659
25791
|
function WorktreeTable({ blocks, selectedIndex, selection = new Set, frame, repoVerbs, rowVerbs }) {
|
|
25660
|
-
const scrollRef =
|
|
25792
|
+
const scrollRef = useRef3(null);
|
|
25661
25793
|
useEffect2(() => {
|
|
25662
25794
|
if (scrollRef.current?.scrollChildIntoView) {
|
|
25663
25795
|
scrollRef.current.scrollChildIntoView("selected-row");
|
|
@@ -25727,11 +25859,16 @@ function WorktreeTable({ blocks, selectedIndex, selection = new Set, frame, repo
|
|
|
25727
25859
|
var SECONDARY_INDENT = " ";
|
|
25728
25860
|
var init_WorktreeTable = __esm(() => {
|
|
25729
25861
|
init_theme();
|
|
25862
|
+
init_use_tap();
|
|
25730
25863
|
});
|
|
25731
25864
|
|
|
25732
25865
|
// src/tui/components/DetailPane.tsx
|
|
25733
|
-
import { jsx as jsx2, jsxs as jsxs2, Fragment } from "@opentui/react/jsx-runtime";
|
|
25866
|
+
import { jsx as jsx2, jsxs as jsxs2, Fragment as Fragment2 } from "@opentui/react/jsx-runtime";
|
|
25734
25867
|
function DetailPane({ selectedRow }) {
|
|
25868
|
+
const prTap = useTapHandler(() => {
|
|
25869
|
+
if (selectedRow?.prUrl)
|
|
25870
|
+
openInBrowser(selectedRow.prUrl);
|
|
25871
|
+
});
|
|
25735
25872
|
if (!selectedRow) {
|
|
25736
25873
|
return /* @__PURE__ */ jsx2("box", {
|
|
25737
25874
|
id: "detail-pane",
|
|
@@ -25946,7 +26083,7 @@ function DetailPane({ selectedRow }) {
|
|
|
25946
26083
|
})
|
|
25947
26084
|
]
|
|
25948
26085
|
}),
|
|
25949
|
-
prNumber !== null && /* @__PURE__ */ jsxs2(
|
|
26086
|
+
prNumber !== null && /* @__PURE__ */ jsxs2(Fragment2, {
|
|
25950
26087
|
children: [
|
|
25951
26088
|
/* @__PURE__ */ jsxs2("text", {
|
|
25952
26089
|
style: { marginTop: 1 },
|
|
@@ -25983,20 +26120,25 @@ function DetailPane({ selectedRow }) {
|
|
|
25983
26120
|
})
|
|
25984
26121
|
]
|
|
25985
26122
|
}),
|
|
25986
|
-
prUrl && /* @__PURE__ */
|
|
25987
|
-
|
|
25988
|
-
|
|
25989
|
-
|
|
25990
|
-
|
|
25991
|
-
|
|
25992
|
-
|
|
25993
|
-
|
|
25994
|
-
|
|
25995
|
-
|
|
25996
|
-
|
|
25997
|
-
|
|
25998
|
-
|
|
25999
|
-
|
|
26123
|
+
prUrl && /* @__PURE__ */ jsx2("box", {
|
|
26124
|
+
...prTap,
|
|
26125
|
+
children: /* @__PURE__ */ jsxs2("text", {
|
|
26126
|
+
selectable: false,
|
|
26127
|
+
children: [
|
|
26128
|
+
/* @__PURE__ */ jsx2("span", {
|
|
26129
|
+
fg: tokens.dim,
|
|
26130
|
+
children: "URL:"
|
|
26131
|
+
}),
|
|
26132
|
+
/* @__PURE__ */ jsx2("span", {
|
|
26133
|
+
fg: tokens.accent,
|
|
26134
|
+
children: ` ${prUrl}`
|
|
26135
|
+
}),
|
|
26136
|
+
/* @__PURE__ */ jsx2("span", {
|
|
26137
|
+
fg: tokens.dim,
|
|
26138
|
+
children: " ↗ click"
|
|
26139
|
+
})
|
|
26140
|
+
]
|
|
26141
|
+
})
|
|
26000
26142
|
})
|
|
26001
26143
|
]
|
|
26002
26144
|
}),
|
|
@@ -26037,7 +26179,7 @@ function DetailPane({ selectedRow }) {
|
|
|
26037
26179
|
fg: tokens.dim,
|
|
26038
26180
|
children: "Actions:"
|
|
26039
26181
|
}),
|
|
26040
|
-
!isMainCheckout && /* @__PURE__ */ jsxs2(
|
|
26182
|
+
!isMainCheckout && /* @__PURE__ */ jsxs2(Fragment2, {
|
|
26041
26183
|
children: [
|
|
26042
26184
|
/* @__PURE__ */ jsxs2("text", {
|
|
26043
26185
|
fg: tokens.dim,
|
|
@@ -26068,6 +26210,7 @@ function DetailPane({ selectedRow }) {
|
|
|
26068
26210
|
}
|
|
26069
26211
|
var init_DetailPane = __esm(() => {
|
|
26070
26212
|
init_theme();
|
|
26213
|
+
init_use_tap();
|
|
26071
26214
|
});
|
|
26072
26215
|
|
|
26073
26216
|
// src/tui/components/Footer.tsx
|
|
@@ -26114,11 +26257,15 @@ function Footer({ loading, lastRefreshed, errorCount, message, busyText, spinner
|
|
|
26114
26257
|
]
|
|
26115
26258
|
}) : null,
|
|
26116
26259
|
errorCount > 0 ? /* @__PURE__ */ jsxs3("text", {
|
|
26117
|
-
fg: tokens.error,
|
|
26118
26260
|
children: [
|
|
26119
|
-
|
|
26120
|
-
|
|
26121
|
-
|
|
26261
|
+
/* @__PURE__ */ jsx3("span", {
|
|
26262
|
+
fg: tokens.error,
|
|
26263
|
+
children: `${errorCount} error${errorCount !== 1 ? "s" : ""}`
|
|
26264
|
+
}),
|
|
26265
|
+
/* @__PURE__ */ jsx3("span", {
|
|
26266
|
+
fg: tokens.dim,
|
|
26267
|
+
children: " · e view"
|
|
26268
|
+
})
|
|
26122
26269
|
]
|
|
26123
26270
|
}) : null,
|
|
26124
26271
|
/* @__PURE__ */ jsx3("text", {
|
|
@@ -26238,8 +26385,11 @@ var init_HelpOverlay = __esm(() => {
|
|
|
26238
26385
|
["o", "Open selected in IDE"],
|
|
26239
26386
|
["a", "Spawn agent in selected"],
|
|
26240
26387
|
["d", "Remove selected worktree(s)"],
|
|
26388
|
+
["e", "View data warnings (when count > 0)"],
|
|
26241
26389
|
["r", "Refresh data"],
|
|
26242
26390
|
["H", "Action history"],
|
|
26391
|
+
["cmd+c / ctrl+shift+c", "Copy selected text to clipboard"],
|
|
26392
|
+
["click PR #/URL", "Open pull request in browser"],
|
|
26243
26393
|
["?", "Toggle help"],
|
|
26244
26394
|
["q/esc", "Quit"]
|
|
26245
26395
|
];
|
|
@@ -26695,7 +26845,7 @@ var init_ChoiceModal = __esm(() => {
|
|
|
26695
26845
|
// src/tui/components/ConfigOverlay.tsx
|
|
26696
26846
|
import { useState as useState5, useEffect as useEffect4 } from "react";
|
|
26697
26847
|
import { useKeyboard as useKeyboard2 } from "@opentui/react";
|
|
26698
|
-
import { jsx as jsx11, jsxs as jsxs10, Fragment as
|
|
26848
|
+
import { jsx as jsx11, jsxs as jsxs10, Fragment as Fragment3 } from "@opentui/react/jsx-runtime";
|
|
26699
26849
|
function ConfigOverlay({ onClose, onSaved, onError }) {
|
|
26700
26850
|
const [config2, setConfig] = useState5(null);
|
|
26701
26851
|
const [viewState, setViewState] = useState5({ type: "main" });
|
|
@@ -26958,7 +27108,7 @@ function ConfigOverlay({ onClose, onSaved, onError }) {
|
|
|
26958
27108
|
hint = "Remove this repository from config";
|
|
26959
27109
|
}
|
|
26960
27110
|
}
|
|
26961
|
-
return /* @__PURE__ */ jsxs10(
|
|
27111
|
+
return /* @__PURE__ */ jsxs10(Fragment3, {
|
|
26962
27112
|
children: [
|
|
26963
27113
|
/* @__PURE__ */ jsx11(Overlay, {
|
|
26964
27114
|
title: "Configuration",
|
|
@@ -27065,6 +27215,47 @@ var init_ConfigOverlay = __esm(() => {
|
|
|
27065
27215
|
init_ConfirmModal();
|
|
27066
27216
|
});
|
|
27067
27217
|
|
|
27218
|
+
// src/tui/components/WarningsOverlay.tsx
|
|
27219
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "@opentui/react/jsx-runtime";
|
|
27220
|
+
function WarningsOverlay({ warnings }) {
|
|
27221
|
+
return /* @__PURE__ */ jsxs11(Overlay, {
|
|
27222
|
+
title: `Warnings (${warnings.length})`,
|
|
27223
|
+
borderColor: tokens.warning,
|
|
27224
|
+
children: [
|
|
27225
|
+
/* @__PURE__ */ jsx12("box", {
|
|
27226
|
+
flexDirection: "column",
|
|
27227
|
+
style: { maxHeight: 30 },
|
|
27228
|
+
children: /* @__PURE__ */ jsx12("scrollbox", {
|
|
27229
|
+
flexGrow: 1,
|
|
27230
|
+
children: warnings.map((warning, i2) => /* @__PURE__ */ jsxs11("box", {
|
|
27231
|
+
flexDirection: "column",
|
|
27232
|
+
style: { marginBottom: 1 },
|
|
27233
|
+
children: [
|
|
27234
|
+
/* @__PURE__ */ jsx12("text", {
|
|
27235
|
+
fg: tokens.warning,
|
|
27236
|
+
children: `⚠ ${warning.repoName}`
|
|
27237
|
+
}),
|
|
27238
|
+
wrapText(warning.message, 56).map((line, j) => /* @__PURE__ */ jsx12("text", {
|
|
27239
|
+
fg: tokens.fg,
|
|
27240
|
+
children: ` ${line}`
|
|
27241
|
+
}, j))
|
|
27242
|
+
]
|
|
27243
|
+
}, i2))
|
|
27244
|
+
})
|
|
27245
|
+
}),
|
|
27246
|
+
/* @__PURE__ */ jsx12("text", {
|
|
27247
|
+
style: { marginTop: 1, fg: tokens.dim },
|
|
27248
|
+
children: "Press any key to close"
|
|
27249
|
+
})
|
|
27250
|
+
]
|
|
27251
|
+
});
|
|
27252
|
+
}
|
|
27253
|
+
var init_WarningsOverlay = __esm(() => {
|
|
27254
|
+
init_Overlay();
|
|
27255
|
+
init_theme();
|
|
27256
|
+
init_utils();
|
|
27257
|
+
});
|
|
27258
|
+
|
|
27068
27259
|
// src/tui/hooks/useSpinnerFrame.ts
|
|
27069
27260
|
import { useEffect as useEffect5, useState as useState6 } from "react";
|
|
27070
27261
|
function useSpinnerFrame(active) {
|
|
@@ -27083,9 +27274,9 @@ var init_useSpinnerFrame = __esm(() => {
|
|
|
27083
27274
|
});
|
|
27084
27275
|
|
|
27085
27276
|
// src/tui/components/App.tsx
|
|
27086
|
-
import { useState as useState7, useEffect as useEffect6, useMemo, useRef as
|
|
27277
|
+
import { useState as useState7, useEffect as useEffect6, useMemo, useRef as useRef4, useCallback as useCallback3 } from "react";
|
|
27087
27278
|
import { useKeyboard as useKeyboard3, useRenderer } from "@opentui/react";
|
|
27088
|
-
import { jsx as
|
|
27279
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "@opentui/react/jsx-runtime";
|
|
27089
27280
|
function getWorktreePathFor(repoName, branch) {
|
|
27090
27281
|
try {
|
|
27091
27282
|
const config2 = loadConfig();
|
|
@@ -27101,10 +27292,10 @@ function App({ opts }) {
|
|
|
27101
27292
|
const [selectedIndex, setSelectedIndex] = useState7(0);
|
|
27102
27293
|
const [modal, setModal] = useState7({ type: "none" });
|
|
27103
27294
|
const [actionMessage, setActionMessage] = useState7();
|
|
27104
|
-
const messageTimer =
|
|
27295
|
+
const messageTimer = useRef4(null);
|
|
27105
27296
|
const [ops, setOps] = useState7([]);
|
|
27106
27297
|
const [failedLogs, setFailedLogs] = useState7([]);
|
|
27107
|
-
const nextOpId =
|
|
27298
|
+
const nextOpId = useRef4(1);
|
|
27108
27299
|
const [createModal, setCreateModal] = useState7(false);
|
|
27109
27300
|
const [createError, setCreateError] = useState7();
|
|
27110
27301
|
const [createBaseModal, setCreateBaseModal] = useState7(null);
|
|
@@ -27117,7 +27308,7 @@ function App({ opts }) {
|
|
|
27117
27308
|
const [filterText, setFilterText] = useState7("");
|
|
27118
27309
|
const [isFiltering, setIsFiltering] = useState7(false);
|
|
27119
27310
|
const [selection, setSelection] = useState7(new Set);
|
|
27120
|
-
const doRefresh =
|
|
27311
|
+
const doRefresh = useCallback3(async (scope) => {
|
|
27121
27312
|
const targets = scope ?? [
|
|
27122
27313
|
...new Set([...blocks.map((b) => b.repoName), ...pendingRepos])
|
|
27123
27314
|
];
|
|
@@ -27133,7 +27324,7 @@ function App({ opts }) {
|
|
|
27133
27324
|
setModal({ type: "error", message: error52 });
|
|
27134
27325
|
}
|
|
27135
27326
|
}, [error52]);
|
|
27136
|
-
const flash =
|
|
27327
|
+
const flash = useCallback3((message, ms = 3000) => {
|
|
27137
27328
|
if (messageTimer.current)
|
|
27138
27329
|
clearTimeout(messageTimer.current);
|
|
27139
27330
|
setActionMessage(message);
|
|
@@ -27324,7 +27515,7 @@ function App({ opts }) {
|
|
|
27324
27515
|
return;
|
|
27325
27516
|
}
|
|
27326
27517
|
if (modal.type !== "none") {
|
|
27327
|
-
if (modal.type === "error" || modal.type === "help" || modal.type === "history") {
|
|
27518
|
+
if (modal.type === "error" || modal.type === "help" || modal.type === "history" || modal.type === "warnings") {
|
|
27328
27519
|
setModal({ type: "none" });
|
|
27329
27520
|
if (modal.type === "error" && error52) {
|
|
27330
27521
|
renderer.destroy();
|
|
@@ -27372,6 +27563,15 @@ function App({ opts }) {
|
|
|
27372
27563
|
return;
|
|
27373
27564
|
}
|
|
27374
27565
|
}
|
|
27566
|
+
if ((key.super || key.meta || key.ctrl && key.shift) && key.name === "c") {
|
|
27567
|
+
const text = renderer.getSelection()?.getSelectedText() ?? "";
|
|
27568
|
+
if (!text) {
|
|
27569
|
+
flash("Nothing selected to copy");
|
|
27570
|
+
return;
|
|
27571
|
+
}
|
|
27572
|
+
copyTextToClipboard(renderer, text).then((ok) => flash(ok ? `Copied ${text.length} character${text.length !== 1 ? "s" : ""}` : "Copy failed"));
|
|
27573
|
+
return;
|
|
27574
|
+
}
|
|
27375
27575
|
if (key.name === "q" || key.name === "escape" || key.name === "c" && key.ctrl) {
|
|
27376
27576
|
if (key.name === "escape" && selection.size > 0) {
|
|
27377
27577
|
setSelection(new Set);
|
|
@@ -27414,6 +27614,10 @@ function App({ opts }) {
|
|
|
27414
27614
|
}
|
|
27415
27615
|
return;
|
|
27416
27616
|
}
|
|
27617
|
+
if (key.name === "e" && warnings.length > 0) {
|
|
27618
|
+
setModal({ type: "warnings" });
|
|
27619
|
+
return;
|
|
27620
|
+
}
|
|
27417
27621
|
if (key.name === "n") {
|
|
27418
27622
|
if (!selectedRow)
|
|
27419
27623
|
return;
|
|
@@ -27591,17 +27795,17 @@ function App({ opts }) {
|
|
|
27591
27795
|
})();
|
|
27592
27796
|
}
|
|
27593
27797
|
});
|
|
27594
|
-
return /* @__PURE__ */
|
|
27798
|
+
return /* @__PURE__ */ jsxs12("box", {
|
|
27595
27799
|
flexDirection: "column",
|
|
27596
27800
|
width: "100%",
|
|
27597
27801
|
height: "100%",
|
|
27598
27802
|
children: [
|
|
27599
|
-
/* @__PURE__ */
|
|
27803
|
+
/* @__PURE__ */ jsxs12("box", {
|
|
27600
27804
|
flexDirection: "row",
|
|
27601
27805
|
width: "100%",
|
|
27602
27806
|
flexGrow: 1,
|
|
27603
27807
|
children: [
|
|
27604
|
-
/* @__PURE__ */
|
|
27808
|
+
/* @__PURE__ */ jsx13(WorktreeTable, {
|
|
27605
27809
|
blocks: displayBlocks,
|
|
27606
27810
|
selectedIndex,
|
|
27607
27811
|
selection,
|
|
@@ -27609,28 +27813,28 @@ function App({ opts }) {
|
|
|
27609
27813
|
repoVerbs,
|
|
27610
27814
|
rowVerbs
|
|
27611
27815
|
}),
|
|
27612
|
-
/* @__PURE__ */
|
|
27816
|
+
/* @__PURE__ */ jsx13(DetailPane, {
|
|
27613
27817
|
selectedRow
|
|
27614
27818
|
})
|
|
27615
27819
|
]
|
|
27616
27820
|
}),
|
|
27617
|
-
isFiltering && /* @__PURE__ */
|
|
27821
|
+
isFiltering && /* @__PURE__ */ jsxs12("box", {
|
|
27618
27822
|
flexDirection: "row",
|
|
27619
27823
|
paddingX: 1,
|
|
27620
27824
|
border: true,
|
|
27621
27825
|
borderColor: "magenta",
|
|
27622
27826
|
children: [
|
|
27623
|
-
/* @__PURE__ */
|
|
27827
|
+
/* @__PURE__ */ jsx13("text", {
|
|
27624
27828
|
children: "filter: "
|
|
27625
27829
|
}),
|
|
27626
|
-
/* @__PURE__ */
|
|
27830
|
+
/* @__PURE__ */ jsx13("input", {
|
|
27627
27831
|
focused: true,
|
|
27628
27832
|
placeholder: "Type to filter...",
|
|
27629
27833
|
onInput: (v) => setFilterText(v)
|
|
27630
27834
|
})
|
|
27631
27835
|
]
|
|
27632
27836
|
}),
|
|
27633
|
-
/* @__PURE__ */
|
|
27837
|
+
/* @__PURE__ */ jsx13(Footer, {
|
|
27634
27838
|
loading: loading || refreshing,
|
|
27635
27839
|
lastRefreshed,
|
|
27636
27840
|
errorCount: warnings.length,
|
|
@@ -27639,13 +27843,16 @@ function App({ opts }) {
|
|
|
27639
27843
|
spinnerFrame,
|
|
27640
27844
|
filter: filterText ? { term: filterText, matches: flatRows.length, total: totalRows } : undefined
|
|
27641
27845
|
}),
|
|
27642
|
-
modal.type === "help" && /* @__PURE__ */
|
|
27643
|
-
modal.type === "history" && /* @__PURE__ */
|
|
27644
|
-
modal.type === "
|
|
27846
|
+
modal.type === "help" && /* @__PURE__ */ jsx13(HelpOverlay, {}),
|
|
27847
|
+
modal.type === "history" && /* @__PURE__ */ jsx13(HistoryOverlay, {}),
|
|
27848
|
+
modal.type === "warnings" && /* @__PURE__ */ jsx13(WarningsOverlay, {
|
|
27849
|
+
warnings
|
|
27850
|
+
}),
|
|
27851
|
+
modal.type === "error" && /* @__PURE__ */ jsx13(ConfirmModal, {
|
|
27645
27852
|
title: "Error",
|
|
27646
27853
|
message: modal.message
|
|
27647
27854
|
}),
|
|
27648
|
-
modal.type === "confirm_remove" && /* @__PURE__ */
|
|
27855
|
+
modal.type === "confirm_remove" && /* @__PURE__ */ jsx13(ConfirmModal, {
|
|
27649
27856
|
title: `Remove ${modal.rows.length} Worktree(s)`,
|
|
27650
27857
|
message: (() => {
|
|
27651
27858
|
const count2 = modal.rows.length;
|
|
@@ -27662,15 +27869,15 @@ function App({ opts }) {
|
|
|
27662
27869
|
`);
|
|
27663
27870
|
})()
|
|
27664
27871
|
}),
|
|
27665
|
-
modal.type === "confirm_rebase" && /* @__PURE__ */
|
|
27872
|
+
modal.type === "confirm_rebase" && /* @__PURE__ */ jsx13(ConfirmModal, {
|
|
27666
27873
|
title: `Rebase ${modal.rows.length} Worktree(s)`,
|
|
27667
27874
|
message: `Are you sure you want to fetch and rebase ${modal.rows.length === 1 ? modal.rows[0]?.branch : modal.rows.length + " worktrees"}?`
|
|
27668
27875
|
}),
|
|
27669
|
-
modal.type === "confirm_sync" && /* @__PURE__ */
|
|
27876
|
+
modal.type === "confirm_sync" && /* @__PURE__ */ jsx13(ConfirmModal, {
|
|
27670
27877
|
title: `Sync ${modal.rows.length} Worktree(s)`,
|
|
27671
27878
|
message: `Are you sure you want to sync ${modal.rows.length === 1 ? modal.rows[0]?.branch : modal.rows.length + " worktrees"}?`
|
|
27672
27879
|
}),
|
|
27673
|
-
createModal && /* @__PURE__ */
|
|
27880
|
+
createModal && /* @__PURE__ */ jsx13(InputModal, {
|
|
27674
27881
|
title: `New worktree branch in ${selectedRow?.repoName ?? ""}`,
|
|
27675
27882
|
placeholder: "Branch name (empty to cancel)",
|
|
27676
27883
|
errorMessage: createError,
|
|
@@ -27697,7 +27904,7 @@ function App({ opts }) {
|
|
|
27697
27904
|
setCreateBaseModal({ branch, repoName });
|
|
27698
27905
|
}
|
|
27699
27906
|
}),
|
|
27700
|
-
createBaseModal && /* @__PURE__ */
|
|
27907
|
+
createBaseModal && /* @__PURE__ */ jsx13(InputModal, {
|
|
27701
27908
|
title: `Base ref for ${createBaseModal.branch}`,
|
|
27702
27909
|
placeholder: "origin/main (empty for default main)",
|
|
27703
27910
|
errorMessage: createBaseError,
|
|
@@ -27713,7 +27920,7 @@ function App({ opts }) {
|
|
|
27713
27920
|
setCreateDepsChoice({ branch, repoName, base: base2 || undefined });
|
|
27714
27921
|
}
|
|
27715
27922
|
}),
|
|
27716
|
-
createDepsChoice && /* @__PURE__ */
|
|
27923
|
+
createDepsChoice && /* @__PURE__ */ jsx13(ChoiceModal, {
|
|
27717
27924
|
title: `Dependencies for ${createDepsChoice.branch}`,
|
|
27718
27925
|
options: DEPS_CHOICES,
|
|
27719
27926
|
onSubmit: (choice) => {
|
|
@@ -27723,7 +27930,7 @@ function App({ opts }) {
|
|
|
27723
27930
|
},
|
|
27724
27931
|
onCancel: () => setCreateDepsChoice(null)
|
|
27725
27932
|
}),
|
|
27726
|
-
renameModal && selectedRow && /* @__PURE__ */
|
|
27933
|
+
renameModal && selectedRow && /* @__PURE__ */ jsx13(InputModal, {
|
|
27727
27934
|
title: `Rename branch ${selectedRow.branch}`,
|
|
27728
27935
|
placeholder: `New branch name (${selectedRow.branch})`,
|
|
27729
27936
|
errorMessage: renameError,
|
|
@@ -27747,7 +27954,7 @@ function App({ opts }) {
|
|
|
27747
27954
|
setModal({ type: "confirm_rename", row: target, to });
|
|
27748
27955
|
}
|
|
27749
27956
|
}),
|
|
27750
|
-
modal.type === "confirm_rename" && /* @__PURE__ */
|
|
27957
|
+
modal.type === "confirm_rename" && /* @__PURE__ */ jsx13(ConfirmModal, {
|
|
27751
27958
|
title: "Rename Worktree",
|
|
27752
27959
|
message: [
|
|
27753
27960
|
`${modal.row.branch} → ${modal.to}`,
|
|
@@ -27760,12 +27967,12 @@ function App({ opts }) {
|
|
|
27760
27967
|
].join(`
|
|
27761
27968
|
`)
|
|
27762
27969
|
}),
|
|
27763
|
-
configOpen && /* @__PURE__ */
|
|
27970
|
+
configOpen && /* @__PURE__ */ jsx13(ConfigOverlay, {
|
|
27764
27971
|
onClose: () => setConfigOpen(false),
|
|
27765
27972
|
onSaved: () => void doRefresh(),
|
|
27766
27973
|
onError: (msg) => setModal({ type: "error", message: msg })
|
|
27767
27974
|
}),
|
|
27768
|
-
failedLogs.length > 0 && /* @__PURE__ */
|
|
27975
|
+
failedLogs.length > 0 && /* @__PURE__ */ jsx13(ActionLogModal, {
|
|
27769
27976
|
title: failedLogs[0].title,
|
|
27770
27977
|
lines: failedLogs[0].lines,
|
|
27771
27978
|
done: true,
|
|
@@ -27789,6 +27996,7 @@ var init_App = __esm(() => {
|
|
|
27789
27996
|
init_InputModal();
|
|
27790
27997
|
init_ChoiceModal();
|
|
27791
27998
|
init_ConfigOverlay();
|
|
27999
|
+
init_WarningsOverlay();
|
|
27792
28000
|
init_utils();
|
|
27793
28001
|
init_agents();
|
|
27794
28002
|
init_config();
|
|
@@ -27819,14 +28027,14 @@ __export(exports_tui, {
|
|
|
27819
28027
|
});
|
|
27820
28028
|
import { createCliRenderer, TextTableRenderable } from "@opentui/core";
|
|
27821
28029
|
import { createRoot, extend as extend2 } from "@opentui/react";
|
|
27822
|
-
import { jsx as
|
|
28030
|
+
import { jsx as jsx14 } from "@opentui/react/jsx-runtime";
|
|
27823
28031
|
async function runTerminal(opts) {
|
|
27824
28032
|
const renderer = await createCliRenderer({
|
|
27825
28033
|
exitOnCtrlC: false
|
|
27826
28034
|
});
|
|
27827
28035
|
const root = createRoot(renderer);
|
|
27828
28036
|
try {
|
|
27829
|
-
root.render(/* @__PURE__ */
|
|
28037
|
+
root.render(/* @__PURE__ */ jsx14(App, {
|
|
27830
28038
|
opts
|
|
27831
28039
|
}));
|
|
27832
28040
|
} catch (err) {
|
|
@@ -31233,7 +31441,7 @@ function registerLsCommand(program2) {
|
|
|
31233
31441
|
const prInfo = prMap?.get(branch);
|
|
31234
31442
|
if (prInfo) {
|
|
31235
31443
|
const display = derivePrDisplay(prInfo);
|
|
31236
|
-
prSegment = ` #${prInfo.number} ${renderDisplayState(display)} ${source_default.dim(prInfo.url)}`;
|
|
31444
|
+
prSegment = ` #${prInfo.number} ${renderDisplayState(display)} ${source_default.dim(terminalLink(prInfo.url))}`;
|
|
31237
31445
|
}
|
|
31238
31446
|
let ownerSuffix = "";
|
|
31239
31447
|
const baseRef = wt.branch ? stackMetadata.branches[wt.branch]?.baseRef ?? prInfo?.baseRefName : prInfo?.baseRefName;
|
|
@@ -32163,7 +32371,7 @@ function renderTable(rows) {
|
|
|
32163
32371
|
const detailSuffix = details ? ` ${details}` : "";
|
|
32164
32372
|
const baseSuffix = row.baseRef ? ` → ${row.baseRef}` : "";
|
|
32165
32373
|
const authorTag = row.ownership && !row.ownership.mine && row.ownership.author ? ` ${source_default.dim(row.ownership.author)}` : "";
|
|
32166
|
-
info(` #${row.prNumber} ${paddedBranch} ${renderDisplayState(row.prDisplay)}${baseSuffix}${detailSuffix}${authorTag} ${formatRelativeTime(row.updatedAt)} ${source_default.dim(row.url)}`);
|
|
32374
|
+
info(` #${row.prNumber} ${paddedBranch} ${renderDisplayState(row.prDisplay)}${baseSuffix}${detailSuffix}${authorTag} ${formatRelativeTime(row.updatedAt)} ${source_default.dim(terminalLink(row.url))}`);
|
|
32167
32375
|
}
|
|
32168
32376
|
}
|
|
32169
32377
|
}
|