mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
refactor SerializeAddon: use public api as much as possible
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
+30
-5
@@ -5,8 +5,9 @@
|
||||
|
||||
import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ISelectionPosition, IBuffer as IBufferApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi } from 'xterm';
|
||||
import { ITerminal } from '../Types';
|
||||
import { IBufferLine } from 'common/Types';
|
||||
import { IBufferLine, ICellData } from 'common/Types';
|
||||
import { IBuffer } from 'common/buffer/Types';
|
||||
import { CellData } from 'common/buffer/CellData';
|
||||
import { Terminal as TerminalCore } from '../Terminal';
|
||||
import * as Strings from '../browser/LocalizableStrings';
|
||||
import { IEvent } from 'common/EventEmitter';
|
||||
@@ -204,11 +205,15 @@ class BufferLineApiView implements IBufferLineApi {
|
||||
constructor(private _line: IBufferLine) {}
|
||||
|
||||
public get isWrapped(): boolean { return this._line.isWrapped; }
|
||||
public get length(): number { return this._line.length; }
|
||||
public getCell(x: number): IBufferCellApi | undefined {
|
||||
if (x < 0 || x >= this._line.length) {
|
||||
return undefined;
|
||||
}
|
||||
return new BufferCellApiView(this._line, x);
|
||||
|
||||
const cell = new CellData();
|
||||
this._line.loadCell(x, cell);
|
||||
return new BufferCellApiView(cell);
|
||||
}
|
||||
public translateToString(trimRight?: boolean, startColumn?: number, endColumn?: number): string {
|
||||
return this._line.translateToString(trimRight, startColumn, endColumn);
|
||||
@@ -216,7 +221,27 @@ class BufferLineApiView implements IBufferLineApi {
|
||||
}
|
||||
|
||||
class BufferCellApiView implements IBufferCellApi {
|
||||
constructor(private _line: IBufferLine, private _x: number) {}
|
||||
public get char(): string { return this._line.getString(this._x); }
|
||||
public get width(): number { return this._line.getWidth(this._x); }
|
||||
constructor(private _cell: ICellData) {}
|
||||
|
||||
public get fg(): number { return this._cell.fg; }
|
||||
public get bg(): number { return this._cell.bg; }
|
||||
public get char(): string { return this._cell.getChars(); }
|
||||
public get width(): number { return this._cell.getWidth(); }
|
||||
public get isInverse(): number { return this._cell.isInverse(); }
|
||||
public get isBold(): number { return this._cell.isBold(); }
|
||||
public get isUnderline(): number { return this._cell.isUnderline(); }
|
||||
public get isBlink(): number { return this._cell.isBlink(); }
|
||||
public get isInvisible(): number { return this._cell.isInvisible(); }
|
||||
public get isItalic(): number { return this._cell.isItalic(); }
|
||||
public get isDim(): number { return this._cell.isDim(); }
|
||||
public get fgColorMode(): number { return this._cell.getFgColorMode(); }
|
||||
public get bgColorMode(): number { return this._cell.getBgColorMode(); }
|
||||
public get isFgRGB(): boolean { return this._cell.isFgRGB(); }
|
||||
public get isBgRGB(): boolean { return this._cell.isBgRGB(); }
|
||||
public get isFgPalette(): boolean { return this._cell.isFgPalette(); }
|
||||
public get isBgPalette(): boolean { return this._cell.isBgPalette(); }
|
||||
public get isFgDefault(): boolean { return this._cell.isFgDefault(); }
|
||||
public get isBgDefault(): boolean { return this._cell.isBgDefault(); }
|
||||
public get fgColor(): number { return this._cell.getFgColor(); }
|
||||
public get bgColor(): number { return this._cell.getBgColor(); }
|
||||
}
|
||||
|
||||
Vendored
+27
@@ -910,6 +910,7 @@ declare module 'xterm' {
|
||||
* Whether the line is wrapped from the previous line.
|
||||
*/
|
||||
readonly isWrapped: boolean;
|
||||
readonly length: number;
|
||||
|
||||
/**
|
||||
* Gets a cell from the line, or undefined if the line index does not exist.
|
||||
@@ -937,6 +938,9 @@ declare module 'xterm' {
|
||||
* Represents a single cell in the terminal's buffer.
|
||||
*/
|
||||
interface IBufferCell {
|
||||
readonly fg: number;
|
||||
readonly bg: number;
|
||||
|
||||
/**
|
||||
* The character within the cell.
|
||||
*/
|
||||
@@ -950,5 +954,28 @@ declare module 'xterm' {
|
||||
* - This is `0` for cells immediately following cells with a width of `2`.
|
||||
*/
|
||||
readonly width: number;
|
||||
|
||||
// flags
|
||||
readonly isInverse: number;
|
||||
readonly isBold: number;
|
||||
readonly isUnderline: number;
|
||||
readonly isBlink: number;
|
||||
readonly isInvisible: number;
|
||||
readonly isItalic: number;
|
||||
readonly isDim: number;
|
||||
|
||||
// color modes
|
||||
readonly fgColorMode: number;
|
||||
readonly bgColorMode: number;
|
||||
readonly isFgRGB: boolean;
|
||||
readonly isBgRGB: boolean;
|
||||
readonly isFgPalette: boolean;
|
||||
readonly isBgPalette: boolean;
|
||||
readonly isFgDefault: boolean;
|
||||
readonly isBgDefault: boolean;
|
||||
|
||||
// colors
|
||||
readonly fgColor: number;
|
||||
readonly bgColor: number;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user