Created
August 28, 2019 18:53
-
-
Save jerch/cfe4360e7f23df8bc7189c3761bd13f5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Terminal, ITerminalAddon, IBufferCell } from 'xterm'; | |
export class SerializeAddon implements ITerminalAddon { | |
private _terminal: Terminal|undefined = undefined; | |
public dispose(): void {} | |
public activate(terminal: Terminal): void { | |
this._terminal = terminal; | |
} | |
private _extractAttributes(oldCell: IBufferCell, newCell: IBufferCell): string { | |
if (oldCell.equalAttibutes(newCell)) { | |
return ''; | |
} | |
const switches: number[] = []; | |
// flags | |
if (!oldCell.equalFlags(newCell)) { | |
if (oldCell.flags.bold !== newCell.flags.bold) switches.push(newCell.flags.bold ? 1 : 22); | |
if (oldCell.flags.underline !== newCell.flags.underline) switches.push(newCell.flags.underline ? 4 : 24); | |
if (oldCell.flags.inverse !== newCell.flags.inverse) switches.push(newCell.flags.inverse ? 7 : 27); | |
if (oldCell.flags.invisible !== newCell.flags.invisible) switches.push(newCell.flags.invisible ? 8 : 28); | |
if (oldCell.flags.blink !== newCell.flags.blink) switches.push(newCell.flags.blink ? 5 : 25); | |
if (oldCell.flags.italic !== newCell.flags.italic) switches.push(newCell.flags.italic ? 3 : 23); | |
if (oldCell.flags.dim !== newCell.flags.dim) switches.push(newCell.flags.dim ? 2 : 22); | |
} | |
// colors | |
if (!oldCell.equalFg(newCell)) { | |
switch (newCell.fg.colorMode) { | |
case 'RGB': | |
switches.push(38); | |
switches.push(2); | |
switches.push((newCell.fg.color >> 16) & 0xFF); | |
switches.push((newCell.fg.color >> 8) & 0xFF); | |
switches.push(newCell.fg.color & 0xFF); | |
break; | |
case 'P256': | |
switches.push(38); | |
switches.push(5); | |
switches.push(newCell.fg.color); | |
break; | |
case 'P16': | |
switches.push(newCell.fg.color & 8 ? 90 + (newCell.fg.color & 7) : 30 + (newCell.fg.color & 7)); | |
break; | |
default: | |
switches.push(39); | |
} | |
} | |
if (!oldCell.equalBg(newCell)) { | |
switch (newCell.bg.colorMode) { | |
case 'RGB': | |
switches.push(48); | |
switches.push(2); | |
switches.push((newCell.bg.color >> 16) & 0xFF); | |
switches.push((newCell.bg.color >> 8) & 0xFF); | |
switches.push(newCell.bg.color & 0xFF); | |
break; | |
case 'P256': | |
switches.push(48); | |
switches.push(5); | |
switches.push(newCell.bg.color); | |
break; | |
case 'P16': | |
switches.push(newCell.bg.color & 8 ? 100 + (newCell.bg.color & 7) : 40 + (newCell.bg.color & 7)); | |
break; | |
default: | |
switches.push(49); | |
} | |
} | |
if (switches.length) { | |
return `\x1b[${switches.join(';')}m`; | |
} | |
return ''; | |
} | |
public serialize(): string { | |
if (!this._terminal) { | |
return ''; | |
} | |
// cells for ref style usage | |
// we need two of them to flip between old and new cell | |
const cell1 = this._terminal.buffer.getNullCell(); | |
const cell2 = this._terminal.buffer.getNullCell(); | |
let oldCell = cell1; | |
const result: string[] = []; | |
const end = this._terminal.buffer.length; | |
for (let y = 0; y < end; ++y) { | |
const sLine: string[] = []; | |
const line = this._terminal.buffer.getLine(y); | |
if (!line) { | |
continue; | |
} | |
const length = this._terminal.cols; | |
for (let x = 0; x < length;) { | |
const newCell = line.getCell(x, oldCell === cell1 ? cell2 : cell1); | |
if (!newCell) { | |
continue; | |
} | |
const diff = this._extractAttributes(oldCell, newCell); | |
if (diff) { | |
sLine.push(diff); | |
oldCell = newCell; | |
} | |
sLine.push(newCell.char || ' '); | |
x += newCell.width || 1; // always advance by 1! | |
} | |
result.push(sLine.join('')); | |
} | |
return result.join('\r\n'); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment