Skip to content

Commit

Permalink
Merge pull request #2369 from JavaCS3/feat/serialize-addon
Browse files Browse the repository at this point in the history
Add foreground/background color support for SerializeAddon
  • Loading branch information
Tyriar authored Feb 3, 2020
2 parents 83e582b + cf33f7c commit 1d8e242
Show file tree
Hide file tree
Showing 21 changed files with 719 additions and 116 deletions.
4 changes: 2 additions & 2 deletions addons/xterm-addon-search/src/SearchAddon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,13 +320,13 @@ export class SearchAddon implements ITerminalAddon {
break;
}
// Adjust the searchIndex to normalize emoji into single chars
const char = cell.char;
const char = cell.getChars();
if (char.length > 1) {
resultIndex -= char.length - 1;
}
// Adjust the searchIndex for empty characters following wide unicode
// chars (eg. CJK)
const charWidth = cell.width;
const charWidth = cell.getWidth();
if (charWidth === 0) {
resultIndex++;
}
Expand Down
1 change: 1 addition & 0 deletions addons/xterm-addon-serialize/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
lib
node_modules
out-benchmark
42 changes: 42 additions & 0 deletions addons/xterm-addon-serialize/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
## xterm-addon-serialize

An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables xterm.js to serialize a terminal framebuffer into string or html. This addon requires xterm.js v4+.

⚠️ This is an experimental addon that is still under construction ⚠️

### Install

```bash
npm install --save xterm-addon-serialize
```

### Usage

```ts
import { Terminal } from "xterm";
import { SerializeAddon } from "xterm-addon-serialize";

const terminal = new Terminal();
const serializeAddon = new SerializeAddon();
terminal.loadAddon(serializeAddon);

terminal.write("something...", () => {
console.log(serializeAddon.serialize());
});
```

See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts) for more advanced usage.

### Benchmark

⚠️ Ensure you have `lolcat`, `hexdump` programs installed in your computer

```shell
$ git clone https://github.com/xtermjs/xterm.js.git
$ cd xterm.js
$ yarn
$ cd addons/xterm-addon-serialize
$ yarn benchmark && yarn benchmark-baseline
$ # change some code in `xterm-addon-serialize`
$ yarn benchmark-eval
```
65 changes: 65 additions & 0 deletions addons/xterm-addon-serialize/benchmark/SerializeAddon.benchmark.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/

import { perfContext, before, ThroughputRuntimeCase } from 'xterm-benchmark';

import { spawn } from 'node-pty';
import { Utf8ToUtf32, stringFromCodePoint } from 'common/input/TextDecoder';
import { Terminal } from 'public/Terminal';
import { SerializeAddon } from 'SerializeAddon';

class TestTerminal extends Terminal {
writeSync(data: string): void {
(<any>this)._core.writeSync(data);
}
}

perfContext('Terminal: sh -c "dd if=/dev/random count=40 bs=1k | hexdump | lolcat -f"', () => {
let content = '';
let contentUtf8: Uint8Array;

before(async () => {
const p = spawn('sh', ['-c', 'dd if=/dev/random count=40 bs=1k | hexdump | lolcat -f'], {
name: 'xterm-256color',
cols: 80,
rows: 25,
cwd: process.env.HOME,
env: process.env,
encoding: (null as unknown as string) // needs to be fixed in node-pty
});
const chunks: Buffer[] = [];
let length = 0;
p.on('data', data => {
chunks.push(data as unknown as Buffer);
length += data.length;
});
await new Promise(resolve => p.on('exit', () => resolve()));
contentUtf8 = Buffer.concat(chunks, length);
// translate to content string
const buffer = new Uint32Array(contentUtf8.length);
const decoder = new Utf8ToUtf32();
const codepoints = decoder.decode(contentUtf8, buffer);
for (let i = 0; i < codepoints; ++i) {
content += stringFromCodePoint(buffer[i]);
// peek into content to force flat repr in v8
if (!(i % 10000000)) {
content[i];
}
}
});

perfContext('serialize', () => {
let terminal: TestTerminal;
const serializeAddon = new SerializeAddon();
before(() => {
terminal = new TestTerminal({ cols: 80, rows: 25, scrollback: 5000 });
serializeAddon.activate(terminal);
terminal.writeSync(content);
});
new ThroughputRuntimeCase('', () => {
return { payloadSize: serializeAddon.serialize().length };
}, { fork: false }).showAverageThroughput();
});
});
19 changes: 19 additions & 0 deletions addons/xterm-addon-serialize/benchmark/benchmark.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"APP_PATH": ".benchmark",
"evalConfig": {
"tolerance": {
"*": [0.75, 1.5],
"*.dev": [0.01, 1.5],
"*.cv": [0.01, 1.5],
"EscapeSequenceParser.benchmark.js.*.averageThroughput.mean": [0.9, 5]
},
"skip": [
"*.median",
"*.runs",
"*.dev",
"*.cv",
"EscapeSequenceParser.benchmark.js.*.averageRuntime",
"Terminal.benchmark.js.*.averageRuntime"
]
}
}
25 changes: 25 additions & 0 deletions addons/xterm-addon-serialize/benchmark/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"compilerOptions": {
"lib": ["dom", "es6"],
"outDir": "../out-benchmark",
"types": ["../../../node_modules/@types/node"],
"moduleResolution": "node",
"strict": false,
"target": "es2015",
"module": "commonjs",
"baseUrl": ".",
"paths": {
"common/*": ["../../../src/common/*"],
"browser/*": ["../../../src/browser/*"],
"public/*": ["../../../src/public/*"],
"Terminal": ["../../../src/Terminal"],
"SerializeAddon": ["../src/SerializeAddon"]
}
},
"include": ["../**/*", "../../../typings/xterm.d.ts", "../../../out/**/*"],
"exclude": ["../../../**/*test.ts", "../../**/*api.ts"],
"references": [
{ "path": "../../../src/common" },
{ "path": "../../../src/browser" }
]
}
5 changes: 4 additions & 1 deletion addons/xterm-addon-serialize/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
"build": "../../node_modules/.bin/tsc -p src",
"prepackage": "npm run build",
"package": "../../node_modules/.bin/webpack",
"prepublishOnly": "npm run package"
"prepublishOnly": "npm run package",
"benchmark": "NODE_PATH=../../out:./out:./out-benchmark/ ../../node_modules/.bin/xterm-benchmark -r 5 -c benchmark/benchmark.json",
"benchmark-baseline": "NODE_PATH=../../out:./out:./out-benchmark/ ../../node_modules/.bin/xterm-benchmark -r 5 -c benchmark/benchmark.json --baseline out-benchmark/addons/xterm-addon-serialize/benchmark/*benchmark.js",
"benchmark-eval": "NODE_PATH=../../out:./out:./out-benchmark/ ../../node_modules/.bin/xterm-benchmark -r 5 -c benchmark/benchmark.json --eval out-benchmark/addons/xterm-addon-serialize/benchmark/*benchmark.js"
},
"peerDependencies": {
"xterm": "^3.14.0"
Expand Down
Loading

0 comments on commit 1d8e242

Please sign in to comment.