diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionTipsService.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionTipsService.ts index eb853688336b7dacd579a4f4fc9190ab5e0aff93..816a552161030a6535c2366376563d101ecb6274 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionTipsService.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionTipsService.ts @@ -913,7 +913,8 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe windowsPath = windowsPath.replace('%USERPROFILE%', process.env['USERPROFILE']!) .replace('%ProgramFiles(x86)%', process.env['ProgramFiles(x86)']!) .replace('%ProgramFiles%', process.env['ProgramFiles']!) - .replace('%APPDATA%', process.env['APPDATA']!); + .replace('%APPDATA%', process.env['APPDATA']!) + .replace('%WINDIR%', process.env['WINDIR']!); promises.push(findExecutable(exeName, windowsPath)); } else { promises.push(findExecutable(exeName, join('/usr/local/bin', exeName))); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts b/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts index 899cbf7f5249b675fa19b670e24e3dd2934aa33c..0da7d6c690bf807b7835513bfadd08282a173278 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts @@ -8,12 +8,15 @@ import * as platform from 'vs/base/common/platform'; import { EDITOR_FONT_DEFAULTS, IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { ITerminalConfiguration, ITerminalFont, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, TERMINAL_CONFIG_SECTION, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, MINIMUM_LETTER_SPACING, LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalConfiguration, ITerminalFont, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, TERMINAL_CONFIG_SECTION, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, MINIMUM_LETTER_SPACING, LinuxDistro, IShellLaunchConfig } from 'vs/workbench/contrib/terminal/common/terminal'; import Severity from 'vs/base/common/severity'; import { Terminal as XTermTerminal } from 'xterm'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { IBrowserTerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminal'; import { Emitter, Event } from 'vs/base/common/event'; +import { basename } from 'vs/base/common/path'; +import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { ExtensionType } from 'vs/platform/extensions/common/extensions'; const MINIMUM_FONT_SIZE = 6; const MAXIMUM_FONT_SIZE = 25; @@ -35,7 +38,7 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { public constructor( private readonly _linuxDistro: LinuxDistro, @IConfigurationService private readonly _configurationService: IConfigurationService, - @IConfigurationService private readonly _workspaceConfigurationService: IConfigurationService, + @IExtensionManagementService private readonly _extensionManagementService: IExtensionManagementService, @INotificationService private readonly _notificationService: INotificationService, @IStorageService private readonly _storageService: IStorageService ) { @@ -174,9 +177,9 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { public checkWorkspaceShellPermissions(osOverride: platform.OperatingSystem = platform.OS): boolean { // Check whether there is a workspace setting const platformKey = osOverride === platform.OperatingSystem.Windows ? 'windows' : osOverride === platform.OperatingSystem.Macintosh ? 'osx' : 'linux'; - const shellConfigValue = this._workspaceConfigurationService.inspect(`terminal.integrated.shell.${platformKey}`); - const shellArgsConfigValue = this._workspaceConfigurationService.inspect(`terminal.integrated.shellArgs.${platformKey}`); - const envConfigValue = this._workspaceConfigurationService.inspect<{ [key: string]: string }>(`terminal.integrated.env.${platformKey}`); + const shellConfigValue = this._configurationService.inspect(`terminal.integrated.shell.${platformKey}`); + const shellArgsConfigValue = this._configurationService.inspect(`terminal.integrated.shellArgs.${platformKey}`); + const envConfigValue = this._configurationService.inspect<{ [key: string]: string }>(`terminal.integrated.env.${platformKey}`); // Check if workspace setting exists and whether it's whitelisted let isWorkspaceShellAllowed: boolean | undefined = false; @@ -244,4 +247,48 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { } return r; } + + private readonly NO_RECOMMENDATIONS_KEY = 'terminalConfigHelper/launchRecommendationsIgnore'; + private recommendationsShown = false; + + public async showRecommendations(shellLaunchConfig: IShellLaunchConfig): Promise { + if (this.recommendationsShown) { + return; + } + this.recommendationsShown = true; + + if (platform.isWindows && shellLaunchConfig.executable && basename(shellLaunchConfig.executable).toLowerCase() === 'wsl.exe') { + if (this._storageService.getBoolean(this.NO_RECOMMENDATIONS_KEY, StorageScope.WORKSPACE, false)) { + return; + } + + if (! await this.isExtensionInstalled('ms-vscode-remote.remote-wsl')) { + this._notificationService.prompt( + Severity.Info, + nls.localize( + 'useWslExtension.title', + "Check out the 'Visual Studio Code Remote - WSL' extension for a great development experience in WSL. Click [here]({0}) to learn more.", + 'https://go.microsoft.com/fwlink/?linkid=2097212' + ), + [ + { + label: nls.localize('doNotShowAgain', "Don't Show Again"), + run: () => { + this._storageService.store(this.NO_RECOMMENDATIONS_KEY, true, StorageScope.WORKSPACE); + } + } + ], + { + sticky: true + } + ); + } + } + } + + private isExtensionInstalled(id: string): Promise { + return this._extensionManagementService.getInstalled(ExtensionType.User).then(extensions => { + return extensions.some(e => e.identifier.id === id); + }); + } } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index bfa9741748eb5b991605712926d82e80496f883e..0d898575cd3e29161f40609172ae89d317c0116c 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -209,6 +209,7 @@ export class TerminalProcessManager implements ITerminalProcessManager { const initialCwd = terminalEnvironment.getCwd(shellLaunchConfig, this._environmentService.userHome, activeWorkspaceRootUri, this._configHelper.config.cwd); const envFromConfigValue = this._workspaceConfigurationService.inspect(`terminal.integrated.env.${platformKey}`); const isWorkspaceShellAllowed = this._configHelper.checkWorkspaceShellPermissions(); + this._configHelper.showRecommendations(shellLaunchConfig); const baseEnv = this._configHelper.config.inheritEnv ? process.env as platform.IProcessEnvironment : await this._terminalInstanceService.getMainProcessParentEnv(); const env = terminalEnvironment.createTerminalEnvironment(shellLaunchConfig, lastActiveWorkspace, envFromConfigValue, this._configurationResolverService, isWorkspaceShellAllowed, this._productService.version, this._configHelper.config.setLocaleVariables, baseEnv); diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index dfd828343974dfa781ce492a834253e836fd42d4..c126bf709783bdbc38ab7faa6fd74380c3891287 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -122,6 +122,7 @@ export interface ITerminalConfigHelper { /** Sets whether a workspace shell configuration is allowed or not */ setWorkspaceShellAllowed(isAllowed: boolean): void; checkWorkspaceShellPermissions(osOverride?: OperatingSystem): boolean; + showRecommendations(shellLaunchConfig: IShellLaunchConfig): void; } export interface ITerminalFont {