Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP R Executable Selection #1473

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
"typescript.tsdk": "./node_modules/typescript/lib", // we want to use the TS server from our node_modules folder to control its version
"r.lsp.diagnostics": true,
"editor.codeActionsOnSave": {
"source.fixAll.markdownlint": true
"source.fixAll.markdownlint": "explicit"
}
}
27 changes: 19 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,11 @@
}
],
"commands": [
{
"category": "R",
"command": "r.setExecutable",
"title": "Select executable"
},
{
"command": "r.workspaceViewer.refreshEntry",
"title": "Manual Refresh",
Expand Down Expand Up @@ -1428,32 +1433,38 @@
"r.rpath.windows": {
"type": "string",
"default": "",
"markdownDescription": "Path to an R executable to launch R background processes (Windows). Must be \"vanilla\" R, not radian etc.! Some variables defined in <https://code.visualstudio.com/docs/editor/variables-reference> such as `${userHome}`, `${workspaceFolder}`, `${fileWorkspaceFolder}`, and `${fileDirname}` are supported."
"markdownDescription": "Path to an R executable to launch R background processes (Windows). Must be \"vanilla\" R, not radian etc.! Some variables defined in <https://code.visualstudio.com/docs/editor/variables-reference> such as `${userHome}`, `${workspaceFolder}`, `${fileWorkspaceFolder}`, and `${fileDirname}` are supported.",
"scope": "machine-overridable"
},
"r.rpath.mac": {
"type": "string",
"default": "",
"markdownDescription": "Path to an R executable to launch R background processes (macOS). Must be \"vanilla\" R, not radian etc.! Some variables defined in <https://code.visualstudio.com/docs/editor/variables-reference> such as `${userHome}`, `${workspaceFolder}`, `${fileWorkspaceFolder}`, and `${fileDirname}` are supported."
"markdownDescription": "Path to an R executable to launch R background processes (macOS). Must be \"vanilla\" R, not radian etc.! Some variables defined in <https://code.visualstudio.com/docs/editor/variables-reference> such as `${userHome}`, `${workspaceFolder}`, `${fileWorkspaceFolder}`, and `${fileDirname}` are supported.",
"scope": "machine-overridable"
},
"r.rpath.linux": {
"type": "string",
"default": "",
"markdownDescription": "Path to an R executable to launch R background processes (Linux). Must be \"vanilla\" R, not radian etc.! Some variables defined in <https://code.visualstudio.com/docs/editor/variables-reference> such as `${userHome}`, `${workspaceFolder}`, `${fileWorkspaceFolder}`, and `${fileDirname}` are supported."
"markdownDescription": "Path to an R executable to launch R background processes (Linux). Must be \"vanilla\" R, not radian etc.! Some variables defined in <https://code.visualstudio.com/docs/editor/variables-reference> such as `${userHome}`, `${workspaceFolder}`, `${fileWorkspaceFolder}`, and `${fileDirname}` are supported.",
"scope": "machine-overridable"
},
"r.rterm.windows": {
"type": "string",
"default": "",
"markdownDescription": "R path for interactive terminals (Windows). Can also be radian etc. Some variables defined in <https://code.visualstudio.com/docs/editor/variables-reference> such as `${userHome}`, `${workspaceFolder}`, `${fileWorkspaceFolder}`, and `${fileDirname}` are supported."
"markdownDescription": "R path for interactive terminals (Windows). Can also be radian etc. Some variables defined in <https://code.visualstudio.com/docs/editor/variables-reference> such as `${userHome}`, `${workspaceFolder}`, `${fileWorkspaceFolder}`, and `${fileDirname}` are supported.",
"scope": "machine-overridable"
},
"r.rterm.mac": {
"type": "string",
"default": "",
"markdownDescription": "R path for interactive terminals (macOS). Can also be radian etc. Some variables defined in <https://code.visualstudio.com/docs/editor/variables-reference> such as `${userHome}`, `${workspaceFolder}`, `${fileWorkspaceFolder}`, and `${fileDirname}` are supported."
"markdownDescription": "R path for interactive terminals (macOS). Can also be radian etc. Some variables defined in <https://code.visualstudio.com/docs/editor/variables-reference> such as `${userHome}`, `${workspaceFolder}`, `${fileWorkspaceFolder}`, and `${fileDirname}` are supported.",
"scope": "machine-overridable"
},
"r.rterm.linux": {
"type": "string",
"default": "",
"markdownDescription": "R path for interactive terminals (Linux). Can also be radian etc. Some variables defined in <https://code.visualstudio.com/docs/editor/variables-reference> such as `${userHome}`, `${workspaceFolder}`, `${fileWorkspaceFolder}`, and `${fileDirname}` are supported."
"markdownDescription": "R path for interactive terminals (Linux). Can also be radian etc. Some variables defined in <https://code.visualstudio.com/docs/editor/variables-reference> such as `${userHome}`, `${workspaceFolder}`, `${fileWorkspaceFolder}`, and `${fileDirname}` are supported.",
"scope": "machine-overridable"
},
"r.rterm.option": {
"type": "array",
Expand All @@ -1474,7 +1485,7 @@
"default": [],
"markdownDescription": "Additional library paths to launch R background processes (R languageserver, help server, etc.). These paths will be appended to `.libPaths()` on process startup. It could be useful for projects with [renv](https://rstudio.github.io/renv/index.html) enabled."
},
"r.useRenvLibPath" : {
"r.useRenvLibPath": {
"type": "boolean",
"default": false,
"markdownDescription": "Use renv library paths to launch R background processes (R languageserver, help server, etc.)."
Expand Down Expand Up @@ -2173,4 +2184,4 @@
"vsls": "^1.0.4753",
"winreg": "^1.2.4"
}
}
}
2 changes: 1 addition & 1 deletion src/cppProperties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function platformChoose<A, B, C>(win32: A, darwin: B, other: C): A | B | C {

// See: https://code.visualstudio.com/docs/cpp/c-cpp-properties-schema-reference
async function generateCppPropertiesProc(workspaceFolder: string) {
const rPath = await getRpath();
const rPath = getRpath();
if (!rPath) {
return;
}
Expand Down
5 changes: 5 additions & 0 deletions src/executables/TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# PR TODO

- cleanup todos
- services when changing rpath
- very buggy right now
84 changes: 84 additions & 0 deletions src/executables/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
'use strict';

import * as vscode from 'vscode';

import { ExecutableStatusItem, ExecutableQuickPick } from './ui';
import { RExecutableService, RExecutableType, WorkspaceExecutableEvent } from './service';
import { extensionContext } from '../extension';

export * from './virtual';
export * from './util';
export { RExecutableType, VirtualRExecutableType } from './service';

// super class that manages relevant sub classes
export class RExecutableManager {
private readonly executableService: RExecutableService;
private statusBar: ExecutableStatusItem;
private quickPick: ExecutableQuickPick;

private constructor(service: RExecutableService) {
this.executableService = service;
this.statusBar = new ExecutableStatusItem(this.executableService);
this.quickPick = new ExecutableQuickPick(this.executableService);
extensionContext.subscriptions.push(
this.onDidChangeActiveExecutable(() => this.reload()),
vscode.window.onDidChangeActiveTextEditor((e: vscode.TextEditor | undefined) => {
if (e?.document) {this.reload();}
}),
this.executableService,
this.statusBar
);
this.reload();
}

static async initialize(): Promise<RExecutableManager> {
const executableService = await RExecutableService.initialize();
return new this(executableService);
}

public get executableQuickPick(): ExecutableQuickPick {
return this.quickPick;
}

public get languageStatusItem(): ExecutableStatusItem {
return this.statusBar;
}

public get activeExecutablePath(): string | undefined {
return this.executableService.activeExecutable?.rBin;
}

/**
* Get the associated R executable for a given working directory path
* @param workingDir
* @returns
*/
public getExecutablePath(workingDir: string): string | undefined {
return this.executableService.getWorkspaceExecutable(workingDir)?.rBin;
}

public getExecutableFromPath(rpath: string): RExecutableType | undefined {
return this.executableService.executableFactory.create(rpath);
}

public get activeExecutable(): RExecutableType | undefined {
return this.executableService.activeExecutable;
}

public get onDidChangeActiveExecutable(): vscode.Event<RExecutableType | undefined> {
return this.executableService.onDidChangeActiveExecutable;
}

public get onDidChangeWorkspaceExecutable(): vscode.Event<WorkspaceExecutableEvent> {
return this.executableService.onDidChangeWorkspaceExecutable;
}

/**
* @description
* Orders a refresh of the executable manager, causing a refresh of the language status bar item
* @memberof RExecutableManager
*/
public reload(): void {
this.statusBar.refresh();
}
}
105 changes: 105 additions & 0 deletions src/executables/service/class.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
'use strict';

import { getRDetailsFromPath } from '../util';
import { RExecutableRegistry } from './registry';
import { RExecutableType } from './types';
import { isCondaInstallation, isMambaInstallation, condaName, getRDetailsFromCondaMetaHistory } from '../virtual';

/**
* Creates and caches instances of RExecutableType
* based on the provided executable path.
*/
export class RExecutableFactory {
private readonly registry: RExecutableRegistry;

constructor (registry: RExecutableRegistry) {
this.registry = registry;
}

public create(executablePath: string): RExecutableType {
const cachedExec = [...this.registry.executables.values()].find((v) => v.rBin === executablePath);
if (cachedExec) {
return cachedExec;
} else {
let executable: AbstractRExecutable;
if (isCondaInstallation(executablePath)) {
executable = new CondaVirtualRExecutable(executablePath);
} else if (isMambaInstallation(executablePath)) {
executable = new MambaVirtualRExecutable(executablePath);
} else {
executable = new RExecutable(executablePath);
}
this.registry.addExecutable(executable);
return executable;
}
}
}

export abstract class AbstractRExecutable {
protected _rBin!: string;
protected _rVersion!: string;
protected _rArch!: string;
public get rBin(): string {
return this._rBin;
}

public get rVersion(): string {
return this._rVersion;
}

public get rArch(): string {
return this._rArch;
}
public abstract tooltip: string;
}


export class RExecutable extends AbstractRExecutable {
constructor (executablePath: string) {
super();
const details = getRDetailsFromPath(executablePath);
this._rBin = executablePath;
this._rVersion = details.version;
this._rArch = details.arch;
}

public get tooltip(): string {
if (this.rVersion && this.rArch) {
return `R ${this.rVersion} ${this.rArch}`;
}
return `$(error) R`;
}
}

export abstract class AbstractVirtualRExecutable extends AbstractRExecutable {
protected _name!: string;
public get name(): string {
return this._name;
}
public get tooltip(): string {
if (this.rVersion && this.rArch) {
return `R ${this.rVersion} ${this.rArch} ('${this.name}')`;
}
return `$(error) '${this.name}'`;
}
}

export class CondaVirtualRExecutable extends AbstractVirtualRExecutable {
constructor (executablePath: string) {
super();
this._name = condaName(executablePath);
const details = getRDetailsFromCondaMetaHistory(executablePath);
this._rVersion = details?.version ?? '';
this._rArch = details?.arch ?? '';
this._rBin = executablePath;
}
}

// TODO

export class MambaVirtualRExecutable extends AbstractVirtualRExecutable {
constructor (executablePath: string) {

Check warning on line 101 in src/executables/service/class.ts

View workflow job for this annotation

GitHub Actions / eslint

'executablePath' is defined but never used
super();
}
}

Loading
Loading