@ogpoyraz/wtx 0.8.1 → 0.8.2
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/README.md +1 -1
- package/dist/cli.mjs +40 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -169,7 +169,7 @@ Config lives at `~/.config/wtx/config.json`.
|
|
|
169
169
|
| `agents.<name>.command` | – | Shell command template for `--agent`; `{wt}`, `{branch}`, `{repo}` expanded |
|
|
170
170
|
| `repos.<name>.main_branch` | `"auto"` | Auto-detects via `git symbolic-ref` |
|
|
171
171
|
| `repos.<name>.fetch_main_on_create` | `true` | Fetch before creating so branches start fresh |
|
|
172
|
-
| `repos.<name>.sync_files` | `[]` | Files copied from main checkout on create and sync |
|
|
172
|
+
| `repos.<name>.sync_files` | `[]` | Files or folders copied from main checkout on create and sync — directories are copied recursively (`build/`) |
|
|
173
173
|
| `repos.<name>.post_create` / `post_sync` | `[]` | Hook commands; failures fail the command with a rerun hint |
|
|
174
174
|
| `repos.<name>.install_script` | `null` | Command run inside a worktree (or the main checkout via `wtx deps --install`) for dependency installs (`{wt}`, `{branch}`, `{main}` expanded); when unset, the detected package manager performs a real install |
|
|
175
175
|
| `repos.<name>.deps.manager` | `"auto"` | Force a manager: `npm` `bun` `pnpm` `yarn` `go` `python` `cargo` |
|
package/dist/cli.mjs
CHANGED
|
@@ -26388,7 +26388,8 @@ var init_HelpOverlay = __esm(() => {
|
|
|
26388
26388
|
["e", "View data warnings (when count > 0)"],
|
|
26389
26389
|
["r", "Refresh data"],
|
|
26390
26390
|
["H", "Action history"],
|
|
26391
|
-
["
|
|
26391
|
+
["mouse drag", "Select text — copied to clipboard automatically"],
|
|
26392
|
+
["ctrl+shift+c", "Copy selection again (terminals reserve cmd+c)"],
|
|
26392
26393
|
["click PR #/URL", "Open pull request in browser"],
|
|
26393
26394
|
["?", "Toggle help"],
|
|
26394
26395
|
["q/esc", "Quit"]
|
|
@@ -26738,8 +26739,8 @@ var init_HistoryOverlay = __esm(() => {
|
|
|
26738
26739
|
// src/tui/components/InputModal.tsx
|
|
26739
26740
|
import { useState as useState3 } from "react";
|
|
26740
26741
|
import { jsx as jsx9, jsxs as jsxs8 } from "@opentui/react/jsx-runtime";
|
|
26741
|
-
function InputModal({ title, placeholder, errorMessage, onSubmit }) {
|
|
26742
|
-
const [value, setValue] = useState3("");
|
|
26742
|
+
function InputModal({ title, placeholder, initialValue, errorMessage, onSubmit }) {
|
|
26743
|
+
const [value, setValue] = useState3(initialValue ?? "");
|
|
26743
26744
|
return /* @__PURE__ */ jsx9(Overlay, {
|
|
26744
26745
|
title,
|
|
26745
26746
|
borderColor: tokens.accent,
|
|
@@ -26748,6 +26749,7 @@ function InputModal({ title, placeholder, errorMessage, onSubmit }) {
|
|
|
26748
26749
|
children: [
|
|
26749
26750
|
/* @__PURE__ */ jsx9("input", {
|
|
26750
26751
|
focused: true,
|
|
26752
|
+
value: initialValue ?? "",
|
|
26751
26753
|
placeholder,
|
|
26752
26754
|
onInput: (val) => setValue(val),
|
|
26753
26755
|
onSubmit: () => onSubmit(value)
|
|
@@ -27195,7 +27197,8 @@ function ConfigOverlay({ onClose, onSaved, onError }) {
|
|
|
27195
27197
|
}),
|
|
27196
27198
|
editState.type === "input" && /* @__PURE__ */ jsx11(InputModal, {
|
|
27197
27199
|
title: editState.title,
|
|
27198
|
-
|
|
27200
|
+
initialValue: editState.currentValue,
|
|
27201
|
+
placeholder: "Enter value...",
|
|
27199
27202
|
errorMessage: editState.error,
|
|
27200
27203
|
onSubmit: handleInputSubmit
|
|
27201
27204
|
}),
|
|
@@ -27275,7 +27278,7 @@ var init_useSpinnerFrame = __esm(() => {
|
|
|
27275
27278
|
|
|
27276
27279
|
// src/tui/components/App.tsx
|
|
27277
27280
|
import { useState as useState7, useEffect as useEffect6, useMemo, useRef as useRef4, useCallback as useCallback3 } from "react";
|
|
27278
|
-
import { useKeyboard as useKeyboard3, useRenderer } from "@opentui/react";
|
|
27281
|
+
import { useKeyboard as useKeyboard3, useRenderer, useSelectionHandler } from "@opentui/react";
|
|
27279
27282
|
import { jsx as jsx13, jsxs as jsxs12 } from "@opentui/react/jsx-runtime";
|
|
27280
27283
|
function getWorktreePathFor(repoName, branch) {
|
|
27281
27284
|
try {
|
|
@@ -27330,6 +27333,16 @@ function App({ opts }) {
|
|
|
27330
27333
|
setActionMessage(message);
|
|
27331
27334
|
messageTimer.current = setTimeout(() => setActionMessage(undefined), ms);
|
|
27332
27335
|
}, []);
|
|
27336
|
+
const copySelectedText = useCallback3((warnOnEmpty) => {
|
|
27337
|
+
const text = renderer.getSelection()?.getSelectedText() ?? "";
|
|
27338
|
+
if (!text) {
|
|
27339
|
+
if (warnOnEmpty)
|
|
27340
|
+
flash("Nothing selected to copy");
|
|
27341
|
+
return;
|
|
27342
|
+
}
|
|
27343
|
+
copyTextToClipboard(renderer, text).then((ok) => flash(ok ? `Copied ${text.length} character${text.length !== 1 ? "s" : ""}` : "Copy failed"));
|
|
27344
|
+
}, [renderer, flash]);
|
|
27345
|
+
useSelectionHandler(() => copySelectedText(false));
|
|
27333
27346
|
const busyRepos = useMemo(() => new Set(ops.flatMap((o2) => o2.repoNames)), [ops]);
|
|
27334
27347
|
const busyRowPaths = useMemo(() => new Set(ops.map((o2) => o2.rowPath).filter((p) => p !== undefined)), [ops]);
|
|
27335
27348
|
const anyRunning = ops.some((o2) => o2.status === "running");
|
|
@@ -27564,12 +27577,7 @@ function App({ opts }) {
|
|
|
27564
27577
|
}
|
|
27565
27578
|
}
|
|
27566
27579
|
if ((key.super || key.meta || key.ctrl && key.shift) && key.name === "c") {
|
|
27567
|
-
|
|
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"));
|
|
27580
|
+
copySelectedText(true);
|
|
27573
27581
|
return;
|
|
27574
27582
|
}
|
|
27575
27583
|
if (key.name === "q" || key.name === "escape" || key.name === "c" && key.ctrl) {
|
|
@@ -27932,7 +27940,8 @@ function App({ opts }) {
|
|
|
27932
27940
|
}),
|
|
27933
27941
|
renameModal && selectedRow && /* @__PURE__ */ jsx13(InputModal, {
|
|
27934
27942
|
title: `Rename branch ${selectedRow.branch}`,
|
|
27935
|
-
|
|
27943
|
+
initialValue: selectedRow.branch,
|
|
27944
|
+
placeholder: "New branch name",
|
|
27936
27945
|
errorMessage: renameError,
|
|
27937
27946
|
onSubmit: (value) => {
|
|
27938
27947
|
const target = selectedRow;
|
|
@@ -30315,20 +30324,29 @@ async function getWorktreePort(repoName, branch, config2, currentWtPath) {
|
|
|
30315
30324
|
}
|
|
30316
30325
|
|
|
30317
30326
|
// src/lib/worktree-setup.ts
|
|
30327
|
+
function syncEntry(mainPath, wtPath, entry) {
|
|
30328
|
+
const src = path17.join(mainPath, entry);
|
|
30329
|
+
const dest = path17.join(wtPath, entry);
|
|
30330
|
+
if (!fs10.existsSync(src))
|
|
30331
|
+
return false;
|
|
30332
|
+
fs10.mkdirSync(path17.dirname(dest), { recursive: true });
|
|
30333
|
+
if (fs10.statSync(src).isDirectory()) {
|
|
30334
|
+
fs10.cpSync(src, dest, { recursive: true });
|
|
30335
|
+
} else {
|
|
30336
|
+
fs10.copyFileSync(src, dest);
|
|
30337
|
+
}
|
|
30338
|
+
return true;
|
|
30339
|
+
}
|
|
30318
30340
|
async function runPostCreateSetup(params) {
|
|
30319
30341
|
const { config: config2, repo, wtPath, branch, globalOpts } = params;
|
|
30320
30342
|
let copiedFiles = [];
|
|
30321
30343
|
let hooks = [];
|
|
30322
30344
|
if (repo.config.sync_files && repo.config.sync_files.length > 0) {
|
|
30323
30345
|
for (const file2 of repo.config.sync_files) {
|
|
30324
|
-
|
|
30325
|
-
|
|
30326
|
-
|
|
30327
|
-
|
|
30328
|
-
fs10.mkdirSync(path17.dirname(dest), { recursive: true });
|
|
30329
|
-
fs10.copyFileSync(src, dest);
|
|
30330
|
-
copiedFiles.push(file2);
|
|
30331
|
-
}
|
|
30346
|
+
if (!globalOpts.dryRun && syncEntry(repo.mainPath, wtPath, file2)) {
|
|
30347
|
+
copiedFiles.push(file2);
|
|
30348
|
+
}
|
|
30349
|
+
if (fs10.existsSync(path17.join(repo.mainPath, file2))) {
|
|
30332
30350
|
stepSuccess(`Synced ${file2}`);
|
|
30333
30351
|
} else {
|
|
30334
30352
|
stepWarning(`Could not sync ${file2}`, "file not found in main checkout");
|
|
@@ -31709,12 +31727,9 @@ function registerSyncCommand(program2) {
|
|
|
31709
31727
|
try {
|
|
31710
31728
|
if (repo.config.sync_files) {
|
|
31711
31729
|
for (const file2 of repo.config.sync_files) {
|
|
31712
|
-
|
|
31713
|
-
const dest = path32.join(wtPath, file2);
|
|
31714
|
-
if (fs25.existsSync(src)) {
|
|
31730
|
+
if (fs25.existsSync(path32.join(repo.mainPath, file2))) {
|
|
31715
31731
|
if (!opts.dryRun) {
|
|
31716
|
-
|
|
31717
|
-
fs25.copyFileSync(src, dest);
|
|
31732
|
+
syncEntry(repo.mainPath, wtPath, file2);
|
|
31718
31733
|
}
|
|
31719
31734
|
stepSuccess(`Synced ${file2}`);
|
|
31720
31735
|
}
|