Skip to content

Commit

Permalink
Enhance version manager config to accept more fields
Browse files Browse the repository at this point in the history
  • Loading branch information
vinistock committed Apr 5, 2024
1 parent c8a18d8 commit 7be1827
Show file tree
Hide file tree
Showing 13 changed files with 112 additions and 53 deletions.
7 changes: 6 additions & 1 deletion vscode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,12 @@ by clicking `Change version manager` in the language status center or by changin
// "rbenv"
// "rvm"
// "shadowenv"
"rubyLsp.rubyVersionManager": "chruby"
// "mise"
{
"rubyLsp.rubyVersionManager": {
"identifier": "chruby",
},
}
```

To make sure that the Ruby LSP can find the version manager scripts, make sure that they are loaded in the shell's
Expand Down
20 changes: 5 additions & 15 deletions vscode/VERSION_MANAGERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ If you're using a different version manager that's not supported by this extensi
executable into the PATH, you will probably need to define custom activation so that the extension can find the correct
Ruby.

For these cases, set `rubyLsp.rubyVersionManager` to `"custom"` and then set `rubyLsp.customRubyCommand` to a shell
command that will activate the right Ruby version or add the Ruby `bin` folder to the `PATH`. Some examples:
For these cases, set `rubyLsp.rubyVersionManager.identifier` to `"custom"` and then set `rubyLsp.customRubyCommand` to a
shell command that will activate the right Ruby version or add the Ruby `bin` folder to the `PATH`. Some examples:

```jsonc
{
// Don't forget to set the manager to custom when using this option
"rubyLsp.rubyVersionManager": "custom",
"rubyLsp.rubyVersionManager": {
"identifier": "custom",
},

// Using a different version manager than the ones included by default
"rubyLsp.customRubyCommand": "my_custom_version_manager activate",
Expand All @@ -25,15 +27,3 @@ command that will activate the right Ruby version or add the Ruby `bin` folder t
"rubyLsp.customRubyCommand": "PATH=/path/to/ruby/bin:$PATH",
}
```

### mise (formerly rtx)

[mise](https://github.com/jdx/mise) is a Rust clone compatible with asdf. You can use it by adding the following
snippet to your user configuration JSON

```json
{
"rubyLsp.rubyVersionManager": "custom",
"rubyLsp.customRubyCommand": "eval \"$(mise env -s zsh)\"" // Instructions for zsh, change for bash or fish
}
```
36 changes: 22 additions & 14 deletions vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -232,20 +232,28 @@
}
},
"rubyLsp.rubyVersionManager": {
"description": "The Ruby version manager to use",
"type": "string",
"enum": [
"asdf",
"auto",
"chruby",
"none",
"rbenv",
"rvm",
"shadowenv",
"mise",
"custom"
],
"default": "auto"
"type": "object",
"properties": {
"identifier": {
"description": "The Ruby version manager to use",
"type": "string",
"enum": [
"asdf",
"auto",
"chruby",
"none",
"rbenv",
"rvm",
"shadowenv",
"mise",
"custom"
],
"default": "auto"
}
},
"default": {
"identifier": "auto"
}
},
"rubyLsp.customRubyCommand": {
"description": "A shell command to activate the right Ruby version or add a custom Ruby bin folder to the PATH. Only used if rubyVersionManager is set to 'custom'",
Expand Down
2 changes: 1 addition & 1 deletion vscode/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export enum Command {

export interface RubyInterface {
error: boolean;
versionManager?: string;
versionManager: { identifier: string };
rubyVersion?: string;
}

Expand Down
34 changes: 34 additions & 0 deletions vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,42 @@ export async function activate(context: vscode.ExtensionContext) {

extension = new RubyLsp(context);
await extension.activate();

await migrateManagerConfigurations();
}

export async function deactivate(): Promise<void> {
await extension.deactivate();
}

type InspectKeys =
| "globalValue"
| "workspaceValue"
| "workspaceFolderValue"
| "globalLanguageValue"
| "workspaceLanguageValue"
| "workspaceFolderLanguageValue";
// Function to migrate the old version manager configuration to the new format. Remove this after a few months
async function migrateManagerConfigurations() {
const configuration = vscode.workspace.getConfiguration("rubyLsp");
const currentManagerSettings =
configuration.inspect<string>("rubyVersionManager")!;
let identifier: string | undefined;

const targetMap: Record<InspectKeys, vscode.ConfigurationTarget> = {
globalValue: vscode.ConfigurationTarget.Global,
globalLanguageValue: vscode.ConfigurationTarget.Global,
workspaceFolderLanguageValue: vscode.ConfigurationTarget.WorkspaceFolder,
workspaceFolderValue: vscode.ConfigurationTarget.WorkspaceFolder,
workspaceLanguageValue: vscode.ConfigurationTarget.Workspace,
workspaceValue: vscode.ConfigurationTarget.Workspace,
};

for (const [key, target] of Object.entries(targetMap)) {
identifier = currentManagerSettings[key as InspectKeys];

if (identifier && typeof identifier === "string") {
await configuration.update("rubyVersionManager", { identifier }, target);
}
}
}
30 changes: 21 additions & 9 deletions vscode/src/ruby.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,19 @@ export enum ManagerIdentifier {
Custom = "custom",
}

export interface ManagerConfiguration {
identifier: ManagerIdentifier;
}

export class Ruby implements RubyInterface {
public rubyVersion?: string;
// This property indicates that Ruby has been compiled with YJIT support and that we're running on a Ruby version
// where it will be activated, either by the extension or by the server
public yjitEnabled?: boolean;
private readonly workspaceFolder: vscode.WorkspaceFolder;
#versionManager?: ManagerIdentifier;
#versionManager: ManagerConfiguration = vscode.workspace
.getConfiguration("rubyLsp")
.get<ManagerConfiguration>("rubyVersionManager")!;

private readonly shell = process.env.SHELL?.replace(/(\s+)/g, "\\$1");
private _env: NodeJS.ProcessEnv = {};
Expand Down Expand Up @@ -71,12 +77,18 @@ export class Ruby implements RubyInterface {
: this.workspaceFolder.uri.fsPath;
}

get versionManager() {
get versionManager(): ManagerConfiguration {
return this.#versionManager;
}

private set versionManager(versionManager: ManagerIdentifier | undefined) {
this.#versionManager = versionManager;
private set versionManager(
versionManager: ManagerConfiguration | ManagerIdentifier,
) {
if (typeof versionManager === "string") {
this.#versionManager.identifier = versionManager;
} else {
this.#versionManager = versionManager;
}
}

get env() {
Expand All @@ -88,22 +100,22 @@ export class Ruby implements RubyInterface {
}

async activateRuby(
versionManager: ManagerIdentifier = vscode.workspace
versionManager: ManagerConfiguration = vscode.workspace
.getConfiguration("rubyLsp")
.get("rubyVersionManager")!,
.get<ManagerConfiguration>("rubyVersionManager")!,
) {
this.versionManager = versionManager;

// If the version manager is auto, discover the actual manager before trying to activate anything
if (this.versionManager === ManagerIdentifier.Auto) {
if (this.versionManager.identifier === ManagerIdentifier.Auto) {
await this.discoverVersionManager();
this.outputChannel.info(
`Discovered version manager ${this.versionManager}`,
);
}

try {
switch (this.versionManager) {
switch (this.versionManager.identifier) {
case ManagerIdentifier.Asdf:
await this.activate("asdf exec ruby");
break;
Expand Down Expand Up @@ -281,7 +293,7 @@ export class Ruby implements RubyInterface {
await vscode.workspace.fs.stat(
vscode.Uri.joinPath(this.workspaceFolder.uri, ".shadowenv.d"),
);
this.versionManager = ManagerIdentifier.Shadowenv;
this.versionManager.identifier = ManagerIdentifier.Shadowenv;
return;
} catch (error: any) {
// If .shadowenv.d doesn't exist, then we check the other version managers
Expand Down
14 changes: 8 additions & 6 deletions vscode/src/rubyLsp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Telemetry } from "./telemetry";
import DocumentProvider from "./documentProvider";
import { Workspace } from "./workspace";
import { Command, STATUS_EMITTER } from "./common";
import { ManagerIdentifier } from "./ruby";
import { ManagerIdentifier, ManagerConfiguration } from "./ruby";
import { StatusItems } from "./status";
import { TestController } from "./testController";
import { Debugger } from "./debugger";
Expand Down Expand Up @@ -286,16 +286,18 @@ export class RubyLsp {
Command.SelectVersionManager,
async () => {
const configuration = vscode.workspace.getConfiguration("rubyLsp");
const managerConfig =
configuration.get<ManagerConfiguration>("rubyVersionManager")!;
const options = Object.values(ManagerIdentifier);
const manager = await vscode.window.showQuickPick(options, {
placeHolder: `Current: ${configuration.get("rubyVersionManager")}`,
});
const manager = (await vscode.window.showQuickPick(options, {
placeHolder: `Current: ${managerConfig.identifier}`,
})) as ManagerIdentifier | undefined;

if (manager !== undefined) {
managerConfig.identifier = manager;
await configuration.update(
"rubyVersionManager",
manager,
true,
managerConfig,
true,
);
}
Expand Down
2 changes: 1 addition & 1 deletion vscode/src/status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export class RubyVersionStatus extends StatusItem {
this.item.text = "Failed to activate Ruby";
this.item.severity = vscode.LanguageStatusSeverity.Error;
} else {
this.item.text = `Using Ruby ${workspace.ruby.rubyVersion} with ${workspace.ruby.versionManager}`;
this.item.text = `Using Ruby ${workspace.ruby.rubyVersion} with ${workspace.ruby.versionManager.identifier}`;
this.item.severity = vscode.LanguageStatusSeverity.Information;
}
}
Expand Down
2 changes: 1 addition & 1 deletion vscode/src/telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export class Telemetry {
const promises: Promise<void>[] = [
{ namespace: "workbench", field: "colorTheme" },
{ namespace: "rubyLsp", field: "enableExperimentalFeatures" },
{ namespace: "rubyLsp", field: "rubyVersionManager" },
{ namespace: "rubyLsp", field: "rubyVersionManager.identifier" },
{ namespace: "rubyLsp", field: "formatter" },
].map(({ namespace, field }) => {
return this.sendEvent({
Expand Down
7 changes: 6 additions & 1 deletion vscode/src/test/suite/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,12 @@ suite("Client", () => {
if (process.env.CI) {
await vscode.workspace
.getConfiguration("rubyLsp")
.update("rubyVersionManager", ManagerIdentifier.None, true, true);
.update(
"rubyVersionManager",
{ identifier: ManagerIdentifier.None },
true,
true,
);
}
client = await launchClient(workspaceUri);
});
Expand Down
2 changes: 1 addition & 1 deletion vscode/src/test/suite/debugger.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ suite("Debugger", () => {
.returns({
get: (name: string) => {
if (name === "rubyVersionManager") {
return manager;
return { identifier: manager };
} else if (name === "bundleGemfile") {
return "";
} else if (name === "saveBeforeStart") {
Expand Down
4 changes: 2 additions & 2 deletions vscode/src/test/suite/ruby.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ suite("Ruby environment activation", () => {
.returns({
get: (name: string) => {
if (name === "rubyVersionManager") {
return manager;
return { identifier: manager };
} else if (name === "bundleGemfile") {
return "";
}
Expand Down Expand Up @@ -66,7 +66,7 @@ suite("Ruby environment activation", () => {
.returns({
get: (name: string) => {
if (name === "rubyVersionManager") {
return manager;
return { identifier: manager };
} else if (name === "bundleGemfile") {
return "";
}
Expand Down
5 changes: 4 additions & 1 deletion vscode/src/test/suite/status.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ suite("StatusItems", () => {

suite("RubyVersionStatus", () => {
beforeEach(() => {
ruby = { rubyVersion: "3.2.0", versionManager: "shadowenv" } as Ruby;
ruby = {
rubyVersion: "3.2.0",
versionManager: { identifier: "shadowenv" },
} as Ruby;
workspace = {
ruby,
lspClient: {
Expand Down

0 comments on commit 7be1827

Please sign in to comment.