diff --git a/src/vs/workbench/contrib/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/contrib/tasks/electron-browser/task.contribution.ts index 688ffaf6fe8..03ab2edd62d 100644 --- a/src/vs/workbench/contrib/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/contrib/tasks/electron-browser/task.contribution.ts @@ -1360,6 +1360,7 @@ class TaskService extends Disposable implements ITaskService { this.modelService, this.configurationResolverService, this.telemetryService, this.contextService, this._environmentService, TaskService.OutputChannelId, + this.configurationService, (workspaceFolder: IWorkspaceFolder) => { if (!workspaceFolder) { return undefined; @@ -2736,6 +2737,7 @@ let schema: IJSONSchema = { import schemaVersion1 from '../common/jsonSchema_v1'; import schemaVersion2, { updateProblemMatchers } from '../common/jsonSchema_v2'; +import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; schema.definitions = { ...schemaVersion1.definitions, ...schemaVersion2.definitions, @@ -2749,3 +2751,19 @@ ProblemMatcherRegistry.onMatcherChanged(() => { updateProblemMatchers(); jsonRegistry.notifySchemaChanged(schemaId); }); + +const configurationRegistry = Registry.as(Extensions.Configuration); +configurationRegistry.registerConfiguration({ + id: 'Tasks', + order: 100, + title: nls.localize('tasksConfigurationTitle', "Tasks"), + type: 'object', + properties: { + 'tasks.terminal.windowsUseWinpty': { + markdownDescription: nls.localize('tasks.terminal.windowsUseWinpty', "Takes precedent over all other pty settings and forces the integrated terminal to use Winpty instead of Conpty."), + type: 'boolean', + default: true + } + } +}); + diff --git a/src/vs/workbench/contrib/tasks/electron-browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/electron-browser/terminalTaskSystem.ts index b0302bd3d23..0dad2c99818 100644 --- a/src/vs/workbench/contrib/tasks/electron-browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/electron-browser/terminalTaskSystem.ts @@ -44,6 +44,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/ import { Schemas } from 'vs/base/common/network'; import { getWindowsBuildNumber } from 'vs/workbench/contrib/terminal/node/terminal'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; interface TerminalData { terminal: ITerminalInstance; @@ -171,7 +172,8 @@ export class TerminalTaskSystem implements ITaskSystem { private contextService: IWorkspaceContextService, private environmentService: IWorkbenchEnvironmentService, private outputChannelId: string, - taskSystemInfoResolver: TaskSystemInfoResovler + private readonly configurationService: IConfigurationService, + taskSystemInfoResolver: TaskSystemInfoResovler, ) { this.activeTasks = Object.create(null); @@ -877,6 +879,9 @@ export class TerminalTaskSystem implements ITaskSystem { if (options.env) { shellLaunchConfig.env = options.env; } + + // Conpty doesn't do linefeeds in an expected way. Force winpty unless the user has requested otherwise. + shellLaunchConfig.forceWinpty = this.configurationService.getValue('tasks.terminal.windowsUseWinpty'); return shellLaunchConfig; } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index 7bcf1281bdd..5180ade91ae 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -182,7 +182,8 @@ export class TerminalProcessManager implements ITerminalProcessManager { const env = terminalEnvironment.createTerminalEnvironment(shellLaunchConfig, lastActiveWorkspace, envFromConfigValue, this._configurationResolverService, isWorkspaceShellAllowed, this._productService.version, this._configHelper.config.setLocaleVariables); this._logService.debug(`Terminal process launching`, shellLaunchConfig, initialCwd, cols, rows, env); - return this._terminalInstanceService.createTerminalProcess(shellLaunchConfig, initialCwd, cols, rows, env, this._configHelper.config.windowsEnableConpty); + const useConpty = (shellLaunchConfig.forceWinpty !== true) && this._configHelper.config.windowsEnableConpty; + return this._terminalInstanceService.createTerminalProcess(shellLaunchConfig, initialCwd, cols, rows, env, useConpty); } public setDimensions(cols: number, rows: number): void { diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index a1932f39345..94acb510847 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -192,6 +192,12 @@ export interface IShellLaunchConfig { * provided as nothing will be inherited from the process or any configuration. */ strictEnv?: boolean; + + /** + * Moving forward, conpty will be the default. However, there are cases where conpty is not ready + * do be the default. This property will force winpty to be uses, even when conpty would normally be used. + */ + forceWinpty?: boolean; } export interface ITerminalService {