refactor SerializeAddon: use public api as much as possible

This commit is contained in:
javacs3
2019-11-21 20:41:47 +08:00
parent 6710c13cc2
commit 3cba961dad
3 changed files with 123 additions and 41 deletions
@@ -3,10 +3,7 @@
* @license MIT
*/
import { Terminal, ITerminalAddon } from 'xterm';
import { ICellData } from 'common/Types';
import { CellData } from 'common/buffer/CellData';
import { IBuffer } from 'common/buffer/Types';
import { Terminal, ITerminalAddon, IBuffer, IBufferCell } from 'xterm';
import { Attributes, FgFlags, BgFlags } from 'common/buffer/Constants';
function crop(value: number | undefined, low: number, high: number, initial: number): number {
@@ -16,24 +13,50 @@ function crop(value: number | undefined, low: number, high: number, initial: num
return Math.max(low, Math.min(value, high));
}
class NullBufferCell implements IBufferCell {
fg: number = 0; bg: number = 0;
char: string = '';
width: number = 0;
isInverse: number = 0;
isBold: number = 0;
isUnderline: number = 0;
isBlink: number = 0;
isInvisible: number = 0;
isItalic: number = 0;
isDim: number = 0;
fgColorMode: number = 0;
bgColorMode: number = 0;
isFgRGB: boolean = false;
isBgRGB: boolean = false;
isFgPalette: boolean = false;
isBgPalette: boolean = false;
isFgDefault: boolean = false;
isBgDefault: boolean = false;
fgColor: number = 0;
bgColor: number = 0;
}
class BaseSerializeHandler {
constructor(private _buffer: IBuffer) { }
serialize(startRow: number, endRow: number): string {
let oldCell = new CellData();
let oldCell: IBufferCell = new NullBufferCell();
this._serializeStart(endRow - startRow);
for (let row = startRow; row < endRow; row++) {
const line = this._buffer.lines.get(row);
const line = this._buffer.getLine(row);
this._lineStart(row);
if (line) {
for (let col = 0; col < line.length; col++) {
const cell = new CellData();
const cell = line.getCell(col);
line.loadCell(col, cell);
if (!cell) {
console.warn(`Can't get cell at row=${row}, col=${col}`);
continue;
}
if (oldCell.fg !== cell.fg) {
this._fgChanged(cell, oldCell, row, col);
@@ -41,7 +64,6 @@ class BaseSerializeHandler {
if (oldCell.bg !== cell.bg) {
this._bgChanged(cell, oldCell, row, col);
}
this._cellChanged(cell, oldCell, row, col);
oldCell = cell;
@@ -56,11 +78,11 @@ class BaseSerializeHandler {
return this._serializeFinished();
}
protected _cellChanged(cell: ICellData, oldCell: ICellData, row: number, col: number): void { }
protected _cellChanged(cell: IBufferCell, oldCell: IBufferCell, row: number, col: number): void { }
protected _fgChanged(cell: ICellData, oldCell: ICellData, row: number, col: number): void { }
protected _fgChanged(cell: IBufferCell, oldCell: IBufferCell, row: number, col: number): void { }
protected _bgChanged(cell: ICellData, oldCell: ICellData, row: number, col: number): void { }
protected _bgChanged(cell: IBufferCell, oldCell: IBufferCell, row: number, col: number): void { }
protected _lineStart(row: number): void { }
@@ -95,6 +117,14 @@ function bgColor256to16(c: number): number {
return -1;
}
function hex2rgb(value: number): [number, number, number] {
return [
value >>> Attributes.RED_SHIFT & 255,
value >>> Attributes.GREEN_SHIFT & 255,
value & 255
];
}
class StringSerializeHandler extends BaseSerializeHandler {
private _rowIndex: number = 0;
private _allRows: string[] = new Array<string>();
@@ -114,7 +144,7 @@ class StringSerializeHandler extends BaseSerializeHandler {
this._currentRow = '';
}
protected _fgChanged(cell: ICellData, oldCell: ICellData, row: number, col: number): void {
protected _fgChanged(cell: IBufferCell, oldCell: IBufferCell, row: number, col: number): void {
const fgFlagsChanged = (cell.fg ^ oldCell.fg) & FG_FM_MASK;
const fgColorChanged = (cell.fg ^ oldCell.fg) & COLOR_MASK;
const sgrSeq = this._sgrSeq;
@@ -125,40 +155,40 @@ class StringSerializeHandler extends BaseSerializeHandler {
if (fgFlagsChanged) {
if (fgFlagsChanged & FgFlags.INVERSE) {
sgrSeq.push(cell.isInverse() ? '7' : '27');
sgrSeq.push(cell.isInverse ? '7' : '27');
}
if (fgFlagsChanged & FgFlags.BOLD) {
sgrSeq.push(cell.isBold() ? '1' : '22');
sgrSeq.push(cell.isBold ? '1' : '22');
}
if (fgFlagsChanged & FgFlags.UNDERLINE) {
sgrSeq.push(cell.isUnderline() ? '4' : '24');
sgrSeq.push(cell.isUnderline ? '4' : '24');
}
if (fgFlagsChanged & FgFlags.BLINK) {
sgrSeq.push(cell.isBlink() ? '5' : '25');
sgrSeq.push(cell.isBlink ? '5' : '25');
}
if (fgFlagsChanged & FgFlags.INVISIBLE) {
sgrSeq.push(cell.isInvisible() ? '8' : '28');
sgrSeq.push(cell.isInvisible ? '8' : '28');
}
}
if (fgColorChanged) {
const fgColor = cell.getFgColor();
const fgColor = cell.fgColor;
if (cell.isFgDefault()) {
if (cell.isFgDefault) {
sgrSeq.push('39');
} else if (cell.isFgPalette()) {
switch (cell.getFgColorMode()) {
} else if (cell.isFgPalette) {
switch (cell.fgColorMode) {
case Attributes.CM_P16: sgrSeq.push(fgColor256to16(fgColor).toString()); break;
case Attributes.CM_P256: sgrSeq.push(`38;5;${fgColor}`); break;
}
} else if (cell.isFgRGB()) {
const [r, g, b] = CellData.toColorRGB(fgColor);
} else if (cell.isFgRGB) {
const [r, g, b] = hex2rgb(fgColor);
sgrSeq.push(`38;2;${r};${g};${b}`);
}
}
}
protected _bgChanged(cell: ICellData, oldCell: ICellData, row: number, col: number): void {
protected _bgChanged(cell: IBufferCell, oldCell: IBufferCell, row: number, col: number): void {
const bgFlagsChanged = (cell.bg ^ oldCell.bg) & BG_FM_MASK;
const bgColorChanged = (cell.bg ^ oldCell.bg) & COLOR_MASK;
const sgrSeq = this._sgrSeq;
@@ -169,31 +199,31 @@ class StringSerializeHandler extends BaseSerializeHandler {
if (bgFlagsChanged) {
if (bgFlagsChanged & BgFlags.ITALIC) {
sgrSeq.push(cell.isItalic() ? '3' : '23');
sgrSeq.push(cell.isItalic ? '3' : '23');
}
if (bgFlagsChanged & BgFlags.DIM) {
sgrSeq.push(cell.isDim() ? '2' : '22');
sgrSeq.push(cell.isDim ? '2' : '22');
}
}
if (bgColorChanged) {
const bgColor = cell.getBgColor();
const bgColor = cell.bgColor;
if (cell.isBgDefault()) {
if (cell.isBgDefault) {
sgrSeq.push('49');
} else if (cell.isBgPalette()) {
switch (cell.getBgColorMode()) {
} else if (cell.isBgPalette) {
switch (cell.bgColorMode) {
case Attributes.CM_P16: sgrSeq.push(bgColor256to16(bgColor).toString()); break;
case Attributes.CM_P256: sgrSeq.push(`48;5;${bgColor}`); break;
}
} else if (cell.isFgRGB()) {
const [r, g, b] = CellData.toColorRGB(bgColor);
} else if (cell.isFgRGB) {
const [r, g, b] = hex2rgb(bgColor);
sgrSeq.push(`48;2;${r};${g};${b}`);
}
}
}
protected _cellChanged(cell: ICellData, oldCell: ICellData, row: number, col: number): void {
protected _cellChanged(cell: IBufferCell, oldCell: IBufferCell, row: number, col: number): void {
const fgChanged = cell.fg !== oldCell.fg;
const bgChanged = cell.bg !== oldCell.bg;
const isfgBgNormal = (cell.fg === 0) && (cell.bg === 0);
@@ -207,7 +237,7 @@ class StringSerializeHandler extends BaseSerializeHandler {
this._sgrSeq = [];
}
this._currentRow += cell.getChars();
this._currentRow += cell.char;
}
protected _serializeFinished(): string {
@@ -241,7 +271,7 @@ export class SerializeAddon implements ITerminalAddon {
}
const maxRows = this._terminal.rows;
const handler = new StringSerializeHandler((<any>this._terminal)._core.buffer);
const handler = new StringSerializeHandler(this._terminal.buffer);
rows = crop(rows, 0, maxRows, maxRows);