diff --git a/package.json b/package.json index 84ebdea..67b1a20 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "zig.zigPath": { "type": "string", "default": null, - "description": "Set a custom path to the Zig binary." + "description": "Set a custom path to the Zig binary. Empty string will lookup zig in PATH." }, "zig.zigVersion": { "type": "string", diff --git a/src/zigBuild.ts b/src/zigBuild.ts index 7e99928..5394bf5 100644 --- a/src/zigBuild.ts +++ b/src/zigBuild.ts @@ -1,6 +1,7 @@ import { buildDiagnosticCollection, logChannel } from './extension'; import * as cp from 'child_process'; import * as vscode from 'vscode'; +import { getZigPath } from './zigUtil'; export function zigBuild(): void { const editor = vscode.window.activeTextEditor; @@ -28,7 +29,7 @@ export function zigBuild(): void { }); const cwd = vscode.workspace.getWorkspaceFolder(editor.document.uri).uri.fsPath; - const buildPath = config.get("zigPath"); + const buildPath = getZigPath(); logChannel.appendLine(`Starting building the current workspace at ${cwd}`); diff --git a/src/zigCompilerProvider.ts b/src/zigCompilerProvider.ts index 1d1b525..8ee7af0 100644 --- a/src/zigCompilerProvider.ts +++ b/src/zigCompilerProvider.ts @@ -5,6 +5,7 @@ import * as cp from "child_process"; import * as vscode from "vscode"; // This will be treeshaked to only the debounce function import { throttle } from "lodash-es"; +import { getZigPath } from "./zigUtil"; export default class ZigCompilerProvider implements vscode.CodeActionProvider { private buildDiagnostics: vscode.DiagnosticCollection; @@ -58,16 +59,15 @@ export default class ZigCompilerProvider implements vscode.CodeActionProvider { } private _doASTGenErrorCheck(change: vscode.TextDocumentChangeEvent) { - let config = vscode.workspace.getConfiguration("zig"); const textDocument = change.document; if (textDocument.languageId !== "zig") { return; } - const zig_path = config.get("zigPath"); + const zigPath = getZigPath(); const cwd = vscode.workspace.getWorkspaceFolder(textDocument.uri).uri .fsPath; - let childProcess = cp.spawn(zig_path as string, ["ast-check"], { cwd }); + let childProcess = cp.spawn(zigPath, ["ast-check"], { cwd }); if (!childProcess.pid) { return; diff --git a/src/zigFormat.ts b/src/zigFormat.ts index 271dfb9..8c66b42 100644 --- a/src/zigFormat.ts +++ b/src/zigFormat.ts @@ -1,6 +1,6 @@ import * as vscode from 'vscode'; import { TextEdit, OutputChannel } from 'vscode'; -import { execCmd } from './zigUtil'; +import { execCmd, getZigPath } from './zigUtil'; export class ZigFormatProvider implements vscode.DocumentFormattingEditProvider { private _channel: OutputChannel; @@ -80,8 +80,7 @@ export class ZigRangeFormatProvider implements vscode.DocumentRangeFormattingEdi } function zigFormat(document: vscode.TextDocument) { - const config = vscode.workspace.getConfiguration("zig"); - const zigPath = config.get("zigPath"); + const zigPath = getZigPath(); const options = { cmdArguments: ['fmt', '--stdin'], diff --git a/src/zigSetup.ts b/src/zigSetup.ts index 69cf3a8..e1cb566 100644 --- a/src/zigSetup.ts +++ b/src/zigSetup.ts @@ -172,13 +172,10 @@ export async function setupZig(context: ExtensionContext) { }); const configuration = workspace.getConfiguration("zig", null); - if (!configuration.get("zigPath", null)) { - const zigInPath = which.sync("zig", { nothrow: true }); - const options = ["Install", "Specify path"]; - if (zigInPath) options.push("Use Zig in PATH"); + if (configuration.get("zigPath", null) === null) { const response = await window.showInformationMessage( "Zig path hasn't been set, do you want to specify the path or install Zig?", - ...options + "Install", "Specify path", "Use Zig in PATH" ); if (response === "Install") { @@ -200,7 +197,7 @@ export async function setupZig(context: ExtensionContext) { await configuration.update("zigPath", uris[0].fsPath, true); } } else if (response == "Use Zig in PATH") { - await configuration.update("zigPath", zigInPath, true); + await configuration.update("zigPath", "", true); } else throw "zigPath not specified"; } diff --git a/src/zigUtil.ts b/src/zigUtil.ts index ba63a72..46d7758 100644 --- a/src/zigUtil.ts +++ b/src/zigUtil.ts @@ -2,6 +2,7 @@ import * as cp from 'child_process'; import * as fs from 'fs'; import * as path from 'path'; import { window, workspace } from 'vscode'; +import which from 'which'; export const isWindows = process.platform === 'win32'; @@ -50,7 +51,7 @@ export function execCmd let cmdArguments = options ? options.cmdArguments : []; childProcess = - cp.execFile(cmd, cmdArguments, { cwd: detectProjectRoot(fileName || workspace.rootPath + '/fakeFileName'), maxBuffer: 10 * 1024 * 1024}, handleExit); + cp.execFile(cmd, cmdArguments, { cwd: detectProjectRoot(fileName || workspace.rootPath + '/fakeFileName'), maxBuffer: 10 * 1024 * 1024 }, handleExit); childProcess.stdout.on('data', (data: Buffer) => { @@ -143,3 +144,16 @@ export function detectProjectRoot(fileName: string): string { } return undefined; } + +export function getZigPath(): string { + const configuration = workspace.getConfiguration("zig"); + let zigPath = configuration.get("zigPath", null); + if (!zigPath) { + zigPath = which.sync("zig", { nothrow: true }); + if (!zigPath) { + window.showErrorMessage("zig not found in PATH"); + throw "zig not found in PATH"; + } + } + return zigPath; +} diff --git a/src/zls.ts b/src/zls.ts index 824b1db..2bf03b8 100644 --- a/src/zls.ts +++ b/src/zls.ts @@ -16,6 +16,7 @@ import { } from "vscode-languageclient/node"; import which from "which"; import { shouldCheckUpdate } from "./extension"; +import { getZigPath } from "./zigUtil"; export let outputChannel: vscode.OutputChannel; export let client: LanguageClient | null = null; @@ -127,10 +128,12 @@ export async function startClient(context: ExtensionContext) { workspace: { async configuration(params, token, next) { let indexOfAstCheck = null; + let indexOfZigPath = null; for (const [index, param] of Object.entries(params.items)) { if (param.section === "zls.zig_exe_path") { param.section = `zig.zigPath`; + indexOfZigPath = index; } else if (param.section === "zls.enable_ast_check_diagnostics") { indexOfAstCheck = index; } else { @@ -143,6 +146,13 @@ export async function startClient(context: ExtensionContext) { if (indexOfAstCheck !== null) { result[indexOfAstCheck] = workspace.getConfiguration("zig").get("astCheckProvider", "zls") === "zls"; } + if (indexOfZigPath !== null) { + try { + result[indexOfZigPath] = getZigPath(); + } catch { + result[indexOfZigPath] = "zig"; + } + } return result; } @@ -174,11 +184,13 @@ export async function stopClient(): Promise { export async function promptAfterFailure(context: ExtensionContext): Promise { const configuration = workspace.getConfiguration("zig.zls"); - const response = await window.showWarningMessage("Couldn't find Zig Language Server (ZLS) executable", "Install ZLS", "Specify Path"); + const response = await window.showWarningMessage("Couldn't find Zig Language Server (ZLS) executable", + "Install", "Specify path", "Use ZLS in PATH", "Disable" + ); - if (response === "Install ZLS") { + if (response === "Install") { return await installExecutable(context); - } else if (response === "Specify Path") { + } else if (response === "Specify path") { const uris = await window.showOpenDialog({ canSelectFiles: true, canSelectFolders: false, @@ -190,6 +202,10 @@ export async function promptAfterFailure(context: ExtensionContext): Promise("path", null)) { - const response = await window.showInformationMessage("We recommend enabling ZLS (the Zig Language Server) for a better editing experience. Would you like to enable it? You can always change this later by modifying `zig.zls.enabled` in your settings.", "Enable", "Disable"); + const response = await window.showInformationMessage( + "We recommend enabling ZLS (the Zig Language Server) for a better editing experience. Would you like to install it? You can always change this later by modifying `zig.zls.enabled` in your settings.", + "Install", "Specify path", "Use ZLS in PATH", "Disable" + ); - if (response === "Enable") { + if (response === "Install") { + await configuration.update("enabled", true, true); await installExecutable(context); - } else if (response === "Disable") { - await configuration.update("enabled", false, true); - return; + } else if (response === "Specify path") { + await configuration.update("enabled", true, true); + const uris = await window.showOpenDialog({ + canSelectFiles: true, + canSelectFolders: false, + canSelectMany: false, + title: "Select Zig Language Server (ZLS) executable", + }); + + if (uris) { + await configuration.update("path", uris[0].fsPath, true); + } + } else { + await configuration.update("enabled", response === "Use ZLS in PATH", true); } }