IBufferLine interface
This commit is contained in:
+10
-10
@@ -8,7 +8,7 @@ import { ITerminal } from './Types';
|
|||||||
import { Buffer, DEFAULT_ATTR } from './Buffer';
|
import { Buffer, DEFAULT_ATTR } from './Buffer';
|
||||||
import { CircularList } from './common/CircularList';
|
import { CircularList } from './common/CircularList';
|
||||||
import { MockTerminal } from './utils/TestUtils.test';
|
import { MockTerminal } from './utils/TestUtils.test';
|
||||||
import { TerminalLine } from './TerminalLine';
|
import { BufferLine } from './TerminalLine';
|
||||||
|
|
||||||
const INIT_COLS = 80;
|
const INIT_COLS = 80;
|
||||||
const INIT_ROWS = 24;
|
const INIT_ROWS = 24;
|
||||||
@@ -37,7 +37,7 @@ describe('Buffer', () => {
|
|||||||
|
|
||||||
describe('fillViewportRows', () => {
|
describe('fillViewportRows', () => {
|
||||||
it('should fill the buffer with blank lines based on the size of the viewport', () => {
|
it('should fill the buffer with blank lines based on the size of the viewport', () => {
|
||||||
const blankLineChar = TerminalLine.blankLine(terminal.cols, DEFAULT_ATTR).get(0);
|
const blankLineChar = BufferLine.blankLine(terminal.cols, DEFAULT_ATTR).get(0);
|
||||||
buffer.fillViewportRows();
|
buffer.fillViewportRows();
|
||||||
assert.equal(buffer.lines.length, INIT_ROWS);
|
assert.equal(buffer.lines.length, INIT_ROWS);
|
||||||
for (let y = 0; y < INIT_ROWS; y++) {
|
for (let y = 0; y < INIT_ROWS; y++) {
|
||||||
@@ -180,7 +180,7 @@ describe('Buffer', () => {
|
|||||||
buffer.fillViewportRows();
|
buffer.fillViewportRows();
|
||||||
// Create 10 extra blank lines
|
// Create 10 extra blank lines
|
||||||
for (let i = 0; i < 10; i++) {
|
for (let i = 0; i < 10; i++) {
|
||||||
buffer.lines.push(TerminalLine.blankLine(terminal.cols, DEFAULT_ATTR));
|
buffer.lines.push(BufferLine.blankLine(terminal.cols, DEFAULT_ATTR));
|
||||||
}
|
}
|
||||||
// Set cursor to the bottom of the buffer
|
// Set cursor to the bottom of the buffer
|
||||||
buffer.y = INIT_ROWS - 1;
|
buffer.y = INIT_ROWS - 1;
|
||||||
@@ -200,7 +200,7 @@ describe('Buffer', () => {
|
|||||||
buffer.fillViewportRows();
|
buffer.fillViewportRows();
|
||||||
// Create 10 extra blank lines
|
// Create 10 extra blank lines
|
||||||
for (let i = 0; i < 10; i++) {
|
for (let i = 0; i < 10; i++) {
|
||||||
buffer.lines.push(TerminalLine.blankLine(terminal.cols, DEFAULT_ATTR));
|
buffer.lines.push(BufferLine.blankLine(terminal.cols, DEFAULT_ATTR));
|
||||||
}
|
}
|
||||||
// Set cursor to the bottom of the buffer
|
// Set cursor to the bottom of the buffer
|
||||||
buffer.y = INIT_ROWS - 1;
|
buffer.y = INIT_ROWS - 1;
|
||||||
@@ -273,7 +273,7 @@ describe('Buffer', () => {
|
|||||||
|
|
||||||
describe ('translateBufferLineToString', () => {
|
describe ('translateBufferLineToString', () => {
|
||||||
it('should handle selecting a section of ascii text', () => {
|
it('should handle selecting a section of ascii text', () => {
|
||||||
const line = new TerminalLine();
|
const line = new BufferLine();
|
||||||
line.push([ null, 'a', 1, 'a'.charCodeAt(0)]);
|
line.push([ null, 'a', 1, 'a'.charCodeAt(0)]);
|
||||||
line.push([ null, 'b', 1, 'b'.charCodeAt(0)]);
|
line.push([ null, 'b', 1, 'b'.charCodeAt(0)]);
|
||||||
line.push([ null, 'c', 1, 'c'.charCodeAt(0)]);
|
line.push([ null, 'c', 1, 'c'.charCodeAt(0)]);
|
||||||
@@ -285,7 +285,7 @@ describe('Buffer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should handle a cut-off double width character by including it', () => {
|
it('should handle a cut-off double width character by including it', () => {
|
||||||
const line = new TerminalLine();
|
const line = new BufferLine();
|
||||||
line.push([ null, '語', 2, 35486 ]);
|
line.push([ null, '語', 2, 35486 ]);
|
||||||
line.push([ null, '', 0, null]);
|
line.push([ null, '', 0, null]);
|
||||||
line.push([ null, 'a', 1, 'a'.charCodeAt(0)]);
|
line.push([ null, 'a', 1, 'a'.charCodeAt(0)]);
|
||||||
@@ -296,7 +296,7 @@ describe('Buffer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should handle a zero width character in the middle of the string by not including it', () => {
|
it('should handle a zero width character in the middle of the string by not including it', () => {
|
||||||
const line = new TerminalLine();
|
const line = new BufferLine();
|
||||||
line.push([ null, '語', 2, '語'.charCodeAt(0) ]);
|
line.push([ null, '語', 2, '語'.charCodeAt(0) ]);
|
||||||
line.push([ null, '', 0, null]);
|
line.push([ null, '', 0, null]);
|
||||||
line.push([ null, 'a', 1, 'a'.charCodeAt(0)]);
|
line.push([ null, 'a', 1, 'a'.charCodeAt(0)]);
|
||||||
@@ -313,7 +313,7 @@ describe('Buffer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should handle single width emojis', () => {
|
it('should handle single width emojis', () => {
|
||||||
const line = new TerminalLine();
|
const line = new BufferLine();
|
||||||
line.push([ null, '😁', 1, '😁'.charCodeAt(0) ]);
|
line.push([ null, '😁', 1, '😁'.charCodeAt(0) ]);
|
||||||
line.push([ null, 'a', 1, 'a'.charCodeAt(0)]);
|
line.push([ null, 'a', 1, 'a'.charCodeAt(0)]);
|
||||||
buffer.lines.set(0, line);
|
buffer.lines.set(0, line);
|
||||||
@@ -326,7 +326,7 @@ describe('Buffer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should handle double width emojis', () => {
|
it('should handle double width emojis', () => {
|
||||||
const line = new TerminalLine();
|
const line = new BufferLine();
|
||||||
line.push([ null, '😁', 2, '😁'.charCodeAt(0) ]);
|
line.push([ null, '😁', 2, '😁'.charCodeAt(0) ]);
|
||||||
line.push([ null, '', 0, null]);
|
line.push([ null, '', 0, null]);
|
||||||
buffer.lines.set(0, line);
|
buffer.lines.set(0, line);
|
||||||
@@ -337,7 +337,7 @@ describe('Buffer', () => {
|
|||||||
const str2 = buffer.translateBufferLineToString(0, true, 0, 2);
|
const str2 = buffer.translateBufferLineToString(0, true, 0, 2);
|
||||||
assert.equal(str2, '😁');
|
assert.equal(str2, '😁');
|
||||||
|
|
||||||
const line2 = new TerminalLine();
|
const line2 = new BufferLine();
|
||||||
line2.push([ null, '😁', 2, '😁'.charCodeAt(0) ]);
|
line2.push([ null, '😁', 2, '😁'.charCodeAt(0) ]);
|
||||||
line2.push([ null, '', 0, null]);
|
line2.push([ null, '', 0, null]);
|
||||||
line2.push([ null, 'a', 1, 'a'.charCodeAt(0)]);
|
line2.push([ null, 'a', 1, 'a'.charCodeAt(0)]);
|
||||||
|
|||||||
+6
-6
@@ -4,10 +4,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { CircularList } from './common/CircularList';
|
import { CircularList } from './common/CircularList';
|
||||||
import { CharData, ITerminal, IBuffer } from './Types';
|
import { CharData, ITerminal, IBuffer, IBufferLine } from './Types';
|
||||||
import { EventEmitter } from './EventEmitter';
|
import { EventEmitter } from './EventEmitter';
|
||||||
import { IMarker } from 'xterm';
|
import { IMarker } from 'xterm';
|
||||||
import { TerminalLine } from './TerminalLine';
|
import { BufferLine } from './TerminalLine';
|
||||||
|
|
||||||
export const DEFAULT_ATTR = (0 << 18) | (257 << 9) | (256 << 0);
|
export const DEFAULT_ATTR = (0 << 18) | (257 << 9) | (256 << 0);
|
||||||
export const CHAR_DATA_ATTR_INDEX = 0;
|
export const CHAR_DATA_ATTR_INDEX = 0;
|
||||||
@@ -28,7 +28,7 @@ export const NULL_CELL_CODE = 32;
|
|||||||
* - scroll position
|
* - scroll position
|
||||||
*/
|
*/
|
||||||
export class Buffer implements IBuffer {
|
export class Buffer implements IBuffer {
|
||||||
public lines: CircularList<TerminalLine>;
|
public lines: CircularList<IBufferLine>;
|
||||||
public ydisp: number;
|
public ydisp: number;
|
||||||
public ybase: number;
|
public ybase: number;
|
||||||
public y: number;
|
public y: number;
|
||||||
@@ -85,7 +85,7 @@ export class Buffer implements IBuffer {
|
|||||||
if (this.lines.length === 0) {
|
if (this.lines.length === 0) {
|
||||||
let i = this._terminal.rows;
|
let i = this._terminal.rows;
|
||||||
while (i--) {
|
while (i--) {
|
||||||
this.lines.push(TerminalLine.blankLine(this._terminal.cols, DEFAULT_ATTR));
|
this.lines.push(BufferLine.blankLine(this._terminal.cols, DEFAULT_ATTR));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,7 +98,7 @@ export class Buffer implements IBuffer {
|
|||||||
this.ybase = 0;
|
this.ybase = 0;
|
||||||
this.y = 0;
|
this.y = 0;
|
||||||
this.x = 0;
|
this.x = 0;
|
||||||
this.lines = new CircularList<TerminalLine>(this._getCorrectBufferLength(this._terminal.rows));
|
this.lines = new CircularList<IBufferLine>(this._getCorrectBufferLength(this._terminal.rows));
|
||||||
this.scrollTop = 0;
|
this.scrollTop = 0;
|
||||||
this.scrollBottom = this._terminal.rows - 1;
|
this.scrollBottom = this._terminal.rows - 1;
|
||||||
this.setupTabStops();
|
this.setupTabStops();
|
||||||
@@ -147,7 +147,7 @@ export class Buffer implements IBuffer {
|
|||||||
} else {
|
} else {
|
||||||
// Add a blank line if there is no buffer left at the top to scroll to, or if there
|
// Add a blank line if there is no buffer left at the top to scroll to, or if there
|
||||||
// are blank lines after the cursor
|
// are blank lines after the cursor
|
||||||
this.lines.push(TerminalLine.blankLine(newCols, DEFAULT_ATTR));
|
this.lines.push(BufferLine.blankLine(newCols, DEFAULT_ATTR));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import { assert, expect } from 'chai';
|
|||||||
import { InputHandler } from './InputHandler';
|
import { InputHandler } from './InputHandler';
|
||||||
import { MockInputHandlingTerminal } from './utils/TestUtils.test';
|
import { MockInputHandlingTerminal } from './utils/TestUtils.test';
|
||||||
import { NULL_CELL_CHAR, NULL_CELL_CODE, NULL_CELL_WIDTH, CHAR_DATA_CHAR_INDEX } from './Buffer';
|
import { NULL_CELL_CHAR, NULL_CELL_CODE, NULL_CELL_WIDTH, CHAR_DATA_CHAR_INDEX } from './Buffer';
|
||||||
import { TerminalLine } from './TerminalLine';
|
|
||||||
import { Terminal } from './Terminal';
|
import { Terminal } from './Terminal';
|
||||||
|
import { IBufferLine } from './Types';
|
||||||
|
|
||||||
describe('InputHandler', () => {
|
describe('InputHandler', () => {
|
||||||
describe('save and restore cursor', () => {
|
describe('save and restore cursor', () => {
|
||||||
@@ -90,7 +90,7 @@ describe('InputHandler', () => {
|
|||||||
describe('regression tests', function(): void {
|
describe('regression tests', function(): void {
|
||||||
type CharData = [number, string, number, number];
|
type CharData = [number, string, number, number];
|
||||||
|
|
||||||
function lineContent(line: TerminalLine): string {
|
function lineContent(line: IBufferLine): string {
|
||||||
let content = '';
|
let content = '';
|
||||||
for (let i = 0; i < line.length; ++i) content += line.get(i)[CHAR_DATA_CHAR_INDEX];
|
for (let i = 0; i < line.length; ++i) content += line.get(i)[CHAR_DATA_CHAR_INDEX];
|
||||||
return content;
|
return content;
|
||||||
@@ -128,8 +128,8 @@ describe('InputHandler', () => {
|
|||||||
inputHandler.parse('1234567890');
|
inputHandler.parse('1234567890');
|
||||||
inputHandler.parse(Array(term.cols - 9).join('a'));
|
inputHandler.parse(Array(term.cols - 9).join('a'));
|
||||||
inputHandler.parse('1234567890');
|
inputHandler.parse('1234567890');
|
||||||
const line1: TerminalLine = term.buffer.lines.get(0); // line for old variant
|
const line1: IBufferLine = term.buffer.lines.get(0); // line for old variant
|
||||||
const line2: TerminalLine = term.buffer.lines.get(1); // line for new variant
|
const line2: IBufferLine = term.buffer.lines.get(1); // line for new variant
|
||||||
expect(lineContent(line1)).equals(Array(term.cols - 9).join('a') + '1234567890');
|
expect(lineContent(line1)).equals(Array(term.cols - 9).join('a') + '1234567890');
|
||||||
expect(lineContent(line2)).equals(Array(term.cols - 9).join('a') + '1234567890');
|
expect(lineContent(line2)).equals(Array(term.cols - 9).join('a') + '1234567890');
|
||||||
|
|
||||||
@@ -205,8 +205,8 @@ describe('InputHandler', () => {
|
|||||||
inputHandler.parse('1234567890');
|
inputHandler.parse('1234567890');
|
||||||
inputHandler.parse(Array(term.cols - 9).join('a'));
|
inputHandler.parse(Array(term.cols - 9).join('a'));
|
||||||
inputHandler.parse('1234567890');
|
inputHandler.parse('1234567890');
|
||||||
const line1: TerminalLine = term.buffer.lines.get(0); // line for old variant
|
const line1: IBufferLine = term.buffer.lines.get(0); // line for old variant
|
||||||
const line2: TerminalLine = term.buffer.lines.get(1); // line for new variant
|
const line2: IBufferLine = term.buffer.lines.get(1); // line for new variant
|
||||||
expect(lineContent(line1)).equals(Array(term.cols - 9).join('a') + '1234567890');
|
expect(lineContent(line1)).equals(Array(term.cols - 9).join('a') + '1234567890');
|
||||||
expect(lineContent(line2)).equals(Array(term.cols - 9).join('a') + '1234567890');
|
expect(lineContent(line2)).equals(Array(term.cols - 9).join('a') + '1234567890');
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -13,7 +13,7 @@ import { wcwidth } from './CharWidth';
|
|||||||
import { EscapeSequenceParser } from './EscapeSequenceParser';
|
import { EscapeSequenceParser } from './EscapeSequenceParser';
|
||||||
import { ICharset } from './core/Types';
|
import { ICharset } from './core/Types';
|
||||||
import { Disposable } from './common/Lifecycle';
|
import { Disposable } from './common/Lifecycle';
|
||||||
import { TerminalLine } from './TerminalLine';
|
import { BufferLine } from './TerminalLine';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map collect to glevel. Used in `selectCharset`.
|
* Map collect to glevel. Used in `selectCharset`.
|
||||||
@@ -832,7 +832,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|||||||
// test: echo -e '\e[44m\e[1L\e[0m'
|
// test: echo -e '\e[44m\e[1L\e[0m'
|
||||||
// blankLine(true) - xterm/linux behavior
|
// blankLine(true) - xterm/linux behavior
|
||||||
buffer.lines.splice(scrollBottomAbsolute - 1, 1);
|
buffer.lines.splice(scrollBottomAbsolute - 1, 1);
|
||||||
buffer.lines.splice(row, 0, TerminalLine.blankLine(this._terminal.cols, this._terminal.eraseAttr()));
|
buffer.lines.splice(row, 0, BufferLine.blankLine(this._terminal.cols, this._terminal.eraseAttr()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// this.maxRange();
|
// this.maxRange();
|
||||||
@@ -862,7 +862,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|||||||
// test: echo -e '\e[44m\e[1M\e[0m'
|
// test: echo -e '\e[44m\e[1M\e[0m'
|
||||||
// blankLine(true) - xterm/linux behavior
|
// blankLine(true) - xterm/linux behavior
|
||||||
buffer.lines.splice(row, 1);
|
buffer.lines.splice(row, 1);
|
||||||
buffer.lines.splice(j, 0, TerminalLine.blankLine(this._terminal.cols, this._terminal.eraseAttr()));
|
buffer.lines.splice(j, 0, BufferLine.blankLine(this._terminal.cols, this._terminal.eraseAttr()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// this.maxRange();
|
// this.maxRange();
|
||||||
@@ -894,7 +894,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|||||||
|
|
||||||
while (param--) {
|
while (param--) {
|
||||||
buffer.lines.splice(buffer.ybase + buffer.scrollTop, 1);
|
buffer.lines.splice(buffer.ybase + buffer.scrollTop, 1);
|
||||||
buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 0, TerminalLine.blankLine(this._terminal.cols, DEFAULT_ATTR));
|
buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 0, BufferLine.blankLine(this._terminal.cols, DEFAULT_ATTR));
|
||||||
}
|
}
|
||||||
// this.maxRange();
|
// this.maxRange();
|
||||||
this._terminal.updateRange(buffer.scrollTop);
|
this._terminal.updateRange(buffer.scrollTop);
|
||||||
@@ -913,7 +913,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|||||||
|
|
||||||
while (param--) {
|
while (param--) {
|
||||||
buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 1);
|
buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 1);
|
||||||
buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 0, TerminalLine.blankLine(this._terminal.cols, DEFAULT_ATTR));
|
buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 0, BufferLine.blankLine(this._terminal.cols, DEFAULT_ATTR));
|
||||||
}
|
}
|
||||||
// this.maxRange();
|
// this.maxRange();
|
||||||
this._terminal.updateRange(buffer.scrollTop);
|
this._terminal.updateRange(buffer.scrollTop);
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
|
|
||||||
import { assert } from 'chai';
|
import { assert } from 'chai';
|
||||||
import { IMouseZoneManager, IMouseZone } from './ui/Types';
|
import { IMouseZoneManager, IMouseZone } from './ui/Types';
|
||||||
import { ILinkMatcher, ITerminal } from './Types';
|
import { ILinkMatcher, ITerminal, IBufferLine } from './Types';
|
||||||
import { Linkifier } from './Linkifier';
|
import { Linkifier } from './Linkifier';
|
||||||
import { MockBuffer, MockTerminal } from './utils/TestUtils.test';
|
import { MockBuffer, MockTerminal } from './utils/TestUtils.test';
|
||||||
import { CircularList } from './common/CircularList';
|
import { CircularList } from './common/CircularList';
|
||||||
import { TerminalLine } from './TerminalLine';
|
import { BufferLine } from './TerminalLine';
|
||||||
|
|
||||||
class TestLinkifier extends Linkifier {
|
class TestLinkifier extends Linkifier {
|
||||||
constructor(terminal: ITerminal) {
|
constructor(terminal: ITerminal) {
|
||||||
@@ -43,14 +43,14 @@ describe('Linkifier', () => {
|
|||||||
terminal = new MockTerminal();
|
terminal = new MockTerminal();
|
||||||
terminal.cols = 100;
|
terminal.cols = 100;
|
||||||
terminal.buffer = new MockBuffer();
|
terminal.buffer = new MockBuffer();
|
||||||
(<MockBuffer>terminal.buffer).setLines(new CircularList<TerminalLine>(20));
|
(<MockBuffer>terminal.buffer).setLines(new CircularList<IBufferLine>(20));
|
||||||
terminal.buffer.ydisp = 0;
|
terminal.buffer.ydisp = 0;
|
||||||
linkifier = new TestLinkifier(terminal);
|
linkifier = new TestLinkifier(terminal);
|
||||||
mouseZoneManager = new TestMouseZoneManager();
|
mouseZoneManager = new TestMouseZoneManager();
|
||||||
});
|
});
|
||||||
|
|
||||||
function stringToRow(text: string): TerminalLine {
|
function stringToRow(text: string): IBufferLine {
|
||||||
const result = new TerminalLine();
|
const result = new BufferLine();
|
||||||
for (let i = 0; i < text.length; i++) {
|
for (let i = 0; i < text.length; i++) {
|
||||||
result.push([0, text.charAt(i), 1, text.charCodeAt(i)]);
|
result.push([0, text.charAt(i), 1, text.charCodeAt(i)]);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -4,10 +4,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { IMouseZoneManager } from './ui/Types';
|
import { IMouseZoneManager } from './ui/Types';
|
||||||
import { ILinkHoverEvent, ILinkMatcher, LinkMatcherHandler, LinkHoverEventTypes, ILinkMatcherOptions, ILinkifier, ITerminal } from './Types';
|
import { ILinkHoverEvent, ILinkMatcher, LinkMatcherHandler, LinkHoverEventTypes, ILinkMatcherOptions, ILinkifier, ITerminal, IBufferLine } from './Types';
|
||||||
import { MouseZone } from './ui/MouseZoneManager';
|
import { MouseZone } from './ui/MouseZoneManager';
|
||||||
import { EventEmitter } from './EventEmitter';
|
import { EventEmitter } from './EventEmitter';
|
||||||
import { TerminalLine } from './TerminalLine';
|
|
||||||
import { CHAR_DATA_ATTR_INDEX } from './Buffer';
|
import { CHAR_DATA_ATTR_INDEX } from './Buffer';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,7 +170,7 @@ export class Linkifier extends EventEmitter implements ILinkifier {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// If the first row is wrapped, backtrack to find the origin row and linkify that
|
// If the first row is wrapped, backtrack to find the origin row and linkify that
|
||||||
let line: TerminalLine;
|
let line: IBufferLine;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
rowIndex--;
|
rowIndex--;
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import { CharMeasure } from './ui/CharMeasure';
|
|||||||
import { SelectionManager, SelectionMode } from './SelectionManager';
|
import { SelectionManager, SelectionMode } from './SelectionManager';
|
||||||
import { SelectionModel } from './SelectionModel';
|
import { SelectionModel } from './SelectionModel';
|
||||||
import { BufferSet } from './BufferSet';
|
import { BufferSet } from './BufferSet';
|
||||||
import { ITerminal, IBuffer } from './Types';
|
import { ITerminal, IBuffer, IBufferLine } from './Types';
|
||||||
import { MockTerminal } from './utils/TestUtils.test';
|
import { MockTerminal } from './utils/TestUtils.test';
|
||||||
import { TerminalLine } from './TerminalLine';
|
import { BufferLine } from './TerminalLine';
|
||||||
|
|
||||||
class TestMockTerminal extends MockTerminal {
|
class TestMockTerminal extends MockTerminal {
|
||||||
emit(event: string, data: any): void {}
|
emit(event: string, data: any): void {}
|
||||||
@@ -53,16 +53,16 @@ describe('SelectionManager', () => {
|
|||||||
selectionManager = new TestSelectionManager(terminal, null);
|
selectionManager = new TestSelectionManager(terminal, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
function stringToRow(text: string): TerminalLine {
|
function stringToRow(text: string): IBufferLine {
|
||||||
const result = new TerminalLine();
|
const result = new BufferLine();
|
||||||
for (let i = 0; i < text.length; i++) {
|
for (let i = 0; i < text.length; i++) {
|
||||||
result.push([0, text.charAt(i), 1, text.charCodeAt(i)]);
|
result.push([0, text.charAt(i), 1, text.charCodeAt(i)]);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function stringArrayToRow(chars: string[]): TerminalLine {
|
function stringArrayToRow(chars: string[]): IBufferLine {
|
||||||
const line = new TerminalLine();
|
const line = new BufferLine();
|
||||||
chars.map(c => line.push([0, c, 1, c.charCodeAt(0)]));
|
chars.map(c => line.push([0, c, 1, c.charCodeAt(0)]));
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
@@ -100,7 +100,7 @@ describe('SelectionManager', () => {
|
|||||||
});
|
});
|
||||||
it('should expand selection for wide characters', () => {
|
it('should expand selection for wide characters', () => {
|
||||||
// Wide characters use a special format
|
// Wide characters use a special format
|
||||||
const line = new TerminalLine();
|
const line = new BufferLine();
|
||||||
const data: [number, string, number, number][] = [
|
const data: [number, string, number, number][] = [
|
||||||
[null, '中', 2, '中'.charCodeAt(0)],
|
[null, '中', 2, '中'.charCodeAt(0)],
|
||||||
[null, '', 0, null],
|
[null, '', 0, null],
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ITerminal, ISelectionManager, IBuffer, CharData, XtermListener } from './Types';
|
import { ITerminal, ISelectionManager, IBuffer, CharData, XtermListener, IBufferLine } from './Types';
|
||||||
import { MouseHelper } from './utils/MouseHelper';
|
import { MouseHelper } from './utils/MouseHelper';
|
||||||
import * as Browser from './shared/utils/Browser';
|
import * as Browser from './shared/utils/Browser';
|
||||||
import { CharMeasure } from './ui/CharMeasure';
|
import { CharMeasure } from './ui/CharMeasure';
|
||||||
@@ -11,7 +11,6 @@ import { EventEmitter } from './EventEmitter';
|
|||||||
import { SelectionModel } from './SelectionModel';
|
import { SelectionModel } from './SelectionModel';
|
||||||
import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_CODE_INDEX } from './Buffer';
|
import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_CODE_INDEX } from './Buffer';
|
||||||
import { AltClickHandler } from './handlers/AltClickHandler';
|
import { AltClickHandler } from './handlers/AltClickHandler';
|
||||||
import { TerminalLine } from './TerminalLine';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of pixels the mouse needs to be above or below the viewport in
|
* The number of pixels the mouse needs to be above or below the viewport in
|
||||||
@@ -662,7 +661,7 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
|||||||
* latter takes into account wide characters.
|
* latter takes into account wide characters.
|
||||||
* @param coords The coordinates to find the 2 index for.
|
* @param coords The coordinates to find the 2 index for.
|
||||||
*/
|
*/
|
||||||
private _convertViewportColToCharacterIndex(bufferLine: TerminalLine, coords: [number, number]): number {
|
private _convertViewportColToCharacterIndex(bufferLine: IBufferLine, coords: [number, number]): number {
|
||||||
let charIndex = coords[0];
|
let charIndex = coords[0];
|
||||||
for (let i = 0; coords[0] >= i; i++) {
|
for (let i = 0; coords[0] >= i; i++) {
|
||||||
const char = bufferLine.get(i);
|
const char = bufferLine.get(i);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { assert, expect } from 'chai';
|
|||||||
import { Terminal } from './Terminal';
|
import { Terminal } from './Terminal';
|
||||||
import { MockViewport, MockCompositionHelper, MockRenderer } from './utils/TestUtils.test';
|
import { MockViewport, MockCompositionHelper, MockRenderer } from './utils/TestUtils.test';
|
||||||
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, DEFAULT_ATTR } from './Buffer';
|
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, DEFAULT_ATTR } from './Buffer';
|
||||||
import { TerminalLine } from './TerminalLine';
|
import { BufferLine } from './TerminalLine';
|
||||||
|
|
||||||
const INIT_COLS = 80;
|
const INIT_COLS = 80;
|
||||||
const INIT_ROWS = 24;
|
const INIT_ROWS = 24;
|
||||||
@@ -142,7 +142,7 @@ describe('term.js addons', () => {
|
|||||||
assert.equal(term.buffer.lines.length, term.rows);
|
assert.equal(term.buffer.lines.length, term.rows);
|
||||||
assert.deepEqual(term.buffer.lines.get(0), promptLine);
|
assert.deepEqual(term.buffer.lines.get(0), promptLine);
|
||||||
for (let i = 1; i < term.rows; i++) {
|
for (let i = 1; i < term.rows; i++) {
|
||||||
assert.deepEqual(term.buffer.lines.get(i), TerminalLine.blankLine(term.cols, DEFAULT_ATTR));
|
assert.deepEqual(term.buffer.lines.get(i), BufferLine.blankLine(term.cols, DEFAULT_ATTR));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
it('should clear a buffer larger than rows', () => {
|
it('should clear a buffer larger than rows', () => {
|
||||||
@@ -159,7 +159,7 @@ describe('term.js addons', () => {
|
|||||||
assert.equal(term.buffer.lines.length, term.rows);
|
assert.equal(term.buffer.lines.length, term.rows);
|
||||||
assert.deepEqual(term.buffer.lines.get(0), promptLine);
|
assert.deepEqual(term.buffer.lines.get(0), promptLine);
|
||||||
for (let i = 1; i < term.rows; i++) {
|
for (let i = 1; i < term.rows; i++) {
|
||||||
assert.deepEqual(term.buffer.lines.get(i), TerminalLine.blankLine(term.cols, DEFAULT_ATTR));
|
assert.deepEqual(term.buffer.lines.get(i), BufferLine.blankLine(term.cols, DEFAULT_ATTR));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
it('should not break the prompt when cleared twice', () => {
|
it('should not break the prompt when cleared twice', () => {
|
||||||
@@ -172,7 +172,7 @@ describe('term.js addons', () => {
|
|||||||
assert.equal(term.buffer.lines.length, term.rows);
|
assert.equal(term.buffer.lines.length, term.rows);
|
||||||
assert.deepEqual(term.buffer.lines.get(0), promptLine);
|
assert.deepEqual(term.buffer.lines.get(0), promptLine);
|
||||||
for (let i = 1; i < term.rows; i++) {
|
for (let i = 1; i < term.rows; i++) {
|
||||||
assert.deepEqual(term.buffer.lines.get(i), TerminalLine.blankLine(term.cols, DEFAULT_ATTR));
|
assert.deepEqual(term.buffer.lines.get(i), BufferLine.blankLine(term.cols, DEFAULT_ATTR));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+4
-4
@@ -52,7 +52,7 @@ import { DomRenderer } from './renderer/dom/DomRenderer';
|
|||||||
import { IKeyboardEvent } from './common/Types';
|
import { IKeyboardEvent } from './common/Types';
|
||||||
import { evaluateKeyboardEvent } from './core/input/Keyboard';
|
import { evaluateKeyboardEvent } from './core/input/Keyboard';
|
||||||
import { KeyboardResultType, ICharset } from './core/Types';
|
import { KeyboardResultType, ICharset } from './core/Types';
|
||||||
import { TerminalLine } from './TerminalLine';
|
import { BufferLine } from './TerminalLine';
|
||||||
|
|
||||||
// Let it work inside Node.js for automated testing purposes.
|
// Let it work inside Node.js for automated testing purposes.
|
||||||
const document = (typeof window !== 'undefined') ? window.document : null;
|
const document = (typeof window !== 'undefined') ? window.document : null;
|
||||||
@@ -1171,7 +1171,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
|||||||
* @param isWrapped Whether the new line is wrapped from the previous line.
|
* @param isWrapped Whether the new line is wrapped from the previous line.
|
||||||
*/
|
*/
|
||||||
public scroll(isWrapped?: boolean): void {
|
public scroll(isWrapped?: boolean): void {
|
||||||
const newLine = TerminalLine.blankLine(this.cols, DEFAULT_ATTR, isWrapped);
|
const newLine = BufferLine.blankLine(this.cols, DEFAULT_ATTR, isWrapped);
|
||||||
const topRow = this.buffer.ybase + this.buffer.scrollTop;
|
const topRow = this.buffer.ybase + this.buffer.scrollTop;
|
||||||
const bottomRow = this.buffer.ybase + this.buffer.scrollBottom;
|
const bottomRow = this.buffer.ybase + this.buffer.scrollBottom;
|
||||||
|
|
||||||
@@ -1753,7 +1753,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
|||||||
this.buffer.ybase = 0;
|
this.buffer.ybase = 0;
|
||||||
this.buffer.y = 0;
|
this.buffer.y = 0;
|
||||||
for (let i = 1; i < this.rows; i++) {
|
for (let i = 1; i < this.rows; i++) {
|
||||||
this.buffer.lines.push(TerminalLine.blankLine(this.cols, DEFAULT_ATTR));
|
this.buffer.lines.push(BufferLine.blankLine(this.cols, DEFAULT_ATTR));
|
||||||
}
|
}
|
||||||
this.refresh(0, this.rows - 1);
|
this.refresh(0, this.rows - 1);
|
||||||
this.emit('scroll', this.buffer.ydisp);
|
this.emit('scroll', this.buffer.ydisp);
|
||||||
@@ -1854,7 +1854,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
|||||||
// blankLine(true) is xterm/linux behavior
|
// blankLine(true) is xterm/linux behavior
|
||||||
const scrollRegionHeight = this.buffer.scrollBottom - this.buffer.scrollTop;
|
const scrollRegionHeight = this.buffer.scrollBottom - this.buffer.scrollTop;
|
||||||
this.buffer.lines.shiftElements(this.buffer.y + this.buffer.ybase, scrollRegionHeight, 1);
|
this.buffer.lines.shiftElements(this.buffer.y + this.buffer.ybase, scrollRegionHeight, 1);
|
||||||
this.buffer.lines.set(this.buffer.y + this.buffer.ybase, TerminalLine.blankLine(this.cols, this.eraseAttr()));
|
this.buffer.lines.set(this.buffer.y + this.buffer.ybase, BufferLine.blankLine(this.cols, this.eraseAttr()));
|
||||||
this.updateRange(this.buffer.scrollTop);
|
this.updateRange(this.buffer.scrollTop);
|
||||||
this.updateRange(this.buffer.scrollBottom);
|
this.updateRange(this.buffer.scrollBottom);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+21
-14
@@ -3,31 +3,38 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import { TerminalLine } from './TerminalLine';
|
import { BufferLine } from './TerminalLine';
|
||||||
import { CharData } from './Types';
|
import { CharData, IBufferLine } from './Types';
|
||||||
import { NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, CHAR_DATA_ATTR_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CODE_INDEX } from './Buffer';
|
import { NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, CHAR_DATA_ATTR_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CODE_INDEX } from './Buffer';
|
||||||
|
|
||||||
describe('TerminalLine', function(): void {
|
|
||||||
|
class TestBufferLine extends BufferLine {
|
||||||
|
public toArray(): CharData[] {
|
||||||
|
return this._data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('BufferLine', function(): void {
|
||||||
it('ctor', function(): void {
|
it('ctor', function(): void {
|
||||||
let line = new TerminalLine();
|
let line: IBufferLine = new TestBufferLine();
|
||||||
chai.expect(line.length).equals(0);
|
chai.expect(line.length).equals(0);
|
||||||
chai.expect(line.pop()).equals(undefined);
|
chai.expect(line.pop()).equals(undefined);
|
||||||
chai.expect(line.isWrapped).equals(false);
|
chai.expect(line.isWrapped).equals(false);
|
||||||
line = new TerminalLine(10);
|
line = new TestBufferLine(10);
|
||||||
chai.expect(line.length).equals(10);
|
chai.expect(line.length).equals(10);
|
||||||
chai.expect(line.pop()).eql(TerminalLine.defaultCell);
|
chai.expect(line.pop()).eql(TestBufferLine.defaultCell);
|
||||||
chai.expect(line.isWrapped).equals(false);
|
chai.expect(line.isWrapped).equals(false);
|
||||||
line = new TerminalLine(10, null, true);
|
line = new TestBufferLine(10, null, true);
|
||||||
chai.expect(line.length).equals(10);
|
chai.expect(line.length).equals(10);
|
||||||
chai.expect(line.pop()).eql(TerminalLine.defaultCell);
|
chai.expect(line.pop()).eql(TestBufferLine.defaultCell);
|
||||||
chai.expect(line.isWrapped).equals(true);
|
chai.expect(line.isWrapped).equals(true);
|
||||||
line = new TerminalLine(10, [123, 'a', 456, 789], true);
|
line = new TestBufferLine(10, [123, 'a', 456, 789], true);
|
||||||
chai.expect(line.length).equals(10);
|
chai.expect(line.length).equals(10);
|
||||||
chai.expect(line.pop()).eql([123, 'a', 456, 789]);
|
chai.expect(line.pop()).eql([123, 'a', 456, 789]);
|
||||||
chai.expect(line.isWrapped).equals(true);
|
chai.expect(line.isWrapped).equals(true);
|
||||||
});
|
});
|
||||||
it('splice', function(): void {
|
it('splice', function(): void {
|
||||||
const line = new TerminalLine();
|
const line = new TestBufferLine();
|
||||||
const data: CharData[] = [
|
const data: CharData[] = [
|
||||||
[1, 'a', 0, 0],
|
[1, 'a', 0, 0],
|
||||||
[2, 'b', 0, 0],
|
[2, 'b', 0, 0],
|
||||||
@@ -41,7 +48,7 @@ describe('TerminalLine', function(): void {
|
|||||||
chai.expect(line.toArray()).eql(data);
|
chai.expect(line.toArray()).eql(data);
|
||||||
});
|
});
|
||||||
it('TerminalLine.blankLine', function(): void {
|
it('TerminalLine.blankLine', function(): void {
|
||||||
const line = TerminalLine.blankLine(5, 123);
|
const line = TestBufferLine.blankLine(5, 123);
|
||||||
chai.expect(line.length).equals(5);
|
chai.expect(line.length).equals(5);
|
||||||
chai.expect(line.isWrapped).equals(false);
|
chai.expect(line.isWrapped).equals(false);
|
||||||
const ch = line.get(0);
|
const ch = line.get(0);
|
||||||
@@ -51,7 +58,7 @@ describe('TerminalLine', function(): void {
|
|||||||
chai.expect(ch[CHAR_DATA_CODE_INDEX]).equals(NULL_CELL_CODE);
|
chai.expect(ch[CHAR_DATA_CODE_INDEX]).equals(NULL_CELL_CODE);
|
||||||
});
|
});
|
||||||
it('insertCells', function(): void {
|
it('insertCells', function(): void {
|
||||||
const line = new TerminalLine();
|
const line = new TestBufferLine();
|
||||||
const data: CharData[] = [
|
const data: CharData[] = [
|
||||||
[1, 'a', 0, 0],
|
[1, 'a', 0, 0],
|
||||||
[2, 'b', 0, 0],
|
[2, 'b', 0, 0],
|
||||||
@@ -62,7 +69,7 @@ describe('TerminalLine', function(): void {
|
|||||||
chai.expect(line.toArray()).eql([[1, 'a', 0, 0], [4, 'd', 0, 0], [4, 'd', 0, 0]]);
|
chai.expect(line.toArray()).eql([[1, 'a', 0, 0], [4, 'd', 0, 0], [4, 'd', 0, 0]]);
|
||||||
});
|
});
|
||||||
it('deleteCells', function(): void {
|
it('deleteCells', function(): void {
|
||||||
const line = new TerminalLine();
|
const line = new TestBufferLine();
|
||||||
const data: CharData[] = [
|
const data: CharData[] = [
|
||||||
[1, 'a', 0, 0],
|
[1, 'a', 0, 0],
|
||||||
[2, 'b', 0, 0],
|
[2, 'b', 0, 0],
|
||||||
@@ -75,7 +82,7 @@ describe('TerminalLine', function(): void {
|
|||||||
chai.expect(line.toArray()).eql([[1, 'a', 0, 0], [4, 'd', 0, 0], [5, 'e', 0, 0], [6, 'f', 0, 0], [6, 'f', 0, 0]]);
|
chai.expect(line.toArray()).eql([[1, 'a', 0, 0], [4, 'd', 0, 0], [5, 'e', 0, 0], [6, 'f', 0, 0], [6, 'f', 0, 0]]);
|
||||||
});
|
});
|
||||||
it('replaceCells', function(): void {
|
it('replaceCells', function(): void {
|
||||||
const line = new TerminalLine();
|
const line = new TestBufferLine();
|
||||||
const data: CharData[] = [
|
const data: CharData[] = [
|
||||||
[1, 'a', 0, 0],
|
[1, 'a', 0, 0],
|
||||||
[2, 'b', 0, 0],
|
[2, 'b', 0, 0],
|
||||||
|
|||||||
+6
-17
@@ -2,7 +2,7 @@
|
|||||||
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
|
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
|
||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
import { CharData } from './Types';
|
import { CharData, IBufferLine } from './Types';
|
||||||
import { NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR } from './Buffer';
|
import { NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR } from './Buffer';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,13 +20,13 @@ import { NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR } from './Buffer';
|
|||||||
* - remove push/pop/splice
|
* - remove push/pop/splice
|
||||||
* - implement typed array alternative once string is removed from CharData
|
* - implement typed array alternative once string is removed from CharData
|
||||||
*/
|
*/
|
||||||
export class TerminalLine {
|
export class BufferLine implements IBufferLine {
|
||||||
static defaultCell: CharData = [0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE];
|
static defaultCell: CharData = [0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE];
|
||||||
static blankLine(cols: number, attr: number, isWrapped?: boolean): TerminalLine {
|
static blankLine(cols: number, attr: number, isWrapped?: boolean): BufferLine {
|
||||||
const ch: CharData = [attr, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE];
|
const ch: CharData = [attr, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE];
|
||||||
return new TerminalLine(cols, ch, isWrapped);
|
return new BufferLine(cols, ch, isWrapped);
|
||||||
}
|
}
|
||||||
private _data: CharData[];
|
protected _data: CharData[];
|
||||||
public isWrapped = false;
|
public isWrapped = false;
|
||||||
public length: number;
|
public length: number;
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ export class TerminalLine {
|
|||||||
this.length = this._data.length;
|
this.length = this._data.length;
|
||||||
if (cols) {
|
if (cols) {
|
||||||
if (!ch) {
|
if (!ch) {
|
||||||
ch = TerminalLine.defaultCell;
|
ch = BufferLine.defaultCell;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < cols; i++) {
|
for (let i = 0; i < cols; i++) {
|
||||||
this.push(ch); // Note: the ctor ch is not cloned
|
this.push(ch); // Note: the ctor ch is not cloned
|
||||||
@@ -57,7 +57,6 @@ export class TerminalLine {
|
|||||||
|
|
||||||
// to be removed for typed array
|
// to be removed for typed array
|
||||||
public pop(): CharData | undefined {
|
public pop(): CharData | undefined {
|
||||||
// TODO: unref here, change CharData to [typeof Attributes, ...]
|
|
||||||
const data = this._data.pop();
|
const data = this._data.pop();
|
||||||
this.length = this._data.length;
|
this.length = this._data.length;
|
||||||
return data;
|
return data;
|
||||||
@@ -67,25 +66,15 @@ export class TerminalLine {
|
|||||||
public push(data: CharData): void {
|
public push(data: CharData): void {
|
||||||
this._data.push(data);
|
this._data.push(data);
|
||||||
this.length = this._data.length;
|
this.length = this._data.length;
|
||||||
// TODO: ref here
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// to be removed for typed array
|
// to be removed for typed array
|
||||||
public splice(start: number, deleteCount: number, ...items: CharData[]): CharData[] {
|
public splice(start: number, deleteCount: number, ...items: CharData[]): CharData[] {
|
||||||
const removed = this._data.splice(start, deleteCount, ...items);
|
const removed = this._data.splice(start, deleteCount, ...items);
|
||||||
this.length = this._data.length;
|
this.length = this._data.length;
|
||||||
// TODO: ref new, unref old
|
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** to be called when a line gets removed */
|
|
||||||
public release(): void {
|
|
||||||
// TODO: unref here
|
|
||||||
}
|
|
||||||
public toArray(): CharData[] {
|
|
||||||
return this._data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** insert n cells ch at pos, right cells are lost (stable length) */
|
/** insert n cells ch at pos, right cells are lost (stable length) */
|
||||||
public insertCells(pos: number, n: number, ch: CharData): void {
|
public insertCells(pos: number, n: number, ch: CharData): void {
|
||||||
while (n--) {
|
while (n--) {
|
||||||
|
|||||||
+17
-2
@@ -7,7 +7,6 @@ import { Terminal as PublicTerminal, ITerminalOptions as IPublicTerminalOptions,
|
|||||||
import { IColorSet, IRenderer } from './renderer/Types';
|
import { IColorSet, IRenderer } from './renderer/Types';
|
||||||
import { IMouseZoneManager } from './ui/Types';
|
import { IMouseZoneManager } from './ui/Types';
|
||||||
import { ICharset } from './core/Types';
|
import { ICharset } from './core/Types';
|
||||||
import { TerminalLine } from './TerminalLine';
|
|
||||||
|
|
||||||
export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean;
|
export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean;
|
||||||
|
|
||||||
@@ -272,7 +271,7 @@ export interface ITerminalOptions extends IPublicTerminalOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IBuffer {
|
export interface IBuffer {
|
||||||
readonly lines: ICircularList<TerminalLine>;
|
readonly lines: ICircularList<IBufferLine>;
|
||||||
ydisp: number;
|
ydisp: number;
|
||||||
ybase: number;
|
ybase: number;
|
||||||
y: number;
|
y: number;
|
||||||
@@ -511,3 +510,19 @@ export interface IEscapeSequenceParser extends IDisposable {
|
|||||||
setErrorHandler(callback: (state: IParsingState) => IParsingState): void;
|
setErrorHandler(callback: (state: IParsingState) => IParsingState): void;
|
||||||
clearErrorHandler(): void;
|
clearErrorHandler(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for a line in the terminal buffer.
|
||||||
|
*/
|
||||||
|
export interface IBufferLine {
|
||||||
|
length: number;
|
||||||
|
isWrapped: boolean;
|
||||||
|
get(index: number): CharData;
|
||||||
|
set(index: number, value: CharData): void;
|
||||||
|
pop(): CharData | undefined;
|
||||||
|
push(data: CharData): void;
|
||||||
|
splice(start: number, deleteCount: number, ...items: CharData[]): CharData[];
|
||||||
|
insertCells(pos: number, n: number, ch: CharData): void;
|
||||||
|
deleteCells(pos: number, n: number, fill: CharData): void;
|
||||||
|
replaceCells(start: number, end: number, fill: CharData): void;
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,9 +3,8 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ITerminal, ICircularList } from '../Types';
|
import { ITerminal, ICircularList, IBufferLine } from '../Types';
|
||||||
import { C0 } from '../common/data/EscapeSequences';
|
import { C0 } from '../common/data/EscapeSequences';
|
||||||
import { TerminalLine } from '../TerminalLine';
|
|
||||||
|
|
||||||
const enum Direction {
|
const enum Direction {
|
||||||
UP = 'A',
|
UP = 'A',
|
||||||
@@ -19,7 +18,7 @@ export class AltClickHandler {
|
|||||||
private _startCol: number;
|
private _startCol: number;
|
||||||
private _endRow: number;
|
private _endRow: number;
|
||||||
private _endCol: number;
|
private _endCol: number;
|
||||||
private _lines: ICircularList<TerminalLine>;
|
private _lines: ICircularList<IBufferLine>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _mouseEvent: MouseEvent,
|
private _mouseEvent: MouseEvent,
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ import { CircularList } from '../common/CircularList';
|
|||||||
|
|
||||||
import { ICharacterJoinerRegistry } from './Types';
|
import { ICharacterJoinerRegistry } from './Types';
|
||||||
import { CharacterJoinerRegistry } from './CharacterJoinerRegistry';
|
import { CharacterJoinerRegistry } from './CharacterJoinerRegistry';
|
||||||
import { TerminalLine } from '../TerminalLine';
|
import { BufferLine } from '../TerminalLine';
|
||||||
|
import { IBufferLine } from '../Types';
|
||||||
|
|
||||||
describe('CharacterJoinerRegistry', () => {
|
describe('CharacterJoinerRegistry', () => {
|
||||||
let registry: ICharacterJoinerRegistry;
|
let registry: ICharacterJoinerRegistry;
|
||||||
@@ -14,13 +15,13 @@ describe('CharacterJoinerRegistry', () => {
|
|||||||
const terminal = new MockTerminal();
|
const terminal = new MockTerminal();
|
||||||
terminal.cols = 16;
|
terminal.cols = 16;
|
||||||
terminal.buffer = new MockBuffer();
|
terminal.buffer = new MockBuffer();
|
||||||
const lines = new CircularList<TerminalLine>(7);
|
const lines = new CircularList<IBufferLine>(7);
|
||||||
lines.set(0, lineData([['a -> b -> c -> d']]));
|
lines.set(0, lineData([['a -> b -> c -> d']]));
|
||||||
lines.set(1, lineData([['a -> b => c -> d']]));
|
lines.set(1, lineData([['a -> b => c -> d']]));
|
||||||
lines.set(2, lineData([['a -> b -', 0xFFFFFFFF], ['> c -> d', 0]]));
|
lines.set(2, lineData([['a -> b -', 0xFFFFFFFF], ['> c -> d', 0]]));
|
||||||
|
|
||||||
lines.set(3, lineData([['no joined ranges']]));
|
lines.set(3, lineData([['no joined ranges']]));
|
||||||
lines.set(4, new TerminalLine());
|
lines.set(4, new BufferLine());
|
||||||
lines.set(5, lineData([['a', 0x11111111], [' -> b -> c -> '], ['d', 0x22222222]]));
|
lines.set(5, lineData([['a', 0x11111111], [' -> b -> c -> '], ['d', 0x22222222]]));
|
||||||
const line6 = lineData([['wi']]);
|
const line6 = lineData([['wi']]);
|
||||||
line6.push([0, '¥', 2, '¥'.charCodeAt(0)]);
|
line6.push([0, '¥', 2, '¥'.charCodeAt(0)]);
|
||||||
@@ -262,8 +263,8 @@ describe('CharacterJoinerRegistry', () => {
|
|||||||
|
|
||||||
type IPartialLineData = ([string] | [string, number]);
|
type IPartialLineData = ([string] | [string, number]);
|
||||||
|
|
||||||
function lineData(data: IPartialLineData[]): TerminalLine {
|
function lineData(data: IPartialLineData[]): IBufferLine {
|
||||||
const tline = new TerminalLine();
|
const tline = new BufferLine();
|
||||||
for (let i = 0; i < data.length; ++i) {
|
for (let i = 0; i < data.length; ++i) {
|
||||||
const line = data[i][0];
|
const line = data[i][0];
|
||||||
const attr = <number>(data[i][1] || 0);
|
const attr = <number>(data[i][1] || 0);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { CHAR_DATA_ATTR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer';
|
import { CHAR_DATA_ATTR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer';
|
||||||
import { ITerminal } from '../Types';
|
import { ITerminal, IBufferLine } from '../Types';
|
||||||
import { ICharacterJoinerRegistry, ICharacterJoiner } from './Types';
|
import { ICharacterJoinerRegistry, ICharacterJoiner } from './Types';
|
||||||
import { TerminalLine } from '../TerminalLine';
|
|
||||||
|
|
||||||
export class CharacterJoinerRegistry implements ICharacterJoinerRegistry {
|
export class CharacterJoinerRegistry implements ICharacterJoinerRegistry {
|
||||||
|
|
||||||
@@ -116,7 +115,7 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry {
|
|||||||
* @param startIndex Start position of the range to search in the string (inclusive)
|
* @param startIndex Start position of the range to search in the string (inclusive)
|
||||||
* @param endIndex End position of the range to search in the string (exclusive)
|
* @param endIndex End position of the range to search in the string (exclusive)
|
||||||
*/
|
*/
|
||||||
private _getJoinedRanges(line: string, startIndex: number, endIndex: number, lineData: TerminalLine, startCol: number): [number, number][] {
|
private _getJoinedRanges(line: string, startIndex: number, endIndex: number, lineData: IBufferLine, startCol: number): [number, number][] {
|
||||||
const text = line.substring(startIndex, endIndex);
|
const text = line.substring(startIndex, endIndex);
|
||||||
// At this point we already know that there is at least one joiner so
|
// At this point we already know that there is at least one joiner so
|
||||||
// we can just pull its value and assign it directly rather than
|
// we can just pull its value and assign it directly rather than
|
||||||
@@ -141,7 +140,7 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry {
|
|||||||
* @param line Cell data for the relevant line in the terminal
|
* @param line Cell data for the relevant line in the terminal
|
||||||
* @param startCol Offset within the line to start from
|
* @param startCol Offset within the line to start from
|
||||||
*/
|
*/
|
||||||
private _stringRangesToCellRanges(ranges: [number, number][], line: TerminalLine, startCol: number): void {
|
private _stringRangesToCellRanges(ranges: [number, number][], line: IBufferLine, startCol: number): void {
|
||||||
let currentRangeIndex = 0;
|
let currentRangeIndex = 0;
|
||||||
let currentRangeStarted = false;
|
let currentRangeStarted = false;
|
||||||
let currentStringIndex = 0;
|
let currentStringIndex = 0;
|
||||||
|
|||||||
@@ -8,12 +8,13 @@ import { assert } from 'chai';
|
|||||||
import { DomRendererRowFactory } from './DomRendererRowFactory';
|
import { DomRendererRowFactory } from './DomRendererRowFactory';
|
||||||
import { DEFAULT_ATTR, NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR } from '../../Buffer';
|
import { DEFAULT_ATTR, NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR } from '../../Buffer';
|
||||||
import { FLAGS } from '../Types';
|
import { FLAGS } from '../Types';
|
||||||
import { TerminalLine } from '../../TerminalLine';
|
import { BufferLine } from '../../TerminalLine';
|
||||||
|
import { IBufferLine } from '../../Types';
|
||||||
|
|
||||||
describe('DomRendererRowFactory', () => {
|
describe('DomRendererRowFactory', () => {
|
||||||
let dom: jsdom.JSDOM;
|
let dom: jsdom.JSDOM;
|
||||||
let rowFactory: DomRendererRowFactory;
|
let rowFactory: DomRendererRowFactory;
|
||||||
let lineData: TerminalLine;
|
let lineData: IBufferLine;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
dom = new jsdom.JSDOM('');
|
dom = new jsdom.JSDOM('');
|
||||||
@@ -146,8 +147,8 @@ describe('DomRendererRowFactory', () => {
|
|||||||
return element.innerHTML;
|
return element.innerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createEmptyLineData(cols: number): TerminalLine {
|
function createEmptyLineData(cols: number): IBufferLine {
|
||||||
const lineData = new TerminalLine();
|
const lineData = new BufferLine();
|
||||||
for (let i = 0; i < cols; i++) {
|
for (let i = 0; i < cols; i++) {
|
||||||
lineData.push([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]);
|
lineData.push([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_ATTR_INDEX, CHAR_DATA_WIDTH_INDEX } from '../../Buffer';
|
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_ATTR_INDEX, CHAR_DATA_WIDTH_INDEX } from '../../Buffer';
|
||||||
import { FLAGS } from '../Types';
|
import { FLAGS } from '../Types';
|
||||||
import { TerminalLine } from '../../TerminalLine';
|
import { IBufferLine } from '../../Types';
|
||||||
|
|
||||||
export const BOLD_CLASS = 'xterm-bold';
|
export const BOLD_CLASS = 'xterm-bold';
|
||||||
export const ITALIC_CLASS = 'xterm-italic';
|
export const ITALIC_CLASS = 'xterm-italic';
|
||||||
@@ -17,7 +17,7 @@ export class DomRendererRowFactory {
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public createRow(lineData: TerminalLine, isCursorRow: boolean, cursorX: number, cellWidth: number, cols: number): DocumentFragment {
|
public createRow(lineData: IBufferLine, isCursorRow: boolean, cursorX: number, cellWidth: number, cols: number): DocumentFragment {
|
||||||
const fragment = this._document.createDocumentFragment();
|
const fragment = this._document.createDocumentFragment();
|
||||||
let colCount = 0;
|
let colCount = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { IColorSet, IRenderer, IRenderDimensions, IColorManager } from '../renderer/Types';
|
import { IColorSet, IRenderer, IRenderDimensions, IColorManager } from '../renderer/Types';
|
||||||
import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, ICircularList, ILinkifier, IMouseHelper, ILinkMatcherOptions, XtermListener, CharacterJoinerHandler } from '../Types';
|
import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, ICircularList, ILinkifier, IMouseHelper, ILinkMatcherOptions, XtermListener, CharacterJoinerHandler, IBufferLine } from '../Types';
|
||||||
import { Buffer } from '../Buffer';
|
import { Buffer } from '../Buffer';
|
||||||
import * as Browser from '../shared/utils/Browser';
|
import * as Browser from '../shared/utils/Browser';
|
||||||
import { ITheme, IDisposable, IMarker } from 'xterm';
|
import { ITheme, IDisposable, IMarker } from 'xterm';
|
||||||
import { TerminalLine } from '../TerminalLine';
|
|
||||||
|
|
||||||
export class MockTerminal implements ITerminal {
|
export class MockTerminal implements ITerminal {
|
||||||
markers: IMarker[];
|
markers: IMarker[];
|
||||||
@@ -285,7 +284,7 @@ export class MockInputHandlingTerminal implements IInputHandlingTerminal {
|
|||||||
|
|
||||||
export class MockBuffer implements IBuffer {
|
export class MockBuffer implements IBuffer {
|
||||||
isCursorInViewport: boolean;
|
isCursorInViewport: boolean;
|
||||||
lines: ICircularList<TerminalLine>;
|
lines: ICircularList<IBufferLine>;
|
||||||
ydisp: number;
|
ydisp: number;
|
||||||
ybase: number;
|
ybase: number;
|
||||||
hasScrollback: boolean;
|
hasScrollback: boolean;
|
||||||
@@ -308,7 +307,7 @@ export class MockBuffer implements IBuffer {
|
|||||||
prevStop(x?: number): number {
|
prevStop(x?: number): number {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
setLines(lines: ICircularList<TerminalLine>): void {
|
setLines(lines: ICircularList<IBufferLine>): void {
|
||||||
this.lines = lines;
|
this.lines = lines;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user