Adopt options service in buffer
This commit is contained in:
+15
-17
@@ -7,28 +7,30 @@ import { assert, expect } from 'chai';
|
||||
import { ITerminal } from './Types';
|
||||
import { Buffer } from './Buffer';
|
||||
import { CircularList } from 'common/CircularList';
|
||||
import { MockTerminal, TestTerminal } from './TestUtils.test';
|
||||
import { MockTerminal, TestTerminal, MockOptionsService } from './TestUtils.test';
|
||||
import { BufferLine, CellData, DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
|
||||
|
||||
const INIT_COLS = 80;
|
||||
const INIT_ROWS = 24;
|
||||
const INIT_SCROLLBACK = 1000;
|
||||
|
||||
describe('Buffer', () => {
|
||||
let terminal: ITerminal;
|
||||
let optionsService: MockOptionsService;
|
||||
let buffer: Buffer;
|
||||
|
||||
beforeEach(() => {
|
||||
terminal = new MockTerminal();
|
||||
(terminal as any).cols = INIT_COLS;
|
||||
(terminal as any).rows = INIT_ROWS;
|
||||
terminal.options.scrollback = 1000;
|
||||
buffer = new Buffer(terminal, true);
|
||||
optionsService = new MockOptionsService({ scrollback: INIT_SCROLLBACK });
|
||||
buffer = new Buffer(terminal, true, optionsService);
|
||||
});
|
||||
|
||||
describe('constructor', () => {
|
||||
it('should create a CircularList with max length equal to rows + scrollback, for its lines', () => {
|
||||
assert.instanceOf(buffer.lines, CircularList);
|
||||
assert.equal(buffer.lines.maxLength, terminal.rows + terminal.options.scrollback);
|
||||
assert.equal(buffer.lines.maxLength, terminal.rows + INIT_SCROLLBACK);
|
||||
});
|
||||
it('should set the Buffer\'s scrollBottom value equal to the terminal\'s rows -1', () => {
|
||||
assert.equal(buffer.scrollBottom, terminal.rows - 1);
|
||||
@@ -150,8 +152,7 @@ describe('Buffer', () => {
|
||||
|
||||
describe('no scrollback', () => {
|
||||
it('should trim from the top of the buffer when the cursor reaches the bottom', () => {
|
||||
terminal.options.scrollback = 0;
|
||||
buffer = new Buffer(terminal, true);
|
||||
buffer = new Buffer(terminal, true, new MockOptionsService({ scrollback: 0 }));
|
||||
assert.equal(buffer.lines.maxLength, INIT_ROWS);
|
||||
buffer.y = INIT_ROWS - 1;
|
||||
buffer.fillViewportRows();
|
||||
@@ -295,7 +296,7 @@ describe('Buffer', () => {
|
||||
});
|
||||
it('should discard parts of wrapped lines that go out of the scrollback', () => {
|
||||
buffer.fillViewportRows();
|
||||
terminal.options.scrollback = 1;
|
||||
optionsService.options.scrollback = 1;
|
||||
buffer.resize(10, 5);
|
||||
const lastLine = buffer.lines.get(3);
|
||||
for (let i = 0; i < 10; i++) {
|
||||
@@ -462,7 +463,7 @@ describe('Buffer', () => {
|
||||
});
|
||||
it('should dispose markers whose rows are trimmed during a reflow', () => {
|
||||
buffer.fillViewportRows();
|
||||
terminal.options.scrollback = 1;
|
||||
optionsService.options.scrollback = 1;
|
||||
buffer.resize(10, 11);
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const code = 'a'.charCodeAt(0) + i;
|
||||
@@ -788,7 +789,7 @@ describe('Buffer', () => {
|
||||
// ybase === 0 doesn't make sense here as scrollback=0 isn't really supported
|
||||
describe('ybase !== 0', () => {
|
||||
beforeEach(() => {
|
||||
terminal.options.scrollback = 10;
|
||||
optionsService.options.scrollback = 10;
|
||||
// Add 10 empty rows to start
|
||||
for (let i = 0; i < 10; i++) {
|
||||
buffer.lines.splice(0, 0, buffer.getBlankLine(DEFAULT_ATTR_DATA));
|
||||
@@ -986,7 +987,7 @@ describe('Buffer', () => {
|
||||
// ybase === 0 doesn't make sense here as scrollback=0 isn't really supported
|
||||
describe('ybase !== 0', () => {
|
||||
beforeEach(() => {
|
||||
terminal.options.scrollback = 10;
|
||||
optionsService.options.scrollback = 10;
|
||||
// Add 10 empty rows to start
|
||||
for (let i = 0; i < 10; i++) {
|
||||
buffer.lines.splice(0, 0, buffer.getBlankLine(DEFAULT_ATTR_DATA));
|
||||
@@ -1053,9 +1054,8 @@ describe('Buffer', () => {
|
||||
|
||||
describe('buffer marked to have no scrollback', () => {
|
||||
it('should always have a scrollback of 0', () => {
|
||||
assert.equal(terminal.options.scrollback, 1000);
|
||||
// Test size on initialization
|
||||
buffer = new Buffer(terminal, false);
|
||||
buffer = new Buffer(terminal, false, new MockOptionsService({ scrollback: 1000 }));
|
||||
buffer.fillViewportRows();
|
||||
assert.equal(buffer.lines.maxLength, INIT_ROWS);
|
||||
// Test size on buffer increase
|
||||
@@ -1069,8 +1069,7 @@ describe('Buffer', () => {
|
||||
|
||||
describe('addMarker', () => {
|
||||
it('should adjust a marker line when the buffer is trimmed', () => {
|
||||
terminal.options.scrollback = 0;
|
||||
buffer = new Buffer(terminal, true);
|
||||
buffer = new Buffer(terminal, true, new MockOptionsService({ scrollback: 0 }));
|
||||
buffer.fillViewportRows();
|
||||
const marker = buffer.addMarker(buffer.lines.length - 1);
|
||||
assert.equal(marker.line, buffer.lines.length - 1);
|
||||
@@ -1078,8 +1077,7 @@ describe('Buffer', () => {
|
||||
assert.equal(marker.line, buffer.lines.length - 2);
|
||||
});
|
||||
it('should dispose of a marker if it is trimmed off the buffer', () => {
|
||||
terminal.options.scrollback = 0;
|
||||
buffer = new Buffer(terminal, true);
|
||||
buffer = new Buffer(terminal, true, new MockOptionsService({ scrollback: 0 }));
|
||||
buffer.fillViewportRows();
|
||||
assert.equal(buffer.markers.length, 0);
|
||||
const marker = buffer.addMarker(0);
|
||||
@@ -1366,7 +1364,7 @@ describe('Buffer', () => {
|
||||
const input = '\thttps://google.de';
|
||||
terminal.writeSync(input);
|
||||
const s = terminal.buffer.iterator(true).next().content;
|
||||
assert.equal(s, Array(terminal.options.tabStopWidth + 1).join(' ') + 'https://google.de');
|
||||
assert.equal(s, Array(optionsService.options.tabStopWidth + 1).join(' ') + 'https://google.de');
|
||||
});
|
||||
});
|
||||
describe('BufferStringIterator', function(): void {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { assert } from 'chai';
|
||||
import { ITerminal } from './Types';
|
||||
import { BufferSet } from './BufferSet';
|
||||
import { Buffer } from './Buffer';
|
||||
import { MockTerminal } from './TestUtils.test';
|
||||
import { MockTerminal, MockOptionsService } from './TestUtils.test';
|
||||
|
||||
describe('BufferSet', () => {
|
||||
let terminal: ITerminal;
|
||||
@@ -17,8 +17,7 @@ describe('BufferSet', () => {
|
||||
terminal = new MockTerminal();
|
||||
(terminal as any).cols = 80;
|
||||
(terminal as any).rows = 24;
|
||||
terminal.options.scrollback = 1000;
|
||||
bufferSet = new BufferSet(terminal);
|
||||
bufferSet = new BufferSet(terminal, new MockOptionsService({ scrollback: 1000 }));
|
||||
});
|
||||
|
||||
describe('constructor', () => {
|
||||
|
||||
+7
-3
@@ -7,6 +7,7 @@ import { ITerminal, IBufferSet, IBuffer } from './Types';
|
||||
import { IAttributeData } from 'common/Types';
|
||||
import { Buffer } from './Buffer';
|
||||
import { EventEmitter2, IEvent } from 'common/EventEmitter2';
|
||||
import { IOptionsService } from 'common/services/Services';
|
||||
|
||||
/**
|
||||
* The BufferSet represents the set of two buffers used by xterm terminals (normal and alt) and
|
||||
@@ -25,13 +26,16 @@ export class BufferSet implements IBufferSet {
|
||||
* Create a new BufferSet for the given terminal.
|
||||
* @param _terminal - The terminal the BufferSet will belong to
|
||||
*/
|
||||
constructor(private _terminal: ITerminal) {
|
||||
this._normal = new Buffer(this._terminal, true);
|
||||
constructor(
|
||||
private _terminal: ITerminal,
|
||||
readonly optionsService: IOptionsService
|
||||
) {
|
||||
this._normal = new Buffer(this._terminal, true, optionsService);
|
||||
this._normal.fillViewportRows();
|
||||
|
||||
// The alt buffer should never have scrollback.
|
||||
// See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer
|
||||
this._alt = new Buffer(this._terminal, false);
|
||||
this._alt = new Buffer(this._terminal, false, optionsService);
|
||||
this._activeBuffer = this._normal;
|
||||
|
||||
this.setupTabStops();
|
||||
|
||||
@@ -9,7 +9,7 @@ import { SelectionModel } from './SelectionModel';
|
||||
import { BufferSet } from './BufferSet';
|
||||
import { ITerminal, IBuffer } from './Types';
|
||||
import { IBufferLine } from 'common/Types';
|
||||
import { MockTerminal, MockCharSizeService } from './TestUtils.test';
|
||||
import { MockTerminal, MockCharSizeService, MockOptionsService } from './TestUtils.test';
|
||||
import { BufferLine, CellData } from 'common/buffer/BufferLine';
|
||||
|
||||
class TestMockTerminal extends MockTerminal {
|
||||
@@ -46,8 +46,7 @@ describe('SelectionManager', () => {
|
||||
terminal = new TestMockTerminal();
|
||||
(terminal as any).cols = 80;
|
||||
(terminal as any).rows = 2;
|
||||
terminal.options.scrollback = 100;
|
||||
terminal.buffers = new BufferSet(terminal);
|
||||
terminal.buffers = new BufferSet(terminal, new MockOptionsService({ scrollback: 100 }));
|
||||
terminal.buffer = terminal.buffers.active;
|
||||
buffer = terminal.buffer;
|
||||
selectionManager = new TestSelectionManager(terminal);
|
||||
|
||||
@@ -7,7 +7,7 @@ import { assert } from 'chai';
|
||||
import { ITerminal } from './Types';
|
||||
import { SelectionModel } from './SelectionModel';
|
||||
import { BufferSet } from './BufferSet';
|
||||
import { MockTerminal } from './TestUtils.test';
|
||||
import { MockTerminal, MockOptionsService } from './TestUtils.test';
|
||||
|
||||
class TestSelectionModel extends SelectionModel {
|
||||
constructor(
|
||||
@@ -25,8 +25,7 @@ describe('SelectionManager', () => {
|
||||
terminal = new MockTerminal();
|
||||
(terminal as any).cols = 80;
|
||||
(terminal as any).rows = 2;
|
||||
terminal.options.scrollback = 10;
|
||||
terminal.buffers = new BufferSet(terminal);
|
||||
terminal.buffers = new BufferSet(terminal, new MockOptionsService({ scrollback: 10 }));
|
||||
terminal.buffer = terminal.buffers.active;
|
||||
|
||||
model = new TestSelectionModel(terminal);
|
||||
|
||||
@@ -379,10 +379,10 @@ describe('Terminal', () => {
|
||||
describe('scrollLines', () => {
|
||||
let startYDisp: number;
|
||||
beforeEach(() => {
|
||||
for (let i = 0; i < term.rows * 2; i++) {
|
||||
for (let i = 0; i < INIT_ROWS * 2; i++) {
|
||||
term.writeln('test');
|
||||
}
|
||||
startYDisp = term.rows + 1;
|
||||
startYDisp = INIT_ROWS + 1;
|
||||
});
|
||||
it('should scroll a single line', () => {
|
||||
assert.equal(term.buffer.ydisp, startYDisp);
|
||||
|
||||
+1
-1
@@ -313,7 +313,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
||||
this.soundManager = this.soundManager || new SoundManager(this);
|
||||
|
||||
// Create the terminal's buffers and set the current buffer
|
||||
this.buffers = new BufferSet(this);
|
||||
this.buffers = new BufferSet(this, this.optionsService);
|
||||
if (this.selectionManager) {
|
||||
this.selectionManager.clearSelection();
|
||||
this.selectionManager.initBuffersListeners();
|
||||
|
||||
+20
-4
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { IRenderer, IRenderDimensions } from './renderer/Types';
|
||||
import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBuffer, IBufferSet, IBrowser, ISelectionManager, ITerminalOptions, ILinkifier, IMouseHelper, ILinkMatcherOptions, CharacterJoinerHandler, IBufferStringIterator } from './Types';
|
||||
import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBuffer, IBufferSet, IBrowser, ISelectionManager, ITerminalOptions as IInternalTerminalOptions, ILinkifier, IMouseHelper, ILinkMatcherOptions, CharacterJoinerHandler, IBufferStringIterator } from './Types';
|
||||
import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener } from 'common/Types';
|
||||
import { Buffer } from './Buffer';
|
||||
import * as Browser from 'common/Platform';
|
||||
@@ -12,8 +12,10 @@ import { IDisposable, IMarker, IEvent, ISelectionPosition } from 'xterm';
|
||||
import { Terminal } from './Terminal';
|
||||
import { AttributeData } from 'common/buffer/BufferLine';
|
||||
import { IColorManager, IColorSet } from 'browser/Types';
|
||||
import { IOptionsService } from 'common/services/Services';
|
||||
import { IOptionsService, IPartialTerminalOptions, ITerminalOptions } from 'common/services/Services';
|
||||
import { ICharSizeService } from 'browser/services/Services';
|
||||
import { DEFAULT_OPTIONS } from 'common/services/OptionsService';
|
||||
import { clone } from 'common/Clone';
|
||||
|
||||
export class TestTerminal extends Terminal {
|
||||
writeSync(data: string): void {
|
||||
@@ -122,7 +124,7 @@ export class MockTerminal implements ITerminal {
|
||||
renderer: IRenderer;
|
||||
linkifier: ILinkifier;
|
||||
isFocused: boolean;
|
||||
options: ITerminalOptions = {};
|
||||
options: IInternalTerminalOptions = {};
|
||||
element: HTMLElement;
|
||||
screenElement: HTMLElement;
|
||||
rowContainer: HTMLElement;
|
||||
@@ -183,7 +185,7 @@ export class MockTerminal implements ITerminal {
|
||||
|
||||
export class MockInputHandlingTerminal implements IInputHandlingTerminal {
|
||||
element: HTMLElement;
|
||||
options: ITerminalOptions = {};
|
||||
options: IInternalTerminalOptions = {};
|
||||
cols: number;
|
||||
rows: number;
|
||||
charset: { [key: string]: string; };
|
||||
@@ -435,3 +437,17 @@ export class MockCharSizeService implements ICharSizeService {
|
||||
constructor(public width: number, public height: number) {}
|
||||
measure(): void {}
|
||||
}
|
||||
|
||||
export class MockOptionsService implements IOptionsService {
|
||||
options: ITerminalOptions = clone(DEFAULT_OPTIONS);
|
||||
onOptionChange: IEvent<string>;
|
||||
constructor(testOptions: IPartialTerminalOptions) {
|
||||
Object.keys(testOptions).forEach(key => this.options[key] = (<any>testOptions)[key]);
|
||||
}
|
||||
setOption<T>(key: string, value: T): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getOption<T>(key: string): T {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import { clone } from 'common/Clone';
|
||||
export const DEFAULT_BELL_SOUND = 'data:audio/wav;base64,UklGRigBAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQQBAADpAFgCwAMlBZoG/wdmCcoKRAypDQ8PbRDBEQQTOxRtFYcWlBePGIUZXhoiG88bcBz7HHIdzh0WHlMeZx51HmkeUx4WHs8dah0AHXwc3hs9G4saxRnyGBIYGBcQFv8U4RPAEoYRQBACD70NWwwHC6gJOwjWBloF7gOBAhABkf8b/qv8R/ve+Xf4Ife79W/0JfPZ8Z/wde9N7ijtE+wU6xvqM+lb6H7nw+YX5mrlxuQz5Mzje+Ma49fioeKD4nXiYeJy4pHitOL04j/jn+MN5IPkFOWs5U3mDefM55/ogOl36m7rdOyE7abuyu8D8Unyj/Pg9D/2qfcb+Yn6/vuK/Qj/lAAlAg==';
|
||||
|
||||
// TODO: Freeze?
|
||||
const DEFAULT_OPTIONS: ITerminalOptions = {
|
||||
export const DEFAULT_OPTIONS: ITerminalOptions = {
|
||||
cols: 80,
|
||||
rows: 24,
|
||||
cursorBlink: false,
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@
|
||||
{"type": "default", "format": "camelCase", "leadingUnderscore": "forbid"},
|
||||
{"type": "type", "format": "PascalCase"},
|
||||
{"type": "class", "format": "PascalCase"},
|
||||
{"type": "property", "modifiers": ["const"], "format": "UPPER_CASE"},
|
||||
{"type": "property", "modifiers": ["const"], "format": ["camelCase", "UPPER_CASE"]},
|
||||
{"type": "member", "modifiers": ["protected"], "format": "camelCase", "leadingUnderscore": "allow"},
|
||||
// TODO: Change allow to require when there aren't many PRs out
|
||||
// {"type": "member", "modifiers": ["protected"], "format": "camelCase", "leadingUnderscore": "require"},
|
||||
|
||||
Reference in New Issue
Block a user