mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-31 09:10:30 -04:00
Merge from vscode 31e03b8ffbb218a87e3941f2b63a249f061fe0e4 (#4986)
This commit is contained in:
@@ -264,6 +264,11 @@ configurationRegistry.registerConfiguration({
|
||||
type: 'boolean',
|
||||
default: true
|
||||
},
|
||||
'terminal.integrated.enableLatencyMitigation': {
|
||||
description: nls.localize('terminal.integrated.enableLatencyMitigation', "Whether to enable the latency mitigation feature for high-latency terminals."),
|
||||
type: 'boolean',
|
||||
default: false
|
||||
},
|
||||
'terminal.integrated.experimentalRefreshOnResume': {
|
||||
description: nls.localize('terminal.integrated.experimentalRefreshOnResume', "An experimental setting that will refresh the terminal renderer when the system is resumed."),
|
||||
type: 'boolean',
|
||||
|
||||
@@ -587,6 +587,19 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
if (this._processManager) {
|
||||
this._widgetManager = new TerminalWidgetManager(this._wrapperElement);
|
||||
this._processManager.onProcessReady(() => this._linkHandler.setWidgetManager(this._widgetManager));
|
||||
|
||||
this._processManager.onProcessReady(() => {
|
||||
if (this._configHelper.config.enableLatencyMitigation) {
|
||||
if (!this._processManager) {
|
||||
return;
|
||||
}
|
||||
this._processManager.getLatency().then(latency => {
|
||||
if (latency > 20 && (this._xterm as any).typeAheadInit) {
|
||||
(this._xterm as any).typeAheadInit(this._processManager, this._themeService);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const computedStyle = window.getComputedStyle(this._container);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ProcessState, ITerminalProcessManager, IShellLaunchConfig, ITerminalConfigHelper, ITerminalChildProcess } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { ProcessState, ITerminalProcessManager, IShellLaunchConfig, ITerminalConfigHelper, ITerminalChildProcess, IBeforeProcessDataEvent } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IHistoryService } from 'vs/workbench/services/history/common/history';
|
||||
@@ -14,11 +14,10 @@ import { TerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/commo
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { REMOTE_HOST_SCHEME, getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
|
||||
import { sanitizeProcessEnvironment } from 'vs/base/common/processes';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IProductService } from 'vs/platform/product/common/product';
|
||||
import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
@@ -57,6 +56,8 @@ export class TerminalProcessManager implements ITerminalProcessManager {
|
||||
|
||||
private readonly _onProcessReady = new Emitter<void>();
|
||||
public get onProcessReady(): Event<void> { return this._onProcessReady.event; }
|
||||
private readonly _onBeforeProcessData = new Emitter<IBeforeProcessDataEvent>();
|
||||
public get onBeforeProcessData(): Event<IBeforeProcessDataEvent> { return this._onBeforeProcessData.event; }
|
||||
private readonly _onProcessData = new Emitter<string>();
|
||||
public get onProcessData(): Event<string> { return this._onProcessData.event; }
|
||||
private readonly _onProcessTitle = new Emitter<string>();
|
||||
@@ -72,9 +73,8 @@ export class TerminalProcessManager implements ITerminalProcessManager {
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService,
|
||||
@IConfigurationResolverService private readonly _configurationResolverService: IConfigurationResolverService,
|
||||
@IWindowService private readonly _windowService: IWindowService,
|
||||
@IConfigurationService private readonly _workspaceConfigurationService: IConfigurationService,
|
||||
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
|
||||
@IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService,
|
||||
@IProductService private readonly _productService: IProductService,
|
||||
@ITerminalInstanceService private readonly _terminalInstanceService: ITerminalInstanceService,
|
||||
@IRemoteAgentService private readonly _remoteAgentService: IRemoteAgentService
|
||||
@@ -114,7 +114,7 @@ export class TerminalProcessManager implements ITerminalProcessManager {
|
||||
if (shellLaunchConfig.cwd && typeof shellLaunchConfig.cwd === 'object') {
|
||||
this.remoteAuthority = getRemoteAuthority(shellLaunchConfig.cwd);
|
||||
} else {
|
||||
this.remoteAuthority = this._windowService.getConfiguration().remoteAuthority;
|
||||
this.remoteAuthority = this._environmentService.configuration.remoteAuthority;
|
||||
}
|
||||
const hasRemoteAuthority = !!this.remoteAuthority;
|
||||
let launchRemotely = hasRemoteAuthority || forceExtHostProcess;
|
||||
@@ -183,7 +183,11 @@ export class TerminalProcessManager implements ITerminalProcessManager {
|
||||
const p = this._process!;
|
||||
|
||||
p.onProcessData(data => {
|
||||
this._onProcessData.fire(data);
|
||||
const beforeProcessDataEvent: IBeforeProcessDataEvent = { data };
|
||||
this._onBeforeProcessData.fire(beforeProcessDataEvent);
|
||||
if (beforeProcessDataEvent.data && beforeProcessDataEvent.data.length > 0) {
|
||||
this._onProcessData.fire(beforeProcessDataEvent.data);
|
||||
}
|
||||
});
|
||||
|
||||
p.onProcessIdReady(pid => {
|
||||
|
||||
@@ -17,7 +17,7 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { TerminalTab } from 'vs/workbench/contrib/terminal/browser/terminalTab';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminalInstance';
|
||||
@@ -35,7 +35,7 @@ export abstract class TerminalService extends CommonTerminalService implements I
|
||||
@INotificationService notificationService: INotificationService,
|
||||
@IDialogService dialogService: IDialogService,
|
||||
@IInstantiationService protected readonly _instantiationService: IInstantiationService,
|
||||
@IWindowService private _windowService: IWindowService,
|
||||
@IWorkbenchEnvironmentService private _environmentService: IWorkbenchEnvironmentService,
|
||||
@IExtensionService extensionService: IExtensionService,
|
||||
@IFileService fileService: IFileService,
|
||||
) {
|
||||
@@ -76,7 +76,7 @@ export abstract class TerminalService extends CommonTerminalService implements I
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._windowService.getConfiguration().remoteAuthority) {
|
||||
if (this._environmentService.configuration.remoteAuthority) {
|
||||
// Don't suggest if the opened workspace is remote
|
||||
return;
|
||||
}
|
||||
@@ -87,7 +87,7 @@ export abstract class TerminalService extends CommonTerminalService implements I
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._windowService.getConfiguration().remoteAuthority) {
|
||||
if (this._environmentService.configuration.remoteAuthority) {
|
||||
// Don't suggest if the opened workspace is remote
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Terminal as XTermTerminal } from 'vscode-xterm';
|
||||
import { ITerminalProcessManager } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
export interface ITerminalCore {
|
||||
buffer: any;
|
||||
}
|
||||
|
||||
export interface ITypeAheadAddonTerminal {
|
||||
_core: ITerminalCore;
|
||||
on: any;
|
||||
write(data: string): void;
|
||||
cols: number;
|
||||
|
||||
__typeAheadQueue: string[];
|
||||
__typeAheadState: TypeAheadState;
|
||||
__typeAheadCurrentYBase: number;
|
||||
__typeAheadCurrentY: number;
|
||||
}
|
||||
|
||||
enum TypeAheadState {
|
||||
/**
|
||||
* The normal state, ready to type if it starts.
|
||||
*/
|
||||
Normal,
|
||||
/**
|
||||
* Something happens such that we cannot make a good guess on what to print,
|
||||
* wait until the cursor row changes before proceeding.
|
||||
*/
|
||||
AwaitingRowChange
|
||||
}
|
||||
|
||||
function isCharPrintable(data: string): boolean {
|
||||
const code = data.charCodeAt(0);
|
||||
return data.length === 1 && code >= 32 && code <= 126;
|
||||
}
|
||||
|
||||
function init(terminal: any, processManager: ITerminalProcessManager, themeService: IThemeService): void {
|
||||
const t = terminal as ITypeAheadAddonTerminal;
|
||||
|
||||
t.__typeAheadQueue = [];
|
||||
t.__typeAheadState = TypeAheadState.Normal;
|
||||
t.__typeAheadCurrentYBase = 0;
|
||||
t.__typeAheadCurrentY = 0;
|
||||
|
||||
function typeAhead(data: string): void {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
t.__typeAheadQueue.push(data[i]);
|
||||
}
|
||||
t.write(data);
|
||||
}
|
||||
|
||||
t.on('cursormove', () => {
|
||||
// Reset if the cursor row changed
|
||||
if (t._core.buffer.ybase !== t.__typeAheadCurrentYBase || t._core.buffer.y !== t.__typeAheadCurrentY) {
|
||||
t.__typeAheadCurrentYBase = t._core.buffer.ybase;
|
||||
t.__typeAheadCurrentY = t._core.buffer.y;
|
||||
t.__typeAheadState = TypeAheadState.Normal;
|
||||
}
|
||||
});
|
||||
|
||||
t.on('data', (data: string) => {
|
||||
// Exit if we're waiting for a row change
|
||||
if (t.__typeAheadState === TypeAheadState.AwaitingRowChange) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only enable in the normal buffer
|
||||
if (!t._core.buffer._hasScrollback) {
|
||||
return;
|
||||
}
|
||||
|
||||
// // Handle enter
|
||||
// if (data === '\r') {
|
||||
// typeAhead('\r\n');
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // Left arrow
|
||||
// if (data === '\x1b[D') {
|
||||
// // TODO: How to stop it from going beyond prompt?
|
||||
// typeAhead(String.fromCharCode(8));
|
||||
// }
|
||||
|
||||
// // Right arrow
|
||||
// if (data === '\x1b[C') {
|
||||
// // TODO: How to stop it from going beyond prompt?
|
||||
// typeAhead('\x1b[C');
|
||||
// }
|
||||
|
||||
// // Backspace (DEL)
|
||||
// if (data.charCodeAt(0) === 127) {
|
||||
// // TODO: This would require knowing the prompt length to be able to shift everything
|
||||
// }
|
||||
|
||||
if (!isCharPrintable(data)) {
|
||||
t.__typeAheadState = TypeAheadState.AwaitingRowChange;
|
||||
return;
|
||||
}
|
||||
|
||||
if (t._core.buffer.x === t.cols - 1) {
|
||||
// TODO: Does the space get added on Windows/Linux too?
|
||||
data += ' \r';
|
||||
}
|
||||
typeAhead(data);
|
||||
});
|
||||
|
||||
processManager.onBeforeProcessData(event => {
|
||||
let consumeCount = 0;
|
||||
for (let i = 0; i < event.data.length; i++) {
|
||||
if (t.__typeAheadQueue[0] === event.data[i]) {
|
||||
t.__typeAheadQueue.shift();
|
||||
consumeCount++;
|
||||
} else {
|
||||
t.__typeAheadQueue.length = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (consumeCount === event.data.length) {
|
||||
event.data = '';
|
||||
} else if (consumeCount > 0) {
|
||||
event.data = event.data.substr(consumeCount);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function apply(terminalConstructor: typeof XTermTerminal) {
|
||||
(<any>terminalConstructor.prototype).typeAheadInit = function (processManager: ITerminalProcessManager, themeService: IThemeService): void {
|
||||
init(this, processManager, themeService);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user