Merge from vscode fcf3346a8e9f5ee1e00674461d9e2c2292a14ee3 (#12295)

* Merge from vscode fcf3346a8e9f5ee1e00674461d9e2c2292a14ee3

* Fix test build break

* Update distro

* Fix build errors

* Update distro

* Update REH build file

* Update build task names for REL

* Fix product build yaml

* Fix product REH task name

* Fix type in task name

* Update linux build step

* Update windows build tasks

* Turn off server publish

* Disable REH

* Fix typo

* Bump distro

* Update vscode tests

* Bump distro

* Fix type in disto

* Bump distro

* Turn off docker build

* Remove docker step from release

Co-authored-by: ADS Merger <andresse@microsoft.com>
Co-authored-by: Karl Burtram <karlb@microsoft.com>
This commit is contained in:
Christopher Suh
2020-10-03 14:42:05 -04:00
committed by GitHub
parent 58d02b76db
commit 6ff1e3866b
687 changed files with 10507 additions and 9104 deletions

View File

@@ -65,7 +65,7 @@ export class TerminalExternalLinkProviderAdapter extends TerminalBaseLinkProvide
}, startLine);
const matchingText = lineContent.substr(link.startIndex, link.length) || '';
const activateLink = this._wrapLinkHandler((_, text) => link.activate(text));
return this._instantiationService.createInstance(TerminalLink, bufferRange, matchingText, this._xterm.buffer.active.viewportY, activateLink, this._tooltipCallback, true, link.label);
return this._instantiationService.createInstance(TerminalLink, this._xterm, bufferRange, matchingText, this._xterm.buffer.active.viewportY, activateLink, this._tooltipCallback, true, link.label);
});
}
}

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import type { IViewportRange, IBufferRange, ILink, ILinkDecorations } from 'xterm';
import type { IViewportRange, IBufferRange, ILink, ILinkDecorations, Terminal } from 'xterm';
import { DisposableStore } from 'vs/base/common/lifecycle';
import * as dom from 'vs/base/browser/dom';
import { RunOnceScheduler } from 'vs/base/common/async';
@@ -23,10 +23,11 @@ export class TerminalLink extends DisposableStore implements ILink {
private _tooltipScheduler: RunOnceScheduler | undefined;
private _hoverListeners: DisposableStore | undefined;
private readonly _onLeave = new Emitter<void>();
public get onLeave(): Event<void> { return this._onLeave.event; }
private readonly _onInvalidated = new Emitter<void>();
public get onInvalidated(): Event<void> { return this._onInvalidated.event; }
constructor(
private readonly _xterm: Terminal,
public readonly range: IBufferRange,
public readonly text: string,
private readonly _viewportY: number,
@@ -57,17 +58,26 @@ export class TerminalLink extends DisposableStore implements ILink {
hover(event: MouseEvent, text: string): void {
// Listen for modifier before handing it off to the hover to handle so it gets disposed correctly
this.add(dom.addDisposableListener(document, 'keydown', e => {
if (this._isModifierDown(e)) {
this._hoverListeners = new DisposableStore();
this._hoverListeners.add(dom.addDisposableListener(document, 'keydown', e => {
if (!e.repeat && this._isModifierDown(e)) {
this._enableDecorations();
}
}));
this.add(dom.addDisposableListener(document, 'keyup', e => {
if (!this._isModifierDown(e)) {
this._hoverListeners.add(dom.addDisposableListener(document, 'keyup', e => {
if (!e.repeat && !this._isModifierDown(e)) {
this._disableDecorations();
}
}));
// Listen for when the terminal renders on the same line as the link
this._hoverListeners.add(this._xterm.onRender(e => {
const viewportRangeY = this.range.start.y - this._viewportY;
if (viewportRangeY >= e.start && viewportRangeY <= e.end) {
this._onInvalidated.fire();
}
}));
// Only show the tooltip and highlight for high confidence links (not word/search workspace
// links). Feedback was that this makes using the terminal overly noisy.
if (this._isHighConfidenceLink) {
@@ -88,7 +98,6 @@ export class TerminalLink extends DisposableStore implements ILink {
}
const origin = { x: event.pageX, y: event.pageY };
this._hoverListeners = new DisposableStore();
this._hoverListeners.add(dom.addDisposableListener(document, dom.EventType.MOUSE_MOVE, e => {
// Update decorations
if (this._isModifierDown(e)) {
@@ -111,7 +120,6 @@ export class TerminalLink extends DisposableStore implements ILink {
this._hoverListeners = undefined;
this._tooltipScheduler?.dispose();
this._tooltipScheduler = undefined;
this._onLeave.fire();
}
private _enableDecorations(): void {

View File

@@ -14,7 +14,7 @@ import { ITextEditorSelection } from 'vs/platform/editor/common/editor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IFileService } from 'vs/platform/files/common/files';
import type { Terminal, IViewportRange, ILinkProvider } from 'xterm';
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
import { Schemas } from 'vs/base/common/network';
import { posix, win32 } from 'vs/base/common/path';
import { ITerminalExternalLinkProvider, ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal';
import { OperatingSystem, isMacintosh, OS } from 'vs/base/common/platform';
@@ -116,7 +116,7 @@ export class TerminalLinkManager extends DisposableStore {
const widget = this._instantiationService.createInstance(TerminalHover, targetOptions, text, linkHandler);
const attached = this._widgetManager.attachWidget(widget);
if (attached) {
link?.onLeave(() => attached.dispose());
link?.onInvalidated(() => attached.dispose());
}
}
}
@@ -296,7 +296,7 @@ export class TerminalLinkManager extends DisposableStore {
let uri: URI;
if (this._processManager.remoteAuthority) {
uri = URI.from({
scheme: REMOTE_HOST_SCHEME,
scheme: Schemas.vscodeRemote,
authority: this._processManager.remoteAuthority,
path: linkUrl
});

View File

@@ -52,7 +52,7 @@ export class TerminalProtocolLinkProvider extends TerminalBaseLinkProvider {
? (typeof link.url === 'string' ? URI.parse(link.url) : link.url)
: undefined;
const label = (uri?.scheme === 'file') ? OPEN_FILE_LABEL : undefined;
return this._instantiationService.createInstance(TerminalLink, range, link.url?.toString() || '', this._xterm.buffer.active.viewportY, this._activateCallback, this._tooltipCallback, true, label);
return this._instantiationService.createInstance(TerminalLink, this._xterm, range, link.url?.toString() || '', this._xterm.buffer.active.viewportY, this._activateCallback, this._tooltipCallback, true, label);
});
}
}

View File

@@ -20,14 +20,14 @@ const pathPrefix = '(\\.\\.?|\\~)';
const pathSeparatorClause = '\\/';
// '":; are allowed in paths but they are often separators so ignore them
// Also disallow \\ to prevent a catastropic backtracking case #24798
const excludedPathCharactersClause = '[^\\0\\s!$`&*()\\[\\]+\'":;\\\\]';
const excludedPathCharactersClause = '[^\\0\\s!$`&*()\\[\\]\'":;\\\\]';
/** A regex that matches paths in the form /foo, ~/foo, ./foo, ../foo, foo/bar */
export const unixLocalLinkClause = '((' + pathPrefix + '|(' + excludedPathCharactersClause + ')+)?(' + pathSeparatorClause + '(' + excludedPathCharactersClause + ')+)+)';
export const winDrivePrefix = '(?:\\\\\\\\\\?\\\\)?[a-zA-Z]:';
const winPathPrefix = '(' + winDrivePrefix + '|\\.\\.?|\\~)';
const winPathSeparatorClause = '(\\\\|\\/)';
const winExcludedPathCharactersClause = '[^\\0<>\\?\\|\\/\\s!$`&*()\\[\\]+\'":;]';
const winExcludedPathCharactersClause = '[^\\0<>\\?\\|\\/\\s!$`&*()\\[\\]\'":;]';
/** A regex that matches paths in the form \\?\c:\foo c:\foo, ~\foo, .\foo, ..\foo, foo\bar */
export const winLocalLinkClause = '((' + winPathPrefix + '|(' + winExcludedPathCharactersClause + ')+)?(' + winPathSeparatorClause + '(' + winExcludedPathCharactersClause + ')+)+)';
@@ -144,7 +144,7 @@ export class TerminalValidatedLocalLinkProvider extends TerminalBaseLinkProvider
this._activateFileCallback(event, text);
}
});
r(this._instantiationService.createInstance(TerminalLink, bufferRange, link, this._xterm.buffer.active.viewportY, activateCallback, this._tooltipCallback, true, label));
r(this._instantiationService.createInstance(TerminalLink, this._xterm, bufferRange, link, this._xterm.buffer.active.viewportY, activateCallback, this._tooltipCallback, true, label));
} else {
r(undefined);
}

View File

@@ -53,7 +53,7 @@ export class TerminalWordLinkProvider extends TerminalBaseLinkProvider {
// Add a link if this is a separator
if (width !== 0 && wordSeparators.indexOf(chars) >= 0) {
if (startX !== -1) {
result.push(new TerminalLink({ start: { x: startX + 1, y }, end: { x, y } }, text, this._xterm.buffer.active.viewportY, activateCallback, this._tooltipCallback, false, localize('searchWorkspace', 'Search workspace'), this._configurationService));
result.push(this._createTerminalLink(startX, x, y, text, activateCallback));
text = '';
startX = -1;
}
@@ -70,12 +70,30 @@ export class TerminalWordLinkProvider extends TerminalBaseLinkProvider {
// Add the final link if there is one
if (startX !== -1) {
result.push(new TerminalLink({ start: { x: startX + 1, y }, end: { x: line.length, y } }, text, this._xterm.buffer.active.viewportY, activateCallback, this._tooltipCallback, false, localize('searchWorkspace', 'Search workspace'), this._configurationService));
result.push(this._createTerminalLink(startX, line.length, y, text, activateCallback));
}
return result;
}
private _createTerminalLink(startX: number, endX: number, y: number, text: string, activateCallback: XtermLinkMatcherHandler): TerminalLink {
// Remove trailing colon if there is one so the link is more useful
if (text.length > 0 && text.charAt(text.length - 1) === ':') {
text = text.slice(0, -1);
endX--;
}
return this._instantiationService.createInstance(TerminalLink,
this._xterm,
{ start: { x: startX + 1, y }, end: { x: endX, y } },
text,
this._xterm.buffer.active.viewportY,
activateCallback,
this._tooltipCallback,
false,
localize('searchWorkspace', 'Search workspace')
);
}
private async _activate(link: string) {
const results = await this._searchService.fileSearch(
this._fileQueryBuilder.file(this._workspaceContextService.getWorkspace().folders, {

View File

@@ -652,7 +652,7 @@ export function registerTerminalActions() {
const codeEditorService = accessor.get(ICodeEditorService);
const instance = terminalService.getActiveOrCreateInstance();
let editor = codeEditorService.getFocusedCodeEditor();
let editor = codeEditorService.getActiveCodeEditor();
if (!editor || !editor.hasModel()) {
return;
}

View File

@@ -8,7 +8,7 @@ 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, IShellLaunchConfig } 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, MINIMUM_FONT_WEIGHT, MAXIMUM_FONT_WEIGHT, DEFAULT_FONT_WEIGHT, DEFAULT_BOLD_FONT_WEIGHT, FontWeight } from 'vs/workbench/contrib/terminal/common/terminal';
import Severity from 'vs/base/common/severity';
import { INotificationService, NeverShowAgainScope } from 'vs/platform/notification/common/notification';
import { IBrowserTerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminal';
@@ -67,7 +67,11 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
}
private _updateConfig(): void {
this.config = this._configurationService.getValue<ITerminalConfiguration>(TERMINAL_CONFIG_SECTION);
const configValues = this._configurationService.getValue<ITerminalConfiguration>(TERMINAL_CONFIG_SECTION);
configValues.fontWeight = this._normalizeFontWeight(configValues.fontWeight, DEFAULT_FONT_WEIGHT);
configValues.fontWeightBold = this._normalizeFontWeight(configValues.fontWeightBold, DEFAULT_BOLD_FONT_WEIGHT);
this.config = configValues;
}
public configFontIsMonospace(): boolean {
@@ -157,7 +161,7 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
const editorConfig = this._configurationService.getValue<IEditorOptions>('editor');
let fontFamily = this.config.fontFamily || editorConfig.fontFamily || EDITOR_FONT_DEFAULTS.fontFamily;
let fontSize = this._toInteger(this.config.fontSize, MINIMUM_FONT_SIZE, MAXIMUM_FONT_SIZE, EDITOR_FONT_DEFAULTS.fontSize);
let fontSize = this._clampInt(this.config.fontSize, MINIMUM_FONT_SIZE, MAXIMUM_FONT_SIZE, EDITOR_FONT_DEFAULTS.fontSize);
// Work around bad font on Fedora/Ubuntu
if (!this.config.fontFamily) {
@@ -168,7 +172,7 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
fontFamily = '\'Ubuntu Mono\', monospace';
// Ubuntu mono is somehow smaller, so set fontSize a bit larger to get the same perceived size.
fontSize = this._toInteger(fontSize + 2, MINIMUM_FONT_SIZE, MAXIMUM_FONT_SIZE, EDITOR_FONT_DEFAULTS.fontSize);
fontSize = this._clampInt(fontSize + 2, MINIMUM_FONT_SIZE, MAXIMUM_FONT_SIZE, EDITOR_FONT_DEFAULTS.fontSize);
}
}
@@ -271,7 +275,7 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
return !!isWorkspaceShellAllowed;
}
private _toInteger(source: any, minimum: number, maximum: number, fallback: number): number {
private _clampInt<T>(source: any, minimum: number, maximum: number, fallback: T): number | T {
let r = parseInt(source, 10);
if (isNaN(r)) {
return fallback;
@@ -340,4 +344,11 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
const extensions = await this._extensionManagementService.getInstalled(ExtensionType.User);
return extensions.some(e => e.identifier.id === id);
}
private _normalizeFontWeight(input: any, defaultWeight: FontWeight): FontWeight {
if (input === 'normal' || input === 'bold') {
return input;
}
return this._clampInt(input, MINIMUM_FONT_WEIGHT, MAXIMUM_FONT_WEIGHT, defaultWeight);
}
}

View File

@@ -35,6 +35,7 @@ import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/browser/te
import type { Terminal as XTermTerminal, IBuffer, ITerminalAddon } from 'xterm';
import type { SearchAddon, ISearchOptions } from 'xterm-addon-search';
import type { Unicode11Addon } from 'xterm-addon-unicode11';
import type { WebglAddon } from 'xterm-addon-webgl';
import { CommandTrackerAddon } from 'vs/workbench/contrib/terminal/browser/addons/commandTrackerAddon';
import { NavigationModeAddon } from 'vs/workbench/contrib/terminal/browser/addons/navigationModeAddon';
import { XTermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private';
@@ -105,6 +106,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
private _widgetManager: TerminalWidgetManager = this._instantiationService.createInstance(TerminalWidgetManager);
private _linkManager: TerminalLinkManager | undefined;
private _environmentInfo: { widget: EnvironmentVariableInfoWidget, disposable: IDisposable } | undefined;
private _webglAddon: WebglAddon | undefined;
private _commandTrackerAddon: CommandTrackerAddon | undefined;
private _navigationModeAddon: INavigationMode & ITerminalAddon | undefined;
@@ -496,9 +498,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
this._container.appendChild(this._wrapperElement);
xterm.open(this._xtermElement);
if (this._configHelper.config.rendererType === 'experimentalWebgl') {
this._terminalInstanceService.getXtermWebglConstructor().then(Addon => {
xterm.loadAddon(new Addon());
});
this._enableWebglRenderer();
}
if (!xterm.element || !xterm.textarea) {
@@ -767,7 +767,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
if (!this._xterm) {
return;
}
this._xterm.refresh(0, this._xterm.rows - 1);
this._webglAddon?.clearTextureAtlas();
// TODO: Do canvas renderer too?
}
public focus(force?: boolean): void {
@@ -1227,13 +1228,26 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
this._safeSetOption('macOptionClickForcesSelection', config.macOptionClickForcesSelection);
this._safeSetOption('rightClickSelectsWord', config.rightClickBehavior === 'selectWord');
this._safeSetOption('wordSeparator', config.wordSeparators);
if (config.rendererType !== 'experimentalWebgl') {
if (config.rendererType === 'experimentalWebgl') {
this._enableWebglRenderer();
} else {
this._webglAddon?.dispose();
this._webglAddon = undefined;
// Never set webgl as it's an addon not a rendererType
this._safeSetOption('rendererType', config.rendererType === 'auto' ? 'canvas' : config.rendererType);
}
this._refreshEnvironmentVariableInfoWidgetState(this._processManager.environmentVariableInfo);
}
private async _enableWebglRenderer(): Promise<void> {
if (!this._xterm || this._webglAddon) {
return;
}
const Addon = await this._terminalInstanceService.getXtermWebglConstructor();
this._webglAddon = new Addon();
this._xterm.loadAddon(this._webglAddon);
}
private async _updateUnicodeVersion(): Promise<void> {
if (!this._xterm) {
throw new Error('Cannot update unicode version before xterm has been initialized');

View File

@@ -43,9 +43,9 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal
private readonly _onRequestLatency = this._register(new Emitter<void>());
public readonly onRequestLatency: Event<void> = this._onRequestLatency.event;
private _pendingInitialCwdRequests: ((value?: string | Thenable<string>) => void)[] = [];
private _pendingCwdRequests: ((value?: string | Thenable<string>) => void)[] = [];
private _pendingLatencyRequests: ((value?: number | Thenable<number>) => void)[] = [];
private _pendingInitialCwdRequests: ((value: string | PromiseLike<string>) => void)[] = [];
private _pendingCwdRequests: ((value: string | PromiseLike<string>) => void)[] = [];
private _pendingLatencyRequests: ((value: number | PromiseLike<number>) => void)[] = [];
constructor(
public terminalId: number,

View File

@@ -25,7 +25,6 @@ import { FindReplaceState } from 'vs/editor/contrib/find/findState';
import { escapeNonWindowsPath } from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
import { isWindows, isMacintosh, OperatingSystem, isWeb } from 'vs/base/common/platform';
import { basename } from 'vs/base/common/path';
import { find } from 'vs/base/common/arrays';
import { timeout } from 'vs/base/common/async';
import { IViewsService, ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views';
import { IDisposable } from 'vs/base/common/lifecycle';
@@ -232,7 +231,9 @@ export class TerminalService implements ITerminalService {
private _removeTab(tab: ITerminalTab): void {
// Get the index of the tab and remove it from the list
const index = this._terminalTabs.indexOf(tab);
const wasActiveTab = tab === this.getActiveTab();
const activeTab = this.getActiveTab();
const activeTabIndex = activeTab ? this._terminalTabs.indexOf(activeTab) : -1;
const wasActiveTab = tab === activeTab;
if (index !== -1) {
this._terminalTabs.splice(index, 1);
}
@@ -247,6 +248,9 @@ export class TerminalService implements ITerminalService {
if (activeInstance) {
activeInstance.focus(true);
}
} else if (activeTabIndex >= this._terminalTabs.length) {
const newIndex = this._terminalTabs.length - 1;
this.setActiveTabByIndex(newIndex);
}
// Hide the panel if there are no more instances, provided that VS Code is not shutting
@@ -454,7 +458,7 @@ export class TerminalService implements ITerminalService {
}
private _getTabForInstance(instance: ITerminalInstance): ITerminalTab | undefined {
return find(this._terminalTabs, tab => tab.terminalInstances.indexOf(instance) !== -1);
return this._terminalTabs.find(tab => tab.terminalInstances.indexOf(instance) !== -1);
}
public async showPanel(focus?: boolean): Promise<void> {

View File

@@ -41,13 +41,16 @@ export class TerminalHover extends Disposable implements ITerminalWidget {
attach(container: HTMLElement): void {
const target = new CellHoverTarget(container, this._targetOptions);
this._hoverService.showHover({
const hover = this._hoverService.showHover({
target,
text: this._text,
linkHandler: this._linkHandler,
// .xterm-hover lets xterm know that the hover is part of a link
additionalClasses: ['xterm-hover']
});
if (hover) {
this._register(hover);
}
}
}

View File

@@ -70,7 +70,13 @@ export const DEFAULT_LETTER_SPACING = 0;
export const MINIMUM_LETTER_SPACING = -5;
export const DEFAULT_LINE_HEIGHT = 1;
export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
export const MINIMUM_FONT_WEIGHT = 1;
export const MAXIMUM_FONT_WEIGHT = 1000;
export const DEFAULT_FONT_WEIGHT = 'normal';
export const DEFAULT_BOLD_FONT_WEIGHT = 'bold';
export const SUGGESTIONS_FONT_WEIGHT = ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'];
export type FontWeight = 'normal' | 'bold' | number;
export interface ITerminalConfiguration {
shell: {

View File

@@ -6,7 +6,7 @@
import { IConfigurationNode } from 'vs/platform/configuration/common/configurationRegistry';
import { localize } from 'vs/nls';
import { EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions';
import { DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, TerminalCursorStyle, DEFAULT_COMMANDS_TO_SKIP_SHELL } from 'vs/workbench/contrib/terminal/common/terminal';
import { DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, TerminalCursorStyle, DEFAULT_COMMANDS_TO_SKIP_SHELL, SUGGESTIONS_FONT_WEIGHT, MINIMUM_FONT_WEIGHT, MAXIMUM_FONT_WEIGHT } from 'vs/workbench/contrib/terminal/common/terminal';
import { isMacintosh, isWindows, Platform } from 'vs/base/common/platform';
export const terminalConfiguration: IConfigurationNode = {
@@ -136,15 +136,41 @@ export const terminalConfiguration: IConfigurationNode = {
default: 1
},
'terminal.integrated.fontWeight': {
type: 'string',
enum: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'],
description: localize('terminal.integrated.fontWeight', "The font weight to use within the terminal for non-bold text."),
'anyOf': [
{
type: 'number',
minimum: MINIMUM_FONT_WEIGHT,
maximum: MAXIMUM_FONT_WEIGHT,
errorMessage: localize('terminal.integrated.fontWeightError', "Only \"normal\" and \"bold\" keywords or numbers between 1 and 1000 are allowed.")
},
{
type: 'string',
pattern: '^(normal|bold|1000|[1-9][0-9]{0,2})$'
},
{
enum: SUGGESTIONS_FONT_WEIGHT,
}
],
description: localize('terminal.integrated.fontWeight', "The font weight to use within the terminal for non-bold text. Accepts \"normal\" and \"bold\" keywords or numbers between 1 and 1000."),
default: 'normal'
},
'terminal.integrated.fontWeightBold': {
type: 'string',
enum: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'],
description: localize('terminal.integrated.fontWeightBold', "The font weight to use within the terminal for bold text."),
'anyOf': [
{
type: 'number',
minimum: MINIMUM_FONT_WEIGHT,
maximum: MAXIMUM_FONT_WEIGHT,
errorMessage: localize('terminal.integrated.fontWeightError', "Only \"normal\" and \"bold\" keywords or numbers between 1 and 1000 are allowed.")
},
{
type: 'string',
pattern: '^(normal|bold|1000|[1-9][0-9]{0,2})$'
},
{
enum: SUGGESTIONS_FONT_WEIGHT,
}
],
description: localize('terminal.integrated.fontWeightBold', "The font weight to use within the terminal for bold text. Accepts \"normal\" and \"bold\" keywords or numbers between 1 and 1000."),
default: 'bold'
},
'terminal.integrated.cursorBlinking': {

View File

@@ -46,11 +46,7 @@ export class TerminalNativeContribution extends Disposable implements IWorkbench
}
private _onOsResume(): void {
const activeTab = this._terminalService.getActiveTab();
if (!activeTab) {
return;
}
activeTab.terminalInstances.forEach(instance => instance.forceRedraw());
this._terminalService.terminalInstances.forEach(instance => instance.forceRedraw());
}
private async _onOpenFileRequest(request: INativeOpenFileRequest): Promise<void> {

View File

@@ -36,6 +36,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
private _titleInterval: NodeJS.Timer | null = null;
private _writeQueue: string[] = [];
private _writeTimeout: NodeJS.Timeout | undefined;
private _delayedResizer: DelayedResizer | undefined;
private readonly _initialCwd: string;
private readonly _ptyOptions: pty.IPtyForkOptions | pty.IWindowsPtyForkOptions;
@@ -80,6 +81,17 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
// This option will force conpty to not redraw the whole viewport on launch
conptyInheritCursor: useConpty && !!_shellLaunchConfig.initialText
};
// Delay resizes to avoid conpty not respecting very early resize calls
if (platform.isWindows && useConpty && cols === 0 && rows === 0 && this._shellLaunchConfig.executable?.endsWith('Git\\bin\\bash.exe')) {
this._delayedResizer = new DelayedResizer();
this._register(this._delayedResizer.onTrigger(dimensions => {
this._delayedResizer?.dispose();
this._delayedResizer = undefined;
if (dimensions.cols && dimensions.rows) {
this.resize(dimensions.cols, dimensions.rows);
}
}));
}
}
public async start(): Promise<ITerminalLaunchError | undefined> {
@@ -286,6 +298,14 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
if (this._ptyProcess) {
cols = Math.max(cols, 1);
rows = Math.max(rows, 1);
// Delay resize if needed
if (this._delayedResizer) {
this._delayedResizer.cols = cols;
this._delayedResizer.rows = rows;
return;
}
this._logService.trace('IPty#resize', cols, rows);
try {
this._ptyProcess.resize(cols, rows);
@@ -344,3 +364,32 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
return Promise.resolve(0);
}
}
/**
* Tracks the latest resize event to be trigger at a later point.
*/
class DelayedResizer extends Disposable {
public rows: number | undefined;
public cols: number | undefined;
private _timeout: NodeJS.Timeout;
private readonly _onTrigger = this._register(new Emitter<{ rows?: number, cols?: number }>());
public get onTrigger(): Event<{ rows?: number, cols?: number }> { return this._onTrigger.event; }
constructor() {
super();
this._timeout = setTimeout(() => {
this._onTrigger.fire({ rows: this.rows, cols: this.cols });
}, 1000);
this._register({
dispose: () => {
clearTimeout(this._timeout);
}
});
}
dispose(): void {
super.dispose();
clearTimeout(this._timeout);
}
}

View File

@@ -19,7 +19,9 @@ const unixLinks = [
'./foo',
'../foo',
'/foo/bar',
'foo/bar'
'/foo/bar+more',
'foo/bar',
'foo/bar+more',
];
const windowsLinks = [
@@ -33,10 +35,12 @@ const windowsLinks = [
'~/foo',
'c:/foo/bar',
'c:\\foo\\bar',
'c:\\foo\\bar+more',
'c:\\foo/bar\\baz',
'foo/bar',
'foo/bar',
'foo\\bar'
'foo\\bar',
'foo\\bar+more',
];
interface LinkFormatInfo {

View File

@@ -79,4 +79,13 @@ suite('Workbench - TerminalWordLinkProvider', () => {
{ range: [[5, 1], [7, 1]], text: 'bar' }
]);
});
test('should remove trailing colon in the link results', async () => {
await configurationService.setUserConfiguration('terminal', { integrated: { wordSeparators: ' ' } });
await assertLink('foo:5:6: bar:0:32:', [
{ range: [[1, 1], [7, 1]], text: 'foo:5:6' },
{ range: [[10, 1], [17, 1]], text: 'bar:0:32' }
]);
});
});

View File

@@ -7,13 +7,14 @@ import * as assert from 'assert';
import { Extensions as ThemeingExtensions, IColorRegistry, ColorIdentifier } from 'vs/platform/theme/common/colorRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
import { ansiColorIdentifiers, registerColors } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry';
import { IColorTheme, ThemeType } from 'vs/platform/theme/common/themeService';
import { IColorTheme } from 'vs/platform/theme/common/themeService';
import { Color } from 'vs/base/common/color';
import { ColorScheme } from 'vs/platform/theme/common/theme';
registerColors();
let themingRegistry = Registry.as<IColorRegistry>(ThemeingExtensions.ColorContribution);
function getMockTheme(type: ThemeType): IColorTheme {
function getMockTheme(type: ColorScheme): IColorTheme {
let theme = {
selector: '',
label: '',
@@ -30,7 +31,7 @@ function getMockTheme(type: ThemeType): IColorTheme {
suite('Workbench - TerminalColorRegistry', () => {
test('hc colors', function () {
let theme = getMockTheme('hc');
let theme = getMockTheme(ColorScheme.HIGH_CONTRAST);
let colors = ansiColorIdentifiers.map(colorId => Color.Format.CSS.formatHexA(theme.getColor(colorId)!, true));
assert.deepEqual(colors, [
@@ -55,7 +56,7 @@ suite('Workbench - TerminalColorRegistry', () => {
});
test('light colors', function () {
let theme = getMockTheme('light');
let theme = getMockTheme(ColorScheme.LIGHT);
let colors = ansiColorIdentifiers.map(colorId => Color.Format.CSS.formatHexA(theme.getColor(colorId)!, true));
assert.deepEqual(colors, [
@@ -80,7 +81,7 @@ suite('Workbench - TerminalColorRegistry', () => {
});
test('dark colors', function () {
let theme = getMockTheme('dark');
let theme = getMockTheme(ColorScheme.DARK);
let colors = ansiColorIdentifiers.map(colorId => Color.Format.CSS.formatHexA(theme.getColor(colorId)!, true));
assert.deepEqual(colors, [