clawt 2.19.0 → 2.20.0
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 +2 -2
- package/dist/index.js +234 -89
- package/dist/postinstall.js +4 -0
- package/docs/spec.md +30 -4
- package/package.json +1 -1
- package/src/commands/resume.ts +8 -2
- package/src/constants/index.ts +1 -1
- package/src/constants/prompt.ts +28 -0
- package/src/utils/index.ts +1 -1
- package/src/utils/worktree-matcher.ts +268 -1
- package/tests/unit/commands/resume.test.ts +29 -8
- package/tests/unit/utils/worktree-matcher.test.ts +142 -1
package/dist/index.js
CHANGED
|
@@ -567,8 +567,14 @@ var CLEAR_SCREEN = "\x1B[2J";
|
|
|
567
567
|
var CURSOR_HOME = "\x1B[H";
|
|
568
568
|
|
|
569
569
|
// src/constants/prompt.ts
|
|
570
|
+
import chalk from "chalk";
|
|
570
571
|
var SELECT_ALL_NAME = "__select_all__";
|
|
571
572
|
var SELECT_ALL_LABEL = "[select-all]";
|
|
573
|
+
var GROUP_SELECT_ALL_PREFIX = "__group_select_all_";
|
|
574
|
+
var GROUP_SELECT_ALL_LABEL = (dateLabel) => `[select-all: ${dateLabel}]`;
|
|
575
|
+
var GROUP_SEPARATOR_LABEL = (dateLabel, relativeTime) => `\u2550\u2550\u2550\u2550 ${chalk.bold.hex("#FF8C00")(dateLabel)}\uFF08${chalk.hex("#FF8C00")(relativeTime)}\uFF09 \u2550\u2550\u2550\u2550`;
|
|
576
|
+
var UNKNOWN_DATE_GROUP = "\u672A\u77E5\u65E5\u671F";
|
|
577
|
+
var UNKNOWN_DATE_SEPARATOR_LABEL = `\u2550\u2550\u2550\u2550 ${chalk.bold.hex("#FF8C00")("\u672A\u77E5\u65E5\u671F")} \u2550\u2550\u2550\u2550`;
|
|
572
578
|
|
|
573
579
|
// src/errors/index.ts
|
|
574
580
|
var ClawtError = class extends Error {
|
|
@@ -588,7 +594,7 @@ var ClawtError = class extends Error {
|
|
|
588
594
|
// src/logger/index.ts
|
|
589
595
|
import winston from "winston";
|
|
590
596
|
import DailyRotateFile from "winston-daily-rotate-file";
|
|
591
|
-
import
|
|
597
|
+
import chalk2 from "chalk";
|
|
592
598
|
import { existsSync, mkdirSync } from "fs";
|
|
593
599
|
if (!existsSync(LOGS_DIR)) {
|
|
594
600
|
mkdirSync(LOGS_DIR, { recursive: true });
|
|
@@ -613,13 +619,13 @@ var logger = winston.createLogger({
|
|
|
613
619
|
transports: [dailyRotateTransport]
|
|
614
620
|
});
|
|
615
621
|
var LEVEL_COLORS = {
|
|
616
|
-
error:
|
|
617
|
-
warn:
|
|
618
|
-
info:
|
|
619
|
-
debug:
|
|
622
|
+
error: chalk2.red,
|
|
623
|
+
warn: chalk2.yellow,
|
|
624
|
+
info: chalk2.cyan,
|
|
625
|
+
debug: chalk2.gray
|
|
620
626
|
};
|
|
621
627
|
function colorizeLevel(level) {
|
|
622
|
-
const colorFn = LEVEL_COLORS[level] ||
|
|
628
|
+
const colorFn = LEVEL_COLORS[level] || chalk2.white;
|
|
623
629
|
return colorFn(level.toUpperCase().padEnd(5));
|
|
624
630
|
}
|
|
625
631
|
function enableConsoleTransport() {
|
|
@@ -630,7 +636,7 @@ function enableConsoleTransport() {
|
|
|
630
636
|
return;
|
|
631
637
|
}
|
|
632
638
|
const consoleFormat = winston.format.printf(({ level, message, timestamp }) => {
|
|
633
|
-
return `${
|
|
639
|
+
return `${chalk2.gray(timestamp)} ${colorizeLevel(level)} ${message}`;
|
|
634
640
|
});
|
|
635
641
|
const consoleTransport = new winston.transports.Console({
|
|
636
642
|
level: "debug",
|
|
@@ -898,22 +904,22 @@ function getBranchCreatedAt(branchName, cwd) {
|
|
|
898
904
|
}
|
|
899
905
|
|
|
900
906
|
// src/utils/formatter.ts
|
|
901
|
-
import
|
|
907
|
+
import chalk3 from "chalk";
|
|
902
908
|
import { createInterface } from "readline";
|
|
903
909
|
function printSuccess(message) {
|
|
904
|
-
console.log(
|
|
910
|
+
console.log(chalk3.green(message));
|
|
905
911
|
}
|
|
906
912
|
function printError(message) {
|
|
907
|
-
console.error(
|
|
913
|
+
console.error(chalk3.red(`\u2717 ${message}`));
|
|
908
914
|
}
|
|
909
915
|
function printWarning(message) {
|
|
910
|
-
console.log(
|
|
916
|
+
console.log(chalk3.yellow(`\u26A0 ${message}`));
|
|
911
917
|
}
|
|
912
918
|
function printInfo(message) {
|
|
913
919
|
console.log(message);
|
|
914
920
|
}
|
|
915
921
|
function printHint(message) {
|
|
916
|
-
console.log(
|
|
922
|
+
console.log(chalk3.hex("#FF8C00")(message));
|
|
917
923
|
}
|
|
918
924
|
function printSeparator() {
|
|
919
925
|
console.log(MESSAGES.SEPARATOR);
|
|
@@ -934,7 +940,7 @@ function confirmAction(question) {
|
|
|
934
940
|
});
|
|
935
941
|
}
|
|
936
942
|
function confirmDestructiveAction(dangerousCommand, description) {
|
|
937
|
-
printWarning(`\u5373\u5C06\u6267\u884C ${
|
|
943
|
+
printWarning(`\u5373\u5C06\u6267\u884C ${chalk3.red.bold(dangerousCommand)}\uFF0C${description}`);
|
|
938
944
|
return confirmAction("\u662F\u5426\u7EE7\u7EED\uFF1F");
|
|
939
945
|
}
|
|
940
946
|
function isWorktreeIdle(status) {
|
|
@@ -942,17 +948,17 @@ function isWorktreeIdle(status) {
|
|
|
942
948
|
}
|
|
943
949
|
function formatWorktreeStatus(status) {
|
|
944
950
|
const parts = [];
|
|
945
|
-
parts.push(
|
|
951
|
+
parts.push(chalk3.yellow(`${status.commitCount} \u4E2A\u63D0\u4EA4`));
|
|
946
952
|
if (status.insertions === 0 && status.deletions === 0) {
|
|
947
953
|
parts.push("\u65E0\u53D8\u66F4");
|
|
948
954
|
} else {
|
|
949
955
|
const diffParts = [];
|
|
950
|
-
diffParts.push(
|
|
951
|
-
diffParts.push(
|
|
956
|
+
diffParts.push(chalk3.green(`+${status.insertions}`));
|
|
957
|
+
diffParts.push(chalk3.red(`-${status.deletions}`));
|
|
952
958
|
parts.push(diffParts.join(" "));
|
|
953
959
|
}
|
|
954
960
|
if (status.hasDirtyFiles) {
|
|
955
|
-
parts.push(
|
|
961
|
+
parts.push(chalk3.gray("(\u672A\u63D0\u4EA4\u4FEE\u6539)"));
|
|
956
962
|
}
|
|
957
963
|
return parts.join(" ");
|
|
958
964
|
}
|
|
@@ -1454,6 +1460,7 @@ function removeProjectSnapshots(projectName) {
|
|
|
1454
1460
|
|
|
1455
1461
|
// src/utils/worktree-matcher.ts
|
|
1456
1462
|
import Enquirer2 from "enquirer";
|
|
1463
|
+
import { statSync as statSync3 } from "fs";
|
|
1457
1464
|
function findExactMatch(worktrees, branchName) {
|
|
1458
1465
|
return worktrees.find((wt) => wt.branch === branchName);
|
|
1459
1466
|
}
|
|
@@ -1558,9 +1565,142 @@ async function resolveTargetWorktree(worktrees, messages, branchName) {
|
|
|
1558
1565
|
const allBranches = worktrees.map((wt) => wt.branch);
|
|
1559
1566
|
throw new ClawtError(messages.noMatch(branchName, allBranches));
|
|
1560
1567
|
}
|
|
1568
|
+
function formatLocalDate(date) {
|
|
1569
|
+
const year = date.getFullYear();
|
|
1570
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
1571
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
1572
|
+
return `${year}-${month}-${day}`;
|
|
1573
|
+
}
|
|
1574
|
+
function getWorktreeCreatedDate(dirPath) {
|
|
1575
|
+
try {
|
|
1576
|
+
const stat = statSync3(dirPath);
|
|
1577
|
+
return formatLocalDate(stat.birthtime);
|
|
1578
|
+
} catch {
|
|
1579
|
+
return null;
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
function formatRelativeDate(dateStr) {
|
|
1583
|
+
const today = formatLocalDate(/* @__PURE__ */ new Date());
|
|
1584
|
+
const todayMs = new Date(today).getTime();
|
|
1585
|
+
const targetMs = new Date(dateStr).getTime();
|
|
1586
|
+
const diffDays = Math.round((todayMs - targetMs) / (1e3 * 60 * 60 * 24));
|
|
1587
|
+
if (diffDays === 0) return "\u4ECA\u5929";
|
|
1588
|
+
if (diffDays === 1) return "\u6628\u5929";
|
|
1589
|
+
if (diffDays < 30) return `${diffDays} \u5929\u524D`;
|
|
1590
|
+
if (diffDays < 365) {
|
|
1591
|
+
const months = Math.floor(diffDays / 30);
|
|
1592
|
+
return `${months} \u4E2A\u6708\u524D`;
|
|
1593
|
+
}
|
|
1594
|
+
const years = Math.floor(diffDays / 365);
|
|
1595
|
+
return `${years} \u5E74\u524D`;
|
|
1596
|
+
}
|
|
1597
|
+
function groupWorktreesByDate(worktrees) {
|
|
1598
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1599
|
+
for (const wt of worktrees) {
|
|
1600
|
+
const dateKey = getWorktreeCreatedDate(wt.path) ?? UNKNOWN_DATE_GROUP;
|
|
1601
|
+
if (!groups.has(dateKey)) {
|
|
1602
|
+
groups.set(dateKey, []);
|
|
1603
|
+
}
|
|
1604
|
+
groups.get(dateKey).push(wt);
|
|
1605
|
+
}
|
|
1606
|
+
const sortedEntries = [...groups.entries()].sort((a, b) => {
|
|
1607
|
+
if (a[0] === UNKNOWN_DATE_GROUP) return 1;
|
|
1608
|
+
if (b[0] === UNKNOWN_DATE_GROUP) return -1;
|
|
1609
|
+
return b[0].localeCompare(a[0]);
|
|
1610
|
+
});
|
|
1611
|
+
return new Map(sortedEntries);
|
|
1612
|
+
}
|
|
1613
|
+
function buildGroupedChoices(groups) {
|
|
1614
|
+
const choices = [];
|
|
1615
|
+
choices.push({ name: SELECT_ALL_NAME, message: SELECT_ALL_LABEL });
|
|
1616
|
+
for (const [dateKey, worktreeList] of groups) {
|
|
1617
|
+
if (dateKey === UNKNOWN_DATE_GROUP) {
|
|
1618
|
+
choices.push({ role: "separator", message: UNKNOWN_DATE_SEPARATOR_LABEL });
|
|
1619
|
+
} else {
|
|
1620
|
+
const relativeTime = formatRelativeDate(dateKey);
|
|
1621
|
+
choices.push({ role: "separator", message: GROUP_SEPARATOR_LABEL(dateKey, relativeTime) });
|
|
1622
|
+
}
|
|
1623
|
+
const groupSelectAllName = `${GROUP_SELECT_ALL_PREFIX}${dateKey}`;
|
|
1624
|
+
choices.push({ name: groupSelectAllName, message: GROUP_SELECT_ALL_LABEL(dateKey) });
|
|
1625
|
+
for (const wt of worktreeList) {
|
|
1626
|
+
choices.push({ name: wt.branch, message: wt.branch });
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
return choices;
|
|
1630
|
+
}
|
|
1631
|
+
function buildGroupMembershipMap(groups) {
|
|
1632
|
+
const map = /* @__PURE__ */ new Map();
|
|
1633
|
+
for (const [dateKey, worktreeList] of groups) {
|
|
1634
|
+
const groupSelectAllName = `${GROUP_SELECT_ALL_PREFIX}${dateKey}`;
|
|
1635
|
+
map.set(groupSelectAllName, worktreeList.map((wt) => wt.branch));
|
|
1636
|
+
}
|
|
1637
|
+
return map;
|
|
1638
|
+
}
|
|
1639
|
+
async function promptGroupedMultiSelectBranches(worktrees, message) {
|
|
1640
|
+
const groups = groupWorktreesByDate(worktrees);
|
|
1641
|
+
const choices = buildGroupedChoices(groups);
|
|
1642
|
+
const groupMembershipMap = buildGroupMembershipMap(groups);
|
|
1643
|
+
const groupSelectAllNames = new Set(groupMembershipMap.keys());
|
|
1644
|
+
const allBranchNames = new Set(worktrees.map((wt) => wt.branch));
|
|
1645
|
+
const MultiSelect = Enquirer2.MultiSelect;
|
|
1646
|
+
class MultiSelectWithGroupSelectAll extends MultiSelect {
|
|
1647
|
+
space() {
|
|
1648
|
+
if (!this.focused) return;
|
|
1649
|
+
const focusedName = this.focused.name;
|
|
1650
|
+
if (focusedName === SELECT_ALL_NAME) {
|
|
1651
|
+
const willEnable = !this.focused.enabled;
|
|
1652
|
+
for (const ch of this.choices) {
|
|
1653
|
+
ch.enabled = willEnable;
|
|
1654
|
+
}
|
|
1655
|
+
return this.render();
|
|
1656
|
+
}
|
|
1657
|
+
if (groupSelectAllNames.has(focusedName)) {
|
|
1658
|
+
const willEnable = !this.focused.enabled;
|
|
1659
|
+
const memberNames = groupMembershipMap.get(focusedName);
|
|
1660
|
+
this.focused.enabled = willEnable;
|
|
1661
|
+
for (const ch of this.choices) {
|
|
1662
|
+
if (memberNames.includes(ch.name)) {
|
|
1663
|
+
ch.enabled = willEnable;
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
syncGlobalSelectAll(this.choices);
|
|
1667
|
+
return this.render();
|
|
1668
|
+
}
|
|
1669
|
+
this.toggle(this.focused);
|
|
1670
|
+
syncGroupSelectAll(this.choices, focusedName);
|
|
1671
|
+
syncGlobalSelectAll(this.choices);
|
|
1672
|
+
return this.render();
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
function syncGlobalSelectAll(choiceList) {
|
|
1676
|
+
const selectAllChoice = choiceList.find((ch) => ch.name === SELECT_ALL_NAME);
|
|
1677
|
+
if (!selectAllChoice) return;
|
|
1678
|
+
const branchItems = choiceList.filter((ch) => allBranchNames.has(ch.name));
|
|
1679
|
+
selectAllChoice.enabled = branchItems.length > 0 && branchItems.every((ch) => ch.enabled);
|
|
1680
|
+
}
|
|
1681
|
+
function syncGroupSelectAll(choiceList, branchName) {
|
|
1682
|
+
for (const [groupName, memberNames] of groupMembershipMap) {
|
|
1683
|
+
if (!memberNames.includes(branchName)) continue;
|
|
1684
|
+
const groupChoice = choiceList.find((ch) => ch.name === groupName);
|
|
1685
|
+
if (!groupChoice) continue;
|
|
1686
|
+
const memberChoices = choiceList.filter((ch) => memberNames.includes(ch.name));
|
|
1687
|
+
groupChoice.enabled = memberChoices.length > 0 && memberChoices.every((ch) => ch.enabled);
|
|
1688
|
+
break;
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
const selectedBranches = await new MultiSelectWithGroupSelectAll({
|
|
1692
|
+
message,
|
|
1693
|
+
choices,
|
|
1694
|
+
// 使用空心圆/实心圆作为选中指示符
|
|
1695
|
+
symbols: {
|
|
1696
|
+
indicator: { on: "\u25CF", off: "\u25CB" }
|
|
1697
|
+
}
|
|
1698
|
+
}).run();
|
|
1699
|
+
return worktrees.filter((wt) => selectedBranches.includes(wt.branch));
|
|
1700
|
+
}
|
|
1561
1701
|
|
|
1562
1702
|
// src/utils/progress-render.ts
|
|
1563
|
-
import
|
|
1703
|
+
import chalk4 from "chalk";
|
|
1564
1704
|
import stringWidth from "string-width";
|
|
1565
1705
|
var ANSI_RESET = "\x1B[0m";
|
|
1566
1706
|
function truncateToTerminalWidth(text, maxWidth) {
|
|
@@ -1597,23 +1737,23 @@ function renderTaskLine(task, total, maxPathWidth, spinnerChar) {
|
|
|
1597
1737
|
const pathStr = task.path.padEnd(maxPathWidth);
|
|
1598
1738
|
switch (task.status) {
|
|
1599
1739
|
case "pending": {
|
|
1600
|
-
return `${indexStr} ${pathStr} ${
|
|
1740
|
+
return `${indexStr} ${pathStr} ${chalk4.gray(TASK_STATUS_ICONS.PENDING)} ${chalk4.gray(TASK_STATUS_LABELS.PENDING)}`;
|
|
1601
1741
|
}
|
|
1602
1742
|
case "running": {
|
|
1603
1743
|
const elapsed = formatDuration(Date.now() - task.startedAt);
|
|
1604
|
-
const detail = task.activity ? ` ${
|
|
1605
|
-
return `${indexStr} ${pathStr} ${
|
|
1744
|
+
const detail = task.activity ? ` ${chalk4.dim(task.activity)}` : "";
|
|
1745
|
+
return `${indexStr} ${pathStr} ${chalk4.cyan(spinnerChar)} ${chalk4.cyan(TASK_STATUS_LABELS.RUNNING)} ${chalk4.gray(elapsed)}${detail}`;
|
|
1606
1746
|
}
|
|
1607
1747
|
case "done": {
|
|
1608
1748
|
const duration = task.durationMs != null ? formatDuration(task.durationMs) : "N/A";
|
|
1609
1749
|
const cost = task.costUsd != null ? `$${task.costUsd.toFixed(2)}` : "";
|
|
1610
|
-
const preview = task.resultPreview ? ` ${
|
|
1611
|
-
return `${indexStr} ${pathStr} ${
|
|
1750
|
+
const preview = task.resultPreview ? ` ${chalk4.dim(task.resultPreview)}` : "";
|
|
1751
|
+
return `${indexStr} ${pathStr} ${chalk4.green(TASK_STATUS_ICONS.DONE)} ${chalk4.green(TASK_STATUS_LABELS.DONE)} ${chalk4.gray(duration)} ${chalk4.yellow(cost)}${preview}`;
|
|
1612
1752
|
}
|
|
1613
1753
|
case "failed": {
|
|
1614
1754
|
const duration = task.durationMs != null ? formatDuration(task.durationMs) : "N/A";
|
|
1615
|
-
const preview = task.resultPreview ? ` ${
|
|
1616
|
-
return `${indexStr} ${pathStr} ${
|
|
1755
|
+
const preview = task.resultPreview ? ` ${chalk4.dim(task.resultPreview)}` : "";
|
|
1756
|
+
return `${indexStr} ${pathStr} ${chalk4.red(TASK_STATUS_ICONS.FAILED)} ${chalk4.red(TASK_STATUS_LABELS.FAILED)} ${chalk4.gray(duration)}${preview}`;
|
|
1617
1757
|
}
|
|
1618
1758
|
}
|
|
1619
1759
|
}
|
|
@@ -1623,10 +1763,10 @@ function renderSummaryLine(tasks, total) {
|
|
|
1623
1763
|
const failed = tasks.filter((t) => t.status === "failed").length;
|
|
1624
1764
|
const pending = tasks.filter((t) => t.status === "pending").length;
|
|
1625
1765
|
const parts = [];
|
|
1626
|
-
if (running > 0) parts.push(
|
|
1627
|
-
if (done > 0) parts.push(
|
|
1628
|
-
if (failed > 0) parts.push(
|
|
1629
|
-
if (pending > 0) parts.push(
|
|
1766
|
+
if (running > 0) parts.push(chalk4.cyan(`${running}/${total} ${TASK_STATUS_LABELS.RUNNING}`));
|
|
1767
|
+
if (done > 0) parts.push(chalk4.green(`${done}/${total} ${TASK_STATUS_LABELS.DONE}`));
|
|
1768
|
+
if (failed > 0) parts.push(chalk4.red(`${failed}/${total} ${TASK_STATUS_LABELS.FAILED}`));
|
|
1769
|
+
if (pending > 0) parts.push(chalk4.gray(`${pending}/${total} ${TASK_STATUS_LABELS.PENDING}`));
|
|
1630
1770
|
return `[${parts.join(", ")}]`;
|
|
1631
1771
|
}
|
|
1632
1772
|
|
|
@@ -2241,7 +2381,7 @@ async function executeBatchTasks(worktrees, tasks, concurrency) {
|
|
|
2241
2381
|
}
|
|
2242
2382
|
|
|
2243
2383
|
// src/utils/dry-run.ts
|
|
2244
|
-
import
|
|
2384
|
+
import chalk5 from "chalk";
|
|
2245
2385
|
import { join as join6 } from "path";
|
|
2246
2386
|
var DRY_RUN_TASK_DESC_MAX_LENGTH = 80;
|
|
2247
2387
|
function truncateTaskDesc(task) {
|
|
@@ -2255,7 +2395,7 @@ function printDryRunPreview(branchNames, tasks, concurrency) {
|
|
|
2255
2395
|
const projectDir = getProjectWorktreeDir();
|
|
2256
2396
|
const isInteractive = tasks.length === 0;
|
|
2257
2397
|
printDoubleSeparator();
|
|
2258
|
-
printInfo(` ${
|
|
2398
|
+
printInfo(` ${chalk5.bold(MESSAGES.DRY_RUN_TITLE)}`);
|
|
2259
2399
|
printDoubleSeparator();
|
|
2260
2400
|
const summaryParts = [
|
|
2261
2401
|
MESSAGES.DRY_RUN_TASK_COUNT(branchNames.length),
|
|
@@ -2265,7 +2405,7 @@ function printDryRunPreview(branchNames, tasks, concurrency) {
|
|
|
2265
2405
|
if (isInteractive) {
|
|
2266
2406
|
summaryParts.push(MESSAGES.DRY_RUN_INTERACTIVE_MODE);
|
|
2267
2407
|
}
|
|
2268
|
-
printInfo(summaryParts.join(
|
|
2408
|
+
printInfo(summaryParts.join(chalk5.gray(" \u2502 ")));
|
|
2269
2409
|
printSeparator();
|
|
2270
2410
|
let hasConflict = false;
|
|
2271
2411
|
for (let i = 0; i < branchNames.length; i++) {
|
|
@@ -2275,21 +2415,21 @@ function printDryRunPreview(branchNames, tasks, concurrency) {
|
|
|
2275
2415
|
if (exists) hasConflict = true;
|
|
2276
2416
|
const indexLabel = `[${i + 1}/${branchNames.length}]`;
|
|
2277
2417
|
if (exists) {
|
|
2278
|
-
printInfo(`${
|
|
2418
|
+
printInfo(`${chalk5.yellow("\u26A0")} ${indexLabel} ${chalk5.yellow(branch)} ${chalk5.gray("\u2014")} ${chalk5.yellow(MESSAGES.DRY_RUN_BRANCH_EXISTS_WARNING(branch))}`);
|
|
2279
2419
|
} else {
|
|
2280
|
-
printInfo(`${
|
|
2420
|
+
printInfo(`${chalk5.green("\u2713")} ${indexLabel} ${chalk5.cyan(branch)}`);
|
|
2281
2421
|
}
|
|
2282
|
-
printInfo(` ${
|
|
2422
|
+
printInfo(` ${chalk5.gray("\u8DEF\u5F84:")} ${worktreePath}`);
|
|
2283
2423
|
if (!isInteractive) {
|
|
2284
|
-
printInfo(` ${
|
|
2424
|
+
printInfo(` ${chalk5.gray("\u4EFB\u52A1:")} ${truncateTaskDesc(tasks[i])}`);
|
|
2285
2425
|
}
|
|
2286
2426
|
printInfo("");
|
|
2287
2427
|
}
|
|
2288
2428
|
printDoubleSeparator();
|
|
2289
2429
|
if (hasConflict) {
|
|
2290
|
-
printInfo(
|
|
2430
|
+
printInfo(chalk5.yellow(`\u26A0 ${MESSAGES.DRY_RUN_HAS_CONFLICT}`));
|
|
2291
2431
|
} else {
|
|
2292
|
-
printInfo(
|
|
2432
|
+
printInfo(chalk5.green(`\u2713 ${MESSAGES.DRY_RUN_READY}`));
|
|
2293
2433
|
}
|
|
2294
2434
|
}
|
|
2295
2435
|
|
|
@@ -2307,7 +2447,7 @@ function applyAliases(program2, aliases) {
|
|
|
2307
2447
|
}
|
|
2308
2448
|
|
|
2309
2449
|
// src/utils/config-strategy.ts
|
|
2310
|
-
import
|
|
2450
|
+
import chalk6 from "chalk";
|
|
2311
2451
|
import Enquirer3 from "enquirer";
|
|
2312
2452
|
function isValidConfigKey(key) {
|
|
2313
2453
|
return key in DEFAULT_CONFIG;
|
|
@@ -2351,9 +2491,9 @@ async function promptConfigValue(key, currentValue) {
|
|
|
2351
2491
|
}
|
|
2352
2492
|
function formatConfigValue(value) {
|
|
2353
2493
|
if (typeof value === "boolean") {
|
|
2354
|
-
return value ?
|
|
2494
|
+
return value ? chalk6.green("true") : chalk6.yellow("false");
|
|
2355
2495
|
}
|
|
2356
|
-
return
|
|
2496
|
+
return chalk6.cyan(String(value));
|
|
2357
2497
|
}
|
|
2358
2498
|
async function promptBooleanValue(key, currentValue) {
|
|
2359
2499
|
const choices = [
|
|
@@ -2400,7 +2540,7 @@ async function promptStringValue(key, currentValue) {
|
|
|
2400
2540
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
2401
2541
|
import { execSync as execSync3 } from "child_process";
|
|
2402
2542
|
import { request } from "https";
|
|
2403
|
-
import
|
|
2543
|
+
import chalk7 from "chalk";
|
|
2404
2544
|
import stringWidth2 from "string-width";
|
|
2405
2545
|
function readUpdateCache() {
|
|
2406
2546
|
try {
|
|
@@ -2475,12 +2615,12 @@ function detectPackageManager() {
|
|
|
2475
2615
|
}
|
|
2476
2616
|
function printUpdateNotification(currentVersion, latestVersion) {
|
|
2477
2617
|
const updateText = UPDATE_MESSAGES.UPDATE_AVAILABLE(
|
|
2478
|
-
|
|
2479
|
-
|
|
2618
|
+
chalk7.red(currentVersion),
|
|
2619
|
+
chalk7.green(latestVersion)
|
|
2480
2620
|
);
|
|
2481
2621
|
const pm = detectPackageManager();
|
|
2482
2622
|
const updateCommand = UPDATE_COMMANDS[pm] || UPDATE_COMMANDS.npm;
|
|
2483
|
-
const commandText = UPDATE_MESSAGES.UPDATE_HINT(
|
|
2623
|
+
const commandText = UPDATE_MESSAGES.UPDATE_HINT(chalk7.cyan(updateCommand));
|
|
2484
2624
|
const updateTextWidth = stringWidth2(updateText);
|
|
2485
2625
|
const commandTextWidth = stringWidth2(commandText);
|
|
2486
2626
|
const innerWidth = Math.max(updateTextWidth, commandTextWidth) + 4;
|
|
@@ -2528,7 +2668,7 @@ async function checkForUpdates(currentVersion) {
|
|
|
2528
2668
|
}
|
|
2529
2669
|
|
|
2530
2670
|
// src/commands/list.ts
|
|
2531
|
-
import
|
|
2671
|
+
import chalk8 from "chalk";
|
|
2532
2672
|
function registerListCommand(program2) {
|
|
2533
2673
|
program2.command("list").description("\u5217\u51FA\u5F53\u524D\u9879\u76EE\u6240\u6709 worktree").option("--json", "\u4EE5 JSON \u683C\u5F0F\u8F93\u51FA").action((options) => {
|
|
2534
2674
|
handleList(options);
|
|
@@ -2565,12 +2705,12 @@ function printListAsText(projectName, worktrees) {
|
|
|
2565
2705
|
for (const wt of worktrees) {
|
|
2566
2706
|
const status = getWorktreeStatus(wt);
|
|
2567
2707
|
const isIdle = status ? isWorktreeIdle(status) : false;
|
|
2568
|
-
const pathDisplay = isIdle ?
|
|
2708
|
+
const pathDisplay = isIdle ? chalk8.hex("#FF8C00")(wt.path) : wt.path;
|
|
2569
2709
|
printInfo(` ${pathDisplay} [${wt.branch}]`);
|
|
2570
2710
|
if (status) {
|
|
2571
2711
|
printInfo(` ${formatWorktreeStatus(status)}`);
|
|
2572
2712
|
} else {
|
|
2573
|
-
printInfo(` ${
|
|
2713
|
+
printInfo(` ${chalk8.yellow(MESSAGES.WORKTREE_STATUS_UNAVAILABLE)}`);
|
|
2574
2714
|
}
|
|
2575
2715
|
printInfo("");
|
|
2576
2716
|
}
|
|
@@ -2778,7 +2918,12 @@ async function handleResume(options) {
|
|
|
2778
2918
|
validateClaudeCodeInstalled();
|
|
2779
2919
|
logger.info(`resume \u547D\u4EE4\u6267\u884C\uFF0C\u5206\u652F\u8FC7\u6EE4: ${options.branch ?? "(\u65E0)"}`);
|
|
2780
2920
|
const worktrees = getProjectWorktrees();
|
|
2781
|
-
|
|
2921
|
+
let targetWorktrees;
|
|
2922
|
+
if (!options.branch && worktrees.length > 1) {
|
|
2923
|
+
targetWorktrees = await promptGroupedMultiSelectBranches(worktrees, RESUME_RESOLVE_MESSAGES.selectBranch);
|
|
2924
|
+
} else {
|
|
2925
|
+
targetWorktrees = await resolveTargetWorktrees(worktrees, RESUME_RESOLVE_MESSAGES, options.branch);
|
|
2926
|
+
}
|
|
2782
2927
|
if (targetWorktrees.length === 0) {
|
|
2783
2928
|
return;
|
|
2784
2929
|
}
|
|
@@ -3253,7 +3398,7 @@ async function handleMerge(options) {
|
|
|
3253
3398
|
}
|
|
3254
3399
|
|
|
3255
3400
|
// src/commands/config.ts
|
|
3256
|
-
import
|
|
3401
|
+
import chalk9 from "chalk";
|
|
3257
3402
|
import Enquirer5 from "enquirer";
|
|
3258
3403
|
function registerConfigCommand(program2) {
|
|
3259
3404
|
const configCmd = program2.command("config").description("\u4EA4\u4E92\u5F0F\u67E5\u770B\u548C\u4FEE\u6539\u5168\u5C40\u914D\u7F6E").action(async () => {
|
|
@@ -3314,7 +3459,7 @@ async function handleInteractiveConfigSet() {
|
|
|
3314
3459
|
const isObject = typeof DEFAULT_CONFIG[k] === "object";
|
|
3315
3460
|
return {
|
|
3316
3461
|
name: k,
|
|
3317
|
-
message: `${k}: ${isObject ?
|
|
3462
|
+
message: `${k}: ${isObject ? chalk9.dim(JSON.stringify(config2[k])) : formatConfigValue(config2[k])} ${chalk9.dim(`\u2014 ${CONFIG_DESCRIPTIONS[k]}`)}`,
|
|
3318
3463
|
...isObject && { disabled: CONFIG_ALIAS_DISABLED_HINT }
|
|
3319
3464
|
};
|
|
3320
3465
|
});
|
|
@@ -3369,7 +3514,7 @@ async function handleReset() {
|
|
|
3369
3514
|
}
|
|
3370
3515
|
|
|
3371
3516
|
// src/commands/status.ts
|
|
3372
|
-
import
|
|
3517
|
+
import chalk10 from "chalk";
|
|
3373
3518
|
function registerStatusCommand(program2) {
|
|
3374
3519
|
program2.command("status").description("\u663E\u793A\u9879\u76EE\u5168\u5C40\u72B6\u6001\u603B\u89C8").option("--json", "\u4EE5 JSON \u683C\u5F0F\u8F93\u51FA").action((options) => {
|
|
3375
3520
|
handleStatus(options);
|
|
@@ -3482,7 +3627,7 @@ function printStatusAsJson(result) {
|
|
|
3482
3627
|
}
|
|
3483
3628
|
function printStatusAsText(result) {
|
|
3484
3629
|
printDoubleSeparator();
|
|
3485
|
-
printInfo(` ${
|
|
3630
|
+
printInfo(` ${chalk10.bold.cyan(MESSAGES.STATUS_TITLE(result.main.projectName))}`);
|
|
3486
3631
|
printDoubleSeparator();
|
|
3487
3632
|
printInfo("");
|
|
3488
3633
|
printMainSection(result.main);
|
|
@@ -3495,17 +3640,17 @@ function printStatusAsText(result) {
|
|
|
3495
3640
|
printDoubleSeparator();
|
|
3496
3641
|
}
|
|
3497
3642
|
function printMainSection(main2) {
|
|
3498
|
-
printInfo(` ${
|
|
3499
|
-
printInfo(` \u5206\u652F: ${
|
|
3643
|
+
printInfo(` ${chalk10.bold("\u25C6")} ${chalk10.bold(MESSAGES.STATUS_MAIN_SECTION)}`);
|
|
3644
|
+
printInfo(` \u5206\u652F: ${chalk10.bold(main2.branch)}`);
|
|
3500
3645
|
if (main2.isClean) {
|
|
3501
|
-
printInfo(` \u72B6\u6001: ${
|
|
3646
|
+
printInfo(` \u72B6\u6001: ${chalk10.green("\u2713 \u5E72\u51C0")}`);
|
|
3502
3647
|
} else {
|
|
3503
|
-
printInfo(` \u72B6\u6001: ${
|
|
3648
|
+
printInfo(` \u72B6\u6001: ${chalk10.yellow("\u2717 \u6709\u672A\u63D0\u4EA4\u4FEE\u6539")}`);
|
|
3504
3649
|
}
|
|
3505
3650
|
printInfo("");
|
|
3506
3651
|
}
|
|
3507
3652
|
function printWorktreesSection(worktrees, total) {
|
|
3508
|
-
printInfo(` ${
|
|
3653
|
+
printInfo(` ${chalk10.bold("\u25C6")} ${chalk10.bold(MESSAGES.STATUS_WORKTREES_SECTION)} (${total} \u4E2A)`);
|
|
3509
3654
|
printInfo("");
|
|
3510
3655
|
if (worktrees.length === 0) {
|
|
3511
3656
|
printInfo(` ${MESSAGES.STATUS_NO_WORKTREES}`);
|
|
@@ -3517,56 +3662,56 @@ function printWorktreesSection(worktrees, total) {
|
|
|
3517
3662
|
}
|
|
3518
3663
|
function printWorktreeItem(wt) {
|
|
3519
3664
|
const statusLabel = formatChangeStatusLabel(wt.changeStatus);
|
|
3520
|
-
printInfo(` ${
|
|
3665
|
+
printInfo(` ${chalk10.bold("\u25CF")} ${chalk10.bold(wt.branch)} [${statusLabel}]`);
|
|
3521
3666
|
if (wt.insertions > 0 || wt.deletions > 0) {
|
|
3522
|
-
printInfo(` ${
|
|
3667
|
+
printInfo(` ${chalk10.green(`+${wt.insertions}`)} ${chalk10.red(`-${wt.deletions}`)}`);
|
|
3523
3668
|
}
|
|
3524
3669
|
if (wt.commitsAhead > 0) {
|
|
3525
|
-
printInfo(` ${
|
|
3670
|
+
printInfo(` ${chalk10.yellow(`${wt.commitsAhead} \u4E2A\u672C\u5730\u63D0\u4EA4`)}`);
|
|
3526
3671
|
}
|
|
3527
3672
|
if (wt.commitsBehind > 0) {
|
|
3528
|
-
printInfo(` ${
|
|
3673
|
+
printInfo(` ${chalk10.yellow(`\u843D\u540E\u4E3B\u5206\u652F ${wt.commitsBehind} \u4E2A\u63D0\u4EA4`)}`);
|
|
3529
3674
|
} else {
|
|
3530
|
-
printInfo(` ${
|
|
3675
|
+
printInfo(` ${chalk10.green("\u4E0E\u4E3B\u5206\u652F\u540C\u6B65")}`);
|
|
3531
3676
|
}
|
|
3532
3677
|
if (wt.createdAt) {
|
|
3533
3678
|
const relativeTime = formatRelativeTime(wt.createdAt);
|
|
3534
3679
|
if (relativeTime) {
|
|
3535
|
-
printInfo(` ${
|
|
3680
|
+
printInfo(` ${chalk10.gray(MESSAGES.STATUS_CREATED_AT(relativeTime))}`);
|
|
3536
3681
|
}
|
|
3537
3682
|
}
|
|
3538
3683
|
if (wt.snapshotTime) {
|
|
3539
3684
|
const relativeTime = formatRelativeTime(wt.snapshotTime);
|
|
3540
3685
|
if (relativeTime) {
|
|
3541
|
-
printInfo(` ${
|
|
3686
|
+
printInfo(` ${chalk10.green(MESSAGES.STATUS_LAST_VALIDATED(relativeTime))}`);
|
|
3542
3687
|
}
|
|
3543
3688
|
} else {
|
|
3544
|
-
printInfo(` ${
|
|
3689
|
+
printInfo(` ${chalk10.red(MESSAGES.STATUS_NOT_VALIDATED)}`);
|
|
3545
3690
|
}
|
|
3546
3691
|
printInfo("");
|
|
3547
3692
|
}
|
|
3548
3693
|
function formatChangeStatusLabel(status) {
|
|
3549
3694
|
switch (status) {
|
|
3550
3695
|
case "committed":
|
|
3551
|
-
return
|
|
3696
|
+
return chalk10.green(MESSAGES.STATUS_CHANGE_COMMITTED);
|
|
3552
3697
|
case "uncommitted":
|
|
3553
|
-
return
|
|
3698
|
+
return chalk10.yellow(MESSAGES.STATUS_CHANGE_UNCOMMITTED);
|
|
3554
3699
|
case "conflict":
|
|
3555
|
-
return
|
|
3700
|
+
return chalk10.red(MESSAGES.STATUS_CHANGE_CONFLICT);
|
|
3556
3701
|
case "clean":
|
|
3557
|
-
return
|
|
3702
|
+
return chalk10.gray(MESSAGES.STATUS_CHANGE_CLEAN);
|
|
3558
3703
|
}
|
|
3559
3704
|
}
|
|
3560
3705
|
function printSnapshotsSection(snapshots) {
|
|
3561
|
-
printInfo(` ${
|
|
3706
|
+
printInfo(` ${chalk10.bold("\u25C6")} ${chalk10.bold(MESSAGES.STATUS_SNAPSHOTS_SECTION)} (${snapshots.total} \u4E2A)`);
|
|
3562
3707
|
if (snapshots.orphaned > 0) {
|
|
3563
|
-
printInfo(` ${
|
|
3708
|
+
printInfo(` ${chalk10.yellow(MESSAGES.STATUS_SNAPSHOT_ORPHANED(snapshots.orphaned))}`);
|
|
3564
3709
|
}
|
|
3565
3710
|
printInfo("");
|
|
3566
3711
|
}
|
|
3567
3712
|
|
|
3568
3713
|
// src/commands/alias.ts
|
|
3569
|
-
import
|
|
3714
|
+
import chalk11 from "chalk";
|
|
3570
3715
|
function getRegisteredCommandNames(program2) {
|
|
3571
3716
|
return program2.commands.map((cmd) => cmd.name());
|
|
3572
3717
|
}
|
|
@@ -3587,7 +3732,7 @@ ${MESSAGES.ALIAS_LIST_TITLE}
|
|
|
3587
3732
|
`);
|
|
3588
3733
|
printSeparator();
|
|
3589
3734
|
for (const [alias, command] of entries) {
|
|
3590
|
-
printInfo(` ${
|
|
3735
|
+
printInfo(` ${chalk11.bold(alias)} \u2192 ${chalk11.cyan(command)}`);
|
|
3591
3736
|
}
|
|
3592
3737
|
printInfo("");
|
|
3593
3738
|
printSeparator();
|
|
@@ -3634,9 +3779,9 @@ function registerAliasCommand(program2) {
|
|
|
3634
3779
|
}
|
|
3635
3780
|
|
|
3636
3781
|
// src/commands/projects.ts
|
|
3637
|
-
import { existsSync as existsSync9, readdirSync as readdirSync5, statSync as
|
|
3782
|
+
import { existsSync as existsSync9, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
|
|
3638
3783
|
import { join as join7 } from "path";
|
|
3639
|
-
import
|
|
3784
|
+
import chalk12 from "chalk";
|
|
3640
3785
|
function registerProjectsCommand(program2) {
|
|
3641
3786
|
program2.command("projects [name]").description("\u5C55\u793A\u6240\u6709\u9879\u76EE\u7684 worktree \u6982\u89C8\uFF0C\u6216\u67E5\u770B\u6307\u5B9A\u9879\u76EE\u7684 worktree \u8BE6\u60C5").option("--json", "\u4EE5 JSON \u683C\u5F0F\u8F93\u51FA").action((name, options) => {
|
|
3642
3787
|
handleProjects({ name, json: options.json });
|
|
@@ -3728,7 +3873,7 @@ function collectProjectDetail(name, projectDir) {
|
|
|
3728
3873
|
};
|
|
3729
3874
|
}
|
|
3730
3875
|
function collectSingleWorktreeDetail(branch, wtPath) {
|
|
3731
|
-
const stat =
|
|
3876
|
+
const stat = statSync4(wtPath);
|
|
3732
3877
|
const diskUsage = calculateDirSize(wtPath);
|
|
3733
3878
|
return {
|
|
3734
3879
|
branch,
|
|
@@ -3738,10 +3883,10 @@ function collectSingleWorktreeDetail(branch, wtPath) {
|
|
|
3738
3883
|
};
|
|
3739
3884
|
}
|
|
3740
3885
|
function resolveProjectLastActiveTime(projectDir, worktreePaths) {
|
|
3741
|
-
let latestTime =
|
|
3886
|
+
let latestTime = statSync4(projectDir).mtime;
|
|
3742
3887
|
for (const wtPath of worktreePaths) {
|
|
3743
3888
|
try {
|
|
3744
|
-
const wtStat =
|
|
3889
|
+
const wtStat = statSync4(wtPath);
|
|
3745
3890
|
if (wtStat.mtime > latestTime) {
|
|
3746
3891
|
latestTime = wtStat.mtime;
|
|
3747
3892
|
}
|
|
@@ -3755,7 +3900,7 @@ function sortByLastActiveTimeDesc(projects) {
|
|
|
3755
3900
|
}
|
|
3756
3901
|
function printProjectsOverviewAsText(result) {
|
|
3757
3902
|
printDoubleSeparator();
|
|
3758
|
-
printInfo(` ${
|
|
3903
|
+
printInfo(` ${chalk12.bold.cyan(MESSAGES.PROJECTS_OVERVIEW_TITLE)}`);
|
|
3759
3904
|
printDoubleSeparator();
|
|
3760
3905
|
printInfo("");
|
|
3761
3906
|
if (result.projects.length === 0) {
|
|
@@ -3769,7 +3914,7 @@ function printProjectsOverviewAsText(result) {
|
|
|
3769
3914
|
}
|
|
3770
3915
|
printSeparator();
|
|
3771
3916
|
printInfo("");
|
|
3772
|
-
printInfo(` \u5171 ${
|
|
3917
|
+
printInfo(` \u5171 ${chalk12.bold(String(result.totalProjects))} \u4E2A\u9879\u76EE ${chalk12.gray(MESSAGES.PROJECTS_TOTAL_DISK_USAGE(formatDiskSize(result.totalDiskUsage)))}`);
|
|
3773
3918
|
printInfo("");
|
|
3774
3919
|
printDoubleSeparator();
|
|
3775
3920
|
}
|
|
@@ -3777,16 +3922,16 @@ function printProjectOverviewItem(project) {
|
|
|
3777
3922
|
const relativeTime = formatRelativeTime(project.lastActiveTime);
|
|
3778
3923
|
const activeLabel = relativeTime ? MESSAGES.PROJECTS_LAST_ACTIVE(relativeTime) : "";
|
|
3779
3924
|
const diskLabel = MESSAGES.PROJECTS_DISK_USAGE(formatDiskSize(project.diskUsage));
|
|
3780
|
-
printInfo(` ${
|
|
3781
|
-
printInfo(` ${MESSAGES.PROJECTS_WORKTREE_COUNT(project.worktreeCount)} ${
|
|
3925
|
+
printInfo(` ${chalk12.bold("\u25CF")} ${chalk12.bold(project.name)}`);
|
|
3926
|
+
printInfo(` ${MESSAGES.PROJECTS_WORKTREE_COUNT(project.worktreeCount)} ${chalk12.gray(activeLabel)} ${chalk12.gray(diskLabel)}`);
|
|
3782
3927
|
printInfo("");
|
|
3783
3928
|
}
|
|
3784
3929
|
function printProjectDetailAsText(result) {
|
|
3785
3930
|
printDoubleSeparator();
|
|
3786
|
-
printInfo(` ${
|
|
3931
|
+
printInfo(` ${chalk12.bold.cyan(MESSAGES.PROJECTS_DETAIL_TITLE(result.name))}`);
|
|
3787
3932
|
printDoubleSeparator();
|
|
3788
3933
|
printInfo("");
|
|
3789
|
-
printInfo(` ${
|
|
3934
|
+
printInfo(` ${chalk12.bold("\u25C6")} ${chalk12.bold(MESSAGES.PROJECTS_PATH(result.projectDir))}`);
|
|
3790
3935
|
printInfo(` ${MESSAGES.PROJECTS_TOTAL_DISK_USAGE(formatDiskSize(result.totalDiskUsage))}`);
|
|
3791
3936
|
printInfo("");
|
|
3792
3937
|
printSeparator();
|
|
@@ -3806,9 +3951,9 @@ function printWorktreeDetailItem(wt) {
|
|
|
3806
3951
|
const relativeTime = formatRelativeTime(wt.lastModifiedTime);
|
|
3807
3952
|
const modifiedLabel = relativeTime ? MESSAGES.PROJECTS_LAST_MODIFIED(relativeTime) : "";
|
|
3808
3953
|
const diskLabel = MESSAGES.PROJECTS_DISK_USAGE(formatDiskSize(wt.diskUsage));
|
|
3809
|
-
printInfo(` ${
|
|
3954
|
+
printInfo(` ${chalk12.bold("\u25CF")} ${chalk12.bold(wt.branch)}`);
|
|
3810
3955
|
printInfo(` ${wt.path}`);
|
|
3811
|
-
printInfo(` ${
|
|
3956
|
+
printInfo(` ${chalk12.gray(modifiedLabel)} ${chalk12.gray(diskLabel)}`);
|
|
3812
3957
|
printInfo("");
|
|
3813
3958
|
}
|
|
3814
3959
|
|
|
@@ -3864,7 +4009,7 @@ compdef _clawt_completion clawt
|
|
|
3864
4009
|
}
|
|
3865
4010
|
|
|
3866
4011
|
// src/utils/completion-engine.ts
|
|
3867
|
-
import { existsSync as existsSync10, readdirSync as readdirSync6, statSync as
|
|
4012
|
+
import { existsSync as existsSync10, readdirSync as readdirSync6, statSync as statSync5 } from "fs";
|
|
3868
4013
|
import { join as join8, dirname, basename as basename2 } from "path";
|
|
3869
4014
|
function completeFilePath(partial) {
|
|
3870
4015
|
const cwd = process.cwd();
|
|
@@ -3882,7 +4027,7 @@ function completeFilePath(partial) {
|
|
|
3882
4027
|
if (entry.startsWith(".")) continue;
|
|
3883
4028
|
const fullPath = join8(searchDir, entry);
|
|
3884
4029
|
try {
|
|
3885
|
-
const stat =
|
|
4030
|
+
const stat = statSync5(fullPath);
|
|
3886
4031
|
if (stat.isDirectory()) {
|
|
3887
4032
|
results.push(dirPrefix + entry + "/");
|
|
3888
4033
|
} else if (stat.isFile()) {
|