From 007410995a5218c3bde2196065deb11f41ffabc5 Mon Sep 17 00:00:00 2001 From: Bruno Ribeito Date: Wed, 8 Nov 2017 21:04:04 +0000 Subject: [PATCH 01/26] Fix#1117 --- fixtures/typings-test/typings-test.ts | 8 +++++--- src/Interfaces.ts | 3 ++- src/Terminal.ts | 10 ++++++++-- src/renderer/BaseRenderLayer.ts | 22 +++++++++++++++------- src/renderer/CharAtlas.ts | 18 ++++++++++++------ src/renderer/TextRenderLayer.ts | 2 +- typings/xterm.d.ts | 6 ++++++ 7 files changed, 49 insertions(+), 20 deletions(-) diff --git a/fixtures/typings-test/typings-test.ts b/fixtures/typings-test/typings-test.ts index 93fd501f4..b84252054 100644 --- a/fixtures/typings-test/typings-test.ts +++ b/fixtures/typings-test/typings-test.ts @@ -143,8 +143,9 @@ namespace methods_core { const r18: (data: string) => void = t.getOption('handler'); const r19: string = t.getOption('bellSound'); const r20: string = t.getOption('bellStyle'); - const r21: boolean = t.getOption('enableBold'); - const r22: number = t.getOption('letterSpacing'); + const r21: number = t.getOption('letterSpacing'); + const r22: number = t.getOption('fontWeight'); + const r23: number = t.getOption('fontWeightBold'); } { const t: Terminal = new Terminal(); @@ -157,7 +158,8 @@ namespace methods_core { t.setOption('cursorBlink', true); t.setOption('debug', true); t.setOption('disableStdin', true); - t.setOption('enableBold', true); + t.setOption('fontWeight', 'normal'); + t.setOption('fontWeightBold', 'bold'); t.setOption('popOnBell', true); t.setOption('screenKeys', true); t.setOption('useFlowControl', true); diff --git a/src/Interfaces.ts b/src/Interfaces.ts index 354e2c4e3..77e94978f 100644 --- a/src/Interfaces.ts +++ b/src/Interfaces.ts @@ -137,9 +137,10 @@ export interface ITerminalOptions { cursorStyle?: string; debug?: boolean; disableStdin?: boolean; - enableBold?: boolean; fontSize?: number; fontFamily?: string; + fontWeight?: string; + fontWeightBold?: string; geometry?: [number, number]; handler?: (data: string) => void; letterSpacing?: number; diff --git a/src/Terminal.ts b/src/Terminal.ts index 867c522dc..1f08ce8a9 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -77,9 +77,10 @@ const DEFAULT_OPTIONS: ITerminalOptions = { cursorStyle: 'block', bellSound: BellSound, bellStyle: 'none', - enableBold: true, fontFamily: 'courier-new, courier, monospace', fontSize: 15, + fontWeight: 'normal', + fontWeightBold: 'bold', lineHeight: 1.0, letterSpacing: 0, scrollback: 1000, @@ -416,7 +417,6 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.renderer.clear(); this.charMeasure.measure(this.options); break; - case 'enableBold': case 'letterSpacing': case 'lineHeight': // When the font changes the size of the cells may change which requires a renderer clear @@ -424,6 +424,12 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.renderer.onResize(this.cols, this.rows, false); this.refresh(0, this.rows - 1); // this.charMeasure.measure(this.options); + case 'fontWeight': + case 'fontWeightBold': + // When the font weight changes the size of the cells may change which requires a renderer clear + this.renderer.clear(); + this.renderer.onResize(this.cols, this.rows, true); + this.refresh(0, this.rows - 1); case 'scrollback': this.buffers.resize(this.cols, this.rows); this.viewport.syncScrollArea(); diff --git a/src/renderer/BaseRenderLayer.ts b/src/renderer/BaseRenderLayer.ts index b4becbce0..a5f4370c2 100644 --- a/src/renderer/BaseRenderLayer.ts +++ b/src/renderer/BaseRenderLayer.ts @@ -201,7 +201,7 @@ export abstract class BaseRenderLayer implements IRenderLayer { * @param color The color of the character. */ protected fillCharTrueColor(terminal: ITerminal, charData: CharData, x: number, y: number): void { - this._ctx.font = `${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`; + this._ctx.font = this._getFont(terminal, false); this._ctx.textBaseline = 'top'; this._clipRow(terminal, y); this._ctx.fillText( @@ -230,7 +230,7 @@ export abstract class BaseRenderLayer implements IRenderLayer { colorIndex = fg + 2; } else { // If default color and bold - if (bold && terminal.options.enableBold) { + if (bold) { colorIndex = 1; } } @@ -252,7 +252,7 @@ export abstract class BaseRenderLayer implements IRenderLayer { } // Draw the non-bold version of the same color if bold is not enabled - if (bold && !terminal.options.enableBold) { + if (bold) { // Ignore default color as it's not touched above if (colorIndex > 1) { colorIndex -= 8; @@ -289,10 +289,7 @@ export abstract class BaseRenderLayer implements IRenderLayer { */ private _drawUncachedChar(terminal: ITerminal, char: string, width: number, fg: number, x: number, y: number, bold: boolean, dim: boolean): void { this._ctx.save(); - this._ctx.font = `${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`; - if (bold && terminal.options.enableBold) { - this._ctx.font = `bold ${this._ctx.font}`; - } + this._ctx.font = this._getFont(terminal, bold); this._ctx.textBaseline = 'top'; if (fg === INVERTED_DEFAULT_COLOR) { @@ -332,5 +329,16 @@ export abstract class BaseRenderLayer implements IRenderLayer { this._scaledCellHeight); this._ctx.clip(); } + + /** + * Gets the current font. + * @param terminal The terminal. + * @param isBold The font weight that should be used uses terminal option as fallback. + */ + private _getFont(terminal: ITerminal, isBold: boolean): string { + const fontWeight = isBold ? terminal.options.fontWeightBold : terminal.options.fontWeight; + + return `${fontWeight} ${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`; + } } diff --git a/src/renderer/CharAtlas.ts b/src/renderer/CharAtlas.ts index 9ac1e1618..50b9b9bd4 100644 --- a/src/renderer/CharAtlas.ts +++ b/src/renderer/CharAtlas.ts @@ -12,6 +12,8 @@ export const CHAR_ATLAS_CELL_SPACING = 1; interface ICharAtlasConfig { fontSize: number; fontFamily: string; + fontWeight: string; + fontWeightBold: string; scaledCharWidth: number; scaledCharHeight: number; colors: IColorSet; @@ -64,7 +66,7 @@ export function acquireCharAtlas(terminal: ITerminal, colors: IColorSet, scaledC } const newEntry: ICharAtlasCacheEntry = { - bitmap: generator.generate(scaledCharWidth, scaledCharHeight, terminal.options.fontSize, terminal.options.fontFamily, colors.background, colors.foreground, colors.ansi), + bitmap: generator.generate(scaledCharWidth, scaledCharHeight, terminal.options.fontSize, terminal.options.fontFamily, terminal.options.fontWeight, terminal.options.fontWeightBold, colors.background, colors.foreground, colors.ansi), config: newConfig, ownedBy: [terminal] }; @@ -86,6 +88,8 @@ function generateConfig(scaledCharWidth: number, scaledCharHeight: number, termi scaledCharHeight, fontFamily: terminal.options.fontFamily, fontSize: terminal.options.fontSize, + fontWeight: terminal.options.fontWeight, + fontWeightBold: terminal.options.fontWeightBold, colors: clonedColors }; } @@ -98,6 +102,8 @@ function configEquals(a: ICharAtlasConfig, b: ICharAtlasConfig): boolean { } return a.fontFamily === b.fontFamily && a.fontSize === b.fontSize && + a.fontWeight === b.fontWeight && + a.fontWeightBold === b.fontWeightBold && a.scaledCharWidth === b.scaledCharWidth && a.scaledCharHeight === b.scaledCharHeight && a.colors.foreground === b.colors.foreground && @@ -126,7 +132,7 @@ class CharAtlasGenerator { this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio); } - public generate(scaledCharWidth: number, scaledCharHeight: number, fontSize: number, fontFamily: string, background: string, foreground: string, ansiColors: string[]): HTMLCanvasElement | Promise { + public generate(scaledCharWidth: number, scaledCharHeight: number, fontSize: number, fontFamily: string, fontWeight: string, fontWeightBold: string, background: string, foreground: string, ansiColors: string[]): HTMLCanvasElement | Promise { const cellWidth = scaledCharWidth + CHAR_ATLAS_CELL_SPACING; const cellHeight = scaledCharHeight + CHAR_ATLAS_CELL_SPACING; this._canvas.width = 255 * cellWidth; @@ -137,7 +143,7 @@ class CharAtlasGenerator { this._ctx.save(); this._ctx.fillStyle = foreground; - this._ctx.font = `${fontSize * window.devicePixelRatio}px ${fontFamily}`; + this._ctx.font = `${fontWeight} ${fontSize * window.devicePixelRatio}px ${fontFamily}`; this._ctx.textBaseline = 'top'; // Default color @@ -151,7 +157,7 @@ class CharAtlasGenerator { } // Default color bold this._ctx.save(); - this._ctx.font = `bold ${this._ctx.font}`; + this._ctx.font = `${fontWeightBold} ${fontSize * window.devicePixelRatio}px ${fontFamily}`; for (let i = 0; i < 256; i++) { this._ctx.save(); this._ctx.beginPath(); @@ -163,11 +169,11 @@ class CharAtlasGenerator { this._ctx.restore(); // Colors 0-15 - this._ctx.font = `${fontSize * window.devicePixelRatio}px ${fontFamily}`; + this._ctx.font = `${fontWeight} ${fontSize * window.devicePixelRatio}px ${fontFamily}`; for (let colorIndex = 0; colorIndex < 16; colorIndex++) { // colors 8-15 are bold if (colorIndex === 8) { - this._ctx.font = `bold ${this._ctx.font}`; + this._ctx.font = `${fontWeightBold} ${fontSize * window.devicePixelRatio}px ${fontFamily}`; } const y = (colorIndex + 2) * cellHeight; // Draw ascii characters diff --git a/src/renderer/TextRenderLayer.ts b/src/renderer/TextRenderLayer.ts index 2ecb6ec6e..5a13242ff 100644 --- a/src/renderer/TextRenderLayer.ts +++ b/src/renderer/TextRenderLayer.ts @@ -33,7 +33,7 @@ export class TextRenderLayer extends BaseRenderLayer { super.resize(terminal, dim, charSizeChanged); // Clear the character width cache if the font or width has changed - const terminalFont = `${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`; + const terminalFont = `${terminal.options.fontWeight} ${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`; if (this._characterWidth !== dim.scaledCharWidth || this._characterFont !== terminalFont) { this._characterWidth = dim.scaledCharWidth; this._characterFont = terminalFont; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index b0f5ac4d0..aa7d8f3e3 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -442,6 +442,12 @@ declare module 'xterm' { * @param value The option value. */ setOption(key: 'fontFamily' | 'termName' | 'bellSound', value: string): void; + /** + * Sets an option on the terminal. + * @param key The option key. + * @param value The option value. + */ + setOption(key: 'fontWeight' | 'fontWeightBold', value: null | 'normal' | 'bold' | 'bolder' | 'lighter' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'): void; /** * Sets an option on the terminal. * @param key The option key. From f12eb5367bd2bf566cffd18c9407f8c936d7f7cb Mon Sep 17 00:00:00 2001 From: Bruno Ribeito Date: Wed, 8 Nov 2017 23:40:13 +0000 Subject: [PATCH 02/26] Adress feedback --- src/Terminal.ts | 23 +++++++++++++++-------- typings/xterm.d.ts | 2 +- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 1f08ce8a9..9b3e485c6 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -367,6 +367,16 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT value = 'block'; } break; + case 'fontWeight': + if (!value) { + value = 'normal'; + } + break; + case 'fontWeightBold': + if (!value) { + value = 'bold'; + } + break; case 'lineHeight': if (value < 1) { console.warn(`${key} cannot be less than 1, value: ${value}`); @@ -419,17 +429,14 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT break; case 'letterSpacing': case 'lineHeight': + case 'fontWeight': + case 'fontWeightBold': + const didCharSizeChange = (key === 'fontWeight' || key === 'fontWeightBold'); + // When the font changes the size of the cells may change which requires a renderer clear this.renderer.clear(); - this.renderer.onResize(this.cols, this.rows, false); + this.renderer.onResize(this.cols, this.rows, didCharSizeChange); this.refresh(0, this.rows - 1); - // this.charMeasure.measure(this.options); - case 'fontWeight': - case 'fontWeightBold': - // When the font weight changes the size of the cells may change which requires a renderer clear - this.renderer.clear(); - this.renderer.onResize(this.cols, this.rows, true); - this.refresh(0, this.rows - 1); case 'scrollback': this.buffers.resize(this.cols, this.rows); this.viewport.syncScrollArea(); diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index aa7d8f3e3..ced58fcfb 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -404,7 +404,7 @@ declare module 'xterm' { * Retrieves an option's value from the terminal. * @param key The option key. */ - getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'termName'): string; + getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'fontWeight' | 'fontWeightBold'| 'termName'): string; /** * Retrieves an option's value from the terminal. * @param key The option key. From 51de968fdecdebd541c1480bc0622bf5ce8c2606 Mon Sep 17 00:00:00 2001 From: Bruno Ribeito Date: Sun, 12 Nov 2017 23:05:27 +0000 Subject: [PATCH 03/26] Fix non-white colors not being drawn as bold --- src/renderer/BaseRenderLayer.ts | 11 ++--------- src/renderer/CharAtlas.ts | 12 ++++++++---- src/renderer/TextRenderLayer.ts | 4 ++-- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/renderer/BaseRenderLayer.ts b/src/renderer/BaseRenderLayer.ts index a5f4370c2..977cbf526 100644 --- a/src/renderer/BaseRenderLayer.ts +++ b/src/renderer/BaseRenderLayer.ts @@ -251,13 +251,6 @@ export abstract class BaseRenderLayer implements IRenderLayer { this._ctx.globalAlpha = DIM_OPACITY; } - // Draw the non-bold version of the same color if bold is not enabled - if (bold) { - // Ignore default color as it's not touched above - if (colorIndex > 1) { - colorIndex -= 8; - } - } this._ctx.drawImage(this._charAtlas, code * charAtlasCellWidth, @@ -333,9 +326,9 @@ export abstract class BaseRenderLayer implements IRenderLayer { /** * Gets the current font. * @param terminal The terminal. - * @param isBold The font weight that should be used uses terminal option as fallback. + * @param isBold If we should use the bold fontWeight. */ - private _getFont(terminal: ITerminal, isBold: boolean): string { + protected _getFont(terminal: ITerminal, isBold: boolean): string { const fontWeight = isBold ? terminal.options.fontWeightBold : terminal.options.fontWeight; return `${fontWeight} ${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`; diff --git a/src/renderer/CharAtlas.ts b/src/renderer/CharAtlas.ts index 50b9b9bd4..1458ba762 100644 --- a/src/renderer/CharAtlas.ts +++ b/src/renderer/CharAtlas.ts @@ -143,7 +143,7 @@ class CharAtlasGenerator { this._ctx.save(); this._ctx.fillStyle = foreground; - this._ctx.font = `${fontWeight} ${fontSize * window.devicePixelRatio}px ${fontFamily}`; + this._ctx.font = this._getFont(fontWeight, fontSize, fontFamily); this._ctx.textBaseline = 'top'; // Default color @@ -157,7 +157,7 @@ class CharAtlasGenerator { } // Default color bold this._ctx.save(); - this._ctx.font = `${fontWeightBold} ${fontSize * window.devicePixelRatio}px ${fontFamily}`; + this._ctx.font = this._getFont(fontWeightBold, fontSize, fontFamily); for (let i = 0; i < 256; i++) { this._ctx.save(); this._ctx.beginPath(); @@ -169,11 +169,11 @@ class CharAtlasGenerator { this._ctx.restore(); // Colors 0-15 - this._ctx.font = `${fontWeight} ${fontSize * window.devicePixelRatio}px ${fontFamily}`; + this._ctx.font = this._getFont(fontWeight, fontSize, fontFamily); for (let colorIndex = 0; colorIndex < 16; colorIndex++) { // colors 8-15 are bold if (colorIndex === 8) { - this._ctx.font = `${fontWeightBold} ${fontSize * window.devicePixelRatio}px ${fontFamily}`; + this._ctx.font = this._getFont(fontWeightBold, fontSize, fontFamily); } const y = (colorIndex + 2) * cellHeight; // Draw ascii characters @@ -225,4 +225,8 @@ class CharAtlasGenerator { } } } + + private _getFont(fontWeight: string, fontSize: number, fontFamily: string): string { + return `${fontWeight} ${fontSize * window.devicePixelRatio}px ${fontFamily}`; + } } diff --git a/src/renderer/TextRenderLayer.ts b/src/renderer/TextRenderLayer.ts index 5a13242ff..41454adb9 100644 --- a/src/renderer/TextRenderLayer.ts +++ b/src/renderer/TextRenderLayer.ts @@ -33,7 +33,7 @@ export class TextRenderLayer extends BaseRenderLayer { super.resize(terminal, dim, charSizeChanged); // Clear the character width cache if the font or width has changed - const terminalFont = `${terminal.options.fontWeight} ${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`; + const terminalFont = this._getFont(terminal, false); if (this._characterWidth !== dim.scaledCharWidth || this._characterFont !== terminalFont) { this._characterWidth = dim.scaledCharWidth; this._characterFont = terminalFont; @@ -166,7 +166,7 @@ export class TextRenderLayer extends BaseRenderLayer { this._ctx.save(); if (flags & FLAGS.BOLD) { - this._ctx.font = `bold ${this._ctx.font}`; + this._ctx.font = this._getFont(terminal, true); // Convert the FG color to the bold variant if (fg < 8) { fg += 8; From 50ed83ca64d6bcef386cbd075d906200a906fbe5 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 5 Jan 2018 14:40:41 -0800 Subject: [PATCH 04/26] Set version to 3.1.0-master This will make it clear in bug reports etc. when someone is running off master and not 3.0. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1dfadf9fc..d7d94b765 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "xterm", "description": "Full xterm terminal, in your browser", - "version": "3.0.0", + "version": "3.1.0-master", "ignore": [ "demo", "test", From d0ef868215f1caa4b457603f3b2791407bf49609 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 6 Jan 2018 13:43:34 -0800 Subject: [PATCH 05/26] Refactor char atlas to enable generation with worker This doesn't actually add workers but it separates the code nicely such that the minimal amount of relevant code can be pulled in by worker code. Part of #955 --- src/SelectionManager.ts | 2 +- src/Terminal.ts | 5 +- src/renderer/CharAtlas.ts | 140 +++++------------------------- src/shared/CharAtlasGenerator.ts | 133 ++++++++++++++++++++++++++++ src/{ => shared}/utils/Browser.ts | 11 ++- src/utils/Generic.ts | 13 --- 6 files changed, 165 insertions(+), 139 deletions(-) create mode 100644 src/shared/CharAtlasGenerator.ts rename src/{ => shared}/utils/Browser.ts (75%) delete mode 100644 src/utils/Generic.ts diff --git a/src/SelectionManager.ts b/src/SelectionManager.ts index cd6fc9961..83aaf6a31 100644 --- a/src/SelectionManager.ts +++ b/src/SelectionManager.ts @@ -4,7 +4,7 @@ */ import { MouseHelper } from './utils/MouseHelper'; -import * as Browser from './utils/Browser'; +import * as Browser from './shared/utils/Browser'; import { CharMeasure } from './utils/CharMeasure'; import { CircularList } from './utils/CircularList'; import { EventEmitter } from './EventEmitter'; diff --git a/src/Terminal.ts b/src/Terminal.ts index f95cc0eaf..220af9e38 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -35,7 +35,7 @@ import { Renderer } from './renderer/Renderer'; import { Linkifier } from './Linkifier'; import { SelectionManager } from './SelectionManager'; import { CharMeasure } from './utils/CharMeasure'; -import * as Browser from './utils/Browser'; +import * as Browser from './shared/utils/Browser'; import { MouseHelper } from './utils/MouseHelper'; import { CHARSETS } from './Charsets'; import { CustomKeyEventHandler, Charset, LinkMatcherHandler, LinkMatcherValidationCallback, CharData, LineData } from './Types'; @@ -44,7 +44,6 @@ import { BellSound } from './utils/Sounds'; import { DEFAULT_ANSI_COLORS } from './renderer/ColorManager'; import { IMouseZoneManager } from './input/Interfaces'; import { MouseZoneManager } from './input/MouseZoneManager'; -import { initialize as initializeCharAtlas } from './renderer/CharAtlas'; import { IRenderer } from './renderer/Interfaces'; // Let it work inside Node.js for automated testing purposes. @@ -574,8 +573,6 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.document = this.parent.ownerDocument; this.body = this.document.body; - initializeCharAtlas(this.document); - // Create main element container this.element = this.document.createElement('div'); this.element.classList.add('terminal'); diff --git a/src/renderer/CharAtlas.ts b/src/renderer/CharAtlas.ts index 9ac1e1618..3bc4291aa 100644 --- a/src/renderer/CharAtlas.ts +++ b/src/renderer/CharAtlas.ts @@ -5,7 +5,8 @@ import { ITerminal, ITheme } from '../Interfaces'; import { IColorSet } from '../renderer/Interfaces'; -import { isFirefox } from '../utils/Browser'; +import { isFirefox } from '../shared/utils/Browser'; +import { generateCharAtlas, ICharAtlasRequest } from '../shared/CharAtlasGenerator'; export const CHAR_ATLAS_CELL_SPACING = 1; @@ -63,8 +64,26 @@ export function acquireCharAtlas(terminal: ITerminal, colors: IColorSet, scaledC } } + const canvasFactory = (width: number, height: number) => { + const canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + return canvas; + }; + + const charAtlasConfig: ICharAtlasRequest = { + scaledCharWidth, + scaledCharHeight, + fontSize: terminal.options.fontSize, + fontFamily: terminal.options.fontFamily, + background: colors.background, + foreground: colors.foreground, + ansiColors: colors.ansi, + devicePixelRatio: window.devicePixelRatio + }; + const newEntry: ICharAtlasCacheEntry = { - bitmap: generator.generate(scaledCharWidth, scaledCharHeight, terminal.options.fontSize, terminal.options.fontFamily, colors.background, colors.foreground, colors.ansi), + bitmap: generateCharAtlas(window, canvasFactory, charAtlasConfig), config: newConfig, ownedBy: [terminal] }; @@ -103,120 +122,3 @@ function configEquals(a: ICharAtlasConfig, b: ICharAtlasConfig): boolean { a.colors.foreground === b.colors.foreground && a.colors.background === b.colors.background; } - -let generator: CharAtlasGenerator; - -/** - * Initializes the char atlas generator. - * @param document The document. - */ -export function initialize(document: Document): void { - if (!generator) { - generator = new CharAtlasGenerator(document); - } -} - -class CharAtlasGenerator { - private _canvas: HTMLCanvasElement; - private _ctx: CanvasRenderingContext2D; - - constructor(private _document: Document) { - this._canvas = this._document.createElement('canvas'); - this._ctx = this._canvas.getContext('2d', {alpha: false}); - this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio); - } - - public generate(scaledCharWidth: number, scaledCharHeight: number, fontSize: number, fontFamily: string, background: string, foreground: string, ansiColors: string[]): HTMLCanvasElement | Promise { - const cellWidth = scaledCharWidth + CHAR_ATLAS_CELL_SPACING; - const cellHeight = scaledCharHeight + CHAR_ATLAS_CELL_SPACING; - this._canvas.width = 255 * cellWidth; - this._canvas.height = (/*default+default bold*/2 + /*0-15*/16) * cellHeight; - - this._ctx.fillStyle = background; - this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height); - - this._ctx.save(); - this._ctx.fillStyle = foreground; - this._ctx.font = `${fontSize * window.devicePixelRatio}px ${fontFamily}`; - this._ctx.textBaseline = 'top'; - - // Default color - for (let i = 0; i < 256; i++) { - this._ctx.save(); - this._ctx.beginPath(); - this._ctx.rect(i * cellWidth, 0, cellWidth, cellHeight); - this._ctx.clip(); - this._ctx.fillText(String.fromCharCode(i), i * cellWidth, 0); - this._ctx.restore(); - } - // Default color bold - this._ctx.save(); - this._ctx.font = `bold ${this._ctx.font}`; - for (let i = 0; i < 256; i++) { - this._ctx.save(); - this._ctx.beginPath(); - this._ctx.rect(i * cellWidth, cellHeight, cellWidth, cellHeight); - this._ctx.clip(); - this._ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight); - this._ctx.restore(); - } - this._ctx.restore(); - - // Colors 0-15 - this._ctx.font = `${fontSize * window.devicePixelRatio}px ${fontFamily}`; - for (let colorIndex = 0; colorIndex < 16; colorIndex++) { - // colors 8-15 are bold - if (colorIndex === 8) { - this._ctx.font = `bold ${this._ctx.font}`; - } - const y = (colorIndex + 2) * cellHeight; - // Draw ascii characters - for (let i = 0; i < 256; i++) { - this._ctx.save(); - this._ctx.beginPath(); - this._ctx.rect(i * cellWidth, y, cellWidth, cellHeight); - this._ctx.clip(); - this._ctx.fillStyle = ansiColors[colorIndex]; - this._ctx.fillText(String.fromCharCode(i), i * cellWidth, y); - this._ctx.restore(); - } - } - this._ctx.restore(); - - // Support is patchy for createImageBitmap at the moment, pass a canvas back - // if support is lacking as drawImage works there too. Firefox is also - // included here as ImageBitmap appears both buggy and has horrible - // performance (tested on v55). - if (!('createImageBitmap' in window) || isFirefox) { - // Regenerate canvas and context as they are now owned by the char atlas - const result = this._canvas; - this._canvas = this._document.createElement('canvas'); - this._ctx = this._canvas.getContext('2d'); - this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio); - return result; - } - - const charAtlasImageData = this._ctx.getImageData(0, 0, this._canvas.width, this._canvas.height); - - // Remove the background color from the image so characters may overlap - const r = parseInt(background.substr(1, 2), 16); - const g = parseInt(background.substr(3, 2), 16); - const b = parseInt(background.substr(5, 2), 16); - this._clearColor(charAtlasImageData, r, g, b); - - const promise = window.createImageBitmap(charAtlasImageData); - // Clear the rect while the promise is in progress - this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); - return promise; - } - - private _clearColor(imageData: ImageData, r: number, g: number, b: number): void { - for (let offset = 0; offset < imageData.data.length; offset += 4) { - if (imageData.data[offset] === r && - imageData.data[offset + 1] === g && - imageData.data[offset + 2] === b) { - imageData.data[offset + 3] = 0; - } - } - } -} diff --git a/src/shared/CharAtlasGenerator.ts b/src/shared/CharAtlasGenerator.ts new file mode 100644 index 000000000..9452f8c64 --- /dev/null +++ b/src/shared/CharAtlasGenerator.ts @@ -0,0 +1,133 @@ +/** + * Copyright (c) 2018 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { isFirefox } from './utils/Browser'; + +declare const Promise: any; + +export interface IOffscreenCanvas { + width: number; + height: number; + getContext(type: '2d', config?: Canvas2DContextAttributes): CanvasRenderingContext2D; + transferToImageBitmap(): ImageBitmap; +} + +export interface ICharAtlasRequest { + scaledCharWidth: number; + scaledCharHeight: number; + fontSize: number; + fontFamily: string; + background: string; + foreground: string; + ansiColors: string[]; + devicePixelRatio: number; +} + +export const CHAR_ATLAS_CELL_SPACING = 1; + +/** + * Generates a char atlas. + * @param context The window or worker context. + * @param canvasFactory A function to generate a canvas with a width or height. + * @param request The config for the new char atlas. + */ +export function generateCharAtlas(context: Window, canvasFactory: (width: number, height: number) => HTMLCanvasElement | IOffscreenCanvas, request: ICharAtlasRequest): HTMLCanvasElement | Promise { + const cellWidth = request.scaledCharWidth + CHAR_ATLAS_CELL_SPACING; + const cellHeight = request.scaledCharHeight + CHAR_ATLAS_CELL_SPACING; + const canvas = canvasFactory( + /*255 ascii chars*/255 * cellWidth, + (/*default+default bold*/2 + /*0-15*/16) * cellHeight + ); + const ctx = canvas.getContext('2d', {alpha: false}); + + ctx.fillStyle = request.background; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + ctx.save(); + ctx.fillStyle = request.foreground; + ctx.font = `${request.fontSize * request.devicePixelRatio}px ${request.fontFamily}`; + ctx.textBaseline = 'top'; + + // Default color + for (let i = 0; i < 256; i++) { + ctx.save(); + ctx.beginPath(); + ctx.rect(i * cellWidth, 0, cellWidth, cellHeight); + ctx.clip(); + ctx.fillText(String.fromCharCode(i), i * cellWidth, 0); + ctx.restore(); + } + // Default color bold + ctx.save(); + ctx.font = `bold ${ctx.font}`; + for (let i = 0; i < 256; i++) { + ctx.save(); + ctx.beginPath(); + ctx.rect(i * cellWidth, cellHeight, cellWidth, cellHeight); + ctx.clip(); + ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight); + ctx.restore(); + } + ctx.restore(); + + // Colors 0-15 + ctx.font = `${request.fontSize * request.devicePixelRatio}px ${request.fontFamily}`; + for (let colorIndex = 0; colorIndex < 16; colorIndex++) { + // colors 8-15 are bold + if (colorIndex === 8) { + ctx.font = `bold ${ctx.font}`; + } + const y = (colorIndex + 2) * cellHeight; + // Draw ascii characters + for (let i = 0; i < 256; i++) { + ctx.save(); + ctx.beginPath(); + ctx.rect(i * cellWidth, y, cellWidth, cellHeight); + ctx.clip(); + ctx.fillStyle = request.ansiColors[colorIndex]; + ctx.fillText(String.fromCharCode(i), i * cellWidth, y); + ctx.restore(); + } + } + ctx.restore(); + + // Support is patchy for createImageBitmap at the moment, pass a canvas back + // if support is lacking as drawImage works there too. Firefox is also + // included here as ImageBitmap appears both buggy and has horrible + // performance (tested on v55). + if (!('createImageBitmap' in context) || isFirefox) { + // Don't attempt to clear background colors if createImageBitmap is not supported + if (canvas instanceof HTMLCanvasElement) { + // Just return the HTMLCanvas if it's a HTMLCanvasElement + return canvas; + } else { + // Transfer to an ImageBitmap is this is an OffscreenCanvas + return new Promise(r => r(canvas.transferToImageBitmap())); + } + } + + const charAtlasImageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + + // Remove the background color from the image so characters may overlap + const r = parseInt(request.background.substr(1, 2), 16); + const g = parseInt(request.background.substr(3, 2), 16); + const b = parseInt(request.background.substr(5, 2), 16); + clearColor(charAtlasImageData, r, g, b); + + return context.createImageBitmap(charAtlasImageData); +} + +/** + * Makes a partiicular rgb color in an ImageData completely transparent. + */ +function clearColor(imageData: ImageData, r: number, g: number, b: number): void { + for (let offset = 0; offset < imageData.data.length; offset += 4) { + if (imageData.data[offset] === r && + imageData.data[offset + 1] === g && + imageData.data[offset + 2] === b) { + imageData.data[offset + 3] = 0; + } + } +} diff --git a/src/utils/Browser.ts b/src/shared/utils/Browser.ts similarity index 75% rename from src/utils/Browser.ts rename to src/shared/utils/Browser.ts index 48c0c3748..1d4774d21 100644 --- a/src/utils/Browser.ts +++ b/src/shared/utils/Browser.ts @@ -3,8 +3,6 @@ * @license MIT */ -import { contains } from './Generic'; - const isNode = (typeof navigator === 'undefined') ? true : false; const userAgent = (isNode) ? 'node' : navigator.userAgent; const platform = (isNode) ? 'node' : navigator.platform; @@ -20,3 +18,12 @@ export const isIpad = platform === 'iPad'; export const isIphone = platform === 'iPhone'; export const isMSWindows = contains(['Windows', 'Win16', 'Win32', 'WinCE'], platform); export const isLinux = platform.indexOf('Linux') >= 0; + +/** + * Return if the given array contains the given element + * @param {Array} array The array to search for the given element. + * @param {Object} el The element to look for into the array + */ +export function contains(arr: any[], el: any): boolean { + return arr.indexOf(el) >= 0; +}; diff --git a/src/utils/Generic.ts b/src/utils/Generic.ts deleted file mode 100644 index 823736178..000000000 --- a/src/utils/Generic.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Copyright (c) 2016 The xterm.js authors. All rights reserved. - * @license MIT - */ - -/** - * Return if the given array contains the given element - * @param {Array} array The array to search for the given element. - * @param {Object} el The element to look for into the array - */ -export function contains(arr: any[], el: any): boolean { - return arr.indexOf(el) >= 0; -}; From e49d84428451af0c0d0b092e62bca56ac359bfe5 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 6 Jan 2018 13:46:27 -0800 Subject: [PATCH 06/26] Add note in README about code structure --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 1719efb27..05c26f84a 100644 --- a/README.md +++ b/README.md @@ -161,6 +161,10 @@ Xterm.js is maintained by [SourceLair](https://www.sourcelair.com/) and a few ex To contribute either code, documentation or issues to xterm.js please read the [Contributing document](CONTRIBUTING.md) beforehand. The development of xterm.js does not require any special tool. All you need is an editor that supports JavaScript/TypeScript and a browser. You will need Node.js installed locally to get all the features working in the demo. +### Code structure + +`src/` is roughly split up into areas of functionality such as `renderer/` that handles all rendering and `utils/` which provides general utility functions. The `shared/` folder contains code that can be used from either the main thread or a web worker thread, all code inside a `shared/` folder should only ever import other code from a `shared/` folder to minimize the amount of code run what launching a web worker. + ## License Agreement If you contribute code to this project, you are implicitly allowing your code to be distributed under the MIT license. You are also implicitly verifying that all code is your original work. From 8d3bdad7e478d31ed7149ef6bca36254a172ccf0 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 16 Jan 2018 07:06:10 -0800 Subject: [PATCH 07/26] Fix search for wide unicode Part of #1103 --- src/addons/search/SearchHelper.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/addons/search/SearchHelper.ts b/src/addons/search/SearchHelper.ts index 5735dd48e..015acf98a 100644 --- a/src/addons/search/SearchHelper.ts +++ b/src/addons/search/SearchHelper.ts @@ -114,8 +114,17 @@ export class SearchHelper { private _findInLine(term: string, y: number): ISearchResult { const lowerStringLine = this._terminal.buffer.translateBufferLineToString(y, true).toLowerCase(); const lowerTerm = term.toLowerCase(); - const searchIndex = lowerStringLine.indexOf(lowerTerm); + let searchIndex = lowerStringLine.indexOf(lowerTerm); if (searchIndex >= 0) { + const line = this._terminal.buffer.lines.get(y); + for (let i = 0; i < searchIndex; i++) { + // Adjust the selection for empty characters following wide unicode chars + const char = line[i]; + const charWidth = char[2/*CHAR_DATA_WIDTH_INDEX*/]; + if (charWidth === 0) { + searchIndex++; + } + } return { term, col: searchIndex, From 0e870d106fc872c788fa9e9edce751dbdde3cd79 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 16 Jan 2018 07:26:03 -0800 Subject: [PATCH 08/26] Fix search for emojis Fixes #1103 --- src/addons/search/SearchHelper.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/addons/search/SearchHelper.ts b/src/addons/search/SearchHelper.ts index 015acf98a..705c41c70 100644 --- a/src/addons/search/SearchHelper.ts +++ b/src/addons/search/SearchHelper.ts @@ -118,9 +118,15 @@ export class SearchHelper { if (searchIndex >= 0) { const line = this._terminal.buffer.lines.get(y); for (let i = 0; i < searchIndex; i++) { - // Adjust the selection for empty characters following wide unicode chars - const char = line[i]; - const charWidth = char[2/*CHAR_DATA_WIDTH_INDEX*/]; + const charData = line[i]; + // Adjust the searchIndex to normalize emoji into single chars + const char = charData[1/*CHAR_DATA_CHAR_INDEX*/]; + if (char.length > 1) { + searchIndex -= char.length - 1; + } + // Adjust the searchIndex for empty characters following wide unicode + // chars (eg. CJK) + const charWidth = charData[2/*CHAR_DATA_WIDTH_INDEX*/]; if (charWidth === 0) { searchIndex++; } From 47df04976ce8c51cb628f1e30493328bd0086fbf Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 18 Jan 2018 20:17:13 -0800 Subject: [PATCH 09/26] Base ITerminal on interface in .d.ts Part of #1221 --- src/EventEmitter.test.ts | 12 ------- src/EventEmitter.ts | 22 ++++-------- src/Interfaces.ts | 34 ++++-------------- src/Terminal.ts | 10 +++--- src/renderer/Interfaces.ts | 3 +- src/utils/TestUtils.test.ts | 72 +++++++++++++++++++++++++++++++++---- typings/xterm.d.ts | 12 +++++-- 7 files changed, 96 insertions(+), 69 deletions(-) diff --git a/src/EventEmitter.test.ts b/src/EventEmitter.test.ts index c1f0a0aba..f2d31cf64 100644 --- a/src/EventEmitter.test.ts +++ b/src/EventEmitter.test.ts @@ -13,18 +13,6 @@ describe('EventEmitter', () => { eventEmitter = new EventEmitter(); }); - describe('once', () => { - it('should trigger the listener only once', () => { - let count = 0; - const listener = () => count++; - eventEmitter.once('test', listener); - eventEmitter.emit('test'); - assert.equal(count, 1); - eventEmitter.emit('test'); - assert.equal(count, 1); - }); - }); - describe('emit', () => { it('should emit events to listeners', () => { let count1 = 0; diff --git a/src/EventEmitter.ts b/src/EventEmitter.ts index 414eac895..440eab2b6 100644 --- a/src/EventEmitter.ts +++ b/src/EventEmitter.ts @@ -3,10 +3,10 @@ * @license MIT */ -import { IEventEmitter, IListenerType } from './Interfaces'; +import { IEventEmitter } from 'xterm'; export class EventEmitter implements IEventEmitter { - private _events: {[type: string]: IListenerType[]}; + private _events: {[type: string]: ((...args: any[]) => void)[]}; constructor() { // Restore the previous events if available, this will happen if the @@ -14,12 +14,12 @@ export class EventEmitter implements IEventEmitter { this._events = this._events || {}; } - public on(type: string, listener: IListenerType): void { + public on(type: string, listener: ((...args: any[]) => void)): void { this._events[type] = this._events[type] || []; this._events[type].push(listener); } - public off(type: string, listener: IListenerType): void { + public off(type: string, listener: ((...args: any[]) => void)): void { if (!this._events[type]) { return; } @@ -28,7 +28,7 @@ export class EventEmitter implements IEventEmitter { let i = obj.length; while (i--) { - if (obj[i] === listener || obj[i].listener === listener) { + if (obj[i] === listener) { obj.splice(i, 1); return; } @@ -41,16 +41,6 @@ export class EventEmitter implements IEventEmitter { } } - public once(type: string, listener: IListenerType): void { - function on(): void { - let args = Array.prototype.slice.call(arguments); - this.off(type, on); - listener.apply(this, args); - } - (on).listener = listener; - this.on(type, on); - } - public emit(type: string, ...args: any[]): void { if (!this._events[type]) { return; @@ -61,7 +51,7 @@ export class EventEmitter implements IEventEmitter { } } - public listeners(type: string): IListenerType[] { + public listeners(type: string): ((...args: any[]) => void)[] { return this._events[type] || []; } diff --git a/src/Interfaces.ts b/src/Interfaces.ts index 8f0baa2f3..57d45752d 100644 --- a/src/Interfaces.ts +++ b/src/Interfaces.ts @@ -3,6 +3,9 @@ * @license MIT */ +/// + +import { Terminal as PublicTerminal, ITerminalOptions as IPublicTerminalOptions, IEventEmitter } from 'xterm'; import { ICharset, ILinkMatcherOptions } from './Interfaces'; import { LinkMatcherHandler, LinkMatcherValidationCallback, LineData } from './Types'; import { IColorSet, IRenderer } from './renderer/Interfaces'; @@ -32,7 +35,7 @@ export interface ILinkifierAccessor { linkifier: ILinkifier; } -export interface ITerminal extends ILinkifierAccessor, IBufferAccessor, IElementAccessor, IEventEmitter { +export interface ITerminal extends PublicTerminal, ILinkifierAccessor, IBufferAccessor, IElementAccessor { selectionManager: ISelectionManager; charMeasure: ICharMeasure; textarea: HTMLTextAreaElement; @@ -127,28 +130,14 @@ export interface IInputHandlingTerminal extends IEventEmitter { setOption(key: string, value: any): void; } -export interface ITerminalOptions { - bellSound?: string; - bellStyle?: string; +// TODO: The options that are not in the public API should be reviewed +export interface ITerminalOptions extends IPublicTerminalOptions { cancelEvents?: boolean; - cols?: number; convertEol?: boolean; - cursorBlink?: boolean; - cursorStyle?: string; debug?: boolean; - disableStdin?: boolean; - enableBold?: boolean; - fontSize?: number; - fontFamily?: string; handler?: (data: string) => void; - letterSpacing?: number; - lineHeight?: number; - rows?: number; screenKeys?: boolean; - scrollback?: number; - tabStopWidth?: number; termName?: string; - theme?: ITheme; useFlowControl?: boolean; } @@ -239,17 +228,6 @@ export interface ICircularList extends IEventEmitter { shiftElements(start: number, count: number, offset: number): void; } -export interface IEventEmitter { - on(type: string, listener: IListenerType): void; - off(type: string, listener: IListenerType): void; - emit(type: string, data?: any): void; -} - -export interface IListenerType { - (data?: any): void; - listener?: (data?: any) => void; -} - export interface ILinkMatcherOptions { /** * The index of the link from the regex.match(text) call. This defaults to 0 diff --git a/src/Terminal.ts b/src/Terminal.ts index d9bb27d10..b66372976 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -2112,13 +2112,15 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT } private visualBell(): boolean { - return this.options.bellStyle === 'visual' || - this.options.bellStyle === 'both'; + return false; + // return this.options.bellStyle === 'visual' || + // this.options.bellStyle === 'both'; } private soundBell(): boolean { - return this.options.bellStyle === 'sound' || - this.options.bellStyle === 'both'; + return this.options.bellStyle === 'sound'; + // return this.options.bellStyle === 'sound' || + // this.options.bellStyle === 'both'; } private syncBellSound(): void { diff --git a/src/renderer/Interfaces.ts b/src/renderer/Interfaces.ts index be1b39dd1..2c07b3a9b 100644 --- a/src/renderer/Interfaces.ts +++ b/src/renderer/Interfaces.ts @@ -3,7 +3,8 @@ * @license MIT */ -import { ITerminal, ITerminalOptions, ITheme, IEventEmitter } from '../Interfaces'; +import { ITerminal, ITerminalOptions, ITheme } from '../Interfaces'; +import { IEventEmitter } from 'xterm'; export interface IRenderer extends IEventEmitter { dimensions: IRenderDimensions; diff --git a/src/utils/TestUtils.test.ts b/src/utils/TestUtils.test.ts index 80e252774..12b032984 100644 --- a/src/utils/TestUtils.test.ts +++ b/src/utils/TestUtils.test.ts @@ -3,13 +3,73 @@ * @license MIT */ -import { ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, IListenerType, IInputHandlingTerminal, IViewport, ICircularList, ICompositionHelper, ITheme, ILinkifier, IMouseHelper } from '../Interfaces'; +import { ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, IInputHandlingTerminal, IViewport, ICircularList, ICompositionHelper, ITheme, ILinkifier, IMouseHelper, ILinkMatcherOptions } from '../Interfaces'; import { LineData } from '../Types'; import { Buffer } from '../Buffer'; import * as Browser from './Browser'; import { IColorSet, IRenderer, IRenderDimensions, IColorManager } from '../renderer/Interfaces'; export class MockTerminal implements ITerminal { + getOption(key: any): any { + throw new Error('Method not implemented.'); + } + setOption(key: any, value: any): void { + throw new Error('Method not implemented.'); + } + blur(): void { + throw new Error('Method not implemented.'); + } + focus(): void { + throw new Error('Method not implemented.'); + } + resize(columns: number, rows: number): void { + throw new Error('Method not implemented.'); + } + writeln(data: string): void { + throw new Error('Method not implemented.'); + } + open(parent: HTMLElement): void { + throw new Error('Method not implemented.'); + } + attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void { + throw new Error('Method not implemented.'); + } + registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => boolean | void, options?: ILinkMatcherOptions): number { + throw new Error('Method not implemented.'); + } + deregisterLinkMatcher(matcherId: number): void { + throw new Error('Method not implemented.'); + } + hasSelection(): boolean { + throw new Error('Method not implemented.'); + } + getSelection(): string { + throw new Error('Method not implemented.'); + } + clearSelection(): void { + throw new Error('Method not implemented.'); + } + selectAll(): void { + throw new Error('Method not implemented.'); + } + destroy(): void { + throw new Error('Method not implemented.'); + } + scrollPages(pageCount: number): void { + throw new Error('Method not implemented.'); + } + scrollToTop(): void { + throw new Error('Method not implemented.'); + } + scrollToBottom(): void { + throw new Error('Method not implemented.'); + } + clear(): void { + throw new Error('Method not implemented.'); + } + write(data: string): void { + throw new Error('Method not implemented.'); + } bracketedPasteMode: boolean; mouseHelper: IMouseHelper; renderer: IRenderer; @@ -39,7 +99,7 @@ export class MockTerminal implements ITerminal { on(event: string, callback: () => void): void { throw new Error('Method not implemented.'); } - off(type: string, listener: IListenerType): void { + off(type: string, listener: (...args: any[]) => void): void { throw new Error('Method not implemented.'); } scrollLines(disp: number, suppressScrollEvent: boolean): void { @@ -184,10 +244,10 @@ export class MockInputHandlingTerminal implements IInputHandlingTerminal { setOption(key: string, value: any): void { this.options[key] = value; } - on(type: string, listener: IListenerType): void { + on(type: string, listener: (...args: any[]) => void): void { throw new Error('Method not implemented.'); } - off(type: string, listener: IListenerType): void { + off(type: string, listener: (...args: any[]) => void): void { throw new Error('Method not implemented.'); } emit(type: string, data?: any): void { @@ -220,10 +280,10 @@ export class MockBuffer implements IBuffer { export class MockRenderer implements IRenderer { colorManager: IColorManager; - on(type: string, listener: IListenerType): void { + on(type: string, listener: (...args: any[]) => void): void { throw new Error('Method not implemented.'); } - off(type: string, listener: IListenerType): void { + off(type: string, listener: (...args: any[]) => void): void { throw new Error('Method not implemented.'); } emit(type: string, data?: any): void { diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 83199e08b..bf13dda50 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -172,10 +172,16 @@ declare module 'xterm' { priority?: number; } + export interface IEventEmitter { + on(type: string, listener: (...args: any[]) => void): void; + off(type: string, listener: (...args: any[]) => void): void; + emit(type: string, data?: any): void; + } + /** * The class that represents an xterm.js terminal. */ - export class Terminal { + export class Terminal implements IEventEmitter { /** * The element containing the terminal. */ @@ -224,7 +230,7 @@ declare module 'xterm' { * @param type The type of the event. * @param listener The listener. */ - on(type: 'data', listener: (data?: string) => void): void; + on(type: 'data', listener: (...args: any[]) => void): void; /** * Registers an event listener. * @param type The type of the event. @@ -275,6 +281,8 @@ declare module 'xterm' { */ off(type: 'blur' | 'focus' | 'linefeed' | 'selection' | 'data' | 'key' | 'keypress' | 'keydown' | 'refresh' | 'resize' | 'scroll' | 'title' | string, listener: (...args: any[]) => void): void; + emit(type: string, data?: any): void; + /** * Resizes the terminal. * @param x The number of columns to resize to. From 78a63d486019937676e8be337efaa7c1368bf537 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 18 Jan 2018 20:24:30 -0800 Subject: [PATCH 10/26] Simplify interfaces, reduce duplication --- src/Interfaces.ts | 5 ----- typings/xterm.d.ts | 16 ---------------- 2 files changed, 21 deletions(-) diff --git a/src/Interfaces.ts b/src/Interfaces.ts index 57d45752d..b5026df60 100644 --- a/src/Interfaces.ts +++ b/src/Interfaces.ts @@ -38,10 +38,7 @@ export interface ILinkifierAccessor { export interface ITerminal extends PublicTerminal, ILinkifierAccessor, IBufferAccessor, IElementAccessor { selectionManager: ISelectionManager; charMeasure: ICharMeasure; - textarea: HTMLTextAreaElement; renderer: IRenderer; - rows: number; - cols: number; browser: IBrowser; writeBuffer: string[]; cursorHidden: boolean; @@ -61,10 +58,8 @@ export interface ITerminal extends PublicTerminal, ILinkifierAccessor, IBufferAc scrollLines(disp: number, suppressScrollEvent?: boolean): void; cancel(ev: Event, force?: boolean): boolean | void; log(text: string): void; - reset(): void; showCursor(): void; blankLine(cur?: boolean, isWrapped?: boolean, cols?: number): LineData; - refresh(start: number, end: number): void; } /** diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index bf13dda50..26aa5e0ed 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -354,22 +354,6 @@ declare module 'xterm' { */ selectAll(): void; - // /** - // * Find the next instance of the term, then scroll to and select it. If it - // * doesn't exist, do nothing. - // * @param term Tne search term. - // * @return Whether a result was found. - // */ - // findNext(term: string): boolean; - - // /** - // * Find the previous instance of the term, then scroll to and select it. If it - // * doesn't exist, do nothing. - // * @param term Tne search term. - // * @return Whether a result was found. - // */ - // findPrevious(term: string): boolean; - /** * Destroys the terminal and detaches it from the DOM. */ From e4abd4dd8a61d39886f4f59af2ed7446f9cebab7 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 18 Jan 2018 21:39:43 -0800 Subject: [PATCH 11/26] Move Shared interfaces into a new typings file This will enable sharing the internal interface with addons (and catching breakages early) --- src/Buffer.test.ts | 2 +- src/Buffer.ts | 3 +- src/BufferSet.test.ts | 2 +- src/BufferSet.ts | 2 +- src/CompositionHelper.ts | 2 +- src/InputHandler.ts | 4 +- src/Interfaces.ts | 192 +------------------- src/Linkifier.test.ts | 5 +- src/Linkifier.ts | 6 +- src/SelectionManager.test.ts | 3 +- src/SelectionManager.ts | 3 +- src/SelectionModel.test.ts | 2 +- src/SelectionModel.ts | 2 +- src/Terminal.ts | 7 +- src/Types.ts | 6 - src/Viewport.ts | 4 +- src/handlers/Clipboard.ts | 2 +- src/input/Interfaces.ts | 19 -- src/input/MouseZoneManager.ts | 3 +- src/renderer/BaseRenderLayer.ts | 5 +- src/renderer/CharAtlas.ts | 3 +- src/renderer/ColorManager.ts | 3 +- src/renderer/CursorRenderLayer.ts | 5 +- src/renderer/Interfaces.ts | 48 +---- src/renderer/LinkRenderLayer.ts | 4 +- src/renderer/Renderer.ts | 4 +- src/renderer/SelectionRenderLayer.ts | 3 +- src/renderer/TextRenderLayer.ts | 4 +- src/utils/CharMeasure.test.ts | 2 +- src/utils/CharMeasure.ts | 2 +- src/utils/CircularList.ts | 2 +- src/utils/MouseHelper.ts | 5 +- src/utils/TestUtils.test.ts | 6 +- typings/xterm-internal.d.ts | 259 +++++++++++++++++++++++++++ 34 files changed, 307 insertions(+), 317 deletions(-) delete mode 100644 src/input/Interfaces.ts create mode 100644 typings/xterm-internal.d.ts diff --git a/src/Buffer.test.ts b/src/Buffer.test.ts index 210d29718..b2522d1c4 100644 --- a/src/Buffer.test.ts +++ b/src/Buffer.test.ts @@ -4,7 +4,7 @@ */ import { assert } from 'chai'; -import { ITerminal } from './Interfaces'; +import { ITerminal } from '../typings/xterm-internal'; import { Buffer } from './Buffer'; import { CircularList } from './utils/CircularList'; import { MockTerminal } from './utils/TestUtils.test'; diff --git a/src/Buffer.ts b/src/Buffer.ts index 623c38543..f8610ea78 100644 --- a/src/Buffer.ts +++ b/src/Buffer.ts @@ -3,9 +3,8 @@ * @license MIT */ -import { ITerminal, IBuffer } from './Interfaces'; +import { ITerminal, IBuffer, LineData, CharData } from '../typings/xterm-internal'; import { CircularList } from './utils/CircularList'; -import { LineData, CharData } from './Types'; export const CHAR_DATA_ATTR_INDEX = 0; export const CHAR_DATA_CHAR_INDEX = 1; diff --git a/src/BufferSet.test.ts b/src/BufferSet.test.ts index b9c1824db..921b5442c 100644 --- a/src/BufferSet.test.ts +++ b/src/BufferSet.test.ts @@ -4,7 +4,7 @@ */ import { assert } from 'chai'; -import { ITerminal } from './Interfaces'; +import { ITerminal } from '../typings/xterm-internal'; import { BufferSet } from './BufferSet'; import { Buffer } from './Buffer'; import { MockTerminal } from './utils/TestUtils.test'; diff --git a/src/BufferSet.ts b/src/BufferSet.ts index e31d2278f..eb6f4507b 100644 --- a/src/BufferSet.ts +++ b/src/BufferSet.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ITerminal, IBufferSet } from './Interfaces'; +import { ITerminal, IBufferSet } from '../typings/xterm-internal'; import { Buffer } from './Buffer'; import { EventEmitter } from './EventEmitter'; diff --git a/src/CompositionHelper.ts b/src/CompositionHelper.ts index e588be783..7c1888dd6 100644 --- a/src/CompositionHelper.ts +++ b/src/CompositionHelper.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ITerminal } from './Interfaces'; +import { ITerminal } from '../typings/xterm-internal'; interface IPosition { start: number; diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 7d3a4d24b..42b89543d 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -4,10 +4,10 @@ * @license MIT */ -import { IInputHandler, ITerminal, IInputHandlingTerminal } from './Interfaces'; +import { CharData, ITerminal } from '../typings/xterm-internal'; +import { IInputHandler, IInputHandlingTerminal } from './Interfaces'; import { C0 } from './EscapeSequences'; import { DEFAULT_CHARSET } from './Charsets'; -import { CharData } from './Types'; import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX } from './Buffer'; import { FLAGS } from './renderer/Types'; import { wcwidth } from './CharWidth'; diff --git a/src/Interfaces.ts b/src/Interfaces.ts index b5026df60..b639d5a3d 100644 --- a/src/Interfaces.ts +++ b/src/Interfaces.ts @@ -3,64 +3,11 @@ * @license MIT */ -/// +import { IEventEmitter } from 'xterm'; +import { ITerminalOptions, ILinkMatcherOptions, IMouseZoneManager, LinkMatcherHandler, LinkMatcherValidationCallback, LineData, IColorSet, IRenderer, IBufferSet, IBuffer, ISelectionManager } from '../typings/xterm-internal'; +import { ICharset } from './Interfaces'; -import { Terminal as PublicTerminal, ITerminalOptions as IPublicTerminalOptions, IEventEmitter } from 'xterm'; -import { ICharset, ILinkMatcherOptions } from './Interfaces'; -import { LinkMatcherHandler, LinkMatcherValidationCallback, LineData } from './Types'; -import { IColorSet, IRenderer } from './renderer/Interfaces'; -import { IMouseZoneManager } from './input/Interfaces'; -export interface IBrowser { - isNode: boolean; - userAgent: string; - platform: string; - isFirefox: boolean; - isMSIE: boolean; - isMac: boolean; - isIpad: boolean; - isIphone: boolean; - isMSWindows: boolean; -} - -export interface IBufferAccessor { - buffer: IBuffer; -} - -export interface IElementAccessor { - element: HTMLElement; -} - -export interface ILinkifierAccessor { - linkifier: ILinkifier; -} - -export interface ITerminal extends PublicTerminal, ILinkifierAccessor, IBufferAccessor, IElementAccessor { - selectionManager: ISelectionManager; - charMeasure: ICharMeasure; - renderer: IRenderer; - browser: IBrowser; - writeBuffer: string[]; - cursorHidden: boolean; - cursorState: number; - defAttr: number; - options: ITerminalOptions; - buffers: IBufferSet; - isFocused: boolean; - mouseHelper: IMouseHelper; - bracketedPasteMode: boolean; - - /** - * Emit the 'data' event and populate the given data. - * @param data The data to populate in the event. - */ - handler(data: string): void; - scrollLines(disp: number, suppressScrollEvent?: boolean): void; - cancel(ev: Event, force?: boolean): boolean | void; - log(text: string): void; - showCursor(): void; - blankLine(cur?: boolean, isWrapped?: boolean, cols?: number): LineData; -} /** * This interface encapsulates everything needed from the Terminal by the @@ -125,48 +72,6 @@ export interface IInputHandlingTerminal extends IEventEmitter { setOption(key: string, value: any): void; } -// TODO: The options that are not in the public API should be reviewed -export interface ITerminalOptions extends IPublicTerminalOptions { - cancelEvents?: boolean; - convertEol?: boolean; - debug?: boolean; - handler?: (data: string) => void; - screenKeys?: boolean; - termName?: string; - useFlowControl?: boolean; -} - -export interface IBuffer { - lines: ICircularList; - ydisp: number; - ybase: number; - y: number; - x: number; - tabs: any; - scrollBottom: number; - scrollTop: number; - savedY: number; - savedX: number; - isCursorInViewport: boolean; - translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol?: number, endCol?: number): string; - nextStop(x?: number): number; - prevStop(x?: number): number; -} - -export interface IBufferSet { - alt: IBuffer; - normal: IBuffer; - active: IBuffer; - - activateNormalBuffer(): void; - activateAltBuffer(): void; -} - -export interface IMouseHelper { - getCoords(event: {pageX: number, pageY: number}, element: HTMLElement, charMeasure: ICharMeasure, lineHeight: number, colCount: number, rowCount: number, isSelection?: boolean): [number, number]; - getRawByteCoords(event: MouseEvent, element: HTMLElement, charMeasure: ICharMeasure, lineHeight: number, colCount: number, rowCount: number): { x: number, y: number }; -} - export interface IViewport { syncScrollArea(): void; onWheel(ev: WheelEvent): void; @@ -175,17 +80,6 @@ export interface IViewport { onThemeChanged(colors: IColorSet): void; } -export interface ISelectionManager { - selectionText: string; - selectionStart: [number, number]; - selectionEnd: [number, number]; - - disable(): void; - enable(): void; - setBuffer(buffer: IBuffer): void; - setSelection(row: number, col: number, length: number): void; -} - export interface ICompositionHelper { compositionstart(): void; compositionupdate(ev: CompositionEvent): void; @@ -194,62 +88,6 @@ export interface ICompositionHelper { keydown(ev: KeyboardEvent): boolean; } -export interface ICharMeasure { - width: number; - height: number; - measure(options: ITerminalOptions): void; -} - -export interface ILinkifier extends IEventEmitter { - attachToDom(mouseZoneManager: IMouseZoneManager): void; - linkifyRows(start: number, end: number): void; - setHypertextLinkHandler(handler: LinkMatcherHandler): void; - setHypertextValidationCallback(callback: LinkMatcherValidationCallback): void; - registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler, options?: ILinkMatcherOptions): number; - deregisterLinkMatcher(matcherId: number): boolean; -} - -export interface ICircularList extends IEventEmitter { - length: number; - maxLength: number; - forEach: (callbackfn: (value: T, index: number) => void) => void; - - get(index: number): T; - set(index: number, value: T): void; - push(value: T): void; - pop(): T; - splice(start: number, deleteCount: number, ...items: T[]): void; - trimStart(count: number): void; - shiftElements(start: number, count: number, offset: number): void; -} - -export interface ILinkMatcherOptions { - /** - * The index of the link from the regex.match(text) call. This defaults to 0 - * (for regular expressions without capture groups). - */ - matchIndex?: number; - /** - * A callback that validates an individual link, returning true if valid and - * false if invalid. - */ - validationCallback?: LinkMatcherValidationCallback; - /** - * A callback that fires when the mouse hovers over a link. - */ - tooltipCallback?: LinkMatcherHandler; - /** - * A callback that fires when the mouse leaves a link that was hovered. - */ - leaveCallback?: () => void; - /** - * The priority of the link matcher, this defines the order in which the link - * matcher is evaluated relative to others, from highest to lowest. The - * default value is 0. - */ - priority?: number; -} - /** * Handles actions generated by the parser. */ @@ -302,30 +140,6 @@ export interface IInputHandler { /** CSI u */ restoreCursor(params?: number[]): void; } -export interface ITheme { - foreground?: string; - background?: string; - cursor?: string; - cursorAccent?: string; - selection?: string; - black?: string; - red?: string; - green?: string; - yellow?: string; - blue?: string; - magenta?: string; - cyan?: string; - white?: string; - brightBlack?: string; - brightRed?: string; - brightGreen?: string; - brightYellow?: string; - brightBlue?: string; - brightMagenta?: string; - brightCyan?: string; - brightWhite?: string; -} - export interface ILinkMatcher { id: number; regex: RegExp; diff --git a/src/Linkifier.test.ts b/src/Linkifier.test.ts index 8b66dcaa5..1a7c60476 100644 --- a/src/Linkifier.test.ts +++ b/src/Linkifier.test.ts @@ -4,10 +4,9 @@ */ import { assert } from 'chai'; -import { ITerminal, ILinkifier, ILinkMatcher, IBuffer, IBufferAccessor, IElementAccessor } from './Interfaces'; +import { ITerminal, ILinkifier, IBuffer, IBufferAccessor, IElementAccessor, LineData, IMouseZoneManager, IMouseZone } from '../typings/xterm-internal'; +import { ILinkMatcher } from './Interfaces'; import { Linkifier } from './Linkifier'; -import { LineData } from './Types'; -import { IMouseZoneManager, IMouseZone } from './input/Interfaces'; import { MockBuffer } from './utils/TestUtils.test'; import { CircularList } from './utils/CircularList'; diff --git a/src/Linkifier.ts b/src/Linkifier.ts index 767719301..5d601fce7 100644 --- a/src/Linkifier.ts +++ b/src/Linkifier.ts @@ -3,9 +3,9 @@ * @license MIT */ -import { ILinkHoverEvent, ILinkMatcher, ILinkMatcherOptions, ITerminal, IBufferAccessor, ILinkifier, IElementAccessor } from './Interfaces'; -import { LinkMatcherHandler, LinkMatcherValidationCallback, LineData, LinkHoverEventTypes } from './Types'; -import { IMouseZoneManager } from './input/Interfaces'; +import { ILinkMatcherOptions, ITerminal, IBufferAccessor, ILinkifier, IElementAccessor, LinkMatcherHandler, LinkMatcherValidationCallback, LineData, IMouseZoneManager } from '../typings/xterm-internal'; +import { ILinkHoverEvent, ILinkMatcher } from './Interfaces'; +import { LinkHoverEventTypes } from './Types'; import { MouseZone } from './input/MouseZoneManager'; import { EventEmitter } from './EventEmitter'; diff --git a/src/SelectionManager.test.ts b/src/SelectionManager.test.ts index a10dc6692..08f2d9814 100644 --- a/src/SelectionManager.test.ts +++ b/src/SelectionManager.test.ts @@ -4,15 +4,14 @@ */ import jsdom = require('jsdom'); +import { ITerminal, ICircularList, IBuffer, LineData, CharData } from '../typings/xterm-internal'; import { assert } from 'chai'; -import { ITerminal, ICircularList, IBuffer } from './Interfaces'; import { CharMeasure } from './utils/CharMeasure'; import { CircularList } from './utils/CircularList'; import { SelectionManager } from './SelectionManager'; import { SelectionModel } from './SelectionModel'; import { BufferSet } from './BufferSet'; import { MockTerminal } from './utils/TestUtils.test'; -import { LineData, CharData } from './Types'; class TestMockTerminal extends MockTerminal { emit(event: string, data: any): void {} diff --git a/src/SelectionManager.ts b/src/SelectionManager.ts index cd6fc9961..5061fd9d3 100644 --- a/src/SelectionManager.ts +++ b/src/SelectionManager.ts @@ -3,14 +3,13 @@ * @license MIT */ +import { ITerminal, ICircularList, ISelectionManager, IBuffer, LineData, CharData } from '../typings/xterm-internal'; import { MouseHelper } from './utils/MouseHelper'; import * as Browser from './utils/Browser'; import { CharMeasure } from './utils/CharMeasure'; import { CircularList } from './utils/CircularList'; import { EventEmitter } from './EventEmitter'; -import { ITerminal, ICircularList, ISelectionManager, IBuffer } from './Interfaces'; import { SelectionModel } from './SelectionModel'; -import { LineData, CharData } from './Types'; import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from './Buffer'; /** diff --git a/src/SelectionModel.test.ts b/src/SelectionModel.test.ts index eda947188..b84fef5ec 100644 --- a/src/SelectionModel.test.ts +++ b/src/SelectionModel.test.ts @@ -4,7 +4,7 @@ */ import { assert } from 'chai'; -import { ITerminal } from './Interfaces'; +import { ITerminal } from '../typings/xterm-internal'; import { SelectionModel } from './SelectionModel'; import { BufferSet } from './BufferSet'; import { MockTerminal } from './utils/TestUtils.test'; diff --git a/src/SelectionModel.ts b/src/SelectionModel.ts index 5982b1e91..1e0f816d9 100644 --- a/src/SelectionModel.ts +++ b/src/SelectionModel.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ITerminal } from './Interfaces'; +import { ITerminal } from '../typings/xterm-internal'; /** * Represents a selection within the buffer. This model only cares about column diff --git a/src/Terminal.ts b/src/Terminal.ts index b66372976..dbdd700b4 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -21,6 +21,7 @@ * http://linux.die.net/man/7/urxvt */ +import { ITerminalOptions, ITerminal, IBrowser, IRenderer, ILinkifier, IMouseZoneManager, ITheme, LinkMatcherHandler, LinkMatcherValidationCallback, ILinkMatcherOptions, CharData, LineData } from '../typings/xterm-internal'; import { BufferSet } from './BufferSet'; import { Buffer, MAX_BUFFER_SIZE } from './Buffer'; import { CompositionHelper } from './CompositionHelper'; @@ -38,14 +39,12 @@ import { CharMeasure } from './utils/CharMeasure'; import * as Browser from './utils/Browser'; import { MouseHelper } from './utils/MouseHelper'; import { CHARSETS } from './Charsets'; -import { CustomKeyEventHandler, LinkMatcherHandler, LinkMatcherValidationCallback, CharData, LineData } from './Types'; -import { ITerminal, IBrowser, ICharset, ITerminalOptions, IInputHandlingTerminal, ILinkMatcherOptions, IViewport, ICompositionHelper, ITheme, ILinkifier } from './Interfaces'; +import { CustomKeyEventHandler } from './Types'; +import { ICharset, IInputHandlingTerminal, IViewport, ICompositionHelper } from './Interfaces'; import { BELL_SOUND } from './utils/Sounds'; import { DEFAULT_ANSI_COLORS } from './renderer/ColorManager'; -import { IMouseZoneManager } from './input/Interfaces'; import { MouseZoneManager } from './input/MouseZoneManager'; import { initialize as initializeCharAtlas } from './renderer/CharAtlas'; -import { IRenderer } from './renderer/Interfaces'; // Let it work inside Node.js for automated testing purposes. const document = (typeof window !== 'undefined') ? window.document : null; diff --git a/src/Types.ts b/src/Types.ts index 3263282e0..e112d6d96 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -3,14 +3,8 @@ * @license MIT */ -export type LinkMatcherHandler = (event: MouseEvent, uri: string) => boolean | void; -export type LinkMatcherValidationCallback = (uri: string, callback: (isValid: boolean) => void) => void; - export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean; -export type CharData = [number, string, number, number]; -export type LineData = CharData[]; - export enum LinkHoverEventTypes { HOVER = 'linkhover', TOOLTIP = 'linktooltip', diff --git a/src/Viewport.ts b/src/Viewport.ts index fcac68ad4..147cc90e9 100644 --- a/src/Viewport.ts +++ b/src/Viewport.ts @@ -3,9 +3,9 @@ * @license MIT */ -import { ITerminal, IViewport } from './Interfaces'; +import { ITerminal, IColorSet } from '../typings/xterm-internal'; +import { IViewport } from './Interfaces'; import { CharMeasure } from './utils/CharMeasure'; -import { IColorSet } from './renderer/Interfaces'; /** * Represents the viewport of a terminal, the visible area within the larger buffer of output. diff --git a/src/handlers/Clipboard.ts b/src/handlers/Clipboard.ts index cf6661fe2..1974ef88b 100644 --- a/src/handlers/Clipboard.ts +++ b/src/handlers/Clipboard.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ITerminal, ISelectionManager } from '../Interfaces'; +import { ITerminal, ISelectionManager } from '../../typings/xterm-internal'; interface IWindow extends Window { clipboardData?: { diff --git a/src/input/Interfaces.ts b/src/input/Interfaces.ts deleted file mode 100644 index 21514a53c..000000000 --- a/src/input/Interfaces.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2017 The xterm.js authors. All rights reserved. - * @license MIT - */ - -export interface IMouseZoneManager { - add(zone: IMouseZone): void; - clearAll(start?: number, end?: number): void; -} - -export interface IMouseZone { - x1: number; - x2: number; - y: number; - clickCallback: (e: MouseEvent) => any; - hoverCallback?: (e: MouseEvent) => any; - tooltipCallback?: (e: MouseEvent) => any; - leaveCallback?: () => any; -} diff --git a/src/input/MouseZoneManager.ts b/src/input/MouseZoneManager.ts index 6fbe1c673..f9413e629 100644 --- a/src/input/MouseZoneManager.ts +++ b/src/input/MouseZoneManager.ts @@ -3,8 +3,7 @@ * @license MIT */ -import { IMouseZoneManager, IMouseZone } from './Interfaces'; -import { ITerminal } from '../Interfaces'; +import { IMouseZoneManager, IMouseZone, ITerminal } from '../../typings/xterm-internal'; const HOVER_DURATION = 500; diff --git a/src/renderer/BaseRenderLayer.ts b/src/renderer/BaseRenderLayer.ts index b4becbce0..299d8b6f1 100644 --- a/src/renderer/BaseRenderLayer.ts +++ b/src/renderer/BaseRenderLayer.ts @@ -3,10 +3,9 @@ * @license MIT */ -import { IRenderLayer, IColorSet, IRenderDimensions } from './Interfaces'; -import { ITerminal, ITerminalOptions } from '../Interfaces'; +import { IColorSet, IRenderDimensions, ITerminal, ITerminalOptions, CharData } from '../../typings/xterm-internal'; +import { IRenderLayer } from './Interfaces'; import { acquireCharAtlas, CHAR_ATLAS_CELL_SPACING } from './CharAtlas'; -import { CharData } from '../Types'; import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer'; export const INVERTED_DEFAULT_COLOR = -1; diff --git a/src/renderer/CharAtlas.ts b/src/renderer/CharAtlas.ts index 9ac1e1618..3a7886ffe 100644 --- a/src/renderer/CharAtlas.ts +++ b/src/renderer/CharAtlas.ts @@ -3,8 +3,7 @@ * @license MIT */ -import { ITerminal, ITheme } from '../Interfaces'; -import { IColorSet } from '../renderer/Interfaces'; +import { ITerminal, ITheme, IColorSet } from '../../typings/xterm-internal'; import { isFirefox } from '../utils/Browser'; export const CHAR_ATLAS_CELL_SPACING = 1; diff --git a/src/renderer/ColorManager.ts b/src/renderer/ColorManager.ts index 6c0d29454..53fb165e0 100644 --- a/src/renderer/ColorManager.ts +++ b/src/renderer/ColorManager.ts @@ -3,8 +3,7 @@ * @license MIT */ -import { IColorSet, IColorManager } from './Interfaces'; -import { ITheme } from '../Interfaces'; +import { IColorSet, IColorManager, ITheme } from '../../typings/xterm-internal'; const DEFAULT_FOREGROUND = '#ffffff'; const DEFAULT_BACKGROUND = '#000000'; diff --git a/src/renderer/CursorRenderLayer.ts b/src/renderer/CursorRenderLayer.ts index 6ac489fcc..f6bbc0a61 100644 --- a/src/renderer/CursorRenderLayer.ts +++ b/src/renderer/CursorRenderLayer.ts @@ -3,13 +3,12 @@ * @license MIT */ -import { IColorSet, IRenderDimensions } from './Interfaces'; -import { IBuffer, ICharMeasure, ITerminal, ITerminalOptions } from '../Interfaces'; +import { IColorSet, IRenderDimensions, IBuffer, ICharMeasure, ITerminal, ITerminalOptions, CharData } from '../../typings/xterm-internal'; import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CODE_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer'; import { GridCache } from './GridCache'; import { FLAGS } from './Types'; import { BaseRenderLayer } from './BaseRenderLayer'; -import { CharData } from '../Types'; +import { } from '../Types'; interface ICursorState { x: number; diff --git a/src/renderer/Interfaces.ts b/src/renderer/Interfaces.ts index 2c07b3a9b..d65c9d359 100644 --- a/src/renderer/Interfaces.ts +++ b/src/renderer/Interfaces.ts @@ -3,26 +3,10 @@ * @license MIT */ -import { ITerminal, ITerminalOptions, ITheme } from '../Interfaces'; +import { IColorSet, IRenderDimensions, ITerminal } from '../../typings/xterm-internal'; + import { IEventEmitter } from 'xterm'; -export interface IRenderer extends IEventEmitter { - dimensions: IRenderDimensions; - colorManager: IColorManager; - - setTheme(theme: ITheme): IColorSet; - onWindowResize(devicePixelRatio: number): void; - onResize(cols: number, rows: number, didCharSizeChange: boolean): void; - onCharSizeChanged(): void; - onBlur(): void; - onFocus(): void; - onSelectionChanged(start: [number, number], end: [number, number]): void; - onCursorMove(): void; - onOptionsChanged(): void; - clear(): void; - queueRefresh(start: number, end: number): void; -} - export interface IRenderLayer { /** * Called when the terminal loses focus. @@ -70,31 +54,3 @@ export interface IRenderLayer { */ reset(terminal: ITerminal): void; } - -export interface IColorManager { - colors: IColorSet; -} - -export interface IColorSet { - foreground: string; - background: string; - cursor: string; - cursorAccent: string; - selection: string; - ansi: string[]; -} - -export interface IRenderDimensions { - scaledCharWidth: number; - scaledCharHeight: number; - scaledCellWidth: number; - scaledCellHeight: number; - scaledCharLeft: number; - scaledCharTop: number; - scaledCanvasWidth: number; - scaledCanvasHeight: number; - canvasWidth: number; - canvasHeight: number; - actualCellWidth: number; - actualCellHeight: number; -} diff --git a/src/renderer/LinkRenderLayer.ts b/src/renderer/LinkRenderLayer.ts index 87fbddbdf..24bc89b49 100644 --- a/src/renderer/LinkRenderLayer.ts +++ b/src/renderer/LinkRenderLayer.ts @@ -3,8 +3,8 @@ * @license MIT */ -import { IColorSet, IRenderDimensions } from './Interfaces'; -import { IBuffer, ICharMeasure, ILinkHoverEvent, ITerminal, ILinkifierAccessor } from '../Interfaces'; +import { IColorSet, IRenderDimensions, ITerminal, ILinkifierAccessor, IBuffer, ICharMeasure } from '../../typings/xterm-internal'; +import { ILinkHoverEvent } from '../Interfaces'; import { CHAR_DATA_ATTR_INDEX } from '../Buffer'; import { GridCache } from './GridCache'; import { FLAGS } from './Types'; diff --git a/src/renderer/Renderer.ts b/src/renderer/Renderer.ts index 680d9490f..afeefe3d9 100644 --- a/src/renderer/Renderer.ts +++ b/src/renderer/Renderer.ts @@ -3,14 +3,14 @@ * @license MIT */ -import { ITerminal, ITheme } from '../Interfaces'; +import { ITerminal, ITheme, IColorSet, IRenderer, IRenderDimensions } from '../../typings/xterm-internal'; import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer'; import { TextRenderLayer } from './TextRenderLayer'; import { SelectionRenderLayer } from './SelectionRenderLayer'; import { CursorRenderLayer } from './CursorRenderLayer'; import { ColorManager } from './ColorManager'; import { BaseRenderLayer } from './BaseRenderLayer'; -import { IRenderLayer, IColorSet, IRenderer, IRenderDimensions } from './Interfaces'; +import { IRenderLayer } from './Interfaces'; import { LinkRenderLayer } from './LinkRenderLayer'; import { EventEmitter } from '../EventEmitter'; import { ScreenDprMonitor } from '../utils/ScreenDprMonitor'; diff --git a/src/renderer/SelectionRenderLayer.ts b/src/renderer/SelectionRenderLayer.ts index 9740bb9a6..033da76a6 100644 --- a/src/renderer/SelectionRenderLayer.ts +++ b/src/renderer/SelectionRenderLayer.ts @@ -3,8 +3,7 @@ * @license MIT */ -import { IColorSet, IRenderDimensions } from './Interfaces'; -import { IBuffer, ICharMeasure, ITerminal } from '../Interfaces'; +import { IColorSet, IRenderDimensions, IBuffer, ICharMeasure, ITerminal } from '../../typings/xterm-internal'; import { CHAR_DATA_ATTR_INDEX } from '../Buffer'; import { GridCache } from './GridCache'; import { FLAGS } from './Types'; diff --git a/src/renderer/TextRenderLayer.ts b/src/renderer/TextRenderLayer.ts index 99a6feae9..f8d6a5bb0 100644 --- a/src/renderer/TextRenderLayer.ts +++ b/src/renderer/TextRenderLayer.ts @@ -3,12 +3,10 @@ * @license MIT */ -import { IColorSet, IRenderDimensions } from './Interfaces'; -import { IBuffer, ICharMeasure, ITerminal } from '../Interfaces'; +import { IBuffer, ICharMeasure, ITerminal, IColorSet, IRenderDimensions, CharData } from '../../typings/xterm-internal'; import { CHAR_DATA_ATTR_INDEX, CHAR_DATA_CODE_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX } from '../Buffer'; import { FLAGS } from './Types'; import { GridCache } from './GridCache'; -import { CharData } from '../Types'; import { BaseRenderLayer, INVERTED_DEFAULT_COLOR } from './BaseRenderLayer'; /** diff --git a/src/utils/CharMeasure.test.ts b/src/utils/CharMeasure.test.ts index f50ce96b7..a706ea3b4 100644 --- a/src/utils/CharMeasure.test.ts +++ b/src/utils/CharMeasure.test.ts @@ -4,8 +4,8 @@ */ import jsdom = require('jsdom'); +import { ICharMeasure, ITerminal } from '../../typings/xterm-internal'; import { assert } from 'chai'; -import { ICharMeasure, ITerminal } from '../Interfaces'; import { CharMeasure } from './CharMeasure'; describe('CharMeasure', () => { diff --git a/src/utils/CharMeasure.ts b/src/utils/CharMeasure.ts index 62291ab23..d91c10a4f 100644 --- a/src/utils/CharMeasure.ts +++ b/src/utils/CharMeasure.ts @@ -3,8 +3,8 @@ * @license MIT */ +import { ICharMeasure, ITerminal, ITerminalOptions } from '../../typings/xterm-internal'; import { EventEmitter } from '../EventEmitter'; -import { ICharMeasure, ITerminal, ITerminalOptions } from '../Interfaces'; /** * Utility class that measures the size of a character. Measurements are done in diff --git a/src/utils/CircularList.ts b/src/utils/CircularList.ts index 97a32b790..f8c60b5a9 100644 --- a/src/utils/CircularList.ts +++ b/src/utils/CircularList.ts @@ -4,7 +4,7 @@ */ import { EventEmitter } from '../EventEmitter'; -import { ICircularList } from '../Interfaces'; +import { ICircularList } from '../../typings/xterm-internal'; /** * Represents a circular list; a list with a maximum size that wraps around when push is called, diff --git a/src/utils/MouseHelper.ts b/src/utils/MouseHelper.ts index d7d8f6981..de07dda75 100644 --- a/src/utils/MouseHelper.ts +++ b/src/utils/MouseHelper.ts @@ -3,8 +3,7 @@ * @license MIT */ -import { ICharMeasure } from '../Interfaces'; -import { IRenderer } from '../renderer/Interfaces'; +import { ICharMeasure, IRenderer } from '../../typings/xterm-internal'; export class MouseHelper { constructor(private _renderer: IRenderer) {} @@ -24,7 +23,7 @@ export class MouseHelper { while (element) { x -= element.offsetLeft; y -= element.offsetTop; - element = 'offsetParent' in element ? element.offsetParent : element.parentElement; + element = element.offsetParent; } element = originalElement; while (element && element !== element.ownerDocument.body) { diff --git a/src/utils/TestUtils.test.ts b/src/utils/TestUtils.test.ts index 12b032984..34f3ced8b 100644 --- a/src/utils/TestUtils.test.ts +++ b/src/utils/TestUtils.test.ts @@ -3,11 +3,11 @@ * @license MIT */ -import { ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, IInputHandlingTerminal, IViewport, ICircularList, ICompositionHelper, ITheme, ILinkifier, IMouseHelper, ILinkMatcherOptions } from '../Interfaces'; -import { LineData } from '../Types'; +import { ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, ICircularList, ITheme, ILinkifier, IMouseHelper, ILinkMatcherOptions, LineData, IColorSet, IRenderer, IRenderDimensions, IColorManager } from '../../typings/xterm-internal'; +import { IInputHandlingTerminal, IViewport, ICompositionHelper } from '../Interfaces'; +import { } from '../Types'; import { Buffer } from '../Buffer'; import * as Browser from './Browser'; -import { IColorSet, IRenderer, IRenderDimensions, IColorManager } from '../renderer/Interfaces'; export class MockTerminal implements ITerminal { getOption(key: any): any { diff --git a/typings/xterm-internal.d.ts b/typings/xterm-internal.d.ts new file mode 100644 index 000000000..eca7fe334 --- /dev/null +++ b/typings/xterm-internal.d.ts @@ -0,0 +1,259 @@ +/** + * Copyright (c) 2018 The xterm.js authors. All rights reserved. + * @license MIT + */ + +/// + +import { Terminal as PublicTerminal, ITerminalOptions as IPublicTerminalOptions, IEventEmitter } from 'xterm'; + +export type CharData = [number, string, number, number]; +export type LineData = CharData[]; + +export type LinkMatcherHandler = (event: MouseEvent, uri: string) => boolean | void; +export type LinkMatcherValidationCallback = (uri: string, callback: (isValid: boolean) => void) => void; + +export interface ITerminal extends PublicTerminal, IElementAccessor, IBufferAccessor, ILinkifierAccessor { + selectionManager: ISelectionManager; + charMeasure: ICharMeasure; + renderer: IRenderer; + browser: IBrowser; + writeBuffer: string[]; + cursorHidden: boolean; + cursorState: number; + defAttr: number; + options: ITerminalOptions; + buffer: IBuffer; + buffers: IBufferSet; + isFocused: boolean; + mouseHelper: IMouseHelper; + bracketedPasteMode: boolean; + + /** + * Emit the 'data' event and populate the given data. + * @param data The data to populate in the event. + */ + handler(data: string): void; + scrollLines(disp: number, suppressScrollEvent?: boolean): void; + cancel(ev: Event, force?: boolean): boolean | void; + log(text: string): void; + showCursor(): void; + blankLine(cur?: boolean, isWrapped?: boolean, cols?: number): LineData; +} + +export interface IBufferAccessor { + buffer: IBuffer; +} + +export interface IElementAccessor { + element: HTMLElement; +} + +export interface ILinkifierAccessor { + linkifier: ILinkifier; +} + +export interface IMouseHelper { + getCoords(event: {pageX: number, pageY: number}, element: HTMLElement, charMeasure: ICharMeasure, lineHeight: number, colCount: number, rowCount: number, isSelection?: boolean): [number, number]; + getRawByteCoords(event: MouseEvent, element: HTMLElement, charMeasure: ICharMeasure, lineHeight: number, colCount: number, rowCount: number): { x: number, y: number }; +} + +export interface ICharMeasure { + width: number; + height: number; + measure(options: ITerminalOptions): void; +} + +// TODO: The options that are not in the public API should be reviewed +export interface ITerminalOptions extends IPublicTerminalOptions { + cancelEvents?: boolean; + convertEol?: boolean; + debug?: boolean; + handler?: (data: string) => void; + screenKeys?: boolean; + termName?: string; + useFlowControl?: boolean; +} + +export interface IBuffer { + lines: ICircularList; + ydisp: number; + ybase: number; + y: number; + x: number; + tabs: any; + scrollBottom: number; + scrollTop: number; + savedY: number; + savedX: number; + isCursorInViewport: boolean; + translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol?: number, endCol?: number): string; + nextStop(x?: number): number; + prevStop(x?: number): number; +} + +export interface IBufferSet { + alt: IBuffer; + normal: IBuffer; + active: IBuffer; + + activateNormalBuffer(): void; + activateAltBuffer(): void; +} + +export interface ICircularList extends IEventEmitter { + length: number; + maxLength: number; + forEach: (callbackfn: (value: T, index: number) => void) => void; + + get(index: number): T; + set(index: number, value: T): void; + push(value: T): void; + pop(): T; + splice(start: number, deleteCount: number, ...items: T[]): void; + trimStart(count: number): void; + shiftElements(start: number, count: number, offset: number): void; +} + +export interface ISelectionManager { + selectionText: string; + selectionStart: [number, number]; + selectionEnd: [number, number]; + + disable(): void; + enable(): void; + setBuffer(buffer: IBuffer): void; + setSelection(row: number, col: number, length: number): void; +} + +export interface ILinkifier extends IEventEmitter { + attachToDom(mouseZoneManager: IMouseZoneManager): void; + linkifyRows(start: number, end: number): void; + setHypertextLinkHandler(handler: LinkMatcherHandler): void; + setHypertextValidationCallback(callback: LinkMatcherValidationCallback): void; + registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler, options?: ILinkMatcherOptions): number; + deregisterLinkMatcher(matcherId: number): boolean; +} + +export interface ILinkMatcherOptions { + /** + * The index of the link from the regex.match(text) call. This defaults to 0 + * (for regular expressions without capture groups). + */ + matchIndex?: number; + /** + * A callback that validates an individual link, returning true if valid and + * false if invalid. + */ + validationCallback?: LinkMatcherValidationCallback; + /** + * A callback that fires when the mouse hovers over a link. + */ + tooltipCallback?: LinkMatcherHandler; + /** + * A callback that fires when the mouse leaves a link that was hovered. + */ + leaveCallback?: () => void; + /** + * The priority of the link matcher, this defines the order in which the link + * matcher is evaluated relative to others, from highest to lowest. The + * default value is 0. + */ + priority?: number; +} + +export interface IBrowser { + isNode: boolean; + userAgent: string; + platform: string; + isFirefox: boolean; + isMSIE: boolean; + isMac: boolean; + isIpad: boolean; + isIphone: boolean; + isMSWindows: boolean; +} + +export interface IMouseZoneManager { + add(zone: IMouseZone): void; + clearAll(start?: number, end?: number): void; +} + +export interface IMouseZone { + x1: number; + x2: number; + y: number; + clickCallback: (e: MouseEvent) => any; + hoverCallback?: (e: MouseEvent) => any; + tooltipCallback?: (e: MouseEvent) => any; + leaveCallback?: () => any; +} + +export interface IRenderer extends IEventEmitter { + dimensions: IRenderDimensions; + colorManager: IColorManager; + + setTheme(theme: ITheme): IColorSet; + onWindowResize(devicePixelRatio: number): void; + onResize(cols: number, rows: number, didCharSizeChange: boolean): void; + onCharSizeChanged(): void; + onBlur(): void; + onFocus(): void; + onSelectionChanged(start: [number, number], end: [number, number]): void; + onCursorMove(): void; + onOptionsChanged(): void; + clear(): void; + queueRefresh(start: number, end: number): void; +} + +export interface IColorManager { + colors: IColorSet; +} + +export interface IColorSet { + foreground: string; + background: string; + cursor: string; + cursorAccent: string; + selection: string; + ansi: string[]; +} + +export interface IRenderDimensions { + scaledCharWidth: number; + scaledCharHeight: number; + scaledCellWidth: number; + scaledCellHeight: number; + scaledCharLeft: number; + scaledCharTop: number; + scaledCanvasWidth: number; + scaledCanvasHeight: number; + canvasWidth: number; + canvasHeight: number; + actualCellWidth: number; + actualCellHeight: number; +} + +export interface ITheme { + foreground?: string; + background?: string; + cursor?: string; + cursorAccent?: string; + selection?: string; + black?: string; + red?: string; + green?: string; + yellow?: string; + blue?: string; + magenta?: string; + cyan?: string; + white?: string; + brightBlack?: string; + brightRed?: string; + brightGreen?: string; + brightYellow?: string; + brightBlue?: string; + brightMagenta?: string; + brightCyan?: string; + brightWhite?: string; +} From 4f5936333177cbef0a185472793691884d021c73 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 20 Jan 2018 08:22:12 -0800 Subject: [PATCH 12/26] Fix Intefaces typo --- src/addons/attach/{Intefaces.ts => Interfaces.ts} | 0 src/addons/attach/attach.ts | 2 +- src/addons/terminado/{Intefaces.ts => Interfaces.ts} | 0 src/addons/terminado/terminado.ts | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) rename src/addons/attach/{Intefaces.ts => Interfaces.ts} (100%) rename src/addons/terminado/{Intefaces.ts => Interfaces.ts} (100%) diff --git a/src/addons/attach/Intefaces.ts b/src/addons/attach/Interfaces.ts similarity index 100% rename from src/addons/attach/Intefaces.ts rename to src/addons/attach/Interfaces.ts diff --git a/src/addons/attach/attach.ts b/src/addons/attach/attach.ts index d963a658f..cbfd4a248 100644 --- a/src/addons/attach/attach.ts +++ b/src/addons/attach/attach.ts @@ -8,7 +8,7 @@ /// import { Terminal } from 'xterm'; -import { IAttachAddonTerminal } from './Intefaces'; +import { IAttachAddonTerminal } from './Interfaces'; /** * Attaches the given terminal to the given socket. diff --git a/src/addons/terminado/Intefaces.ts b/src/addons/terminado/Interfaces.ts similarity index 100% rename from src/addons/terminado/Intefaces.ts rename to src/addons/terminado/Interfaces.ts diff --git a/src/addons/terminado/terminado.ts b/src/addons/terminado/terminado.ts index d5cf72d1b..4acf9dd84 100644 --- a/src/addons/terminado/terminado.ts +++ b/src/addons/terminado/terminado.ts @@ -9,7 +9,7 @@ /// import { Terminal } from 'xterm'; -import { ITerminadoAddonTerminal } from './Intefaces'; +import { ITerminadoAddonTerminal } from './Interfaces'; /** * Attaches the given terminal to the given socket. From 4e20b48aa0d1dea6a734c7e7218a5b937a447b6f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 20 Jan 2018 11:06:53 -0800 Subject: [PATCH 13/26] Add missing macOptionIsMeta typings Follow up from #1225 --- typings/xterm.d.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 43842bad6..c37e0fe12 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -67,6 +67,11 @@ declare module 'xterm' { */ lineHeight?: number; + /** + * Whether to treat option as the meta key. + */ + macOptionIsMeta?: boolean; + /** * The number of rows in the terminal. */ @@ -409,7 +414,7 @@ declare module 'xterm' { * Retrieves an option's value from the terminal. * @param key The option key. */ - getOption(key: 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell'): boolean; + getOption(key: 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell'): boolean; /** * Retrieves an option's value from the terminal. * @param key The option key. From 16abf71b780fb3aa3e2b0480a3601fa9596bb87f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 22 Jan 2018 11:51:09 -0800 Subject: [PATCH 14/26] Use explicit null check to ensure start/end row is valid It looks like this could have caused the inconsistent behavior with links not activating and then working again after scrolling Fixes #1233 --- src/Linkifier.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Linkifier.ts b/src/Linkifier.ts index 767719301..e82a553b8 100644 --- a/src/Linkifier.ts +++ b/src/Linkifier.ts @@ -82,12 +82,12 @@ export class Linkifier extends EventEmitter implements ILinkifier { } // Increase range to linkify - if (!this._rowsToLinkify.start) { + if (this._rowsToLinkify.start === null) { this._rowsToLinkify.start = start; this._rowsToLinkify.end = end; } else { - this._rowsToLinkify.start = this._rowsToLinkify.start < start ? this._rowsToLinkify.start : start; - this._rowsToLinkify.end = this._rowsToLinkify.end > end ? this._rowsToLinkify.end : end; + this._rowsToLinkify.start = Math.min(this._rowsToLinkify.start, start); + this._rowsToLinkify.end = Math.max(this._rowsToLinkify.end, end); } // Clear out any existing links on this row range @@ -97,7 +97,7 @@ export class Linkifier extends EventEmitter implements ILinkifier { if (this._rowsTimeoutId) { clearTimeout(this._rowsTimeoutId); } - this._rowsTimeoutId = setTimeout(() => this._linkifyRows(), Linkifier.TIME_BEFORE_LINKIFY); + this._rowsTimeoutId = window.setTimeout(() => this._linkifyRows(), Linkifier.TIME_BEFORE_LINKIFY); } /** From a9d3e61794c384efeed16eda220727da707314d0 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 22 Jan 2018 12:43:42 -0800 Subject: [PATCH 15/26] Fix tests --- src/Linkifier.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Linkifier.ts b/src/Linkifier.ts index e82a553b8..b5f30b562 100644 --- a/src/Linkifier.ts +++ b/src/Linkifier.ts @@ -97,7 +97,7 @@ export class Linkifier extends EventEmitter implements ILinkifier { if (this._rowsTimeoutId) { clearTimeout(this._rowsTimeoutId); } - this._rowsTimeoutId = window.setTimeout(() => this._linkifyRows(), Linkifier.TIME_BEFORE_LINKIFY); + this._rowsTimeoutId = setTimeout(() => this._linkifyRows(), Linkifier.TIME_BEFORE_LINKIFY); } /** From 2ebc5d904dee1395e853bec22c48817fe1a128e9 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 23 Jan 2018 06:51:22 -0800 Subject: [PATCH 16/26] Resize saved cursor position on buffer resize Saved cursor coordinates were not being resized as well which could lead to crashes when resizing down while the alt buffer is active. Fixes #1151 --- src/Buffer.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Buffer.ts b/src/Buffer.ts index 3e7d61224..39b0726c2 100644 --- a/src/Buffer.ts +++ b/src/Buffer.ts @@ -177,16 +177,13 @@ export class Buffer implements IBuffer { } // Make sure that the cursor stays on screen - if (this.y >= newRows) { - this.y = newRows - 1; - } + this.x = Math.min(this.x, newCols - 1); + this.y = Math.min(this.y, newRows - 1); if (addToY) { this.y += addToY; } - - if (this.x >= newCols) { - this.x = newCols - 1; - } + this.savedY = Math.min(this.savedY, newRows - 1); + this.savedX = Math.min(this.savedX, newCols - 1); this.scrollTop = 0; } From f3ecbea3e885541e8ef17c4992e3c9e6c8073183 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 23 Jan 2018 07:55:18 -0800 Subject: [PATCH 17/26] Fix tests --- fixtures/typings-test/typings-test.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fixtures/typings-test/typings-test.ts b/fixtures/typings-test/typings-test.ts index 2aa2264ed..4718110d6 100644 --- a/fixtures/typings-test/typings-test.ts +++ b/fixtures/typings-test/typings-test.ts @@ -145,8 +145,8 @@ namespace methods_core { const r21: boolean = t.getOption('enableBold'); const r22: number = t.getOption('letterSpacing'); const r23: boolean = t.getOption('macOptionIsMeta'); - const r24: number = t.getOption('fontWeight'); - const r25: number = t.getOption('fontWeightBold'); + const r24: string = t.getOption('fontWeight'); + const r25: string = t.getOption('fontWeightBold'); } { const t: Terminal = new Terminal(); @@ -160,6 +160,8 @@ namespace methods_core { t.setOption('debug', true); t.setOption('disableStdin', true); t.setOption('fontWeight', 'normal'); + t.setOption('fontWeight', 'bold'); + t.setOption('fontWeightBold', 'normal'); t.setOption('fontWeightBold', 'bold'); t.setOption('popOnBell', true); t.setOption('screenKeys', true); From 01c95168f205199b767607008688dad1e64b85d9 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 23 Jan 2018 08:02:48 -0800 Subject: [PATCH 18/26] Make font weight types in ITerminalOption more strict --- src/Interfaces.ts | 6 +++--- src/Types.ts | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Interfaces.ts b/src/Interfaces.ts index 424f76925..6d1c36d3c 100644 --- a/src/Interfaces.ts +++ b/src/Interfaces.ts @@ -4,7 +4,7 @@ */ import { ICharset, ILinkMatcherOptions } from './Interfaces'; -import { LinkMatcherHandler, LinkMatcherValidationCallback, LineData } from './Types'; +import { LinkMatcherHandler, LinkMatcherValidationCallback, LineData, FontWeight } from './Types'; import { IColorSet, IRenderer } from './renderer/Interfaces'; import { IMouseZoneManager } from './input/Interfaces'; @@ -139,8 +139,8 @@ export interface ITerminalOptions { disableStdin?: boolean; fontSize?: number; fontFamily?: string; - fontWeight?: string; - fontWeightBold?: string; + fontWeight?: FontWeight; + fontWeightBold?: FontWeight; handler?: (data: string) => void; letterSpacing?: number; lineHeight?: number; diff --git a/src/Types.ts b/src/Types.ts index 3263282e0..336ac5cc0 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -16,3 +16,5 @@ export enum LinkHoverEventTypes { TOOLTIP = 'linktooltip', LEAVE = 'linkleave' } + +export type FontWeight = 'normal' | 'bold' | 'bolder' | 'lighter' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; From df02dacdc445cdda2a98cbd7951663b5c89a63d7 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 23 Jan 2018 08:28:01 -0800 Subject: [PATCH 19/26] Add enableBold back Part of #1117 --- fixtures/typings-test/typings-test.ts | 1 + src/Interfaces.ts | 1 + src/Terminal.ts | 4 +++- src/renderer/BaseRenderLayer.ts | 11 +++++++++-- typings/xterm.d.ts | 15 +++++++++++++++ 5 files changed, 29 insertions(+), 3 deletions(-) diff --git a/fixtures/typings-test/typings-test.ts b/fixtures/typings-test/typings-test.ts index 4718110d6..6761dcd54 100644 --- a/fixtures/typings-test/typings-test.ts +++ b/fixtures/typings-test/typings-test.ts @@ -159,6 +159,7 @@ namespace methods_core { t.setOption('cursorBlink', true); t.setOption('debug', true); t.setOption('disableStdin', true); + t.setOption('enableBold', true); t.setOption('fontWeight', 'normal'); t.setOption('fontWeight', 'bold'); t.setOption('fontWeightBold', 'normal'); diff --git a/src/Interfaces.ts b/src/Interfaces.ts index 6d1c36d3c..5237fa5b9 100644 --- a/src/Interfaces.ts +++ b/src/Interfaces.ts @@ -137,6 +137,7 @@ export interface ITerminalOptions { cursorStyle?: string; debug?: boolean; disableStdin?: boolean; + enableBold?: boolean; fontSize?: number; fontFamily?: string; fontWeight?: FontWeight; diff --git a/src/Terminal.ts b/src/Terminal.ts index 044f5351f..70b7deaa0 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -72,6 +72,7 @@ const DEFAULT_OPTIONS: ITerminalOptions = { cursorStyle: 'block', bellSound: BELL_SOUND, bellStyle: 'none', + enableBold: true, fontFamily: 'courier-new, courier, monospace', fontSize: 15, fontWeight: 'normal', @@ -424,11 +425,12 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.renderer.clear(); this.charMeasure.measure(this.options); break; + case 'enableBold': case 'letterSpacing': case 'lineHeight': case 'fontWeight': case 'fontWeightBold': - const didCharSizeChange = (key === 'fontWeight' || key === 'fontWeightBold'); + const didCharSizeChange = (key === 'fontWeight' || key === 'fontWeightBold' || key === 'enableBold'); // When the font changes the size of the cells may change which requires a renderer clear this.renderer.clear(); diff --git a/src/renderer/BaseRenderLayer.ts b/src/renderer/BaseRenderLayer.ts index 977cbf526..bf952d06f 100644 --- a/src/renderer/BaseRenderLayer.ts +++ b/src/renderer/BaseRenderLayer.ts @@ -230,7 +230,7 @@ export abstract class BaseRenderLayer implements IRenderLayer { colorIndex = fg + 2; } else { // If default color and bold - if (bold) { + if (bold && terminal.options.enableBold) { colorIndex = 1; } } @@ -251,6 +251,13 @@ export abstract class BaseRenderLayer implements IRenderLayer { this._ctx.globalAlpha = DIM_OPACITY; } + // Draw the non-bold version of the same color if bold is not enabled + if (bold && !terminal.options.enableBold) { + // Ignore default color as it's not touched above + if (colorIndex > 1) { + colorIndex -= 8; + } + } this._ctx.drawImage(this._charAtlas, code * charAtlasCellWidth, @@ -262,7 +269,7 @@ export abstract class BaseRenderLayer implements IRenderLayer { charAtlasCellWidth, this._scaledCharHeight); } else { - this._drawUncachedChar(terminal, char, width, fg, x, y, bold, dim); + this._drawUncachedChar(terminal, char, width, fg, x, y, bold && terminal.options.enableBold, dim); } // This draws the atlas (for debugging purposes) // this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 7c8612cf6..7f19a5027 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -8,6 +8,11 @@ */ declare module 'xterm' { + /** + * A string representing text font weight. + */ + export type FontWeight = 'normal' | 'bold' | 'bolder' | 'lighter' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; + /** * An object containing start up options for the terminal. */ @@ -57,6 +62,16 @@ declare module 'xterm' { */ fontFamily?: string; + /** + * The font weight used to render non-bold text. + */ + fontWeight?: FontWeight; + + /** + * The font weight used to render bold text. + */ + fontWeightBold?: FontWeight; + /** * The spacing in whole pixels between characters.. */ From a13562bf4542a9305bd2475a68ed9ff1515e7293 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 23 Jan 2018 08:58:33 -0800 Subject: [PATCH 20/26] Remove relative font weight as valid values --- src/Types.ts | 2 +- typings/xterm.d.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Types.ts b/src/Types.ts index 336ac5cc0..3c502b025 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -17,4 +17,4 @@ export enum LinkHoverEventTypes { LEAVE = 'linkleave' } -export type FontWeight = 'normal' | 'bold' | 'bolder' | 'lighter' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; +export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 7f19a5027..69d345bc7 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -11,7 +11,7 @@ declare module 'xterm' { /** * A string representing text font weight. */ - export type FontWeight = 'normal' | 'bold' | 'bolder' | 'lighter' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; + export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; /** * An object containing start up options for the terminal. @@ -457,7 +457,7 @@ declare module 'xterm' { * @param key The option key. * @param value The option value. */ - setOption(key: 'fontWeight' | 'fontWeightBold', value: null | 'normal' | 'bold' | 'bolder' | 'lighter' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'): void; + setOption(key: 'fontWeight' | 'fontWeightBold', value: null | 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'): void; /** * Sets an option on the terminal. * @param key The option key. From d454a50a846639348e47495dd2fc0d699e6c8c52 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 25 Jan 2018 09:48:12 -0800 Subject: [PATCH 21/26] Move FontWeight type to xterm.d.ts --- src/shared/CharAtlasGenerator.ts | 2 +- src/shared/Types.ts | 6 ------ src/shared/utils/Browser.ts | 2 +- 3 files changed, 2 insertions(+), 8 deletions(-) delete mode 100644 src/shared/Types.ts diff --git a/src/shared/CharAtlasGenerator.ts b/src/shared/CharAtlasGenerator.ts index 9b895c9c3..9ae9f4b31 100644 --- a/src/shared/CharAtlasGenerator.ts +++ b/src/shared/CharAtlasGenerator.ts @@ -3,8 +3,8 @@ * @license MIT */ +import { FontWeight } from 'xterm'; import { isFirefox } from './utils/Browser'; -import { FontWeight } from './Types'; declare const Promise: any; diff --git a/src/shared/Types.ts b/src/shared/Types.ts deleted file mode 100644 index b61525bd4..000000000 --- a/src/shared/Types.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Copyright (c) 2018 The xterm.js authors. All rights reserved. - * @license MIT - */ - - export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; diff --git a/src/shared/utils/Browser.ts b/src/shared/utils/Browser.ts index 1d4774d21..85d739a61 100644 --- a/src/shared/utils/Browser.ts +++ b/src/shared/utils/Browser.ts @@ -26,4 +26,4 @@ export const isLinux = platform.indexOf('Linux') >= 0; */ export function contains(arr: any[], el: any): boolean { return arr.indexOf(el) >= 0; -}; +} From 177edfa66e01c2487050a52540437a0215a53c68 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 25 Jan 2018 10:03:28 -0800 Subject: [PATCH 22/26] Merge interfaces and types files --- src/Charsets.ts | 2 +- src/InputHandler.ts | 2 +- src/Linkifier.test.ts | 2 +- src/Linkifier.ts | 2 +- src/Parser.ts | 2 +- src/Terminal.ts | 2 +- src/{Interfaces.ts => Types.d.ts} | 9 ++++++++- src/Types.ts | 12 ------------ src/Viewport.ts | 2 +- src/renderer/BaseRenderLayer.ts | 2 +- src/renderer/LinkRenderLayer.ts | 2 +- src/renderer/Renderer.ts | 2 +- src/renderer/{Interfaces.ts => Types.d.ts} | 13 ++++++++++++- src/renderer/Types.ts | 16 ---------------- src/utils/TestUtils.test.ts | 2 +- 15 files changed, 31 insertions(+), 41 deletions(-) rename src/{Interfaces.ts => Types.d.ts} (96%) delete mode 100644 src/Types.ts rename src/renderer/{Interfaces.ts => Types.d.ts} (88%) delete mode 100644 src/renderer/Types.ts diff --git a/src/Charsets.ts b/src/Charsets.ts index e62e3f9c0..fe0112ec7 100644 --- a/src/Charsets.ts +++ b/src/Charsets.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ICharset } from './Interfaces'; +import { ICharset } from './Types'; /** * The character sets supported by the terminal. These enable several languages diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 4fc14bd93..19f77d1e4 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -5,7 +5,7 @@ */ import { CharData, ITerminal } from '../typings/xterm-internal'; -import { IInputHandler, IInputHandlingTerminal } from './Interfaces'; +import { IInputHandler, IInputHandlingTerminal } from './Types'; import { C0 } from './EscapeSequences'; import { DEFAULT_CHARSET } from './Charsets'; import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX } from './Buffer'; diff --git a/src/Linkifier.test.ts b/src/Linkifier.test.ts index 1a7c60476..1e7b41c94 100644 --- a/src/Linkifier.test.ts +++ b/src/Linkifier.test.ts @@ -5,7 +5,7 @@ import { assert } from 'chai'; import { ITerminal, ILinkifier, IBuffer, IBufferAccessor, IElementAccessor, LineData, IMouseZoneManager, IMouseZone } from '../typings/xterm-internal'; -import { ILinkMatcher } from './Interfaces'; +import { ILinkMatcher } from './Types'; import { Linkifier } from './Linkifier'; import { MockBuffer } from './utils/TestUtils.test'; import { CircularList } from './utils/CircularList'; diff --git a/src/Linkifier.ts b/src/Linkifier.ts index 64d7510c5..aac3048d5 100644 --- a/src/Linkifier.ts +++ b/src/Linkifier.ts @@ -4,7 +4,7 @@ */ import { ILinkMatcherOptions, ITerminal, IBufferAccessor, ILinkifier, IElementAccessor, LinkMatcherHandler, LinkMatcherValidationCallback, LineData, IMouseZoneManager } from '../typings/xterm-internal'; -import { ILinkHoverEvent, ILinkMatcher } from './Interfaces'; +import { ILinkHoverEvent, ILinkMatcher } from './Types'; import { LinkHoverEventTypes } from './Types'; import { MouseZone } from './input/MouseZoneManager'; import { EventEmitter } from './EventEmitter'; diff --git a/src/Parser.ts b/src/Parser.ts index 6f4b0932c..3ac03e4fb 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -5,7 +5,7 @@ */ import { C0 } from './EscapeSequences'; -import { IInputHandler } from './Interfaces'; +import { IInputHandler } from './Types'; import { CHARSETS, DEFAULT_CHARSET } from './Charsets'; const normalStateHandler: {[key: string]: (parser: Parser, handler: IInputHandler) => void} = {}; diff --git a/src/Terminal.ts b/src/Terminal.ts index 0c2ce7922..daf1a231e 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -40,7 +40,7 @@ import * as Browser from './shared/utils/Browser'; import { MouseHelper } from './utils/MouseHelper'; import { CHARSETS } from './Charsets'; import { CustomKeyEventHandler } from './Types'; -import { ICharset, IInputHandlingTerminal, IViewport, ICompositionHelper } from './Interfaces'; +import { ICharset, IInputHandlingTerminal, IViewport, ICompositionHelper } from './Types'; import { BELL_SOUND } from './utils/Sounds'; import { DEFAULT_ANSI_COLORS } from './renderer/ColorManager'; import { MouseZoneManager } from './input/MouseZoneManager'; diff --git a/src/Interfaces.ts b/src/Types.d.ts similarity index 96% rename from src/Interfaces.ts rename to src/Types.d.ts index 4ecc87f60..0e5af373a 100644 --- a/src/Interfaces.ts +++ b/src/Types.d.ts @@ -5,7 +5,14 @@ import { IEventEmitter } from 'xterm'; import { ITerminalOptions, ILinkMatcherOptions, IMouseZoneManager, LinkMatcherHandler, LinkMatcherValidationCallback, LineData, IColorSet, IRenderer, IBufferSet, IBuffer, ISelectionManager } from '../typings/xterm-internal'; -import { ICharset } from './Interfaces'; + +export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean; + +export enum LinkHoverEventTypes { + HOVER = 'linkhover', + TOOLTIP = 'linktooltip', + LEAVE = 'linkleave' +} /** * This interface encapsulates everything needed from the Terminal by the diff --git a/src/Types.ts b/src/Types.ts deleted file mode 100644 index e112d6d96..000000000 --- a/src/Types.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Copyright (c) 2017 The xterm.js authors. All rights reserved. - * @license MIT - */ - -export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean; - -export enum LinkHoverEventTypes { - HOVER = 'linkhover', - TOOLTIP = 'linktooltip', - LEAVE = 'linkleave' -} diff --git a/src/Viewport.ts b/src/Viewport.ts index 147cc90e9..bf4d8da01 100644 --- a/src/Viewport.ts +++ b/src/Viewport.ts @@ -4,7 +4,7 @@ */ import { ITerminal, IColorSet } from '../typings/xterm-internal'; -import { IViewport } from './Interfaces'; +import { IViewport } from './Types'; import { CharMeasure } from './utils/CharMeasure'; /** diff --git a/src/renderer/BaseRenderLayer.ts b/src/renderer/BaseRenderLayer.ts index 3c1f52be6..0e1654244 100644 --- a/src/renderer/BaseRenderLayer.ts +++ b/src/renderer/BaseRenderLayer.ts @@ -4,7 +4,7 @@ */ import { IColorSet, IRenderDimensions, ITerminal, ITerminalOptions, CharData } from '../../typings/xterm-internal'; -import { IRenderLayer } from './Interfaces'; +import { IRenderLayer } from './Types'; import { acquireCharAtlas, CHAR_ATLAS_CELL_SPACING } from './CharAtlas'; import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer'; diff --git a/src/renderer/LinkRenderLayer.ts b/src/renderer/LinkRenderLayer.ts index 24bc89b49..de14dd4dd 100644 --- a/src/renderer/LinkRenderLayer.ts +++ b/src/renderer/LinkRenderLayer.ts @@ -4,7 +4,7 @@ */ import { IColorSet, IRenderDimensions, ITerminal, ILinkifierAccessor, IBuffer, ICharMeasure } from '../../typings/xterm-internal'; -import { ILinkHoverEvent } from '../Interfaces'; +import { ILinkHoverEvent } from '../Types'; import { CHAR_DATA_ATTR_INDEX } from '../Buffer'; import { GridCache } from './GridCache'; import { FLAGS } from './Types'; diff --git a/src/renderer/Renderer.ts b/src/renderer/Renderer.ts index afeefe3d9..afc66db13 100644 --- a/src/renderer/Renderer.ts +++ b/src/renderer/Renderer.ts @@ -10,7 +10,7 @@ import { SelectionRenderLayer } from './SelectionRenderLayer'; import { CursorRenderLayer } from './CursorRenderLayer'; import { ColorManager } from './ColorManager'; import { BaseRenderLayer } from './BaseRenderLayer'; -import { IRenderLayer } from './Interfaces'; +import { IRenderLayer } from './Types'; import { LinkRenderLayer } from './LinkRenderLayer'; import { EventEmitter } from '../EventEmitter'; import { ScreenDprMonitor } from '../utils/ScreenDprMonitor'; diff --git a/src/renderer/Interfaces.ts b/src/renderer/Types.d.ts similarity index 88% rename from src/renderer/Interfaces.ts rename to src/renderer/Types.d.ts index d65c9d359..8f3716936 100644 --- a/src/renderer/Interfaces.ts +++ b/src/renderer/Types.d.ts @@ -4,9 +4,20 @@ */ import { IColorSet, IRenderDimensions, ITerminal } from '../../typings/xterm-internal'; - import { IEventEmitter } from 'xterm'; +/** + * Flags used to render terminal text properly. + */ +export enum FLAGS { + BOLD = 1, + UNDERLINE = 2, + BLINK = 4, + INVERSE = 8, + INVISIBLE = 16, + DIM = 32 +} + export interface IRenderLayer { /** * Called when the terminal loses focus. diff --git a/src/renderer/Types.ts b/src/renderer/Types.ts deleted file mode 100644 index 834f88135..000000000 --- a/src/renderer/Types.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) 2017 The xterm.js authors. All rights reserved. - * @license MIT - */ - - /** - * Flags used to render terminal text properly. - */ -export enum FLAGS { - BOLD = 1, - UNDERLINE = 2, - BLINK = 4, - INVERSE = 8, - INVISIBLE = 16, - DIM = 32 -} diff --git a/src/utils/TestUtils.test.ts b/src/utils/TestUtils.test.ts index 64c326d55..54474a7f3 100644 --- a/src/utils/TestUtils.test.ts +++ b/src/utils/TestUtils.test.ts @@ -4,7 +4,7 @@ */ import { ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, ICircularList, ITheme, ILinkifier, IMouseHelper, ILinkMatcherOptions, LineData, IColorSet, IRenderer, IRenderDimensions, IColorManager } from '../../typings/xterm-internal'; -import { IInputHandlingTerminal, IViewport, ICompositionHelper } from '../Interfaces'; +import { IInputHandlingTerminal, IViewport, ICompositionHelper } from '../Types'; import { Buffer } from '../Buffer'; import * as Browser from '../shared/utils/Browser'; From 4db4fcb40a569aa3135e29cea709f5a245c03fcc Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 25 Jan 2018 10:23:14 -0800 Subject: [PATCH 23/26] Remove declaration file generation, we have explicit types --- tsconfig.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index a3aa790cf..38bfd2faf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,8 +5,7 @@ "rootDir": "src", "outDir": "lib", "sourceMap": true, - "removeComments": true, - "declaration": true + "removeComments": true }, "include": [ "src/**/*" From 8225b94d3476bde681d9e55ca47b80218d2a5400 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 25 Jan 2018 10:24:17 -0800 Subject: [PATCH 24/26] Types.d.ts -> .ts --- src/{Types.d.ts => Types.ts} | 0 src/renderer/{Types.d.ts => Types.ts} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/{Types.d.ts => Types.ts} (100%) rename src/renderer/{Types.d.ts => Types.ts} (100%) diff --git a/src/Types.d.ts b/src/Types.ts similarity index 100% rename from src/Types.d.ts rename to src/Types.ts diff --git a/src/renderer/Types.d.ts b/src/renderer/Types.ts similarity index 100% rename from src/renderer/Types.d.ts rename to src/renderer/Types.ts From 2e23dd34e0d7477fe535d047480bfc77f31f5c30 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 25 Jan 2018 11:06:52 -0800 Subject: [PATCH 25/26] Move xterm-internal types back into Types.ts files --- src/Buffer.test.ts | 2 +- src/Buffer.ts | 2 +- src/BufferSet.test.ts | 2 +- src/BufferSet.ts | 2 +- src/CompositionHelper.ts | 2 +- src/InputHandler.ts | 3 +- src/Linkifier.test.ts | 4 +- src/Linkifier.ts | 5 +- src/SelectionManager.test.ts | 2 +- src/SelectionManager.ts | 2 +- src/SelectionModel.test.ts | 2 +- src/SelectionModel.ts | 2 +- src/Terminal.ts | 7 +- src/Types.ts | 171 +++++++++++++++++- src/Viewport.ts | 4 +- src/handlers/Clipboard.ts | 2 +- src/input/MouseZoneManager.ts | 3 +- src/input/Types.ts | 19 ++ src/renderer/BaseRenderLayer.ts | 4 +- src/renderer/CharAtlas.ts | 3 +- src/renderer/ColorManager.ts | 3 +- src/renderer/CursorRenderLayer.ts | 5 +- src/renderer/LinkRenderLayer.ts | 6 +- src/renderer/Renderer.ts | 5 +- src/renderer/SelectionRenderLayer.ts | 4 +- src/renderer/TextRenderLayer.ts | 4 +- src/renderer/Types.ts | 49 ++++- src/utils/CharMeasure.test.ts | 2 +- src/utils/CharMeasure.ts | 2 +- src/utils/CircularList.ts | 2 +- src/utils/MouseHelper.ts | 3 +- src/utils/TestUtils.test.ts | 5 +- tslint.json | 1 + typings/xterm-internal.d.ts | 258 --------------------------- 34 files changed, 284 insertions(+), 308 deletions(-) create mode 100644 src/input/Types.ts delete mode 100644 typings/xterm-internal.d.ts diff --git a/src/Buffer.test.ts b/src/Buffer.test.ts index b2522d1c4..0607a573d 100644 --- a/src/Buffer.test.ts +++ b/src/Buffer.test.ts @@ -4,7 +4,7 @@ */ import { assert } from 'chai'; -import { ITerminal } from '../typings/xterm-internal'; +import { ITerminal } from './Types'; import { Buffer } from './Buffer'; import { CircularList } from './utils/CircularList'; import { MockTerminal } from './utils/TestUtils.test'; diff --git a/src/Buffer.ts b/src/Buffer.ts index 82e524e94..462cde56d 100644 --- a/src/Buffer.ts +++ b/src/Buffer.ts @@ -3,8 +3,8 @@ * @license MIT */ -import { ITerminal, IBuffer, LineData, CharData } from '../typings/xterm-internal'; import { CircularList } from './utils/CircularList'; +import { LineData, CharData, ITerminal, IBuffer } from './Types'; export const CHAR_DATA_ATTR_INDEX = 0; export const CHAR_DATA_CHAR_INDEX = 1; diff --git a/src/BufferSet.test.ts b/src/BufferSet.test.ts index 921b5442c..009ebf2ec 100644 --- a/src/BufferSet.test.ts +++ b/src/BufferSet.test.ts @@ -4,7 +4,7 @@ */ import { assert } from 'chai'; -import { ITerminal } from '../typings/xterm-internal'; +import { ITerminal } from './Types'; import { BufferSet } from './BufferSet'; import { Buffer } from './Buffer'; import { MockTerminal } from './utils/TestUtils.test'; diff --git a/src/BufferSet.ts b/src/BufferSet.ts index 01af2a7bc..553b20560 100644 --- a/src/BufferSet.ts +++ b/src/BufferSet.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ITerminal, IBufferSet } from '../typings/xterm-internal'; +import { ITerminal, IBufferSet } from './Types'; import { Buffer } from './Buffer'; import { EventEmitter } from './EventEmitter'; diff --git a/src/CompositionHelper.ts b/src/CompositionHelper.ts index 7c1888dd6..2aa0449f1 100644 --- a/src/CompositionHelper.ts +++ b/src/CompositionHelper.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ITerminal } from '../typings/xterm-internal'; +import { ITerminal } from './Types'; interface IPosition { start: number; diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 19f77d1e4..f71117f83 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -4,8 +4,7 @@ * @license MIT */ -import { CharData, ITerminal } from '../typings/xterm-internal'; -import { IInputHandler, IInputHandlingTerminal } from './Types'; +import { CharData, IInputHandler, IInputHandlingTerminal, ITerminal } from './Types'; import { C0 } from './EscapeSequences'; import { DEFAULT_CHARSET } from './Charsets'; import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX } from './Buffer'; diff --git a/src/Linkifier.test.ts b/src/Linkifier.test.ts index 1e7b41c94..14b1ac0f2 100644 --- a/src/Linkifier.test.ts +++ b/src/Linkifier.test.ts @@ -4,8 +4,8 @@ */ import { assert } from 'chai'; -import { ITerminal, ILinkifier, IBuffer, IBufferAccessor, IElementAccessor, LineData, IMouseZoneManager, IMouseZone } from '../typings/xterm-internal'; -import { ILinkMatcher } from './Types'; +import { IMouseZoneManager, IMouseZone } from './input/Types'; +import { ILinkMatcher, LineData, ITerminal, ILinkifier, IBuffer, IBufferAccessor, IElementAccessor } from './Types'; import { Linkifier } from './Linkifier'; import { MockBuffer } from './utils/TestUtils.test'; import { CircularList } from './utils/CircularList'; diff --git a/src/Linkifier.ts b/src/Linkifier.ts index aac3048d5..da901a6ed 100644 --- a/src/Linkifier.ts +++ b/src/Linkifier.ts @@ -3,9 +3,8 @@ * @license MIT */ -import { ILinkMatcherOptions, ITerminal, IBufferAccessor, ILinkifier, IElementAccessor, LinkMatcherHandler, LinkMatcherValidationCallback, LineData, IMouseZoneManager } from '../typings/xterm-internal'; -import { ILinkHoverEvent, ILinkMatcher } from './Types'; -import { LinkHoverEventTypes } from './Types'; +import { IMouseZoneManager } from './input/Types'; +import { ILinkHoverEvent, ILinkMatcher, LinkMatcherHandler, LinkMatcherValidationCallback, LineData, LinkHoverEventTypes, ILinkMatcherOptions, ITerminal, IBufferAccessor, ILinkifier, IElementAccessor } from './Types'; import { MouseZone } from './input/MouseZoneManager'; import { EventEmitter } from './EventEmitter'; diff --git a/src/SelectionManager.test.ts b/src/SelectionManager.test.ts index 4662c8a15..5c53565fc 100644 --- a/src/SelectionManager.test.ts +++ b/src/SelectionManager.test.ts @@ -4,13 +4,13 @@ */ import jsdom = require('jsdom'); -import { ITerminal, ICircularList, IBuffer, LineData, CharData } from '../typings/xterm-internal'; import { assert } from 'chai'; import { CharMeasure } from './utils/CharMeasure'; import { CircularList } from './utils/CircularList'; import { SelectionManager } from './SelectionManager'; import { SelectionModel } from './SelectionModel'; import { BufferSet } from './BufferSet'; +import { LineData, CharData, ITerminal, ICircularList, IBuffer } from './Types'; import { MockTerminal } from './utils/TestUtils.test'; class TestMockTerminal extends MockTerminal { diff --git a/src/SelectionManager.ts b/src/SelectionManager.ts index 2b5b0fec7..10612c5c6 100644 --- a/src/SelectionManager.ts +++ b/src/SelectionManager.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ITerminal, ICircularList, ISelectionManager, IBuffer, LineData, CharData } from '../typings/xterm-internal'; +import { ITerminal, ICircularList, ISelectionManager, IBuffer, LineData, CharData } from './Types'; import { MouseHelper } from './utils/MouseHelper'; import * as Browser from './shared/utils/Browser'; import { CharMeasure } from './utils/CharMeasure'; diff --git a/src/SelectionModel.test.ts b/src/SelectionModel.test.ts index b84fef5ec..ed483dbe1 100644 --- a/src/SelectionModel.test.ts +++ b/src/SelectionModel.test.ts @@ -4,7 +4,7 @@ */ import { assert } from 'chai'; -import { ITerminal } from '../typings/xterm-internal'; +import { ITerminal } from './Types'; import { SelectionModel } from './SelectionModel'; import { BufferSet } from './BufferSet'; import { MockTerminal } from './utils/TestUtils.test'; diff --git a/src/SelectionModel.ts b/src/SelectionModel.ts index 1e0f816d9..a9a3c89eb 100644 --- a/src/SelectionModel.ts +++ b/src/SelectionModel.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ITerminal } from '../typings/xterm-internal'; +import { ITerminal } from './Types'; /** * Represents a selection within the buffer. This model only cares about column diff --git a/src/Terminal.ts b/src/Terminal.ts index daf1a231e..5536cf03c 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -21,7 +21,9 @@ * http://linux.die.net/man/7/urxvt */ -import { ITerminalOptions, ITerminal, IBrowser, IRenderer, ILinkifier, IMouseZoneManager, ITheme, LinkMatcherHandler, LinkMatcherValidationCallback, ILinkMatcherOptions, CharData, LineData } from '../typings/xterm-internal'; +import { ICharset, IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminalOptions, ITerminal, IBrowser, ILinkifier, ILinkMatcherOptions, CustomKeyEventHandler, LinkMatcherHandler, LinkMatcherValidationCallback, CharData, LineData } from './Types'; +import { IMouseZoneManager } from './input/Types'; +import { IRenderer } from './renderer/Types'; import { BufferSet } from './BufferSet'; import { Buffer, MAX_BUFFER_SIZE } from './Buffer'; import { CompositionHelper } from './CompositionHelper'; @@ -39,11 +41,10 @@ import { CharMeasure } from './utils/CharMeasure'; import * as Browser from './shared/utils/Browser'; import { MouseHelper } from './utils/MouseHelper'; import { CHARSETS } from './Charsets'; -import { CustomKeyEventHandler } from './Types'; -import { ICharset, IInputHandlingTerminal, IViewport, ICompositionHelper } from './Types'; import { BELL_SOUND } from './utils/Sounds'; import { DEFAULT_ANSI_COLORS } from './renderer/ColorManager'; import { MouseZoneManager } from './input/MouseZoneManager'; +import { ITheme } from 'xterm'; // Let it work inside Node.js for automated testing purposes. const document = (typeof window !== 'undefined') ? window.document : null; diff --git a/src/Types.ts b/src/Types.ts index 0e5af373a..f3e9bb941 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -3,11 +3,18 @@ * @license MIT */ -import { IEventEmitter } from 'xterm'; -import { ITerminalOptions, ILinkMatcherOptions, IMouseZoneManager, LinkMatcherHandler, LinkMatcherValidationCallback, LineData, IColorSet, IRenderer, IBufferSet, IBuffer, ISelectionManager } from '../typings/xterm-internal'; +import { Terminal as PublicTerminal, ITerminalOptions as IPublicTerminalOptions, IEventEmitter } from 'xterm'; +import { IColorSet, IRenderer } from './renderer/Types'; +import { IMouseZoneManager } from './input/Types'; export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean; +export type CharData = [number, string, number, number]; +export type LineData = CharData[]; + +export type LinkMatcherHandler = (event: MouseEvent, uri: string) => boolean | void; +export type LinkMatcherValidationCallback = (uri: string, callback: (isValid: boolean) => void) => void; + export enum LinkHoverEventTypes { HOVER = 'linkhover', TOOLTIP = 'linktooltip', @@ -165,3 +172,163 @@ export interface ILinkHoverEvent { y: number; length: number; } + +export interface ITerminal extends PublicTerminal, IElementAccessor, IBufferAccessor, ILinkifierAccessor { + selectionManager: ISelectionManager; + charMeasure: ICharMeasure; + renderer: IRenderer; + browser: IBrowser; + writeBuffer: string[]; + cursorHidden: boolean; + cursorState: number; + defAttr: number; + options: ITerminalOptions; + buffer: IBuffer; + buffers: IBufferSet; + isFocused: boolean; + mouseHelper: IMouseHelper; + bracketedPasteMode: boolean; + + /** + * Emit the 'data' event and populate the given data. + * @param data The data to populate in the event. + */ + handler(data: string): void; + scrollLines(disp: number, suppressScrollEvent?: boolean): void; + cancel(ev: Event, force?: boolean): boolean | void; + log(text: string): void; + showCursor(): void; + blankLine(cur?: boolean, isWrapped?: boolean, cols?: number): LineData; +} + +export interface IBufferAccessor { + buffer: IBuffer; +} + +export interface IElementAccessor { + element: HTMLElement; +} + +export interface ILinkifierAccessor { + linkifier: ILinkifier; +} + +export interface IMouseHelper { + getCoords(event: {pageX: number, pageY: number}, element: HTMLElement, charMeasure: ICharMeasure, lineHeight: number, colCount: number, rowCount: number, isSelection?: boolean): [number, number]; + getRawByteCoords(event: MouseEvent, element: HTMLElement, charMeasure: ICharMeasure, lineHeight: number, colCount: number, rowCount: number): { x: number, y: number }; +} + +export interface ICharMeasure { + width: number; + height: number; + measure(options: ITerminalOptions): void; +} + +// TODO: The options that are not in the public API should be reviewed +export interface ITerminalOptions extends IPublicTerminalOptions { + cancelEvents?: boolean; + convertEol?: boolean; + debug?: boolean; + handler?: (data: string) => void; + screenKeys?: boolean; + termName?: string; + useFlowControl?: boolean; +} + +export interface IBuffer { + lines: ICircularList; + ydisp: number; + ybase: number; + y: number; + x: number; + tabs: any; + scrollBottom: number; + scrollTop: number; + savedY: number; + savedX: number; + isCursorInViewport: boolean; + translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol?: number, endCol?: number): string; + nextStop(x?: number): number; + prevStop(x?: number): number; +} + +export interface IBufferSet extends IEventEmitter { + alt: IBuffer; + normal: IBuffer; + active: IBuffer; + + activateNormalBuffer(): void; + activateAltBuffer(): void; +} + +export interface ICircularList extends IEventEmitter { + length: number; + maxLength: number; + forEach: (callbackfn: (value: T, index: number) => void) => void; + + get(index: number): T; + set(index: number, value: T): void; + push(value: T): void; + pop(): T; + splice(start: number, deleteCount: number, ...items: T[]): void; + trimStart(count: number): void; + shiftElements(start: number, count: number, offset: number): void; +} + +export interface ISelectionManager { + selectionText: string; + selectionStart: [number, number]; + selectionEnd: [number, number]; + + disable(): void; + enable(): void; + setSelection(row: number, col: number, length: number): void; +} + +export interface ILinkifier extends IEventEmitter { + attachToDom(mouseZoneManager: IMouseZoneManager): void; + linkifyRows(start: number, end: number): void; + setHypertextLinkHandler(handler: LinkMatcherHandler): void; + setHypertextValidationCallback(callback: LinkMatcherValidationCallback): void; + registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler, options?: ILinkMatcherOptions): number; + deregisterLinkMatcher(matcherId: number): boolean; +} + +export interface ILinkMatcherOptions { + /** + * The index of the link from the regex.match(text) call. This defaults to 0 + * (for regular expressions without capture groups). + */ + matchIndex?: number; + /** + * A callback that validates an individual link, returning true if valid and + * false if invalid. + */ + validationCallback?: LinkMatcherValidationCallback; + /** + * A callback that fires when the mouse hovers over a link. + */ + tooltipCallback?: LinkMatcherHandler; + /** + * A callback that fires when the mouse leaves a link that was hovered. + */ + leaveCallback?: () => void; + /** + * The priority of the link matcher, this defines the order in which the link + * matcher is evaluated relative to others, from highest to lowest. The + * default value is 0. + */ + priority?: number; +} + +export interface IBrowser { + isNode: boolean; + userAgent: string; + platform: string; + isFirefox: boolean; + isMSIE: boolean; + isMac: boolean; + isIpad: boolean; + isIphone: boolean; + isMSWindows: boolean; +} diff --git a/src/Viewport.ts b/src/Viewport.ts index bf4d8da01..87ecd69ec 100644 --- a/src/Viewport.ts +++ b/src/Viewport.ts @@ -3,8 +3,8 @@ * @license MIT */ -import { ITerminal, IColorSet } from '../typings/xterm-internal'; -import { IViewport } from './Types'; +import { IColorSet } from './renderer/Types'; +import { ITerminal, IViewport } from './Types'; import { CharMeasure } from './utils/CharMeasure'; /** diff --git a/src/handlers/Clipboard.ts b/src/handlers/Clipboard.ts index 1974ef88b..fd2b3d779 100644 --- a/src/handlers/Clipboard.ts +++ b/src/handlers/Clipboard.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ITerminal, ISelectionManager } from '../../typings/xterm-internal'; +import { ITerminal, ISelectionManager } from '../Types'; interface IWindow extends Window { clipboardData?: { diff --git a/src/input/MouseZoneManager.ts b/src/input/MouseZoneManager.ts index f9413e629..98377f36c 100644 --- a/src/input/MouseZoneManager.ts +++ b/src/input/MouseZoneManager.ts @@ -3,7 +3,8 @@ * @license MIT */ -import { IMouseZoneManager, IMouseZone, ITerminal } from '../../typings/xterm-internal'; +import { ITerminal } from '../Types'; +import { IMouseZoneManager, IMouseZone } from './Types'; const HOVER_DURATION = 500; diff --git a/src/input/Types.ts b/src/input/Types.ts new file mode 100644 index 000000000..21514a53c --- /dev/null +++ b/src/input/Types.ts @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +export interface IMouseZoneManager { + add(zone: IMouseZone): void; + clearAll(start?: number, end?: number): void; +} + +export interface IMouseZone { + x1: number; + x2: number; + y: number; + clickCallback: (e: MouseEvent) => any; + hoverCallback?: (e: MouseEvent) => any; + tooltipCallback?: (e: MouseEvent) => any; + leaveCallback?: () => any; +} diff --git a/src/renderer/BaseRenderLayer.ts b/src/renderer/BaseRenderLayer.ts index 0e1654244..20a41cfa3 100644 --- a/src/renderer/BaseRenderLayer.ts +++ b/src/renderer/BaseRenderLayer.ts @@ -3,8 +3,8 @@ * @license MIT */ -import { IColorSet, IRenderDimensions, ITerminal, ITerminalOptions, CharData } from '../../typings/xterm-internal'; -import { IRenderLayer } from './Types'; +import { IRenderLayer, IColorSet, IRenderDimensions } from './Types'; +import { CharData, ITerminal, ITerminalOptions } from '../Types'; import { acquireCharAtlas, CHAR_ATLAS_CELL_SPACING } from './CharAtlas'; import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer'; diff --git a/src/renderer/CharAtlas.ts b/src/renderer/CharAtlas.ts index 274bcc8f0..05cf72014 100644 --- a/src/renderer/CharAtlas.ts +++ b/src/renderer/CharAtlas.ts @@ -3,7 +3,8 @@ * @license MIT */ -import { ITerminal, ITheme, IColorSet } from '../../typings/xterm-internal'; +import { ITerminal } from '../Types'; +import { IColorSet } from './Types'; import { isFirefox } from '../shared/utils/Browser'; import { generateCharAtlas, ICharAtlasRequest } from '../shared/CharAtlasGenerator'; diff --git a/src/renderer/ColorManager.ts b/src/renderer/ColorManager.ts index 53fb165e0..b45c86469 100644 --- a/src/renderer/ColorManager.ts +++ b/src/renderer/ColorManager.ts @@ -3,7 +3,8 @@ * @license MIT */ -import { IColorSet, IColorManager, ITheme } from '../../typings/xterm-internal'; +import { IColorSet, IColorManager } from './Types'; +import { ITheme } from 'xterm'; const DEFAULT_FOREGROUND = '#ffffff'; const DEFAULT_BACKGROUND = '#000000'; diff --git a/src/renderer/CursorRenderLayer.ts b/src/renderer/CursorRenderLayer.ts index f6bbc0a61..d430b81d6 100644 --- a/src/renderer/CursorRenderLayer.ts +++ b/src/renderer/CursorRenderLayer.ts @@ -3,12 +3,11 @@ * @license MIT */ -import { IColorSet, IRenderDimensions, IBuffer, ICharMeasure, ITerminal, ITerminalOptions, CharData } from '../../typings/xterm-internal'; import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CODE_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer'; import { GridCache } from './GridCache'; -import { FLAGS } from './Types'; +import { FLAGS, IColorSet, IRenderDimensions } from './Types'; import { BaseRenderLayer } from './BaseRenderLayer'; -import { } from '../Types'; +import { CharData, IBuffer, ICharMeasure, ITerminal, ITerminalOptions } from '../Types'; interface ICursorState { x: number; diff --git a/src/renderer/LinkRenderLayer.ts b/src/renderer/LinkRenderLayer.ts index de14dd4dd..61352f154 100644 --- a/src/renderer/LinkRenderLayer.ts +++ b/src/renderer/LinkRenderLayer.ts @@ -3,13 +3,11 @@ * @license MIT */ -import { IColorSet, IRenderDimensions, ITerminal, ILinkifierAccessor, IBuffer, ICharMeasure } from '../../typings/xterm-internal'; -import { ILinkHoverEvent } from '../Types'; +import { ILinkHoverEvent, ITerminal, ILinkifierAccessor, IBuffer, ICharMeasure, LinkHoverEventTypes } from '../Types'; import { CHAR_DATA_ATTR_INDEX } from '../Buffer'; import { GridCache } from './GridCache'; -import { FLAGS } from './Types'; +import { FLAGS, IColorSet, IRenderDimensions } from './Types'; import { BaseRenderLayer, INVERTED_DEFAULT_COLOR } from './BaseRenderLayer'; -import { LinkHoverEventTypes } from '../Types'; export class LinkRenderLayer extends BaseRenderLayer { private _state: ILinkHoverEvent = null; diff --git a/src/renderer/Renderer.ts b/src/renderer/Renderer.ts index afc66db13..8b9f5006e 100644 --- a/src/renderer/Renderer.ts +++ b/src/renderer/Renderer.ts @@ -3,17 +3,18 @@ * @license MIT */ -import { ITerminal, ITheme, IColorSet, IRenderer, IRenderDimensions } from '../../typings/xterm-internal'; import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer'; import { TextRenderLayer } from './TextRenderLayer'; import { SelectionRenderLayer } from './SelectionRenderLayer'; import { CursorRenderLayer } from './CursorRenderLayer'; import { ColorManager } from './ColorManager'; import { BaseRenderLayer } from './BaseRenderLayer'; -import { IRenderLayer } from './Types'; +import { IRenderLayer, IColorSet, IRenderer, IRenderDimensions } from './Types'; +import { ITerminal } from '../Types'; import { LinkRenderLayer } from './LinkRenderLayer'; import { EventEmitter } from '../EventEmitter'; import { ScreenDprMonitor } from '../utils/ScreenDprMonitor'; +import { ITheme } from 'xterm'; export class Renderer extends EventEmitter implements IRenderer { /** A queue of the rows to be refreshed */ diff --git a/src/renderer/SelectionRenderLayer.ts b/src/renderer/SelectionRenderLayer.ts index 033da76a6..53fc9b39d 100644 --- a/src/renderer/SelectionRenderLayer.ts +++ b/src/renderer/SelectionRenderLayer.ts @@ -3,10 +3,10 @@ * @license MIT */ -import { IColorSet, IRenderDimensions, IBuffer, ICharMeasure, ITerminal } from '../../typings/xterm-internal'; +import { IBuffer, ICharMeasure, ITerminal } from '../Types'; import { CHAR_DATA_ATTR_INDEX } from '../Buffer'; import { GridCache } from './GridCache'; -import { FLAGS } from './Types'; +import { FLAGS, IColorSet, IRenderDimensions } from './Types'; import { BaseRenderLayer } from './BaseRenderLayer'; export class SelectionRenderLayer extends BaseRenderLayer { diff --git a/src/renderer/TextRenderLayer.ts b/src/renderer/TextRenderLayer.ts index eebcc87c1..3c01cea3b 100644 --- a/src/renderer/TextRenderLayer.ts +++ b/src/renderer/TextRenderLayer.ts @@ -3,9 +3,9 @@ * @license MIT */ -import { IBuffer, ICharMeasure, ITerminal, IColorSet, IRenderDimensions, CharData } from '../../typings/xterm-internal'; import { CHAR_DATA_ATTR_INDEX, CHAR_DATA_CODE_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX } from '../Buffer'; -import { FLAGS } from './Types'; +import { FLAGS, IColorSet, IRenderDimensions } from './Types'; +import { CharData, IBuffer, ICharMeasure, ITerminal } from '../Types'; import { GridCache } from './GridCache'; import { BaseRenderLayer, INVERTED_DEFAULT_COLOR } from './BaseRenderLayer'; diff --git a/src/renderer/Types.ts b/src/renderer/Types.ts index 8f3716936..52c06e045 100644 --- a/src/renderer/Types.ts +++ b/src/renderer/Types.ts @@ -3,8 +3,8 @@ * @license MIT */ -import { IColorSet, IRenderDimensions, ITerminal } from '../../typings/xterm-internal'; -import { IEventEmitter } from 'xterm'; +import { ITerminal } from '../Types'; +import { IEventEmitter, ITheme } from 'xterm'; /** * Flags used to render terminal text properly. @@ -18,6 +18,51 @@ export enum FLAGS { DIM = 32 } +export interface IRenderer extends IEventEmitter { + dimensions: IRenderDimensions; + colorManager: IColorManager; + + setTheme(theme: ITheme): IColorSet; + onWindowResize(devicePixelRatio: number): void; + onResize(cols: number, rows: number, didCharSizeChange: boolean): void; + onCharSizeChanged(): void; + onBlur(): void; + onFocus(): void; + onSelectionChanged(start: [number, number], end: [number, number]): void; + onCursorMove(): void; + onOptionsChanged(): void; + clear(): void; + queueRefresh(start: number, end: number): void; +} + +export interface IColorManager { + colors: IColorSet; +} + +export interface IColorSet { + foreground: string; + background: string; + cursor: string; + cursorAccent: string; + selection: string; + ansi: string[]; +} + +export interface IRenderDimensions { + scaledCharWidth: number; + scaledCharHeight: number; + scaledCellWidth: number; + scaledCellHeight: number; + scaledCharLeft: number; + scaledCharTop: number; + scaledCanvasWidth: number; + scaledCanvasHeight: number; + canvasWidth: number; + canvasHeight: number; + actualCellWidth: number; + actualCellHeight: number; +} + export interface IRenderLayer { /** * Called when the terminal loses focus. diff --git a/src/utils/CharMeasure.test.ts b/src/utils/CharMeasure.test.ts index a706ea3b4..e4f4e1d6b 100644 --- a/src/utils/CharMeasure.test.ts +++ b/src/utils/CharMeasure.test.ts @@ -4,7 +4,7 @@ */ import jsdom = require('jsdom'); -import { ICharMeasure, ITerminal } from '../../typings/xterm-internal'; +import { ICharMeasure, ITerminal } from '../Types'; import { assert } from 'chai'; import { CharMeasure } from './CharMeasure'; diff --git a/src/utils/CharMeasure.ts b/src/utils/CharMeasure.ts index d91c10a4f..91cfce5ff 100644 --- a/src/utils/CharMeasure.ts +++ b/src/utils/CharMeasure.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ICharMeasure, ITerminal, ITerminalOptions } from '../../typings/xterm-internal'; +import { ICharMeasure, ITerminal, ITerminalOptions } from '../Types'; import { EventEmitter } from '../EventEmitter'; /** diff --git a/src/utils/CircularList.ts b/src/utils/CircularList.ts index f8c60b5a9..6b74971b6 100644 --- a/src/utils/CircularList.ts +++ b/src/utils/CircularList.ts @@ -4,7 +4,7 @@ */ import { EventEmitter } from '../EventEmitter'; -import { ICircularList } from '../../typings/xterm-internal'; +import { ICircularList } from '../Types'; /** * Represents a circular list; a list with a maximum size that wraps around when push is called, diff --git a/src/utils/MouseHelper.ts b/src/utils/MouseHelper.ts index de07dda75..f62593eb3 100644 --- a/src/utils/MouseHelper.ts +++ b/src/utils/MouseHelper.ts @@ -3,7 +3,8 @@ * @license MIT */ -import { ICharMeasure, IRenderer } from '../../typings/xterm-internal'; +import { ICharMeasure } from '../Types'; +import { IRenderer } from '../renderer/Types'; export class MouseHelper { constructor(private _renderer: IRenderer) {} diff --git a/src/utils/TestUtils.test.ts b/src/utils/TestUtils.test.ts index 54474a7f3..0744cd142 100644 --- a/src/utils/TestUtils.test.ts +++ b/src/utils/TestUtils.test.ts @@ -3,10 +3,11 @@ * @license MIT */ -import { ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, ICircularList, ITheme, ILinkifier, IMouseHelper, ILinkMatcherOptions, LineData, IColorSet, IRenderer, IRenderDimensions, IColorManager } from '../../typings/xterm-internal'; -import { IInputHandlingTerminal, IViewport, ICompositionHelper } from '../Types'; +import { IColorSet, IRenderer, IRenderDimensions, IColorManager } from '../renderer/Types'; +import { LineData, IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, ICircularList, ILinkifier, IMouseHelper, ILinkMatcherOptions } from '../Types'; import { Buffer } from '../Buffer'; import * as Browser from '../shared/utils/Browser'; +import { ITheme } from 'xterm'; export class MockTerminal implements ITerminal { getOption(key: any): any { diff --git a/tslint.json b/tslint.json index b5367f6a0..f6ad759a7 100644 --- a/tslint.json +++ b/tslint.json @@ -24,6 +24,7 @@ "parameter" ], "eofline": true, + "no-duplicate-imports": true, "no-eval": true, "no-internal-module": true, "no-trailing-whitespace": true, diff --git a/typings/xterm-internal.d.ts b/typings/xterm-internal.d.ts deleted file mode 100644 index 3670bad06..000000000 --- a/typings/xterm-internal.d.ts +++ /dev/null @@ -1,258 +0,0 @@ -/** - * Copyright (c) 2018 The xterm.js authors. All rights reserved. - * @license MIT - */ - -/// - -import { Terminal as PublicTerminal, ITerminalOptions as IPublicTerminalOptions, IEventEmitter } from 'xterm'; - -export type CharData = [number, string, number, number]; -export type LineData = CharData[]; - -export type LinkMatcherHandler = (event: MouseEvent, uri: string) => boolean | void; -export type LinkMatcherValidationCallback = (uri: string, callback: (isValid: boolean) => void) => void; - -export interface ITerminal extends PublicTerminal, IElementAccessor, IBufferAccessor, ILinkifierAccessor { - selectionManager: ISelectionManager; - charMeasure: ICharMeasure; - renderer: IRenderer; - browser: IBrowser; - writeBuffer: string[]; - cursorHidden: boolean; - cursorState: number; - defAttr: number; - options: ITerminalOptions; - buffer: IBuffer; - buffers: IBufferSet; - isFocused: boolean; - mouseHelper: IMouseHelper; - bracketedPasteMode: boolean; - - /** - * Emit the 'data' event and populate the given data. - * @param data The data to populate in the event. - */ - handler(data: string): void; - scrollLines(disp: number, suppressScrollEvent?: boolean): void; - cancel(ev: Event, force?: boolean): boolean | void; - log(text: string): void; - showCursor(): void; - blankLine(cur?: boolean, isWrapped?: boolean, cols?: number): LineData; -} - -export interface IBufferAccessor { - buffer: IBuffer; -} - -export interface IElementAccessor { - element: HTMLElement; -} - -export interface ILinkifierAccessor { - linkifier: ILinkifier; -} - -export interface IMouseHelper { - getCoords(event: {pageX: number, pageY: number}, element: HTMLElement, charMeasure: ICharMeasure, lineHeight: number, colCount: number, rowCount: number, isSelection?: boolean): [number, number]; - getRawByteCoords(event: MouseEvent, element: HTMLElement, charMeasure: ICharMeasure, lineHeight: number, colCount: number, rowCount: number): { x: number, y: number }; -} - -export interface ICharMeasure { - width: number; - height: number; - measure(options: ITerminalOptions): void; -} - -// TODO: The options that are not in the public API should be reviewed -export interface ITerminalOptions extends IPublicTerminalOptions { - cancelEvents?: boolean; - convertEol?: boolean; - debug?: boolean; - handler?: (data: string) => void; - screenKeys?: boolean; - termName?: string; - useFlowControl?: boolean; -} - -export interface IBuffer { - lines: ICircularList; - ydisp: number; - ybase: number; - y: number; - x: number; - tabs: any; - scrollBottom: number; - scrollTop: number; - savedY: number; - savedX: number; - isCursorInViewport: boolean; - translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol?: number, endCol?: number): string; - nextStop(x?: number): number; - prevStop(x?: number): number; -} - -export interface IBufferSet extends IEventEmitter { - alt: IBuffer; - normal: IBuffer; - active: IBuffer; - - activateNormalBuffer(): void; - activateAltBuffer(): void; -} - -export interface ICircularList extends IEventEmitter { - length: number; - maxLength: number; - forEach: (callbackfn: (value: T, index: number) => void) => void; - - get(index: number): T; - set(index: number, value: T): void; - push(value: T): void; - pop(): T; - splice(start: number, deleteCount: number, ...items: T[]): void; - trimStart(count: number): void; - shiftElements(start: number, count: number, offset: number): void; -} - -export interface ISelectionManager { - selectionText: string; - selectionStart: [number, number]; - selectionEnd: [number, number]; - - disable(): void; - enable(): void; - setSelection(row: number, col: number, length: number): void; -} - -export interface ILinkifier extends IEventEmitter { - attachToDom(mouseZoneManager: IMouseZoneManager): void; - linkifyRows(start: number, end: number): void; - setHypertextLinkHandler(handler: LinkMatcherHandler): void; - setHypertextValidationCallback(callback: LinkMatcherValidationCallback): void; - registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler, options?: ILinkMatcherOptions): number; - deregisterLinkMatcher(matcherId: number): boolean; -} - -export interface ILinkMatcherOptions { - /** - * The index of the link from the regex.match(text) call. This defaults to 0 - * (for regular expressions without capture groups). - */ - matchIndex?: number; - /** - * A callback that validates an individual link, returning true if valid and - * false if invalid. - */ - validationCallback?: LinkMatcherValidationCallback; - /** - * A callback that fires when the mouse hovers over a link. - */ - tooltipCallback?: LinkMatcherHandler; - /** - * A callback that fires when the mouse leaves a link that was hovered. - */ - leaveCallback?: () => void; - /** - * The priority of the link matcher, this defines the order in which the link - * matcher is evaluated relative to others, from highest to lowest. The - * default value is 0. - */ - priority?: number; -} - -export interface IBrowser { - isNode: boolean; - userAgent: string; - platform: string; - isFirefox: boolean; - isMSIE: boolean; - isMac: boolean; - isIpad: boolean; - isIphone: boolean; - isMSWindows: boolean; -} - -export interface IMouseZoneManager { - add(zone: IMouseZone): void; - clearAll(start?: number, end?: number): void; -} - -export interface IMouseZone { - x1: number; - x2: number; - y: number; - clickCallback: (e: MouseEvent) => any; - hoverCallback?: (e: MouseEvent) => any; - tooltipCallback?: (e: MouseEvent) => any; - leaveCallback?: () => any; -} - -export interface IRenderer extends IEventEmitter { - dimensions: IRenderDimensions; - colorManager: IColorManager; - - setTheme(theme: ITheme): IColorSet; - onWindowResize(devicePixelRatio: number): void; - onResize(cols: number, rows: number, didCharSizeChange: boolean): void; - onCharSizeChanged(): void; - onBlur(): void; - onFocus(): void; - onSelectionChanged(start: [number, number], end: [number, number]): void; - onCursorMove(): void; - onOptionsChanged(): void; - clear(): void; - queueRefresh(start: number, end: number): void; -} - -export interface IColorManager { - colors: IColorSet; -} - -export interface IColorSet { - foreground: string; - background: string; - cursor: string; - cursorAccent: string; - selection: string; - ansi: string[]; -} - -export interface IRenderDimensions { - scaledCharWidth: number; - scaledCharHeight: number; - scaledCellWidth: number; - scaledCellHeight: number; - scaledCharLeft: number; - scaledCharTop: number; - scaledCanvasWidth: number; - scaledCanvasHeight: number; - canvasWidth: number; - canvasHeight: number; - actualCellWidth: number; - actualCellHeight: number; -} - -export interface ITheme { - foreground?: string; - background?: string; - cursor?: string; - cursorAccent?: string; - selection?: string; - black?: string; - red?: string; - green?: string; - yellow?: string; - blue?: string; - magenta?: string; - cyan?: string; - white?: string; - brightBlack?: string; - brightRed?: string; - brightGreen?: string; - brightYellow?: string; - brightBlue?: string; - brightMagenta?: string; - brightCyan?: string; - brightWhite?: string; -} From c12394a6875ff2049c5f36d006b10deeb8587d30 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 25 Jan 2018 11:09:20 -0800 Subject: [PATCH 26/26] Don't export contains --- src/shared/utils/Browser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/utils/Browser.ts b/src/shared/utils/Browser.ts index 85d739a61..be71d875e 100644 --- a/src/shared/utils/Browser.ts +++ b/src/shared/utils/Browser.ts @@ -24,6 +24,6 @@ export const isLinux = platform.indexOf('Linux') >= 0; * @param {Array} array The array to search for the given element. * @param {Object} el The element to look for into the array */ -export function contains(arr: any[], el: any): boolean { +function contains(arr: any[], el: any): boolean { return arr.indexOf(el) >= 0; }