feat: status 命令支持可选 change-name 参数,展示详细状态与下一步建议
This commit is contained in:
98
src/cli.ts
98
src/cli.ts
@@ -15,6 +15,8 @@ import { scanChanges } from "./core/scanner.ts";
|
||||
import { UsageError, ConfigError, CommandError, InternalError, CliError } from "./cli/errors.ts";
|
||||
import { printError } from "./cli/output.ts";
|
||||
import { showGlobalHelp, showCommandHelp } from "./cli/help.ts";
|
||||
import type { ChangeStatus } from "./types.ts";
|
||||
import { defaultConfig } from "./defaults/config.ts";
|
||||
|
||||
function requireProjectRoot(): string {
|
||||
const root = findProjectRoot();
|
||||
@@ -24,6 +26,62 @@ function requireProjectRoot(): string {
|
||||
return root;
|
||||
}
|
||||
|
||||
function formatChangeStatus(change: ChangeStatus): string {
|
||||
const lines: string[] = [];
|
||||
lines.push(`变更:${change.name}`);
|
||||
|
||||
lines.push(" 规划阶段:");
|
||||
for (const doc of change.documents) {
|
||||
if (doc.completed) {
|
||||
lines.push(` ${doc.name}.md ✓ 已完成`);
|
||||
} else {
|
||||
const docConfig = defaultConfig.stages.plan?.documents.find((d) => d.name === doc.name);
|
||||
const depInfo = !doc.dependMet && docConfig?.depend?.length
|
||||
? `(依赖 ${docConfig.depend.map((d) => `${d}.md`).join("、")})`
|
||||
: "";
|
||||
lines.push(` ${doc.name}.md ○ 待完成${depInfo}`);
|
||||
}
|
||||
}
|
||||
|
||||
const completedCount = change.documents.filter((d) => d.completed).length;
|
||||
lines.push(` 规划进度:${completedCount}/${change.documents.length} 文档已完成`);
|
||||
|
||||
if (change.buildUnlocked) {
|
||||
lines.push(" 构建阶段:已解锁");
|
||||
} else {
|
||||
lines.push(" 构建阶段:未解锁(需完成规划)");
|
||||
}
|
||||
|
||||
if (change.taskProgress) {
|
||||
lines.push(` 任务进度:${change.taskProgress.completed}/${change.taskProgress.total} 已完成`);
|
||||
}
|
||||
|
||||
lines.push("");
|
||||
lines.push(` 建议下一步:${suggestNextStep(change)}`);
|
||||
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
function suggestNextStep(change: ChangeStatus): string {
|
||||
if (!change.planCompleted) {
|
||||
const nextDoc = change.documents.find((d) => !d.completed && d.dependMet);
|
||||
if (nextDoc) {
|
||||
return `rune plan ${change.name} ${nextDoc.name}`;
|
||||
}
|
||||
return `完成前置依赖后再规划文档`;
|
||||
}
|
||||
|
||||
if (change.taskProgress && change.taskProgress.completed < change.taskProgress.total) {
|
||||
return `rune build ${change.name}`;
|
||||
}
|
||||
|
||||
if (change.taskProgress && change.taskProgress.completed === change.taskProgress.total) {
|
||||
return `rune archive ${change.name}`;
|
||||
}
|
||||
|
||||
return `rune build ${change.name}`;
|
||||
}
|
||||
|
||||
const cli = cac("rune");
|
||||
|
||||
cli.command("", "").action(() => {
|
||||
@@ -140,20 +198,32 @@ cli.command("archive <change-name>", "归档阶段").action(
|
||||
},
|
||||
);
|
||||
|
||||
cli.command("status", "查看变更状态").action(async () => {
|
||||
const root = requireProjectRoot();
|
||||
const changes = await scanChanges(root);
|
||||
if (changes.length === 0) {
|
||||
console.log("当前无进行中的变更。");
|
||||
return;
|
||||
}
|
||||
for (const change of changes) {
|
||||
const progress = change.taskProgress
|
||||
? ` (${change.taskProgress.completed}/${change.taskProgress.total} 任务)`
|
||||
: "";
|
||||
console.log(`- ${change.name}${progress} [${change.documents.join(", ")}]`);
|
||||
}
|
||||
});
|
||||
cli.command("status [change-name]", "查看变更状态").action(
|
||||
async (changeName?: string) => {
|
||||
const root = requireProjectRoot();
|
||||
const config = await loadConfig(root);
|
||||
const changes = await scanChanges(root, config);
|
||||
|
||||
if (changeName) {
|
||||
const change = changes.find((c) => c.name === changeName);
|
||||
if (!change) {
|
||||
throw new CommandError(`变更 "${changeName}" 不存在`, {
|
||||
hint: "运行 rune status 查看所有变更",
|
||||
});
|
||||
}
|
||||
console.log(formatChangeStatus(change));
|
||||
} else {
|
||||
if (changes.length === 0) {
|
||||
console.log("当前无进行中的变更。");
|
||||
return;
|
||||
}
|
||||
for (const change of changes) {
|
||||
console.log(formatChangeStatus(change));
|
||||
console.log("---\n");
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
function handleError(e: unknown): never {
|
||||
if (e instanceof CliError) {
|
||||
|
||||
Reference in New Issue
Block a user