@ogpoyraz/wtx 0.8.9 → 0.8.10
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 +522 -257
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from "node:module";
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __returnValue = (v) => v;
|
|
4
5
|
function __exportSetter(name, newValue) {
|
|
@@ -14,6 +15,7 @@ var __export = (target, all) => {
|
|
|
14
15
|
});
|
|
15
16
|
};
|
|
16
17
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
18
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
17
19
|
|
|
18
20
|
// node_modules/zod/v4/core/core.js
|
|
19
21
|
function $constructor(name, initializer, params) {
|
|
@@ -25100,6 +25102,18 @@ class Semaphore {
|
|
|
25100
25102
|
}
|
|
25101
25103
|
}
|
|
25102
25104
|
|
|
25105
|
+
// src/tui/env.ts
|
|
25106
|
+
var init_env = __esm(() => {
|
|
25107
|
+
process.env.RUST_LOG ??= "fatal";
|
|
25108
|
+
process.env.ZIG_LOG ??= "fatal";
|
|
25109
|
+
process.env.PAGE_LIST_LOG ??= "fatal";
|
|
25110
|
+
process.env.OPENTUI_LOG ??= "fatal";
|
|
25111
|
+
process.env.LOG_LEVEL ??= "fatal";
|
|
25112
|
+
process.env.ZIG_LOG_LEVEL ??= "fatal";
|
|
25113
|
+
process.env.OPENTUI_LOG_LEVEL ??= "fatal";
|
|
25114
|
+
process.env.BUN_DEBUG ??= "0";
|
|
25115
|
+
});
|
|
25116
|
+
|
|
25103
25117
|
// src/tui/data.ts
|
|
25104
25118
|
async function fetchWorktreeData(opts, scope) {
|
|
25105
25119
|
const warnings = [];
|
|
@@ -25597,6 +25611,39 @@ async function copyTextToClipboard(renderer, text) {
|
|
|
25597
25611
|
}
|
|
25598
25612
|
return viaSystem || viaTerminal;
|
|
25599
25613
|
}
|
|
25614
|
+
function pasteCandidatesFor(platform2, env2 = process.env) {
|
|
25615
|
+
if (platform2 === "darwin")
|
|
25616
|
+
return [{ cmd: "pbpaste", args: [] }];
|
|
25617
|
+
if (platform2 === "win32")
|
|
25618
|
+
return [{ cmd: "powershell.exe", args: ["-command", "Get-Clipboard"] }];
|
|
25619
|
+
const candidates = [];
|
|
25620
|
+
if (env2.WAYLAND_DISPLAY)
|
|
25621
|
+
candidates.push({ cmd: "wl-paste", args: ["--no-newline"] });
|
|
25622
|
+
if (env2.DISPLAY) {
|
|
25623
|
+
candidates.push({ cmd: "xclip", args: ["-selection", "clipboard", "-o"] });
|
|
25624
|
+
candidates.push({ cmd: "xsel", args: ["--clipboard", "--output"] });
|
|
25625
|
+
}
|
|
25626
|
+
candidates.push({ cmd: "wl-paste", args: ["--no-newline"] });
|
|
25627
|
+
candidates.push({ cmd: "xclip", args: ["-selection", "clipboard", "-o"] });
|
|
25628
|
+
candidates.push({ cmd: "xsel", args: ["--clipboard", "--output"] });
|
|
25629
|
+
return candidates;
|
|
25630
|
+
}
|
|
25631
|
+
async function readTextFromClipboard() {
|
|
25632
|
+
for (const candidate of pasteCandidatesFor(process.platform)) {
|
|
25633
|
+
try {
|
|
25634
|
+
const proc = Bun.spawn([candidate.cmd, ...candidate.args], {
|
|
25635
|
+
stdin: "ignore",
|
|
25636
|
+
stdout: "pipe",
|
|
25637
|
+
stderr: "ignore"
|
|
25638
|
+
});
|
|
25639
|
+
const text = await new Response(proc.stdout).text();
|
|
25640
|
+
const code = await proc.exited;
|
|
25641
|
+
if (code === 0 && text)
|
|
25642
|
+
return text;
|
|
25643
|
+
} catch {}
|
|
25644
|
+
}
|
|
25645
|
+
return null;
|
|
25646
|
+
}
|
|
25600
25647
|
function browserCommandFor(platform2, url2) {
|
|
25601
25648
|
if (!/^https?:\/\//.test(url2))
|
|
25602
25649
|
return null;
|
|
@@ -25926,8 +25973,255 @@ var init_TabBar = __esm(() => {
|
|
|
25926
25973
|
init_use_tap();
|
|
25927
25974
|
});
|
|
25928
25975
|
|
|
25929
|
-
// src/tui/
|
|
25976
|
+
// src/tui/components/TerminalView.tsx
|
|
25977
|
+
import { useState as useState2, useEffect as useEffect3, useRef as useRef4, useCallback as useCallback3 } from "react";
|
|
25930
25978
|
import { jsx as jsx3, jsxs as jsxs3 } from "@opentui/react/jsx-runtime";
|
|
25979
|
+
function TerminalView({ session, focused, onFocus, onSend, onResize, registerListener, unregisterListener }) {
|
|
25980
|
+
const [draft, setDraft] = useState2("");
|
|
25981
|
+
const focusTap = useTapHandler(() => onFocus());
|
|
25982
|
+
const termRef = useRef4(null);
|
|
25983
|
+
const pipeScrollRef = useRef4(null);
|
|
25984
|
+
const handlePtyScroll = useCallback3((e) => {
|
|
25985
|
+
const ev = e;
|
|
25986
|
+
const dir = ev.scroll?.direction;
|
|
25987
|
+
if (dir !== "up" && dir !== "down")
|
|
25988
|
+
return;
|
|
25989
|
+
const term = termRef.current;
|
|
25990
|
+
if (term?.handle && term?.lib) {
|
|
25991
|
+
try {
|
|
25992
|
+
term.lib.embeddedTerminalScroll(term.handle, dir === "up" ? -8 : 8);
|
|
25993
|
+
term.requestRender?.();
|
|
25994
|
+
ev.preventDefault?.();
|
|
25995
|
+
ev.stopPropagation?.();
|
|
25996
|
+
} catch {}
|
|
25997
|
+
}
|
|
25998
|
+
}, []);
|
|
25999
|
+
const handlePipeScroll = useCallback3((e) => {
|
|
26000
|
+
const ev = e;
|
|
26001
|
+
const dir = ev.scroll?.direction;
|
|
26002
|
+
if (dir !== "up" && dir !== "down")
|
|
26003
|
+
return;
|
|
26004
|
+
try {
|
|
26005
|
+
pipeScrollRef.current?.scrollBy(dir === "up" ? -4 : 4);
|
|
26006
|
+
ev.preventDefault?.();
|
|
26007
|
+
ev.stopPropagation?.();
|
|
26008
|
+
} catch {}
|
|
26009
|
+
}, []);
|
|
26010
|
+
const handleData = useCallback3((data, source) => {
|
|
26011
|
+
if (source !== "input")
|
|
26012
|
+
return;
|
|
26013
|
+
if (session.usePty && focused)
|
|
26014
|
+
return;
|
|
26015
|
+
onSend(data);
|
|
26016
|
+
}, [onSend, focused, session.id, session.usePty]);
|
|
26017
|
+
const handleResize = useCallback3((cols, rows) => {
|
|
26018
|
+
onResize?.(cols, rows);
|
|
26019
|
+
}, [onResize]);
|
|
26020
|
+
useEffect3(() => {
|
|
26021
|
+
if (!session.usePty || !session.terminal)
|
|
26022
|
+
return;
|
|
26023
|
+
if (!termRef.current || !registerListener || !unregisterListener)
|
|
26024
|
+
return;
|
|
26025
|
+
const write = (data) => {
|
|
26026
|
+
try {
|
|
26027
|
+
termRef.current?.write(data);
|
|
26028
|
+
} catch {}
|
|
26029
|
+
};
|
|
26030
|
+
registerListener(session.id, write);
|
|
26031
|
+
try {
|
|
26032
|
+
termRef.current?.invalidate?.();
|
|
26033
|
+
} catch {}
|
|
26034
|
+
return () => unregisterListener(session.id);
|
|
26035
|
+
}, [session.id, session.usePty, session.terminal, registerListener, unregisterListener]);
|
|
26036
|
+
useEffect3(() => {
|
|
26037
|
+
if (!session.usePty)
|
|
26038
|
+
return;
|
|
26039
|
+
if (!termRef.current)
|
|
26040
|
+
return;
|
|
26041
|
+
try {
|
|
26042
|
+
if (focused)
|
|
26043
|
+
termRef.current.focus?.();
|
|
26044
|
+
else
|
|
26045
|
+
termRef.current.blur?.();
|
|
26046
|
+
} catch {}
|
|
26047
|
+
}, [focused, session.usePty]);
|
|
26048
|
+
useEffect3(() => {
|
|
26049
|
+
if (!session.usePty || !session.terminal)
|
|
26050
|
+
return;
|
|
26051
|
+
if (!termRef.current)
|
|
26052
|
+
return;
|
|
26053
|
+
try {
|
|
26054
|
+
termRef.current.invalidate?.();
|
|
26055
|
+
} catch {}
|
|
26056
|
+
}, [session.cols, session.rows, session.usePty]);
|
|
26057
|
+
useEffect3(() => {
|
|
26058
|
+
if (!session.usePty || !termRef.current)
|
|
26059
|
+
return;
|
|
26060
|
+
const term = termRef.current;
|
|
26061
|
+
const orig = term.forwardMouse?.bind(term);
|
|
26062
|
+
if (!orig)
|
|
26063
|
+
return;
|
|
26064
|
+
const patched = (event, action) => {
|
|
26065
|
+
const ev = event;
|
|
26066
|
+
if (ev.type === "scroll") {
|
|
26067
|
+
const dir = ev.scroll?.direction;
|
|
26068
|
+
const shift = ev.modifiers?.shift;
|
|
26069
|
+
if (dir === "up" || dir === "down") {
|
|
26070
|
+
const shouldScrollOuter = shift === true;
|
|
26071
|
+
if (!shouldScrollOuter) {
|
|
26072
|
+
return orig(event, action);
|
|
26073
|
+
}
|
|
26074
|
+
try {
|
|
26075
|
+
if (term.handle && term.lib) {
|
|
26076
|
+
term.lib.embeddedTerminalScroll(term.handle, dir === "up" ? -12 : 12);
|
|
26077
|
+
term.requestRender?.();
|
|
26078
|
+
}
|
|
26079
|
+
ev.preventDefault?.();
|
|
26080
|
+
ev.stopPropagation?.();
|
|
26081
|
+
return;
|
|
26082
|
+
} catch {}
|
|
26083
|
+
}
|
|
26084
|
+
}
|
|
26085
|
+
return orig(event, action);
|
|
26086
|
+
};
|
|
26087
|
+
term.forwardMouse = patched;
|
|
26088
|
+
return () => {
|
|
26089
|
+
term.forwardMouse = orig;
|
|
26090
|
+
};
|
|
26091
|
+
}, [session.id, session.usePty, session.terminal]);
|
|
26092
|
+
if (session.usePty && session.terminal) {
|
|
26093
|
+
return /* @__PURE__ */ jsxs3("box", {
|
|
26094
|
+
flexDirection: "column",
|
|
26095
|
+
flexGrow: 1,
|
|
26096
|
+
width: "100%",
|
|
26097
|
+
height: "100%",
|
|
26098
|
+
...focusTap,
|
|
26099
|
+
onMouseScroll: handlePtyScroll,
|
|
26100
|
+
children: [
|
|
26101
|
+
/* @__PURE__ */ jsx3("box", {
|
|
26102
|
+
flexGrow: 1,
|
|
26103
|
+
width: "100%",
|
|
26104
|
+
height: "100%",
|
|
26105
|
+
flexDirection: "column",
|
|
26106
|
+
padding: 1,
|
|
26107
|
+
onMouseScroll: handlePtyScroll,
|
|
26108
|
+
children: /* @__PURE__ */ jsx3("embedded-terminal", {
|
|
26109
|
+
ref: termRef,
|
|
26110
|
+
width: "100%",
|
|
26111
|
+
height: "100%",
|
|
26112
|
+
cols: session.cols,
|
|
26113
|
+
rows: session.rows,
|
|
26114
|
+
maxScrollback: 1e4,
|
|
26115
|
+
onData: handleData,
|
|
26116
|
+
onTerminalResize: handleResize,
|
|
26117
|
+
selectable: true,
|
|
26118
|
+
focused
|
|
26119
|
+
})
|
|
26120
|
+
}),
|
|
26121
|
+
session.exited !== null && /* @__PURE__ */ jsxs3("text", {
|
|
26122
|
+
fg: tokens.warning,
|
|
26123
|
+
children: [
|
|
26124
|
+
"— exited with code ",
|
|
26125
|
+
session.exited,
|
|
26126
|
+
" — press t for new session"
|
|
26127
|
+
]
|
|
26128
|
+
}),
|
|
26129
|
+
!focused && /* @__PURE__ */ jsxs3("text", {
|
|
26130
|
+
fg: tokens.dim,
|
|
26131
|
+
children: [
|
|
26132
|
+
"Click to focus · Ctrl+G or click table to unfocus · ",
|
|
26133
|
+
session.label,
|
|
26134
|
+
" PTY · scroll wheel to view history"
|
|
26135
|
+
]
|
|
26136
|
+
}),
|
|
26137
|
+
focused && /* @__PURE__ */ jsx3("text", {
|
|
26138
|
+
fg: tokens.accent,
|
|
26139
|
+
children: "Focused PTY — all keys go to shell · Ctrl+G to unfocus · scroll wheel to view history"
|
|
26140
|
+
})
|
|
26141
|
+
]
|
|
26142
|
+
});
|
|
26143
|
+
}
|
|
26144
|
+
const lines = session.lines;
|
|
26145
|
+
return /* @__PURE__ */ jsxs3("box", {
|
|
26146
|
+
flexDirection: "column",
|
|
26147
|
+
flexGrow: 1,
|
|
26148
|
+
width: "100%",
|
|
26149
|
+
height: "100%",
|
|
26150
|
+
...focusTap,
|
|
26151
|
+
onMouseScroll: handlePipeScroll,
|
|
26152
|
+
children: [
|
|
26153
|
+
/* @__PURE__ */ jsxs3("scrollbox", {
|
|
26154
|
+
ref: pipeScrollRef,
|
|
26155
|
+
flexGrow: 1,
|
|
26156
|
+
width: "100%",
|
|
26157
|
+
border: false,
|
|
26158
|
+
focused: false,
|
|
26159
|
+
stickyScroll: false,
|
|
26160
|
+
style: { marginBottom: 1 },
|
|
26161
|
+
onMouseScroll: handlePipeScroll,
|
|
26162
|
+
children: [
|
|
26163
|
+
lines.length === 0 ? /* @__PURE__ */ jsx3("text", {
|
|
26164
|
+
fg: tokens.dim,
|
|
26165
|
+
children: "No output yet — type a command below."
|
|
26166
|
+
}) : lines.slice(-500).map((line, idx) => /* @__PURE__ */ jsx3("text", {
|
|
26167
|
+
fg: session.exited !== null ? tokens.dim : tokens.fg,
|
|
26168
|
+
children: line || " "
|
|
26169
|
+
}, idx)),
|
|
26170
|
+
session.exited !== null && /* @__PURE__ */ jsxs3("text", {
|
|
26171
|
+
fg: tokens.warning,
|
|
26172
|
+
children: [
|
|
26173
|
+
"— exited with code ",
|
|
26174
|
+
session.exited,
|
|
26175
|
+
" —"
|
|
26176
|
+
]
|
|
26177
|
+
})
|
|
26178
|
+
]
|
|
26179
|
+
}),
|
|
26180
|
+
/* @__PURE__ */ jsxs3("box", {
|
|
26181
|
+
flexDirection: "row",
|
|
26182
|
+
gap: 1,
|
|
26183
|
+
width: "100%",
|
|
26184
|
+
children: [
|
|
26185
|
+
/* @__PURE__ */ jsx3("text", {
|
|
26186
|
+
fg: tokens.dim,
|
|
26187
|
+
children: "$"
|
|
26188
|
+
}),
|
|
26189
|
+
/* @__PURE__ */ jsx3("box", {
|
|
26190
|
+
flexGrow: 1,
|
|
26191
|
+
children: /* @__PURE__ */ jsx3("input", {
|
|
26192
|
+
focused,
|
|
26193
|
+
value: draft,
|
|
26194
|
+
placeholder: focused ? "Type command, Enter to send, Esc to unfocus" : "Click to focus terminal",
|
|
26195
|
+
onInput: (v) => setDraft(v),
|
|
26196
|
+
onSubmit: () => {
|
|
26197
|
+
if (!draft)
|
|
26198
|
+
return;
|
|
26199
|
+
onSend(draft + `
|
|
26200
|
+
`);
|
|
26201
|
+
setDraft("");
|
|
26202
|
+
}
|
|
26203
|
+
})
|
|
26204
|
+
})
|
|
26205
|
+
]
|
|
26206
|
+
}),
|
|
26207
|
+
!focused && /* @__PURE__ */ jsx3("text", {
|
|
26208
|
+
fg: tokens.dim,
|
|
26209
|
+
children: "Click terminal or press 't' to focus · Ctrl+G or click table to unfocus"
|
|
26210
|
+
}),
|
|
26211
|
+
focused && /* @__PURE__ */ jsx3("text", {
|
|
26212
|
+
fg: tokens.accent,
|
|
26213
|
+
children: "Focused — typing goes to shell · Ctrl+G to unfocus · max 5 per worktree persist across switches"
|
|
26214
|
+
})
|
|
26215
|
+
]
|
|
26216
|
+
});
|
|
26217
|
+
}
|
|
26218
|
+
var init_TerminalView = __esm(() => {
|
|
26219
|
+
init_theme();
|
|
26220
|
+
init_use_tap();
|
|
26221
|
+
});
|
|
26222
|
+
|
|
26223
|
+
// src/tui/tabs/TabPane.tsx
|
|
26224
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "@opentui/react/jsx-runtime";
|
|
25931
26225
|
function TabPane({
|
|
25932
26226
|
selectedRow,
|
|
25933
26227
|
tabs,
|
|
@@ -25937,12 +26231,13 @@ function TabPane({
|
|
|
25937
26231
|
onSelect,
|
|
25938
26232
|
onAdd,
|
|
25939
26233
|
onClose,
|
|
25940
|
-
|
|
25941
|
-
|
|
26234
|
+
allSessionsFlat,
|
|
26235
|
+
terminalFocused,
|
|
26236
|
+
activeTabId,
|
|
26237
|
+
terminalSessions
|
|
25942
26238
|
}) {
|
|
25943
|
-
const activeTab = tabs.find((t) => t.id === activeId) ?? tabs[0] ?? null;
|
|
25944
26239
|
const borderColor = focused ? tokens.accent : tokens.border;
|
|
25945
|
-
return /* @__PURE__ */
|
|
26240
|
+
return /* @__PURE__ */ jsxs4("box", {
|
|
25946
26241
|
flexDirection: "column",
|
|
25947
26242
|
flexGrow: 1,
|
|
25948
26243
|
width: "100%",
|
|
@@ -25953,7 +26248,7 @@ function TabPane({
|
|
|
25953
26248
|
focusable: false,
|
|
25954
26249
|
id: "detail-pane",
|
|
25955
26250
|
children: [
|
|
25956
|
-
/* @__PURE__ */
|
|
26251
|
+
/* @__PURE__ */ jsx4(TabBar, {
|
|
25957
26252
|
tabs,
|
|
25958
26253
|
activeId,
|
|
25959
26254
|
canAdd,
|
|
@@ -25961,14 +26256,39 @@ function TabPane({
|
|
|
25961
26256
|
onAdd,
|
|
25962
26257
|
onClose
|
|
25963
26258
|
}),
|
|
25964
|
-
/* @__PURE__ */
|
|
26259
|
+
/* @__PURE__ */ jsxs4("box", {
|
|
25965
26260
|
flexGrow: 1,
|
|
25966
26261
|
width: "100%",
|
|
25967
26262
|
flexDirection: "column",
|
|
25968
|
-
children:
|
|
25969
|
-
|
|
25970
|
-
|
|
25971
|
-
|
|
26263
|
+
children: [
|
|
26264
|
+
tabs.map((t) => /* @__PURE__ */ jsx4("box", {
|
|
26265
|
+
flexGrow: 1,
|
|
26266
|
+
width: "100%",
|
|
26267
|
+
flexDirection: "column",
|
|
26268
|
+
visible: t.id === activeId && t.id === "details",
|
|
26269
|
+
children: t.render({ worktree: selectedRow, isActive: t.id === activeId })
|
|
26270
|
+
}, t.id)),
|
|
26271
|
+
allSessionsFlat?.map((s) => /* @__PURE__ */ jsx4("box", {
|
|
26272
|
+
flexGrow: 1,
|
|
26273
|
+
width: "100%",
|
|
26274
|
+
height: "100%",
|
|
26275
|
+
flexDirection: "column",
|
|
26276
|
+
visible: activeTabId === s.id,
|
|
26277
|
+
children: /* @__PURE__ */ jsx4(TerminalView, {
|
|
26278
|
+
session: s,
|
|
26279
|
+
focused: !!(terminalFocused && activeTabId === s.id),
|
|
26280
|
+
onFocus: () => {},
|
|
26281
|
+
onSend: (data) => terminalSessions?.sendInput(s.repoName, s.branch, s.worktreePath, s.id, data),
|
|
26282
|
+
onResize: (cols, rows) => terminalSessions?.resizeSession(s.repoName, s.branch, s.worktreePath, s.id, cols, rows),
|
|
26283
|
+
registerListener: terminalSessions?.registerListener,
|
|
26284
|
+
unregisterListener: terminalSessions?.unregisterListener
|
|
26285
|
+
})
|
|
26286
|
+
}, s.id)),
|
|
26287
|
+
tabs.length === 0 && (!allSessionsFlat || allSessionsFlat.length === 0) && /* @__PURE__ */ jsx4("text", {
|
|
26288
|
+
fg: tokens.dim,
|
|
26289
|
+
children: "No tab"
|
|
26290
|
+
})
|
|
26291
|
+
]
|
|
25972
26292
|
})
|
|
25973
26293
|
]
|
|
25974
26294
|
});
|
|
@@ -25976,23 +26296,24 @@ function TabPane({
|
|
|
25976
26296
|
var init_TabPane = __esm(() => {
|
|
25977
26297
|
init_theme();
|
|
25978
26298
|
init_TabBar();
|
|
26299
|
+
init_TerminalView();
|
|
25979
26300
|
});
|
|
25980
26301
|
|
|
25981
26302
|
// src/tui/components/DetailsTab.tsx
|
|
25982
|
-
import { jsx as
|
|
26303
|
+
import { jsx as jsx5, jsxs as jsxs5, Fragment } from "@opentui/react/jsx-runtime";
|
|
25983
26304
|
function DetailsContent({ selectedRow }) {
|
|
25984
26305
|
const prTap = useTapHandler(() => {
|
|
25985
26306
|
if (selectedRow?.prUrl)
|
|
25986
26307
|
openInBrowser(selectedRow.prUrl);
|
|
25987
26308
|
});
|
|
25988
26309
|
if (!selectedRow) {
|
|
25989
|
-
return /* @__PURE__ */
|
|
26310
|
+
return /* @__PURE__ */ jsx5("box", {
|
|
25990
26311
|
flexGrow: 1,
|
|
25991
26312
|
width: "100%",
|
|
25992
26313
|
height: "100%",
|
|
25993
26314
|
justifyContent: "center",
|
|
25994
26315
|
alignItems: "center",
|
|
25995
|
-
children: /* @__PURE__ */
|
|
26316
|
+
children: /* @__PURE__ */ jsx5("text", {
|
|
25996
26317
|
fg: tokens.dim,
|
|
25997
26318
|
children: "No worktree selected"
|
|
25998
26319
|
})
|
|
@@ -26020,20 +26341,20 @@ function DetailsContent({ selectedRow }) {
|
|
|
26020
26341
|
baseChanged
|
|
26021
26342
|
} = selectedRow;
|
|
26022
26343
|
const aheadBehindStr = ahead !== null && behind !== null ? `${ahead} ahead, ${behind} behind` : "unknown";
|
|
26023
|
-
return /* @__PURE__ */
|
|
26344
|
+
return /* @__PURE__ */ jsxs5("scrollbox", {
|
|
26024
26345
|
flexGrow: 1,
|
|
26025
26346
|
width: "100%",
|
|
26026
26347
|
height: "100%",
|
|
26027
26348
|
focused: false,
|
|
26028
26349
|
padding: 1,
|
|
26029
26350
|
children: [
|
|
26030
|
-
/* @__PURE__ */
|
|
26351
|
+
/* @__PURE__ */ jsxs5("text", {
|
|
26031
26352
|
children: [
|
|
26032
|
-
/* @__PURE__ */
|
|
26353
|
+
/* @__PURE__ */ jsx5("span", {
|
|
26033
26354
|
fg: tokens.dim,
|
|
26034
26355
|
children: "Repo:"
|
|
26035
26356
|
}),
|
|
26036
|
-
/* @__PURE__ */
|
|
26357
|
+
/* @__PURE__ */ jsxs5("span", {
|
|
26037
26358
|
fg: tokens.fg,
|
|
26038
26359
|
children: [
|
|
26039
26360
|
" ",
|
|
@@ -26042,13 +26363,13 @@ function DetailsContent({ selectedRow }) {
|
|
|
26042
26363
|
})
|
|
26043
26364
|
]
|
|
26044
26365
|
}),
|
|
26045
|
-
/* @__PURE__ */
|
|
26366
|
+
/* @__PURE__ */ jsxs5("text", {
|
|
26046
26367
|
children: [
|
|
26047
|
-
/* @__PURE__ */
|
|
26368
|
+
/* @__PURE__ */ jsx5("span", {
|
|
26048
26369
|
fg: tokens.dim,
|
|
26049
26370
|
children: "Branch:"
|
|
26050
26371
|
}),
|
|
26051
|
-
/* @__PURE__ */
|
|
26372
|
+
/* @__PURE__ */ jsxs5("span", {
|
|
26052
26373
|
fg: tokens.fg,
|
|
26053
26374
|
children: [
|
|
26054
26375
|
" ",
|
|
@@ -26059,13 +26380,13 @@ function DetailsContent({ selectedRow }) {
|
|
|
26059
26380
|
})
|
|
26060
26381
|
]
|
|
26061
26382
|
}),
|
|
26062
|
-
/* @__PURE__ */
|
|
26383
|
+
/* @__PURE__ */ jsxs5("text", {
|
|
26063
26384
|
children: [
|
|
26064
|
-
/* @__PURE__ */
|
|
26385
|
+
/* @__PURE__ */ jsx5("span", {
|
|
26065
26386
|
fg: tokens.dim,
|
|
26066
26387
|
children: "Path:"
|
|
26067
26388
|
}),
|
|
26068
|
-
/* @__PURE__ */
|
|
26389
|
+
/* @__PURE__ */ jsxs5("span", {
|
|
26069
26390
|
fg: tokens.fg,
|
|
26070
26391
|
children: [
|
|
26071
26392
|
" ",
|
|
@@ -26074,13 +26395,13 @@ function DetailsContent({ selectedRow }) {
|
|
|
26074
26395
|
})
|
|
26075
26396
|
]
|
|
26076
26397
|
}),
|
|
26077
|
-
/* @__PURE__ */
|
|
26398
|
+
/* @__PURE__ */ jsxs5("text", {
|
|
26078
26399
|
children: [
|
|
26079
|
-
/* @__PURE__ */
|
|
26400
|
+
/* @__PURE__ */ jsx5("span", {
|
|
26080
26401
|
fg: tokens.dim,
|
|
26081
26402
|
children: "Commit:"
|
|
26082
26403
|
}),
|
|
26083
|
-
/* @__PURE__ */
|
|
26404
|
+
/* @__PURE__ */ jsxs5("span", {
|
|
26084
26405
|
fg: tokens.fg,
|
|
26085
26406
|
children: [
|
|
26086
26407
|
" ",
|
|
@@ -26089,13 +26410,13 @@ function DetailsContent({ selectedRow }) {
|
|
|
26089
26410
|
})
|
|
26090
26411
|
]
|
|
26091
26412
|
}),
|
|
26092
|
-
owner && /* @__PURE__ */
|
|
26413
|
+
owner && /* @__PURE__ */ jsxs5("text", {
|
|
26093
26414
|
children: [
|
|
26094
|
-
/* @__PURE__ */
|
|
26415
|
+
/* @__PURE__ */ jsx5("span", {
|
|
26095
26416
|
fg: tokens.dim,
|
|
26096
26417
|
children: "Owner:"
|
|
26097
26418
|
}),
|
|
26098
|
-
/* @__PURE__ */
|
|
26419
|
+
/* @__PURE__ */ jsxs5("span", {
|
|
26099
26420
|
fg: tokens.fg,
|
|
26100
26421
|
children: [
|
|
26101
26422
|
" ",
|
|
@@ -26104,13 +26425,13 @@ function DetailsContent({ selectedRow }) {
|
|
|
26104
26425
|
})
|
|
26105
26426
|
]
|
|
26106
26427
|
}),
|
|
26107
|
-
/* @__PURE__ */
|
|
26428
|
+
/* @__PURE__ */ jsxs5("text", {
|
|
26108
26429
|
children: [
|
|
26109
|
-
/* @__PURE__ */
|
|
26430
|
+
/* @__PURE__ */ jsx5("span", {
|
|
26110
26431
|
fg: tokens.dim,
|
|
26111
26432
|
children: "Status:"
|
|
26112
26433
|
}),
|
|
26113
|
-
/* @__PURE__ */
|
|
26434
|
+
/* @__PURE__ */ jsxs5("span", {
|
|
26114
26435
|
fg: tokens.fg,
|
|
26115
26436
|
children: [
|
|
26116
26437
|
" ",
|
|
@@ -26119,13 +26440,13 @@ function DetailsContent({ selectedRow }) {
|
|
|
26119
26440
|
})
|
|
26120
26441
|
]
|
|
26121
26442
|
}),
|
|
26122
|
-
base2 && /* @__PURE__ */
|
|
26443
|
+
base2 && /* @__PURE__ */ jsxs5("text", {
|
|
26123
26444
|
children: [
|
|
26124
|
-
/* @__PURE__ */
|
|
26445
|
+
/* @__PURE__ */ jsx5("span", {
|
|
26125
26446
|
fg: tokens.dim,
|
|
26126
26447
|
children: "Base:"
|
|
26127
26448
|
}),
|
|
26128
|
-
/* @__PURE__ */
|
|
26449
|
+
/* @__PURE__ */ jsxs5("span", {
|
|
26129
26450
|
fg: tokens.accent,
|
|
26130
26451
|
children: [
|
|
26131
26452
|
" ",
|
|
@@ -26134,26 +26455,26 @@ function DetailsContent({ selectedRow }) {
|
|
|
26134
26455
|
})
|
|
26135
26456
|
]
|
|
26136
26457
|
}),
|
|
26137
|
-
baseChanged && /* @__PURE__ */
|
|
26458
|
+
baseChanged && /* @__PURE__ */ jsxs5("text", {
|
|
26138
26459
|
children: [
|
|
26139
|
-
/* @__PURE__ */
|
|
26460
|
+
/* @__PURE__ */ jsx5("span", {
|
|
26140
26461
|
fg: tokens.dim,
|
|
26141
26462
|
children: "Base state:"
|
|
26142
26463
|
}),
|
|
26143
|
-
/* @__PURE__ */
|
|
26464
|
+
/* @__PURE__ */ jsx5("span", {
|
|
26144
26465
|
fg: tokens.warning,
|
|
26145
26466
|
children: " moved since recorded"
|
|
26146
26467
|
})
|
|
26147
26468
|
]
|
|
26148
26469
|
}),
|
|
26149
|
-
/* @__PURE__ */
|
|
26470
|
+
/* @__PURE__ */ jsxs5("text", {
|
|
26150
26471
|
style: { marginTop: 1 },
|
|
26151
26472
|
children: [
|
|
26152
|
-
/* @__PURE__ */
|
|
26473
|
+
/* @__PURE__ */ jsx5("span", {
|
|
26153
26474
|
fg: tokens.dim,
|
|
26154
26475
|
children: base2 ? "vs base:" : "vs main:"
|
|
26155
26476
|
}),
|
|
26156
|
-
/* @__PURE__ */
|
|
26477
|
+
/* @__PURE__ */ jsxs5("span", {
|
|
26157
26478
|
fg: tokens.fg,
|
|
26158
26479
|
children: [
|
|
26159
26480
|
" ",
|
|
@@ -26162,13 +26483,13 @@ function DetailsContent({ selectedRow }) {
|
|
|
26162
26483
|
})
|
|
26163
26484
|
]
|
|
26164
26485
|
}),
|
|
26165
|
-
/* @__PURE__ */
|
|
26486
|
+
/* @__PURE__ */ jsxs5("text", {
|
|
26166
26487
|
children: [
|
|
26167
|
-
/* @__PURE__ */
|
|
26488
|
+
/* @__PURE__ */ jsx5("span", {
|
|
26168
26489
|
fg: tokens.dim,
|
|
26169
26490
|
children: "Deps:"
|
|
26170
26491
|
}),
|
|
26171
|
-
/* @__PURE__ */
|
|
26492
|
+
/* @__PURE__ */ jsxs5("span", {
|
|
26172
26493
|
fg: tokens.fg,
|
|
26173
26494
|
children: [
|
|
26174
26495
|
" ",
|
|
@@ -26177,13 +26498,13 @@ function DetailsContent({ selectedRow }) {
|
|
|
26177
26498
|
})
|
|
26178
26499
|
]
|
|
26179
26500
|
}),
|
|
26180
|
-
rebaseStatus && /* @__PURE__ */
|
|
26501
|
+
rebaseStatus && /* @__PURE__ */ jsxs5("text", {
|
|
26181
26502
|
children: [
|
|
26182
|
-
/* @__PURE__ */
|
|
26503
|
+
/* @__PURE__ */ jsx5("span", {
|
|
26183
26504
|
fg: tokens.dim,
|
|
26184
26505
|
children: "Rebase:"
|
|
26185
26506
|
}),
|
|
26186
|
-
/* @__PURE__ */
|
|
26507
|
+
/* @__PURE__ */ jsxs5("span", {
|
|
26187
26508
|
fg: tokens.error,
|
|
26188
26509
|
children: [
|
|
26189
26510
|
" ",
|
|
@@ -26192,12 +26513,12 @@ function DetailsContent({ selectedRow }) {
|
|
|
26192
26513
|
})
|
|
26193
26514
|
]
|
|
26194
26515
|
}),
|
|
26195
|
-
prNumber !== null && /* @__PURE__ */
|
|
26516
|
+
prNumber !== null && /* @__PURE__ */ jsxs5(Fragment, {
|
|
26196
26517
|
children: [
|
|
26197
|
-
/* @__PURE__ */
|
|
26518
|
+
/* @__PURE__ */ jsxs5("text", {
|
|
26198
26519
|
style: { marginTop: 1 },
|
|
26199
26520
|
children: [
|
|
26200
|
-
/* @__PURE__ */
|
|
26521
|
+
/* @__PURE__ */ jsxs5("span", {
|
|
26201
26522
|
fg: tokens.accent,
|
|
26202
26523
|
children: [
|
|
26203
26524
|
"PR #",
|
|
@@ -26205,7 +26526,7 @@ function DetailsContent({ selectedRow }) {
|
|
|
26205
26526
|
":"
|
|
26206
26527
|
]
|
|
26207
26528
|
}),
|
|
26208
|
-
/* @__PURE__ */
|
|
26529
|
+
/* @__PURE__ */ jsxs5("span", {
|
|
26209
26530
|
fg: tokens.dim,
|
|
26210
26531
|
children: [
|
|
26211
26532
|
" ",
|
|
@@ -26214,13 +26535,13 @@ function DetailsContent({ selectedRow }) {
|
|
|
26214
26535
|
})
|
|
26215
26536
|
]
|
|
26216
26537
|
}),
|
|
26217
|
-
prChecks && /* @__PURE__ */
|
|
26538
|
+
prChecks && /* @__PURE__ */ jsxs5("text", {
|
|
26218
26539
|
children: [
|
|
26219
|
-
/* @__PURE__ */
|
|
26540
|
+
/* @__PURE__ */ jsx5("span", {
|
|
26220
26541
|
fg: tokens.dim,
|
|
26221
26542
|
children: "Checks:"
|
|
26222
26543
|
}),
|
|
26223
|
-
/* @__PURE__ */
|
|
26544
|
+
/* @__PURE__ */ jsxs5("span", {
|
|
26224
26545
|
fg: tokens.fg,
|
|
26225
26546
|
children: [
|
|
26226
26547
|
" ",
|
|
@@ -26229,20 +26550,20 @@ function DetailsContent({ selectedRow }) {
|
|
|
26229
26550
|
})
|
|
26230
26551
|
]
|
|
26231
26552
|
}),
|
|
26232
|
-
prUrl && /* @__PURE__ */
|
|
26553
|
+
prUrl && /* @__PURE__ */ jsx5("box", {
|
|
26233
26554
|
...prTap,
|
|
26234
|
-
children: /* @__PURE__ */
|
|
26555
|
+
children: /* @__PURE__ */ jsxs5("text", {
|
|
26235
26556
|
selectable: false,
|
|
26236
26557
|
children: [
|
|
26237
|
-
/* @__PURE__ */
|
|
26558
|
+
/* @__PURE__ */ jsx5("span", {
|
|
26238
26559
|
fg: tokens.dim,
|
|
26239
26560
|
children: "URL:"
|
|
26240
26561
|
}),
|
|
26241
|
-
/* @__PURE__ */
|
|
26562
|
+
/* @__PURE__ */ jsx5("span", {
|
|
26242
26563
|
fg: tokens.accent,
|
|
26243
26564
|
children: ` ${prUrl}`
|
|
26244
26565
|
}),
|
|
26245
|
-
/* @__PURE__ */
|
|
26566
|
+
/* @__PURE__ */ jsx5("span", {
|
|
26246
26567
|
fg: tokens.dim,
|
|
26247
26568
|
children: " ↗ click"
|
|
26248
26569
|
})
|
|
@@ -26251,11 +26572,11 @@ function DetailsContent({ selectedRow }) {
|
|
|
26251
26572
|
})
|
|
26252
26573
|
]
|
|
26253
26574
|
}),
|
|
26254
|
-
dirtyFiles.length > 0 && /* @__PURE__ */
|
|
26575
|
+
dirtyFiles.length > 0 && /* @__PURE__ */ jsxs5("box", {
|
|
26255
26576
|
flexDirection: "column",
|
|
26256
26577
|
style: { marginTop: 1 },
|
|
26257
26578
|
children: [
|
|
26258
|
-
/* @__PURE__ */
|
|
26579
|
+
/* @__PURE__ */ jsxs5("text", {
|
|
26259
26580
|
fg: tokens.warning,
|
|
26260
26581
|
children: [
|
|
26261
26582
|
"Dirty Files (",
|
|
@@ -26263,14 +26584,14 @@ function DetailsContent({ selectedRow }) {
|
|
|
26263
26584
|
"):"
|
|
26264
26585
|
]
|
|
26265
26586
|
}),
|
|
26266
|
-
dirtyFiles.slice(0, 20).map((file2, idx) => /* @__PURE__ */
|
|
26587
|
+
dirtyFiles.slice(0, 20).map((file2, idx) => /* @__PURE__ */ jsxs5("text", {
|
|
26267
26588
|
fg: tokens.warning,
|
|
26268
26589
|
children: [
|
|
26269
26590
|
" ",
|
|
26270
26591
|
file2
|
|
26271
26592
|
]
|
|
26272
26593
|
}, idx)),
|
|
26273
|
-
dirtyFiles.length > 20 && /* @__PURE__ */
|
|
26594
|
+
dirtyFiles.length > 20 && /* @__PURE__ */ jsxs5("text", {
|
|
26274
26595
|
fg: tokens.warning,
|
|
26275
26596
|
children: [
|
|
26276
26597
|
" ...and ",
|
|
@@ -26280,17 +26601,17 @@ function DetailsContent({ selectedRow }) {
|
|
|
26280
26601
|
})
|
|
26281
26602
|
]
|
|
26282
26603
|
}),
|
|
26283
|
-
/* @__PURE__ */
|
|
26604
|
+
/* @__PURE__ */ jsxs5("box", {
|
|
26284
26605
|
flexDirection: "column",
|
|
26285
26606
|
style: { marginTop: 1 },
|
|
26286
26607
|
children: [
|
|
26287
|
-
/* @__PURE__ */
|
|
26608
|
+
/* @__PURE__ */ jsx5("text", {
|
|
26288
26609
|
fg: tokens.dim,
|
|
26289
26610
|
children: "Actions:"
|
|
26290
26611
|
}),
|
|
26291
|
-
!isMainCheckout && /* @__PURE__ */
|
|
26612
|
+
!isMainCheckout && /* @__PURE__ */ jsxs5(Fragment, {
|
|
26292
26613
|
children: [
|
|
26293
|
-
/* @__PURE__ */
|
|
26614
|
+
/* @__PURE__ */ jsxs5("text", {
|
|
26294
26615
|
fg: tokens.dim,
|
|
26295
26616
|
children: [
|
|
26296
26617
|
" i install deps (",
|
|
@@ -26298,21 +26619,21 @@ function DetailsContent({ selectedRow }) {
|
|
|
26298
26619
|
")"
|
|
26299
26620
|
]
|
|
26300
26621
|
}),
|
|
26301
|
-
/* @__PURE__ */
|
|
26622
|
+
/* @__PURE__ */ jsx5("text", {
|
|
26302
26623
|
fg: tokens.dim,
|
|
26303
26624
|
children: " m rename worktree"
|
|
26304
26625
|
})
|
|
26305
26626
|
]
|
|
26306
26627
|
}),
|
|
26307
|
-
/* @__PURE__ */
|
|
26628
|
+
/* @__PURE__ */ jsx5("text", {
|
|
26308
26629
|
fg: tokens.dim,
|
|
26309
26630
|
children: " p pull branch"
|
|
26310
26631
|
}),
|
|
26311
|
-
/* @__PURE__ */
|
|
26632
|
+
/* @__PURE__ */ jsx5("text", {
|
|
26312
26633
|
fg: tokens.dim,
|
|
26313
26634
|
children: " b rebase · s sync · o open in IDE · d remove"
|
|
26314
26635
|
}),
|
|
26315
|
-
/* @__PURE__ */
|
|
26636
|
+
/* @__PURE__ */ jsx5("text", {
|
|
26316
26637
|
fg: tokens.dim,
|
|
26317
26638
|
children: " t new terminal session (max 5)"
|
|
26318
26639
|
})
|
|
@@ -26326,176 +26647,6 @@ var init_DetailsTab = __esm(() => {
|
|
|
26326
26647
|
init_use_tap();
|
|
26327
26648
|
});
|
|
26328
26649
|
|
|
26329
|
-
// src/tui/components/TerminalView.tsx
|
|
26330
|
-
import { useState as useState2, useEffect as useEffect3, useRef as useRef4, useCallback as useCallback3 } from "react";
|
|
26331
|
-
import { jsx as jsx5, jsxs as jsxs5 } from "@opentui/react/jsx-runtime";
|
|
26332
|
-
function TerminalView({ session, focused, onFocus, onSend, onResize, registerListener, unregisterListener }) {
|
|
26333
|
-
const [draft, setDraft] = useState2("");
|
|
26334
|
-
const focusTap = useTapHandler(() => onFocus());
|
|
26335
|
-
const termRef = useRef4(null);
|
|
26336
|
-
const handleData = useCallback3((data, source) => {
|
|
26337
|
-
if (source !== "input")
|
|
26338
|
-
return;
|
|
26339
|
-
if (session.usePty && focused)
|
|
26340
|
-
return;
|
|
26341
|
-
onSend(data);
|
|
26342
|
-
}, [onSend, focused, session.id, session.usePty]);
|
|
26343
|
-
const handleResize = useCallback3((cols, rows) => {
|
|
26344
|
-
onResize?.(cols, rows);
|
|
26345
|
-
}, [onResize]);
|
|
26346
|
-
useEffect3(() => {
|
|
26347
|
-
if (!session.usePty || !session.terminal)
|
|
26348
|
-
return;
|
|
26349
|
-
if (!termRef.current || !registerListener || !unregisterListener)
|
|
26350
|
-
return;
|
|
26351
|
-
try {
|
|
26352
|
-
termRef.current.write(new TextEncoder().encode("\x1B[2J\x1B[H"));
|
|
26353
|
-
} catch {}
|
|
26354
|
-
const write = (data) => {
|
|
26355
|
-
try {
|
|
26356
|
-
termRef.current?.write(data);
|
|
26357
|
-
} catch {}
|
|
26358
|
-
};
|
|
26359
|
-
registerListener(session.id, write);
|
|
26360
|
-
return () => unregisterListener(session.id);
|
|
26361
|
-
}, [session.id, session.usePty, session.terminal, registerListener, unregisterListener]);
|
|
26362
|
-
useEffect3(() => {
|
|
26363
|
-
if (!session.usePty)
|
|
26364
|
-
return;
|
|
26365
|
-
if (!termRef.current)
|
|
26366
|
-
return;
|
|
26367
|
-
try {
|
|
26368
|
-
if (focused)
|
|
26369
|
-
termRef.current.focus?.();
|
|
26370
|
-
else
|
|
26371
|
-
termRef.current.blur?.();
|
|
26372
|
-
} catch {}
|
|
26373
|
-
}, [focused, session.usePty]);
|
|
26374
|
-
if (session.usePty && session.terminal) {
|
|
26375
|
-
return /* @__PURE__ */ jsxs5("box", {
|
|
26376
|
-
flexDirection: "column",
|
|
26377
|
-
flexGrow: 1,
|
|
26378
|
-
width: "100%",
|
|
26379
|
-
height: "100%",
|
|
26380
|
-
...focusTap,
|
|
26381
|
-
children: [
|
|
26382
|
-
/* @__PURE__ */ jsx5("box", {
|
|
26383
|
-
flexGrow: 1,
|
|
26384
|
-
width: "100%",
|
|
26385
|
-
height: "100%",
|
|
26386
|
-
flexDirection: "column",
|
|
26387
|
-
padding: 1,
|
|
26388
|
-
children: /* @__PURE__ */ jsx5("embedded-terminal", {
|
|
26389
|
-
ref: termRef,
|
|
26390
|
-
width: "100%",
|
|
26391
|
-
height: "100%",
|
|
26392
|
-
cols: session.cols,
|
|
26393
|
-
rows: session.rows,
|
|
26394
|
-
maxScrollback: 1000,
|
|
26395
|
-
onData: handleData,
|
|
26396
|
-
onTerminalResize: handleResize,
|
|
26397
|
-
selectable: true,
|
|
26398
|
-
focused
|
|
26399
|
-
})
|
|
26400
|
-
}),
|
|
26401
|
-
session.exited !== null && /* @__PURE__ */ jsxs5("text", {
|
|
26402
|
-
fg: tokens.warning,
|
|
26403
|
-
children: [
|
|
26404
|
-
"— exited with code ",
|
|
26405
|
-
session.exited,
|
|
26406
|
-
" — press t for new session"
|
|
26407
|
-
]
|
|
26408
|
-
}),
|
|
26409
|
-
!focused && /* @__PURE__ */ jsxs5("text", {
|
|
26410
|
-
fg: tokens.dim,
|
|
26411
|
-
children: [
|
|
26412
|
-
"Click to focus · Ctrl+G or click table to unfocus · ",
|
|
26413
|
-
session.label,
|
|
26414
|
-
" PTY"
|
|
26415
|
-
]
|
|
26416
|
-
}),
|
|
26417
|
-
focused && /* @__PURE__ */ jsx5("text", {
|
|
26418
|
-
fg: tokens.accent,
|
|
26419
|
-
children: "Focused PTY — all keys go to shell · Ctrl+G to unfocus"
|
|
26420
|
-
})
|
|
26421
|
-
]
|
|
26422
|
-
});
|
|
26423
|
-
}
|
|
26424
|
-
const lines = session.lines;
|
|
26425
|
-
return /* @__PURE__ */ jsxs5("box", {
|
|
26426
|
-
flexDirection: "column",
|
|
26427
|
-
flexGrow: 1,
|
|
26428
|
-
width: "100%",
|
|
26429
|
-
height: "100%",
|
|
26430
|
-
...focusTap,
|
|
26431
|
-
children: [
|
|
26432
|
-
/* @__PURE__ */ jsxs5("scrollbox", {
|
|
26433
|
-
flexGrow: 1,
|
|
26434
|
-
width: "100%",
|
|
26435
|
-
border: false,
|
|
26436
|
-
focused: false,
|
|
26437
|
-
style: { marginBottom: 1 },
|
|
26438
|
-
children: [
|
|
26439
|
-
lines.length === 0 ? /* @__PURE__ */ jsx5("text", {
|
|
26440
|
-
fg: tokens.dim,
|
|
26441
|
-
children: "No output yet — type a command below."
|
|
26442
|
-
}) : lines.slice(-200).map((line, idx) => /* @__PURE__ */ jsx5("text", {
|
|
26443
|
-
fg: session.exited !== null ? tokens.dim : tokens.fg,
|
|
26444
|
-
children: line || " "
|
|
26445
|
-
}, idx)),
|
|
26446
|
-
session.exited !== null && /* @__PURE__ */ jsxs5("text", {
|
|
26447
|
-
fg: tokens.warning,
|
|
26448
|
-
children: [
|
|
26449
|
-
"— exited with code ",
|
|
26450
|
-
session.exited,
|
|
26451
|
-
" —"
|
|
26452
|
-
]
|
|
26453
|
-
})
|
|
26454
|
-
]
|
|
26455
|
-
}),
|
|
26456
|
-
/* @__PURE__ */ jsxs5("box", {
|
|
26457
|
-
flexDirection: "row",
|
|
26458
|
-
gap: 1,
|
|
26459
|
-
width: "100%",
|
|
26460
|
-
children: [
|
|
26461
|
-
/* @__PURE__ */ jsx5("text", {
|
|
26462
|
-
fg: tokens.dim,
|
|
26463
|
-
children: "$"
|
|
26464
|
-
}),
|
|
26465
|
-
/* @__PURE__ */ jsx5("box", {
|
|
26466
|
-
flexGrow: 1,
|
|
26467
|
-
children: /* @__PURE__ */ jsx5("input", {
|
|
26468
|
-
focused,
|
|
26469
|
-
value: draft,
|
|
26470
|
-
placeholder: focused ? "Type command, Enter to send, Esc to unfocus" : "Click to focus terminal",
|
|
26471
|
-
onInput: (v) => setDraft(v),
|
|
26472
|
-
onSubmit: () => {
|
|
26473
|
-
if (!draft)
|
|
26474
|
-
return;
|
|
26475
|
-
onSend(draft + `
|
|
26476
|
-
`);
|
|
26477
|
-
setDraft("");
|
|
26478
|
-
}
|
|
26479
|
-
})
|
|
26480
|
-
})
|
|
26481
|
-
]
|
|
26482
|
-
}),
|
|
26483
|
-
!focused && /* @__PURE__ */ jsx5("text", {
|
|
26484
|
-
fg: tokens.dim,
|
|
26485
|
-
children: "Click terminal or press 't' to focus · Ctrl+G or click table to unfocus"
|
|
26486
|
-
}),
|
|
26487
|
-
focused && /* @__PURE__ */ jsx5("text", {
|
|
26488
|
-
fg: tokens.accent,
|
|
26489
|
-
children: "Focused — typing goes to shell · Ctrl+G to unfocus · max 5 per worktree persist across switches"
|
|
26490
|
-
})
|
|
26491
|
-
]
|
|
26492
|
-
});
|
|
26493
|
-
}
|
|
26494
|
-
var init_TerminalView = __esm(() => {
|
|
26495
|
-
init_theme();
|
|
26496
|
-
init_use_tap();
|
|
26497
|
-
});
|
|
26498
|
-
|
|
26499
26650
|
// src/tui/components/Footer.tsx
|
|
26500
26651
|
import { jsx as jsx6, jsxs as jsxs6 } from "@opentui/react/jsx-runtime";
|
|
26501
26652
|
function HintItem({ hintKey, label, isFirst, onClick }) {
|
|
@@ -27831,9 +27982,24 @@ function useTerminalSessions() {
|
|
|
27831
27982
|
});
|
|
27832
27983
|
};
|
|
27833
27984
|
const onPtyData = (data) => {
|
|
27985
|
+
if (data.length > 0) {
|
|
27986
|
+
const text = new TextDecoder().decode(data);
|
|
27987
|
+
if (text.includes("page_list") || text.includes("x icon") || text.includes("received and ignored")) {
|
|
27988
|
+
const reset2 = new TextEncoder().encode("\x1B[0m");
|
|
27989
|
+
const buf2 = rawBuffersRef.current.get(id) ?? [];
|
|
27990
|
+
buf2.push(reset2);
|
|
27991
|
+
if (buf2.length > 2000)
|
|
27992
|
+
buf2.shift();
|
|
27993
|
+
rawBuffersRef.current.set(id, buf2);
|
|
27994
|
+
const listener2 = listenersRef.current.get(id);
|
|
27995
|
+
if (listener2)
|
|
27996
|
+
listener2(reset2);
|
|
27997
|
+
return;
|
|
27998
|
+
}
|
|
27999
|
+
}
|
|
27834
28000
|
const buf = rawBuffersRef.current.get(id) ?? [];
|
|
27835
28001
|
buf.push(data);
|
|
27836
|
-
if (buf.length >
|
|
28002
|
+
if (buf.length > 2000)
|
|
27837
28003
|
buf.shift();
|
|
27838
28004
|
rawBuffersRef.current.set(id, buf);
|
|
27839
28005
|
const listener = listenersRef.current.get(id);
|
|
@@ -28129,7 +28295,7 @@ var init_useTerminalSessions = () => {};
|
|
|
28129
28295
|
// src/tui/components/App.tsx
|
|
28130
28296
|
import { useState as useState10, useEffect as useEffect8, useMemo, useRef as useRef7, useCallback as useCallback6 } from "react";
|
|
28131
28297
|
import { existsSync as existsSync4 } from "node:fs";
|
|
28132
|
-
import { useKeyboard as useKeyboard3, useRenderer as useRenderer2, useSelectionHandler, useTerminalDimensions } from "@opentui/react";
|
|
28298
|
+
import { useKeyboard as useKeyboard3, usePaste, useRenderer as useRenderer2, useSelectionHandler, useTerminalDimensions } from "@opentui/react";
|
|
28133
28299
|
import { jsx as jsx17, jsxs as jsxs15 } from "@opentui/react/jsx-runtime";
|
|
28134
28300
|
function getWorktreePathFor(repoName, branch) {
|
|
28135
28301
|
try {
|
|
@@ -28278,6 +28444,18 @@ function App({ opts }) {
|
|
|
28278
28444
|
}
|
|
28279
28445
|
}
|
|
28280
28446
|
}, [sessionsForSelected, activeTabId, worktreeKey]);
|
|
28447
|
+
usePaste((event) => {
|
|
28448
|
+
if (!terminalFocused)
|
|
28449
|
+
return;
|
|
28450
|
+
const activeSession = sessionsForSelected.find((s) => s.id === activeTabId);
|
|
28451
|
+
if (!activeSession)
|
|
28452
|
+
return;
|
|
28453
|
+
event.preventDefault();
|
|
28454
|
+
const data = event.bytes;
|
|
28455
|
+
if (data.length === 0)
|
|
28456
|
+
return;
|
|
28457
|
+
terminalSessions.sendInput(activeSession.repoName, activeSession.branch, activeSession.worktreePath, activeSession.id, data);
|
|
28458
|
+
});
|
|
28281
28459
|
const handleSelectTab = useCallback6((id) => {
|
|
28282
28460
|
if (!worktreeKey)
|
|
28283
28461
|
return;
|
|
@@ -28335,6 +28513,7 @@ function App({ opts }) {
|
|
|
28335
28513
|
terminalSessions.pruneKey(key);
|
|
28336
28514
|
}
|
|
28337
28515
|
}, [blocks, terminalSessions]);
|
|
28516
|
+
const allSessionsFlat = useMemo(() => Array.from(terminalSessions.sessionsByKey.values()).flat(), [terminalSessions.sessionsByKey]);
|
|
28338
28517
|
const tabsForSelected = useMemo(() => {
|
|
28339
28518
|
const base2 = [
|
|
28340
28519
|
{
|
|
@@ -28350,19 +28529,15 @@ function App({ opts }) {
|
|
|
28350
28529
|
id: s.id,
|
|
28351
28530
|
label: s.label,
|
|
28352
28531
|
closable: true,
|
|
28353
|
-
render: () => /* @__PURE__ */ jsx17(
|
|
28354
|
-
|
|
28355
|
-
|
|
28356
|
-
|
|
28357
|
-
onSend: (data) => terminalSessions.sendInput(s.repoName, s.branch, s.worktreePath, s.id, data),
|
|
28358
|
-
onResize: (cols, rows) => terminalSessions.resizeSession(s.repoName, s.branch, s.worktreePath, s.id, cols, rows),
|
|
28359
|
-
registerListener: terminalSessions.registerListener,
|
|
28360
|
-
unregisterListener: terminalSessions.unregisterListener
|
|
28532
|
+
render: () => /* @__PURE__ */ jsx17("box", {
|
|
28533
|
+
flexGrow: 1,
|
|
28534
|
+
width: "100%",
|
|
28535
|
+
height: "100%"
|
|
28361
28536
|
})
|
|
28362
28537
|
});
|
|
28363
28538
|
}
|
|
28364
28539
|
return base2;
|
|
28365
|
-
}, [sessionsForSelected
|
|
28540
|
+
}, [sessionsForSelected]);
|
|
28366
28541
|
const { repoVerbs, rowVerbs } = useMemo(() => {
|
|
28367
28542
|
const rv = new Map;
|
|
28368
28543
|
const nv = new Map;
|
|
@@ -28673,6 +28848,13 @@ function App({ opts }) {
|
|
|
28673
28848
|
}
|
|
28674
28849
|
const activeSession = sessionsForSelected.find((s) => s.id === activeTabId);
|
|
28675
28850
|
if (activeSession) {
|
|
28851
|
+
if ((key.ctrl || key.super || key.meta) && key.name === "v") {
|
|
28852
|
+
readTextFromClipboard().then((text) => {
|
|
28853
|
+
if (text)
|
|
28854
|
+
terminalSessions.sendInput(activeSession.repoName, activeSession.branch, activeSession.worktreePath, activeSession.id, text);
|
|
28855
|
+
});
|
|
28856
|
+
return;
|
|
28857
|
+
}
|
|
28676
28858
|
let data = null;
|
|
28677
28859
|
const seq = key.sequence;
|
|
28678
28860
|
const raw = key.raw;
|
|
@@ -29108,7 +29290,11 @@ function App({ opts }) {
|
|
|
29108
29290
|
canAdd: sessionsForSelected.length < MAX_TERMINAL_SESSIONS,
|
|
29109
29291
|
onSelect: handleSelectTab,
|
|
29110
29292
|
onAdd: handleAddSession,
|
|
29111
|
-
onClose: handleCloseSession
|
|
29293
|
+
onClose: handleCloseSession,
|
|
29294
|
+
allSessionsFlat,
|
|
29295
|
+
terminalFocused,
|
|
29296
|
+
activeTabId,
|
|
29297
|
+
terminalSessions
|
|
29112
29298
|
})
|
|
29113
29299
|
})
|
|
29114
29300
|
]
|
|
@@ -29388,7 +29574,6 @@ var init_App = __esm(() => {
|
|
|
29388
29574
|
init_WorktreeTable();
|
|
29389
29575
|
init_TabPane();
|
|
29390
29576
|
init_DetailsTab();
|
|
29391
|
-
init_TerminalView();
|
|
29392
29577
|
init_Footer();
|
|
29393
29578
|
init_Divider();
|
|
29394
29579
|
init_HelpOverlay();
|
|
@@ -29431,22 +29616,98 @@ import { createCliRenderer, TextTableRenderable, EmbeddedTerminalRenderable } fr
|
|
|
29431
29616
|
import { createRoot, extend as extend2 } from "@opentui/react";
|
|
29432
29617
|
import { jsx as jsx18 } from "@opentui/react/jsx-runtime";
|
|
29433
29618
|
async function runTerminal(opts) {
|
|
29619
|
+
setQuiet(true);
|
|
29620
|
+
const prevLog = console.log;
|
|
29621
|
+
const prevInfo = console.info;
|
|
29622
|
+
const prevWarn = console.warn;
|
|
29623
|
+
const prevError = console.error;
|
|
29624
|
+
const prevStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
29625
|
+
const prevStderrWrite = process.stderr.write.bind(process.stderr);
|
|
29626
|
+
const shouldSuppress = (chunk) => {
|
|
29627
|
+
const s = typeof chunk === "string" ? chunk : chunk instanceof Uint8Array ? new TextDecoder().decode(chunk) : String(chunk);
|
|
29628
|
+
return s.includes("page_list") || s.includes("adjusting page") || s.includes("x icon") || s.includes("received and ignored");
|
|
29629
|
+
};
|
|
29630
|
+
const suppressed = (..._args) => {};
|
|
29631
|
+
const filteredError = (...args) => {
|
|
29632
|
+
if (args.some(shouldSuppress))
|
|
29633
|
+
return;
|
|
29634
|
+
prevError(...args);
|
|
29635
|
+
};
|
|
29636
|
+
console.log = suppressed;
|
|
29637
|
+
console.info = suppressed;
|
|
29638
|
+
console.warn = suppressed;
|
|
29639
|
+
console.error = filteredError;
|
|
29640
|
+
process.stdout.write = (chunk, ...rest) => {
|
|
29641
|
+
if (shouldSuppress(chunk))
|
|
29642
|
+
return true;
|
|
29643
|
+
return prevStdoutWrite(chunk, ...rest);
|
|
29644
|
+
};
|
|
29645
|
+
process.stderr.write = (chunk, ...rest) => {
|
|
29646
|
+
if (shouldSuppress(chunk))
|
|
29647
|
+
return true;
|
|
29648
|
+
return prevStderrWrite(chunk, ...rest);
|
|
29649
|
+
};
|
|
29650
|
+
let nativeStderrSaved = null;
|
|
29651
|
+
let nativeLib = null;
|
|
29652
|
+
try {
|
|
29653
|
+
const { dlopen, FFIType } = await import("bun:ffi");
|
|
29654
|
+
nativeLib = dlopen("/usr/lib/libSystem.B.dylib", {
|
|
29655
|
+
dup: { args: [FFIType.i32], returns: FFIType.i32 },
|
|
29656
|
+
dup2: { args: [FFIType.i32, FFIType.i32], returns: FFIType.i32 },
|
|
29657
|
+
open: { args: [FFIType.cstring, FFIType.i32], returns: FFIType.i32 },
|
|
29658
|
+
close: { args: [FFIType.i32], returns: FFIType.i32 }
|
|
29659
|
+
});
|
|
29660
|
+
const nullFd = nativeLib.symbols.open("/dev/null", 1);
|
|
29661
|
+
if (nullFd >= 0) {
|
|
29662
|
+
const saved = nativeLib.symbols.dup(2);
|
|
29663
|
+
if (saved >= 0) {
|
|
29664
|
+
nativeStderrSaved = saved;
|
|
29665
|
+
nativeLib.symbols.dup2(nullFd, 2);
|
|
29666
|
+
}
|
|
29667
|
+
nativeLib.symbols.close(nullFd);
|
|
29668
|
+
}
|
|
29669
|
+
} catch {}
|
|
29434
29670
|
const renderer = await createCliRenderer({
|
|
29435
|
-
exitOnCtrlC: false
|
|
29436
|
-
|
|
29671
|
+
exitOnCtrlC: false,
|
|
29672
|
+
consoleMode: "disabled"
|
|
29673
|
+
});
|
|
29674
|
+
const restoreConsole = () => {
|
|
29675
|
+
console.log = prevLog;
|
|
29676
|
+
console.info = prevInfo;
|
|
29677
|
+
console.warn = prevWarn;
|
|
29678
|
+
console.error = prevError;
|
|
29679
|
+
process.stdout.write = prevStdoutWrite;
|
|
29680
|
+
process.stderr.write = prevStderrWrite;
|
|
29681
|
+
if (nativeStderrSaved !== null && nativeStderrSaved >= 0 && nativeLib) {
|
|
29682
|
+
try {
|
|
29683
|
+
nativeLib.symbols.dup2(nativeStderrSaved, 2);
|
|
29684
|
+
nativeLib.symbols.close(nativeStderrSaved);
|
|
29685
|
+
} catch {}
|
|
29686
|
+
nativeStderrSaved = null;
|
|
29687
|
+
}
|
|
29688
|
+
setQuiet(false);
|
|
29689
|
+
};
|
|
29437
29690
|
const root = createRoot(renderer);
|
|
29438
29691
|
try {
|
|
29439
29692
|
root.render(/* @__PURE__ */ jsx18(App, {
|
|
29440
29693
|
opts
|
|
29441
29694
|
}));
|
|
29442
29695
|
} catch (err) {
|
|
29696
|
+
restoreConsole();
|
|
29443
29697
|
renderer.destroy();
|
|
29444
29698
|
console.error("Failed to render TUI:", err);
|
|
29445
29699
|
process.exit(1);
|
|
29446
29700
|
}
|
|
29701
|
+
const originalDestroy = renderer.destroy.bind(renderer);
|
|
29702
|
+
renderer.destroy = () => {
|
|
29703
|
+
restoreConsole();
|
|
29704
|
+
return originalDestroy();
|
|
29705
|
+
};
|
|
29447
29706
|
}
|
|
29448
29707
|
var init_tui = __esm(() => {
|
|
29708
|
+
init_env();
|
|
29449
29709
|
init_App();
|
|
29710
|
+
init_log();
|
|
29450
29711
|
extend2({ "text-table": TextTableRenderable, "embedded-terminal": EmbeddedTerminalRenderable });
|
|
29451
29712
|
});
|
|
29452
29713
|
|
|
@@ -34422,6 +34683,10 @@ function registerTerminalCommand(program2) {
|
|
|
34422
34683
|
`);
|
|
34423
34684
|
process.exit(1);
|
|
34424
34685
|
}
|
|
34686
|
+
process.env.RUST_LOG ??= "off";
|
|
34687
|
+
process.env.ZIG_LOG ??= "off";
|
|
34688
|
+
process.env.PAGE_LIST_LOG ??= "off";
|
|
34689
|
+
process.env.OPENTUI_LOG ??= "off";
|
|
34425
34690
|
const { runTerminal: runTerminal2 } = await Promise.resolve().then(() => (init_tui(), exports_tui));
|
|
34426
34691
|
await runTerminal2(opts);
|
|
34427
34692
|
});
|