changesCommands
The Changes view's commands: the changes a history entry made or a branch has (tcm diff, as a document),
resetting the names to an entry, merging a branch into this one, and showing more history.
import { runTcm } from "#codebase/tcmts/vscode/changes"; import type { ChangesNode, ChangesTree } from "#codebase/tcmts/vscode/changes"; import * as vscode from "vscode"; export function changesCommands(tree: ChangesTree, cwd: string | undefined): vscode.Disposable[] { const show = async (title: string, args: string[]) => { const r = await runTcm(args, cwd); const doc = await vscode.workspace.openTextDocument({ content: `# ${title}\n\n${r.out}`, language: "diff" }); await vscode.window.showTextDocument(doc, { preview: true }); }; return [ // the definitions whose code the changes touched, in VS Code's multi-file diff editor: edits old beside new, // additions and removals whole (renames, and dependents only re-hashed, are in the tree: their code is the same) vscode.commands.registerCommand("tcm.showChanges", async (x?: ChangesNode) => { if (x?.kind !== "entry" && x?.kind !== "branch") return; const title = x.kind === "entry" ? `${x.command} (${x.short})` : `${tree.branch || "this branch"} → ${x.name}`; const changes = (await tree.changesOf(x)).filter((c) => (c.change === "edited" || c.change === "added" || c.change === "removed") && c.uri); if (!changes.length) return vscode.window.showInformationMessage(`${title}: no code changed`); const uri = (u: string | undefined) => (u ? vscode.Uri.parse(u) : undefined); const label = (path: string) => vscode.Uri.from({ scheme: "tcm", path: `/${path.replaceAll(".", "/")}.ts` }); const resources = changes.map((c) => c.change === "edited" ? [label(c.path), uri(c.oldUri), uri(c.uri)] : c.change === "removed" ? [label(c.path), uri(c.uri), undefined] : [label(c.path), undefined, uri(c.uri)], ); return vscode.commands.executeCommand("vscode.changes", title, resources); }), vscode.commands.registerCommand("tcm.showChangesText", (x?: ChangesNode) => { if (x?.kind === "entry") return show(`${x.command} (${x.short})`, ["diff", x.parents[0]!, x.hash]); if (x?.kind === "branch") return show(`this branch → ${x.name}`, ["diff", x.name]); return show("the last command's changes", ["diff"]); }), vscode.commands.registerCommand("tcm.resetTo", async (x?: ChangesNode) => { if (x?.kind !== "entry") return; const ok = await vscode.window.showWarningMessage( `Bring back the names as they were after "${x.command}" (${x.short})?`, { modal: true, detail: "A new history entry on top: nothing is rewritten, and it can be undone the same way. Code isn't deleted." }, "Reset", ); if (ok !== "Reset") return; const r = await runTcm(["reset", x.hash], cwd); if (r.code) vscode.window.showErrorMessage(`tcm reset: ${r.out.trim()}`); else vscode.window.showInformationMessage(r.out.trim().split("\n").at(-1) ?? "reset"); }), vscode.commands.registerCommand("tcm.mergeBranch", async (x?: ChangesNode) => { if (x?.kind !== "branch" || x.current) return; const ok = await vscode.window.showWarningMessage(`Merge ${x.name} into ${tree.branch || "this branch"}?`, { modal: true, detail: `${x.differs} name(s) differ. Conflicts, if any, are listed by tcm todo.` }, "Merge"); if (ok !== "Merge") return; const r = await runTcm(["merge", x.name], cwd); if (r.code) vscode.window.showErrorMessage(`tcm merge: ${r.out.trim()}`); else vscode.window.showInformationMessage(r.out.trim().split("\n").at(-1) ?? "merged"); }), vscode.commands.registerCommand("tcm.moreHistory", () => { tree.limit += 30; tree.refresh(); }), vscode.commands.registerCommand("tcm.refreshChanges", () => tree.refresh()), ]; }