Skip to content

Commit

Permalink
Support variable substitution in configurations
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Jul 28, 2024
1 parent acb6f59 commit 839acfa
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 4 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
# Changelog

<!-- markdownlint-disable no-duplicate-header -->
<!-- markdownlint-disable no-duplicate-heading -->

## [Unreleased]

### Added

- Supports variable substitution in some configurations.

## [1.6.4] - 2023-11-13

### Fixed
Expand Down
21 changes: 19 additions & 2 deletions projects/extension/src/configurations.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Engine } from "./engines";
import * as dot from "./engines/dot";
import { WorkspaceConfiguration } from "vscode";
import * as utilities from "./utilities";
import { TextDocument, workspace, WorkspaceConfiguration } from "vscode";

function getDotPath(configuration: WorkspaceConfiguration): string {
return configuration.get("graphvizPreview.dotPath", "dot");
Expand All @@ -20,7 +21,7 @@ function getEngine(configuration: WorkspaceConfiguration): Engine {
}

export class Configuration {
public constructor(
private constructor(
public readonly dotPath: string,
public readonly dotExtraArgs: string[],
public readonly engine: Engine,
Expand All @@ -33,4 +34,20 @@ export class Configuration {

return new Configuration(dotPath, dotExtraArgs, engine);
}

// TODO: Use a new type for resolved configuration?
public resolve(document: TextDocument): Configuration {
const resolve = (s: string) =>
utilities.resolveVariables(s, (key) => {
switch (key) {
case "workspaceFolder": {
return workspace.getWorkspaceFolder(document.uri)?.uri?.fsPath;
}
}

return undefined;
});

return new Configuration(resolve(this.dotPath), this.dotExtraArgs.map(resolve), this.engine);
}
}
2 changes: 1 addition & 1 deletion projects/extension/src/preview-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ export class PreviewState implements ChannelClient<ExtensionRequest, ExtensionRe
return `Error: ${reason}`;
}

const configuration = this.context.configuration;
const document = this.document;
const configuration = this.context.configuration.resolve(document);

// Lock task parameters.

Expand Down
10 changes: 10 additions & 0 deletions projects/extension/src/utilities.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const placeholderRegex = /\$\{([^{}]+)\}/g;

export function createPromise<T>(): [Promise<T>, (value: T) => void, (reason: unknown) => void] {
let resolve: (value: T) => void;
let reject: (reason: unknown) => void;
Expand All @@ -10,3 +12,11 @@ export function createPromise<T>(): [Promise<T>, (value: T) => void, (reason: un
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return [promise, resolve!, reject!];
}

export function resolveVariables(s: string, resolve: (key: string) => string | undefined): string {
return s.replace(placeholderRegex, (fallback, key) => {
const candidate = resolve(key);

return candidate === undefined ? fallback : candidate;
});
}
48 changes: 48 additions & 0 deletions projects/extension/tests/utilities-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import * as utilities from "../src/utilities";
import * as assert from "assert";

describe("Variable resolver tests", () => {
it("No replacement if no placeholder", () => {
assert.strictEqual(
utilities.resolveVariables("abc", () => "xyz"),
"abc",
);
});

it("No replacement if no key", () => {
assert.strictEqual(
utilities.resolveVariables("ab${a}", () => undefined),
"ab${a}",
);
});

it("Replace if found key", () => {
assert.strictEqual(
utilities.resolveVariables("a ${aa} bc ${bb} def ${cc} g", (key) => (key === "aa" ? "foo" : "bar")),
"a foo bc bar def bar g",
);
});

it("Replace with empty string", () => {
assert.strictEqual(
utilities.resolveVariables("a ${aa} bc ${bb} def ${cc} g", () => ""),
"a bc def g",
);
});

it("Replace mixed", () => {
assert.strictEqual(
utilities.resolveVariables("a ${foo} bc ${bar} def ${baz} g", (key) => {
switch (key) {
case "foo":
return "xyz";
case "baz":
return "uvw";
}

return undefined;
}),
"a xyz bc ${bar} def uvw g",
);
});
});

0 comments on commit 839acfa

Please sign in to comment.