diff --git a/src/extension.ts b/src/extension.ts index 080af39..73b650a 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -37,7 +37,9 @@ async function initializeMisePath() { "Mise binary not found. Please configure the binary path.", { settingsKey: "mise.binPath", type: "error" }, ); - logger.error("Failed to resolve mise binary path:", error as Error); + logger.info( + `Failed to resolve mise binary path: ${error instanceof Error ? error?.message : String(error)}`, + ); } } @@ -111,21 +113,28 @@ export async function activate(context: vscode.ExtensionContext) { const taskProvider = vscode.tasks.registerTaskProvider("mise", { provideTasks: async () => { const tasks = await miseService.getTasks(); - return tasks.map((task) => { - const taskDefinition: vscode.TaskDefinition = { - type: "mise", - task: task.name, - }; - const baseCommand = miseService.createMiseCommand(`run ${task.name}`); - const execution = new vscode.ShellExecution(baseCommand); - return new vscode.Task( - taskDefinition, - vscode.TaskScope.Workspace, - task.name, - "mise", - execution, - ); - }); + return tasks + .map((task) => { + const taskDefinition: vscode.TaskDefinition = { + type: "mise", + task: task.name, + }; + + const baseCommand = miseService.createMiseCommand(`run ${task.name}`); + if (!baseCommand) { + return undefined; + } + + const execution = new vscode.ShellExecution(baseCommand); + return new vscode.Task( + taskDefinition, + vscode.TaskScope.Workspace, + task.name, + "mise", + execution, + ); + }) + .filter((task) => task !== undefined); }, resolveTask(_task: vscode.Task): vscode.Task | undefined { return undefined; diff --git a/src/miseService.ts b/src/miseService.ts index cb8745b..5738c34 100644 --- a/src/miseService.ts +++ b/src/miseService.ts @@ -3,6 +3,14 @@ import { logger } from "./utils/logger"; import { execAsync } from "./utils/shell"; import { type MiseTaskInfo, parseTaskInfo } from "./utils/taskInfoParser"; +function ensureMiseCommand( + miseCommand: string | undefined, +): asserts miseCommand { + if (!miseCommand) { + throw new Error("Mise binary path is not configured"); + } +} + export class MiseService { private terminal: vscode.Terminal | undefined; private readonly workspaceRoot: string | undefined; @@ -13,14 +21,20 @@ export class MiseService { async execMiseCommand(command: string) { const miseCommand = this.createMiseCommand(command); + ensureMiseCommand(miseCommand); logger.info(`Executing mise command: ${miseCommand}`); return execAsync(miseCommand, { cwd: this.workspaceRoot }); } + public getMiseBinaryPath(): string | undefined { + return vscode.workspace.getConfiguration("mise").get("binPath"); + } + public createMiseCommand(command: string) { - const miseBinaryPath = vscode.workspace - .getConfiguration("mise") - .get("binPath"); + const miseBinaryPath = this.getMiseBinaryPath(); + if (!miseBinaryPath) { + return undefined; + } let miseCommand = `"${miseBinaryPath}"`; const miseProfile = vscode.workspace @@ -66,6 +80,10 @@ export class MiseService { } async getTasks(): Promise { + if (!this.getMiseBinaryPath()) { + return []; + } + try { const { stdout } = await this.execMiseCommand("tasks ls --json"); return JSON.parse(stdout).map((task: MiseTask) => ({ @@ -85,6 +103,10 @@ export class MiseService { } async getTaskInfo(taskName: string): Promise { + if (!this.getMiseBinaryPath()) { + return undefined; + } + try { const { stdout } = await this.execMiseCommand(`tasks info ${taskName}`); return parseTaskInfo(stdout); @@ -95,6 +117,10 @@ export class MiseService { } async getTools(): Promise> { + if (!this.getMiseBinaryPath()) { + return []; + } + try { const { stdout } = await this.execMiseCommand( "ls --current --offline --json", @@ -124,6 +150,10 @@ export class MiseService { } async getEnvs(): Promise { + if (!this.getMiseBinaryPath()) { + return []; + } + try { const { stdout } = await this.execMiseCommand("env --json"); return Object.entries(JSON.parse(stdout)).map(([key, value]) => ({ @@ -145,6 +175,7 @@ export class MiseService { const terminal = this.getOrCreateTerminal(); terminal.show(); const baseCommand = this.createMiseCommand(`run --timing ${taskName}`); + ensureMiseCommand(baseCommand); terminal.sendText(`${baseCommand} ${args.join(" ")}`); } @@ -154,6 +185,7 @@ export class MiseService { const baseCommand = this.createMiseCommand( `watch -t "${taskName.replace(/"/g, '\\"')}"`, ); + ensureMiseCommand(baseCommand); terminal.sendText(`${baseCommand} ${args.join(" ")}`); } diff --git a/src/providers/toolsProvider.ts b/src/providers/toolsProvider.ts index d613fbc..b81f106 100644 --- a/src/providers/toolsProvider.ts +++ b/src/providers/toolsProvider.ts @@ -180,6 +180,11 @@ async function runMiseToolActionInConsole( .createMiseCommand(command); outputChannel.appendLine(`> ${miseCommand}`); + if (!miseCommand) { + logger.warn("Could not find mise binary"); + return; + } + const execution = new vscode.ShellExecution(miseCommand); const task = new vscode.Task( { type: "mise" }, diff --git a/src/utils/miseBinLocator.ts b/src/utils/miseBinLocator.ts index 37a464f..7fa918b 100644 --- a/src/utils/miseBinLocator.ts +++ b/src/utils/miseBinLocator.ts @@ -43,7 +43,9 @@ export async function resolveMisePath(): Promise { } } - throw new Error("Could not find mise binary in any standard location"); + throw new Error( + "Could not find mise binary in any standard location (PATH, ~/.local/bin, ~/bin, /usr/local/bin, /opt/homebrew/bin...)", + ); } export async function isValidBinary(filepath: string): Promise { @@ -55,9 +57,8 @@ export async function isValidBinary(filepath: string): Promise { return stdout.toLowerCase().includes("mise"); } } catch (error) { - logger.error( - `Path ${filepath} is not a valid mise binary:`, - error as Error, + logger.info( + `Path ${filepath} is not a valid mise binary: ${error instanceof Error ? error.message : String(error)}`, ); } return false;