Merge pull request #209294 from microsoft/tyriar/181900_3

Migrate rest of TerminalConfigHelper to TerminalConfigurationService
This commit is contained in:
Daniel Imms 2024-04-01 14:20:42 -07:00 committed by GitHub
commit 68746b09f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 481 additions and 576 deletions

View file

@ -29,6 +29,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { GroupIdentifier } from 'vs/workbench/common/editor';
import { ACTIVE_GROUP_TYPE, AUX_WINDOW_GROUP_TYPE, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService';
import type { ICurrentPartialCommand } from 'vs/platform/terminal/common/capabilities/commandDetection/terminalCommand';
import type { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private';
export const ITerminalService = createDecorator<ITerminalService>('terminalService');
export const ITerminalConfigurationService = createDecorator<ITerminalConfigurationService>('terminalConfigurationService');
@ -87,13 +88,6 @@ export interface ITerminalInstanceService {
didRegisterBackend(remoteAuthority?: string): void;
}
export interface ITerminalConfigHelper {
panelContainer: HTMLElement | undefined;
configFontIsMonospace(): boolean;
getFont(w: Window): ITerminalFont;
}
export const enum Direction {
Left = 0,
Right = 1,
@ -247,7 +241,6 @@ export interface ITerminalService extends ITerminalInstanceHost {
readonly instances: readonly ITerminalInstance[];
/** Gets detached terminal instances created via {@link createDetachedXterm}. */
readonly detachedInstances: Iterable<IDetachedTerminalInstance>;
readonly configHelper: ITerminalConfigHelper;
readonly defaultLocation: TerminalLocation;
readonly isProcessSupportRegistered: boolean;
@ -368,7 +361,9 @@ export interface ITerminalConfigurationService {
*/
readonly onConfigChanged: Event<void>;
// TODO: Expose xterm.js font metrics here
setPanelContainer(panelContainer: HTMLElement): void;
configFontIsMonospace(): boolean;
getFont(w: Window, xtermCore?: IXtermCore, excludeDimensions?: boolean): ITerminalFont;
}
export class TerminalLinkQuickPickEvent extends MouseEvent {

View file

@ -1,193 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Disposable } from 'vs/base/common/lifecycle';
import { isLinux } 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 { ITerminalConfigHelper, ITerminalConfigurationService, LinuxDistro } from 'vs/workbench/contrib/terminal/browser/terminal';
import { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private';
import { DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, ITerminalFont, MINIMUM_LETTER_SPACING } from 'vs/workbench/contrib/terminal/common/terminal';
const enum FontConstants {
MinimumFontSize = 6,
MaximumFontSize = 100,
}
/**
* Encapsulates terminal configuration logic, the primary purpose of this file is so that platform
* specific test cases can be written.
*/
export class TerminalConfigHelper extends Disposable implements ITerminalConfigHelper {
panelContainer: HTMLElement | undefined;
private _charMeasureElement: HTMLElement | undefined;
private _lastFontMeasurement: ITerminalFont | undefined;
protected _linuxDistro: LinuxDistro = LinuxDistro.Unknown;
constructor(
@IConfigurationService private readonly _configurationService: IConfigurationService,
@ITerminalConfigurationService private readonly _terminalConfigurationService: ITerminalConfigurationService,
) {
super();
if (isLinux) {
if (navigator.userAgent.includes('Ubuntu')) {
this._linuxDistro = LinuxDistro.Ubuntu;
} else if (navigator.userAgent.includes('Fedora')) {
this._linuxDistro = LinuxDistro.Fedora;
}
}
}
configFontIsMonospace(): boolean {
const fontSize = 15;
const fontFamily = this._terminalConfigurationService.config.fontFamily || this._configurationService.getValue<IEditorOptions>('editor').fontFamily || EDITOR_FONT_DEFAULTS.fontFamily;
const iRect = this._getBoundingRectFor('i', fontFamily, fontSize);
const wRect = this._getBoundingRectFor('w', fontFamily, fontSize);
// Check for invalid bounds, there is no reason to believe the font is not monospace
if (!iRect || !wRect || !iRect.width || !wRect.width) {
return true;
}
return iRect.width === wRect.width;
}
private _createCharMeasureElementIfNecessary(): HTMLElement {
if (!this.panelContainer) {
throw new Error('Cannot measure element when terminal is not attached');
}
// Create charMeasureElement if it hasn't been created or if it was orphaned by its parent
if (!this._charMeasureElement || !this._charMeasureElement.parentElement) {
this._charMeasureElement = document.createElement('div');
this.panelContainer.appendChild(this._charMeasureElement);
}
return this._charMeasureElement;
}
private _getBoundingRectFor(char: string, fontFamily: string, fontSize: number): ClientRect | DOMRect | undefined {
let charMeasureElement: HTMLElement;
try {
charMeasureElement = this._createCharMeasureElementIfNecessary();
} catch {
return undefined;
}
const style = charMeasureElement.style;
style.display = 'inline-block';
style.fontFamily = fontFamily;
style.fontSize = fontSize + 'px';
style.lineHeight = 'normal';
charMeasureElement.innerText = char;
const rect = charMeasureElement.getBoundingClientRect();
style.display = 'none';
return rect;
}
private _measureFont(w: Window, fontFamily: string, fontSize: number, letterSpacing: number, lineHeight: number): ITerminalFont {
const rect = this._getBoundingRectFor('X', fontFamily, fontSize);
// Bounding client rect was invalid, use last font measurement if available.
if (this._lastFontMeasurement && (!rect || !rect.width || !rect.height)) {
return this._lastFontMeasurement;
}
this._lastFontMeasurement = {
fontFamily,
fontSize,
letterSpacing,
lineHeight,
charWidth: 0,
charHeight: 0
};
if (rect && rect.width && rect.height) {
this._lastFontMeasurement.charHeight = Math.ceil(rect.height);
// Char width is calculated differently for DOM and the other renderer types. Refer to
// how each renderer updates their dimensions in xterm.js
if (this._terminalConfigurationService.config.gpuAcceleration === 'off') {
this._lastFontMeasurement.charWidth = rect.width;
} else {
const deviceCharWidth = Math.floor(rect.width * w.devicePixelRatio);
const deviceCellWidth = deviceCharWidth + Math.round(letterSpacing);
const cssCellWidth = deviceCellWidth / w.devicePixelRatio;
this._lastFontMeasurement.charWidth = cssCellWidth - Math.round(letterSpacing) / w.devicePixelRatio;
}
}
return this._lastFontMeasurement;
}
/**
* Gets the font information based on the terminal.integrated.fontFamily
* terminal.integrated.fontSize, terminal.integrated.lineHeight configuration properties
*/
getFont(w: Window, xtermCore?: IXtermCore, excludeDimensions?: boolean): ITerminalFont {
const editorConfig = this._configurationService.getValue<IEditorOptions>('editor');
let fontFamily = this._terminalConfigurationService.config.fontFamily || editorConfig.fontFamily || EDITOR_FONT_DEFAULTS.fontFamily;
let fontSize = this._clampInt(this._terminalConfigurationService.config.fontSize, FontConstants.MinimumFontSize, FontConstants.MaximumFontSize, EDITOR_FONT_DEFAULTS.fontSize);
// Work around bad font on Fedora/Ubuntu
if (!this._terminalConfigurationService.config.fontFamily) {
if (this._linuxDistro === LinuxDistro.Fedora) {
fontFamily = '\'DejaVu Sans Mono\'';
}
if (this._linuxDistro === LinuxDistro.Ubuntu) {
fontFamily = '\'Ubuntu Mono\'';
// Ubuntu mono is somehow smaller, so set fontSize a bit larger to get the same perceived size.
fontSize = this._clampInt(fontSize + 2, FontConstants.MinimumFontSize, FontConstants.MaximumFontSize, EDITOR_FONT_DEFAULTS.fontSize);
}
}
// Always fallback to monospace, otherwise a proportional font may become the default
fontFamily += ', monospace';
const letterSpacing = this._terminalConfigurationService.config.letterSpacing ? Math.max(Math.floor(this._terminalConfigurationService.config.letterSpacing), MINIMUM_LETTER_SPACING) : DEFAULT_LETTER_SPACING;
const lineHeight = this._terminalConfigurationService.config.lineHeight ? Math.max(this._terminalConfigurationService.config.lineHeight, 1) : DEFAULT_LINE_HEIGHT;
if (excludeDimensions) {
return {
fontFamily,
fontSize,
letterSpacing,
lineHeight
};
}
// Get the character dimensions from xterm if it's available
if (xtermCore?._renderService?._renderer.value) {
const cellDims = xtermCore._renderService.dimensions.css.cell;
if (cellDims?.width && cellDims?.height) {
return {
fontFamily,
fontSize,
letterSpacing,
lineHeight,
charHeight: cellDims.height / lineHeight,
charWidth: cellDims.width - Math.round(letterSpacing) / w.devicePixelRatio
};
}
}
// Fall back to measuring the font ourselves
return this._measureFont(w, fontFamily, fontSize, letterSpacing, lineHeight);
}
private _clampInt<T>(source: any, minimum: number, maximum: number, fallback: T): number | T {
let r = parseInt(source, 10);
if (isNaN(r)) {
return fallback;
}
if (typeof minimum === 'number') {
r = Math.max(minimum, r);
}
if (typeof maximum === 'number') {
r = Math.min(maximum, r);
}
return r;
}
}

View file

@ -4,14 +4,20 @@
*--------------------------------------------------------------------------------------------*/
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { EDITOR_FONT_DEFAULTS, type IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ITerminalConfigurationService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { DEFAULT_BOLD_FONT_WEIGHT, DEFAULT_FONT_WEIGHT, FontWeight, ITerminalConfiguration, MAXIMUM_FONT_WEIGHT, MINIMUM_FONT_WEIGHT, TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal';
import { ITerminalConfigurationService, LinuxDistro } from 'vs/workbench/contrib/terminal/browser/terminal';
import type { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private';
import { DEFAULT_BOLD_FONT_WEIGHT, DEFAULT_FONT_WEIGHT, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, FontWeight, ITerminalConfiguration, MAXIMUM_FONT_WEIGHT, MINIMUM_FONT_WEIGHT, MINIMUM_LETTER_SPACING, TERMINAL_CONFIG_SECTION, type ITerminalFont } from 'vs/workbench/contrib/terminal/common/terminal';
// #region TerminalConfigurationService
export class TerminalConfigurationService extends Disposable implements ITerminalConfigurationService {
declare _serviceBrand: undefined;
private _fontMetrics: TerminalFontMetrics;
private _config!: Readonly<ITerminalConfiguration>;
get config() { return this._config; }
@ -22,6 +28,9 @@ export class TerminalConfigurationService extends Disposable implements ITermina
@IConfigurationService private readonly _configurationService: IConfigurationService,
) {
super();
this._fontMetrics = this._register(new TerminalFontMetrics(this, _configurationService));
this._register(Event.runAndSubscribe(this._configurationService.onDidChangeConfiguration, e => {
if (!e || e.affectsConfiguration(TERMINAL_CONFIG_SECTION)) {
this._updateConfig();
@ -29,6 +38,10 @@ export class TerminalConfigurationService extends Disposable implements ITermina
}));
}
setPanelContainer(panelContainer: HTMLElement): void { return this._fontMetrics.setPanelContainer(panelContainer); }
configFontIsMonospace(): boolean { return this._fontMetrics.configFontIsMonospace(); }
getFont(w: Window, xtermCore?: IXtermCore, excludeDimensions?: boolean): ITerminalFont { return this._fontMetrics.getFont(w, xtermCore, excludeDimensions); }
private _updateConfig(): void {
const configValues = { ...this._configurationService.getValue<ITerminalConfiguration>(TERMINAL_CONFIG_SECTION) };
configValues.fontWeight = this._normalizeFontWeight(configValues.fontWeight, DEFAULT_FONT_WEIGHT);
@ -45,6 +58,174 @@ export class TerminalConfigurationService extends Disposable implements ITermina
}
}
// #endregion TerminalConfigurationService
// #region TerminalFontMetrics
const enum FontConstants {
MinimumFontSize = 6,
MaximumFontSize = 100,
}
class TerminalFontMetrics extends Disposable {
private _panelContainer: HTMLElement | undefined;
private _charMeasureElement: HTMLElement | undefined;
private _lastFontMeasurement: ITerminalFont | undefined;
protected _linuxDistro: LinuxDistro = LinuxDistro.Unknown;
constructor(
private readonly _terminalConfigurationService: ITerminalConfigurationService,
private readonly _configurationService: IConfigurationService,
) {
super();
this._register(toDisposable(() => this._charMeasureElement?.remove()));
}
setPanelContainer(panelContainer: HTMLElement): void {
this._panelContainer = panelContainer;
}
configFontIsMonospace(): boolean {
const fontSize = 15;
const fontFamily = this._terminalConfigurationService.config.fontFamily || this._configurationService.getValue<IEditorOptions>('editor').fontFamily || EDITOR_FONT_DEFAULTS.fontFamily;
const iRect = this._getBoundingRectFor('i', fontFamily, fontSize);
const wRect = this._getBoundingRectFor('w', fontFamily, fontSize);
// Check for invalid bounds, there is no reason to believe the font is not monospace
if (!iRect || !wRect || !iRect.width || !wRect.width) {
return true;
}
return iRect.width === wRect.width;
}
/**
* Gets the font information based on the terminal.integrated.fontFamily
* terminal.integrated.fontSize, terminal.integrated.lineHeight configuration properties
*/
getFont(w: Window, xtermCore?: IXtermCore, excludeDimensions?: boolean): ITerminalFont {
const editorConfig = this._configurationService.getValue<IEditorOptions>('editor');
let fontFamily = this._terminalConfigurationService.config.fontFamily || editorConfig.fontFamily || EDITOR_FONT_DEFAULTS.fontFamily;
let fontSize = clampInt(this._terminalConfigurationService.config.fontSize, FontConstants.MinimumFontSize, FontConstants.MaximumFontSize, EDITOR_FONT_DEFAULTS.fontSize);
// Work around bad font on Fedora/Ubuntu
if (!this._terminalConfigurationService.config.fontFamily) {
if (this._linuxDistro === LinuxDistro.Fedora) {
fontFamily = '\'DejaVu Sans Mono\'';
}
if (this._linuxDistro === LinuxDistro.Ubuntu) {
fontFamily = '\'Ubuntu Mono\'';
// Ubuntu mono is somehow smaller, so set fontSize a bit larger to get the same perceived size.
fontSize = clampInt(fontSize + 2, FontConstants.MinimumFontSize, FontConstants.MaximumFontSize, EDITOR_FONT_DEFAULTS.fontSize);
}
}
// Always fallback to monospace, otherwise a proportional font may become the default
fontFamily += ', monospace';
const letterSpacing = this._terminalConfigurationService.config.letterSpacing ? Math.max(Math.floor(this._terminalConfigurationService.config.letterSpacing), MINIMUM_LETTER_SPACING) : DEFAULT_LETTER_SPACING;
const lineHeight = this._terminalConfigurationService.config.lineHeight ? Math.max(this._terminalConfigurationService.config.lineHeight, 1) : DEFAULT_LINE_HEIGHT;
if (excludeDimensions) {
return {
fontFamily,
fontSize,
letterSpacing,
lineHeight
};
}
// Get the character dimensions from xterm if it's available
if (xtermCore?._renderService?._renderer.value) {
const cellDims = xtermCore._renderService.dimensions.css.cell;
if (cellDims?.width && cellDims?.height) {
return {
fontFamily,
fontSize,
letterSpacing,
lineHeight,
charHeight: cellDims.height / lineHeight,
charWidth: cellDims.width - Math.round(letterSpacing) / w.devicePixelRatio
};
}
}
// Fall back to measuring the font ourselves
return this._measureFont(w, fontFamily, fontSize, letterSpacing, lineHeight);
}
private _createCharMeasureElementIfNecessary(): HTMLElement {
if (!this._panelContainer) {
throw new Error('Cannot measure element when terminal is not attached');
}
// Create charMeasureElement if it hasn't been created or if it was orphaned by its parent
if (!this._charMeasureElement || !this._charMeasureElement.parentElement) {
this._charMeasureElement = document.createElement('div');
this._panelContainer.appendChild(this._charMeasureElement);
}
return this._charMeasureElement;
}
private _getBoundingRectFor(char: string, fontFamily: string, fontSize: number): ClientRect | DOMRect | undefined {
let charMeasureElement: HTMLElement;
try {
charMeasureElement = this._createCharMeasureElementIfNecessary();
} catch {
return undefined;
}
const style = charMeasureElement.style;
style.display = 'inline-block';
style.fontFamily = fontFamily;
style.fontSize = fontSize + 'px';
style.lineHeight = 'normal';
charMeasureElement.innerText = char;
const rect = charMeasureElement.getBoundingClientRect();
style.display = 'none';
return rect;
}
private _measureFont(w: Window, fontFamily: string, fontSize: number, letterSpacing: number, lineHeight: number): ITerminalFont {
const rect = this._getBoundingRectFor('X', fontFamily, fontSize);
// Bounding client rect was invalid, use last font measurement if available.
if (this._lastFontMeasurement && (!rect || !rect.width || !rect.height)) {
return this._lastFontMeasurement;
}
this._lastFontMeasurement = {
fontFamily,
fontSize,
letterSpacing,
lineHeight,
charWidth: 0,
charHeight: 0
};
if (rect && rect.width && rect.height) {
this._lastFontMeasurement.charHeight = Math.ceil(rect.height);
// Char width is calculated differently for DOM and the other renderer types. Refer to
// how each renderer updates their dimensions in xterm.js
if (this._terminalConfigurationService.config.gpuAcceleration === 'off') {
this._lastFontMeasurement.charWidth = rect.width;
} else {
const deviceCharWidth = Math.floor(rect.width * w.devicePixelRatio);
const deviceCellWidth = deviceCharWidth + Math.round(letterSpacing);
const cssCellWidth = deviceCellWidth / w.devicePixelRatio;
this._lastFontMeasurement.charWidth = cssCellWidth - Math.round(letterSpacing) / w.devicePixelRatio;
}
}
return this._lastFontMeasurement;
}
}
// #endregion TerminalFontMetrics
// #region Utils
function clampInt<T>(source: any, minimum: number, maximum: number, fallback: T): number | T {
let r = parseInt(source, 10);
@ -59,3 +240,5 @@ function clampInt<T>(source: any, minimum: number, maximum: number, fallback: T)
}
return r;
}
// #endregion Utils

View file

@ -9,7 +9,7 @@ import { IDisposable, Disposable, DisposableStore, dispose, toDisposable } from
import { SplitView, Orientation, IView, Sizing } from 'vs/base/browser/ui/splitview/splitview';
import { IWorkbenchLayoutService, Position } from 'vs/workbench/services/layout/browser/layoutService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ITerminalInstance, Direction, ITerminalGroup, ITerminalService, ITerminalInstanceService, ITerminalConfigurationService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { ITerminalInstance, Direction, ITerminalGroup, ITerminalInstanceService, ITerminalConfigurationService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views';
import { IShellLaunchConfig, ITerminalTabLayoutInfoById, TerminalLocation } from 'vs/platform/terminal/common/terminal';
import { TerminalStatus } from 'vs/workbench/contrib/terminal/browser/terminalStatusList';
@ -272,7 +272,6 @@ export class TerminalGroup extends Disposable implements ITerminalGroup {
constructor(
private _container: HTMLElement | undefined,
shellLaunchConfigOrInstance: IShellLaunchConfig | ITerminalInstance | undefined,
@ITerminalService private readonly _terminalService: ITerminalService,
@ITerminalConfigurationService private readonly _terminalConfigurationService: ITerminalConfigurationService,
@ITerminalInstanceService private readonly _terminalInstanceService: ITerminalInstanceService,
@IWorkbenchLayoutService private readonly _layoutService: IWorkbenchLayoutService,
@ -580,7 +579,7 @@ export class TerminalGroup extends Disposable implements ITerminalGroup {
(isHorizontalResize && groupOrientation === Orientation.VERTICAL) ||
(!isHorizontalResize && groupOrientation === Orientation.HORIZONTAL);
const font = this._terminalService.configHelper.getFont(getWindow(this._groupElement));
const font = this._terminalConfigurationService.getFont(getWindow(this._groupElement));
// TODO: Support letter spacing and line height
const charSize = (isHorizontalResize ? font.charWidth : font.charHeight);

View file

@ -60,7 +60,6 @@ import { IViewsService } from 'vs/workbench/services/views/common/viewsService';
import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration';
import { IRequestAddInstanceToGroupEvent, ITerminalConfigurationService, ITerminalContribution, ITerminalInstance, IXtermColorProvider, TerminalDataTransfers } from 'vs/workbench/contrib/terminal/browser/terminal';
import { TerminalLaunchHelpAction } from 'vs/workbench/contrib/terminal/browser/terminalActions';
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
import { TerminalEditorInput } from 'vs/workbench/contrib/terminal/browser/terminalEditorInput';
import { TerminalExtensionsRegistry } from 'vs/workbench/contrib/terminal/browser/terminalExtensions';
import { getColorClass, createColorStyleElement, getStandardColors } from 'vs/workbench/contrib/terminal/browser/terminalIcon';
@ -339,7 +338,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
constructor(
private readonly _terminalShellTypeContextKey: IContextKey<string>,
private readonly _terminalInRunCommandPicker: IContextKey<boolean>,
private readonly _configHelper: TerminalConfigHelper,
private _shellLaunchConfig: IShellLaunchConfig,
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
@IInstantiationService instantiationService: IInstantiationService,
@ -649,7 +647,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
return null;
}
const font = this.xterm ? this.xterm.getFont() : this._configHelper.getFont(dom.getWindow(this.domElement));
const font = this.xterm ? this.xterm.getFont() : this._terminalConfigurationService.getFont(dom.getWindow(this.domElement));
const newRC = getXtermScaledDimensions(dom.getWindow(this.domElement), font, dimension.width, dimension.height);
if (!newRC) {
this._setLastKnownColsAndRows();
@ -679,7 +677,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
private _getDimension(width: number, height: number): ICanvasDimensions | undefined {
// The font needs to have been initialized
const font = this.xterm ? this.xterm.getFont() : this._configHelper.getFont(dom.getWindow(this.domElement));
const font = this.xterm ? this.xterm.getFont() : this._terminalConfigurationService.getFont(dom.getWindow(this.domElement));
if (!font || !font.charWidth || !font.charHeight) {
return undefined;
}
@ -727,7 +725,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
const xterm = this._scopedInstantiationService.createInstance(
XtermTerminal,
Terminal,
this._configHelper,
this._cols,
this._rows,
this._scopedInstantiationService.createInstance(TerminalInstanceColorProvider, this),
@ -1999,7 +1996,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
this._initDimensions();
await this._resize();
} else {
const font = this.xterm ? this.xterm.getFont() : this._configHelper.getFont(dom.getWindow(this.domElement));
const font = this.xterm ? this.xterm.getFont() : this._terminalConfigurationService.getFont(dom.getWindow(this.domElement));
const maxColsForTexture = Math.floor(Constants.MaxCanvasWidth / (font.charWidth ?? 20));
// Fixed columns should be at least xterm.js' regular column count
const proposedCols = Math.max(this.maxCols, Math.min(this.xterm.getLongestViewportWrappedLineLength(), maxColsForTexture));
@ -2022,7 +2019,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
}
private async _addScrollbar(): Promise<void> {
const charWidth = (this.xterm ? this.xterm.getFont() : this._configHelper.getFont(dom.getWindow(this.domElement))).charWidth;
const charWidth = (this.xterm ? this.xterm.getFont() : this._terminalConfigurationService.getFont(dom.getWindow(this.domElement))).charWidth;
if (!this.xterm?.raw.element || !this._container || !charWidth || !this._fixedCols) {
return;
}

View file

@ -10,7 +10,6 @@ import { IShellLaunchConfig, ITerminalBackend, ITerminalBackendRegistry, ITermin
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminalInstance';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
import { URI } from 'vs/base/common/uri';
import { Emitter, Event } from 'vs/base/common/event';
import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey';
@ -22,7 +21,6 @@ export class TerminalInstanceService extends Disposable implements ITerminalInst
declare _serviceBrand: undefined;
private _terminalShellTypeContextKey: IContextKey<string>;
private _terminalInRunCommandPicker: IContextKey<boolean>;
private _configHelper: TerminalConfigHelper;
private _backendRegistration = new Map<string | undefined, { promise: Promise<void>; resolve: () => void }>();
private readonly _onDidCreateInstance = this._register(new Emitter<ITerminalInstance>());
@ -36,7 +34,6 @@ export class TerminalInstanceService extends Disposable implements ITerminalInst
super();
this._terminalShellTypeContextKey = TerminalContextKeys.shellType.bindTo(this._contextKeyService);
this._terminalInRunCommandPicker = TerminalContextKeys.inTerminalRunCommandPicker.bindTo(this._contextKeyService);
this._configHelper = _instantiationService.createInstance(TerminalConfigHelper);
for (const remoteAuthority of [undefined, _environmentService.remoteAuthority]) {
const { promise, resolve } = promiseWithResolvers<void>();
@ -51,7 +48,6 @@ export class TerminalInstanceService extends Disposable implements ITerminalInst
const instance = this._instantiationService.createInstance(TerminalInstance,
this._terminalShellTypeContextKey,
this._terminalInRunCommandPicker,
this._configHelper,
shellLaunchConfig
);
instance.target = target;

View file

@ -30,9 +30,8 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
import { VirtualWorkspaceContext } from 'vs/workbench/common/contextkeys';
import { IEditableData } from 'vs/workbench/common/views';
import { IViewsService } from 'vs/workbench/services/views/common/viewsService';
import { ICreateTerminalOptions, IDetachedTerminalInstance, IDetachedXTermOptions, IRequestAddInstanceToGroupEvent, ITerminalConfigHelper, ITerminalConfigurationService, ITerminalEditorService, ITerminalGroup, ITerminalGroupService, ITerminalInstance, ITerminalInstanceHost, ITerminalInstanceService, ITerminalLocationOptions, ITerminalService, ITerminalServiceNativeDelegate, TerminalConnectionState, TerminalEditorLocation } from 'vs/workbench/contrib/terminal/browser/terminal';
import { ICreateTerminalOptions, IDetachedTerminalInstance, IDetachedXTermOptions, IRequestAddInstanceToGroupEvent, ITerminalConfigurationService, ITerminalEditorService, ITerminalGroup, ITerminalGroupService, ITerminalInstance, ITerminalInstanceHost, ITerminalInstanceService, ITerminalLocationOptions, ITerminalService, ITerminalServiceNativeDelegate, TerminalConnectionState, TerminalEditorLocation } from 'vs/workbench/contrib/terminal/browser/terminal';
import { getCwdForSplit } from 'vs/workbench/contrib/terminal/browser/terminalActions';
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
import { TerminalEditorInput } from 'vs/workbench/contrib/terminal/browser/terminalEditorInput';
import { getColorStyleContent, getUriClasses } from 'vs/workbench/contrib/terminal/browser/terminalIcon';
import { TerminalProfileQuickpick } from 'vs/workbench/contrib/terminal/browser/terminalProfileQuickpick';
@ -76,7 +75,6 @@ export class TerminalService extends Disposable implements ITerminalService {
private _primaryBackend?: ITerminalBackend;
private _terminalHasBeenCreated: IContextKey<boolean>;
private _terminalCountContextKey: IContextKey<number>;
private _configHelper: TerminalConfigHelper;
private _nativeDelegate?: ITerminalServiceNativeDelegate;
private _shutdownWindowCount?: number;
@ -93,7 +91,6 @@ export class TerminalService extends Disposable implements ITerminalService {
private _restoredGroupCount: number = 0;
get restoredGroupCount(): number { return this._restoredGroupCount; }
get configHelper(): ITerminalConfigHelper { return this._configHelper; }
get instances(): ITerminalInstance[] {
return this._terminalGroupService.instances.concat(this._terminalEditorService.instances);
}
@ -190,7 +187,6 @@ export class TerminalService extends Disposable implements ITerminalService {
) {
super();
this._configHelper = this._register(this._instantiationService.createInstance(TerminalConfigHelper));
// the below avoids having to poll routinely.
// we update detected profiles when an instance is created so that,
// for example, we detect if you've installed a pwsh
@ -1020,7 +1016,6 @@ export class TerminalService extends Disposable implements ITerminalService {
const xterm = this._instantiationService.createInstance(
XtermTerminal,
ctor,
this._configHelper,
options.cols,
options.rows,
options.colorProvider,
@ -1178,7 +1173,7 @@ export class TerminalService extends Disposable implements ITerminalService {
}
async setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): Promise<void> {
this._configHelper.panelContainer = panelContainer;
this._terminalConfigurationService.setPanelContainer(panelContainer);
this._terminalGroupService.setContainer(terminalContainer);
}

View file

@ -68,6 +68,7 @@ export class TerminalViewPane extends ViewPane {
@IContextMenuService private readonly _contextMenuService: IContextMenuService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@ITerminalService private readonly _terminalService: ITerminalService,
@ITerminalConfigurationService private readonly _terminalConfigurationService: ITerminalConfigurationService,
@ITerminalGroupService private readonly _terminalGroupService: ITerminalGroupService,
@IThemeService themeService: IThemeService,
@ITelemetryService telemetryService: ITelemetryService,
@ -191,8 +192,7 @@ export class TerminalViewPane extends ViewPane {
this._register(this.configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(TerminalSettingId.FontFamily) || e.affectsConfiguration('editor.fontFamily')) {
const configHelper = this._terminalService.configHelper;
if (!configHelper.configFontIsMonospace()) {
if (!this._terminalConfigurationService.configFontIsMonospace()) {
const choices: IPromptChoice[] = [{
label: nls.localize('terminal.useMonospace', "Use 'monospace'"),
run: () => this.configurationService.updateValue(TerminalSettingId.FontFamily, 'monospace'),

View file

@ -13,7 +13,6 @@ import type { ImageAddon as ImageAddonType } from '@xterm/addon-image';
import * as dom from 'vs/base/browser/dom';
import { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { IShellIntegration, ITerminalLogService, TerminalSettingId } from 'vs/platform/terminal/common/terminal';
@ -180,7 +179,6 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach
*/
constructor(
xtermCtor: typeof RawXtermTerminal,
private readonly _configHelper: TerminalConfigHelper,
cols: number,
rows: number,
private readonly _xtermColorProvider: IXtermColorProvider,
@ -200,7 +198,7 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach
@ILayoutService layoutService: ILayoutService
) {
super();
const font = this._configHelper.getFont(dom.getActiveWindow(), undefined, true);
const font = this._terminalConfigurationService.getFont(dom.getActiveWindow(), undefined, true);
const config = this._terminalConfigurationService.config;
const editorOptions = this._configurationService.getValue<IEditorOptions>('editor');
@ -495,7 +493,7 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach
}
getFont(): ITerminalFont {
return this._configHelper.getFont(dom.getWindow(this.raw.element), this._core);
return this._terminalConfigurationService.getFont(dom.getWindow(this.raw.element), this._core);
}
getLongestViewportWrappedLineLength(): number {

View file

@ -1,283 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
import { EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { LinuxDistro } from 'vs/workbench/contrib/terminal/browser/terminal';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
import { mainWindow } from 'vs/base/browser/window';
import { getActiveWindow } from 'vs/base/browser/dom';
import { TerminalConfigurationService } from 'vs/workbench/contrib/terminal/browser/terminalConfigurationService';
class TestTerminalConfigHelper extends TerminalConfigHelper {
set linuxDistro(distro: LinuxDistro) {
this._linuxDistro = distro;
}
}
suite('Workbench - TerminalConfigHelper', function () {
let fixture: HTMLElement;
// This suite has retries setup because the font-related tests flake only on GitHub actions, not
// ADO. It seems Electron hangs for some reason only on GH actions, so the two options are to
// retry or remove the test outright (which would drop coverage).
this.retries(3);
setup(() => {
fixture = mainWindow.document.body;
});
const store = ensureNoDisposablesAreLeakedInTestSuite();
test('TerminalConfigHelper - getFont fontFamily', () => {
const configurationService = new TestConfigurationService({
editor: { fontFamily: 'foo' },
terminal: { integrated: { fontFamily: 'bar' } }
});
const configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.getFont(getActiveWindow()).fontFamily, 'bar, monospace', 'terminal.integrated.fontFamily should be selected over editor.fontFamily');
});
test('TerminalConfigHelper - getFont fontFamily (Linux Fedora)', () => {
const configurationService = new TestConfigurationService({
editor: { fontFamily: 'foo' },
terminal: { integrated: { fontFamily: null } }
});
const configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.linuxDistro = LinuxDistro.Fedora;
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.getFont(getActiveWindow()).fontFamily, '\'DejaVu Sans Mono\', monospace', 'Fedora should have its font overridden when terminal.integrated.fontFamily not set');
});
test('TerminalConfigHelper - getFont fontFamily (Linux Ubuntu)', () => {
const configurationService = new TestConfigurationService({
editor: { fontFamily: 'foo' },
terminal: { integrated: { fontFamily: null } }
});
const configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.linuxDistro = LinuxDistro.Ubuntu;
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.getFont(getActiveWindow()).fontFamily, '\'Ubuntu Mono\', monospace', 'Ubuntu should have its font overridden when terminal.integrated.fontFamily not set');
});
test('TerminalConfigHelper - getFont fontFamily (Linux Unknown)', () => {
const configurationService = new TestConfigurationService({
editor: { fontFamily: 'foo' },
terminal: { integrated: { fontFamily: null } }
});
const configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.getFont(getActiveWindow()).fontFamily, 'foo, monospace', 'editor.fontFamily should be the fallback when terminal.integrated.fontFamily not set');
});
test('TerminalConfigHelper - getFont fontSize 10', () => {
const configurationService = new TestConfigurationService({
editor: {
fontFamily: 'foo',
fontSize: 9
},
terminal: {
integrated: {
fontFamily: 'bar',
fontSize: 10
}
}
});
const configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.getFont(getActiveWindow()).fontSize, 10, 'terminal.integrated.fontSize should be selected over editor.fontSize');
});
test('TerminalConfigHelper - getFont fontSize 0', () => {
const configurationService = new TestConfigurationService({
editor: {
fontFamily: 'foo'
},
terminal: {
integrated: {
fontFamily: null,
fontSize: 0
}
}
});
let configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.linuxDistro = LinuxDistro.Ubuntu;
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.getFont(getActiveWindow()).fontSize, 8, 'The minimum terminal font size (with adjustment) should be used when terminal.integrated.fontSize less than it');
configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.getFont(getActiveWindow()).fontSize, 6, 'The minimum terminal font size should be used when terminal.integrated.fontSize less than it');
});
test('TerminalConfigHelper - getFont fontSize 1500', () => {
const configurationService = new TestConfigurationService({
editor: {
fontFamily: 'foo'
},
terminal: {
integrated: {
fontFamily: 0,
fontSize: 1500
}
}
});
const configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.getFont(getActiveWindow()).fontSize, 100, 'The maximum terminal font size should be used when terminal.integrated.fontSize more than it');
});
test('TerminalConfigHelper - getFont fontSize null', () => {
const configurationService = new TestConfigurationService({
editor: {
fontFamily: 'foo'
},
terminal: {
integrated: {
fontFamily: 0,
fontSize: null
}
}
});
let configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.linuxDistro = LinuxDistro.Ubuntu;
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.getFont(getActiveWindow()).fontSize, EDITOR_FONT_DEFAULTS.fontSize + 2, 'The default editor font size (with adjustment) should be used when terminal.integrated.fontSize is not set');
configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.getFont(getActiveWindow()).fontSize, EDITOR_FONT_DEFAULTS.fontSize, 'The default editor font size should be used when terminal.integrated.fontSize is not set');
});
test('TerminalConfigHelper - getFont lineHeight 2', () => {
const configurationService = new TestConfigurationService({
editor: {
fontFamily: 'foo',
lineHeight: 1
},
terminal: {
integrated: {
fontFamily: 0,
lineHeight: 2
}
}
});
const configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.getFont(getActiveWindow()).lineHeight, 2, 'terminal.integrated.lineHeight should be selected over editor.lineHeight');
});
test('TerminalConfigHelper - getFont lineHeight 0', () => {
const configurationService = new TestConfigurationService({
editor: {
fontFamily: 'foo',
lineHeight: 1
},
terminal: {
integrated: {
fontFamily: 0,
lineHeight: 0
}
}
});
const configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.getFont(getActiveWindow()).lineHeight, 1, 'editor.lineHeight should be 1 when terminal.integrated.lineHeight not set');
});
test('TerminalConfigHelper - isMonospace monospace', () => {
const configurationService = new TestConfigurationService({
terminal: {
integrated: {
fontFamily: 'monospace'
}
}
});
const configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.configFontIsMonospace(), true, 'monospace is monospaced');
});
test('TerminalConfigHelper - isMonospace sans-serif', () => {
const configurationService = new TestConfigurationService({
terminal: {
integrated: {
fontFamily: 'sans-serif'
}
}
});
const configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.configFontIsMonospace(), false, 'sans-serif is not monospaced');
});
test('TerminalConfigHelper - isMonospace serif', () => {
const configurationService = new TestConfigurationService({
terminal: {
integrated: {
fontFamily: 'serif'
}
}
});
const configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.configFontIsMonospace(), false, 'serif is not monospaced');
});
test('TerminalConfigHelper - isMonospace monospace falls back to editor.fontFamily', () => {
const configurationService = new TestConfigurationService({
editor: {
fontFamily: 'monospace'
},
terminal: {
integrated: {
fontFamily: null
}
}
});
const configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.configFontIsMonospace(), true, 'monospace is monospaced');
});
test('TerminalConfigHelper - isMonospace sans-serif falls back to editor.fontFamily', () => {
const configurationService = new TestConfigurationService({
editor: {
fontFamily: 'sans-serif'
},
terminal: {
integrated: {
fontFamily: null
}
}
});
const configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.configFontIsMonospace(), false, 'sans-serif is not monospaced');
});
test('TerminalConfigHelper - isMonospace serif falls back to editor.fontFamily', () => {
const configurationService = new TestConfigurationService({
editor: {
fontFamily: 'serif'
},
terminal: {
integrated: {
fontFamily: null
}
}
});
const configHelper = store.add(new TestTerminalConfigHelper(configurationService, store.add(new TerminalConfigurationService(configurationService))));
configHelper.panelContainer = fixture;
assert.strictEqual(configHelper.configFontIsMonospace(), false, 'serif is not monospaced');
});
});

View file

@ -3,12 +3,15 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { notStrictEqual } from 'assert';
import { notStrictEqual, strictEqual } from 'assert';
import { getActiveWindow } from 'vs/base/browser/dom';
import { mainWindow } from 'vs/base/browser/window';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
import { EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions';
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import type { ITerminalConfigurationService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { ITerminalConfigurationService, LinuxDistro } from 'vs/workbench/contrib/terminal/browser/terminal';
import { TerminalConfigurationService } from 'vs/workbench/contrib/terminal/browser/terminalConfigurationService';
@ -51,4 +54,247 @@ suite('Workbench - TerminalConfigurationService', () => {
});
});
});
function createTerminalConfigationService(config: any, linuxDistro?: LinuxDistro): ITerminalConfigurationService {
const instantiationService = new TestInstantiationService();
instantiationService.set(IConfigurationService, new TestConfigurationService(config));
const terminalConfigurationService = store.add(instantiationService.createInstance(TerminalConfigurationService));
instantiationService.set(ITerminalConfigurationService, terminalConfigurationService);
terminalConfigurationService.setPanelContainer(mainWindow.document.body);
if (linuxDistro) {
(terminalConfigurationService as any)._fontMetrics._linuxDistro = linuxDistro;
}
return terminalConfigurationService;
}
suite('getFont', () => {
test('fontFamily', () => {
const terminalConfigurationService = createTerminalConfigationService({
editor: { fontFamily: 'foo' },
terminal: { integrated: { fontFamily: 'bar' } }
});
strictEqual(terminalConfigurationService.getFont(getActiveWindow()).fontFamily, 'bar, monospace', 'terminal.integrated.fontFamily should be selected over editor.fontFamily');
});
test('fontFamily (Linux Fedora)', () => {
const terminalConfigurationService = createTerminalConfigationService({
editor: { fontFamily: 'foo' },
terminal: { integrated: { fontFamily: null } }
}, LinuxDistro.Fedora);
strictEqual(terminalConfigurationService.getFont(getActiveWindow()).fontFamily, '\'DejaVu Sans Mono\', monospace', 'Fedora should have its font overridden when terminal.integrated.fontFamily not set');
});
test('fontFamily (Linux Ubuntu)', () => {
const terminalConfigurationService = createTerminalConfigationService({
editor: { fontFamily: 'foo' },
terminal: { integrated: { fontFamily: null } }
}, LinuxDistro.Ubuntu);
strictEqual(terminalConfigurationService.getFont(getActiveWindow()).fontFamily, '\'Ubuntu Mono\', monospace', 'Ubuntu should have its font overridden when terminal.integrated.fontFamily not set');
});
test('fontFamily (Linux Unknown)', () => {
const terminalConfigurationService = createTerminalConfigationService({
editor: { fontFamily: 'foo' },
terminal: { integrated: { fontFamily: null } }
});
strictEqual(terminalConfigurationService.getFont(getActiveWindow()).fontFamily, 'foo, monospace', 'editor.fontFamily should be the fallback when terminal.integrated.fontFamily not set');
});
test('fontSize 10', () => {
const terminalConfigurationService = createTerminalConfigationService({
editor: {
fontFamily: 'foo',
fontSize: 9
},
terminal: {
integrated: {
fontFamily: 'bar',
fontSize: 10
}
}
});
strictEqual(terminalConfigurationService.getFont(getActiveWindow()).fontSize, 10, 'terminal.integrated.fontSize should be selected over editor.fontSize');
});
test('fontSize 0', () => {
let terminalConfigurationService = createTerminalConfigationService({
editor: {
fontFamily: 'foo'
},
terminal: {
integrated: {
fontFamily: null,
fontSize: 0
}
}
}, LinuxDistro.Ubuntu);
strictEqual(terminalConfigurationService.getFont(getActiveWindow()).fontSize, 8, 'The minimum terminal font size (with adjustment) should be used when terminal.integrated.fontSize less than it');
terminalConfigurationService = createTerminalConfigationService({
editor: {
fontFamily: 'foo'
},
terminal: {
integrated: {
fontFamily: null,
fontSize: 0
}
}
});
strictEqual(terminalConfigurationService.getFont(getActiveWindow()).fontSize, 6, 'The minimum terminal font size should be used when terminal.integrated.fontSize less than it');
});
test('fontSize 1500', () => {
const terminalConfigurationService = createTerminalConfigationService({
editor: {
fontFamily: 'foo'
},
terminal: {
integrated: {
fontFamily: 0,
fontSize: 1500
}
}
});
strictEqual(terminalConfigurationService.getFont(getActiveWindow()).fontSize, 100, 'The maximum terminal font size should be used when terminal.integrated.fontSize more than it');
});
test('fontSize null', () => {
let terminalConfigurationService = createTerminalConfigationService({
editor: {
fontFamily: 'foo'
},
terminal: {
integrated: {
fontFamily: 0,
fontSize: null
}
}
}, LinuxDistro.Ubuntu);
strictEqual(terminalConfigurationService.getFont(getActiveWindow()).fontSize, EDITOR_FONT_DEFAULTS.fontSize + 2, 'The default editor font size (with adjustment) should be used when terminal.integrated.fontSize is not set');
terminalConfigurationService = createTerminalConfigationService({
editor: {
fontFamily: 'foo'
},
terminal: {
integrated: {
fontFamily: 0,
fontSize: null
}
}
});
strictEqual(terminalConfigurationService.getFont(getActiveWindow()).fontSize, EDITOR_FONT_DEFAULTS.fontSize, 'The default editor font size should be used when terminal.integrated.fontSize is not set');
});
test('lineHeight 2', () => {
const terminalConfigurationService = createTerminalConfigationService({
editor: {
fontFamily: 'foo',
lineHeight: 1
},
terminal: {
integrated: {
fontFamily: 0,
lineHeight: 2
}
}
});
strictEqual(terminalConfigurationService.getFont(getActiveWindow()).lineHeight, 2, 'terminal.integrated.lineHeight should be selected over editor.lineHeight');
});
test('lineHeight 0', () => {
const terminalConfigurationService = createTerminalConfigationService({
editor: {
fontFamily: 'foo',
lineHeight: 1
},
terminal: {
integrated: {
fontFamily: 0,
lineHeight: 0
}
}
});
strictEqual(terminalConfigurationService.getFont(getActiveWindow()).lineHeight, 1, 'editor.lineHeight should be 1 when terminal.integrated.lineHeight not set');
});
});
suite('configFontIsMonospace', () => {
test('isMonospace monospace', () => {
const terminalConfigurationService = createTerminalConfigationService({
terminal: {
integrated: {
fontFamily: 'monospace'
}
}
});
strictEqual(terminalConfigurationService.configFontIsMonospace(), true, 'monospace is monospaced');
});
test('isMonospace sans-serif', () => {
const terminalConfigurationService = createTerminalConfigationService({
terminal: {
integrated: {
fontFamily: 'sans-serif'
}
}
});
strictEqual(terminalConfigurationService.configFontIsMonospace(), false, 'sans-serif is not monospaced');
});
test('isMonospace serif', () => {
const terminalConfigurationService = createTerminalConfigationService({
terminal: {
integrated: {
fontFamily: 'serif'
}
}
});
strictEqual(terminalConfigurationService.configFontIsMonospace(), false, 'serif is not monospaced');
});
test('isMonospace monospace falls back to editor.fontFamily', () => {
const terminalConfigurationService = createTerminalConfigationService({
editor: {
fontFamily: 'monospace'
},
terminal: {
integrated: {
fontFamily: null
}
}
});
strictEqual(terminalConfigurationService.configFontIsMonospace(), true, 'monospace is monospaced');
});
test('isMonospace sans-serif falls back to editor.fontFamily', () => {
const terminalConfigurationService = createTerminalConfigationService({
editor: {
fontFamily: 'sans-serif'
},
terminal: {
integrated: {
fontFamily: null
}
}
});
strictEqual(terminalConfigurationService.configFontIsMonospace(), false, 'sans-serif is not monospaced');
});
test('isMonospace serif falls back to editor.fontFamily', () => {
const terminalConfigurationService = createTerminalConfigationService({
editor: {
fontFamily: 'serif'
},
terminal: {
integrated: {
fontFamily: null
}
}
});
strictEqual(terminalConfigurationService.configFontIsMonospace(), false, 'serif is not monospaced');
});
});
});

View file

@ -12,7 +12,7 @@ import { TestInstantiationService } from 'vs/platform/instantiation/test/common/
import { TestContextService } from 'vs/workbench/test/common/workbenchTestServices';
import { fixPath, getUri } from 'vs/workbench/services/search/test/browser/queryBuilder.test';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { ITerminalInstance, type ITerminalConfigurationService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { ITerminalConfigurationService, ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal';
import { ProcessState } from 'vs/workbench/contrib/terminal/common/terminal';
import { URI } from 'vs/base/common/uri';
import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore';
@ -20,8 +20,9 @@ import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/cap
import { Schemas } from 'vs/base/common/network';
import { TestFileService } from 'vs/workbench/test/browser/workbenchTestServices';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { TerminalConfigurationService } from 'vs/workbench/contrib/terminal/browser/terminalConfigurationService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IFileService } from 'vs/platform/files/common/files';
const root1 = '/foo/root1';
const ROOT_1 = fixPath(root1);
@ -31,7 +32,7 @@ const emptyRoot = '/foo';
const ROOT_EMPTY = fixPath(emptyRoot);
suite('Workbench - TerminalInstance', () => {
ensureNoDisposablesAreLeakedInTestSuite();
const store = ensureNoDisposablesAreLeakedInTestSuite();
suite('parseExitResult', () => {
test('should return no message for exit code = undefined', () => {
@ -140,8 +141,6 @@ suite('Workbench - TerminalInstance', () => {
});
});
suite('TerminalLabelComputer', () => {
let store: DisposableStore;
let configurationService: TestConfigurationService;
let terminalLabelComputer: TerminalLabelComputer;
let instantiationService: TestInstantiationService;
let mockContextService: TestContextService;
@ -151,7 +150,6 @@ suite('Workbench - TerminalInstance', () => {
let mockMultiRootWorkspace: Workspace;
let emptyWorkspace: Workspace;
let capabilities: TerminalCapabilityStore;
let terminalConfigService: ITerminalConfigurationService;
function createInstance(partial?: Partial<ITerminalInstance>): Pick<ITerminalInstance, 'shellLaunchConfig' | 'userHome' | 'cwd' | 'initialCwd' | 'processName' | 'sequence' | 'workspaceFolder' | 'staticTitle' | 'capabilities' | 'title' | 'description'> {
const capabilities = store.add(new TerminalCapabilityStore());
@ -175,9 +173,10 @@ suite('Workbench - TerminalInstance', () => {
}
setup(async () => {
store = new DisposableStore();
instantiationService = store.add(new TestInstantiationService());
instantiationService.stub(IWorkspaceContextService, new TestContextService());
instantiationService.set(IWorkspaceContextService, new TestContextService());
instantiationService.set(IFileService, new TestFileService());
instantiationService.set(IWorkspaceContextService, mockContextService);
capabilities = store.add(new TerminalCapabilityStore());
if (!isWindows) {
capabilities.add(TerminalCapability.NaiveCwdDetection, null!);
@ -199,12 +198,14 @@ suite('Workbench - TerminalInstance', () => {
emptyContextService.setWorkspace(emptyWorkspace);
});
teardown(() => store.dispose());
function createLabelComputer(configuration: any) {
instantiationService.set(IConfigurationService, new TestConfigurationService(configuration));
instantiationService.set(ITerminalConfigurationService, store.add(instantiationService.createInstance(TerminalConfigurationService)));
return store.add(instantiationService.createInstance(TerminalLabelComputer));
}
test('should resolve to "" when the template variables are empty', () => {
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' - ', title: '', description: '' } } } });
terminalConfigService = store.add(new TerminalConfigurationService(configurationService));
terminalLabelComputer = store.add(new TerminalLabelComputer(new TestFileService(), terminalConfigService, mockContextService));
terminalLabelComputer = createLabelComputer({ terminal: { integrated: { tabs: { separator: ' - ', title: '', description: '' } } } });
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: '' }));
// TODO:
// terminalLabelComputer.onLabelChanged(e => {
@ -215,81 +216,60 @@ suite('Workbench - TerminalInstance', () => {
strictEqual(terminalLabelComputer.description, '');
});
test('should resolve cwd', () => {
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' - ', title: '${cwd}', description: '${cwd}' } } } });
terminalConfigService = store.add(new TerminalConfigurationService(configurationService));
terminalLabelComputer = store.add(new TerminalLabelComputer(new TestFileService(), terminalConfigService, mockContextService));
terminalLabelComputer = createLabelComputer({ terminal: { integrated: { tabs: { separator: ' - ', title: '${cwd}', description: '${cwd}' } } } });
terminalLabelComputer.refreshLabel(createInstance({ capabilities, cwd: ROOT_1 }));
strictEqual(terminalLabelComputer.title, ROOT_1);
strictEqual(terminalLabelComputer.description, ROOT_1);
});
test('should resolve workspaceFolder', () => {
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' - ', title: '${workspaceFolder}', description: '${workspaceFolder}' } } } });
terminalConfigService = store.add(new TerminalConfigurationService(configurationService));
terminalLabelComputer = store.add(new TerminalLabelComputer(new TestFileService(), terminalConfigService, mockContextService));
terminalLabelComputer = createLabelComputer({ terminal: { integrated: { tabs: { separator: ' - ', title: '${workspaceFolder}', description: '${workspaceFolder}' } } } });
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'zsh', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: 'folder' }) } as IWorkspaceFolder }));
strictEqual(terminalLabelComputer.title, 'folder');
strictEqual(terminalLabelComputer.description, 'folder');
});
test('should resolve local', () => {
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' - ', title: '${local}', description: '${local}' } } } });
terminalConfigService = store.add(new TerminalConfigurationService(configurationService));
terminalLabelComputer = store.add(new TerminalLabelComputer(new TestFileService(), terminalConfigService, mockContextService));
terminalLabelComputer = createLabelComputer({ terminal: { integrated: { tabs: { separator: ' - ', title: '${local}', description: '${local}' } } } });
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'zsh', shellLaunchConfig: { type: 'Local' } }));
strictEqual(terminalLabelComputer.title, 'Local');
strictEqual(terminalLabelComputer.description, 'Local');
});
test('should resolve process', () => {
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' - ', title: '${process}', description: '${process}' } } } });
terminalConfigService = store.add(new TerminalConfigurationService(configurationService));
terminalLabelComputer = store.add(new TerminalLabelComputer(new TestFileService(), terminalConfigService, mockContextService));
terminalLabelComputer = createLabelComputer({ terminal: { integrated: { tabs: { separator: ' - ', title: '${process}', description: '${process}' } } } });
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'zsh' }));
strictEqual(terminalLabelComputer.title, 'zsh');
strictEqual(terminalLabelComputer.description, 'zsh');
});
test('should resolve sequence', () => {
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' - ', title: '${sequence}', description: '${sequence}' } } } });
terminalConfigService = store.add(new TerminalConfigurationService(configurationService));
terminalLabelComputer = store.add(new TerminalLabelComputer(new TestFileService(), terminalConfigService, mockContextService));
terminalLabelComputer = createLabelComputer({ terminal: { integrated: { tabs: { separator: ' - ', title: '${sequence}', description: '${sequence}' } } } });
terminalLabelComputer.refreshLabel(createInstance({ capabilities, sequence: 'sequence' }));
strictEqual(terminalLabelComputer.title, 'sequence');
strictEqual(terminalLabelComputer.description, 'sequence');
});
test('should resolve task', () => {
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${process}${separator}${task}', description: '${task}' } } } });
terminalConfigService = store.add(new TerminalConfigurationService(configurationService));
terminalLabelComputer = store.add(new TerminalLabelComputer(new TestFileService(), terminalConfigService, mockContextService));
terminalLabelComputer = createLabelComputer({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${process}${separator}${task}', description: '${task}' } } } });
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'zsh', shellLaunchConfig: { type: 'Task' } }));
strictEqual(terminalLabelComputer.title, 'zsh ~ Task');
strictEqual(terminalLabelComputer.description, 'Task');
});
test('should resolve separator', () => {
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${separator}', description: '${separator}' } } } });
terminalConfigService = store.add(new TerminalConfigurationService(configurationService));
terminalLabelComputer = store.add(new TerminalLabelComputer(new TestFileService(), terminalConfigService, mockContextService));
terminalLabelComputer = createLabelComputer({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${separator}', description: '${separator}' } } } });
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'zsh', shellLaunchConfig: { type: 'Task' } }));
strictEqual(terminalLabelComputer.title, 'zsh');
strictEqual(terminalLabelComputer.description, '');
});
test('should always return static title when specified', () => {
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${process}', description: '${workspaceFolder}' } } } });
terminalConfigService = store.add(new TerminalConfigurationService(configurationService));
terminalLabelComputer = store.add(new TerminalLabelComputer(new TestFileService(), terminalConfigService, mockContextService));
terminalLabelComputer = createLabelComputer({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${process}', description: '${workspaceFolder}' } } } });
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'process', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: 'folder' }) } as IWorkspaceFolder, staticTitle: 'my-title' }));
strictEqual(terminalLabelComputer.title, 'my-title');
strictEqual(terminalLabelComputer.description, 'folder');
});
test('should provide cwdFolder for all cwds only when in multi-root', () => {
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${process}${separator}${cwdFolder}', description: '${cwdFolder}' } } } });
terminalConfigService = store.add(new TerminalConfigurationService(configurationService));
terminalLabelComputer = store.add(new TerminalLabelComputer(new TestFileService(), terminalConfigService, mockContextService));
terminalLabelComputer = createLabelComputer({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${process}${separator}${cwdFolder}', description: '${cwdFolder}' } } } });
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'process', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: ROOT_1 }) } as IWorkspaceFolder, cwd: ROOT_1 }));
// single-root, cwd is same as root
strictEqual(terminalLabelComputer.title, 'process');
strictEqual(terminalLabelComputer.description, '');
// multi-root
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${process}${separator}${cwdFolder}', description: '${cwdFolder}' } } } });
terminalConfigService = store.add(new TerminalConfigurationService(configurationService));
terminalLabelComputer = store.add(new TerminalLabelComputer(new TestFileService(), terminalConfigService, mockMultiRootContextService));
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'process', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: ROOT_1 }) } as IWorkspaceFolder, cwd: ROOT_2 }));
if (isWindows) {
strictEqual(terminalLabelComputer.title, 'process');
@ -300,14 +280,12 @@ suite('Workbench - TerminalInstance', () => {
}
});
test('should hide cwdFolder in single folder workspaces when cwd matches the workspace\'s default cwd even when slashes differ', async () => {
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${process}${separator}${cwdFolder}', description: '${cwdFolder}' } } } });
terminalConfigService = store.add(new TerminalConfigurationService(configurationService));
terminalLabelComputer = store.add(new TerminalLabelComputer(new TestFileService(), terminalConfigService, mockContextService));
terminalLabelComputer = createLabelComputer({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${process}${separator}${cwdFolder}', description: '${cwdFolder}' } } } });
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'process', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: ROOT_1 }) } as IWorkspaceFolder, cwd: ROOT_1 }));
strictEqual(terminalLabelComputer.title, 'process');
strictEqual(terminalLabelComputer.description, '');
if (!isWindows) {
terminalLabelComputer = store.add(new TerminalLabelComputer(new TestFileService(), terminalConfigService, mockContextService));
terminalLabelComputer = createLabelComputer({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${process}${separator}${cwdFolder}', description: '${cwdFolder}' } } } });
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'process', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: ROOT_1 }) } as IWorkspaceFolder, cwd: ROOT_2 }));
strictEqual(terminalLabelComputer.title, 'process ~ root2');
strictEqual(terminalLabelComputer.description, 'root2');

View file

@ -5,7 +5,6 @@
import type { IEvent, Terminal } from '@xterm/xterm';
import { XtermTerminal } from 'vs/workbench/contrib/terminal/browser/xterm/xtermTerminal';
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { ITerminalConfiguration, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal';
import { deepStrictEqual, strictEqual } from 'assert';
@ -105,7 +104,6 @@ suite('XtermTerminal', () => {
let themeService: TestThemeService;
let viewDescriptorService: TestViewDescriptorService;
let xterm: TestXtermTerminal;
let configHelper: TerminalConfigHelper;
let XTermBaseCtor: typeof Terminal;
setup(async () => {
@ -133,11 +131,10 @@ suite('XtermTerminal', () => {
instantiationService.stub(IContextKeyService, new MockContextKeyService());
instantiationService.stub(ILayoutService, new TestLayoutService());
configHelper = store.add(instantiationService.createInstance(TerminalConfigHelper));
XTermBaseCtor = (await importAMDNodeModule<typeof import('@xterm/xterm')>('@xterm/xterm', 'lib/xterm.js')).Terminal;
const capabilityStore = store.add(new TerminalCapabilityStore());
xterm = store.add(instantiationService.createInstance(TestXtermTerminal, XTermBaseCtor, configHelper, 80, 30, { getBackgroundColor: () => undefined }, capabilityStore, '', true));
xterm = store.add(instantiationService.createInstance(TestXtermTerminal, XTermBaseCtor, 80, 30, { getBackgroundColor: () => undefined }, capabilityStore, '', true));
TestWebglAddon.shouldThrow = false;
TestWebglAddon.isEnabled = false;
@ -154,7 +151,7 @@ suite('XtermTerminal', () => {
[PANEL_BACKGROUND]: '#ff0000',
[SIDE_BAR_BACKGROUND]: '#00ff00'
}));
xterm = store.add(instantiationService.createInstance(XtermTerminal, XTermBaseCtor, configHelper, 80, 30, { getBackgroundColor: () => new Color(new RGBA(255, 0, 0)) }, store.add(new TerminalCapabilityStore()), '', true));
xterm = store.add(instantiationService.createInstance(XtermTerminal, XTermBaseCtor, 80, 30, { getBackgroundColor: () => new Color(new RGBA(255, 0, 0)) }, store.add(new TerminalCapabilityStore()), '', true));
strictEqual(xterm.raw.options.theme?.background, '#ff0000');
});
test('should react to and apply theme changes', () => {
@ -183,7 +180,7 @@ suite('XtermTerminal', () => {
'terminal.ansiBrightCyan': '#150000',
'terminal.ansiBrightWhite': '#160000',
}));
xterm = store.add(instantiationService.createInstance(XtermTerminal, XTermBaseCtor, configHelper, 80, 30, { getBackgroundColor: () => undefined }, store.add(new TerminalCapabilityStore()), '', true));
xterm = store.add(instantiationService.createInstance(XtermTerminal, XTermBaseCtor, 80, 30, { getBackgroundColor: () => undefined }, store.add(new TerminalCapabilityStore()), '', true));
deepStrictEqual(xterm.raw.options.theme, {
background: undefined,
foreground: '#000200',

View file

@ -21,7 +21,6 @@ import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilitie
import { ITerminalLogService } from 'vs/platform/terminal/common/terminal';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
import { writeP } from 'vs/workbench/contrib/terminal/browser/terminalTestHelpers';
import { XtermTerminal } from 'vs/workbench/contrib/terminal/browser/xterm/xtermTerminal';
import { ITerminalConfiguration } from 'vs/workbench/contrib/terminal/common/terminal';
@ -53,7 +52,6 @@ suite('Buffer Content Tracker', () => {
let themeService: TestThemeService;
let xterm: XtermTerminal;
let capabilities: TerminalCapabilityStore;
let configHelper: TerminalConfigHelper;
let bufferTracker: BufferContentTracker;
const prompt = 'vscode-git:(prompt/more-tests)';
const promptPlusData = 'vscode-git:(prompt/more-tests) ' + 'some data';
@ -76,13 +74,12 @@ suite('Buffer Content Tracker', () => {
} as any);
instantiationService.stub(ILayoutService, new TestLayoutService());
configHelper = store.add(instantiationService.createInstance(TerminalConfigHelper));
capabilities = store.add(new TerminalCapabilityStore());
if (!isWindows) {
capabilities.add(TerminalCapability.NaiveCwdDetection, null!);
}
const TerminalCtor = (await importAMDNodeModule<typeof import('@xterm/xterm')>('@xterm/xterm', 'lib/xterm.js')).Terminal;
xterm = store.add(instantiationService.createInstance(XtermTerminal, TerminalCtor, configHelper, 80, 30, { getBackgroundColor: () => undefined }, capabilities, '', true));
xterm = store.add(instantiationService.createInstance(XtermTerminal, TerminalCtor, 80, 30, { getBackgroundColor: () => undefined }, capabilities, '', true));
const container = document.createElement('div');
xterm.raw.open(container);
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' - ', title: '${cwd}', description: '${cwd}' } } } });

View file

@ -16,7 +16,7 @@ import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { ITerminalLogService, TerminalSettingId } from 'vs/platform/terminal/common/terminal';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IInternalXtermTerminal, ITerminalContribution, ITerminalInstance, ITerminalService, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal';
import { IInternalXtermTerminal, ITerminalConfigurationService, ITerminalContribution, ITerminalInstance, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal';
import { registerTerminalAction } from 'vs/workbench/contrib/terminal/browser/terminalActions';
import { registerTerminalContribution } from 'vs/workbench/contrib/terminal/browser/terminalExtensions';
import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager';
@ -126,7 +126,7 @@ class DevModeContribution extends Disposable implements ITerminalContribution {
processManager: ITerminalProcessManager,
widgetManager: TerminalWidgetManager,
@IConfigurationService private readonly _configurationService: IConfigurationService,
@ITerminalService private readonly _terminalService: ITerminalService
@ITerminalConfigurationService private readonly _terminalConfigurationService: ITerminalConfigurationService,
) {
super();
this._register(this._configurationService.onDidChangeConfiguration(e => {
@ -147,7 +147,7 @@ class DevModeContribution extends Disposable implements ITerminalContribution {
// Text area syncing
if (this._xterm?.raw.textarea) {
const font = this._terminalService.configHelper.getFont(getWindow(this._xterm.raw.textarea));
const font = this._terminalConfigurationService.getFont(getWindow(this._xterm.raw.textarea));
this._xterm.raw.textarea.style.fontFamily = font.fontFamily;
this._xterm.raw.textarea.style.fontSize = `${font.fontSize}px`;
}