From 3a1864df59f0b4850789a80ac538698dd18a8d0a Mon Sep 17 00:00:00 2001 From: Virgil <28490646+sisoe24@users.noreply.github.com> Date: Thu, 10 Oct 2024 11:41:26 -0400 Subject: [PATCH] sisoe24/0.16.0 (#23) * Refactor placeholder replacements in launch_executable.ts * Remove duplicate import * Improve environment variables options #22 * Refactor resolveEnvVariables function and optimize environment variable replacement * Remove commented lines * Update readme * Update changelog * Rename file * Update readme * Update notification message for breaking changes in settings * Use property shorthand * Fix commands camelCaseName #21 * Update run_code.svg icon * Update changelog --- CHANGELOG.md | 13 ++ README.md | 39 ++++-- package.json | 14 ++- resources/icons/light/run_code.svg | 7 +- src/config.ts | 2 +- src/extension.ts | 119 +++++++++++-------- src/launch_executable.ts | 83 ++++++------- src/notification.ts | 4 +- src/{fetch_packages.ts => packages_fetch.ts} | 0 9 files changed, 167 insertions(+), 114 deletions(-) rename src/{fetch_packages.ts => packages_fetch.ts} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9718706..4bf8e2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Change Log +## [0.16.0] - 07/07/2024 + +### Changed + +- Changed the `nuketools.environmentVariables` keys to use an array of strings rather than a single string (`{"VAR_NAME": ["value1", "value2", ...]}`) +- Added new placeholders for the `nuketools.environmentVariables` setting: `${workspaceFolderBasename}` and `${userHome}`. +- Added the ability to use any system environment variable in the `nuketools.environmentVariables` setting. + +### Fixed + +- Fixed light theme icon +- Extensions commands for extra and packages now properly show a label rather than a variable name. + ## [0.15.1] - 07/07/2024 ### Fixed diff --git a/README.md b/README.md index 8a4414c..1dde9ee 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ Seamlessly integrate Nuke into your Visual Studio Code workflow, enabling you to - [1.7. BlinkScript](#17-blinkscript) - [1.8. Available Commands](#18-available-commands) - [1.9. Environment Variables](#19-environment-variables) + - [Placeholders and Variables](#placeholders-and-variables) - [1.9.1. Additional Settings](#191-additional-settings) - [1.9.2. Network Settings](#192-network-settings) - [1.10. Windows Users](#110-windows-users) @@ -163,19 +164,43 @@ NOTES: ## 1.9. Environment Variables -Add environment variables to the terminal instance with `$VAR_NAME` for system variables or `${workspaceFolder}` for the workspace folder. +Add environment variables to the terminal instance using the `nukeTools.environmentVariables` setting. ```json { - "nukeTools.environmentVariables": { - "NUKE_PATH": "${workspaceFolder}/gizmo:$NUKE_PATH", - "PYTHONPATH": "$PYTHONPATH:/path/to/python/lib", - "API_KEY": "0a9f0381-aebb-4e40-a77a-2c381b08e0ea" - } + "nukeTools.environmentVariables": { + "VAR_NAME": ["value1", "value2", ...] + } +} +``` + +### Placeholders and Variables + +- `${workspaceFolder}`: Current workspace folder +- `${workspaceFolderBasename}`: Name of the workspace folder +- `${userHome}`: User's home directory +- `$VAR_NAME`: System environment variables + +Example + +```json +{ + "nukeTools.environmentVariables": { + "NUKE_PATH": [ + "${workspaceFolder}/gizmo", + "$NUKE_PATH" + ], + "PYTHONPATH": [ + "$MYLIB/path/to/python/lib" + ], + "API_KEY": [ + "0a9f0381-aebb-4e40-a77a-2c381b08e0ea" + ] + } } ``` -> Note: From my testing it seems that you can use the ':' separator for multiple paths even on Windows. +The extension combines arrays of strings using the appropriate separator for the detected shell and operating system. ## 1.9.1. Additional Settings diff --git a/package.json b/package.json index 205a8fb..0a46b22 100644 --- a/package.json +++ b/package.json @@ -143,11 +143,21 @@ "type": "boolean" }, "nukeTools.environmentVariables": { - "description": "Environment variables that will be added when running an executable.", + "description": "An object with environment variables that will be added when running an executable.", "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + }, "examples": [ { - "NUKE_PATH": "${workspaceFolder}/gizmos:$NUKE_PATH" + "NUKE_PATH": [ + "${workspaceFolder}/${workspaceFolderBasename}/bin", + "${userHome}/.nuke", + "$NUKE_PATH" + ] } ] }, diff --git a/resources/icons/light/run_code.svg b/resources/icons/light/run_code.svg index 7bd76ec..ba7ebb9 100644 --- a/resources/icons/light/run_code.svg +++ b/resources/icons/light/run_code.svg @@ -2,10 +2,9 @@ - + - - - + + Nuke diff --git a/src/config.ts b/src/config.ts index 1ba2fe4..40f89f7 100644 --- a/src/config.ts +++ b/src/config.ts @@ -9,7 +9,7 @@ type ExecutableMap = { [key: string]: ExecutableConfig; }; -export type EnvVars = { [key: string]: string }; +export type EnvVars = { [key: string]: Array }; type CommandMappings = "executablesMap"; diff --git a/src/extension.ts b/src/extension.ts index cda24f6..ab29cc1 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -10,8 +10,6 @@ import { Version } from "./version"; import * as executables from "./launch_executable"; import * as nukeTemplate from "./create_project"; -import { Version } from "./version"; - import { BlinkSnippets } from "./blinkscript/blink_snippet"; import { BlinkScriptFormat } from "./blinkscript/blink_format"; import { BlinkScriptCompletionProvider } from "./blinkscript/blink_completion"; @@ -20,7 +18,7 @@ import { NukeCompletionProvider } from "./nuke/completitions"; import { NukeNodesInspectorProvider } from "./nuke/nodes_tree"; import { showNotification } from "./notification"; -import { fetchPackagesLatestVersion } from "./fetch_packages"; +import { fetchPackagesLatestVersion } from "./packages_fetch"; import { initializePackageLog } from "./packages"; import { getConfig } from "./config"; @@ -74,69 +72,88 @@ function registerBlinkScriptCommands(context: vscode.ExtensionContext): void { ); } +type Action = { + label: string; + execute: () => void; +}; + +interface ActionItem extends vscode.QuickPickItem { + execute: () => void; +} + +function showActionPicker(items: Array) { + const picker = vscode.window.createQuickPick(); + picker.items = items.map((item) => { + return { + label: item.label, + execute: item.execute, + }; + }); + + picker.onDidChangeSelection((selection) => { + const selected = selection[0] as ActionItem; + if (selected) { + selected.execute(); + picker.hide(); + } + }); + + picker.onDidHide(() => picker.dispose()); + picker.show(); +} + function registerPackagesCommands(context: vscode.ExtensionContext): void { - const addExtras: Record void> = { - pysideTemplate: nukeTemplate.createTemplate, - pythonStubs: stubs.addStubs, - nukeServerSocket: nuke.addNukeServerSocket, - vimDcc: nuke.addVimDcc, - }; + const actions: Array = [ + { + label: "Pyside Template", + execute: nukeTemplate.createTemplate, + }, + { + label: "Python Stubs", + execute: stubs.addStubs, + }, + { + label: "Nuke Server Socket", + execute: nuke.addNukeServerSocket, + }, + { + label: "Vim DCC", + execute: nuke.addVimDcc, + }, + ]; context.subscriptions.push( vscode.commands.registerCommand("nuke-tools.addPackages", () => { - const picker = vscode.window.createQuickPick(); - picker.items = Object.keys(addExtras).map((key) => { - return { - label: key, - }; - }); - - picker.onDidChangeSelection((selection) => { - if (selection[0]) { - addExtras[selection[0].label](); - picker.hide(); - } - }); - - picker.onDidHide(() => picker.dispose()); - picker.show(); + showActionPicker(actions); }) ); } function registerExtraCommands(context: vscode.ExtensionContext): void { - const extras: Record void> = { - clearPackagesCache: () => { - initializePackageLog(); - fetchPackagesLatestVersion(); - vscode.window.showInformationMessage("Packages cached cleared."); + const actions: Array = [ + { + label: "Clear Package Cache", + execute: () => { + initializePackageLog(); + fetchPackagesLatestVersion(); + vscode.window.showInformationMessage("Packages cached cleared."); + }, }, - testRunInsideNuke: () => { - void socket.sendDebugMessage(); + { + label: "Send Debug Message", + execute: socket.sendDebugMessage, }, - showNetworkAddresses: () => { - vscode.window.showInformationMessage(socket.getAddresses()); + { + label: "Show Network Addresses", + execute: () => { + vscode.window.showInformationMessage(socket.getAddresses()); + }, }, - }; + ]; context.subscriptions.push( vscode.commands.registerCommand("nuke-tools.extras", () => { - const picker = vscode.window.createQuickPick(); - picker.items = Object.keys(extras).map((key) => { - return { - label: key, - }; - }); - - picker.onDidChangeSelection((selection) => { - if (selection[0]) { - extras[selection[0].label](); - picker.hide(); - } - }); - - picker.onDidHide(() => picker.dispose()); - picker.show(); + showActionPicker(actions); }) ); } diff --git a/src/launch_executable.ts b/src/launch_executable.ts index c8f8b04..4a8b033 100644 --- a/src/launch_executable.ts +++ b/src/launch_executable.ts @@ -70,23 +70,42 @@ export class ExecutablePath { } /** - * Concatenate the user's environment variables with the system's environment variables. + * Replace placeholders in a string with their corresponding values. + * + * @example + * resolveEnvVariables("foo ${workspaceFolder} $SHELL bar"); + * // => "foo /home/user /bin/bash bar" * - * @param userEnvironmentVars EnvVars object containing the user's environment variables - * return an EnvVars object containing the concatenated environment variables + * @param text - The text to resolve the placeholders in. + * @return - The text with the placeholders resolved. */ -function concatEnv(userEnvironmentVars: EnvVars): EnvVars { - const env: EnvVars = {}; +function resolveEnvVariables(text: string):string { + let workspaceFolder = vscode.workspace.workspaceFolders?.[0].uri.fsPath || ""; + + // on windows we need to convert the path to a unix-like path + if (IS_WINDOWS && isUnixShell()) { + workspaceFolder = workspaceFolder.replace(/\\/g, "/"); + // Convert the drive letter to lowercase and add a leading slash (e.g. C: -> /c) + workspaceFolder = workspaceFolder.replace(/^([a-zA-Z]):/, (_, driveLetter) => { + return `/${driveLetter.toLowerCase()}`; + }); + } - for (const [k, v] of Object.entries(userEnvironmentVars)) { - // Replace all instances of $envVar with the system environment variable - env[k] = v.replace(new RegExp(`\\$${k}`, "g"), process.env[k] || ""); + const placeholders: { [key: string]: string } = { + workspaceFolder, + workspaceFolderBasename: path.basename(workspaceFolder), + userHome: os.homedir(), + }; - // Clean up the path separator in the beginning and end of the string - env[k] = env[k].replace(/^[\s:;]+|[\s:;]+$/g, ""); + for (const [placeholder, replacement] of Object.entries(placeholders)) { + text = text.replace(new RegExp(`\\$\\{${placeholder}\\}`, "g"), replacement); } - return env; + for (const match of text.match(/\$\w+/g) || []) { + text = text.replace(match, process.env[match.replace("$", "")] || match); + } + + return text; } /** @@ -99,14 +118,15 @@ function stringifyEnv(env: EnvVars): string { let envString = ""; for (const [k, v] of Object.entries(env)) { + const envPath = v.join(path.delimiter); if (isPowerShell()) { - envString += `$env:${k}="${v}"; `; + envString += `$env:${k}="${envPath}"; `; } else if (isUnixShell()) { - envString += `${k}=${v} `; + envString += `${k}=${envPath} `; } else if (isCmdShell()) { - envString += `set ${k}=${v}&&`; + envString += `set ${k}=${envPath}&&`; } else { - envString += `${k}=${v} `; + envString += `${k}=${envPath} `; vscode.window.showWarningMessage( `Unknown shell detected ${vscode.env.shell}. Environment variables may not be set correctly.` ); @@ -116,35 +136,6 @@ function stringifyEnv(env: EnvVars): string { return envString; } -/** - * Replace placeholders in a string with their corresponding values. - * - * @param value The string to replace placeholders in - * @returns The string with placeholders replaced - */ -function replacePlaceholders(value: string): string { - let workspaceFolder = vscode.workspace.workspaceFolders?.[0].uri.fsPath || ""; - - // on windows we need to convert the path to a unix-like path - if (IS_WINDOWS && isUnixShell()) { - workspaceFolder = workspaceFolder.replace(/\\/g, "/"); - // Convert the drive letter to lowercase and add a leading slash (e.g. C: -> /c) - workspaceFolder = workspaceFolder.replace(/^([a-zA-Z]):/, (_, driveLetter) => { - return `/${driveLetter.toLowerCase()}`; - }); - } - - // always escape the backslashes in the placeholder - const placeholders = { - "\\$\\{workspaceFolder\\}": workspaceFolder, - }; - - for (const [placeholder, replacement] of Object.entries(placeholders)) { - value = value.replace(new RegExp(placeholder, "g"), replacement); - } - - return value; -} /** * Execute the command in the terminal. Before executing the command, if restartInstance @@ -163,8 +154,8 @@ function execCommand(execPath: ExecutablePath): void { }); } - const env = stringifyEnv(concatEnv(getConfig("environmentVariables"))); - const command = replacePlaceholders(`${env} ${execPath.buildExecutableCommand()}`.trim()); + const env = stringifyEnv(getConfig("environmentVariables")); + const command = resolveEnvVariables(`${env} ${execPath.buildExecutableCommand()}`.trim()); const terminal = vscode.window.createTerminal(terminalName); terminal.sendText(command); diff --git a/src/notification.ts b/src/notification.ts index c0e46e8..7a71984 100644 --- a/src/notification.ts +++ b/src/notification.ts @@ -1,9 +1,7 @@ import * as vscode from "vscode"; const _msg = ` -0.15.0 Introduces some breaking changes in the settings. -Please review the settings and update them accordingly. -See the changelog for more information. +0.16.0. Breaking Changes: 'nuketools.environmentVariables' keys now uses an array of strings rather than a single string `; diff --git a/src/fetch_packages.ts b/src/packages_fetch.ts similarity index 100% rename from src/fetch_packages.ts rename to src/packages_fetch.ts