extract @vt entries from docs
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
/**
|
||||
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*
|
||||
* Script to extract vt features documented in docstrings.
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const Mustache = require('mustache');
|
||||
|
||||
/**
|
||||
* regexp to fetch all comments
|
||||
* Fetches all multiline comments and single lines containing '// @vt:'.
|
||||
*/
|
||||
const REX_COMMENTS = /^\s*?[/][*][*]([\s\S]*?)[*][/]|^\s*?\/\/ ([@]vt[:].*?)$/mug;
|
||||
|
||||
// expected - "@vt: type name "sequence" "short description"
|
||||
/**
|
||||
* regexp to parse the @vt line
|
||||
* expected data - "@vt: <status> <kind> <mnemonic> <"name"> "<sequence>" "<short description>"
|
||||
*/
|
||||
const REX_VT_LINE = /^[@]vt\:\s*(\w+)\s*(\w+)\s*(\w+)\s*"(.*?)"\s*"(.*?)"\s*"(.*?)".*$/;
|
||||
|
||||
// known vt command types
|
||||
const TYPES = [
|
||||
'C0',
|
||||
'C1',
|
||||
'ESC',
|
||||
'CSI',
|
||||
'DCS',
|
||||
'OSC',
|
||||
'APC',
|
||||
'PM',
|
||||
'SOS'
|
||||
];
|
||||
|
||||
const MARKDOWN_TMPL = `
|
||||
# Supported VT features by xterm.js
|
||||
Version: {{version}}
|
||||
### C0
|
||||
|
||||
| Mnemonic | Name | Sequence | Short Description | Status |
|
||||
| -------- | ---- | -------- | ----------------- | ------ |
|
||||
{{#C0}}
|
||||
| {{mnemonic}} | {{name}} | \`{{sequence}}\` | {{shortDescription}} | {{status}} |
|
||||
{{/C0}}
|
||||
|
||||
|
||||
### C1
|
||||
|
||||
| Mnemonic | Name | Sequence | Short Description | Status |
|
||||
| -------- | ---- | -------- | ----------------- | ------ |
|
||||
{{#C1}}
|
||||
| {{mnemonic}} | {{name}} | \`{{sequence}}\` | {{shortDescription}} | {{status}} |
|
||||
{{/C1}}
|
||||
|
||||
|
||||
### CSI
|
||||
|
||||
| Mnemonic | Name | Sequence | Short Description | Status |
|
||||
| -------- | ---- | -------- | ----------------- | ------ |
|
||||
{{#CSI}}
|
||||
| {{mnemonic}} | {{name}} | \`{{sequence}}\` | {{shortDescription}} | {{status}} |
|
||||
{{/CSI}}
|
||||
|
||||
|
||||
### DCS
|
||||
|
||||
| Mnemonic | Name | Sequence | Short Description | Status |
|
||||
| -------- | ---- | -------- | ----------------- | ------ |
|
||||
{{#DCS}}
|
||||
| {{mnemonic}} | {{name}} | \`{{sequence}}\` | {{shortDescription}} | {{status}} |
|
||||
{{/DCS}}
|
||||
|
||||
|
||||
### ESC
|
||||
|
||||
| Mnemonic | Name | Sequence | Short Description | Status |
|
||||
| -------- | ---- | -------- | ----------------- | ------ |
|
||||
{{#ESC}}
|
||||
| {{mnemonic}} | {{name}} | \`{{sequence}}\` | {{shortDescription}} | {{status}} |
|
||||
{{/ESC}}
|
||||
|
||||
|
||||
### OSC
|
||||
|
||||
| Mnemonic | Name | Sequence | Short Description | Status |
|
||||
| -------- | ---- | -------- | ----------------- | ------ |
|
||||
{{#OSC}}
|
||||
| {{mnemonic}} | {{name}} | \`{{sequence}}\` | {{shortDescription}} | {{status}} |
|
||||
{{/OSC}}
|
||||
`
|
||||
|
||||
function parseMultiLine(filename, s) {
|
||||
if (!~s.indexOf('@vt:')) {
|
||||
return;
|
||||
}
|
||||
const lines = s.split('\n').map(el => el.trim().replace(/[*]/, '').replace(/\s/, ''));
|
||||
let grabLine = false;
|
||||
const longDescription = [];
|
||||
let feature;
|
||||
for (const line of lines) {
|
||||
if (grabLine) {
|
||||
if (!line) {
|
||||
break;
|
||||
}
|
||||
longDescription.push(line);
|
||||
}
|
||||
if (~line.indexOf('@vt:')) {
|
||||
feature = parseSingleLine(filename, line);
|
||||
grabLine = true;
|
||||
}
|
||||
}
|
||||
if (feature) {
|
||||
feature.longDescription = longDescription;
|
||||
return feature;
|
||||
}
|
||||
}
|
||||
|
||||
function parseSingleLine(filename, s) {
|
||||
const line = s.trim();
|
||||
const match = line.match(REX_VT_LINE);
|
||||
if (match !== null) {
|
||||
if (!~TYPES.indexOf(match[2])) {
|
||||
throw new Error(`unkown vt-command type "${match[2]}" specified in "${filename}"`);
|
||||
}
|
||||
return {
|
||||
status: match[1],
|
||||
type: match[2],
|
||||
mnemonic: match[3],
|
||||
name: match[4],
|
||||
sequence: match[5],
|
||||
shortDescription: match[6],
|
||||
longDescription: [],
|
||||
source: filename
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function postProcessData(features) {
|
||||
const featureTable = {};
|
||||
for (const feature of features) {
|
||||
if (featureTable[feature.type] === undefined) {
|
||||
featureTable[feature.type] = [];
|
||||
}
|
||||
featureTable[feature.type].push(feature);
|
||||
}
|
||||
for (const entry in featureTable) {
|
||||
featureTable[entry].sort((a, b) => a.sequence.slice(-1) > b.sequence.slice(-1));
|
||||
}
|
||||
// console.error(featureTable);
|
||||
featureTable.version = require('../package.json').version;
|
||||
console.log(Mustache.render(MARKDOWN_TMPL, featureTable));
|
||||
}
|
||||
|
||||
function main(filenames) {
|
||||
// console.error(filenames);
|
||||
let leftToProcess = filenames.length;
|
||||
const features = [];
|
||||
for (const filename of filenames) {
|
||||
fs.readFile(filename, 'utf-8', (err, data) => {
|
||||
let match;
|
||||
while ((match = REX_COMMENTS.exec(data)) !== null) {
|
||||
if (match.index === REX_COMMENTS.lastIndex) {
|
||||
REX_COMMENTS.lastIndex++;
|
||||
}
|
||||
const feature = match[1]
|
||||
? parseMultiLine(filename, match[1])
|
||||
: parseSingleLine(filename, match[2]);
|
||||
if (feature) {
|
||||
features.push(feature);
|
||||
}
|
||||
}
|
||||
leftToProcess--;
|
||||
if (!leftToProcess) {
|
||||
postProcessData(features);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
main(process.argv.slice(2))
|
||||
+3
-1
@@ -23,7 +23,8 @@
|
||||
"benchmark": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json",
|
||||
"benchmark-baseline": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --baseline out-test/benchmark/test/benchmark/*benchmark.js",
|
||||
"benchmark-eval": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --eval out-test/benchmark/test/benchmark/*benchmark.js",
|
||||
"clean": "rm -rf lib out addons/*/lib addons/*/out"
|
||||
"clean": "rm -rf lib out addons/*/lib addons/*/out",
|
||||
"vtfeatures": "node bin/extract_vt.js src/**/*.ts src/*.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^3.4.34",
|
||||
@@ -41,6 +42,7 @@
|
||||
"glob": "^7.0.5",
|
||||
"jsdom": "^11.11.0",
|
||||
"mocha": "^6.1.4",
|
||||
"mustache": "^3.0.1",
|
||||
"node-pty": "0.7.6",
|
||||
"puppeteer": "^1.15.0",
|
||||
"source-map-loader": "^0.2.4",
|
||||
|
||||
@@ -177,13 +177,18 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
* CSI handler
|
||||
*/
|
||||
this._parser.setCsiHandler({final: '@'}, params => this.insertChars(params));
|
||||
// @vt: supported CSI CUU "Cursor Up" "CSI Ps A" "Move the cursor position `Ps` times to the top (default=1)."
|
||||
this._parser.setCsiHandler({final: 'A'}, params => this.cursorUp(params));
|
||||
// @vt: supported CSI CUD "Cursor Down" "CSI Ps B" "Move the cursor position `Ps` times to the bottom (default=1)."
|
||||
this._parser.setCsiHandler({final: 'B'}, params => this.cursorDown(params));
|
||||
// @vt: supported CSI CUF "Cursor Forward" "CSI Ps C" "Move the cursor position `Ps` times to the right (default=1)."
|
||||
this._parser.setCsiHandler({final: 'C'}, params => this.cursorForward(params));
|
||||
// @vt: supported CSI CUB "Cursor Backward" "CSI Ps D" "Move the cursor position `Ps` times to the left (default=1)."
|
||||
this._parser.setCsiHandler({final: 'D'}, params => this.cursorBackward(params));
|
||||
this._parser.setCsiHandler({final: 'E'}, params => this.cursorNextLine(params));
|
||||
this._parser.setCsiHandler({final: 'F'}, params => this.cursorPrecedingLine(params));
|
||||
this._parser.setCsiHandler({final: 'G'}, params => this.cursorCharAbsolute(params));
|
||||
// @vt: supported CSI CUP "Cursor Position" "CSI Ps ; Ps H" "Set the cursor to position [`Ps`, `Ps`]."
|
||||
this._parser.setCsiHandler({final: 'H'}, params => this.cursorPosition(params));
|
||||
this._parser.setCsiHandler({final: 'I'}, params => this.cursorForwardTab(params));
|
||||
this._parser.setCsiHandler({final: 'J'}, params => this.eraseInDisplay(params));
|
||||
@@ -210,6 +215,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
this._parser.setCsiHandler({prefix: '?', final: 'h'}, params => this.setModePrivate(params));
|
||||
this._parser.setCsiHandler({final: 'l'}, params => this.resetMode(params));
|
||||
this._parser.setCsiHandler({prefix: '?', final: 'l'}, params => this.resetModePrivate(params));
|
||||
// @vt: partly CSI SGR "Select Graphic Rendition" "CSI Pm m" "Set various text attributes."
|
||||
this._parser.setCsiHandler({final: 'm'}, params => this.charAttributes(params));
|
||||
this._parser.setCsiHandler({final: 'n'}, params => this.deviceStatus(params));
|
||||
this._parser.setCsiHandler({prefix: '?', final: 'n'}, params => this.deviceStatusPrivate(params));
|
||||
@@ -222,11 +228,15 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
/**
|
||||
* execute handler
|
||||
*/
|
||||
// @vt: supported C0 BEL "Bell" "\x07" "Rings the bell."
|
||||
this._parser.setExecuteHandler(C0.BEL, () => this.bell());
|
||||
// @vt: supported C0 LF "Line Feed" "\n" "Moves the cursor one row down, scrolling if needed."
|
||||
this._parser.setExecuteHandler(C0.LF, () => this.lineFeed());
|
||||
this._parser.setExecuteHandler(C0.VT, () => this.lineFeed());
|
||||
this._parser.setExecuteHandler(C0.FF, () => this.lineFeed());
|
||||
// @vt: supported C0 CR "Carriage Return" "\r" "Moves the cursor to the beginning of the row."
|
||||
this._parser.setExecuteHandler(C0.CR, () => this.carriageReturn());
|
||||
// @vt: supported C0 BS "Backspace" "\x08" "Moves the cursor one position to the left."
|
||||
this._parser.setExecuteHandler(C0.BS, () => this.backspace());
|
||||
this._parser.setExecuteHandler(C0.HT, () => this.tab());
|
||||
this._parser.setExecuteHandler(C0.SO, () => this.shiftOut());
|
||||
@@ -241,9 +251,12 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
* OSC handler
|
||||
*/
|
||||
// 0 - icon name + title
|
||||
// @vt: partly OSC OSC0 "" "OSC 0 ; Pt BEL" "Set window title and icon name."
|
||||
this._parser.setOscHandler(0, new OscHandler((data: string) => this.setTitle(data)));
|
||||
// 1 - icon name
|
||||
// @vt: unsupported OSC OSC1 "" "OSC 1 ; Pt BEL" "Set icon name."
|
||||
// 2 - title
|
||||
// @vt: supported OSC OSC2 "" "OSC 2 ; Pt BEL" "Set window title."
|
||||
this._parser.setOscHandler(2, new OscHandler((data: string) => this.setTitle(data)));
|
||||
// 3 - set property X in the form "prop=value"
|
||||
// 4 - Change Color Number
|
||||
@@ -306,6 +319,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
this._parser.setEscHandler({intermediates: '.', final: flag}, () => this.selectCharset('.' + flag));
|
||||
this._parser.setEscHandler({intermediates: '/', final: flag}, () => this.selectCharset('/' + flag)); // TODO: supported?
|
||||
}
|
||||
// @vt: supported ESC DECALN "Screen Alignment Pattern" "ESC # 8" "Fill viewport with a test pattern (E)."
|
||||
this._parser.setEscHandler({intermediates: '#', final: '8'}, () => this.screenAlignmentPattern());
|
||||
|
||||
/**
|
||||
|
||||
@@ -3133,6 +3133,11 @@ ms@2.1.1, ms@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
|
||||
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
|
||||
|
||||
mustache@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mustache/-/mustache-3.0.1.tgz#873855f23aa8a95b150fb96d9836edbc5a1d248a"
|
||||
integrity sha512-jFI/4UVRsRYdUbuDTKT7KzfOp7FiD5WzYmmwNwXyUVypC0xjoTL78Fqc0jHUPIvvGD+6DQSPHIt1NE7D1ArsqA==
|
||||
|
||||
mute-stream@0.0.7:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
|
||||
|
||||
Reference in New Issue
Block a user