diff --git a/CHANGELOG.md b/CHANGELOG.md index 61920621..fc852f51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### 🎨 Enhancements - [#878](https://github.com/estruyf/vscode-front-matter/issues/878): Allow the `select all` button to work on other pages when there is a selection present +- [#882](https://github.com/estruyf/vscode-front-matter/issues/882): Dynamic evaluation of the `node` executable path ### 🐞 Fixes diff --git a/src/helpers/CustomScript.ts b/src/helpers/CustomScript.ts index 33c0e529..2e83b1e5 100644 --- a/src/helpers/CustomScript.ts +++ b/src/helpers/CustomScript.ts @@ -1,7 +1,7 @@ import { Settings } from './SettingsHelper'; -import { CommandType, EnvironmentType } from './../models/PanelSettings'; +import { CommandType } from './../models/PanelSettings'; import { CustomScript as ICustomScript, ScriptType } from '../models/PanelSettings'; -import { window, env as vscodeEnv, ProgressLocation, Uri, commands } from 'vscode'; +import { window, env as vscodeEnv, ProgressLocation, Uri, commands, workspace } from 'vscode'; import { ArticleHelper, Logger, MediaHelpers } from '.'; import { Folders, WORKSPACE_PLACEHOLDER } from '../commands/Folders'; import { exec, execSync } from 'child_process'; @@ -13,9 +13,10 @@ import { Dashboard } from '../commands/Dashboard'; import { DashboardCommand } from '../dashboardWebView/DashboardCommand'; import { ParsedFrontMatter } from '../parsers'; import { SETTING_CUSTOM_SCRIPTS } from '../constants'; -import { existsAsync } from '../utils'; +import { existsAsync, getPlatform } from '../utils'; import * as l10n from '@vscode/l10n'; import { LocalizationKey } from '../localization'; +import { ShellSetting } from '../models'; export class CustomScript { /** @@ -373,7 +374,7 @@ export class CustomScript { wsPath: string, args: string ): Promise { - const osType = os.type(); + const platform = getPlatform(); // Check the command to use let command = script.nodeBin || 'node'; @@ -381,6 +382,10 @@ export class CustomScript { command = script.command; } + if (script.command === CommandType.Node && platform !== 'windows') { + command = await CustomScript.evaluateCommand(CommandType.Node); + } + let scriptPath = join(wsPath, script.script); if (script.script.includes(WORKSPACE_PLACEHOLDER)) { scriptPath = Folders.getAbsFilePath(script.script); @@ -388,19 +393,15 @@ export class CustomScript { // Check if there is an environments overwrite required if (script.environments) { - let crntType: EnvironmentType | null = null; - if (osType === 'Windows_NT') { - crntType = 'windows'; - } else if (osType === 'Darwin') { - crntType = 'macos'; - } else { - crntType = 'linux'; - } - - const environment = script.environments.find((e) => e.type === crntType); + const environment = script.environments.find((e) => e.type === platform); if (environment && environment.script && environment.command) { if (await CustomScript.validateCommand(environment.command)) { command = environment.command; + + if (command === CommandType.Node && platform !== 'windows') { + command = await CustomScript.evaluateCommand(CommandType.Node); + } + scriptPath = join(wsPath, environment.script); if (environment.script.includes(WORKSPACE_PLACEHOLDER)) { scriptPath = Folders.getAbsFilePath(environment.script); @@ -414,7 +415,7 @@ export class CustomScript { throw new Error(`Script not found: ${scriptPath}`); } - if (osType === 'Windows_NT' && command.toLowerCase() === 'powershell') { + if (platform === 'windows' && command.toLowerCase() === 'powershell') { command = `${command} -File`; } @@ -506,4 +507,64 @@ export class CustomScript { return false; } } + + /** + * Evaluate the command dynamically using `which` command + * @param command + * @returns + */ + private static async evaluateCommand(command: string): Promise { + const shell = CustomScript.getShellPath(); + let shellPath: string | undefined = undefined; + if (typeof shell !== 'string' && !!shell) { + shellPath = shell.path; + } else { + shellPath = shell || undefined; + } + + return new Promise((resolve, reject) => { + exec(`which ${command}`, { shell: shellPath }, (error, stdout) => { + if (error) { + Logger.error(`Error evaluating command: ${command}`); + reject(error); + return; + } + + resolve(stdout.trim()); + }); + }); + } + + /** + * Retrieves the shell path configuration based on the current platform and terminal settings. + * + * This method checks for the following configurations in order: + * 1. `integrated.automationProfile.`: Returns the automation profile if it exists. + * 2. `integrated.defaultProfile.` and `integrated.profiles.`: Returns the shell setting from the default profile if it exists. + * 3. `integrated.shell.`: Returns the shell setting if the above configurations are not found. + * + * @returns {string | ShellSetting | undefined} The shell path configuration or undefined if not found. + */ + private static getShellPath(): string | ShellSetting | undefined { + const platform = getPlatform(); + const terminalSettings = workspace.getConfiguration('terminal'); + + const automationProfile = terminalSettings.get( + `integrated.automationProfile.${platform}` + ); + if (!!automationProfile) { + return automationProfile; + } + + const defaultProfile = terminalSettings.get(`integrated.defaultProfile.${platform}`); + const profiles = terminalSettings.get<{ [prop: string]: ShellSetting }>( + `integrated.profiles.${platform}` + ); + + if (defaultProfile && profiles && profiles[defaultProfile]) { + return profiles[defaultProfile]; + } + + return terminalSettings.get(`integrated.shell.${platform}`); + } } diff --git a/src/models/ShellSetting.ts b/src/models/ShellSetting.ts new file mode 100644 index 00000000..05a90dd8 --- /dev/null +++ b/src/models/ShellSetting.ts @@ -0,0 +1,3 @@ +export interface ShellSetting { + path: string; +} diff --git a/src/models/index.ts b/src/models/index.ts index 82b09148..81684673 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -22,6 +22,7 @@ export * from './Mode'; export * from './PanelSettings'; export * from './PostMessageData'; export * from './Project'; +export * from './ShellSetting'; export * from './Snippets'; export * from './SortOrder'; export * from './SortType'; diff --git a/src/services/Terminal.ts b/src/services/Terminal.ts index fa6b2ff3..9e93c842 100644 --- a/src/services/Terminal.ts +++ b/src/services/Terminal.ts @@ -1,8 +1,8 @@ import { workspace, window, ThemeIcon, TerminalOptions } from 'vscode'; -import * as os from 'os'; import { Folders } from '../commands'; import * as l10n from '@vscode/l10n'; import { LocalizationKey } from '../localization'; +import { getPlatform } from '../utils'; interface ShellSetting { path: string; @@ -96,7 +96,7 @@ export class Terminal { * @returns */ private static getShellPath(): string | ShellSetting | undefined { - const platform = Terminal.getPlatform(); + const platform = getPlatform(); const terminalSettings = workspace.getConfiguration('terminal'); const automationProfile = terminalSettings.get( @@ -117,19 +117,4 @@ export class Terminal { return terminalSettings.get(`integrated.shell.${platform}`); } - - /** - * Get the current platform - * @returns - */ - private static getPlatform = (): 'windows' | 'linux' | 'osx' => { - const platform = os.platform(); - if (platform === 'win32') { - return 'windows'; - } else if (platform === 'darwin') { - return 'osx'; - } - - return 'linux'; - }; } diff --git a/src/utils/getPlatform.ts b/src/utils/getPlatform.ts new file mode 100644 index 00000000..da5b4f77 --- /dev/null +++ b/src/utils/getPlatform.ts @@ -0,0 +1,20 @@ +import * as os from 'os'; + +/** + * Determines the current operating system platform. + * + * @returns {'windows' | 'linux' | 'osx'} - A string representing the platform: + * - 'windows' for Windows OS + * - 'osx' for macOS + * - 'linux' for Linux OS + */ +export const getPlatform = (): 'windows' | 'linux' | 'osx' => { + const platform = os.platform(); + if (platform === 'win32') { + return 'windows'; + } else if (platform === 'darwin') { + return 'osx'; + } + + return 'linux'; +}; diff --git a/src/utils/index.ts b/src/utils/index.ts index f1013c87..ee7fbcfb 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -8,6 +8,7 @@ export * from './flattenObjectKeys'; export * from './getDescriptionField'; export * from './getExtensibilityScripts'; export * from './getLocalizationFile'; +export * from './getPlatform'; export * from './getTitleField'; export * from './getWebviewJsFiles'; export * from './ignoreMsgCommand';