Skip to content

Commit

Permalink
feat: multi-root workspaces: add ability to select folder to use with…
Browse files Browse the repository at this point in the history
… mise
  • Loading branch information
hverlin committed Dec 28, 2024
1 parent b99f789 commit f18adb3
Show file tree
Hide file tree
Showing 12 changed files with 385 additions and 201 deletions.
11 changes: 11 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,10 @@
"command": "mise.openMenu",
"title": "Mise: Open Menu"
},
{
"command": "mise.selectWorkspaceFolder",
"title": "Mise: Select Workspace Folder"
},
{
"command": "mise.runTask",
"title": "Mise: Run task",
Expand Down Expand Up @@ -558,6 +562,13 @@
"group": "inline",
"when": "editorLineNumber in mise.linesWithOutdatedTools"
}
],
"explorer/context": [
{
"command": "mise.selectWorkspaceFolder",
"group": "inline",
"when": "explorerResourceIsRoot && treeElementCanCollapse && workspaceFolderCount > 1"
}
]
},
"taskDefinitions": [
Expand Down
1 change: 1 addition & 0 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ export const MISE_USE_TOOL = "mise.useTool";
export const MISE_WATCH_TASK = "mise.watchTask";
export const MISE_FMT = "mise.fmt";
export const MISE_EDIT_SETTING = "mise.editSetting";
export const MISE_SELECT_WORKSPACE_FOLDER = "mise.selectWorkspaceFolder";
28 changes: 24 additions & 4 deletions src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,30 @@ export async function updateVSCodeSettings(
return updatedKeys;
}

export const getRootFolder = () => {
return vscode.workspace.workspaceFolders?.[0];
export const getCurrentWorkspaceFolder = (context: vscode.ExtensionContext) => {
const availableFolders = vscode.workspace.workspaceFolders;
if (!availableFolders) {
return;
}

const selectedWorkspaceFolder = context.workspaceState.get(
"selectedWorkspaceFolder",
);
if (!selectedWorkspaceFolder) {
return availableFolders[0];
}

const foundFolder = availableFolders.find(
(folder) => folder.name === selectedWorkspaceFolder,
);
if (foundFolder) {
return foundFolder;
}
return availableFolders[0];
};

export const getRootFolderPath = () => {
return getRootFolder()?.uri.fsPath;
export const getCurrentWorkspaceFolderPath = (
context: vscode.ExtensionContext,
) => {
return getCurrentWorkspaceFolder(context)?.uri.fsPath;
};
30 changes: 11 additions & 19 deletions src/extensionMenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
MISE_OPEN_EXTENSION_SETTINGS,
MISE_OPEN_MENU,
MISE_RELOAD,
MISE_SELECT_WORKSPACE_FOLDER,
MISE_SHOW_SETTINGS,
MISE_SHOW_TRACKED_CONFIG,
} from "./commands";
Expand All @@ -18,7 +19,6 @@ import { logger } from "./utils/logger";
export function createMenu(miseService: MiseService) {
return vscode.commands.registerCommand(MISE_OPEN_MENU, async () => {
const miseVersion = await miseService.getVersion();

const pick = await vscode.window.showQuickPick(
[
{
Expand All @@ -36,6 +36,12 @@ export function createMenu(miseService: MiseService) {
detail: "List & manage tracked configurations",
iconPath: new vscode.ThemeIcon("list-selection"),
},
(vscode.workspace.workspaceFolders?.length ?? 0) > 1
? {
label: "Select workspace",
detail: miseService.getCurrentWorkspaceFolderPath(),
}
: undefined,
{ label: "", kind: vscode.QuickPickItemKind.Separator },
{ label: "Mise version", detail: miseVersion },
{
Expand All @@ -62,24 +68,7 @@ export function createMenu(miseService: MiseService) {
label: "Enable extension",
detail: "Enable the mise extension for this workspace",
},
] satisfies Array<
vscode.QuickPickItem & {
label:
| "Mise tools"
| "Mise settings"
| "Tracked configurations"
| "Mise version"
| "Reload configuration"
| "Open extension settings"
| "About vscode-mise"
| "Disable the mise extension for this workspace"
| "Enable extension"
| "Install missing tools"
| "Install all tools"
| "Show logs"
| "";
}
>,
].filter((a) => a !== undefined) satisfies Array<vscode.QuickPickItem>,
{ title: "Mise - Command menu" },
);

Expand All @@ -96,6 +85,9 @@ export function createMenu(miseService: MiseService) {
case "Reload configuration":
await vscode.commands.executeCommand(MISE_RELOAD);
break;
case "Select workspace":
await vscode.commands.executeCommand(MISE_SELECT_WORKSPACE_FOLDER);
break;
case "Open extension settings":
await vscode.commands.executeCommand(MISE_OPEN_EXTENSION_SETTINGS);
break;
Expand Down
149 changes: 121 additions & 28 deletions src/miseExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ import {
MISE_OPEN_LOGS,
MISE_OPEN_MENU,
MISE_RELOAD,
MISE_SELECT_WORKSPACE_FOLDER,
MISE_SHOW_SETTINGS,
MISE_SHOW_TRACKED_CONFIG,
} from "./commands";
import {
CONFIGURATION_FLAGS,
getCurrentWorkspaceFolder,
getMiseEnv,
getRootFolder,
isMiseExtensionEnabled,
shouldAutomaticallyTrustMiseConfigFiles,
shouldConfigureExtensionsAutomatically,
Expand All @@ -27,6 +28,7 @@ import { createMenu } from "./extensionMenu";
import { MiseFileWatcher } from "./miseFileWatcher";
import { MiseService } from "./miseService";
import { ToolCompletionProvider } from "./providers/ToolCompletionProvider";
import { WorkspaceDecorationProvider } from "./providers/WorkspaceDecorationProvider";
import {
MiseEnvsProvider,
registerEnvsCommands,
Expand Down Expand Up @@ -56,18 +58,28 @@ import { allowedFileTaskDirs } from "./utils/miseUtilts";
import WebViewPanel from "./webviewPanel";

export class MiseExtension {
private miseService: MiseService = new MiseService();
private miseService!: MiseService;
private context!: vscode.ExtensionContext;
private statusBarItem = vscode.window.createStatusBarItem(
vscode.StatusBarAlignment.Right,
100,
vscode.StatusBarAlignment.Left,
0,
);
private miseFileWatcher: MiseFileWatcher | undefined;

async activate(context: vscode.ExtensionContext) {
this.context = context;
this.miseService = new MiseService(context);
context.subscriptions.push(this.statusBarItem);
this.statusBarItem.show();
this.updateStatusBar({ state: "loading" });

const workspaceDecorationProvider = new WorkspaceDecorationProvider(
context,
);
context.subscriptions.push(
vscode.window.registerFileDecorationProvider(workspaceDecorationProvider),
);

await this.resetState();

if (
Expand Down Expand Up @@ -125,6 +137,7 @@ export class MiseExtension {
try {
logger.info("Reloading Mise configuration");
this.updateStatusBar({ state: "loading" });
workspaceDecorationProvider.refresh();

await this.resetState();

Expand Down Expand Up @@ -178,6 +191,74 @@ export class MiseExtension {
}),
);

context.subscriptions.push(
vscode.commands.registerCommand(
MISE_SELECT_WORKSPACE_FOLDER,
async (selectedPath: vscode.Uri) => {
if (selectedPath) {
const selectedFolder = vscode.workspace.workspaceFolders?.find(
(folder) => folder.uri.fsPath === selectedPath.fsPath,
);

if (selectedFolder) {
context.workspaceState.update(
"selectedWorkspaceFolder",
selectedFolder.name,
);
vscode.commands.executeCommand(MISE_RELOAD);
}
return;
}

const selectedFolderName = getCurrentWorkspaceFolder(context)?.name;
const selectedFolder = await vscode.window.showWorkspaceFolderPick({
placeHolder: [
"Select a workspace folder to use with Mise",
selectedFolderName ? `Current: ${selectedFolderName}` : "",
]
.filter(Boolean)
.join(" "),
});
if (selectedFolder) {
context.workspaceState.update(
"selectedWorkspaceFolder",
selectedFolder.name,
);
vscode.commands.executeCommand(MISE_RELOAD);
}
},
),
);

vscode.workspace.onDidChangeWorkspaceFolders(() => {
const workspaceFolders = vscode.workspace.workspaceFolders;
if (!workspaceFolders?.length) {
context.workspaceState.update("selectedWorkspaceFolder", undefined);
vscode.commands.executeCommand(MISE_RELOAD);
return;
}

const selectedWorkspaceFolderName = context.workspaceState.get(
"selectedWorkspaceFolder",
);

const selectedFolder = vscode.workspace.workspaceFolders?.find(
(folder) => folder.name === selectedWorkspaceFolderName,
);

if (!selectedWorkspaceFolderName || !selectedFolder) {
const firstFolder = workspaceFolders[0];
if (!selectedFolder && firstFolder) {
context.workspaceState.update(
"selectedWorkspaceFolder",
firstFolder.name,
);
}
}

vscode.commands.executeCommand(MISE_RELOAD);
});

context.subscriptions.push(
vscode.commands.registerCommand(
MISE_OPEN_FILE,
Expand Down Expand Up @@ -224,18 +305,20 @@ export class MiseExtension {
}),
);

const rootFolder = getRootFolder();
if (rootFolder) {
const fileTaskRelativePattern = new vscode.RelativePattern(
rootFolder,
`{${allowedFileTaskDirs.map((dir) => `${dir}/**/*`)}}`,
);
context.subscriptions.push(
vscode.languages.registerCodeLensProvider(
[{ pattern: fileTaskRelativePattern }, { language: "shellscript" }],
new MiseFileTaskCodeLensProvider(this.miseService),
),
);
const rootFolders = vscode.workspace.workspaceFolders;
if (rootFolders) {
for (const rootFolder of rootFolders) {
const fileTaskRelativePattern = new vscode.RelativePattern(
rootFolder,
`{${allowedFileTaskDirs.map((dir) => `${dir}/**/*`)}}`,
);
context.subscriptions.push(
vscode.languages.registerCodeLensProvider(
[{ pattern: fileTaskRelativePattern }, { language: "shellscript" }],
new MiseFileTaskCodeLensProvider(this.miseService),
),
);
}
}

context.subscriptions.push(
Expand Down Expand Up @@ -472,6 +555,13 @@ export class MiseExtension {
if (miseEnv) {
this.statusBarItem.text += ` (${miseEnv})`;
}

if ((vscode.workspace.workspaceFolders?.length || 0) > 1) {
const selectedFolder = getCurrentWorkspaceFolder(this.context);
if (selectedFolder) {
this.statusBarItem.text += ` [${selectedFolder?.name ?? "?"}]`;
}
}
}

private async updateStatusBarTooltip() {
Expand All @@ -480,19 +570,22 @@ export class MiseExtension {
.catch(() => "unknown");
this.statusBarItem.tooltip = new MarkdownString("", true);
this.statusBarItem.tooltip.isTrusted = true;
this.statusBarItem.tooltip.appendMarkdown(
`Mise VSCode ${version} - [Command Menu](command:mise.openMenu)

[$(tools) Mise Tools](command:mise.listAllTools)
[$(gear) Mise Settings](command:mise.showSettings)
[$(list-unordered) Tracked Configurations](command:mise.showTrackedConfig)
[BinPath: ${displayPathRelativeTo(this.miseService.getMiseBinaryPath() || "Not set", "")}](command:${MISE_OPEN_EXTENSION_SETTINGS})
Mise Version: ${miseVersion}`,
);
const selectedFolderName = getCurrentWorkspaceFolder(this.context)?.name;

const infoList = [
`Mise VSCode ${version} - [Command Menu](command:${MISE_OPEN_MENU})`,
(vscode.workspace.workspaceFolders?.length || 0) > 1
? `[Select Workspace Folder](command:${MISE_SELECT_WORKSPACE_FOLDER}) [${selectedFolderName}]`
: "",
`[$(tools) Mise Tools](command:${MISE_LIST_ALL_TOOLS})`,
`[$(gear) Mise Settings](command:${MISE_SHOW_SETTINGS})`,
`[$(list-unordered) Tracked Configurations](command:${MISE_SHOW_TRACKED_CONFIG})`,
`[BinPath: ${displayPathRelativeTo(this.miseService.getMiseBinaryPath() || "Not set", "")}](command:${MISE_OPEN_EXTENSION_SETTINGS})`,
`Mise Version: ${miseVersion}`,
].filter(Boolean);

this.statusBarItem.tooltip.appendMarkdown(infoList.join("\n\n"));
}

setErrorState(errorMsg: string) {
Expand Down
Loading

0 comments on commit f18adb3

Please sign in to comment.