Skip to content

Commit

Permalink
Merge pull request #6998 from kisstkondoros/terminalfont
Browse files Browse the repository at this point in the history
Add setting for fontSize and lineHeight to the integrated terminal
  • Loading branch information
Tyriar committed Jun 3, 2016
2 parents 77c45a9 + 46ab627 commit 6cbd485
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ configurationRegistry.registerConfiguration({
'terminal.integrated.fontFamily': {
'description': nls.localize('terminal.integrated.fontFamily', "The font family used by the terminal (CSS font-family format), this defaults to editor.fontFamily's value."),
'type': 'string'
},
'terminal.integrated.fontSize': {
'description': nls.localize('terminal.integrated.fontSize', "The font size used by the terminal (in pixels), this defaults to editor.fontSize's value."),
'type': 'number'
},
'terminal.integrated.lineHeight': {
'description': nls.localize('terminal.integrated.lineHeight', "The line height used by the terminal (in pixels), this defaults to editor.lineHeight's value."),
'type': 'number'
}
}
});
Expand Down
4 changes: 3 additions & 1 deletion src/vs/workbench/parts/terminal/electron-browser/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ export interface ITerminalConfiguration {
osx: string,
windows: string
},
fontFamily: string
fontFamily: string,
fontSize: number,
lineHeight: number
}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {IConfiguration} from 'vs/editor/common/config/defaultConfig';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
import {ITerminalConfiguration} from 'vs/workbench/parts/terminal/electron-browser/terminal';
import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
import {GOLDEN_LINE_HEIGHT_RATIO} from 'vs/editor/common/config/defaultConfig';
import {Builder} from 'vs/base/browser/builder';

const DEFAULT_ANSI_COLORS = {
'hc-black': [
Expand Down Expand Up @@ -67,34 +69,73 @@ const DEFAULT_ANSI_COLORS = {
]
};

export interface ITerminalFont {
fontFamily: string;
fontSize: number;
lineHeight: number;
charWidth: number;
charHeight: number;
}

/**
* Encapsulates terminal configuration logic, the primary purpose of this file is so that platform
* specific test cases can be written.
*/
export class TerminalConfigHelper {
private charMeasureElement: HTMLElement;

public constructor(
private platform: Platform,
private configurationService: IConfigurationService,
private themeService: IThemeService) {
private themeService: IThemeService,
private parentDomElement: HTMLElement) {
}

public getTheme(): string[] {
let baseThemeId = getBaseThemeId(this.themeService.getTheme());
return DEFAULT_ANSI_COLORS[baseThemeId];
}

private neasureFont(fontFamily: string, fontSize: number, lineHeight: number): ITerminalFont {
if (!this.charMeasureElement) {
this.charMeasureElement = new Builder(this.parentDomElement, true).div().build().getHTMLElement();
}
let style = this.charMeasureElement.style;
style.display = 'inline';
style.fontFamily = fontFamily;
style.fontSize = fontSize + 'px';
style.lineHeight = lineHeight + 'px';
this.charMeasureElement.innerText = 'X';
let rect = this.charMeasureElement.getBoundingClientRect();
style.display = 'none';
let charWidth = Math.ceil(rect.width);
let charHeight = Math.ceil(rect.height);
return {
fontFamily,
fontSize,
lineHeight,
charWidth,
charHeight
};
}

/**
* Set the terminal font to `terminal.integrated.fontFamily` if it is set, otherwise fallback to
* `editor.fontFamily`.
* Gets the font information based on the terminal.integrated.fontFamily,
* terminal.integrated.fontSize, terminal.integrated.lineHeight configuration properties
*/
public getFontFamily(): string {
let terminalConfig = this.configurationService.getConfiguration<ITerminalConfiguration>();
let fontFamily = terminalConfig.terminal.integrated.fontFamily;
if (!fontFamily) {
let editorConfig = this.configurationService.getConfiguration<IConfiguration>();
fontFamily = editorConfig.editor.fontFamily;
public getFont(): ITerminalFont {
let terminalConfig = this.configurationService.getConfiguration<ITerminalConfiguration>().terminal.integrated;
let editorConfig = this.configurationService.getConfiguration<IConfiguration>();

let fontFamily = terminalConfig.fontFamily || editorConfig.editor.fontFamily;
let fontSize = this.toInteger(terminalConfig.fontSize, 0) || editorConfig.editor.fontSize;
let lineHeight = this.toInteger(terminalConfig.lineHeight, 0) || editorConfig.editor.lineHeight;

if (lineHeight === 0) {
lineHeight = Math.round(GOLDEN_LINE_HEIGHT_RATIO * fontSize);
}
return fontFamily;

return this.neasureFont(fontFamily, fontSize, lineHeight);
}

public getShell(): string {
Expand All @@ -107,4 +148,15 @@ export class TerminalConfigHelper {
}
return config.terminal.integrated.shell.linux;
}

private toInteger(source: any, minimum?: number): number {
let r = parseInt(source, 10);
if (isNaN(r)) {
r = 0;
}
if (typeof minimum === 'number') {
r = Math.max(minimum, r);
}
return r;
}
}
49 changes: 25 additions & 24 deletions src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ import {ITerminalService, TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/e
import {Panel} from 'vs/workbench/browser/panel';
import {DomScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElement';
import {ScrollbarVisibility} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';
import {TerminalConfigHelper} from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper';

const TERMINAL_CHAR_WIDTH = 8;
const TERMINAL_CHAR_HEIGHT = 18;
import {TerminalConfigHelper, ITerminalFont} from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper';

export class TerminalPanel extends Panel {

Expand All @@ -35,6 +32,7 @@ export class TerminalPanel extends Panel {
private terminal;
private terminalDomElement: HTMLDivElement;
private configurationHelper: TerminalConfigHelper;
private font: ITerminalFont;

constructor(
@IConfigurationService private configurationService: IConfigurationService,
Expand All @@ -44,22 +42,23 @@ export class TerminalPanel extends Panel {
@IThemeService private themeService: IThemeService
) {
super(TERMINAL_PANEL_ID, telemetryService);
this.configurationHelper = new TerminalConfigHelper(platform.platform, this.configurationService, this.themeService);
this.toDispose = [];
}

public layout(dimension: Dimension): void {
let cols = Math.floor(this.parentDomElement.offsetWidth / TERMINAL_CHAR_WIDTH);
let rows = Math.floor(this.parentDomElement.offsetHeight / TERMINAL_CHAR_HEIGHT);
if (this.terminal) {
this.terminal.resize(cols, rows);
}
if (this.ptyProcess.connected) {
this.ptyProcess.send({
event: 'resize',
cols: cols,
rows: rows
});
if (this.font.charWidth && this.font.charHeight) {
let cols = Math.floor(this.parentDomElement.offsetWidth / this.font.charWidth);
let rows = Math.floor(this.parentDomElement.offsetHeight / this.font.charHeight);
if (this.terminal) {
this.terminal.resize(cols, rows);
}
if (this.ptyProcess.connected) {
this.ptyProcess.send({
event: 'resize',
cols: cols,
rows: rows
});
}
}
}

Expand Down Expand Up @@ -98,6 +97,7 @@ export class TerminalPanel extends Panel {

private createTerminal(): TPromise<void> {
return new TPromise<void>(resolve => {
this.configurationHelper = new TerminalConfigHelper(platform.platform, this.configurationService, this.themeService, this.parentDomElement);
this.parentDomElement.innerHTML = '';
this.ptyProcess = this.createTerminalProcess();
this.terminalDomElement = document.createElement('div');
Expand Down Expand Up @@ -157,13 +157,13 @@ export class TerminalPanel extends Panel {
this.setTerminalTheme();
}));
this.toDispose.push(this.configurationService.onDidUpdateConfiguration((e) => {
this.setTerminalFont();
this.updateFont();
}));

this.terminal.open(this.terminalDomElement);
this.parentDomElement.appendChild(terminalScrollbar.getDomNode());

this.setTerminalFont();
this.updateFont();
this.setTerminalTheme();
resolve(void 0);
});
Expand All @@ -177,14 +177,15 @@ export class TerminalPanel extends Panel {
this.terminal.refresh(0, this.terminal.rows);
}

/**
* Set the terminal font to `terminal.integrated.fontFamily` if it is set, otherwise fallback to
* `editor.fontFamily`.
*/
private setTerminalFont(): void {
this.terminalDomElement.style.fontFamily = this.configurationHelper.getFontFamily();
private updateFont(): void {
this.font = this.configurationHelper.getFont();
this.terminalDomElement.style.fontFamily = this.font.fontFamily;
this.terminalDomElement.style.lineHeight = this.font.lineHeight + 'px';
this.terminalDomElement.style.fontSize = this.font.fontSize + 'px';
this.layout(new Dimension(this.parentDomElement.offsetWidth, this.parentDomElement.offsetHeight));
}


public focus(): void {
this.focusTerminal(true);
}
Expand Down
94 changes: 83 additions & 11 deletions src/vs/workbench/parts/terminal/test/terminalConfigHelper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,19 @@ class MockThemeService implements IThemeService {
}

suite('Workbench - TerminalConfigHelper', () => {
test('TerminalConfigHelper - getFontFamily', function () {
let fixture: HTMLElement;
let fixtureId = 'terminal-config-helper-fixture';
setup(() => {
fixture = document.createElement('div');
fixture.id = fixtureId;
document.body.appendChild(fixture);
});

teardown(() => {
document.body.removeChild(fixture);
});

test('TerminalConfigHelper - getFont', function () {
let themeService: IThemeService = new MockThemeService();
let configurationService: IConfigurationService;
let configHelper: TerminalConfigHelper;
Expand All @@ -51,8 +63,8 @@ suite('Workbench - TerminalConfigHelper', () => {
}
}
});
configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, themeService);
assert.equal(configHelper.getFontFamily(), 'bar', 'terminal.integrated.fontFamily should be selected over editor.fontFamily');
configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, themeService, fixture);
assert.equal(configHelper.getFont().fontFamily, 'bar', 'terminal.integrated.fontFamily should be selected over editor.fontFamily');

configurationService = new MockConfigurationService({
editor: {
Expand All @@ -64,8 +76,68 @@ suite('Workbench - TerminalConfigHelper', () => {
}
}
});
configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, themeService);
assert.equal(configHelper.getFontFamily(), 'foo', 'editor.fontFamily should be the fallback when terminal.integrated.fontFamily not set');
configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, themeService, fixture);
assert.equal(configHelper.getFont().fontFamily, 'foo', 'editor.fontFamily should be the fallback when terminal.integrated.fontFamily not set');

configurationService = new MockConfigurationService({
editor: {
fontFamily: 'foo',
fontSize: 1
},
terminal: {
integrated: {
fontFamily: 'bar',
fontSize: 2
}
}
});
configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, themeService, fixture);
assert.equal(configHelper.getFont().fontSize, 2, 'terminal.integrated.fontSize should be selected over editor.fontSize');

configurationService = new MockConfigurationService({
editor: {
fontFamily: 'foo',
fontSize: 1
},
terminal: {
integrated: {
fontFamily: undefined,
fontSize: undefined
}
}
});
configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, themeService, fixture);
assert.equal(configHelper.getFont().fontSize, 1, 'editor.fontSize should be the fallback when terminal.integrated.fontSize not set');

configurationService = new MockConfigurationService({
editor: {
fontFamily: 'foo',
lineHeight: 1
},
terminal: {
integrated: {
fontFamily: undefined,
lineHeight: 2
}
}
});
configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, themeService, fixture);
assert.equal(configHelper.getFont().lineHeight, 2, 'terminal.integrated.lineHeight should be selected over editor.lineHeight');

configurationService = new MockConfigurationService({
editor: {
fontFamily: 'foo',
lineHeight: 1
},
terminal: {
integrated: {
fontFamily: undefined,
lineHeight: undefined
}
}
});
configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, themeService, fixture);
assert.equal(configHelper.getFont().lineHeight, 1, 'editor.lineHeight should be the fallback when terminal.integrated.lineHeight not set');
});

test('TerminalConfigHelper - getShell', function () {
Expand All @@ -82,7 +154,7 @@ suite('Workbench - TerminalConfigHelper', () => {
}
}
});
configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, themeService);
configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, themeService, fixture);
assert.equal(configHelper.getShell(), 'foo', 'terminal.integrated.shell.linux should be selected on Linux');

configurationService = new MockConfigurationService({
Expand All @@ -94,7 +166,7 @@ suite('Workbench - TerminalConfigHelper', () => {
}
}
});
configHelper = new TerminalConfigHelper(Platform.Mac, configurationService, themeService);
configHelper = new TerminalConfigHelper(Platform.Mac, configurationService, themeService, fixture);
assert.equal(configHelper.getShell(), 'foo', 'terminal.integrated.shell.osx should be selected on OS X');

configurationService = new MockConfigurationService({
Expand All @@ -106,7 +178,7 @@ suite('Workbench - TerminalConfigHelper', () => {
}
}
});
configHelper = new TerminalConfigHelper(Platform.Windows, configurationService, themeService);
configHelper = new TerminalConfigHelper(Platform.Windows, configurationService, themeService, fixture);
assert.equal(configHelper.getShell(), 'foo', 'terminal.integrated.shell.windows should be selected on Windows');
});

Expand All @@ -116,7 +188,7 @@ suite('Workbench - TerminalConfigHelper', () => {
let configHelper: TerminalConfigHelper;

themeService = new MockThemeService('hc-black foo');
configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, themeService);
configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, themeService, fixture);
assert.deepEqual(configHelper.getTheme(), [
'#000000',
'#cd0000',
Expand All @@ -137,7 +209,7 @@ suite('Workbench - TerminalConfigHelper', () => {
], 'The high contrast terminal theme should be selected when the hc-black theme is active');

themeService = new MockThemeService('vs foo');
configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, themeService);
configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, themeService, fixture);
assert.deepEqual(configHelper.getTheme(), [
'#000000',
'#cd3131',
Expand All @@ -158,7 +230,7 @@ suite('Workbench - TerminalConfigHelper', () => {
], 'The light terminal theme should be selected when a vs theme is active');

themeService = new MockThemeService('vs-dark foo');
configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, themeService);
configHelper = new TerminalConfigHelper(Platform.Linux, configurationService, themeService, fixture);
assert.deepEqual(configHelper.getTheme(), [
'#000000',
'#cd3131',
Expand Down

0 comments on commit 6cbd485

Please sign in to comment.