diff --git a/package.json b/package.json
index ffe1154c..39efc112 100644
--- a/package.json
+++ b/package.json
@@ -66,7 +66,11 @@
},
{
"command": "mesonbuild.build",
- "title": "Meson: Build"
+ "title": "Meson: Build",
+ "icon": {
+ "dark": "res/build-icon-dark.svg",
+ "light": "res/build-icon-light.svg"
+ }
},
{
"command": "mesonbuild.test",
@@ -88,6 +92,26 @@
"command": "mesonbuild.restartLanguageServer",
"title": "Meson: Restart Language Server"
},
+ {
+ "command": "mesonbuild.node.reconfigure",
+ "title": "Reconfigure",
+ "icon": {
+ "dark": "res/meson_32.svg",
+ "light": "res/meson_32.svg"
+ }
+ },
+ {
+ "command": "mesonbuild.node.build",
+ "title": "Build",
+ "icon": {
+ "dark": "res/build-icon-dark.svg",
+ "light": "res/build-icon-light.svg"
+ }
+ },
+ {
+ "command": "mesonbuild.node.clean",
+ "title": "Clean"
+ },
{
"command": "mesonbuild.node.runAll",
"title": "Run all",
@@ -398,11 +422,46 @@
},
"menus": {
"view/item/context": [
+ {
+ "command": "mesonbuild.node.reconfigure",
+ "when": "view == meson-project && viewItem == meson-projectroot",
+ "group": "inline"
+ },
+ {
+ "command": "mesonbuild.node.reconfigure",
+ "when": "view == meson-project && viewItem == meson-projectroot",
+ "group": "build@0"
+ },
+ {
+ "command": "mesonbuild.node.build",
+ "when": "view == meson-project && viewItem == meson-projectroot",
+ "group": "inline"
+ },
+ {
+ "command": "mesonbuild.node.build",
+ "when": "view == meson-project && viewItem == meson-projectroot",
+ "group": "build@1"
+ },
+ {
+ "command": "mesonbuild.node.clean",
+ "when": "view == meson-project && viewItem == meson-projectroot",
+ "group": "build@2"
+ },
{
"command": "mesonbuild.openBuildFile",
"when": "view == meson-project && viewItem == meson-target",
"group": "inline"
},
+ {
+ "command": "mesonbuild.openBuildFile",
+ "when": "view == meson-project && viewItem == meson-target",
+ "group": "build"
+ },
+ {
+ "command": "mesonbuild.node.build",
+ "when": "view == meson-project && viewItem == meson-target",
+ "group": "build"
+ },
{
"command": "mesonbuild.node.runAll",
"when": "view == meson-project && viewItem == meson-test-root",
@@ -424,18 +483,23 @@
"group": "run"
}
],
- "view/title": [
- {
- "command": "mesonbuild.reconfigure",
- "when": "view == meson-project",
- "group": "navigation"
- }
- ],
"commandPalette": [
{
"command": "mesonbuild.openBuildFile",
"when": "false"
},
+ {
+ "command": "mesonbuild.node.reconfigure",
+ "when": "false"
+ },
+ {
+ "command": "mesonbuild.node.build",
+ "when": "false"
+ },
+ {
+ "command": "mesonbuild.node.clean",
+ "when": "false"
+ },
{
"command": "mesonbuild.node.run",
"when": "false"
diff --git a/res/build-icon-dark.svg b/res/build-icon-dark.svg
new file mode 100644
index 00000000..2cd8a0c9
--- /dev/null
+++ b/res/build-icon-dark.svg
@@ -0,0 +1,8 @@
+
diff --git a/res/build-icon-light.svg b/res/build-icon-light.svg
new file mode 100644
index 00000000..79a8a633
--- /dev/null
+++ b/res/build-icon-light.svg
@@ -0,0 +1,8 @@
+
diff --git a/src/extension.ts b/src/extension.ts
index 11e0d4ef..8388cc24 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -21,7 +21,7 @@ import { activateFormatters } from "./formatters";
import { SettingsKey, TaskQuickPickItem } from "./types";
import { createLanguageServerClient } from "./lsp/common";
import { dirname, relative } from "path";
-import { IRunnableNode } from "./treeview/nodes/base";
+import { IBuildableNode, IRunnableNode } from "./treeview/nodes/base";
export let extensionPath: string;
export let workspaceState: vscode.Memento;
@@ -202,6 +202,22 @@ export async function activate(ctx: vscode.ExtensionContext) {
}),
);
+ ctx.subscriptions.push(
+ vscode.commands.registerCommand("mesonbuild.node.reconfigure", async () => {
+ runFirstTask("reconfigure");
+ }),
+ );
+
+ ctx.subscriptions.push(
+ vscode.commands.registerCommand("mesonbuild.node.build", async (node: IBuildableNode) => node.build()),
+ );
+
+ ctx.subscriptions.push(
+ vscode.commands.registerCommand("mesonbuild.node.clean", async () => {
+ runFirstTask("clean");
+ }),
+ );
+
// Two commands just to have different icons.
ctx.subscriptions.push(
vscode.commands.registerCommand("mesonbuild.node.runAll", async (node: IRunnableNode) => node.run()),
diff --git a/src/tasks.ts b/src/tasks.ts
index 506fcf79..fdf57b38 100644
--- a/src/tasks.ts
+++ b/src/tasks.ts
@@ -68,7 +68,7 @@ function createReconfigureTask(buildDir: string, sourceDir: string) {
export async function getMesonTasks(buildDir: string, sourceDir: string) {
try {
const defaultBuildTask = new vscode.Task(
- { type: "meson", mode: "build" },
+ { type: "meson", mode: "build", target: pseudoAllTarget },
"Build all targets",
"Meson",
new vscode.ShellExecution(extensionConfiguration("mesonPath"), ["compile", "-C", buildDir]),
diff --git a/src/treeview/nodes/base.ts b/src/treeview/nodes/base.ts
index 29bd40b7..ae0b6ec1 100644
--- a/src/treeview/nodes/base.ts
+++ b/src/treeview/nodes/base.ts
@@ -32,6 +32,11 @@ export abstract class BaseDirectoryNode extends BaseNode {
abstract buildFileTree(fpaths: T[]): FolderMap | Thenable>;
}
+// A node in the meson tree view that can be built.
+export interface IBuildableNode {
+ build(): Thenable;
+}
+
// A node in the meson tree view that can be run.
export interface IRunnableNode {
run(): Thenable;
diff --git a/src/treeview/nodes/targets.ts b/src/treeview/nodes/targets.ts
index d61eea57..20965906 100644
--- a/src/treeview/nodes/targets.ts
+++ b/src/treeview/nodes/targets.ts
@@ -5,7 +5,7 @@ import { BaseNode } from "../basenode";
import { Target, Targets } from "../../types";
import { TargetSourcesRootNode, TargetGeneratedSourcesRootNode } from "./sources";
import { extensionRelative, getTargetName } from "../../utils";
-import { BaseDirectoryNode } from "./base";
+import { BaseDirectoryNode, IBuildableNode } from "./base";
export class TargetDirectoryNode extends BaseDirectoryNode {
constructor(parentId: string, folder: string, targets: Targets) {
@@ -72,7 +72,7 @@ export class TargetDirectoryNode extends BaseDirectoryNode {
}
}
-export class TargetNode extends BaseNode {
+export class TargetNode extends BaseNode implements IBuildableNode {
constructor(
parentId: string,
private readonly target: Target,
@@ -123,6 +123,10 @@ export class TargetNode extends BaseNode {
return item;
}
+ async build() {
+ return vscode.commands.executeCommand("mesonbuild.build", await getTargetName(this.target));
+ }
+
private getIconPath() {
switch (this.target.type) {
case "executable":
diff --git a/src/treeview/nodes/toplevel.ts b/src/treeview/nodes/toplevel.ts
index 4290b0b2..920d7702 100644
--- a/src/treeview/nodes/toplevel.ts
+++ b/src/treeview/nodes/toplevel.ts
@@ -1,13 +1,14 @@
import * as vscode from "vscode";
import { BaseNode } from "../basenode";
-import { ProjectInfo, Subproject, Targets, Tests } from "../../types";
+import { ProjectInfo, Subproject, Targets, Tests, pseudoAllTarget } from "../../types";
import { extensionRelative } from "../../utils";
import { TargetDirectoryNode } from "./targets";
import { getMesonBenchmarks, getMesonTargets, getMesonTests } from "../../introspection";
import { TestRootNode } from "./tests";
+import { IBuildableNode } from "./base";
-export class ProjectNode extends BaseNode {
+export class ProjectNode extends BaseNode implements IBuildableNode {
constructor(
private readonly project: ProjectInfo,
projectDir: string,
@@ -26,6 +27,9 @@ export class ProjectNode extends BaseNode {
item.iconPath = extensionRelative("res/meson_32.svg");
item.collapsibleState = vscode.TreeItemCollapsibleState.Expanded;
+ // To key in to "when": "view == meson-project && viewItem == test" in package.json.
+ item.contextValue = "meson-projectroot";
+
return item;
}
@@ -60,6 +64,10 @@ export class ProjectNode extends BaseNode {
return children;
}
+
+ async build() {
+ return vscode.commands.executeCommand("mesonbuild.build", pseudoAllTarget);
+ }
}
class SubprojectsRootNode extends BaseNode {