Skip to content

Commit 0706c17

Browse files
authored
Add new command palette commands (#430)
This adds some new command palette commands for `buf` to expose some simple features alongside the LSP integration.
1 parent 9d45551 commit 0706c17

21 files changed

+792
-578
lines changed

biome.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"$schema": "https://biomejs.dev/schemas/2.1.2/schema.json",
2+
"$schema": "https://biomejs.dev/schemas/2.1.4/schema.json",
33
"assist": {
44
"actions": {
55
"source": {

package-lock.json

Lines changed: 236 additions & 544 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 81 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,79 @@
4848
"contributes": {
4949
"//": "This is kept in alphabetical order. https://code.visualstudio.com/api/references/contribution-points",
5050
"commands": [
51+
{
52+
"command": "buf.build",
53+
"category": "Buf",
54+
"icon": "$(files)",
55+
"title": "Build",
56+
"description": "Run `buf build` across VS Code workspace(s)."
57+
},
58+
{
59+
"command": "buf.configinit",
60+
"category": "Buf",
61+
"icon": "$(file-add)",
62+
"title": "Init",
63+
"description": "Run `buf config init` to initialize a new Buf workspace"
64+
},
65+
{
66+
"command": "buf.configlsbreakingrules",
67+
"category": "Buf",
68+
"icon": "$(list-unordered)",
69+
"title": "List available breaking change detection rules."
70+
},
71+
{
72+
"command": "buf.configlslintrules",
73+
"category": "Buf",
74+
"icon": "$(list-unordered)",
75+
"title": "List available lint rules."
76+
},
77+
{
78+
"command": "buf.configlsmodules",
79+
"category": "Buf",
80+
"icon": "$(folder-library)",
81+
"title": "List modules in workspace."
82+
},
83+
{
84+
"command": "buf.depprune",
85+
"category": "Buf",
86+
"icon": "$(gather)",
87+
"title": "Prune module dependencies.",
88+
"description": "Run `buf dep prune` across VS Code workspace(s) to prune unused buf.lock dependencies."
89+
},
90+
{
91+
"command": "buf.depupdate",
92+
"category": "Buf",
93+
"icon": "$(repo-pull)",
94+
"title": "Update module dependencies.",
95+
"description": "Run `buf dep update` across VS Code workspace(s) to update buf.lock dependencies."
96+
},
5197
{
5298
"command": "buf.generate",
5399
"category": "Buf",
54-
"icon": "$(run)",
100+
"icon": "$(file-submodule)",
55101
"title": "Generate",
56-
"description": "Run Buf to generate code with protoc plugins."
102+
"description": "Run `buf generate` across VS Code workspace(s)."
57103
},
58104
{
59-
"command": "buf.showOutput",
105+
"command": "buf.lsfiles",
60106
"category": "Buf",
61-
"icon": "$(output)",
62-
"title": "Show Buf Output"
107+
"icon": "$(files)",
108+
"title": "List module files.",
109+
"description": "List module files across VS Code workspace(s)."
110+
},
111+
{
112+
"command": "buf.price",
113+
"category": "Buf",
114+
"icon": "$(briefcase)",
115+
"title": "Price for BSR paid plans.",
116+
"description": "Check the price of BSR paid plans across VS Code workspace(s)."
117+
},
118+
{
119+
"command": "buf.stats",
120+
"category": "Buf",
121+
"icon": "$(graph-line)",
122+
"title": "Module stats",
123+
"description": "Get stats for Buf modules across VS Code workspace(s)."
63124
},
64125
{
65126
"command": "buf.install",
@@ -69,11 +130,10 @@
69130
"description": "Install the Buf CLI from GitHub releases."
70131
},
71132
{
72-
"command": "buf.update",
133+
"command": "buf.showOutput",
73134
"category": "Buf",
74-
"icon": "$(arrow-swap)",
75-
"title": "Update CLI",
76-
"description": "Check for updates and install the latest version of the Buf CLI."
135+
"icon": "$(output)",
136+
"title": "Show Buf Output"
77137
},
78138
{
79139
"command": "buf.startLanguageServer",
@@ -86,6 +146,13 @@
86146
"category": "Buf",
87147
"icon": "$(debug-stop)",
88148
"title": "Stop Buf Language Server"
149+
},
150+
{
151+
"command": "buf.update",
152+
"category": "Buf",
153+
"icon": "$(sync)",
154+
"title": "Update CLI",
155+
"description": "Check for updates and install the latest version of the Buf CLI."
89156
}
90157
],
91158
"configuration": {
@@ -234,25 +301,26 @@
234301
"format": "biome format --write ."
235302
},
236303
"devDependencies": {
237-
"@biomejs/biome": "^2.1.2",
304+
"@biomejs/biome": "^2.1.4",
238305
"@playwright/test": "^1.54.2",
239-
"@types/mocha": "^10.0.6",
240-
"@types/node": "^24.2.0",
306+
"@types/mocha": "^10.0.10",
307+
"@types/node": "^24.2.1",
241308
"@types/semver": "^7.7.0",
242309
"@types/vscode": "^1.102.0",
243310
"@types/which": "^3.0.4",
244311
"@vscode/test-cli": "^0.0.11",
245312
"@vscode/test-electron": "^2.5.2",
246313
"@vscode/vsce": "^3.6.0",
247314
"cross-env": "^10.0.0",
248-
"mocha": "^10.8.2",
315+
"mocha": "^11.7.1",
249316
"msw": "^2.10.4",
250317
"typescript": "^5.9.2"
251318
},
252319
"dependencies": {
253320
"@preact/signals-core": "^1.11.0",
254321
"rimraf": "^6.0.1",
255322
"semver": "^7.7.2",
323+
"tmp": "^0.2.4",
256324
"vscode-languageclient": "^9.0.1",
257325
"which": "^5.0.0"
258326
}

src/commands/buf-build.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import * as vscode from "vscode";
2+
import { log } from "../log";
3+
import { bufState } from "../state";
4+
import { Command } from "./command";
5+
6+
/**
7+
* bufBuild prompts the user to provide an output path for the `buf build` command, and then
8+
* runs `buf build -o <output path>` at the root of each VS Code workspace folder.
9+
*
10+
* If there are no workspace folders, then bufBuild displays a warning and is a no-op.
11+
*
12+
* The output path is expected to be a relative path and defaults to "out.binpb".
13+
*/
14+
export const bufBuild = new Command(
15+
"buf.build",
16+
"COMMAND_TYPE_BUF",
17+
async () => {
18+
if (!vscode.workspace.workspaceFolders) {
19+
log.warn(`No workspace found, unable to run "buf build".`);
20+
return;
21+
}
22+
const recommendedOutPath = "out.binpb";
23+
const outPath = await vscode.window.showInputBox({
24+
placeHolder: recommendedOutPath,
25+
prompt: `Provide an output path for "buf build", e.g. ${recommendedOutPath}. If none is provided, then "buf build" will output to /dev/null.`,
26+
});
27+
const args = ["build"];
28+
if (outPath) {
29+
args.push("-o", outPath);
30+
}
31+
for (const workspaceFolder of vscode.workspace.workspaceFolders) {
32+
bufState.execBufCommand(args, workspaceFolder.uri.path);
33+
}
34+
}
35+
);

src/commands/buf-config-init.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import * as vscode from "vscode";
2+
import { log } from "../log";
3+
import { bufState } from "../state";
4+
import { Command } from "./command";
5+
6+
/**
7+
* bufConfigInit shows the output channel and runs `buf config init`.
8+
*/
9+
export const bufConfigInit = new Command(
10+
"buf.configinit",
11+
"COMMAND_TYPE_BUF",
12+
async () => {
13+
if (!vscode.workspace.workspaceFolders) {
14+
log.warn(`No workspace found, unable to run "buf config init"`);
15+
return;
16+
}
17+
for (const workspaceFolder of vscode.workspace.workspaceFolders) {
18+
bufState.execBufCommand(["config", "init"], workspaceFolder.uri.path);
19+
}
20+
}
21+
);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import * as vscode from "vscode";
2+
import { log } from "../log";
3+
import { bufState } from "../state";
4+
import { execFile } from "../util";
5+
import { Command } from "./command";
6+
7+
/**
8+
* bufConfigLsBreakingRules runs `buf config ls-breaking-rules` and shows the output in a
9+
* text document window.
10+
*/
11+
export const bufConfigLsBreakingRules = new Command(
12+
"buf.configlsbreakingrules",
13+
"COMMAND_TYPE_BUF",
14+
async () => {
15+
const bufBinaryPath = bufState.getBufBinaryPath();
16+
try {
17+
const { stdout, stderr } = await execFile(bufBinaryPath ?? "", [
18+
"config",
19+
"ls-breaking-rules",
20+
]);
21+
if (stderr) {
22+
log.error(`Error executing "buf config ls-breaking-rules": ${stderr}`);
23+
}
24+
const document = await vscode.workspace.openTextDocument({
25+
content: stdout,
26+
language: "plainText",
27+
});
28+
await vscode.window.showTextDocument(document, {
29+
viewColumn: vscode.ViewColumn.Active,
30+
preview: true,
31+
});
32+
} catch (e) {
33+
log.error(`Error executing "buf config ls-breaking-rules": ${e}`);
34+
}
35+
}
36+
);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import * as vscode from "vscode";
2+
import { log } from "../log";
3+
import { bufState } from "../state";
4+
import { execFile } from "../util";
5+
import { Command } from "./command";
6+
7+
/**
8+
* bufConfigLsLintRules runs `buf config ls-lint-rules` and shows the output in a text
9+
* document window.
10+
*/
11+
export const bufConfigLsLintRules = new Command(
12+
"buf.configlslintrules",
13+
"COMMAND_TYPE_BUF",
14+
async () => {
15+
const bufBinaryPath = bufState.getBufBinaryPath();
16+
try {
17+
const { stdout, stderr } = await execFile(bufBinaryPath ?? "", [
18+
"config",
19+
"ls-lint-rules",
20+
]);
21+
if (stderr) {
22+
log.error(`Error executing "buf config ls-lint-rules": ${stderr}`);
23+
}
24+
const document = await vscode.workspace.openTextDocument({
25+
content: stdout,
26+
language: "plainText",
27+
});
28+
await vscode.window.showTextDocument(document, {
29+
viewColumn: vscode.ViewColumn.Active,
30+
preview: true,
31+
});
32+
} catch (e) {
33+
log.error(`Error executing "buf config ls-lint-rules": ${e}`);
34+
}
35+
}
36+
);
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import * as vscode from "vscode";
2+
import { log } from "../log";
3+
import { bufState } from "../state";
4+
import { Command } from "./command";
5+
6+
/**
7+
* Minimum Buf version required for `buf config ls-modules` command.
8+
*/
9+
const minBufVersion = "v1.34.0";
10+
11+
/**
12+
* bufConfigLsModules shows the output channel and runs `buf config ls-modules` at the root
13+
* of each VS Code workspace folder. If there are no workspace folders, then bufConfigLsModules
14+
* displays a warning and is a no-op.
15+
*/
16+
export const bufConfigLsModules = new Command(
17+
"buf.configlsmodules",
18+
"COMMAND_TYPE_BUF",
19+
async () => {
20+
log.show();
21+
if (!vscode.workspace.workspaceFolders) {
22+
log.warn(`No workspace found, unable to run "buf config ls-modules"`);
23+
return;
24+
}
25+
const bufVersion = bufState.getBufBinaryVersion();
26+
if (bufVersion?.compare(minBufVersion) === -1) {
27+
log.warn(
28+
`Current Buf Version ${bufVersion} does not meet minimum required version ${minBufVersion}, unable to run "buf config ls-modules".`
29+
);
30+
return;
31+
}
32+
for (const workspaceFolder of vscode.workspace.workspaceFolders) {
33+
bufState.execBufCommand(
34+
["config", "ls-modules"],
35+
workspaceFolder.uri.path
36+
);
37+
}
38+
}
39+
);

src/commands/buf-dep-prune.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import * as vscode from "vscode";
2+
import { log } from "../log";
3+
import { bufState } from "../state";
4+
import { Command } from "./command";
5+
6+
/**
7+
* bufDepPrune runs `buf dep prune` at the root of each VS Code workspace folder. If there
8+
* are no workspace folders, then bufDepPrune displays a warning and is a no-op.
9+
*/
10+
export const bufDepPrune = new Command(
11+
"buf.depprune",
12+
"COMMAND_TYPE_BUF",
13+
async () => {
14+
log.show();
15+
if (!vscode.workspace.workspaceFolders) {
16+
log.warn(`No workspace found, unable to run "buf dep prune"`);
17+
return;
18+
}
19+
for (const workspaceFolder of vscode.workspace.workspaceFolders) {
20+
bufState.execBufCommand(["dep", "prune"], workspaceFolder.uri.path);
21+
}
22+
}
23+
);

src/commands/buf-dep-update.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import * as vscode from "vscode";
2+
import { log } from "../log";
3+
import { bufState } from "../state";
4+
import { Command } from "./command";
5+
6+
/**
7+
* bufDepUpdate runs `buf dep update` at the root of each VS Code workspace folder. If there
8+
* are no workspace folders, then bufDepUpdate displays a warning and is a no-op.
9+
*/
10+
export const bufDepUpdate = new Command(
11+
"buf.depupdate",
12+
"COMMAND_TYPE_BUF",
13+
async () => {
14+
if (!vscode.workspace.workspaceFolders) {
15+
log.warn(`No workspace found, unable to run "buf dep update"`);
16+
return;
17+
}
18+
for (const workspaceFolder of vscode.workspace.workspaceFolders) {
19+
bufState.execBufCommand(["dep", "update"], workspaceFolder.uri.path);
20+
}
21+
}
22+
);

0 commit comments

Comments
 (0)