Skip to content

Commit

Permalink
Refactor support for multiple Meson projects
Browse files Browse the repository at this point in the history
There were many issues, including:
- The most common case is to have a meson.build at the root of the
  workspace. In that case we should not ask user anything.
- Only the first meson.build in a subdir tree is useful, others are
  unlikely to be projects.
- We need a way to never ask again to select a meson file, especially
  important when opening meson project itself which does not have a
  meson.build at the root, but many projects in test cases.
- If the user cancels selection, the meson extension cannot do anything
  and should be hidden.
- Selecting a meson file and configuring the project are 2 distinct
  questions. The user may want to select a file but not let vscode
  configure it. It is common to configure from an external terminal.
  • Loading branch information
xclaesse committed Nov 17, 2023
1 parent 1c3d322 commit 0d5ba93
Show file tree
Hide file tree
Showing 5 changed files with 222 additions and 142 deletions.
45 changes: 45 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,20 @@
{
"command": "mesonbuild.restartLanguageServer",
"title": "Meson: Restart Language Server"
},
{
"command": "mesonbuild.selectRootDir",
"title": "Meson: Select another project root dir"
}
],
"configuration": {
"title": "Meson build configuration",
"properties": {
"mesonbuild.selectRootDir": {
"type": "boolean",
"default": true,
"description": "Should Meson ask to select a Meson project root directory when more than one project is detected."
},
"mesonbuild.configureOnOpen": {
"type": [
"boolean",
Expand Down Expand Up @@ -405,6 +414,42 @@
{
"command": "mesonbuild.openBuildFile",
"when": "false"
},
{
"command": "mesonbuild.reconfigure",
"when": "mesonbuild.hasProject"
},
{
"command": "mesonbuild.clean",
"when": "mesonbuild.hasProject"
},
{
"command": "mesonbuild.build",
"when": "mesonbuild.hasProject"
},
{
"command": "mesonbuild.test",
"when": "mesonbuild.hasProject"
},
{
"command": "mesonbuild.run",
"when": "mesonbuild.hasProject"
},
{
"command": "mesonbuild.install",
"when": "mesonbuild.hasProject"
},
{
"command": "mesonbuild.benchmark",
"when": "mesonbuild.hasProject"
},
{
"command": "mesonbuild.restartLanguageServer",
"when": "mesonbuild.hasProject"
},
{
"command": "mesonbuild.selectRootDir",
"when": "mesonbuild.hasMultipleProjects"
}
]
},
Expand Down
115 changes: 115 additions & 0 deletions src/dialogs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import * as vscode from "vscode";
import { relative } from "path";
import { extensionConfiguration, extensionConfigurationSet } from "./utils";
import { SettingsKey } from "./types";

export async function askConfigureOnOpen(): Promise<boolean> {
let configureOnOpen = extensionConfiguration(SettingsKey.configureOnOpen);

if (typeof configureOnOpen === "boolean") return configureOnOpen;

enum Options {
yes = "Yes",
always = "Always",
no = "No",
never = "Never",
}

const response = await vscode.window.showInformationMessage(
"Meson project detected in this workspace but does not seems to be configured. Would you like VS Code to configure it?",
...Object.values(Options),
);

switch (response) {
case Options.no:
return false;
case Options.never:
extensionConfigurationSet(SettingsKey.configureOnOpen, false, vscode.ConfigurationTarget.Workspace);
return false;
case Options.yes:
return true;
case Options.always:
extensionConfigurationSet(SettingsKey.configureOnOpen, true, vscode.ConfigurationTarget.Workspace);
return true;
}

return false;
}

export async function askShouldDownload(): Promise<boolean> {
const downloadLanguageServer = extensionConfiguration(SettingsKey.downloadLanguageServer);

if (typeof downloadLanguageServer === "boolean") return downloadLanguageServer;

enum Options {
yes = "Yes",
no = "Not this time",
never = "Never",
}

const response = await vscode.window.showInformationMessage(
"Should the extension try to download the language server?",
...Object.values(Options),
);

switch (response) {
case Options.yes:
extensionConfigurationSet(SettingsKey.downloadLanguageServer, true, vscode.ConfigurationTarget.Global);
return true;
case Options.never:
extensionConfigurationSet(SettingsKey.downloadLanguageServer, false, vscode.ConfigurationTarget.Global);
return false;
case Options.no:
return false;
}

return false;
}

export async function askSelectRootDir(): Promise<boolean> {
const selectRootDir = extensionConfiguration(SettingsKey.selectRootDir);

if (!selectRootDir) return false;

enum Options {
yes = "Yes",
no = "No",
never = "Never",
}

const response = await vscode.window.showInformationMessage(
"Multiple Meson projects detected, select one?",
...Object.values(Options),
);

switch (response) {
case Options.yes:
return true;
case Options.no:
return false;
case Options.never:
extensionConfigurationSet(SettingsKey.selectRootDir, false, vscode.ConfigurationTarget.Workspace);
return false;
}

return false;
}

export async function selectRootDir(rootDirs: string[]): Promise<string | undefined> {
// TODO: What label to use when there is more than one workspace?
const root = vscode.workspace.rootPath ?? "";
const items = rootDirs.map((file, index) => ({ index: index, label: relative(root, file) }));
items.sort((a, b) => a.label.localeCompare(b.label));
const selection = await vscode.window.showQuickPick(items, {
canPickMany: false,
title: "Select configuration to use.",
placeHolder: "path/to/meson.build",
});
if (selection) return rootDirs[selection.index];
return undefined;
}

export async function askAndSelectRootDir(rootDirs: string[]): Promise<string | undefined> {
if (await askSelectRootDir()) return selectRootDir(rootDirs);
return undefined;
}
Loading

0 comments on commit 0d5ba93

Please sign in to comment.