From 2608eed73a6382e573674c5b0932f28936e042af Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Fri, 26 Apr 2024 13:05:35 -0400 Subject: [PATCH] Improve support for Shiny for R apps that use `ui.R` and friends (#39) --- src/extension.ts | 9 +++++++++ src/run.ts | 32 +++++++++++++++++++------------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 585fd89..32938bd 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -147,5 +147,14 @@ function isShinyAppUsername(filename: string, language: string): boolean { return true; } + if (language === "r") { + return isShinyAppRPart(filename); + } + return false; } + +export function isShinyAppRPart(filename: string): boolean { + filename = path.basename(filename); + return ["ui.r", "server.r", "global.r"].includes(filename.toLowerCase()); +} diff --git a/src/run.ts b/src/run.ts index 347b307..575f9b3 100644 --- a/src/run.ts +++ b/src/run.ts @@ -1,7 +1,8 @@ import { PythonExtension } from "@vscode/python-extension"; import * as vscode from "vscode"; -import { join as path_join } from "path"; +import { join as path_join, dirname as path_dirname } from "path"; import * as fs from "fs"; +import { isShinyAppRPart } from "./extension"; import { openBrowser, openBrowserWhenReady } from "./net-utils"; import { envVarsForShell as envVarsForTerminal, @@ -130,11 +131,13 @@ export async function pyDebugApp(): Promise { /* Shiny for R --------------------------------------------------------- */ export async function rRunApp(): Promise { - const path = getActiveEditorFile(); - if (!path) { + const pathFile = getActiveEditorFile(); + if (!pathFile) { return; } + const path = isShinyAppRPart(pathFile) ? path_dirname(pathFile) : pathFile; + const port = await getAppPort("run", "r"); // TODO: Is this needed for Shiny for R too? // const autoreloadPort = await getAutoreloadPort("run"); @@ -164,8 +167,8 @@ export async function rRunApp(): Promise { if (!rscriptBinPath) { vscode.window.showErrorMessage( "Could not find R. Is R installed on your system?" + - "If R is installed, please make sure your PATH " + - "environment variable is configured correctly." + "If R is installed, please make sure your PATH " + + "environment variable is configured correctly." ); return; } @@ -279,7 +282,7 @@ async function checkForPythonExtension(): Promise { const response = await vscode.window.showErrorMessage( "The Python extension is required to run Shiny apps. " + - "Please install it and try again.", + "Please install it and try again.", "Show Python extension", "Not now" ); @@ -311,7 +314,7 @@ async function getSelectedPythonInterpreter(): Promise { if (!resolvedEnv) { vscode.window.showErrorMessage( "Unable to find Python interpreter. " + - 'Please use the "Python: Select Interpreter" command, and try again.' + 'Please use the "Python: Select Interpreter" command, and try again.' ); return false; } @@ -341,7 +344,7 @@ function getExtensionPath(): string | undefined { } async function getRBinPath(bin: string): Promise { - return getRPathFromEnv(bin) || await getRPathFromWindowsReg(bin) || ""; + return getRPathFromEnv(bin) || (await getRPathFromWindowsReg(bin)) || ""; } function getRPathFromEnv(bin: string = "R"): string { @@ -373,15 +376,18 @@ async function getRPathFromWindowsReg(bin: string = "R"): Promise { try { const key = new winreg({ hive: winreg.HKLM, - key: '\\Software\\R-Core\\R', + key: "\\Software\\R-Core\\R", }); const item: winreg.RegistryItem = await new Promise((c, e) => - key.get('InstallPath', (err, result) => err === null ? c(result) : e(err))); - rPath = path_join(item.value, 'bin', bin + ".exe"); + key.get("InstallPath", (err, result) => + err === null ? c(result) : e(err) + ) + ); + rPath = path_join(item.value, "bin", bin + ".exe"); rPath = fs.existsSync(rPath) ? rPath : ""; } catch (e) { - rPath = ''; + rPath = ""; } return rPath; -} \ No newline at end of file +}