vde-worktree 0.0.4 → 0.0.6
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.ja.md +31 -0
- package/README.md +30 -0
- package/dist/index.mjs +315 -30
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -5,10 +5,11 @@ import { access, appendFile, chmod, cp, mkdir, open, readFile, readdir, rename,
|
|
|
5
5
|
import { homedir, hostname } from "node:os";
|
|
6
6
|
import { dirname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
|
+
import chalk, { Chalk } from "chalk";
|
|
8
9
|
import { parseArgs } from "citty";
|
|
9
10
|
import { execa } from "execa";
|
|
11
|
+
import stringWidth from "string-width";
|
|
10
12
|
import { getBorderCharacters, table } from "table";
|
|
11
|
-
import chalk from "chalk";
|
|
12
13
|
|
|
13
14
|
//#region src/core/constants.ts
|
|
14
15
|
const SCHEMA_VERSION = 1;
|
|
@@ -1001,7 +1002,7 @@ const RESERVED_FZF_ARGS = new Set([
|
|
|
1001
1002
|
"height",
|
|
1002
1003
|
"border"
|
|
1003
1004
|
]);
|
|
1004
|
-
const sanitizeCandidate = (value) => value.replace(/[\
|
|
1005
|
+
const sanitizeCandidate = (value) => value.replace(/[\r\n]+/g, " ").trim();
|
|
1005
1006
|
const buildFzfInput = (candidates) => {
|
|
1006
1007
|
return candidates.map((candidate) => sanitizeCandidate(candidate)).filter((candidate) => candidate.length > 0).join("\n");
|
|
1007
1008
|
};
|
|
@@ -1152,11 +1153,149 @@ const loadPackageVersion = (requireFn) => {
|
|
|
1152
1153
|
//#region src/cli/index.ts
|
|
1153
1154
|
const EXIT_CODE_CANCELLED = 130;
|
|
1154
1155
|
const optionNamesAllowOptionLikeValue = new Set(["fzfArg", "fzf-arg"]);
|
|
1156
|
+
const CD_FZF_EXTRA_ARGS = [
|
|
1157
|
+
"--delimiter= ",
|
|
1158
|
+
"--with-nth=1",
|
|
1159
|
+
"--preview=printf '%b' {3}",
|
|
1160
|
+
"--preview-window=right,60%,wrap",
|
|
1161
|
+
"--ansi"
|
|
1162
|
+
];
|
|
1155
1163
|
const COMPLETION_SHELLS = ["zsh", "fish"];
|
|
1156
1164
|
const COMPLETION_FILE_BY_SHELL = {
|
|
1157
1165
|
zsh: "zsh/_vw",
|
|
1158
1166
|
fish: "fish/vw.fish"
|
|
1159
1167
|
};
|
|
1168
|
+
const CATPPUCCIN_MOCHA = {
|
|
1169
|
+
rosewater: "#f5e0dc",
|
|
1170
|
+
mauve: "#cba6f7",
|
|
1171
|
+
red: "#f38ba8",
|
|
1172
|
+
peach: "#fab387",
|
|
1173
|
+
yellow: "#f9e2af",
|
|
1174
|
+
green: "#a6e3a1",
|
|
1175
|
+
blue: "#89b4fa",
|
|
1176
|
+
lavender: "#b4befe",
|
|
1177
|
+
sapphire: "#74c7ec",
|
|
1178
|
+
text: "#cdd6f4",
|
|
1179
|
+
subtext0: "#a6adc8",
|
|
1180
|
+
overlay0: "#6c7086"
|
|
1181
|
+
};
|
|
1182
|
+
const identityColor = (value) => value;
|
|
1183
|
+
const createCatppuccinTheme = ({ enabled }) => {
|
|
1184
|
+
if (enabled !== true) return {
|
|
1185
|
+
header: identityColor,
|
|
1186
|
+
branch: identityColor,
|
|
1187
|
+
branchCurrent: identityColor,
|
|
1188
|
+
branchDetached: identityColor,
|
|
1189
|
+
dirty: identityColor,
|
|
1190
|
+
clean: identityColor,
|
|
1191
|
+
merged: identityColor,
|
|
1192
|
+
unmerged: identityColor,
|
|
1193
|
+
unknown: identityColor,
|
|
1194
|
+
base: identityColor,
|
|
1195
|
+
locked: identityColor,
|
|
1196
|
+
path: identityColor,
|
|
1197
|
+
muted: identityColor,
|
|
1198
|
+
value: identityColor,
|
|
1199
|
+
previewLabel: identityColor,
|
|
1200
|
+
previewSection: identityColor
|
|
1201
|
+
};
|
|
1202
|
+
const chalk = new Chalk({ level: 3 });
|
|
1203
|
+
const color = (hex) => (value) => chalk.hex(hex)(value);
|
|
1204
|
+
return {
|
|
1205
|
+
header: color(CATPPUCCIN_MOCHA.rosewater),
|
|
1206
|
+
branch: color(CATPPUCCIN_MOCHA.lavender),
|
|
1207
|
+
branchCurrent: color(CATPPUCCIN_MOCHA.mauve),
|
|
1208
|
+
branchDetached: color(CATPPUCCIN_MOCHA.peach),
|
|
1209
|
+
dirty: color(CATPPUCCIN_MOCHA.peach),
|
|
1210
|
+
clean: color(CATPPUCCIN_MOCHA.green),
|
|
1211
|
+
merged: color(CATPPUCCIN_MOCHA.green),
|
|
1212
|
+
unmerged: color(CATPPUCCIN_MOCHA.red),
|
|
1213
|
+
unknown: color(CATPPUCCIN_MOCHA.yellow),
|
|
1214
|
+
base: color(CATPPUCCIN_MOCHA.blue),
|
|
1215
|
+
locked: color(CATPPUCCIN_MOCHA.red),
|
|
1216
|
+
path: color(CATPPUCCIN_MOCHA.sapphire),
|
|
1217
|
+
muted: color(CATPPUCCIN_MOCHA.overlay0),
|
|
1218
|
+
value: color(CATPPUCCIN_MOCHA.text),
|
|
1219
|
+
previewLabel: color(CATPPUCCIN_MOCHA.mauve),
|
|
1220
|
+
previewSection: color(CATPPUCCIN_MOCHA.rosewater)
|
|
1221
|
+
};
|
|
1222
|
+
};
|
|
1223
|
+
const shouldUseAnsiColors = ({ interactive }) => {
|
|
1224
|
+
return interactive === true;
|
|
1225
|
+
};
|
|
1226
|
+
const colorizeCellContent = ({ cell, color }) => {
|
|
1227
|
+
const matched = /^(\s*)(.*?)(\s*)$/.exec(cell);
|
|
1228
|
+
if (matched === null) return cell;
|
|
1229
|
+
const leftPadding = matched[1] ?? "";
|
|
1230
|
+
const content = matched[2] ?? "";
|
|
1231
|
+
const rightPadding = matched[3] ?? "";
|
|
1232
|
+
if (content.length === 0) return cell;
|
|
1233
|
+
return `${leftPadding}${color(content)}${rightPadding}`;
|
|
1234
|
+
};
|
|
1235
|
+
const colorizeListTableLine = ({ line, theme }) => {
|
|
1236
|
+
if (line.startsWith("┌") || line.startsWith("├") || line.startsWith("└")) return theme.muted(line);
|
|
1237
|
+
if (line.startsWith("│") !== true) return line;
|
|
1238
|
+
const segments = line.split("│");
|
|
1239
|
+
if (segments.length < 3) return line;
|
|
1240
|
+
const cells = segments.slice(1, -1);
|
|
1241
|
+
if (cells.length !== 5) return line;
|
|
1242
|
+
const headers = cells.map((cell) => cell.trim());
|
|
1243
|
+
if (headers[0] === "branch" && headers[1] === "dirty" && headers[2] === "merged" && headers[3] === "locked" && headers[4] === "path") {
|
|
1244
|
+
const nextCells = cells.map((cell) => colorizeCellContent({
|
|
1245
|
+
cell,
|
|
1246
|
+
color: theme.header
|
|
1247
|
+
}));
|
|
1248
|
+
return [
|
|
1249
|
+
segments[0],
|
|
1250
|
+
...nextCells,
|
|
1251
|
+
segments.at(-1) ?? ""
|
|
1252
|
+
].join("│");
|
|
1253
|
+
}
|
|
1254
|
+
const branchCell = cells[0];
|
|
1255
|
+
const dirtyCell = cells[1];
|
|
1256
|
+
const mergedCell = cells[2];
|
|
1257
|
+
const lockedCell = cells[3];
|
|
1258
|
+
const pathCell = cells[4];
|
|
1259
|
+
const branchColor = branchCell.includes("(detached)") === true ? theme.branchDetached : branchCell.trimStart().startsWith("*") ? theme.branchCurrent : theme.branch;
|
|
1260
|
+
const dirtyTrimmed = dirtyCell.trim();
|
|
1261
|
+
const dirtyColor = dirtyTrimmed === "dirty" ? theme.dirty : dirtyTrimmed === "clean" ? theme.clean : theme.value;
|
|
1262
|
+
const mergedTrimmed = mergedCell.trim();
|
|
1263
|
+
const mergedColor = mergedTrimmed === "merged" ? theme.merged : mergedTrimmed === "unmerged" ? theme.unmerged : mergedTrimmed === "-" ? theme.base : theme.unknown;
|
|
1264
|
+
const lockedColor = lockedCell.trim() === "locked" ? theme.locked : theme.muted;
|
|
1265
|
+
const nextCells = [
|
|
1266
|
+
colorizeCellContent({
|
|
1267
|
+
cell: branchCell,
|
|
1268
|
+
color: branchColor
|
|
1269
|
+
}),
|
|
1270
|
+
colorizeCellContent({
|
|
1271
|
+
cell: dirtyCell,
|
|
1272
|
+
color: dirtyColor
|
|
1273
|
+
}),
|
|
1274
|
+
colorizeCellContent({
|
|
1275
|
+
cell: mergedCell,
|
|
1276
|
+
color: mergedColor
|
|
1277
|
+
}),
|
|
1278
|
+
colorizeCellContent({
|
|
1279
|
+
cell: lockedCell,
|
|
1280
|
+
color: lockedColor
|
|
1281
|
+
}),
|
|
1282
|
+
colorizeCellContent({
|
|
1283
|
+
cell: pathCell,
|
|
1284
|
+
color: theme.path
|
|
1285
|
+
})
|
|
1286
|
+
];
|
|
1287
|
+
return [
|
|
1288
|
+
segments[0],
|
|
1289
|
+
...nextCells,
|
|
1290
|
+
segments.at(-1) ?? ""
|
|
1291
|
+
].join("│");
|
|
1292
|
+
};
|
|
1293
|
+
const colorizeListTable = ({ rendered, theme }) => {
|
|
1294
|
+
return rendered.trimEnd().split("\n").map((line) => colorizeListTableLine({
|
|
1295
|
+
line,
|
|
1296
|
+
theme
|
|
1297
|
+
})).join("\n");
|
|
1298
|
+
};
|
|
1160
1299
|
const commandHelpEntries = [
|
|
1161
1300
|
{
|
|
1162
1301
|
name: "init",
|
|
@@ -1407,6 +1546,11 @@ const collectOptionValues = ({ args, optionNames }) => {
|
|
|
1407
1546
|
}
|
|
1408
1547
|
return values;
|
|
1409
1548
|
};
|
|
1549
|
+
const mergeFzfArgs = ({ defaults, extras }) => {
|
|
1550
|
+
const merged = [...defaults];
|
|
1551
|
+
for (const arg of extras) if (merged.includes(arg) !== true) merged.push(arg);
|
|
1552
|
+
return merged;
|
|
1553
|
+
};
|
|
1410
1554
|
const toNumberOption = ({ value, optionName }) => {
|
|
1411
1555
|
if (value === void 0) return;
|
|
1412
1556
|
if (typeof value !== "string") throw createCliError("INVALID_ARGUMENT", { message: `${optionName} must be a number` });
|
|
@@ -1728,6 +1872,124 @@ const formatDisplayPath = (absolutePath) => {
|
|
|
1728
1872
|
if (absolutePath.startsWith(`${homeDirectory}${sep}`)) return `~${absolutePath.slice(homeDirectory.length)}`;
|
|
1729
1873
|
return absolutePath;
|
|
1730
1874
|
};
|
|
1875
|
+
const encodeCdPreviewField = (value) => {
|
|
1876
|
+
return value.replace(/\\/g, "\\\\").split("\x1B").join("\\033").replace(/\t/g, " ").replace(/\r\n?/g, "\n").replace(/\n/g, "\\n");
|
|
1877
|
+
};
|
|
1878
|
+
const formatMergedDisplayState = ({ mergedOverall, isBaseBranch, baseLabel = "base" }) => {
|
|
1879
|
+
if (isBaseBranch) return baseLabel;
|
|
1880
|
+
if (mergedOverall === true) return "merged";
|
|
1881
|
+
if (mergedOverall === false) return "unmerged";
|
|
1882
|
+
return "unknown";
|
|
1883
|
+
};
|
|
1884
|
+
const formatMergedColor = ({ mergedState, theme }) => {
|
|
1885
|
+
const normalized = mergedState.toLowerCase();
|
|
1886
|
+
if (normalized === "merged") return theme.merged(mergedState);
|
|
1887
|
+
if (normalized === "unmerged") return theme.unmerged(mergedState);
|
|
1888
|
+
if (normalized === "base") return theme.base(mergedState);
|
|
1889
|
+
return theme.unknown(mergedState);
|
|
1890
|
+
};
|
|
1891
|
+
const padToDisplayWidth = ({ value, width }) => {
|
|
1892
|
+
const visibleLength = stringWidth(value);
|
|
1893
|
+
if (visibleLength >= width) return value;
|
|
1894
|
+
return `${value}${" ".repeat(width - visibleLength)}`;
|
|
1895
|
+
};
|
|
1896
|
+
const buildCdBranchLabel = ({ worktree, currentWorktreeRoot }) => {
|
|
1897
|
+
return `${worktree.path === currentWorktreeRoot ? "*" : " "} ${worktree.branch ?? "(detached)"}`;
|
|
1898
|
+
};
|
|
1899
|
+
const buildCdStateSummary = ({ worktree, isBaseBranch, theme }) => {
|
|
1900
|
+
const dirtyLabel = worktree.dirty ? "DIRTY" : "CLEAN";
|
|
1901
|
+
const mergedLabel = formatMergedDisplayState({
|
|
1902
|
+
mergedOverall: worktree.merged.overall,
|
|
1903
|
+
isBaseBranch
|
|
1904
|
+
}).toUpperCase();
|
|
1905
|
+
const lockLabel = worktree.locked.value ? "LOCK" : "OPEN";
|
|
1906
|
+
const dirtyBadge = (worktree.dirty ? theme.unmerged : theme.clean)(padToDisplayWidth({
|
|
1907
|
+
value: dirtyLabel,
|
|
1908
|
+
width: 5
|
|
1909
|
+
}));
|
|
1910
|
+
const mergedBadge = formatMergedColor({
|
|
1911
|
+
mergedState: padToDisplayWidth({
|
|
1912
|
+
value: mergedLabel,
|
|
1913
|
+
width: 8
|
|
1914
|
+
}),
|
|
1915
|
+
theme
|
|
1916
|
+
});
|
|
1917
|
+
const lockBadge = (worktree.locked.value ? theme.locked : theme.muted)(padToDisplayWidth({
|
|
1918
|
+
value: lockLabel,
|
|
1919
|
+
width: 4
|
|
1920
|
+
}));
|
|
1921
|
+
return `${dirtyBadge} ${theme.muted("|")} ${mergedBadge} ${theme.muted("|")} ${lockBadge}`;
|
|
1922
|
+
};
|
|
1923
|
+
const buildCdPreviewText = ({ worktree, baseBranch, theme }) => {
|
|
1924
|
+
const isBaseBranch = typeof worktree.branch === "string" && baseBranch !== null && worktree.branch === baseBranch;
|
|
1925
|
+
const branchLabel = worktree.branch === null ? theme.branchDetached("(detached)") : isBaseBranch ? theme.base(worktree.branch) : theme.branch(worktree.branch);
|
|
1926
|
+
const pathLabel = theme.path(formatDisplayPath(worktree.path));
|
|
1927
|
+
const dirtyValue = worktree.dirty ? theme.unmerged("[DIRTY]") : theme.merged("[CLEAN]");
|
|
1928
|
+
const lockedValue = worktree.locked.value ? theme.locked("[LOCKED]") : theme.clean("[OPEN]");
|
|
1929
|
+
const mergedValue = formatMergedColor({
|
|
1930
|
+
mergedState: formatMergedDisplayState({
|
|
1931
|
+
mergedOverall: worktree.merged.overall,
|
|
1932
|
+
isBaseBranch
|
|
1933
|
+
}).toUpperCase(),
|
|
1934
|
+
theme
|
|
1935
|
+
});
|
|
1936
|
+
const remoteValue = worktree.upstream.remote === null ? theme.muted("none") : theme.value(worktree.upstream.remote ?? "none");
|
|
1937
|
+
const aheadValue = worktree.upstream.ahead === null ? theme.unknown("UNKNOWN") : worktree.upstream.ahead > 0 ? theme.unmerged(String(worktree.upstream.ahead)) : theme.merged("0");
|
|
1938
|
+
const behindValue = worktree.upstream.behind === null ? theme.unknown("UNKNOWN") : worktree.upstream.behind > 0 ? theme.unknown(String(worktree.upstream.behind)) : theme.merged("0");
|
|
1939
|
+
const divider = theme.muted("----------------------------------------");
|
|
1940
|
+
const lines = [
|
|
1941
|
+
theme.previewSection("WORKTREE"),
|
|
1942
|
+
divider,
|
|
1943
|
+
` ${theme.previewLabel("Branch ")}: ${branchLabel}`,
|
|
1944
|
+
` ${theme.previewLabel("Path ")}: ${pathLabel}`,
|
|
1945
|
+
"",
|
|
1946
|
+
theme.previewSection("STATUS"),
|
|
1947
|
+
divider,
|
|
1948
|
+
` ${theme.previewLabel("Dirty ")}: ${dirtyValue}`,
|
|
1949
|
+
` ${theme.previewLabel("Locked ")}: ${lockedValue}`,
|
|
1950
|
+
` ${theme.previewLabel("Merged ")}: ${mergedValue}`,
|
|
1951
|
+
` ${theme.previewLabel("Remote ")}: ${remoteValue}`,
|
|
1952
|
+
` ${theme.previewLabel("Ahead ")}: ${aheadValue}`,
|
|
1953
|
+
` ${theme.previewLabel("Behind ")}: ${behindValue}`
|
|
1954
|
+
];
|
|
1955
|
+
if (worktree.locked.value) {
|
|
1956
|
+
lines.push("");
|
|
1957
|
+
lines.push(theme.previewSection("LOCK"));
|
|
1958
|
+
lines.push(divider);
|
|
1959
|
+
if (typeof worktree.locked.reason === "string" && worktree.locked.reason.length > 0) lines.push(` ${theme.previewLabel("Reason ")}: ${theme.value(worktree.locked.reason)}`);
|
|
1960
|
+
if (typeof worktree.locked.owner === "string" && worktree.locked.owner.length > 0) lines.push(` ${theme.previewLabel("Owner ")}: ${theme.value(worktree.locked.owner)}`);
|
|
1961
|
+
}
|
|
1962
|
+
return lines.join("\n");
|
|
1963
|
+
};
|
|
1964
|
+
const buildCdCandidateLine = ({ worktree, baseBranch, theme, currentWorktreeRoot, branchColumnWidth }) => {
|
|
1965
|
+
const isBaseBranch = typeof worktree.branch === "string" && baseBranch !== null && worktree.branch === baseBranch;
|
|
1966
|
+
const branchLabelPadded = padToDisplayWidth({
|
|
1967
|
+
value: buildCdBranchLabel({
|
|
1968
|
+
worktree,
|
|
1969
|
+
currentWorktreeRoot
|
|
1970
|
+
}),
|
|
1971
|
+
width: branchColumnWidth
|
|
1972
|
+
});
|
|
1973
|
+
const isCurrent = worktree.path === currentWorktreeRoot;
|
|
1974
|
+
return [
|
|
1975
|
+
`${worktree.branch === null ? theme.branchDetached(branchLabelPadded) : isCurrent ? theme.branchCurrent(branchLabelPadded) : isBaseBranch ? theme.base(branchLabelPadded) : theme.branch(branchLabelPadded)} ${buildCdStateSummary({
|
|
1976
|
+
worktree,
|
|
1977
|
+
isBaseBranch,
|
|
1978
|
+
theme
|
|
1979
|
+
})}`,
|
|
1980
|
+
worktree.path,
|
|
1981
|
+
encodeCdPreviewField(buildCdPreviewText({
|
|
1982
|
+
worktree,
|
|
1983
|
+
baseBranch,
|
|
1984
|
+
theme
|
|
1985
|
+
}))
|
|
1986
|
+
].join(" ");
|
|
1987
|
+
};
|
|
1988
|
+
const resolveCdSelectionPath = (selectedLine) => {
|
|
1989
|
+
const rawPath = selectedLine.split(" ")[1];
|
|
1990
|
+
if (typeof rawPath === "string" && rawPath.length > 0) return rawPath;
|
|
1991
|
+
return selectedLine;
|
|
1992
|
+
};
|
|
1731
1993
|
const containsBranch = ({ branch, worktrees }) => {
|
|
1732
1994
|
return worktrees.some((worktree) => worktree.branch === branch);
|
|
1733
1995
|
};
|
|
@@ -2164,28 +2426,32 @@ const createCli = (options = {}) => {
|
|
|
2164
2426
|
})));
|
|
2165
2427
|
return EXIT_CODE.OK;
|
|
2166
2428
|
}
|
|
2167
|
-
const
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2429
|
+
const theme = createCatppuccinTheme({ enabled: shouldUseAnsiColors({ interactive: runtime.isInteractive }) });
|
|
2430
|
+
const colorized = colorizeListTable({
|
|
2431
|
+
rendered: table([[
|
|
2432
|
+
"branch",
|
|
2433
|
+
"dirty",
|
|
2434
|
+
"merged",
|
|
2435
|
+
"locked",
|
|
2436
|
+
"path"
|
|
2437
|
+
], ...snapshot.worktrees.map((worktree) => {
|
|
2438
|
+
const mergedState = (worktree.branch !== null && snapshot.baseBranch !== null && worktree.branch === snapshot.baseBranch) === true ? "-" : worktree.merged.overall === true ? "merged" : worktree.merged.overall === false ? "unmerged" : "unknown";
|
|
2439
|
+
return [
|
|
2440
|
+
`${worktree.path === repoContext.currentWorktreeRoot ? "*" : " "} ${worktree.branch ?? "(detached)"}`,
|
|
2441
|
+
worktree.dirty ? "dirty" : "clean",
|
|
2442
|
+
mergedState,
|
|
2443
|
+
worktree.locked.value ? "locked" : "-",
|
|
2444
|
+
formatDisplayPath(worktree.path)
|
|
2445
|
+
];
|
|
2446
|
+
})], {
|
|
2447
|
+
border: getBorderCharacters("norc"),
|
|
2448
|
+
drawHorizontalLine: (lineIndex, rowCount) => {
|
|
2449
|
+
return lineIndex === 0 || lineIndex === 1 || lineIndex === rowCount;
|
|
2450
|
+
}
|
|
2451
|
+
}),
|
|
2452
|
+
theme
|
|
2187
2453
|
});
|
|
2188
|
-
for (const line of
|
|
2454
|
+
for (const line of colorized.split("\n")) stdout(line);
|
|
2189
2455
|
return EXIT_CODE.OK;
|
|
2190
2456
|
}
|
|
2191
2457
|
if (command === "status") {
|
|
@@ -2581,7 +2847,7 @@ const createCli = (options = {}) => {
|
|
|
2581
2847
|
if (parsedArgs.apply === true && parsedArgs.dryRun === true) throw createCliError("INVALID_ARGUMENT", { message: "Cannot use --apply and --dry-run together" });
|
|
2582
2848
|
const dryRun = parsedArgs.apply !== true;
|
|
2583
2849
|
const execute = async () => {
|
|
2584
|
-
const candidates = (await collectWorktreeSnapshot(repoRoot)).worktrees.filter((worktree) => worktree.branch !== null).filter((worktree) => worktree.path !== repoRoot).filter((worktree) => worktree.dirty === false).filter((worktree) => worktree.locked.value === false).filter((worktree) => worktree.merged.
|
|
2850
|
+
const candidates = (await collectWorktreeSnapshot(repoRoot)).worktrees.filter((worktree) => worktree.branch !== null).filter((worktree) => worktree.path !== repoRoot).filter((worktree) => worktree.dirty === false).filter((worktree) => worktree.locked.value === false).filter((worktree) => worktree.merged.byAncestry === true).map((worktree) => worktree.branch);
|
|
2585
2851
|
if (dryRun) return {
|
|
2586
2852
|
deleted: [],
|
|
2587
2853
|
candidates,
|
|
@@ -3292,15 +3558,33 @@ const createCli = (options = {}) => {
|
|
|
3292
3558
|
min: 0,
|
|
3293
3559
|
max: 0
|
|
3294
3560
|
});
|
|
3295
|
-
const
|
|
3561
|
+
const snapshot = await collectWorktreeSnapshot(repoRoot);
|
|
3562
|
+
const theme = createCatppuccinTheme({ enabled: shouldUseAnsiColors({ interactive: runtime.isInteractive }) });
|
|
3563
|
+
const branchColumnWidth = snapshot.worktrees.reduce((maxWidth, worktree) => {
|
|
3564
|
+
const label = buildCdBranchLabel({
|
|
3565
|
+
worktree,
|
|
3566
|
+
currentWorktreeRoot: repoContext.currentWorktreeRoot
|
|
3567
|
+
});
|
|
3568
|
+
return Math.max(maxWidth, stringWidth(label));
|
|
3569
|
+
}, 0);
|
|
3570
|
+
const candidates = snapshot.worktrees.map((worktree) => buildCdCandidateLine({
|
|
3571
|
+
worktree,
|
|
3572
|
+
baseBranch: snapshot.baseBranch,
|
|
3573
|
+
theme,
|
|
3574
|
+
currentWorktreeRoot: repoContext.currentWorktreeRoot,
|
|
3575
|
+
branchColumnWidth
|
|
3576
|
+
}));
|
|
3296
3577
|
if (candidates.length === 0) throw createCliError("WORKTREE_NOT_FOUND", { message: "No worktree candidates found" });
|
|
3297
3578
|
const promptValue = readStringOption(parsedArgsRecord, "prompt");
|
|
3298
3579
|
const selection = await selectPathWithFzf$1({
|
|
3299
3580
|
candidates,
|
|
3300
3581
|
prompt: typeof promptValue === "string" && promptValue.length > 0 ? promptValue : "worktree> ",
|
|
3301
|
-
fzfExtraArgs:
|
|
3302
|
-
|
|
3303
|
-
|
|
3582
|
+
fzfExtraArgs: mergeFzfArgs({
|
|
3583
|
+
defaults: CD_FZF_EXTRA_ARGS,
|
|
3584
|
+
extras: collectOptionValues({
|
|
3585
|
+
args: beforeDoubleDash,
|
|
3586
|
+
optionNames: ["fzfArg", "fzf-arg"]
|
|
3587
|
+
})
|
|
3304
3588
|
}),
|
|
3305
3589
|
cwd: repoRoot,
|
|
3306
3590
|
isInteractive: () => runtime.isInteractive || process.stderr.isTTY === true
|
|
@@ -3310,16 +3594,17 @@ const createCli = (options = {}) => {
|
|
|
3310
3594
|
throw error;
|
|
3311
3595
|
});
|
|
3312
3596
|
if (selection.status === "cancelled") return EXIT_CODE_CANCELLED;
|
|
3597
|
+
const selectedPath = resolveCdSelectionPath(selection.path);
|
|
3313
3598
|
if (runtime.json) {
|
|
3314
3599
|
stdout(JSON.stringify(buildJsonSuccess({
|
|
3315
3600
|
command,
|
|
3316
3601
|
status: "ok",
|
|
3317
3602
|
repoRoot,
|
|
3318
|
-
details: { path:
|
|
3603
|
+
details: { path: selectedPath }
|
|
3319
3604
|
})));
|
|
3320
3605
|
return EXIT_CODE.OK;
|
|
3321
3606
|
}
|
|
3322
|
-
stdout(
|
|
3607
|
+
stdout(selectedPath);
|
|
3323
3608
|
return EXIT_CODE.OK;
|
|
3324
3609
|
}
|
|
3325
3610
|
throw createCliError("UNKNOWN_COMMAND", { message: `Unknown command: ${command}` });
|