Merge branch 'master' into benchmark_integration

This commit is contained in:
Jörg Breitbart
2019-06-18 03:08:07 +02:00
23 changed files with 108 additions and 142 deletions
+4 -9
View File
@@ -5,13 +5,12 @@
import { assert } from 'chai';
import { SelectionManager, SelectionMode } from './SelectionManager';
import { SelectionModel } from './SelectionModel';
import { BufferSet } from 'common/buffer/BufferSet';
import { SelectionModel } from 'browser/selection/SelectionModel';
import { ITerminal } from './Types';
import { IBuffer } from 'common/buffer/Types';
import { IBufferLine } from 'common/Types';
import { MockTerminal } from './TestUtils.test';
import { MockOptionsService, MockBufferService } from 'common/TestUtils.test';
import { MockBufferService } from 'common/TestUtils.test';
import { BufferLine } from 'common/buffer/BufferLine';
import { IBufferService } from 'common/services/Services';
import { MockCharSizeService, MockMouseService } from 'browser/TestUtils.test';
@@ -52,10 +51,7 @@ describe('SelectionManager', () => {
beforeEach(() => {
terminal = new TestMockTerminal();
bufferService = new MockBufferService(20, 20);
terminal.buffers = new BufferSet(
new MockOptionsService({ scrollback: 100 }),
bufferService
);
terminal.buffers = bufferService.buffers;
terminal.cols = 20;
terminal.rows = 20;
terminal.buffer = terminal.buffers.active;
@@ -366,14 +362,13 @@ describe('SelectionManager', () => {
describe('selectAll', () => {
it('should select the entire buffer, beyond the viewport', () => {
buffer.lines.length = 5;
bufferService.resize(20, 5);
buffer.lines.set(0, stringToRow('1'));
buffer.lines.set(1, stringToRow('2'));
buffer.lines.set(2, stringToRow('3'));
buffer.lines.set(3, stringToRow('4'));
buffer.lines.set(4, stringToRow('5'));
selectionManager.selectAll();
terminal.buffer.ybase = buffer.lines.length - bufferService.rows;
assert.equal(selectionManager.selectionText, '1\n2\n3\n4\n5');
});
});
+2 -2
View File
@@ -7,7 +7,7 @@ import { ITerminal, ISelectionManager, ISelectionRedrawRequestEvent } from './Ty
import { IBuffer } from 'common/buffer/Types';
import { IBufferLine } from 'common/Types';
import * as Browser from 'common/Platform';
import { SelectionModel } from './SelectionModel';
import { SelectionModel } from 'browser/selection/SelectionModel';
import { AltClickHandler } from './handlers/AltClickHandler';
import { CellData } from 'common/buffer/CellData';
import { IDisposable } from 'xterm';
@@ -126,7 +126,7 @@ export class SelectionManager implements ISelectionManager {
this._initListeners();
this.enable();
this._model = new SelectionModel(_terminal, bufferService);
this._model = new SelectionModel(bufferService);
this._activeSelectionMode = SelectionMode.NORMAL;
}
+1 -1
View File
@@ -691,7 +691,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
private _createRenderer(): IRenderer {
switch (this.options.rendererType) {
case 'canvas': return new Renderer(this, this._colorManager.colors, this._charSizeService); break;
case 'dom': return new DomRenderer(this, this._colorManager.colors, this._charSizeService); break;
case 'dom': return new DomRenderer(this, this._colorManager.colors, this._charSizeService, this.optionsService); break;
default: throw new Error(`Unrecognized rendererType "${this.options.rendererType}"`);
}
}
@@ -4,24 +4,19 @@
*/
import { assert } from 'chai';
import { MockTerminal, MockBuffer } from '../TestUtils.test';
import { CircularList } from 'common/CircularList';
import { ICharacterJoinerRegistry } from './Types';
import { CharacterJoinerRegistry } from './CharacterJoinerRegistry';
import { ICharacterJoinerRegistry } from 'browser/renderer/Types';
import { CharacterJoinerRegistry } from 'browser/renderer/CharacterJoinerRegistry';
import { BufferLine } from 'common/buffer/BufferLine';
import { IBufferLine } from 'common/Types';
import { CellData } from 'common/buffer/CellData';
import { MockBufferService } from 'common/TestUtils.test';
describe('CharacterJoinerRegistry', () => {
let registry: ICharacterJoinerRegistry;
beforeEach(() => {
const terminal = new MockTerminal();
terminal.cols = 16;
terminal.buffer = new MockBuffer();
const lines = new CircularList<IBufferLine>(7);
const bufferService = new MockBufferService(16, 10);
const lines = bufferService.buffer.lines;
lines.set(0, lineData([['a -> b -> c -> d']]));
lines.set(1, lineData([['a -> b => c -> d']]));
lines.set(2, lineData([['a -> b -', 0xFFFFFFFF], ['> c -> d', 0]]));
@@ -31,7 +26,7 @@ describe('CharacterJoinerRegistry', () => {
lines.set(5, lineData([['a', 0x11111111], [' -> b -> c -> '], ['d', 0x22222222]]));
const line6 = lineData([['wi']]);
line6.resize(line6.length + 1, CellData.fromCharData([0, '¥', 2, '¥'.charCodeAt(0)]));
line6.resize(line6.length + 1, CellData.fromCharData([0, '', 0, null]));
line6.resize(line6.length + 1, CellData.fromCharData([0, '', 0, 0]));
let sub = lineData([['deemo']]);
let oldSize = line6.length;
line6.resize(oldSize + sub.length, CellData.fromCharData([0, '', 0, 0]));
@@ -44,9 +39,7 @@ describe('CharacterJoinerRegistry', () => {
for (let i = 0; i < sub.length; ++i) line6.setCell(i + oldSize, sub.loadCell(i, new CellData()));
lines.set(6, line6);
(<MockBuffer>terminal.buffer).setLines(lines);
terminal.buffer.ydisp = 0;
registry = new CharacterJoinerRegistry(terminal);
registry = new CharacterJoinerRegistry(bufferService);
});
it('has no joiners upon creation', () => {
@@ -3,12 +3,12 @@
* @license MIT
*/
import { ITerminal } from '../Types';
import { IBufferLine, ICellData, CharData } from 'common/Types';
import { ICharacterJoinerRegistry, ICharacterJoiner } from './Types';
import { ICharacterJoinerRegistry, ICharacterJoiner } from 'browser/renderer/Types';
import { AttributeData } from 'common/buffer/AttributeData';
import { WHITESPACE_CELL_CHAR, Content } from 'common/buffer/Constants';
import { CellData } from 'common/buffer/CellData';
import { IBufferService } from 'common/services/Services';
export class JoinedCellData extends AttributeData implements ICellData {
private _width: number;
@@ -61,8 +61,7 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry {
private _nextCharacterJoinerId: number = 0;
private _workCell: CellData = new CellData();
constructor(private _terminal: ITerminal) {
}
constructor(private _bufferService: IBufferService) { }
public registerCharacterJoiner(handler: (text: string) => [number, number][]): number {
const joiner: ICharacterJoiner = {
@@ -90,8 +89,8 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry {
return [];
}
const line = this._terminal.buffer.lines.get(row);
if (line.length === 0) {
const line = this._bufferService.buffer.lines.get(row);
if (!line || line.length === 0) {
return [];
}
@@ -144,7 +143,7 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry {
}
// Process any trailing ranges.
if (this._terminal.cols - rangeStartColumn > 1) {
if (this._bufferService.cols - rangeStartColumn > 1) {
const joinedRanges = this._getJoinedRanges(
lineStr,
rangeStartStringIndex,
@@ -204,7 +203,7 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry {
return;
}
for (let x = startCol; x < this._terminal.cols; x++) {
for (let x = startCol; x < this._bufferService.cols; x++) {
const width = line.getWidth(x);
const length = line.getString(x).length || WHITESPACE_CELL_CHAR.length;
@@ -252,7 +251,7 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry {
// If there is still a range left at the end, it must extend all the way to
// the end of the line.
if (currentRange) {
currentRange[1] = this._terminal.cols;
currentRange[1] = this._bufferService.cols;
}
}
@@ -4,7 +4,7 @@
*/
import { assert } from 'chai';
import { GridCache } from './GridCache';
import { GridCache } from 'browser/renderer/GridCache';
describe('GridCache', () => {
let grid: GridCache<number>;
@@ -4,7 +4,7 @@
*/
export class GridCache<T> {
public cache: T[][];
public cache: (T | undefined)[][];
public constructor() {
this.cache = [];
@@ -16,7 +16,7 @@ export class GridCache<T> {
this.cache.push([]);
}
for (let y = this.cache[x].length; y < height; y++) {
this.cache[x].push(null);
this.cache[x].push(undefined);
}
this.cache[x].length = height;
}
@@ -26,7 +26,7 @@ export class GridCache<T> {
public clear(): void {
for (let x = 0; x < this.cache.length; x++) {
for (let y = 0; y < this.cache[x].length; y++) {
this.cache[x][y] = null;
this.cache[x][y] = undefined;
}
}
}
+11
View File
@@ -45,3 +45,14 @@ export interface IRenderer extends IDisposable {
registerCharacterJoiner(handler: CharacterJoinerHandler): number;
deregisterCharacterJoiner(joinerId: number): boolean;
}
export interface ICharacterJoiner {
id: number;
handler: CharacterJoinerHandler;
}
export interface ICharacterJoinerRegistry {
registerCharacterJoiner(handler: (text: string) => [number, number][]): number;
deregisterCharacterJoiner(joinerId: number): boolean;
getJoinedCharacters(row: number): [number, number][];
}
@@ -4,7 +4,7 @@
*/
import { assert } from 'chai';
import { LRUMap } from './LRUMap';
import { LRUMap } from 'browser/renderer/atlas/LRUMap';
describe('LRUMap', () => {
it('can be used to store and retrieve values', () => {
@@ -4,16 +4,16 @@
*/
interface ILinkedListNode<T> {
prev: ILinkedListNode<T>;
next: ILinkedListNode<T>;
key: number;
value: T;
prev: ILinkedListNode<T> | null;
next: ILinkedListNode<T> | null;
key: number | null;
value: T | null;
}
export class LRUMap<T> {
private _map: { [key: number]: ILinkedListNode<T> } = {};
private _head: ILinkedListNode<T> = null;
private _tail: ILinkedListNode<T> = null;
private _head: ILinkedListNode<T> | null = null;
private _tail: ILinkedListNode<T> | null = null;
private _nodePool: ILinkedListNode<T>[] = [];
public size: number = 0;
@@ -106,9 +106,9 @@ export class LRUMap<T> {
node.value = value;
} else if (this.size >= this.capacity) {
// we're out of space: recycle the head node, move it to the tail
node = this._head;
node = this._head!;
this._unlinkNode(node);
delete this._map[node.key];
delete this._map[node.key!];
node.key = key;
node.value = value;
this._map[key] = node;
@@ -117,7 +117,7 @@ export class LRUMap<T> {
const nodePool = this._nodePool;
if (nodePool.length > 0) {
// use a preallocated node if we can
node = nodePool.pop();
node = nodePool.pop()!;
node.key = key;
node.value = value;
} else {
@@ -5,25 +5,21 @@
import jsdom = require('jsdom');
import { assert } from 'chai';
import { DomRendererRowFactory } from './DomRendererRowFactory';
import { DomRendererRowFactory } from 'browser/renderer/dom/DomRendererRowFactory';
import { NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, DEFAULT_ATTR, FgFlags, BgFlags, Attributes } from 'common/buffer/Constants';
import { BufferLine, DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
import { ITerminalOptions } from '../../Types';
import { IBufferLine } from 'common/Types';
import { CellData } from 'common/buffer/CellData';
import { MockOptionsService } from 'common/TestUtils.test';
describe('DomRendererRowFactory', () => {
let dom: jsdom.JSDOM;
const options: ITerminalOptions = {};
let rowFactory: DomRendererRowFactory;
let lineData: IBufferLine;
beforeEach(() => {
dom = new jsdom.JSDOM('');
options.drawBoldTextInBrightColors = true;
rowFactory = new DomRendererRowFactory(options, dom.window.document);
rowFactory = new DomRendererRowFactory(dom.window.document, new MockOptionsService({ drawBoldTextInBrightColors: true }));
lineData = createEmptyLineData(2);
});
@@ -38,7 +34,7 @@ describe('DomRendererRowFactory', () => {
it('should set correct attributes for double width characters', () => {
lineData.setCell(0, CellData.fromCharData([DEFAULT_ATTR, '語', 2, '語'.charCodeAt(0)]));
// There should be no element for the following "empty" cell
lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, '', 0, undefined]));
lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, '', 0, 0]));
const fragment = rowFactory.createRow(lineData, false, undefined, 0, false, 5, 20);
assert.equal(getFragmentHtml(fragment),
'<span style="width: 10px;">語</span>'
@@ -3,12 +3,12 @@
* @license MIT
*/
import { ITerminalOptions } from '../../Types';
import { IBufferLine } from 'common/Types';
import { INVERTED_DEFAULT_COLOR } from '../atlas/Constants';
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
import { AttributeData } from 'common/buffer/AttributeData';
import { NULL_CELL_CODE, WHITESPACE_CELL_CHAR } from 'common/buffer/Constants';
import { CellData } from 'common/buffer/CellData';
import { ITerminalOptions, IOptionsService } from 'common/services/Services';
export const BOLD_CLASS = 'xterm-bold';
export const DIM_CLASS = 'xterm-dim';
@@ -24,8 +24,8 @@ export class DomRendererRowFactory {
private _workCell: CellData = new CellData();
constructor(
private _terminalOptions: ITerminalOptions,
private _document: Document
private _document: Document,
private _optionsService: IOptionsService
) {
}
@@ -106,7 +106,7 @@ export class DomRendererRowFactory {
charElement.setAttribute('style', style);
} else if (this._workCell.isFgPalette()) {
let fg = this._workCell.getFgColor();
if (this._workCell.isBold() && fg < 8 && !swapColor && this._terminalOptions.drawBoldTextInBrightColors) {
if (this._workCell.isBold() && fg < 8 && !swapColor && this._optionsService.options.drawBoldTextInBrightColors) {
fg += 8;
}
charElement.classList.add(`xterm-${swapColor ? 'b' : 'f'}g-${fg}`);
@@ -4,36 +4,15 @@
*/
import { assert } from 'chai';
import { ITerminal } from './Types';
import { SelectionModel } from './SelectionModel';
import { BufferSet } from 'common/buffer/BufferSet';
import { MockTerminal } from './TestUtils.test';
import { MockOptionsService, MockBufferService } from 'common/TestUtils.test';
import { IBufferService } from 'common/services/Services';
import { MockBufferService } from 'common/TestUtils.test';
class TestSelectionModel extends SelectionModel {
constructor(
terminal: ITerminal,
bufferService: IBufferService
) {
super(terminal, bufferService);
}
}
describe('SelectionManager', () => {
let terminal: ITerminal;
let model: TestSelectionModel;
describe('SelectionModel', () => {
let model: SelectionModel;
beforeEach(() => {
terminal = new MockTerminal();
const bufferService = new MockBufferService(80, 2);
terminal.buffers = new BufferSet(
new MockOptionsService({ scrollback: 10 }),
bufferService
);
terminal.buffer = terminal.buffers.active;
model = new TestSelectionModel(terminal, bufferService);
model = new SelectionModel(bufferService);
});
describe('clearSelection', () => {
@@ -43,8 +22,8 @@ describe('SelectionManager', () => {
assert.deepEqual(model.finalSelectionStart, [0, 0]);
assert.deepEqual(model.finalSelectionEnd, [10, 2]);
model.clearSelection();
assert.deepEqual(model.finalSelectionStart, null);
assert.deepEqual(model.finalSelectionEnd, null);
assert.deepEqual(model.finalSelectionStart, undefined);
assert.deepEqual(model.finalSelectionEnd, undefined);
});
});
@@ -82,8 +61,8 @@ describe('SelectionManager', () => {
model.selectionStart = [0, 0];
model.selectionEnd = [10, 0];
model.onTrim(1);
assert.deepEqual(model.finalSelectionStart, null);
assert.deepEqual(model.finalSelectionEnd, null);
assert.deepEqual(model.finalSelectionStart, undefined);
assert.deepEqual(model.finalSelectionEnd, undefined);
});
});
@@ -111,9 +90,9 @@ describe('SelectionManager', () => {
assert.deepEqual(model.finalSelectionEnd, [80, 1]);
});
it('should return null if there is no selection start', () => {
assert.equal(model.finalSelectionEnd, null);
assert.equal(model.finalSelectionEnd, undefined);
model.selectionEnd = [1, 2];
assert.equal(model.finalSelectionEnd, null);
assert.equal(model.finalSelectionEnd, undefined);
});
it('should return selection start + length if there is no selection end', () => {
model.selectionStart = [2, 2];
@@ -3,7 +3,6 @@
* @license MIT
*/
import { ITerminal } from './Types';
import { IBufferService } from 'common/services/Services';
/**
@@ -14,38 +13,36 @@ export class SelectionModel {
/**
* Whether select all is currently active.
*/
public isSelectAllActive: boolean;
/**
* The [x, y] position the selection starts at.
*/
public selectionStart: [number, number];
public isSelectAllActive: boolean = false;
/**
* The minimal length of the selection from the start position. When double
* clicking on a word, the word will be selected which makes the selection
* start at the start of the word and makes this variable the length.
*/
public selectionStartLength: number;
public selectionStartLength: number = 0;
/**
* The [x, y] position the selection starts at.
*/
public selectionStart: [number, number] | undefined;
/**
* The [x, y] position the selection ends at.
*/
public selectionEnd: [number, number];
public selectionEnd: [number, number] | undefined;
constructor(
private _terminal: ITerminal,
private _bufferService: IBufferService
) {
this.clearSelection();
}
/**
* Clears the current selection.
*/
public clearSelection(): void {
this.selectionStart = null;
this.selectionEnd = null;
this.selectionStart = undefined;
this.selectionEnd = undefined;
this.isSelectAllActive = false;
this.selectionStartLength = 0;
}
@@ -53,7 +50,7 @@ export class SelectionModel {
/**
* The final selection start, taking into consideration select all.
*/
public get finalSelectionStart(): [number, number] {
public get finalSelectionStart(): [number, number] | undefined {
if (this.isSelectAllActive) {
return [0, 0];
}
@@ -69,13 +66,13 @@ export class SelectionModel {
* The final selection end, taking into consideration select all, double click
* word selection and triple click line selection.
*/
public get finalSelectionEnd(): [number, number] {
public get finalSelectionEnd(): [number, number] | undefined {
if (this.isSelectAllActive) {
return [this._bufferService.cols, this._terminal.buffer.ybase + this._bufferService.rows - 1];
return [this._bufferService.cols, this._bufferService.buffer.ybase + this._bufferService.rows - 1];
}
if (!this.selectionStart) {
return null;
return undefined;
}
// Use the selection start + length if the end doesn't exist or they're reversed
+11 -5
View File
@@ -8,14 +8,18 @@ import { IEvent, EventEmitter } from 'common/EventEmitter';
import { clone } from 'common/Clone';
import { DEFAULT_OPTIONS } from 'common/services/OptionsService';
import { IBufferSet, IBuffer } from 'common/buffer/Types';
import { BufferSet } from 'common/buffer/BufferSet';
export class MockBufferService implements IBufferService {
public buffer: IBuffer = {} as any;
public get buffer(): IBuffer { return this.buffers.active; }
public buffers: IBufferSet = {} as any;
constructor(
public cols: number,
public rows: number
) {}
public rows: number,
optionsService: IOptionsService = new MockOptionsService()
) {
this.buffers = new BufferSet(optionsService, this);
}
resize(cols: number, rows: number): void {
this.cols = cols;
this.rows = rows;
@@ -26,8 +30,10 @@ export class MockBufferService implements IBufferService {
export class MockOptionsService implements IOptionsService {
options: ITerminalOptions = clone(DEFAULT_OPTIONS);
onOptionChange: IEvent<string> = new EventEmitter<string>().event;
constructor(testOptions: IPartialTerminalOptions) {
Object.keys(testOptions).forEach(key => this.options[key] = (<any>testOptions)[key]);
constructor(testOptions?: IPartialTerminalOptions) {
if (testOptions) {
Object.keys(testOptions).forEach(key => this.options[key] = (<any>testOptions)[key]);
}
}
setOption<T>(key: string, value: T): void {
throw new Error('Method not implemented.');
+1 -1
View File
@@ -9,7 +9,7 @@ import { ITerminal } from '../Types';
import { ICellData } from 'common/Types';
import { DEFAULT_COLOR, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_CODE } from 'common/buffer/Constants';
import { IGlyphIdentifier } from './atlas/Types';
import { DIM_OPACITY, INVERTED_DEFAULT_COLOR } from './atlas/Constants';
import { DIM_OPACITY, INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
import { BaseCharAtlas } from './atlas/BaseCharAtlas';
import { acquireCharAtlas } from './atlas/CharAtlasCache';
import { AttributeData } from 'common/buffer/AttributeData';
+1 -1
View File
@@ -6,7 +6,7 @@
import { ILinkifierEvent, ITerminal, ILinkifierAccessor } from '../Types';
import { IRenderDimensions } from 'browser/renderer/Types';
import { BaseRenderLayer } from './BaseRenderLayer';
import { INVERTED_DEFAULT_COLOR } from './atlas/Constants';
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
import { is256Color } from './atlas/CharAtlasUtils';
import { IColorSet } from 'browser/Types';
+3 -3
View File
@@ -6,11 +6,11 @@
import { TextRenderLayer } from './TextRenderLayer';
import { SelectionRenderLayer } from './SelectionRenderLayer';
import { CursorRenderLayer } from './CursorRenderLayer';
import { IRenderLayer, ICharacterJoinerRegistry } from './Types';
import { IRenderer, IRenderDimensions, CharacterJoinerHandler } from 'browser/renderer/Types';
import { IRenderLayer } from './Types';
import { IRenderer, IRenderDimensions, CharacterJoinerHandler, ICharacterJoinerRegistry } from 'browser/renderer/Types';
import { ITerminal } from '../Types';
import { LinkRenderLayer } from './LinkRenderLayer';
import { CharacterJoinerRegistry } from '../renderer/CharacterJoinerRegistry';
import { CharacterJoinerRegistry } from 'browser/renderer/CharacterJoinerRegistry';
import { Disposable } from 'common/Lifecycle';
import { IColorSet } from 'browser/Types';
import { ICharSizeService } from 'browser/services/Services';
+3 -4
View File
@@ -3,15 +3,14 @@
* @license MIT
*/
import { ICharacterJoinerRegistry } from './Types';
import { IRenderDimensions } from 'browser/renderer/Types';
import { ICharacterJoinerRegistry, IRenderDimensions } from 'browser/renderer/Types';
import { ITerminal } from '../Types';
import { CharData, ICellData } from 'common/Types';
import { GridCache } from './GridCache';
import { GridCache } from 'browser/renderer/GridCache';
import { BaseRenderLayer } from './BaseRenderLayer';
import { AttributeData } from 'common/buffer/AttributeData';
import { NULL_CELL_CODE, Content } from 'common/buffer/Constants';
import { JoinedCellData } from './CharacterJoinerRegistry';
import { JoinedCellData } from 'browser/renderer/CharacterJoinerRegistry';
import { IColorSet } from 'browser/Types';
import { CellData } from 'common/buffer/CellData';

Some files were not shown because too many files have changed in this diff Show More