diff --git a/.eslintrc.json b/.eslintrc.json
index 41767bedf..32f8e9927 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -9,7 +9,6 @@
"project": [
"src/browser/tsconfig.json",
"src/common/tsconfig.json",
- "src/tsconfig.json",
"test/api/tsconfig.json",
"test/benchmark/tsconfig.json",
"addons/xterm-addon-attach/src/tsconfig.json",
diff --git a/addons/xterm-addon-serialize/benchmark/SerializeAddon.benchmark.ts b/addons/xterm-addon-serialize/benchmark/SerializeAddon.benchmark.ts
index fbc16e03d..c1764d8ed 100644
--- a/addons/xterm-addon-serialize/benchmark/SerializeAddon.benchmark.ts
+++ b/addons/xterm-addon-serialize/benchmark/SerializeAddon.benchmark.ts
@@ -7,7 +7,7 @@ import { perfContext, before, ThroughputRuntimeCase } from 'xterm-benchmark';
import { spawn } from 'node-pty';
import { Utf8ToUtf32, stringFromCodePoint } from 'common/input/TextDecoder';
-import { Terminal } from 'public/Terminal';
+import { Terminal } from 'browser/public/Terminal';
import { SerializeAddon } from 'SerializeAddon';
class TestTerminal extends Terminal {
diff --git a/addons/xterm-addon-serialize/benchmark/tsconfig.json b/addons/xterm-addon-serialize/benchmark/tsconfig.json
index 4e62ed59a..42aaaa1bf 100644
--- a/addons/xterm-addon-serialize/benchmark/tsconfig.json
+++ b/addons/xterm-addon-serialize/benchmark/tsconfig.json
@@ -11,8 +11,6 @@
"paths": {
"common/*": ["../../../src/common/*"],
"browser/*": ["../../../src/browser/*"],
- "public/*": ["../../../src/public/*"],
- "Terminal": ["../../../src/Terminal"],
"SerializeAddon": ["../src/SerializeAddon"]
}
},
diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/xterm-addon-webgl/src/WebglRenderer.ts
index 0333fd208..ac997c960 100644
--- a/addons/xterm-addon-webgl/src/WebglRenderer.ts
+++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts
@@ -3,7 +3,6 @@
* @license MIT
*/
-import { ITerminal } from '../../../src/Types';
import { GlyphRenderer } from './GlyphRenderer';
import { LinkRenderLayer } from './renderLayer/LinkRenderLayer';
import { CursorRenderLayer } from './renderLayer/CursorRenderLayer';
@@ -17,7 +16,7 @@ import { NULL_CELL_CODE } from 'common/buffer/Constants';
import { Terminal, IEvent } from 'xterm';
import { IRenderLayer } from './renderLayer/Types';
import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/Types';
-import { IColorSet } from 'browser/Types';
+import { ITerminal, IColorSet } from 'browser/Types';
import { EventEmitter } from 'common/EventEmitter';
import { CellData } from 'common/buffer/CellData';
@@ -52,8 +51,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
this._core = (this._terminal as any)._core;
this._renderLayers = [
- new LinkRenderLayer(this._core.screenElement, 2, this._colors, this._core),
- new CursorRenderLayer(this._core.screenElement, 3, this._colors, this._onRequestRedraw)
+ new LinkRenderLayer(this._core.screenElement!, 2, this._colors, this._core),
+ new CursorRenderLayer(this._core.screenElement!, 3, this._colors, this._onRequestRedraw)
];
this.dimensions = {
scaledCharWidth: 0,
@@ -83,7 +82,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
if (!this._gl) {
throw new Error('WebGL2 not supported ' + this._gl);
}
- this._core.screenElement.appendChild(this._canvas);
+ this._core.screenElement!.appendChild(this._canvas);
this._rectangleRenderer = new RectangleRenderer(this._terminal, this._colors, this._gl, this.dimensions);
this._glyphRenderer = new GlyphRenderer(this._terminal, this._colors, this._gl, this.dimensions);
@@ -91,12 +90,12 @@ export class WebglRenderer extends Disposable implements IRenderer {
// Update dimensions and acquire char atlas
this.onCharSizeChanged();
- this._isAttached = document.body.contains(this._core.screenElement);
+ this._isAttached = document.body.contains(this._core.screenElement!);
}
public dispose(): void {
this._renderLayers.forEach(l => l.dispose());
- this._core.screenElement.removeChild(this._canvas);
+ this._core.screenElement!.removeChild(this._canvas);
super.dispose();
}
@@ -150,8 +149,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
this._canvas.style.height = `${this.dimensions.canvasHeight}px`;
// Resize the screen
- this._core.screenElement.style.width = `${this.dimensions.canvasWidth}px`;
- this._core.screenElement.style.height = `${this.dimensions.canvasHeight}px`;
+ this._core.screenElement!.style.width = `${this.dimensions.canvasWidth}px`;
+ this._core.screenElement!.style.height = `${this.dimensions.canvasHeight}px`;
this._glyphRenderer.setDimensions(this.dimensions);
this._glyphRenderer.onResize();
@@ -229,7 +228,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
public renderRows(start: number, end: number): void {
if (!this._isAttached) {
- if (document.body.contains(this._core.screenElement) && (this._core as any)._charSizeService.width && (this._core as any)._charSizeService.height) {
+ if (document.body.contains(this._core.screenElement!) && (this._core as any)._charSizeService.width && (this._core as any)._charSizeService.height) {
this._updateDimensions();
this._refreshCharAtlas();
this._isAttached = true;
diff --git a/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts b/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts
index 10cf9c1fe..8f6b3e6da 100644
--- a/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts
+++ b/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts
@@ -3,18 +3,17 @@
* @license MIT
*/
-import { ILinkifierAccessor } from '../../../../src/Types';
import { Terminal } from 'xterm';
import { BaseRenderLayer } from './BaseRenderLayer';
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
import { is256Color } from '../atlas/CharAtlasUtils';
-import { IColorSet, ILinkifierEvent } from 'browser/Types';
+import { ITerminal, IColorSet, ILinkifierEvent } from 'browser/Types';
import { IRenderDimensions } from 'browser/renderer/Types';
export class LinkRenderLayer extends BaseRenderLayer {
private _state: ILinkifierEvent | undefined;
- constructor(container: HTMLElement, zIndex: number, colors: IColorSet, terminal: ILinkifierAccessor) {
+ constructor(container: HTMLElement, zIndex: number, colors: IColorSet, terminal: ITerminal) {
super(container, 'link', zIndex, true, colors);
terminal.linkifier.onShowLinkUnderline(e => this._onShowLinkUnderline(e));
terminal.linkifier.onHideLinkUnderline(e => this._onHideLinkUnderline(e));
diff --git a/bin/test.js b/bin/test.js
index 1380a5122..b9725acda 100644
--- a/bin/test.js
+++ b/bin/test.js
@@ -13,7 +13,6 @@ const env = { ...process.env };
env.NODE_PATH = path.resolve(__dirname, '../out');
let testFiles = [
- './out/*test.js',
'./out/**/*test.js',
'./addons/**/out/*test.js',
];
diff --git a/demo/client.ts b/demo/client.ts
index b009a534e..eaa6f8c1c 100644
--- a/demo/client.ts
+++ b/demo/client.ts
@@ -8,7 +8,7 @@
///
// Use tsc version (yarn watch)
-import { Terminal } from '../out/public/Terminal';
+import { Terminal } from '../out/browser/public/Terminal';
import { AttachAddon } from '../addons/xterm-addon-attach/out/AttachAddon';
import { FitAddon } from '../addons/xterm-addon-fit/out/FitAddon';
import { SearchAddon, ISearchOptions } from '../addons/xterm-addon-search/out/SearchAddon';
diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts
deleted file mode 100644
index 32b2633f8..000000000
--- a/src/TestUtils.test.ts
+++ /dev/null
@@ -1,327 +0,0 @@
-/**
- * Copyright (c) 2017 The xterm.js authors. All rights reserved.
- * @license MIT
- */
-
-import { IRenderer, IRenderDimensions, CharacterJoinerHandler, IRequestRedrawEvent } from 'browser/renderer/Types';
-import { ICompositionHelper, ITerminal, IBrowser } from './Types';
-import { IBuffer, IBufferStringIterator, IBufferSet } from 'common/buffer/Types';
-import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset, ITerminalOptions } from 'common/Types';
-import { Buffer } from 'common/buffer/Buffer';
-import * as Browser from 'common/Platform';
-import { IDisposable, IMarker, IEvent, ISelectionPosition, ILinkProvider } from 'xterm';
-import { Terminal } from './Terminal';
-import { AttributeData } from 'common/buffer/AttributeData';
-import { IColorManager, IColorSet, ILinkMatcherOptions, ILinkifier, IViewport, ILinkifier2 } from 'browser/Types';
-import { IOptionsService, IUnicodeService } from 'common/services/Services';
-import { IParams, IFunctionIdentifier } from 'common/parser/Types';
-import { ISelectionService } from 'browser/services/Services';
-
-export class TestTerminal extends Terminal {
- public get curAttrData(): IAttributeData { return (this as any)._inputHandler._curAttrData; }
- public keyDown(ev: any): boolean { return this._keyDown(ev); }
- public keyPress(ev: any): boolean { return this._keyPress(ev); }
-}
-
-export class MockTerminal implements ITerminal {
- public onBlur: IEvent;
- public onFocus: IEvent;
- public onA11yChar: IEvent;
- public onA11yTab: IEvent;
- public onCursorMove: IEvent;
- public onLineFeed: IEvent;
- public onSelectionChange: IEvent;
- public onData: IEvent;
- public onBinary: IEvent;
- public onTitleChange: IEvent;
- public onScroll: IEvent;
- public onKey: IEvent<{ key: string, domEvent: KeyboardEvent }>;
- public onRender: IEvent<{ start: number, end: number }>;
- public onResize: IEvent<{ cols: number, rows: number }>;
- public markers: IMarker[];
- public optionsService: IOptionsService;
- public unicodeService: IUnicodeService;
- public addMarker(cursorYOffset: number): IMarker {
- throw new Error('Method not implemented.');
- }
- public selectLines(start: number, end: number): void {
- throw new Error('Method not implemented.');
- }
- public scrollToLine(line: number): void {
- throw new Error('Method not implemented.');
- }
- public static string: any;
- public setOption(key: any, value: any): void {
- throw new Error('Method not implemented.');
- }
- public blur(): void {
- throw new Error('Method not implemented.');
- }
- public focus(): void {
- throw new Error('Method not implemented.');
- }
- public resize(columns: number, rows: number): void {
- throw new Error('Method not implemented.');
- }
- public writeln(data: string): void {
- throw new Error('Method not implemented.');
- }
- public paste(data: string): void {
- throw new Error('Method not implemented.');
- }
- public open(parent: HTMLElement): void {
- throw new Error('Method not implemented.');
- }
- public attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void {
- throw new Error('Method not implemented.');
- }
- public addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable {
- throw new Error('Method not implemented.');
- }
- public addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable {
- throw new Error('Method not implemented.');
- }
- public addEscHandler(id: IFunctionIdentifier, handler: () => boolean): IDisposable {
- throw new Error('Method not implemented.');
- }
- public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable {
- throw new Error('Method not implemented.');
- }
- public registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => boolean | void, options?: ILinkMatcherOptions): number {
- throw new Error('Method not implemented.');
- }
- public deregisterLinkMatcher(matcherId: number): void {
- throw new Error('Method not implemented.');
- }
- public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
- throw new Error('Method not implemented.');
- }
- public hasSelection(): boolean {
- throw new Error('Method not implemented.');
- }
- public getSelection(): string {
- throw new Error('Method not implemented.');
- }
- public getSelectionPosition(): ISelectionPosition | undefined {
- throw new Error('Method not implemented.');
- }
- public clearSelection(): void {
- throw new Error('Method not implemented.');
- }
- public select(column: number, row: number, length: number): void {
- throw new Error('Method not implemented.');
- }
- public selectAll(): void {
- throw new Error('Method not implemented.');
- }
- public dispose(): void {
- throw new Error('Method not implemented.');
- }
- public scrollPages(pageCount: number): void {
- throw new Error('Method not implemented.');
- }
- public scrollToTop(): void {
- throw new Error('Method not implemented.');
- }
- public scrollToBottom(): void {
- throw new Error('Method not implemented.');
- }
- public clear(): void {
- throw new Error('Method not implemented.');
- }
- public write(data: string): void {
- throw new Error('Method not implemented.');
- }
- public writeUtf8(data: Uint8Array): void {
- throw new Error('Method not implemented.');
- }
- public bracketedPasteMode: boolean;
- public renderer: IRenderer;
- public linkifier: ILinkifier;
- public linkifier2: ILinkifier2;
- public isFocused: boolean;
- public options: ITerminalOptions = {};
- public element: HTMLElement;
- public screenElement: HTMLElement;
- public rowContainer: HTMLElement;
- public selectionContainer: HTMLElement;
- public selectionService: ISelectionService;
- public textarea: HTMLTextAreaElement;
- public rows: number;
- public cols: number;
- public browser: IBrowser = Browser;
- public writeBuffer: string[];
- public children: HTMLElement[];
- public cursorHidden: boolean;
- public cursorState: number;
- public scrollback: number;
- public buffers: IBufferSet;
- public buffer: IBuffer;
- public viewport: IViewport;
- public applicationCursor: boolean;
- public handler(data: string): void {
- throw new Error('Method not implemented.');
- }
- public on(event: string, callback: (...args: any[]) => void): void {
- throw new Error('Method not implemented.');
- }
- public off(type: string, listener: XtermListener): void {
- throw new Error('Method not implemented.');
- }
- public addDisposableListener(type: string, handler: XtermListener): IDisposable {
- throw new Error('Method not implemented.');
- }
- public scrollLines(disp: number, suppressScrollEvent: boolean): void {
- throw new Error('Method not implemented.');
- }
- public scrollToRow(absoluteRow: number): number {
- throw new Error('Method not implemented.');
- }
- public cancel(ev: Event, force?: boolean): void {
- throw new Error('Method not implemented.');
- }
- public log(text: string): void {
- throw new Error('Method not implemented.');
- }
- public emit(event: string, data: any): void {
- throw new Error('Method not implemented.');
- }
- public reset(): void {
- throw new Error('Method not implemented.');
- }
- public refresh(start: number, end: number): void {
- throw new Error('Method not implemented.');
- }
- public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; }
- public deregisterCharacterJoiner(joinerId: number): void { }
-}
-
-export class MockBuffer implements IBuffer {
- public markers: IMarker[];
- public addMarker(y: number): IMarker {
- throw new Error('Method not implemented.');
- }
- public isCursorInViewport: boolean;
- public lines: ICircularList;
- public ydisp: number;
- public ybase: number;
- public hasScrollback: boolean;
- public y: number;
- public x: number;
- public tabs: any;
- public scrollBottom: number;
- public scrollTop: number;
- public savedY: number;
- public savedX: number;
- public savedCharset: ICharset | null;
- public savedCurAttrData = new AttributeData();
- public translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol?: number, endCol?: number): string {
- return Buffer.prototype.translateBufferLineToString.apply(this, arguments);
- }
- public getWrappedRangeForLine(y: number): { first: number, last: number } {
- return Buffer.prototype.getWrappedRangeForLine.apply(this, arguments);
- }
- public nextStop(x?: number): number {
- throw new Error('Method not implemented.');
- }
- public prevStop(x?: number): number {
- throw new Error('Method not implemented.');
- }
- public setLines(lines: ICircularList): void {
- this.lines = lines;
- }
- public getBlankLine(attr: IAttributeData, isWrapped?: boolean): IBufferLine {
- return Buffer.prototype.getBlankLine.apply(this, arguments);
- }
- public stringIndexToBufferIndex(lineIndex: number, stringIndex: number): number[] {
- return Buffer.prototype.stringIndexToBufferIndex.apply(this, arguments);
- }
- public iterator(trimRight: boolean, startIndex?: number, endIndex?: number): IBufferStringIterator {
- return Buffer.prototype.iterator.apply(this, arguments);
- }
- public getNullCell(attr?: IAttributeData): ICellData {
- throw new Error('Method not implemented.');
- }
- public getWhitespaceCell(attr?: IAttributeData): ICellData {
- throw new Error('Method not implemented.');
- }
-}
-
-export class MockRenderer implements IRenderer {
- public onRequestRedraw: IEvent;
- public onCanvasResize: IEvent<{ width: number, height: number }>;
- public onRender: IEvent<{ start: number, end: number }>;
- public dispose(): void {
- throw new Error('Method not implemented.');
- }
- public colorManager: IColorManager;
- public on(type: string, listener: XtermListener): void {
- throw new Error('Method not implemented.');
- }
- public off(type: string, listener: XtermListener): void {
- throw new Error('Method not implemented.');
- }
- public emit(type: string, data?: any): void {
- throw new Error('Method not implemented.');
- }
- public addDisposableListener(type: string, handler: XtermListener): IDisposable {
- throw new Error('Method not implemented.');
- }
- public dimensions: IRenderDimensions;
- public setColors(colors: IColorSet): void {
- throw new Error('Method not implemented.');
- }
- public onResize(cols: number, rows: number): void { }
- public onCharSizeChanged(): void { }
- public onBlur(): void { }
- public onFocus(): void { }
- public onSelectionChanged(start: [number, number], end: [number, number]): void { }
- public onCursorMove(): void { }
- public onOptionsChanged(): void { }
- public onDevicePixelRatioChange(): void { }
- public clear(): void { }
- public renderRows(start: number, end: number): void { }
- public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; }
- public deregisterCharacterJoiner(): boolean { return true; }
-}
-
-export class MockViewport implements IViewport {
- public dispose(): void {
- throw new Error('Method not implemented.');
- }
- public scrollBarWidth: number = 0;
- public onThemeChange(colors: IColorSet): void {
- throw new Error('Method not implemented.');
- }
- public onWheel(ev: WheelEvent): boolean {
- throw new Error('Method not implemented.');
- }
- public onTouchStart(ev: TouchEvent): void {
- throw new Error('Method not implemented.');
- }
- public onTouchMove(ev: TouchEvent): boolean {
- throw new Error('Method not implemented.');
- }
- public syncScrollArea(): void { }
- public getLinesScrolled(ev: WheelEvent): number {
- throw new Error('Method not implemented.');
- }
-}
-
-export class MockCompositionHelper implements ICompositionHelper {
- public compositionstart(): void {
- throw new Error('Method not implemented.');
- }
- public compositionupdate(ev: CompositionEvent): void {
- throw new Error('Method not implemented.');
- }
- public compositionend(): void {
- throw new Error('Method not implemented.');
- }
- public updateCompositionElements(dontRecurse?: boolean): void {
- throw new Error('Method not implemented.');
- }
- public keydown(ev: KeyboardEvent): boolean {
- return true;
- }
-}
diff --git a/src/Types.d.ts b/src/Types.d.ts
deleted file mode 100644
index 05c89e158..000000000
--- a/src/Types.d.ts
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * Copyright (c) 2017 The xterm.js authors. All rights reserved.
- * @license MIT
- */
-
-import { IDisposable, IMarker, ISelectionPosition, ILinkProvider } from 'xterm';
-import { IAttributeData, CharData, ITerminalOptions } from 'common/Types';
-import { IEvent } from 'common/EventEmitter';
-import { ILinkifier, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types';
-import { IOptionsService, IUnicodeService } from 'common/services/Services';
-import { IBuffer, IBufferSet } from 'common/buffer/Types';
-import { IParams, IFunctionIdentifier } from 'common/parser/Types';
-
-export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean;
-
-export type LineData = CharData[];
-
-export interface ICompositionHelper {
- compositionstart(): void;
- compositionupdate(ev: CompositionEvent): void;
- compositionend(): void;
- updateCompositionElements(dontRecurse?: boolean): void;
- keydown(ev: KeyboardEvent): boolean;
-}
-
-export interface ITerminal extends IPublicTerminal, IElementAccessor, IBufferAccessor, ILinkifierAccessor {
- screenElement: HTMLElement;
- browser: IBrowser;
- buffer: IBuffer;
- buffers: IBufferSet;
- viewport: IViewport;
- optionsService: IOptionsService;
- // TODO: We should remove options once components adopt optionsService
- options: ITerminalOptions;
- unicodeService: IUnicodeService;
-
- onBlur: IEvent;
- onFocus: IEvent;
- onA11yChar: IEvent;
- onA11yTab: IEvent;
-
- scrollLines(disp: number, suppressScrollEvent?: boolean): void;
- cancel(ev: Event, force?: boolean): boolean | void;
-}
-
-// Portions of the public API that are required by the internal Terminal
-export interface IPublicTerminal extends IDisposable {
- textarea: HTMLTextAreaElement | undefined;
- rows: number;
- cols: number;
- buffer: IBuffer;
- markers: IMarker[];
- onCursorMove: IEvent;
- onData: IEvent;
- onBinary: IEvent;
- onKey: IEvent<{ key: string, domEvent: KeyboardEvent }>;
- onLineFeed: IEvent;
- onScroll: IEvent;
- onSelectionChange: IEvent;
- onRender: IEvent<{ start: number, end: number }>;
- onResize: IEvent<{ cols: number, rows: number }>;
- onTitleChange: IEvent;
- blur(): void;
- focus(): void;
- resize(columns: number, rows: number): void;
- open(parent: HTMLElement): void;
- attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void;
- addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable;
- addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable;
- addEscHandler(id: IFunctionIdentifier, callback: () => boolean): IDisposable;
- addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable;
- registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions): number;
- deregisterLinkMatcher(matcherId: number): void;
- registerLinkProvider(linkProvider: ILinkProvider): IDisposable;
- registerCharacterJoiner(handler: (text: string) => [number, number][]): number;
- deregisterCharacterJoiner(joinerId: number): void;
- addMarker(cursorYOffset: number): IMarker;
- hasSelection(): boolean;
- getSelection(): string;
- getSelectionPosition(): ISelectionPosition | undefined;
- clearSelection(): void;
- select(column: number, row: number, length: number): void;
- selectAll(): void;
- selectLines(start: number, end: number): void;
- dispose(): void;
- scrollLines(amount: number): void;
- scrollPages(pageCount: number): void;
- scrollToTop(): void;
- scrollToBottom(): void;
- scrollToLine(line: number): void;
- clear(): void;
- write(data: string | Uint8Array, callback?: () => void): void;
- paste(data: string): void;
- refresh(start: number, end: number): void;
- reset(): void;
-}
-
-export interface IBufferAccessor {
- buffer: IBuffer;
-}
-
-export interface IElementAccessor {
- readonly element: HTMLElement | undefined;
-}
-
-export interface ILinkifierAccessor {
- linkifier: ILinkifier;
- linkifier2: ILinkifier2;
-}
-
-export interface IBrowser {
- isNode: boolean;
- userAgent: string;
- platform: string;
- isFirefox: boolean;
- isMac: boolean;
- isIpad: boolean;
- isIphone: boolean;
- isWindows: boolean;
-}
diff --git a/src/AccessibilityManager.ts b/src/browser/AccessibilityManager.ts
similarity index 97%
rename from src/AccessibilityManager.ts
rename to src/browser/AccessibilityManager.ts
index 783915011..2a34d6a36 100644
--- a/src/AccessibilityManager.ts
+++ b/src/browser/AccessibilityManager.ts
@@ -3,8 +3,8 @@
* @license MIT
*/
-import * as Strings from './browser/LocalizableStrings';
-import { ITerminal } from './Types';
+import * as Strings from 'browser/LocalizableStrings';
+import { ITerminal } from 'browser/Types';
import { IBuffer } from 'common/buffer/Types';
import { isMac } from 'common/Platform';
import { RenderDebouncer } from 'browser/RenderDebouncer';
@@ -79,6 +79,9 @@ export class AccessibilityManager extends Disposable {
this._liveRegion.setAttribute('aria-live', 'assertive');
this._accessibilityTreeRoot.appendChild(this._liveRegion);
+ if (!this._terminal.element) {
+ throw new Error('Cannot enable accessibility before Terminal.open');
+ }
this._terminal.element.insertAdjacentElement('afterbegin', this._accessibilityTreeRoot);
this.register(this._renderRowsDebouncer);
@@ -103,7 +106,7 @@ export class AccessibilityManager extends Disposable {
public dispose(): void {
super.dispose();
- this._terminal.element.removeChild(this._accessibilityTreeRoot);
+ this._terminal.element?.removeChild(this._accessibilityTreeRoot);
this._rowElements.length = 0;
}
diff --git a/src/browser/Linkifier2.ts b/src/browser/Linkifier2.ts
index 548121699..458b1bff0 100644
--- a/src/browser/Linkifier2.ts
+++ b/src/browser/Linkifier2.ts
@@ -3,7 +3,7 @@
* @license MIT
*/
-import { ILinkifier2, ILinkProvider, IBufferCellPosition, ILink, ILinkifierEvent, ILinkDecorations } from './Types';
+import { ILinkifier2, ILinkProvider, IBufferCellPosition, ILink, ILinkifierEvent, ILinkDecorations } from 'browser/Types';
import { IDisposable } from 'common/Types';
import { IMouseService, IRenderService } from './services/Services';
import { IBufferService } from 'common/services/Services';
diff --git a/src/browser/RenderDebouncer.ts b/src/browser/RenderDebouncer.ts
index 814afcef4..2a06fdd66 100644
--- a/src/browser/RenderDebouncer.ts
+++ b/src/browser/RenderDebouncer.ts
@@ -26,7 +26,7 @@ export class RenderDebouncer implements IDisposable {
}
}
- public refresh(rowStart: number, rowEnd: number, rowCount: number): void {
+ public refresh(rowStart: number | undefined, rowEnd: number | undefined, rowCount: number): void {
this._rowCount = rowCount;
// Get the min/max row start/end for the arg values
rowStart = rowStart !== undefined ? rowStart : 0;
diff --git a/src/Terminal.test.ts b/src/browser/Terminal.test.ts
similarity index 80%
rename from src/Terminal.test.ts
rename to src/browser/Terminal.test.ts
index 6488aa43f..729c0d0f2 100644
--- a/src/Terminal.test.ts
+++ b/src/browser/Terminal.test.ts
@@ -4,7 +4,7 @@
*/
import { assert, expect } from 'chai';
-import { MockViewport, MockCompositionHelper, MockRenderer, TestTerminal } from './TestUtils.test';
+import { MockViewport, MockCompositionHelper, MockRenderer, TestTerminal } from 'browser/TestUtils.test';
import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
import { CellData } from 'common/buffer/CellData';
import { IBufferService, IUnicodeService } from 'common/services/Services';
@@ -395,62 +395,62 @@ describe('Terminal', () => {
describe('scroll() function', () => {
describe('when scrollback > 0', () => {
it('should create a new line and scroll', () => {
- term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)]));
- term.buffer.lines.get(INIT_ROWS - 1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)]));
+ term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)]));
+ term.buffer.lines.get(INIT_ROWS - 1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)]));
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
term.scroll(DEFAULT_ATTR_DATA.clone());
assert.equal(term.buffer.lines.length, INIT_ROWS + 1);
- assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a');
- assert.equal(term.buffer.lines.get(INIT_ROWS - 1).loadCell(0, new CellData()).getChars(), 'b');
- assert.equal(term.buffer.lines.get(INIT_ROWS).loadCell(0, new CellData()).getChars(), '');
+ assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a');
+ assert.equal(term.buffer.lines.get(INIT_ROWS - 1)!.loadCell(0, new CellData()).getChars(), 'b');
+ assert.equal(term.buffer.lines.get(INIT_ROWS)!.loadCell(0, new CellData()).getChars(), '');
});
it('should properly scroll inside a scroll region (scrollTop set)', () => {
- term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)]));
- term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)]));
- term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)]));
+ term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)]));
+ term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)]));
+ term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)]));
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
term.buffer.scrollTop = 1;
term.scroll(DEFAULT_ATTR_DATA.clone());
assert.equal(term.buffer.lines.length, INIT_ROWS);
- assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a');
- assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c');
+ assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a');
+ assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'c');
});
it('should properly scroll inside a scroll region (scrollBottom set)', () => {
- term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)]));
- term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)]));
- term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)]));
- term.buffer.lines.get(3).setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)]));
- term.buffer.lines.get(4).setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)]));
+ term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)]));
+ term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)]));
+ term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)]));
+ term.buffer.lines.get(3)!.setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)]));
+ term.buffer.lines.get(4)!.setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)]));
term.buffer.y = 3;
term.buffer.scrollBottom = 3;
term.scroll(DEFAULT_ATTR_DATA.clone());
assert.equal(term.buffer.lines.length, INIT_ROWS + 1);
- assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a', '\'a\' should be pushed to the scrollback');
- assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'b');
- assert.equal(term.buffer.lines.get(2).loadCell(0, new CellData()).getChars(), 'c');
- assert.equal(term.buffer.lines.get(3).loadCell(0, new CellData()).getChars(), 'd');
- assert.equal(term.buffer.lines.get(4).loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index');
- assert.equal(term.buffer.lines.get(5).loadCell(0, new CellData()).getChars(), 'e');
+ assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a', '\'a\' should be pushed to the scrollback');
+ assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'b');
+ assert.equal(term.buffer.lines.get(2)!.loadCell(0, new CellData()).getChars(), 'c');
+ assert.equal(term.buffer.lines.get(3)!.loadCell(0, new CellData()).getChars(), 'd');
+ assert.equal(term.buffer.lines.get(4)!.loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index');
+ assert.equal(term.buffer.lines.get(5)!.loadCell(0, new CellData()).getChars(), 'e');
});
it('should properly scroll inside a scroll region (scrollTop and scrollBottom set)', () => {
- term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)]));
- term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)]));
- term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)]));
- term.buffer.lines.get(3).setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)]));
- term.buffer.lines.get(4).setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)]));
+ term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)]));
+ term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)]));
+ term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)]));
+ term.buffer.lines.get(3)!.setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)]));
+ term.buffer.lines.get(4)!.setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)]));
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
term.buffer.scrollTop = 1;
term.buffer.scrollBottom = 3;
term.scroll(DEFAULT_ATTR_DATA.clone());
assert.equal(term.buffer.lines.length, INIT_ROWS);
- assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a');
- assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c', '\'b\' should be removed from the buffer');
- assert.equal(term.buffer.lines.get(2).loadCell(0, new CellData()).getChars(), 'd');
- assert.equal(term.buffer.lines.get(3).loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index');
- assert.equal(term.buffer.lines.get(4).loadCell(0, new CellData()).getChars(), 'e');
+ assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a');
+ assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'c', '\'b\' should be removed from the buffer');
+ assert.equal(term.buffer.lines.get(2)!.loadCell(0, new CellData()).getChars(), 'd');
+ assert.equal(term.buffer.lines.get(3)!.loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index');
+ assert.equal(term.buffer.lines.get(4)!.loadCell(0, new CellData()).getChars(), 'e');
});
});
@@ -461,65 +461,65 @@ describe('Terminal', () => {
});
it('should create a new line and shift everything up', () => {
- term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)]));
- term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)]));
- term.buffer.lines.get(INIT_ROWS - 1).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)]));
+ term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)]));
+ term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)]));
+ term.buffer.lines.get(INIT_ROWS - 1)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)]));
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
assert.equal(term.buffer.lines.length, INIT_ROWS);
term.scroll(DEFAULT_ATTR_DATA.clone());
assert.equal(term.buffer.lines.length, INIT_ROWS);
// 'a' gets pushed out of buffer
- assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'b');
- assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), '');
- assert.equal(term.buffer.lines.get(INIT_ROWS - 2).loadCell(0, new CellData()).getChars(), 'c');
- assert.equal(term.buffer.lines.get(INIT_ROWS - 1).loadCell(0, new CellData()).getChars(), '');
+ assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'b');
+ assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), '');
+ assert.equal(term.buffer.lines.get(INIT_ROWS - 2)!.loadCell(0, new CellData()).getChars(), 'c');
+ assert.equal(term.buffer.lines.get(INIT_ROWS - 1)!.loadCell(0, new CellData()).getChars(), '');
});
it('should properly scroll inside a scroll region (scrollTop set)', () => {
- term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)]));
- term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)]));
- term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)]));
+ term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)]));
+ term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)]));
+ term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)]));
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
term.buffer.scrollTop = 1;
term.scroll(DEFAULT_ATTR_DATA.clone());
assert.equal(term.buffer.lines.length, INIT_ROWS);
- assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a');
- assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c');
+ assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a');
+ assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'c');
});
it('should properly scroll inside a scroll region (scrollBottom set)', () => {
- term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)]));
- term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)]));
- term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)]));
- term.buffer.lines.get(3).setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)]));
- term.buffer.lines.get(4).setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)]));
+ term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)]));
+ term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)]));
+ term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)]));
+ term.buffer.lines.get(3)!.setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)]));
+ term.buffer.lines.get(4)!.setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)]));
term.buffer.y = 3;
term.buffer.scrollBottom = 3;
term.scroll(DEFAULT_ATTR_DATA.clone());
assert.equal(term.buffer.lines.length, INIT_ROWS);
- assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'b');
- assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c');
- assert.equal(term.buffer.lines.get(2).loadCell(0, new CellData()).getChars(), 'd');
- assert.equal(term.buffer.lines.get(3).loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index');
- assert.equal(term.buffer.lines.get(4).loadCell(0, new CellData()).getChars(), 'e');
+ assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'b');
+ assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'c');
+ assert.equal(term.buffer.lines.get(2)!.loadCell(0, new CellData()).getChars(), 'd');
+ assert.equal(term.buffer.lines.get(3)!.loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index');
+ assert.equal(term.buffer.lines.get(4)!.loadCell(0, new CellData()).getChars(), 'e');
});
it('should properly scroll inside a scroll region (scrollTop and scrollBottom set)', () => {
- term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)]));
- term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)]));
- term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)]));
- term.buffer.lines.get(3).setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)]));
- term.buffer.lines.get(4).setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)]));
+ term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)]));
+ term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)]));
+ term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)]));
+ term.buffer.lines.get(3)!.setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)]));
+ term.buffer.lines.get(4)!.setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)]));
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
term.buffer.scrollTop = 1;
term.buffer.scrollBottom = 3;
term.scroll(DEFAULT_ATTR_DATA.clone());
assert.equal(term.buffer.lines.length, INIT_ROWS);
- assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a');
- assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c', '\'b\' should be removed from the buffer');
- assert.equal(term.buffer.lines.get(2).loadCell(0, new CellData()).getChars(), 'd');
- assert.equal(term.buffer.lines.get(3).loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index');
- assert.equal(term.buffer.lines.get(4).loadCell(0, new CellData()).getChars(), 'e');
+ assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a');
+ assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'c', '\'b\' should be removed from the buffer');
+ assert.equal(term.buffer.lines.get(2)!.loadCell(0, new CellData()).getChars(), 'd');
+ assert.equal(term.buffer.lines.get(3)!.loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index');
+ assert.equal(term.buffer.lines.get(4)!.loadCell(0, new CellData()).getChars(), 'e');
});
});
});
@@ -722,11 +722,11 @@ describe('Terminal', () => {
const cell = new CellData();
for (let i = 0xDC00; i <= 0xDCFF; ++i) {
term.writeSync(high + String.fromCharCode(i));
- const tchar = term.buffer.lines.get(0).loadCell(0, cell);
+ const tchar = term.buffer.lines.get(0)!.loadCell(0, cell);
expect(tchar.getChars()).eql(high + String.fromCharCode(i));
expect(tchar.getChars().length).eql(2);
expect(tchar.getWidth()).eql(1);
- expect(term.buffer.lines.get(0).loadCell(1, cell).getChars()).eql('');
+ expect(term.buffer.lines.get(0)!.loadCell(1, cell).getChars()).eql('');
term.reset();
}
});
@@ -736,9 +736,9 @@ describe('Terminal', () => {
for (let i = 0xDC00; i <= 0xDCFF; ++i) {
term.buffer.x = term.cols - 1;
term.writeSync(high + String.fromCharCode(i));
- expect(term.buffer.lines.get(0).loadCell(term.buffer.x - 1, cell).getChars()).eql(high + String.fromCharCode(i));
- expect(term.buffer.lines.get(0).loadCell(term.buffer.x - 1, cell).getChars().length).eql(2);
- expect(term.buffer.lines.get(1).loadCell(0, cell).getChars()).eql('');
+ expect(term.buffer.lines.get(0)!.loadCell(term.buffer.x - 1, cell).getChars()).eql(high + String.fromCharCode(i));
+ expect(term.buffer.lines.get(0)!.loadCell(term.buffer.x - 1, cell).getChars().length).eql(2);
+ expect(term.buffer.lines.get(1)!.loadCell(0, cell).getChars()).eql('');
term.reset();
}
});
@@ -749,10 +749,10 @@ describe('Terminal', () => {
term.buffer.x = term.cols - 1;
term.writeSync('a' + high + String.fromCharCode(i));
- expect(term.buffer.lines.get(0).loadCell(term.cols - 1, cell).getChars()).eql('a');
- expect(term.buffer.lines.get(1).loadCell(0, cell).getChars()).eql(high + String.fromCharCode(i));
- expect(term.buffer.lines.get(1).loadCell(0, cell).getChars().length).eql(2);
- expect(term.buffer.lines.get(1).loadCell(1, cell).getChars()).eql('');
+ expect(term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell).getChars()).eql('a');
+ expect(term.buffer.lines.get(1)!.loadCell(0, cell).getChars()).eql(high + String.fromCharCode(i));
+ expect(term.buffer.lines.get(1)!.loadCell(0, cell).getChars().length).eql(2);
+ expect(term.buffer.lines.get(1)!.loadCell(1, cell).getChars()).eql('');
term.reset();
}
});
@@ -768,9 +768,9 @@ describe('Terminal', () => {
}
term.writeSync('a' + high + String.fromCharCode(i));
// auto wraparound mode should cut off the rest of the line
- expect(term.buffer.lines.get(0).loadCell(term.cols - 1, cell).getChars()).eql(high + String.fromCharCode(i));
- expect(term.buffer.lines.get(0).loadCell(term.cols - 1, cell).getChars().length).eql(2);
- expect(term.buffer.lines.get(1).loadCell(1, cell).getChars()).eql('');
+ expect(term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell).getChars()).eql(high + String.fromCharCode(i));
+ expect(term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell).getChars().length).eql(2);
+ expect(term.buffer.lines.get(1)!.loadCell(1, cell).getChars()).eql('');
term.reset();
}
});
@@ -780,11 +780,11 @@ describe('Terminal', () => {
for (let i = 0xDC00; i <= 0xDCFF; ++i) {
term.writeSync(high);
term.writeSync(String.fromCharCode(i));
- const tchar = term.buffer.lines.get(0).loadCell(0, cell);
+ const tchar = term.buffer.lines.get(0)!.loadCell(0, cell);
expect(tchar.getChars()).eql(high + String.fromCharCode(i));
expect(tchar.getChars().length).eql(2);
expect(tchar.getWidth()).eql(1);
- expect(term.buffer.lines.get(0).loadCell(1, cell).getChars()).eql('');
+ expect(term.buffer.lines.get(0)!.loadCell(1, cell).getChars()).eql('');
term.reset();
}
});
@@ -794,7 +794,7 @@ describe('Terminal', () => {
const cell = new CellData();
it('café', () => {
term.writeSync('cafe\u0301');
- term.buffer.lines.get(0).loadCell(3, cell);
+ term.buffer.lines.get(0)!.loadCell(3, cell);
expect(cell.getChars()).eql('e\u0301');
expect(cell.getChars().length).eql(2);
expect(cell.getWidth()).eql(1);
@@ -802,11 +802,11 @@ describe('Terminal', () => {
it('café - end of line', () => {
term.buffer.x = term.cols - 1 - 3;
term.writeSync('cafe\u0301');
- term.buffer.lines.get(0).loadCell(term.cols - 1, cell);
+ term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell);
expect(cell.getChars()).eql('e\u0301');
expect(cell.getChars().length).eql(2);
expect(cell.getWidth()).eql(1);
- term.buffer.lines.get(0).loadCell(1, cell);
+ term.buffer.lines.get(0)!.loadCell(1, cell);
expect(cell.getChars()).eql('');
expect(cell.getChars().length).eql(0);
expect(cell.getWidth()).eql(1);
@@ -814,12 +814,12 @@ describe('Terminal', () => {
it('multiple combined é', () => {
term.writeSync(Array(100).join('e\u0301'));
for (let i = 0; i < term.cols; ++i) {
- term.buffer.lines.get(0).loadCell(i, cell);
+ term.buffer.lines.get(0)!.loadCell(i, cell);
expect(cell.getChars()).eql('e\u0301');
expect(cell.getChars().length).eql(2);
expect(cell.getWidth()).eql(1);
}
- term.buffer.lines.get(1).loadCell(0, cell);
+ term.buffer.lines.get(1)!.loadCell(0, cell);
expect(cell.getChars()).eql('e\u0301');
expect(cell.getChars().length).eql(2);
expect(cell.getWidth()).eql(1);
@@ -827,12 +827,12 @@ describe('Terminal', () => {
it('multiple surrogate with combined', () => {
term.writeSync(Array(100).join('\uD800\uDC00\u0301'));
for (let i = 0; i < term.cols; ++i) {
- term.buffer.lines.get(0).loadCell(i, cell);
+ term.buffer.lines.get(0)!.loadCell(i, cell);
expect(cell.getChars()).eql('\uD800\uDC00\u0301');
expect(cell.getChars().length).eql(3);
expect(cell.getWidth()).eql(1);
}
- term.buffer.lines.get(1).loadCell(0, cell);
+ term.buffer.lines.get(1)!.loadCell(0, cell);
expect(cell.getChars()).eql('\uD800\uDC00\u0301');
expect(cell.getChars().length).eql(3);
expect(cell.getWidth()).eql(1);
@@ -855,7 +855,7 @@ describe('Terminal', () => {
it('line of ¥ even', () => {
term.writeSync(Array(50).join('¥'));
for (let i = 0; i < term.cols; ++i) {
- term.buffer.lines.get(0).loadCell(i, cell);
+ term.buffer.lines.get(0)!.loadCell(i, cell);
if (i % 2) {
expect(cell.getChars()).eql('');
expect(cell.getChars().length).eql(0);
@@ -866,7 +866,7 @@ describe('Terminal', () => {
expect(cell.getWidth()).eql(2);
}
}
- term.buffer.lines.get(1).loadCell(0, cell);
+ term.buffer.lines.get(1)!.loadCell(0, cell);
expect(cell.getChars()).eql('¥');
expect(cell.getChars().length).eql(1);
expect(cell.getWidth()).eql(2);
@@ -875,7 +875,7 @@ describe('Terminal', () => {
term.buffer.x = 1;
term.writeSync(Array(50).join('¥'));
for (let i = 1; i < term.cols - 1; ++i) {
- term.buffer.lines.get(0).loadCell(i, cell);
+ term.buffer.lines.get(0)!.loadCell(i, cell);
if (!(i % 2)) {
expect(cell.getChars()).eql('');
expect(cell.getChars().length).eql(0);
@@ -886,11 +886,11 @@ describe('Terminal', () => {
expect(cell.getWidth()).eql(2);
}
}
- term.buffer.lines.get(0).loadCell(term.cols - 1, cell);
+ term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell);
expect(cell.getChars()).eql('');
expect(cell.getChars().length).eql(0);
expect(cell.getWidth()).eql(1);
- term.buffer.lines.get(1).loadCell(0, cell);
+ term.buffer.lines.get(1)!.loadCell(0, cell);
expect(cell.getChars()).eql('¥');
expect(cell.getChars().length).eql(1);
expect(cell.getWidth()).eql(2);
@@ -899,7 +899,7 @@ describe('Terminal', () => {
term.buffer.x = 1;
term.writeSync(Array(50).join('¥\u0301'));
for (let i = 1; i < term.cols - 1; ++i) {
- term.buffer.lines.get(0).loadCell(i, cell);
+ term.buffer.lines.get(0)!.loadCell(i, cell);
if (!(i % 2)) {
expect(cell.getChars()).eql('');
expect(cell.getChars().length).eql(0);
@@ -910,11 +910,11 @@ describe('Terminal', () => {
expect(cell.getWidth()).eql(2);
}
}
- term.buffer.lines.get(0).loadCell(term.cols - 1, cell);
+ term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell);
expect(cell.getChars()).eql('');
expect(cell.getChars().length).eql(0);
expect(cell.getWidth()).eql(1);
- term.buffer.lines.get(1).loadCell(0, cell);
+ term.buffer.lines.get(1)!.loadCell(0, cell);
expect(cell.getChars()).eql('¥\u0301');
expect(cell.getChars().length).eql(2);
expect(cell.getWidth()).eql(2);
@@ -922,7 +922,7 @@ describe('Terminal', () => {
it('line of ¥ with combining even', () => {
term.writeSync(Array(50).join('¥\u0301'));
for (let i = 0; i < term.cols; ++i) {
- term.buffer.lines.get(0).loadCell(i, cell);
+ term.buffer.lines.get(0)!.loadCell(i, cell);
if (i % 2) {
expect(cell.getChars()).eql('');
expect(cell.getChars().length).eql(0);
@@ -933,7 +933,7 @@ describe('Terminal', () => {
expect(cell.getWidth()).eql(2);
}
}
- term.buffer.lines.get(1).loadCell(0, cell);
+ term.buffer.lines.get(1)!.loadCell(0, cell);
expect(cell.getChars()).eql('¥\u0301');
expect(cell.getChars().length).eql(2);
expect(cell.getWidth()).eql(2);
@@ -942,7 +942,7 @@ describe('Terminal', () => {
term.buffer.x = 1;
term.writeSync(Array(50).join('\ud843\ude6d\u0301'));
for (let i = 1; i < term.cols - 1; ++i) {
- term.buffer.lines.get(0).loadCell(i, cell);
+ term.buffer.lines.get(0)!.loadCell(i, cell);
if (!(i % 2)) {
expect(cell.getChars()).eql('');
expect(cell.getChars().length).eql(0);
@@ -953,11 +953,11 @@ describe('Terminal', () => {
expect(cell.getWidth()).eql(2);
}
}
- term.buffer.lines.get(0).loadCell(term.cols - 1, cell);
+ term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell);
expect(cell.getChars()).eql('');
expect(cell.getChars().length).eql(0);
expect(cell.getWidth()).eql(1);
- term.buffer.lines.get(1).loadCell(0, cell);
+ term.buffer.lines.get(1)!.loadCell(0, cell);
expect(cell.getChars()).eql('\ud843\ude6d\u0301');
expect(cell.getChars().length).eql(3);
expect(cell.getWidth()).eql(2);
@@ -965,7 +965,7 @@ describe('Terminal', () => {
it('line of surrogate fullwidth with combining even', () => {
term.writeSync(Array(50).join('\ud843\ude6d\u0301'));
for (let i = 0; i < term.cols; ++i) {
- term.buffer.lines.get(0).loadCell(i, cell);
+ term.buffer.lines.get(0)!.loadCell(i, cell);
if (i % 2) {
expect(cell.getChars()).eql('');
expect(cell.getChars().length).eql(0);
@@ -976,7 +976,7 @@ describe('Terminal', () => {
expect(cell.getWidth()).eql(2);
}
}
- term.buffer.lines.get(1).loadCell(0, cell);
+ term.buffer.lines.get(1)!.loadCell(0, cell);
expect(cell.getChars()).eql('\ud843\ude6d\u0301');
expect(cell.getChars().length).eql(3);
expect(cell.getWidth()).eql(2);
@@ -991,11 +991,11 @@ describe('Terminal', () => {
term.buffer.y = 0;
term.write('\x1b[4h');
term.writeSync('abcde');
- expect(term.buffer.lines.get(0).length).eql(term.cols);
- expect(term.buffer.lines.get(0).loadCell(10, cell).getChars()).eql('a');
- expect(term.buffer.lines.get(0).loadCell(14, cell).getChars()).eql('e');
- expect(term.buffer.lines.get(0).loadCell(15, cell).getChars()).eql('0');
- expect(term.buffer.lines.get(0).loadCell(79, cell).getChars()).eql('4');
+ expect(term.buffer.lines.get(0)!.length).eql(term.cols);
+ expect(term.buffer.lines.get(0)!.loadCell(10, cell).getChars()).eql('a');
+ expect(term.buffer.lines.get(0)!.loadCell(14, cell).getChars()).eql('e');
+ expect(term.buffer.lines.get(0)!.loadCell(15, cell).getChars()).eql('0');
+ expect(term.buffer.lines.get(0)!.loadCell(79, cell).getChars()).eql('4');
});
it('fullwidth - insert', () => {
term.writeSync(Array(9).join('0123456789').slice(-80));
@@ -1003,12 +1003,12 @@ describe('Terminal', () => {
term.buffer.y = 0;
term.write('\x1b[4h');
term.writeSync('¥¥¥');
- expect(term.buffer.lines.get(0).length).eql(term.cols);
- expect(term.buffer.lines.get(0).loadCell(10, cell).getChars()).eql('¥');
- expect(term.buffer.lines.get(0).loadCell(11, cell).getChars()).eql('');
- expect(term.buffer.lines.get(0).loadCell(14, cell).getChars()).eql('¥');
- expect(term.buffer.lines.get(0).loadCell(15, cell).getChars()).eql('');
- expect(term.buffer.lines.get(0).loadCell(79, cell).getChars()).eql('3');
+ expect(term.buffer.lines.get(0)!.length).eql(term.cols);
+ expect(term.buffer.lines.get(0)!.loadCell(10, cell).getChars()).eql('¥');
+ expect(term.buffer.lines.get(0)!.loadCell(11, cell).getChars()).eql('');
+ expect(term.buffer.lines.get(0)!.loadCell(14, cell).getChars()).eql('¥');
+ expect(term.buffer.lines.get(0)!.loadCell(15, cell).getChars()).eql('');
+ expect(term.buffer.lines.get(0)!.loadCell(79, cell).getChars()).eql('3');
});
it('fullwidth - right border', () => {
term.writeSync(Array(41).join('¥'));
@@ -1016,15 +1016,15 @@ describe('Terminal', () => {
term.buffer.y = 0;
term.write('\x1b[4h');
term.writeSync('a');
- expect(term.buffer.lines.get(0).length).eql(term.cols);
- expect(term.buffer.lines.get(0).loadCell(10, cell).getChars()).eql('a');
- expect(term.buffer.lines.get(0).loadCell(11, cell).getChars()).eql('¥');
- expect(term.buffer.lines.get(0).loadCell(79, cell).getChars()).eql(''); // fullwidth char got replaced
+ expect(term.buffer.lines.get(0)!.length).eql(term.cols);
+ expect(term.buffer.lines.get(0)!.loadCell(10, cell).getChars()).eql('a');
+ expect(term.buffer.lines.get(0)!.loadCell(11, cell).getChars()).eql('¥');
+ expect(term.buffer.lines.get(0)!.loadCell(79, cell).getChars()).eql(''); // fullwidth char got replaced
term.writeSync('b');
- expect(term.buffer.lines.get(0).length).eql(term.cols);
- expect(term.buffer.lines.get(0).loadCell(11, cell).getChars()).eql('b');
- expect(term.buffer.lines.get(0).loadCell(12, cell).getChars()).eql('¥');
- expect(term.buffer.lines.get(0).loadCell(79, cell).getChars()).eql(''); // empty cell after fullwidth
+ expect(term.buffer.lines.get(0)!.length).eql(term.cols);
+ expect(term.buffer.lines.get(0)!.loadCell(11, cell).getChars()).eql('b');
+ expect(term.buffer.lines.get(0)!.loadCell(12, cell).getChars()).eql('¥');
+ expect(term.buffer.lines.get(0)!.loadCell(79, cell).getChars()).eql(''); // empty cell after fullwidth
});
});
@@ -1269,9 +1269,9 @@ describe('Terminal', () => {
terminal.writeSync(input);
const s = terminal.buffer.iterator(true).next().content;
assert.equal(input, s);
- const stringIndex = s.match(/😃/).index;
+ const stringIndex = s.match(/😃/)!.index!;
const bufferIndex = terminal.buffer.stringIndexToBufferIndex(0, stringIndex);
- assert(terminal.buffer.lines.get(bufferIndex[0]).loadCell(bufferIndex[1], new CellData()).getChars(), '😃');
+ assert(terminal.buffer.lines.get(bufferIndex[0])!.loadCell(bufferIndex[1], new CellData()).getChars(), '😃');
});
it('multiline fullwidth chars with offset 1 (currently tests for broken behavior)', () => {
@@ -1298,7 +1298,7 @@ describe('Terminal', () => {
assert.equal(input, s);
for (let i = 0; i < input.length; ++i) {
const bufferIndex = terminal.buffer.stringIndexToBufferIndex(0, i, true);
- assert.equal(input[i], terminal.buffer.lines.get(bufferIndex[0]).loadCell(bufferIndex[1], new CellData()).getChars());
+ assert.equal(input[i], terminal.buffer.lines.get(bufferIndex[0])!.loadCell(bufferIndex[1], new CellData()).getChars());
}
});
@@ -1316,7 +1316,7 @@ describe('Terminal', () => {
: (i % 3 === 1)
? input.substr(i, 2)
: input.substr(i - 1, 2),
- terminal.buffer.lines.get(bufferIndex[0]).loadCell(bufferIndex[1], new CellData()).getChars());
+ terminal.buffer.lines.get(bufferIndex[0])!.loadCell(bufferIndex[1], new CellData()).getChars());
}
});
@@ -1370,15 +1370,15 @@ describe('Terminal', () => {
const normalTerminal = new TestTerminal({rows: 5, cols: 10, windowsMode: false});
normalTerminal.writeSync(data.join(''));
- assert.equal(normalTerminal.buffer.lines.get(0).isWrapped, false);
- assert.equal(normalTerminal.buffer.lines.get(1).isWrapped, false);
- assert.equal(normalTerminal.buffer.lines.get(2).isWrapped, false);
+ assert.equal(normalTerminal.buffer.lines.get(0)!.isWrapped, false);
+ assert.equal(normalTerminal.buffer.lines.get(1)!.isWrapped, false);
+ assert.equal(normalTerminal.buffer.lines.get(2)!.isWrapped, false);
const windowsModeTerminal = new TestTerminal({rows: 5, cols: 10, windowsMode: true});
windowsModeTerminal.writeSync(data.join(''));
- assert.equal(windowsModeTerminal.buffer.lines.get(0).isWrapped, false);
- assert.equal(windowsModeTerminal.buffer.lines.get(1).isWrapped, true, 'This line should wrap in Windows mode as the previous line ends in a non-null character');
- assert.equal(windowsModeTerminal.buffer.lines.get(2).isWrapped, false);
+ assert.equal(windowsModeTerminal.buffer.lines.get(0)!.isWrapped, false);
+ assert.equal(windowsModeTerminal.buffer.lines.get(1)!.isWrapped, true, 'This line should wrap in Windows mode as the previous line ends in a non-null character');
+ assert.equal(windowsModeTerminal.buffer.lines.get(2)!.isWrapped, false);
});
it('should mark lines as wrapped when the line ends in a non-null character after a CUP', () => {
@@ -1390,39 +1390,39 @@ describe('Terminal', () => {
const normalTerminal = new TestTerminal({rows: 5, cols: 10, windowsMode: false});
normalTerminal.writeSync(data.join(''));
- assert.equal(normalTerminal.buffer.lines.get(0).isWrapped, false);
- assert.equal(normalTerminal.buffer.lines.get(1).isWrapped, false);
- assert.equal(normalTerminal.buffer.lines.get(2).isWrapped, false);
+ assert.equal(normalTerminal.buffer.lines.get(0)!.isWrapped, false);
+ assert.equal(normalTerminal.buffer.lines.get(1)!.isWrapped, false);
+ assert.equal(normalTerminal.buffer.lines.get(2)!.isWrapped, false);
const windowsModeTerminal = new TestTerminal({rows: 5, cols: 10, windowsMode: true});
windowsModeTerminal.writeSync(data.join(''));
- assert.equal(windowsModeTerminal.buffer.lines.get(0).isWrapped, false);
- assert.equal(windowsModeTerminal.buffer.lines.get(1).isWrapped, true, 'This line should wrap in Windows mode as the previous line ends in a non-null character');
- assert.equal(windowsModeTerminal.buffer.lines.get(2).isWrapped, false);
+ assert.equal(windowsModeTerminal.buffer.lines.get(0)!.isWrapped, false);
+ assert.equal(windowsModeTerminal.buffer.lines.get(1)!.isWrapped, true, 'This line should wrap in Windows mode as the previous line ends in a non-null character');
+ assert.equal(windowsModeTerminal.buffer.lines.get(2)!.isWrapped, false);
});
});
it('convertEol setting', function(): void {
// not converting
const termNotConverting = new TestTerminal({cols: 15, rows: 10});
termNotConverting.writeSync('Hello\nWorld');
- expect(termNotConverting.buffer.lines.get(0).translateToString(false)).equals('Hello ');
- expect(termNotConverting.buffer.lines.get(1).translateToString(false)).equals(' World ');
- expect(termNotConverting.buffer.lines.get(0).translateToString(true)).equals('Hello');
- expect(termNotConverting.buffer.lines.get(1).translateToString(true)).equals(' World');
+ expect(termNotConverting.buffer.lines.get(0)!.translateToString(false)).equals('Hello ');
+ expect(termNotConverting.buffer.lines.get(1)!.translateToString(false)).equals(' World ');
+ expect(termNotConverting.buffer.lines.get(0)!.translateToString(true)).equals('Hello');
+ expect(termNotConverting.buffer.lines.get(1)!.translateToString(true)).equals(' World');
// converting
const termConverting = new TestTerminal({cols: 15, rows: 10, convertEol: true});
termConverting.writeSync('Hello\nWorld');
- expect(termConverting.buffer.lines.get(0).translateToString(false)).equals('Hello ');
- expect(termConverting.buffer.lines.get(1).translateToString(false)).equals('World ');
- expect(termConverting.buffer.lines.get(0).translateToString(true)).equals('Hello');
- expect(termConverting.buffer.lines.get(1).translateToString(true)).equals('World');
+ expect(termConverting.buffer.lines.get(0)!.translateToString(false)).equals('Hello ');
+ expect(termConverting.buffer.lines.get(1)!.translateToString(false)).equals('World ');
+ expect(termConverting.buffer.lines.get(0)!.translateToString(true)).equals('Hello');
+ expect(termConverting.buffer.lines.get(1)!.translateToString(true)).equals('World');
});
describe('Terminal InputHandler integration', () => {
function getLines(term: TestTerminal, limit: number = term.rows): string[] {
const res: string[] = [];
for (let i = 0; i < limit; ++i) {
- res.push(term.buffer.lines.get(i).translateToString(true));
+ res.push(term.buffer.lines.get(i)!.translateToString(true));
}
return res;
}
diff --git a/src/Terminal.ts b/src/browser/Terminal.ts
similarity index 71%
rename from src/Terminal.ts
rename to src/browser/Terminal.ts
index 61c997bd0..7f3ead61c 100644
--- a/src/Terminal.ts
+++ b/src/browser/Terminal.ts
@@ -21,13 +21,13 @@
* http://linux.die.net/man/7/urxvt
*/
-import { ICompositionHelper, ITerminal, IBrowser, CustomKeyEventHandler } from './Types';
+import { ICompositionHelper, ITerminal, IBrowser, CustomKeyEventHandler, ILinkifier, IMouseZoneManager, LinkMatcherHandler, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types';
import { IRenderer, CharacterJoinerHandler } from 'browser/renderer/Types';
import { CompositionHelper } from 'browser/input/CompositionHelper';
import { Viewport } from 'browser/Viewport';
import { rightClickHandler, moveTextAreaUnderMouseCursor, handlePasteEvent, copyHandler, paste } from 'browser/Clipboard';
import { C0 } from 'common/data/EscapeSequences';
-import { InputHandler, WindowsOptionsReportType } from './common/InputHandler';
+import { WindowsOptionsReportType } from '../common/InputHandler';
import { Renderer } from 'browser/renderer/Renderer';
import { Linkifier } from 'browser/Linkifier';
import { SelectionService } from 'browser/services/SelectionService';
@@ -39,7 +39,7 @@ import { MouseZoneManager } from 'browser/MouseZoneManager';
import { AccessibilityManager } from './AccessibilityManager';
import { ITheme, IMarker, IDisposable, ISelectionPosition, ILinkProvider } from 'xterm';
import { DomRenderer } from 'browser/renderer/dom/DomRenderer';
-import { IKeyboardEvent, KeyboardResultType, IBufferLine, IAttributeData, CoreMouseEventType, CoreMouseButton, CoreMouseAction, ITerminalOptions } from 'common/Types';
+import { IKeyboardEvent, KeyboardResultType, CoreMouseEventType, CoreMouseButton, CoreMouseAction, ITerminalOptions } from 'common/Types';
import { evaluateKeyboardEvent } from 'common/input/Keyboard';
import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter';
import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
@@ -49,49 +49,40 @@ import { ICharSizeService, IRenderService, IMouseService, ISelectionService, ISo
import { CharSizeService } from 'browser/services/CharSizeService';
import { IBuffer } from 'common/buffer/Types';
import { MouseService } from 'browser/services/MouseService';
-import { IParams, IFunctionIdentifier } from 'common/parser/Types';
-import { ILinkifier, IMouseZoneManager, LinkMatcherHandler, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types';
-import { WriteBuffer } from 'common/input/WriteBuffer';
import { Linkifier2 } from 'browser/Linkifier2';
import { CoreBrowserService } from 'browser/services/CoreBrowserService';
import { CoreTerminal } from 'common/CoreTerminal';
+import { ITerminalOptions as IInitializedTerminalOptions } from 'common/services/Services';
// Let it work inside Node.js for automated testing purposes.
-const document = (typeof window !== 'undefined') ? window.document : null;
-
+const document: Document = (typeof window !== 'undefined') ? window.document : null as any;
export class Terminal extends CoreTerminal implements ITerminal {
- public textarea: HTMLTextAreaElement;
- public element: HTMLElement;
- public screenElement: HTMLElement;
+ public textarea: HTMLTextAreaElement | undefined;
+ public element: HTMLElement | undefined;
+ public screenElement: HTMLElement | undefined;
- private _document: Document;
- private _viewportScrollArea: HTMLElement;
- private _viewportElement: HTMLElement;
- private _helperContainer: HTMLElement;
- private _compositionView: HTMLElement;
+ private _document: Document | undefined;
+ private _viewportScrollArea: HTMLElement | undefined;
+ private _viewportElement: HTMLElement | undefined;
+ private _helperContainer: HTMLElement | undefined;
+ private _compositionView: HTMLElement | undefined;
- private _visualBellTimer: number;
+ // private _visualBellTimer: number;
public browser: IBrowser = Browser;
// TODO: We should remove options once components adopt optionsService
- public get options(): ITerminalOptions { return this.optionsService.options; }
+ public get options(): IInitializedTerminalOptions { return this.optionsService.options; }
- private _customKeyEventHandler: CustomKeyEventHandler;
+ private _customKeyEventHandler: CustomKeyEventHandler | undefined;
// browser services
- private _charSizeService: ICharSizeService;
- private _mouseService: IMouseService;
- private _renderService: IRenderService;
- private _selectionService: ISelectionService;
- private _soundService: ISoundService;
-
- // write buffer
- private _writeBuffer: WriteBuffer;
-
- // Store if user went browsing history in scrollback
- private _userScrolling: boolean;
+ private _charSizeService: ICharSizeService | undefined;
+ private _mouseService: IMouseService | undefined;
+ private _renderService: IRenderService | undefined;
+ private _selectionService: ISelectionService | undefined;
+ private _soundService: ISoundService | undefined;
/**
* Records whether the keydown event has already been handled and triggered a data event, if so
@@ -100,18 +91,14 @@ export class Terminal extends CoreTerminal implements ITerminal {
*/
private _keyDownHandled: boolean = false;
- private _inputHandler: InputHandler;
public linkifier: ILinkifier;
public linkifier2: ILinkifier2;
- public viewport: IViewport;
- private _compositionHelper: ICompositionHelper;
- private _mouseZoneManager: IMouseZoneManager;
- private _accessibilityManager: AccessibilityManager;
- private _colorManager: ColorManager;
- private _theme: ITheme;
-
- // bufferline to clone/copy from for new blank lines
- private _blankLine: IBufferLine = null;
+ public viewport: IViewport | undefined;
+ private _compositionHelper: ICompositionHelper | undefined;
+ private _mouseZoneManager: IMouseZoneManager | undefined;
+ private _accessibilityManager: AccessibilityManager | undefined;
+ private _colorManager: ColorManager | undefined;
+ private _theme: ITheme | undefined;
private _onCursorMove = new EventEmitter();
public get onCursorMove(): IEvent { return this._onCursorMove.event; }
@@ -119,8 +106,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
public get onKey(): IEvent<{ key: string, domEvent: KeyboardEvent }> { return this._onKey.event; }
private _onRender = new EventEmitter<{ start: number, end: number }>();
public get onRender(): IEvent<{ start: number, end: number }> { return this._onRender.event; }
- private _onScroll = new EventEmitter();
- public get onScroll(): IEvent { return this._onScroll.event; }
private _onSelectionChange = new EventEmitter();
public get onSelectionChange(): IEvent { return this._onSelectionChange.event; }
private _onTitleChange = new EventEmitter();
@@ -154,10 +139,22 @@ export class Terminal extends CoreTerminal implements ITerminal {
this._setup();
+ this.linkifier = this._instantiationService.createInstance(Linkifier);
+ this.linkifier2 = this._instantiationService.createInstance(Linkifier2);
+
+ // Setup InputHandler listeners
+ this.register(this._inputHandler.onRequestBell(() => this.bell()));
+ this.register(this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end)));
+ this.register(this._inputHandler.onRequestReset(() => this.reset()));
+ this.register(this._inputHandler.onRequestScroll((eraseAttr, isWrapped) => this.scroll(eraseAttr, isWrapped || undefined)));
+ this.register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type)));
+ this.register(forwardEvent(this._inputHandler.onCursorMove, this._onCursorMove));
+ this.register(forwardEvent(this._inputHandler.onTitleChange, this._onTitleChange));
+ this.register(forwardEvent(this._inputHandler.onA11yChar, this._onA11yCharEmitter));
+ this.register(forwardEvent(this._inputHandler.onA11yTab, this._onA11yTabEmitter));
+
// Setup listeners
this._bufferService.onResize(e => this._afterResize(e.cols, e.rows));
-
- this._writeBuffer = new WriteBuffer(data => this._inputHandler.parse(data));
}
public dispose(): void {
@@ -166,41 +163,15 @@ export class Terminal extends CoreTerminal implements ITerminal {
}
super.dispose();
this._renderService?.dispose();
- this._customKeyEventHandler = null;
+ this._customKeyEventHandler = undefined;
this.write = () => { };
this.element?.parentNode?.removeChild(this.element);
}
protected _setup(): void {
- if (this._inputHandler) {
- this._inputHandler.reset();
- } else {
- // Register input handler and refire/handle events
- this._inputHandler = new InputHandler(this._bufferService, this._charsetService, this._coreService, this._dirtyRowService, this._logService, this.optionsService, this._coreMouseService, this.unicodeService);
- this.register(this._inputHandler.onRequestBell(() => this.bell()));
- this.register(this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end)));
- this.register(this._inputHandler.onRequestReset(() => this.reset()));
- this.register(this._inputHandler.onRequestScroll((eraseAttr, isWrapped) => this.scroll(eraseAttr, isWrapped || undefined)));
- this.register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type)));
- this.register(forwardEvent(this._inputHandler.onCursorMove, this._onCursorMove));
- this.register(forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed));
- this.register(forwardEvent(this._inputHandler.onTitleChange, this._onTitleChange));
- this.register(forwardEvent(this._inputHandler.onA11yChar, this._onA11yCharEmitter));
- this.register(forwardEvent(this._inputHandler.onA11yTab, this._onA11yTabEmitter));
- this.register(this._inputHandler);
- }
-
super._setup();
- this._customKeyEventHandler = null;
-
- this._userScrolling = false;
- if (!this.linkifier) {
- this.linkifier = this._instantiationService.createInstance(Linkifier);
- }
- if (!this.linkifier2) {
- this.linkifier2 = this._instantiationService.createInstance(Linkifier2);
- }
+ this._customKeyEventHandler = undefined;
}
/**
@@ -264,7 +235,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
}
} else {
this._accessibilityManager?.dispose();
- this._accessibilityManager = null;
+ this._accessibilityManager = undefined;
}
break;
case 'tabStopWidth': this.buffers.setupTabStops(); break;
@@ -282,7 +253,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
this._coreService.triggerDataEvent(C0.ESC + '[I');
}
this.updateCursorStyle(ev);
- this.element.classList.add('focus');
+ this.element!.classList.add('focus');
this._showCursor();
this._onFocus.fire();
}
@@ -292,7 +263,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
* textarea.
*/
public blur(): void {
- return this.textarea.blur();
+ return this.textarea?.blur();
}
/**
@@ -301,12 +272,12 @@ export class Terminal extends CoreTerminal implements ITerminal {
private _onTextAreaBlur(): void {
// Text can safely be removed on blur. Doing it earlier could interfere with
// screen readers reading it out.
- this.textarea.value = '';
+ this.textarea!.value = '';
this.refresh(this.buffer.y, this.buffer.y);
if (this._coreService.decPrivateModes.sendFocus) {
this._coreService.triggerDataEvent(C0.ESC + '[O');
}
- this.element.classList.remove('focus');
+ this.element!.classList.remove('focus');
this._onBlur.fire();
}
@@ -317,29 +288,29 @@ export class Terminal extends CoreTerminal implements ITerminal {
this._bindKeys();
// Bind clipboard functionality
- this.register(addDisposableDomListener(this.element, 'copy', (event: ClipboardEvent) => {
+ this.register(addDisposableDomListener(this.element!, 'copy', (event: ClipboardEvent) => {
// If mouse events are active it means the selection manager is disabled and
// copy should be handled by the host program.
if (!this.hasSelection()) {
return;
}
- copyHandler(event, this._selectionService);
+ copyHandler(event, this._selectionService!);
}));
- const pasteHandlerWrapper = (event: ClipboardEvent): void => handlePasteEvent(event, this.textarea, this._coreService);
- this.register(addDisposableDomListener(this.textarea, 'paste', pasteHandlerWrapper));
- this.register(addDisposableDomListener(this.element, 'paste', pasteHandlerWrapper));
+ const pasteHandlerWrapper = (event: ClipboardEvent): void => handlePasteEvent(event, this.textarea!, this._coreService);
+ this.register(addDisposableDomListener(this.textarea!, 'paste', pasteHandlerWrapper));
+ this.register(addDisposableDomListener(this.element!, 'paste', pasteHandlerWrapper));
// Handle right click context menus
if (Browser.isFirefox) {
// Firefox doesn't appear to fire the contextmenu event on right click
- this.register(addDisposableDomListener(this.element, 'mousedown', (event: MouseEvent) => {
+ this.register(addDisposableDomListener(this.element!, 'mousedown', (event: MouseEvent) => {
if (event.button === 2) {
- rightClickHandler(event, this.textarea, this.screenElement, this._selectionService, this.options.rightClickSelectsWord);
+ rightClickHandler(event, this.textarea!, this.screenElement!, this._selectionService!, this.options.rightClickSelectsWord);
}
}));
} else {
- this.register(addDisposableDomListener(this.element, 'contextmenu', (event: MouseEvent) => {
- rightClickHandler(event, this.textarea, this.screenElement, this._selectionService, this.options.rightClickSelectsWord);
+ this.register(addDisposableDomListener(this.element!, 'contextmenu', (event: MouseEvent) => {
+ rightClickHandler(event, this.textarea!, this.screenElement!, this._selectionService!, this.options.rightClickSelectsWord);
}));
}
@@ -349,9 +320,9 @@ export class Terminal extends CoreTerminal implements ITerminal {
if (Browser.isLinux) {
// Use auxclick event over mousedown the latter doesn't seem to work. Note
// that the regular click event doesn't fire for the middle mouse button.
- this.register(addDisposableDomListener(this.element, 'auxclick', (event: MouseEvent) => {
+ this.register(addDisposableDomListener(this.element!, 'auxclick', (event: MouseEvent) => {
if (event.button === 1) {
- moveTextAreaUnderMouseCursor(event, this.textarea, this.screenElement);
+ moveTextAreaUnderMouseCursor(event, this.textarea!, this.screenElement!);
}
}));
}
@@ -361,13 +332,13 @@ export class Terminal extends CoreTerminal implements ITerminal {
* Apply key handling to the terminal
*/
private _bindKeys(): void {
- this.register(addDisposableDomListener(this.textarea, 'keyup', (ev: KeyboardEvent) => this._keyUp(ev), true));
- this.register(addDisposableDomListener(this.textarea, 'keydown', (ev: KeyboardEvent) => this._keyDown(ev), true));
- this.register(addDisposableDomListener(this.textarea, 'keypress', (ev: KeyboardEvent) => this._keyPress(ev), true));
- this.register(addDisposableDomListener(this.textarea, 'compositionstart', () => this._compositionHelper.compositionstart()));
- this.register(addDisposableDomListener(this.textarea, 'compositionupdate', (e: CompositionEvent) => this._compositionHelper.compositionupdate(e)));
- this.register(addDisposableDomListener(this.textarea, 'compositionend', () => this._compositionHelper.compositionend()));
- this.register(this.onRender(() => this._compositionHelper.updateCompositionElements()));
+ this.register(addDisposableDomListener(this.textarea!, 'keyup', (ev: KeyboardEvent) => this._keyUp(ev), true));
+ this.register(addDisposableDomListener(this.textarea!, 'keydown', (ev: KeyboardEvent) => this._keyDown(ev), true));
+ this.register(addDisposableDomListener(this.textarea!, 'keypress', (ev: KeyboardEvent) => this._keyPress(ev), true));
+ this.register(addDisposableDomListener(this.textarea!, 'compositionstart', () => this._compositionHelper!.compositionstart()));
+ this.register(addDisposableDomListener(this.textarea!, 'compositionupdate', (e: CompositionEvent) => this._compositionHelper!.compositionupdate(e)));
+ this.register(addDisposableDomListener(this.textarea!, 'compositionend', () => this._compositionHelper!.compositionend()));
+ this.register(this.onRender(() => this._compositionHelper!.updateCompositionElements()));
this.register(this.onRender(e => this._queueLinkification(e.start, e.end)));
}
@@ -385,7 +356,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
this._logService.debug('Terminal.open was called on an element that was not attached to the DOM');
}
- this._document = parent.ownerDocument;
+ this._document = parent.ownerDocument!;
// Create main element container
this.element = this._document.createElement('div');
@@ -441,16 +412,15 @@ export class Terminal extends CoreTerminal implements ITerminal {
this.element.appendChild(fragment);
this._theme = this.options.theme || this._theme;
- this.options.theme = undefined;
this._colorManager = new ColorManager(document, this.options.allowTransparency);
- this.optionsService.onOptionChange(e => this._colorManager.onOptionsChange(e));
+ this.optionsService.onOptionChange(e => this._colorManager!.onOptionsChange(e));
this._colorManager.setTheme(this._theme);
const renderer = this._createRenderer();
this._renderService = this._instantiationService.createInstance(RenderService, renderer, this.rows, this.screenElement);
this._instantiationService.setService(IRenderService, this._renderService);
this._renderService.onRenderedBufferChange(e => this._onRender.fire(e));
- this.onResize(e => this._renderService.resize(e.cols, e.rows));
+ this.onResize(e => this._renderService!.resize(e.cols, e.rows));
this._soundService = this._instantiationService.createInstance(SoundService);
this._instantiationService.setService(ISoundService, this._soundService);
@@ -463,14 +433,14 @@ export class Terminal extends CoreTerminal implements ITerminal {
this._viewportScrollArea
);
this.viewport.onThemeChange(this._colorManager.colors);
- this.register(this._inputHandler.onRequestSyncScrollBar(() => this.viewport.syncScrollArea()));
+ this.register(this._inputHandler.onRequestSyncScrollBar(() => this.viewport!.syncScrollArea()));
this.register(this.viewport);
- this.register(this.onCursorMove(() => this._renderService.onCursorMove()));
- this.register(this.onResize(() => this._renderService.onResize(this.cols, this.rows)));
- this.register(this.onBlur(() => this._renderService.onBlur()));
- this.register(this.onFocus(() => this._renderService.onFocus()));
- this.register(this._renderService.onDimensionsChange(() => this.viewport.syncScrollArea()));
+ this.register(this.onCursorMove(() => this._renderService!.onCursorMove()));
+ this.register(this.onResize(() => this._renderService!.onResize(this.cols, this.rows)));
+ this.register(this.onBlur(() => this._renderService!.onBlur()));
+ this.register(this.onFocus(() => this._renderService!.onFocus()));
+ this.register(this._renderService.onDimensionsChange(() => this.viewport!.syncScrollArea()));
this._selectionService = this._instantiationService.createInstance(SelectionService,
(amount: number, suppressEvent: boolean) => this.scrollLines(amount, suppressEvent),
@@ -478,29 +448,29 @@ export class Terminal extends CoreTerminal implements ITerminal {
this.screenElement);
this._instantiationService.setService(ISelectionService, this._selectionService);
this.register(this._selectionService.onSelectionChange(() => this._onSelectionChange.fire()));
- this.register(this._selectionService.onRedrawRequest(e => this._renderService.onSelectionChanged(e.start, e.end, e.columnSelectMode)));
+ this.register(this._selectionService.onRedrawRequest(e => this._renderService!.onSelectionChanged(e.start, e.end, e.columnSelectMode)));
this.register(this._selectionService.onLinuxMouseSelection(text => {
// If there's a new selection, put it into the textarea, focus and select it
// in order to register it as a selection on the OS. This event is fired
// only on Linux to enable middle click to paste selection.
- this.textarea.value = text;
- this.textarea.focus();
- this.textarea.select();
+ this.textarea!.value = text;
+ this.textarea!.focus();
+ this.textarea!.select();
}));
this.register(this.onScroll(() => {
- this.viewport.syncScrollArea();
- this._selectionService.refresh();
+ this.viewport!.syncScrollArea();
+ this._selectionService!.refresh();
}));
- this.register(addDisposableDomListener(this._viewportElement, 'scroll', () => this._selectionService.refresh()));
+ this.register(addDisposableDomListener(this._viewportElement, 'scroll', () => this._selectionService!.refresh()));
this._mouseZoneManager = this._instantiationService.createInstance(MouseZoneManager, this.element, this.screenElement);
this.register(this._mouseZoneManager);
- this.register(this.onScroll(() => this._mouseZoneManager.clearAll()));
+ this.register(this.onScroll(() => this._mouseZoneManager!.clearAll()));
this.linkifier.attachToDom(this.element, this._mouseZoneManager);
this.linkifier2.attachToDom(this.element, this._mouseService, this._renderService);
// This event listener must be registered aftre MouseZoneManager is created
- this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService.onMouseDown(e)));
+ this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.onMouseDown(e)));
// apply mouse event classes set by escape codes before terminal was attached
if (this._coreMouseService.areMouseEventsActive) {
@@ -532,8 +502,8 @@ export class Terminal extends CoreTerminal implements ITerminal {
private _createRenderer(): IRenderer {
switch (this.options.rendererType) {
- case 'canvas': return this._instantiationService.createInstance(Renderer, this._colorManager.colors, this.screenElement, this.linkifier, this.linkifier2);
- case 'dom': return this._instantiationService.createInstance(DomRenderer, this._colorManager.colors, this.element, this.screenElement, this._viewportElement, this.linkifier, this.linkifier2);
+ case 'canvas': return this._instantiationService.createInstance(Renderer, this._colorManager!.colors, this.screenElement!, this.linkifier, this.linkifier2);
+ case 'dom': return this._instantiationService.createInstance(DomRenderer, this._colorManager!.colors, this.element!, this.screenElement!, this._viewportElement!, this.linkifier, this.linkifier2);
default: throw new Error(`Unrecognized rendererType "${this.options.rendererType}"`);
}
}
@@ -545,8 +515,8 @@ export class Terminal extends CoreTerminal implements ITerminal {
private _setTheme(theme: ITheme): void {
this._theme = theme;
this._colorManager?.setTheme(theme);
- this._renderService?.setColors(this._colorManager.colors);
- this.viewport?.onThemeChange(this._colorManager.colors);
+ this._renderService?.setColors(this._colorManager!.colors);
+ this.viewport?.onThemeChange(this._colorManager!.colors);
}
/**
@@ -566,18 +536,18 @@ export class Terminal extends CoreTerminal implements ITerminal {
*/
public bindMouse(): void {
const self = this;
- const el = this.element;
+ const el = this.element!;
// send event to CoreMouseService
function sendEvent(ev: MouseEvent | WheelEvent): boolean {
// get mouse coordinates
- const pos = self._mouseService.getRawByteCoords(ev, self.screenElement, self.cols, self.rows);
+ const pos = self._mouseService!.getRawByteCoords(ev, self.screenElement!, self.cols, self.rows);
if (!pos) {
return false;
}
let but: CoreMouseButton;
- let action: CoreMouseAction;
+ let action: CoreMouseAction | undefined;
switch ((ev).overrideType || ev.type) {
case 'mousemove':
action = CoreMouseAction.MOVE;
@@ -646,14 +616,14 @@ export class Terminal extends CoreTerminal implements ITerminal {
mousedrag: null,
mousemove: null
};
- const eventListeners: { [key: string]: (ev: Event) => void } = {
+ const eventListeners: { [key: string]: (ev: any) => void | boolean } = {
mouseup: (ev: MouseEvent) => {
sendEvent(ev);
if (!ev.buttons) {
// if no other button is held remove global handlers
- this._document.removeEventListener('mouseup', requestedEvents.mouseup);
+ this._document!.removeEventListener('mouseup', requestedEvents.mouseup!);
if (requestedEvents.mousedrag) {
- this._document.removeEventListener('mousemove', requestedEvents.mousedrag);
+ this._document!.removeEventListener('mousemove', requestedEvents.mousedrag);
}
}
return this.cancel(ev);
@@ -682,18 +652,18 @@ export class Terminal extends CoreTerminal implements ITerminal {
if (this.optionsService.options.logLevel === 'debug') {
this._logService.debug('Binding to mouse events:', this._coreMouseService.explainEvents(events));
}
- this.element.classList.add('enable-mouse-events');
- this._selectionService.disable();
+ this.element!.classList.add('enable-mouse-events');
+ this._selectionService!.disable();
} else {
this._logService.debug('Unbinding from mouse events.');
- this.element.classList.remove('enable-mouse-events');
- this._selectionService.enable();
+ this.element!.classList.remove('enable-mouse-events');
+ this._selectionService!.enable();
}
// add/remove handlers from requestedEvents
if (!(events & CoreMouseEventType.MOVE)) {
- el.removeEventListener('mousemove', requestedEvents.mousemove);
+ el.removeEventListener('mousemove', requestedEvents.mousemove!);
requestedEvents.mousemove = null;
} else if (!requestedEvents.mousemove) {
el.addEventListener('mousemove', eventListeners.mousemove);
@@ -701,7 +671,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
}
if (!(events & CoreMouseEventType.WHEEL)) {
- el.removeEventListener('wheel', requestedEvents.wheel);
+ el.removeEventListener('wheel', requestedEvents.wheel!);
requestedEvents.wheel = null;
} else if (!requestedEvents.wheel) {
el.addEventListener('wheel', eventListeners.wheel);
@@ -709,14 +679,14 @@ export class Terminal extends CoreTerminal implements ITerminal {
}
if (!(events & CoreMouseEventType.UP)) {
- this._document.removeEventListener('mouseup', requestedEvents.mouseup);
+ this._document!.removeEventListener('mouseup', requestedEvents.mouseup!);
requestedEvents.mouseup = null;
} else if (!requestedEvents.mouseup) {
requestedEvents.mouseup = eventListeners.mouseup;
}
if (!(events & CoreMouseEventType.DRAG)) {
- this._document.removeEventListener('mousemove', requestedEvents.mousedrag);
+ this._document!.removeEventListener('mousemove', requestedEvents.mousedrag!);
requestedEvents.mousedrag = null;
} else if (!requestedEvents.mousedrag) {
requestedEvents.mousedrag = eventListeners.mousedrag;
@@ -735,7 +705,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
// Don't send the mouse button to the pty if mouse events are disabled or
// if the selection manager is having selection forced (ie. a modifier is
// held).
- if (!this._coreMouseService.areMouseEventsActive || this._selectionService.shouldForceSelection(ev)) {
+ if (!this._coreMouseService.areMouseEventsActive || this._selectionService!.shouldForceSelection(ev)) {
return;
}
@@ -746,10 +716,10 @@ export class Terminal extends CoreTerminal implements ITerminal {
// Note: Other emulators also do this for 'mousedown' while a button
// is held, we currently limit 'mousedown' to the terminal only.
if (requestedEvents.mouseup) {
- this._document.addEventListener('mouseup', requestedEvents.mouseup);
+ this._document!.addEventListener('mouseup', requestedEvents.mouseup);
}
if (requestedEvents.mousedrag) {
- this._document.addEventListener('mousemove', requestedEvents.mousedrag);
+ this._document!.addEventListener('mousemove', requestedEvents.mousedrag);
}
return this.cancel(ev);
@@ -760,7 +730,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
// Convert wheel events into up/down events when the buffer does not have scrollback, this
// enables scrolling in apps hosted in the alt buffer such as vim or tmux.
if (!this.buffer.hasScrollback) {
- const amount = this.viewport.getLinesScrolled(ev);
+ const amount = this.viewport!.getLinesScrolled(ev);
// Do nothing if there's no vertical scroll
if (amount === 0) {
@@ -783,20 +753,20 @@ export class Terminal extends CoreTerminal implements ITerminal {
// the shell for example
this.register(addDisposableDomListener(el, 'wheel', (ev: WheelEvent) => {
if (requestedEvents.wheel) return;
- if (!this.viewport.onWheel(ev)) {
+ if (!this.viewport!.onWheel(ev)) {
return this.cancel(ev);
}
}));
this.register(addDisposableDomListener(el, 'touchstart', (ev: TouchEvent) => {
if (this._coreMouseService.areMouseEventsActive) return;
- this.viewport.onTouchStart(ev);
+ this.viewport!.onTouchStart(ev);
return this.cancel(ev);
}));
this.register(addDisposableDomListener(el, 'touchmove', (ev: TouchEvent) => {
if (this._coreMouseService.areMouseEventsActive) return;
- if (!this.viewport.onTouchMove(ev)) {
+ if (!this.viewport!.onTouchMove(ev)) {
return this.cancel(ev);
}
}));
@@ -827,9 +797,9 @@ export class Terminal extends CoreTerminal implements ITerminal {
*/
public updateCursorStyle(ev: KeyboardEvent): void {
if (this._selectionService && this._selectionService.shouldColumnSelect(ev)) {
- this.element.classList.add('column-select');
+ this.element!.classList.add('column-select');
} else {
- this.element.classList.remove('column-select');
+ this.element!.classList.remove('column-select');
}
}
@@ -843,134 +813,13 @@ export class Terminal extends CoreTerminal implements ITerminal {
}
}
- /**
- * Scroll the terminal down 1 row, creating a blank line.
- * @param isWrapped Whether the new line is wrapped from the previous line.
- */
- public scroll(eraseAttr: IAttributeData, isWrapped: boolean = false): void {
- let newLine: IBufferLine;
- newLine = this._blankLine;
- if (!newLine || newLine.length !== this.cols || newLine.getFg(0) !== eraseAttr.fg || newLine.getBg(0) !== eraseAttr.bg) {
- newLine = this.buffer.getBlankLine(eraseAttr, isWrapped);
- this._blankLine = newLine;
- }
- newLine.isWrapped = isWrapped;
-
- const topRow = this.buffer.ybase + this.buffer.scrollTop;
- const bottomRow = this.buffer.ybase + this.buffer.scrollBottom;
-
- if (this.buffer.scrollTop === 0) {
- // Determine whether the buffer is going to be trimmed after insertion.
- const willBufferBeTrimmed = this.buffer.lines.isFull;
-
- // Insert the line using the fastest method
- if (bottomRow === this.buffer.lines.length - 1) {
- if (willBufferBeTrimmed) {
- this.buffer.lines.recycle().copyFrom(newLine);
- } else {
- this.buffer.lines.push(newLine.clone());
- }
- } else {
- this.buffer.lines.splice(bottomRow + 1, 0, newLine.clone());
- }
-
- // Only adjust ybase and ydisp when the buffer is not trimmed
- if (!willBufferBeTrimmed) {
- this.buffer.ybase++;
- // Only scroll the ydisp with ybase if the user has not scrolled up
- if (!this._userScrolling) {
- this.buffer.ydisp++;
- }
- } else {
- // When the buffer is full and the user has scrolled up, keep the text
- // stable unless ydisp is right at the top
- if (this._userScrolling) {
- this.buffer.ydisp = Math.max(this.buffer.ydisp - 1, 0);
- }
- }
- } else {
- // scrollTop is non-zero which means no line will be going to the
- // scrollback, instead we can just shift them in-place.
- const scrollRegionHeight = bottomRow - topRow + 1 /* as it's zero-based */;
- this.buffer.lines.shiftElements(topRow + 1, scrollRegionHeight - 1, -1);
- this.buffer.lines.set(bottomRow, newLine.clone());
- }
-
- // Move the viewport to the bottom of the buffer unless the user is
- // scrolling.
- if (!this._userScrolling) {
- this.buffer.ydisp = this.buffer.ybase;
- }
-
- // Flag rows that need updating
- this._dirtyRowService.markRangeDirty(this.buffer.scrollTop, this.buffer.scrollBottom);
-
- this._onScroll.fire(this.buffer.ydisp);
- }
-
- /**
- * Scroll the display of the terminal
- * @param disp The number of lines to scroll down (negative scroll up).
- * @param suppressScrollEvent Don't emit the scroll event as scrollLines. This is used
- * to avoid unwanted events being handled by the viewport when the event was triggered from the
- * viewport originally.
- */
public scrollLines(disp: number, suppressScrollEvent?: boolean): void {
- if (disp < 0) {
- if (this.buffer.ydisp === 0) {
- return;
- }
- this._userScrolling = true;
- } else if (disp + this.buffer.ydisp >= this.buffer.ybase) {
- this._userScrolling = false;
- }
-
- const oldYdisp = this.buffer.ydisp;
- this.buffer.ydisp = Math.max(Math.min(this.buffer.ydisp + disp, this.buffer.ybase), 0);
-
- // No change occurred, don't trigger scroll/refresh
- if (oldYdisp === this.buffer.ydisp) {
- return;
- }
-
- if (!suppressScrollEvent) {
- this._onScroll.fire(this.buffer.ydisp);
- }
-
+ super.scrollLines(disp, suppressScrollEvent);
this.refresh(0, this.rows - 1);
}
- /**
- * Scroll the display of the terminal by a number of pages.
- * @param pageCount The number of pages to scroll (negative scrolls up).
- */
- public scrollPages(pageCount: number): void {
- this.scrollLines(pageCount * (this.rows - 1));
- }
-
- /**
- * Scrolls the display of the terminal to the top.
- */
- public scrollToTop(): void {
- this.scrollLines(-this.buffer.ydisp);
- }
-
- /**
- * Scrolls the display of the terminal to the bottom.
- */
- public scrollToBottom(): void {
- this.scrollLines(this.buffer.ybase - this.buffer.ydisp);
- }
-
- public scrollToLine(line: number): void {
- const scrollAmount = line - this.buffer.ydisp;
- if (scrollAmount !== 0) {
- this.scrollLines(scrollAmount);
- }
- }
-
public paste(data: string): void {
- paste(data, this.textarea, this._coreService);
+ paste(data, this.textarea!, this._coreService);
}
/**
@@ -986,25 +835,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
this._customKeyEventHandler = customKeyEventHandler;
}
- /** Add handler for ESC escape sequence. See xterm.d.ts for details. */
- public addEscHandler(id: IFunctionIdentifier, callback: () => boolean): IDisposable {
- return this._inputHandler.addEscHandler(id, callback);
- }
-
- /** Add handler for DCS escape sequence. See xterm.d.ts for details. */
- public addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable {
- return this._inputHandler.addDcsHandler(id, callback);
- }
-
- /** Add handler for CSI escape sequence. See xterm.d.ts for details. */
- public addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable {
- return this._inputHandler.addCsiHandler(id, callback);
- }
- /** Add handler for OSC escape sequence. See xterm.d.ts for details. */
- public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable {
- return this._inputHandler.addOscHandler(ident, callback);
- }
-
/**
* Registers a link matcher, allowing custom link patterns to be matched and
* handled.
@@ -1036,13 +866,13 @@ export class Terminal extends CoreTerminal implements ITerminal {
}
public registerCharacterJoiner(handler: CharacterJoinerHandler): number {
- const joinerId = this._renderService.registerCharacterJoiner(handler);
+ const joinerId = this._renderService!.registerCharacterJoiner(handler);
this.refresh(0, this.rows - 1);
return joinerId;
}
public deregisterCharacterJoiner(joinerId: number): void {
- if (this._renderService.deregisterCharacterJoiner(joinerId)) {
+ if (this._renderService!.deregisterCharacterJoiner(joinerId)) {
this.refresh(0, this.rows - 1);
}
}
@@ -1051,7 +881,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
return this.buffer.markers;
}
- public addMarker(cursorYOffset: number): IMarker {
+ public addMarker(cursorYOffset: number): IMarker | undefined {
// Disallow markers on the alt buffer
if (this.buffer !== this.buffers.normal) {
return;
@@ -1074,7 +904,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
* @param length The length of the selection.
*/
public select(column: number, row: number, length: number): void {
- this._selectionService.setSelection(column, row, length);
+ this._selectionService!.setSelection(column, row, length);
}
/**
@@ -1086,15 +916,15 @@ export class Terminal extends CoreTerminal implements ITerminal {
}
public getSelectionPosition(): ISelectionPosition | undefined {
- if (!this._selectionService.hasSelection) {
+ if (!this._selectionService || !this._selectionService.hasSelection) {
return undefined;
}
return {
- startColumn: this._selectionService.selectionStart[0],
- startRow: this._selectionService.selectionStart[1],
- endColumn: this._selectionService.selectionEnd[0],
- endRow: this._selectionService.selectionEnd[1]
+ startColumn: this._selectionService.selectionStart![0],
+ startRow: this._selectionService.selectionStart![1],
+ endColumn: this._selectionService.selectionEnd![0],
+ endRow: this._selectionService.selectionEnd![1]
};
}
@@ -1122,14 +952,14 @@ export class Terminal extends CoreTerminal implements ITerminal {
* - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent
* @param ev The keydown event to be handled.
*/
- protected _keyDown(event: KeyboardEvent): boolean {
+ protected _keyDown(event: KeyboardEvent): boolean | undefined {
this._keyDownHandled = false;
if (this._customKeyEventHandler && this._customKeyEventHandler(event) === false) {
return false;
}
- if (!this._compositionHelper.keydown(event)) {
+ if (!this._compositionHelper!.keydown(event)) {
if (this.buffer.ybase !== this.buffer.ydisp) {
this.scrollToBottom();
}
@@ -1167,7 +997,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
// will announce deleted characters. This will not work 100% of the time but it should cover
// most scenarios.
if (result.key === C0.ETX || result.key === C0.CR) {
- this.textarea.value = '';
+ this.textarea!.value = '';
}
this._onKey.fire({ key: result.key, domEvent: event });
@@ -1260,16 +1090,16 @@ export class Terminal extends CoreTerminal implements ITerminal {
*/
public bell(): void {
if (this._soundBell()) {
- this._soundService.playBellSound();
+ this._soundService!.playBellSound();
}
- if (this._visualBell()) {
- this.element.classList.add('visual-bell-active');
- clearTimeout(this._visualBellTimer);
- this._visualBellTimer = window.setTimeout(() => {
- this.element.classList.remove('visual-bell-active');
- }, 200);
- }
+ // if (this._visualBell()) {
+ // this.element.classList.add('visual-bell-active');
+ // clearTimeout(this._visualBellTimer);
+ // this._visualBellTimer = window.setTimeout(() => {
+ // this.element.classList.remove('visual-bell-active');
+ // }, 200);
+ // }
}
/**
@@ -1306,7 +1136,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
// Don't clear if it's already clear
return;
}
- this.buffer.lines.set(0, this.buffer.lines.get(this.buffer.ybase + this.buffer.y));
+ this.buffer.lines.set(0, this.buffer.lines.get(this.buffer.ybase + this.buffer.y)!);
this.buffer.lines.length = 1;
this.buffer.ydisp = 0;
this.buffer.ybase = 0;
@@ -1334,18 +1164,13 @@ export class Terminal extends CoreTerminal implements ITerminal {
this.options.rows = this.rows;
this.options.cols = this.cols;
const customKeyEventHandler = this._customKeyEventHandler;
- const userScrolling = this._userScrolling;
this._setup();
- this._bufferService.reset();
- this._charsetService.reset();
- this._coreService.reset();
- this._coreMouseService.reset();
+ super.reset();
this._selectionService?.reset();
// reattach
this._customKeyEventHandler = customKeyEventHandler;
- this._userScrolling = userScrolling;
// do a full screen refresh
this.refresh(0, this.rows - 1);
@@ -1372,7 +1197,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
}
// TODO: Remove cancel function and cancelEvents option
- public cancel(ev: Event, force?: boolean): boolean {
+ public cancel(ev: Event, force?: boolean): boolean | undefined {
if (!this.options.cancelEvents && !force) {
return;
}
@@ -1392,14 +1217,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
// return this.options.bellStyle === 'sound' ||
// this.options.bellStyle === 'both';
}
-
- public write(data: string | Uint8Array, callback?: () => void): void {
- this._writeBuffer.write(data, callback);
- }
-
- public writeSync(data: string | Uint8Array): void {
- this._writeBuffer.writeSync(data);
- }
}
/**
diff --git a/src/Terminal2.test.ts b/src/browser/Terminal2.test.ts
similarity index 96%
rename from src/Terminal2.test.ts
rename to src/browser/Terminal2.test.ts
index f7046240b..32a47b214 100644
--- a/src/Terminal2.test.ts
+++ b/src/browser/Terminal2.test.ts
@@ -8,14 +8,14 @@ import * as path from 'path';
import * as os from 'os';
import * as fs from 'fs';
import * as pty from 'node-pty';
-import { Terminal } from './Terminal';
+import { Terminal } from 'browser/Terminal';
import { IDisposable } from 'xterm';
// all test files expect terminal in 80x25
const COLS = 80;
const ROWS = 25;
-const TESTFILES = glob.sync('**/escape_sequence_files/*.in', { cwd: path.join(__dirname, '..')});
+const TESTFILES = glob.sync('**/escape_sequence_files/*.in', { cwd: path.join(__dirname, '../..')});
const SKIP_FILES = [
't0084-CBT.in',
't0101-NLM.in',
@@ -124,7 +124,7 @@ function terminalToString(term: Terminal): string {
let result = '';
let lineText = '';
for (let line = term.buffer.ybase; line < term.buffer.ybase + term.rows; line++) {
- lineText = term.buffer.lines.get(line).translateToString(true);
+ lineText = term.buffer.lines.get(line)!.translateToString(true);
// rtrim empty cells as xterm does
lineText = lineText.replace(/\s+$/, '');
result += lineText;
diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts
index 1869ab874..2d6f6cbba 100644
--- a/src/browser/TestUtils.test.ts
+++ b/src/browser/TestUtils.test.ts
@@ -3,10 +3,328 @@
* @license MIT
*/
+import { IDisposable, IMarker, ISelectionPosition, ILinkProvider } from 'xterm';
import { IEvent, EventEmitter } from 'common/EventEmitter';
-import { ICharSizeService, IMouseService, IRenderService } from 'browser/services/Services';
-import { IRenderDimensions, IRenderer, CharacterJoinerHandler } from 'browser/renderer/Types';
-import { IColorSet } from 'browser/Types';
+import { ICharSizeService, IMouseService, IRenderService, ISelectionService } from 'browser/services/Services';
+import { IRenderDimensions, IRenderer, CharacterJoinerHandler, IRequestRedrawEvent } from 'browser/renderer/Types';
+import { IColorSet, ILinkMatcherOptions, ITerminal, ILinkifier, ILinkifier2, IBrowser, IViewport, IColorManager, ICompositionHelper } from 'browser/Types';
+import { IBuffer, IBufferStringIterator, IBufferSet } from 'common/buffer/Types';
+import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset, ITerminalOptions } from 'common/Types';
+import { Buffer } from 'common/buffer/Buffer';
+import * as Browser from 'common/Platform';
+import { Terminal } from 'browser/Terminal';
+import { IUnicodeService, IOptionsService } from 'common/services/Services';
+import { IFunctionIdentifier, IParams } from 'common/parser/Types';
+import { AttributeData } from 'common/buffer/AttributeData';
+
+export class TestTerminal extends Terminal {
+ public get curAttrData(): IAttributeData { return (this as any)._inputHandler._curAttrData; }
+ public keyDown(ev: any): boolean | undefined { return this._keyDown(ev); }
+ public keyPress(ev: any): boolean { return this._keyPress(ev); }
+}
+
+export class MockTerminal implements ITerminal {
+ public onBlur!: IEvent;
+ public onFocus!: IEvent;
+ public onA11yChar!: IEvent;
+ public onA11yTab!: IEvent;
+ public onCursorMove!: IEvent;
+ public onLineFeed!: IEvent;
+ public onSelectionChange!: IEvent;
+ public onData!: IEvent;
+ public onBinary!: IEvent;
+ public onTitleChange!: IEvent;
+ public onScroll!: IEvent;
+ public onKey!: IEvent<{ key: string, domEvent: KeyboardEvent }>;
+ public onRender!: IEvent<{ start: number, end: number }>;
+ public onResize!: IEvent<{ cols: number, rows: number }>;
+ public markers!: IMarker[];
+ public optionsService!: IOptionsService;
+ public unicodeService!: IUnicodeService;
+ public addMarker(cursorYOffset: number): IMarker {
+ throw new Error('Method not implemented.');
+ }
+ public selectLines(start: number, end: number): void {
+ throw new Error('Method not implemented.');
+ }
+ public scrollToLine(line: number): void {
+ throw new Error('Method not implemented.');
+ }
+ public static string: any;
+ public setOption(key: any, value: any): void {
+ throw new Error('Method not implemented.');
+ }
+ public blur(): void {
+ throw new Error('Method not implemented.');
+ }
+ public focus(): void {
+ throw new Error('Method not implemented.');
+ }
+ public resize(columns: number, rows: number): void {
+ throw new Error('Method not implemented.');
+ }
+ public writeln(data: string): void {
+ throw new Error('Method not implemented.');
+ }
+ public paste(data: string): void {
+ throw new Error('Method not implemented.');
+ }
+ public open(parent: HTMLElement): void {
+ throw new Error('Method not implemented.');
+ }
+ public attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void {
+ throw new Error('Method not implemented.');
+ }
+ public addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable {
+ throw new Error('Method not implemented.');
+ }
+ public addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable {
+ throw new Error('Method not implemented.');
+ }
+ public addEscHandler(id: IFunctionIdentifier, handler: () => boolean): IDisposable {
+ throw new Error('Method not implemented.');
+ }
+ public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable {
+ throw new Error('Method not implemented.');
+ }
+ public registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => boolean | void, options?: ILinkMatcherOptions): number {
+ throw new Error('Method not implemented.');
+ }
+ public deregisterLinkMatcher(matcherId: number): void {
+ throw new Error('Method not implemented.');
+ }
+ public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
+ throw new Error('Method not implemented.');
+ }
+ public hasSelection(): boolean {
+ throw new Error('Method not implemented.');
+ }
+ public getSelection(): string {
+ throw new Error('Method not implemented.');
+ }
+ public getSelectionPosition(): ISelectionPosition | undefined {
+ throw new Error('Method not implemented.');
+ }
+ public clearSelection(): void {
+ throw new Error('Method not implemented.');
+ }
+ public select(column: number, row: number, length: number): void {
+ throw new Error('Method not implemented.');
+ }
+ public selectAll(): void {
+ throw new Error('Method not implemented.');
+ }
+ public dispose(): void {
+ throw new Error('Method not implemented.');
+ }
+ public scrollPages(pageCount: number): void {
+ throw new Error('Method not implemented.');
+ }
+ public scrollToTop(): void {
+ throw new Error('Method not implemented.');
+ }
+ public scrollToBottom(): void {
+ throw new Error('Method not implemented.');
+ }
+ public clear(): void {
+ throw new Error('Method not implemented.');
+ }
+ public write(data: string): void {
+ throw new Error('Method not implemented.');
+ }
+ public writeUtf8(data: Uint8Array): void {
+ throw new Error('Method not implemented.');
+ }
+ public bracketedPasteMode!: boolean;
+ public renderer!: IRenderer;
+ public linkifier!: ILinkifier;
+ public linkifier2!: ILinkifier2;
+ public isFocused!: boolean;
+ public options: ITerminalOptions = {};
+ public element!: HTMLElement;
+ public screenElement!: HTMLElement;
+ public rowContainer!: HTMLElement;
+ public selectionContainer!: HTMLElement;
+ public selectionService!: ISelectionService;
+ public textarea!: HTMLTextAreaElement;
+ public rows!: number;
+ public cols!: number;
+ public browser: IBrowser = Browser;
+ public writeBuffer!: string[];
+ public children!: HTMLElement[];
+ public cursorHidden!: boolean;
+ public cursorState!: number;
+ public scrollback!: number;
+ public buffers!: IBufferSet;
+ public buffer!: IBuffer;
+ public viewport!: IViewport;
+ public applicationCursor!: boolean;
+ public handler(data: string): void {
+ throw new Error('Method not implemented.');
+ }
+ public on(event: string, callback: (...args: any[]) => void): void {
+ throw new Error('Method not implemented.');
+ }
+ public off(type: string, listener: XtermListener): void {
+ throw new Error('Method not implemented.');
+ }
+ public addDisposableListener(type: string, handler: XtermListener): IDisposable {
+ throw new Error('Method not implemented.');
+ }
+ public scrollLines(disp: number): void {
+ throw new Error('Method not implemented.');
+ }
+ public scrollToRow(absoluteRow: number): number {
+ throw new Error('Method not implemented.');
+ }
+ public cancel(ev: Event, force?: boolean): void {
+ throw new Error('Method not implemented.');
+ }
+ public log(text: string): void {
+ throw new Error('Method not implemented.');
+ }
+ public emit(event: string, data: any): void {
+ throw new Error('Method not implemented.');
+ }
+ public reset(): void {
+ throw new Error('Method not implemented.');
+ }
+ public refresh(start: number, end: number): void {
+ throw new Error('Method not implemented.');
+ }
+ public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; }
+ public deregisterCharacterJoiner(joinerId: number): void { }
+}
+
+export class MockBuffer implements IBuffer {
+ public markers!: IMarker[];
+ public addMarker(y: number): IMarker {
+ throw new Error('Method not implemented.');
+ }
+ public isCursorInViewport!: boolean;
+ public lines!: ICircularList;
+ public ydisp!: number;
+ public ybase!: number;
+ public hasScrollback!: boolean;
+ public y!: number;
+ public x!: number;
+ public tabs: any;
+ public scrollBottom!: number;
+ public scrollTop!: number;
+ public savedY!: number;
+ public savedX!: number;
+ public savedCharset: ICharset | undefined;
+ public savedCurAttrData = new AttributeData();
+ public translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol?: number, endCol?: number): string {
+ return Buffer.prototype.translateBufferLineToString.apply(this, arguments as any);
+ }
+ public getWrappedRangeForLine(y: number): { first: number, last: number } {
+ return Buffer.prototype.getWrappedRangeForLine.apply(this, arguments as any);
+ }
+ public nextStop(x?: number): number {
+ throw new Error('Method not implemented.');
+ }
+ public prevStop(x?: number): number {
+ throw new Error('Method not implemented.');
+ }
+ public setLines(lines: ICircularList): void {
+ this.lines = lines;
+ }
+ public getBlankLine(attr: IAttributeData, isWrapped?: boolean): IBufferLine {
+ return Buffer.prototype.getBlankLine.apply(this, arguments as any);
+ }
+ public stringIndexToBufferIndex(lineIndex: number, stringIndex: number): number[] {
+ return Buffer.prototype.stringIndexToBufferIndex.apply(this, arguments as any);
+ }
+ public iterator(trimRight: boolean, startIndex?: number, endIndex?: number): IBufferStringIterator {
+ return Buffer.prototype.iterator.apply(this, arguments as any);
+ }
+ public getNullCell(attr?: IAttributeData): ICellData {
+ throw new Error('Method not implemented.');
+ }
+ public getWhitespaceCell(attr?: IAttributeData): ICellData {
+ throw new Error('Method not implemented.');
+ }
+}
+
+export class MockRenderer implements IRenderer {
+ public onRequestRedraw!: IEvent;
+ public onCanvasResize!: IEvent<{ width: number, height: number }>;
+ public onRender!: IEvent<{ start: number, end: number }>;
+ public dispose(): void {
+ throw new Error('Method not implemented.');
+ }
+ public colorManager!: IColorManager;
+ public on(type: string, listener: XtermListener): void {
+ throw new Error('Method not implemented.');
+ }
+ public off(type: string, listener: XtermListener): void {
+ throw new Error('Method not implemented.');
+ }
+ public emit(type: string, data?: any): void {
+ throw new Error('Method not implemented.');
+ }
+ public addDisposableListener(type: string, handler: XtermListener): IDisposable {
+ throw new Error('Method not implemented.');
+ }
+ public dimensions!: IRenderDimensions;
+ public setColors(colors: IColorSet): void {
+ throw new Error('Method not implemented.');
+ }
+ public onResize(cols: number, rows: number): void { }
+ public onCharSizeChanged(): void { }
+ public onBlur(): void { }
+ public onFocus(): void { }
+ public onSelectionChanged(start: [number, number], end: [number, number]): void { }
+ public onCursorMove(): void { }
+ public onOptionsChanged(): void { }
+ public onDevicePixelRatioChange(): void { }
+ public clear(): void { }
+ public renderRows(start: number, end: number): void { }
+ public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; }
+ public deregisterCharacterJoiner(): boolean { return true; }
+}
+
+export class MockViewport implements IViewport {
+ public dispose(): void {
+ throw new Error('Method not implemented.');
+ }
+ public scrollBarWidth: number = 0;
+ public onThemeChange(colors: IColorSet): void {
+ throw new Error('Method not implemented.');
+ }
+ public onWheel(ev: WheelEvent): boolean {
+ throw new Error('Method not implemented.');
+ }
+ public onTouchStart(ev: TouchEvent): void {
+ throw new Error('Method not implemented.');
+ }
+ public onTouchMove(ev: TouchEvent): boolean {
+ throw new Error('Method not implemented.');
+ }
+ public syncScrollArea(): void { }
+ public getLinesScrolled(ev: WheelEvent): number {
+ throw new Error('Method not implemented.');
+ }
+}
+
+export class MockCompositionHelper implements ICompositionHelper {
+ public compositionstart(): void {
+ throw new Error('Method not implemented.');
+ }
+ public compositionupdate(ev: CompositionEvent): void {
+ throw new Error('Method not implemented.');
+ }
+ public compositionend(): void {
+ throw new Error('Method not implemented.');
+ }
+ public updateCompositionElements(dontRecurse?: boolean): void {
+ throw new Error('Method not implemented.');
+ }
+ public keydown(ev: KeyboardEvent): boolean {
+ return true;
+ }
+}
export class MockCharSizeService implements ICharSizeService {
public serviceBrand: undefined;
diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts
index f4645543f..76aa0c8cf 100644
--- a/src/browser/Types.d.ts
+++ b/src/browser/Types.d.ts
@@ -3,9 +3,107 @@
* @license MIT
*/
+import { IDisposable, IMarker, ISelectionPosition } from 'xterm';
import { IEvent } from 'common/EventEmitter';
-import { IDisposable } from 'common/Types';
+import { ICoreTerminal, CharData, ITerminalOptions } from 'common/Types';
import { IMouseService, IRenderService } from './services/Services';
+import { IBuffer, IBufferSet } from 'common/buffer/Types';
+import { IFunctionIdentifier, IParams } from 'common/parser/Types';
+
+export interface ITerminal extends IPublicTerminal, ICoreTerminal {
+ element: HTMLElement | undefined;
+ screenElement: HTMLElement | undefined;
+ browser: IBrowser;
+ buffer: IBuffer;
+ buffers: IBufferSet;
+ viewport: IViewport | undefined;
+ // TODO: We should remove options once components adopt optionsService
+ options: ITerminalOptions;
+ linkifier: ILinkifier;
+ linkifier2: ILinkifier2;
+
+ onBlur: IEvent;
+ onFocus: IEvent;
+ onA11yChar: IEvent;
+ onA11yTab: IEvent;
+
+ cancel(ev: Event, force?: boolean): boolean | void;
+}
+
+// Portions of the public API that are required by the internal Terminal
+export interface IPublicTerminal extends IDisposable {
+ textarea: HTMLTextAreaElement | undefined;
+ rows: number;
+ cols: number;
+ buffer: IBuffer;
+ markers: IMarker[];
+ onCursorMove: IEvent;
+ onData: IEvent;
+ onBinary: IEvent;
+ onKey: IEvent<{ key: string, domEvent: KeyboardEvent }>;
+ onLineFeed: IEvent;
+ onScroll: IEvent;
+ onSelectionChange: IEvent;
+ onRender: IEvent<{ start: number, end: number }>;
+ onResize: IEvent<{ cols: number, rows: number }>;
+ onTitleChange: IEvent;
+ blur(): void;
+ focus(): void;
+ resize(columns: number, rows: number): void;
+ open(parent: HTMLElement): void;
+ attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void;
+ addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable;
+ addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable;
+ addEscHandler(id: IFunctionIdentifier, callback: () => boolean): IDisposable;
+ addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable;
+ registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions): number;
+ deregisterLinkMatcher(matcherId: number): void;
+ registerLinkProvider(linkProvider: ILinkProvider): IDisposable;
+ registerCharacterJoiner(handler: (text: string) => [number, number][]): number;
+ deregisterCharacterJoiner(joinerId: number): void;
+ addMarker(cursorYOffset: number): IMarker | undefined;
+ hasSelection(): boolean;
+ getSelection(): string;
+ getSelectionPosition(): ISelectionPosition | undefined;
+ clearSelection(): void;
+ select(column: number, row: number, length: number): void;
+ selectAll(): void;
+ selectLines(start: number, end: number): void;
+ dispose(): void;
+ scrollLines(amount: number): void;
+ scrollPages(pageCount: number): void;
+ scrollToTop(): void;
+ scrollToBottom(): void;
+ scrollToLine(line: number): void;
+ clear(): void;
+ write(data: string | Uint8Array, callback?: () => void): void;
+ paste(data: string): void;
+ refresh(start: number, end: number): void;
+ reset(): void;
+}
+
+export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean;
+
+export type LineData = CharData[];
+
+export interface ICompositionHelper {
+ compositionstart(): void;
+ compositionupdate(ev: CompositionEvent): void;
+ compositionend(): void;
+ updateCompositionElements(dontRecurse?: boolean): void;
+ keydown(ev: KeyboardEvent): boolean;
+}
+
+export interface IBrowser {
+ isNode: boolean;
+ userAgent: string;
+ platform: string;
+ isFirefox: boolean;
+ isMac: boolean;
+ isIpad: boolean;
+ isIphone: boolean;
+ isWindows: boolean;
+}
export interface IColorManager {
colors: IColorSet;
diff --git a/src/public/AddonManager.test.ts b/src/browser/public/AddonManager.test.ts
similarity index 90%
rename from src/public/AddonManager.test.ts
rename to src/browser/public/AddonManager.test.ts
index ea2290954..e947976ac 100644
--- a/src/public/AddonManager.test.ts
+++ b/src/browser/public/AddonManager.test.ts
@@ -42,9 +42,9 @@ describe('AddonManager', () => {
public activate(): void {}
public dispose(): void { called++; }
}
- manager.loadAddon(null, new Addon());
- manager.loadAddon(null, new Addon());
- manager.loadAddon(null, new Addon());
+ manager.loadAddon(null!, new Addon());
+ manager.loadAddon(null!, new Addon());
+ manager.loadAddon(null!, new Addon());
assert.equal(manager.addons.length, 3);
manager.dispose();
assert.equal(called, 3);
diff --git a/src/public/AddonManager.ts b/src/browser/public/AddonManager.ts
similarity index 100%
rename from src/public/AddonManager.ts
rename to src/browser/public/AddonManager.ts
diff --git a/src/public/Terminal.ts b/src/browser/public/Terminal.ts
similarity index 97%
rename from src/public/Terminal.ts
rename to src/browser/public/Terminal.ts
index 61334f08a..b49fc6b8f 100644
--- a/src/public/Terminal.ts
+++ b/src/browser/public/Terminal.ts
@@ -4,12 +4,12 @@
*/
import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ISelectionPosition, IBuffer as IBufferApi, IBufferNamespace as IBufferNamespaceApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi, IParser, IFunctionIdentifier, ILinkProvider, IUnicodeHandling, IUnicodeVersionProvider } from 'xterm';
-import { ITerminal } from '../Types';
+import { ITerminal } from 'browser/Types';
import { IBufferLine, ICellData } from 'common/Types';
import { IBuffer, IBufferSet } from 'common/buffer/Types';
import { CellData } from 'common/buffer/CellData';
import { Terminal as TerminalCore } from '../Terminal';
-import * as Strings from '../browser/LocalizableStrings';
+import * as Strings from '../LocalizableStrings';
import { IEvent, EventEmitter } from 'common/EventEmitter';
import { AddonManager } from './AddonManager';
import { IParams } from 'common/parser/Types';
@@ -17,7 +17,7 @@ import { IParams } from 'common/parser/Types';
export class Terminal implements ITerminalApi {
private _core: ITerminal;
private _addonManager: AddonManager;
- private _parser: IParser;
+ private _parser: IParser | undefined;
constructor(options?: ITerminalOptions) {
this._core = new TerminalCore(options);
@@ -81,11 +81,11 @@ export class Terminal implements ITerminalApi {
public deregisterCharacterJoiner(joinerId: number): void {
this._core.deregisterCharacterJoiner(joinerId);
}
- public registerMarker(cursorYOffset: number): IMarker {
+ public registerMarker(cursorYOffset: number): IMarker | undefined {
this._verifyIntegers(cursorYOffset);
return this._core.addMarker(cursorYOffset);
}
- public addMarker(cursorYOffset: number): IMarker {
+ public addMarker(cursorYOffset: number): IMarker | undefined {
return this.registerMarker(cursorYOffset);
}
public hasSelection(): boolean {
diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts
index a0ca25d2e..d6b305244 100644
--- a/src/browser/services/RenderService.ts
+++ b/src/browser/services/RenderService.ts
@@ -10,7 +10,7 @@ import { Disposable } from 'common/Lifecycle';
import { ScreenDprMonitor } from 'browser/ScreenDprMonitor';
import { addDisposableDomListener } from 'browser/Lifecycle';
import { IColorSet } from 'browser/Types';
-import { IOptionsService, IBufferService, ICoreService } from 'common/services/Services';
+import { IOptionsService, IBufferService } from 'common/services/Services';
import { ICharSizeService, IRenderService } from 'browser/services/Services';
interface ISelectionState {
diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts
index 49f3509db..3793ae25d 100644
--- a/src/common/CoreTerminal.ts
+++ b/src/common/CoreTerminal.ts
@@ -27,7 +27,7 @@ import { InstantiationService } from 'common/services/InstantiationService';
import { LogService } from 'common/services/LogService';
import { BufferService, MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService';
import { OptionsService } from 'common/services/OptionsService';
-import { ITerminalOptions, IDisposable } from './Types';
+import { ITerminalOptions, IDisposable, IBufferLine, IAttributeData, ICoreTerminal } from 'common/Types';
import { CoreService } from 'common/services/CoreService';
import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter';
import { CoreMouseService } from 'common/services/CoreMouseService';
@@ -37,8 +37,10 @@ import { CharsetService } from 'common/services/CharsetService';
import { updateWindowsModeWrappedState } from 'common/WindowsMode';
import { IFunctionIdentifier, IParams } from 'common/parser/Types';
import { IBufferSet } from 'common/buffer/Types';
+import { InputHandler } from 'common/InputHandler';
+import { WriteBuffer } from 'common/input/WriteBuffer';
-export abstract class CoreTerminal extends Disposable {
+export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
protected readonly _instantiationService: IInstantiationService;
protected readonly _bufferService: IBufferService;
protected readonly _logService: ILogService;
@@ -50,7 +52,11 @@ export abstract class CoreTerminal extends Disposable {
public readonly unicodeService: IUnicodeService;
public readonly optionsService: IOptionsService;
+ protected _inputHandler: InputHandler;
+ private _writeBuffer: WriteBuffer;
private _windowsMode: IDisposable | undefined;
+ /** An IBufferline to clone/copy from for new blank lines */
+ private _cachedBlankLine: IBufferLine | undefined;
private _onBinary = new EventEmitter();
public get onBinary(): IEvent { return this._onBinary.event; }
@@ -60,6 +66,8 @@ export abstract class CoreTerminal extends Disposable {
public get onLineFeed(): IEvent { return this._onLineFeed.event; }
private _onResize = new EventEmitter<{ cols: number, rows: number }>();
public get onResize(): IEvent<{ cols: number, rows: number }> { return this._onResize.event; }
+ protected _onScroll = new EventEmitter();
+ public get onScroll(): IEvent { return this._onScroll.event; }
public get cols(): number { return this._bufferService.cols; }
public get rows(): number { return this._bufferService.rows; }
@@ -89,11 +97,19 @@ export abstract class CoreTerminal extends Disposable {
this._charsetService = this._instantiationService.createInstance(CharsetService);
this._instantiationService.setService(ICharsetService, this._charsetService);
+ // Register input handler and handle/forward events
+ this._inputHandler = new InputHandler(this._bufferService, this._charsetService, this._coreService, this._dirtyRowService, this._logService, this.optionsService, this._coreMouseService, this.unicodeService);
+ this.register(forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed));
+ this.register(this._inputHandler);
+
// Setup listeners
this.register(forwardEvent(this._bufferService.onResize, this._onResize));
this.register(forwardEvent(this._coreService.onData, this._onData));
this.register(forwardEvent(this._coreService.onBinary, this._onBinary));
this.register(this.optionsService.onOptionChange(key => this._updateOptions(key)));
+
+ // Setup WriteBuffer
+ this._writeBuffer = new WriteBuffer(data => this._inputHandler.parse(data));
}
public dispose(): void {
@@ -105,6 +121,14 @@ export abstract class CoreTerminal extends Disposable {
this._windowsMode = undefined;
}
+ public write(data: string | Uint8Array, callback?: () => void): void {
+ this._writeBuffer.write(data, callback);
+ }
+
+ public writeSync(data: string | Uint8Array): void {
+ this._writeBuffer.writeSync(data);
+ }
+
public resize(x: number, y: number): void {
if (isNaN(x) || isNaN(y)) {
return;
@@ -116,12 +140,167 @@ export abstract class CoreTerminal extends Disposable {
this._bufferService.resize(x, y);
}
+ /**
+ * Scroll the terminal down 1 row, creating a blank line.
+ * @param isWrapped Whether the new line is wrapped from the previous line.
+ */
+ public scroll(eraseAttr: IAttributeData, isWrapped: boolean = false): void {
+ const buffer = this._bufferService.buffer;
+
+ let newLine: IBufferLine | undefined;
+ newLine = this._cachedBlankLine;
+ if (!newLine || newLine.length !== this.cols || newLine.getFg(0) !== eraseAttr.fg || newLine.getBg(0) !== eraseAttr.bg) {
+ newLine = buffer.getBlankLine(eraseAttr, isWrapped);
+ this._cachedBlankLine = newLine;
+ }
+ newLine.isWrapped = isWrapped;
+
+ const topRow = buffer.ybase + buffer.scrollTop;
+ const bottomRow = buffer.ybase + buffer.scrollBottom;
+
+ if (buffer.scrollTop === 0) {
+ // Determine whether the buffer is going to be trimmed after insertion.
+ const willBufferBeTrimmed = buffer.lines.isFull;
+
+ // Insert the line using the fastest method
+ if (bottomRow === buffer.lines.length - 1) {
+ if (willBufferBeTrimmed) {
+ buffer.lines.recycle().copyFrom(newLine);
+ } else {
+ buffer.lines.push(newLine.clone());
+ }
+ } else {
+ buffer.lines.splice(bottomRow + 1, 0, newLine.clone());
+ }
+
+ // Only adjust ybase and ydisp when the buffer is not trimmed
+ if (!willBufferBeTrimmed) {
+ buffer.ybase++;
+ // Only scroll the ydisp with ybase if the user has not scrolled up
+ if (!this._bufferService.isUserScrolling) {
+ buffer.ydisp++;
+ }
+ } else {
+ // When the buffer is full and the user has scrolled up, keep the text
+ // stable unless ydisp is right at the top
+ if (this._bufferService.isUserScrolling) {
+ buffer.ydisp = Math.max(buffer.ydisp - 1, 0);
+ }
+ }
+ } else {
+ // scrollTop is non-zero which means no line will be going to the
+ // scrollback, instead we can just shift them in-place.
+ const scrollRegionHeight = bottomRow - topRow + 1 /* as it's zero-based */;
+ buffer.lines.shiftElements(topRow + 1, scrollRegionHeight - 1, -1);
+ buffer.lines.set(bottomRow, newLine.clone());
+ }
+
+ // Move the viewport to the bottom of the buffer unless the user is
+ // scrolling.
+ if (!this._bufferService.isUserScrolling) {
+ buffer.ydisp = buffer.ybase;
+ }
+
+ // Flag rows that need updating
+ this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom);
+
+ this._onScroll.fire(buffer.ydisp);
+ }
+
+ /**
+ * Scroll the display of the terminal
+ * @param disp The number of lines to scroll down (negative scroll up).
+ * @param suppressScrollEvent Don't emit the scroll event as scrollLines. This is used
+ * to avoid unwanted events being handled by the viewport when the event was triggered from the
+ * viewport originally.
+ */
+ public scrollLines(disp: number, suppressScrollEvent?: boolean): void {
+ const buffer = this._bufferService.buffer;
+ if (disp < 0) {
+ if (buffer.ydisp === 0) {
+ return;
+ }
+ this._bufferService.isUserScrolling = true;
+ } else if (disp + buffer.ydisp >= buffer.ybase) {
+ this._bufferService.isUserScrolling = false;
+ }
+
+ const oldYdisp = buffer.ydisp;
+ buffer.ydisp = Math.max(Math.min(buffer.ydisp + disp, buffer.ybase), 0);
+
+ // No change occurred, don't trigger scroll/refresh
+ if (oldYdisp === buffer.ydisp) {
+ return;
+ }
+
+ if (!suppressScrollEvent) {
+ this._onScroll.fire(buffer.ydisp);
+ }
+ }
+
+ /**
+ * Scroll the display of the terminal by a number of pages.
+ * @param pageCount The number of pages to scroll (negative scrolls up).
+ */
+ public scrollPages(pageCount: number): void {
+ this.scrollLines(pageCount * (this.rows - 1));
+ }
+
+ /**
+ * Scrolls the display of the terminal to the top.
+ */
+ public scrollToTop(): void {
+ this.scrollLines(-this._bufferService.buffer.ydisp);
+ }
+
+ /**
+ * Scrolls the display of the terminal to the bottom.
+ */
+ public scrollToBottom(): void {
+ this.scrollLines(this._bufferService.buffer.ybase - this._bufferService.buffer.ydisp);
+ }
+
+ public scrollToLine(line: number): void {
+ const scrollAmount = line - this._bufferService.buffer.ydisp;
+ if (scrollAmount !== 0) {
+ this.scrollLines(scrollAmount);
+ }
+ }
+
+ /** Add handler for ESC escape sequence. See xterm.d.ts for details. */
+ public addEscHandler(id: IFunctionIdentifier, callback: () => boolean): IDisposable {
+ return this._inputHandler.addEscHandler(id, callback);
+ }
+
+ /** Add handler for DCS escape sequence. See xterm.d.ts for details. */
+ public addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable {
+ return this._inputHandler.addDcsHandler(id, callback);
+ }
+
+ /** Add handler for CSI escape sequence. See xterm.d.ts for details. */
+ public addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable {
+ return this._inputHandler.addCsiHandler(id, callback);
+ }
+
+ /** Add handler for OSC escape sequence. See xterm.d.ts for details. */
+ public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable {
+ return this._inputHandler.addOscHandler(ident, callback);
+ }
+
protected _setup(): void {
if (this.optionsService.options.windowsMode) {
this._enableWindowsMode();
}
}
+ public reset(): void {
+ this._inputHandler.reset();
+ this._bufferService.reset();
+ this._charsetService.reset();
+ this._coreService.reset();
+ this._coreMouseService.reset();
+ }
+
protected _updateOptions(key: string): void {
// TODO: These listeners should be owned by individual components
switch (key) {
@@ -154,7 +333,4 @@ export abstract class CoreTerminal extends Disposable {
};
}
}
-
- public abstract scrollToBottom(): void;
- public abstract addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable;
}
diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts
index 55e34084b..71faed99a 100644
--- a/src/common/TestUtils.test.ts
+++ b/src/common/TestUtils.test.ts
@@ -17,6 +17,7 @@ export class MockBufferService implements IBufferService {
public get buffer(): IBuffer { return this.buffers.active; }
public buffers: IBufferSet = {} as any;
public onResize: IEvent<{ cols: number, rows: number }> = new EventEmitter<{ cols: number, rows: number }>().event;
+ public isUserScrolling: boolean = false;
constructor(
public cols: number,
public rows: number,
diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts
index 49a723b21..4fcb627bb 100644
--- a/src/common/Types.d.ts
+++ b/src/common/Types.d.ts
@@ -7,6 +7,12 @@ import { ITerminalOptions as IPublicTerminalOptions } from 'xterm';
import { IEvent, IEventEmitter } from 'common/EventEmitter';
import { IDeleteEvent, IInsertEvent } from 'common/CircularList';
import { IParams } from 'common/parser/Types';
+import { IOptionsService, IUnicodeService } from 'common/services/Services';
+
+export interface ICoreTerminal {
+ optionsService: IOptionsService;
+ unicodeService: IUnicodeService;
+}
export interface IDisposable {
dispose(): void;
@@ -51,7 +57,7 @@ export interface ICircularList {
get(index: number): T | undefined;
set(index: number, value: T): void;
push(value: T): void;
- recycle(): T | undefined;
+ recycle(): T;
pop(): T | undefined;
splice(start: number, deleteCount: number, ...items: T[]): void;
trimStart(count: number): void;
diff --git a/src/common/services/BufferService.ts b/src/common/services/BufferService.ts
index d62d2cb00..8de44e43c 100644
--- a/src/common/services/BufferService.ts
+++ b/src/common/services/BufferService.ts
@@ -17,6 +17,8 @@ export class BufferService implements IBufferService {
public cols: number;
public rows: number;
public buffers: IBufferSet;
+ /** Whether the user is scrolling (locks the scroll position) */
+ public isUserScrolling: boolean = false;
private _onResize = new EventEmitter<{ cols: number, rows: number }>();
public get onResize(): IEvent<{ cols: number, rows: number }> { return this._onResize.event; }
@@ -41,5 +43,6 @@ export class BufferService implements IBufferService {
public reset(): void {
this.buffers = new BufferSet(this._optionsService, this);
+ this.isUserScrolling = false;
}
}
diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts
index 6829d7b96..e123bd8bd 100644
--- a/src/common/services/Services.ts
+++ b/src/common/services/Services.ts
@@ -16,6 +16,7 @@ export interface IBufferService {
readonly rows: number;
readonly buffer: IBuffer;
readonly buffers: IBufferSet;
+ isUserScrolling: boolean;
onResize: IEvent<{ cols: number, rows: number }>;
diff --git a/src/tsconfig.json b/src/tsconfig.json
deleted file mode 100644
index 975766683..000000000
--- a/src/tsconfig.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "extends": "./tsconfig-base",
- "compilerOptions": {
- "module": "commonjs",
- "lib": [
- "dom",
- "es5",
- "es6",
- "scripthost",
- "es2015.promise"
- ],
- "rootDir": ".",
- "outDir": "../out",
- "baseUrl": ".",
- "paths": {
- "common/*": [ "./common/*" ],
- "browser/*": [ "./browser/*" ]
- },
-
- "noUnusedLocals": true,
- "noImplicitAny": true
- },
- "include": [
- "./**/*",
- "../typings/xterm.d.ts"
- ],
- "exclude": [
- "./addons/**/*"
- ],
- "references": [
- { "path": "./common" },
- { "path": "./browser" }
- ]
-}
diff --git a/test/benchmark/Terminal.benchmark.ts b/test/benchmark/Terminal.benchmark.ts
index 71a36cc70..76139cb64 100644
--- a/test/benchmark/Terminal.benchmark.ts
+++ b/test/benchmark/Terminal.benchmark.ts
@@ -7,7 +7,7 @@ import { perfContext, before, ThroughputRuntimeCase } from 'xterm-benchmark';
import { spawn } from 'node-pty';
import { Utf8ToUtf32, stringFromCodePoint } from 'common/input/TextDecoder';
-import { Terminal } from 'Terminal';
+import { Terminal } from 'browser/Terminal';
perfContext('Terminal: ls -lR /usr/lib', () => {
let content = '';
diff --git a/tsconfig.all.json b/tsconfig.all.json
index 8143ea91b..a8febb72a 100644
--- a/tsconfig.all.json
+++ b/tsconfig.all.json
@@ -2,7 +2,7 @@
"files": [],
"include": [],
"references": [
- { "path": "./src" },
+ { "path": "./src/browser" },
{ "path": "./test/api" },
{ "path": "./test/benchmark" },
{ "path": "./addons/xterm-addon-attach/src" },
diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts
index 3487c4104..dfda85831 100644
--- a/typings/xterm.d.ts
+++ b/typings/xterm.d.ts
@@ -799,13 +799,14 @@ declare module 'xterm' {
* (EXPERIMENTAL) Adds a marker to the normal buffer and returns it. If the
* alt buffer is active, undefined is returned.
* @param cursorYOffset The y position offset of the marker from the cursor.
+ * @returns The new marker or undefined.
*/
- registerMarker(cursorYOffset: number): IMarker;
+ registerMarker(cursorYOffset: number): IMarker | undefined;
/**
* @deprecated use `registerMarker` instead.
*/
- addMarker(cursorYOffset: number): IMarker;
+ addMarker(cursorYOffset: number): IMarker | undefined;
/**
* Gets whether the terminal has an active selection.
diff --git a/webpack.config.js b/webpack.config.js
index a9a60241b..4f9087b51 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -12,7 +12,7 @@ const path = require('path');
* output by tsc (because of `baseUrl` and `paths` in `tsconfig.json`.
*/
module.exports = {
- entry: './out/public/Terminal.js',
+ entry: './out/browser/public/Terminal.js',
devtool: 'source-map',
module: {
rules: [