Skip to content

Commit

Permalink
Allow predefined variables in all configuration options
Browse files Browse the repository at this point in the history
  • Loading branch information
Jarred-Sumner authored and Vexu committed Apr 15, 2024
1 parent df63524 commit 7095658
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 16 deletions.
4 changes: 2 additions & 2 deletions src/zigCompilerProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import path from "path";
import { DebouncedFunc, throttle } from "lodash-es";

import * as zls from "./zls";
import { getZigPath } from "./zigUtil";
import { getZigPath, handleConfigOption } from "./zigUtil";

export default class ZigCompilerProvider {
private buildDiagnostics!: vscode.DiagnosticCollection;
Expand Down Expand Up @@ -148,7 +148,7 @@ export default class ZigCompilerProvider {
if (!buildFilePath) break;
processArg.push("--build-file");
try {
processArg.push(path.resolve(buildFilePath.replace("${workspaceFolder}", cwd)));
processArg.push(path.resolve(handleConfigOption(buildFilePath)));
} catch {
//
}
Expand Down
58 changes: 46 additions & 12 deletions src/zigUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,57 @@ import which from "which";

export const isWindows = process.platform === "win32";

export function getExePath(exePath: string | null, exeName: string, optionName: string): string {
// Allow passing the ${workspaceFolder} predefined variable
// See https://code.visualstudio.com/docs/editor/variables-reference#_predefined-variables
if (exePath?.includes("${workspaceFolder}")) {
// We choose the first workspaceFolder since it is ambiguous which one to use in this context
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) {
// older versions of Node (which VSCode uses) may not have String.prototype.replaceAll
exePath = exePath.replace(/\$\{workspaceFolder\}/gm, vscode.workspace.workspaceFolders[0].uri.fsPath);
// Replace any references to predefined variables in config string.
// https://code.visualstudio.com/docs/editor/variables-reference#_predefined-variables
export function handleConfigOption(input: string): string {
if (input.includes("${userHome}")) {
input = input.replaceAll("${userHome}", os.homedir());
}

if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) {
input = input.replaceAll("${workspaceFolder}", vscode.workspace.workspaceFolders[0].uri.fsPath);
input = input.replaceAll("${workspaceFolderBasename}", vscode.workspace.workspaceFolders[0].name);
}

const document = vscode.window.activeTextEditor?.document;
if (document) {
input = input.replaceAll("${file}", document.fileName);
input = input.replaceAll("${fileBasename}", path.basename(document.fileName));
input = input.replaceAll(
"${fileBasenameNoExtension}",
path.basename(document.fileName, path.extname(document.fileName)),
);
input = input.replaceAll("${fileExtname}", path.extname(document.fileName));
input = input.replaceAll("${fileDirname}", path.dirname(document.fileName));
input = input.replaceAll("${fileDirnameBasename}", path.basename(path.dirname(document.fileName)));
}

input = input.replaceAll("${pathSeparator}", path.sep);
input = input.replaceAll("${/}", path.sep);
if (input.includes("${cwd}")) {
input = input.replaceAll("${cwd}", process.cwd());
}

if (input.includes("${env:")) {
for (let env = input.match(/\${env:([^}]+)}/)?.[1]; env; env = input.match(/\${env:([^}]+)}/)?.[1]) {
input = input.replaceAll(`\${env:${env}}`, process.env[env] ?? "");
}
}
return input;
}

export function getExePath(exePath: string | null, exeName: string, optionName: string): string {
if (exePath === null) {
exePath = which.sync(exeName, { nothrow: true });
} else if (exePath.startsWith("~")) {
exePath = path.join(os.homedir(), exePath.substring(1));
} else if (!path.isAbsolute(exePath)) {
exePath = which.sync(exePath, { nothrow: true });
} else {
// allow passing predefined variables
exePath = handleConfigOption(exePath);

if (exePath.startsWith("~")) {
exePath = path.join(os.homedir(), exePath.substring(1));
} else if (!path.isAbsolute(exePath)) {
exePath = which.sync(exePath, { nothrow: true });
}
}

let message;
Expand Down
22 changes: 20 additions & 2 deletions src/zls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,15 @@ import camelCase from "camelcase";
import mkdirp from "mkdirp";
import semver from "semver";

import { getExePath, getHostZigName, getVersion, getZigPath, isWindows, shouldCheckUpdate } from "./zigUtil";
import {
getExePath,
getHostZigName,
getVersion,
getZigPath,
handleConfigOption,
isWindows,
shouldCheckUpdate,
} from "./zigUtil";

let outputChannel: vscode.OutputChannel;
export let client: LanguageClient | null = null;
Expand Down Expand Up @@ -100,6 +108,17 @@ async function configurationMiddleware(
return result;
}

const configuration = vscode.workspace.getConfiguration("zig.zls");

for (const name in optionIndices) {
const index = optionIndices[name] as unknown as number;
const section = name.slice("zig.zls.".length);
const configValue = configuration.get(section);
if (typeof configValue === "string" && configValue) {
result[index] = handleConfigOption(configValue);
}
}

const indexOfZigPath = optionIndices["zig.path"];
if (indexOfZigPath !== undefined) {
try {
Expand All @@ -111,7 +130,6 @@ async function configurationMiddleware(
}
}

const configuration = vscode.workspace.getConfiguration("zig.zls");
const additionalOptions = configuration.get<Record<string, unknown>>("additionalOptions", {});

for (const optionName in additionalOptions) {
Expand Down

0 comments on commit 7095658

Please sign in to comment.