fix imports

This commit is contained in:
Jörg Breitbart
2019-05-11 17:56:26 +02:00
66 changed files with 728 additions and 402 deletions
+22
View File
@@ -0,0 +1,22 @@
FROM node:10
# Configure apt
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get -y install --no-install-recommends apt-utils 2>&1
# Verify git and process tools are installed
RUN apt-get install -y git procps
# Install yarn
RUN apt-get install -y curl apt-transport-https lsb-release \
&& curl -sS https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/pubkey.gpg | apt-key add - 2>/dev/null \
&& echo "deb https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
&& apt-get update \
&& apt-get -y install --no-install-recommends yarn
# Clean up
RUN apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
ENV DEBIAN_FRONTEND=dialog
+9
View File
@@ -0,0 +1,9 @@
{
"name": "xterm.js",
"dockerFile": "Dockerfile",
"appPort": 3000,
"extensions": [
"editorconfig.editorconfig",
"ms-vscode.vscode-typescript-tslint-plugin"
]
}
+51
View File
@@ -0,0 +1,51 @@
{
"version": "2.0.0",
"presentation": {
"echo": false,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": true
},
"tasks": [
{
"type": "npm",
"script": "test",
"group": "test",
"problemMatcher": []
},
{
"type": "npm",
"script": "watch",
"group": "build",
"isBackground": true,
"problemMatcher": [],
"presentation": {
"group": "vscode"
}
},
{
"type": "npm",
"script": "start",
"group": "build",
"isBackground": true,
"problemMatcher": [],
"presentation": {
"group": "vscode"
}
},
{
"label": "Start demo",
"dependsOn": ["npm: watch", "npm: start"],
"group": {
"kind": "build",
"isDefault": true
},
"isBackground": true,
"problemMatcher": [],
"presentation": {
"group": "vscode"
}
}
]
}
+3 -2
View File
@@ -156,7 +156,8 @@ Xterm.js is used in several world-class applications to provide great terminal e
- [**Jumpserver**](https://github.com/jumpserver/luna): Jumpserver Luna project, Jumpserver is a bastion server project, Luna use xterm.js for web terminal emulation. - [**Jumpserver**](https://github.com/jumpserver/luna): Jumpserver Luna project, Jumpserver is a bastion server project, Luna use xterm.js for web terminal emulation.
- [**LxdMosaic**](https://github.com/turtle0x1/LxdMosaic): Uses xterm.js to give terminal access to containers through LXD - [**LxdMosaic**](https://github.com/turtle0x1/LxdMosaic): Uses xterm.js to give terminal access to containers through LXD
- [**CodeInterview.io**](https://codeinterview.io): A coding interview platform in 25+ languages and many web frameworks. Uses xterm.js to provide shell access. - [**CodeInterview.io**](https://codeinterview.io): A coding interview platform in 25+ languages and many web frameworks. Uses xterm.js to provide shell access.
- [**Bastillion**](https://www.bastillion.io): Bastillion is an open-source web-based SSH console that centrally manages administrative access to systems. - [**Bastillion**](https://www.bastillion.io): Bastillion is an open-source web-based SSH console that centrally manages administrative access to systems.
- [**PHP App Server**](https://github.com/cubiclesoft/php-app-server/): Create lightweight, installable almost-native applications for desktop OSes. ExecTerminal (nicely wraps the xterm.js Terminal), TerminalManager, and RunProcessSDK are self-contained, reusable ES5+ compliant Javascript components.
[And much more...](https://github.com/xtermjs/xterm.js/network/dependents) [And much more...](https://github.com/xtermjs/xterm.js/network/dependents)
@@ -186,6 +187,6 @@ You can read the [guide on the wiki](https://github.com/xtermjs/xterm.js/wiki/Co
If you contribute code to this project, you are implicitly allowing your code to be distributed under the MIT license. You are also implicitly verifying that all code is your original work. If you contribute code to this project, you are implicitly allowing your code to be distributed under the MIT license. You are also implicitly verifying that all code is your original work.
Copyright (c) 2017-2018, [The xterm.js authors](https://github.com/xtermjs/xterm.js/graphs/contributors) (MIT License)<br> Copyright (c) 2017-2019, [The xterm.js authors](https://github.com/xtermjs/xterm.js/graphs/contributors) (MIT License)<br>
Copyright (c) 2014-2017, SourceLair, Private Company ([www.sourcelair.com](https://www.sourcelair.com/home)) (MIT License)<br> Copyright (c) 2014-2017, SourceLair, Private Company ([www.sourcelair.com](https://www.sourcelair.com/home)) (MIT License)<br>
Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
+25 -12
View File
@@ -11,9 +11,12 @@ const packageJson = require('../package.json');
// Setup auth // Setup auth
fs.writeFileSync(`${process.env['HOME']}/.npmrc`, `//registry.npmjs.org/:_authToken=${process.env['NPM_AUTH_TOKEN']}`); fs.writeFileSync(`${process.env['HOME']}/.npmrc`, `//registry.npmjs.org/:_authToken=${process.env['NPM_AUTH_TOKEN']}`);
// Get the version // Determine if this is a stable or beta release
const tag = 'beta' const publishedVersions = getPublishedVersions();
const nextVersion = getNextVersion(tag); const isStableRelease = publishedVersions.indexOf(packageJson.version) === -1;
// Get the next version
let nextVersion = isStableRelease ? packageJson.version : getNextBetaVersion();
console.log(`Publishing version: ${nextVersion}`); console.log(`Publishing version: ${nextVersion}`);
// Set the version in package.json // Set the version in package.json
@@ -22,29 +25,39 @@ packageJson.version = nextVersion;
fs.writeFileSync(packageJsonFile, JSON.stringify(packageJson, null, 2)); fs.writeFileSync(packageJsonFile, JSON.stringify(packageJson, null, 2));
// Publish // Publish
const result = cp.spawn('npm', ['publish', '--tag', tag], { const args = ['publish'];
stdio: 'inherit' if (!isStableRelease) {
}); args.push('--tag', 'beta');
}
const result = cp.spawn('npm', args, { stdio: 'inherit' });
result.on('exit', code => process.exit(code)); result.on('exit', code => process.exit(code));
function getNextVersion(tag) { function getNextBetaVersion() {
if (!/^[0-9]+\.[0-9]+\.[0-9]+$/.exec(packageJson.version)) { if (!/^[0-9]+\.[0-9]+\.[0-9]+$/.exec(packageJson.version)) {
console.error('The package.json version must be of the form x.y.z'); console.error('The package.json version must be of the form x.y.z');
process.exit(1); process.exit(1);
} }
const tag = 'beta';
const stableVersion = packageJson.version.split('.'); const stableVersion = packageJson.version.split('.');
const nextStableVersion = `${stableVersion[0]}.${parseInt(stableVersion[1]) + 1}.${stableVersion[2]}`; const nextStableVersion = `${stableVersion[0]}.${parseInt(stableVersion[1]) + 1}.0`;
const publishedVersions = getPublishedVersions(nextStableVersion, tag); const publishedVersions = getPublishedVersions(nextStableVersion, tag);
if (publishedVersions.length === 0) { if (publishedVersions.length === 0) {
return `${packageJson.version}-${tag}1`; return `${nextStableVersion}-${tag}1`;
} }
const latestPublishedVersion = publishedVersions.sort((a, b) => b.localeCompare(a))[0]; const latestPublishedVersion = publishedVersions.sort((a, b) => {
const aVersion = parseInt(a.substr(a.search(/[0-9]+$/)));
const bVersion = parseInt(b.substr(b.search(/[0-9]+$/)));
return aVersion > bVersion ? -1 : 1;
})[0];
const latestTagVersion = parseInt(latestPublishedVersion.substr(latestPublishedVersion.search(/[0-9]+$/)), 10); const latestTagVersion = parseInt(latestPublishedVersion.substr(latestPublishedVersion.search(/[0-9]+$/)), 10);
return `${nextStableVersion}-${tag}${latestTagVersion + 1}`; return `${nextStableVersion}-${tag}${latestTagVersion + 1}`;
} }
function getPublishedVersions(version, tag) { function getPublishedVersions(version, tag) {
const versionsProcess = cp.spawnSync('npm', ['view', 'xterm', 'versions', '--json']); const versionsProcess = cp.spawnSync('npm', ['view', packageJson.name, 'versions', '--json']);
const versionsJson = JSON.parse(versionsProcess.stdout); const versionsJson = JSON.parse(versionsProcess.stdout);
return versionsJson.filter(v => !v.search(new RegExp(`${version}-${tag}[0-9]+`))); if (tag) {
return versionsJson.filter(v => !v.search(new RegExp(`${version}-${tag}[0-9]+`)));
}
return versionsJson;
} }
+4 -1
View File
@@ -260,8 +260,11 @@ function initOptions(term: TerminalType): void {
console.log('change', o, input.value); console.log('change', o, input.value);
if (o === 'cols' || o === 'rows') { if (o === 'cols' || o === 'rows') {
updateTerminalSize(); updateTerminalSize();
} else if (o === 'lineHeight') {
term.setOption(o, parseFloat(input.value));
updateTerminalSize();
} else { } else {
term.setOption(o, o === 'lineHeight' ? parseFloat(input.value) : parseInt(input.value, 10)); term.setOption(o, parseInt(input.value));
} }
}); });
}); });
+5 -3
View File
@@ -21,7 +21,7 @@ namespace constructor {
'disableStdin': false, 'disableStdin': false,
'rows': 1, 'rows': 1,
'scrollback': 10, 'scrollback': 10,
'tabStopWidth': 2, 'tabStopWidth': 2
}); });
} }
} }
@@ -119,8 +119,8 @@ namespace methods_core {
const t: Terminal = new Terminal(); const t: Terminal = new Terminal();
t.attachCustomKeyEventHandler((e: KeyboardEvent) => true); t.attachCustomKeyEventHandler((e: KeyboardEvent) => true);
t.attachCustomKeyEventHandler((e: KeyboardEvent) => false); t.attachCustomKeyEventHandler((e: KeyboardEvent) => false);
const d1: IDisposable = t.addCsiHandler("x", const d1: IDisposable = t.addCsiHandler('x',
(params: number[], collect: string): boolean => params[0]===1); (params: number[], collect: string): boolean => params[0] === 1);
d1.dispose(); d1.dispose();
const d2: IDisposable = t.addOscHandler(199, const d2: IDisposable = t.addOscHandler(199,
(data: string): boolean => true); (data: string): boolean => true);
@@ -155,6 +155,7 @@ namespace methods_core {
const r25: string = t.getOption('fontWeightBold'); const r25: string = t.getOption('fontWeightBold');
const r26: boolean = t.getOption('allowTransparency'); const r26: boolean = t.getOption('allowTransparency');
const r27: boolean = t.getOption('rightClickSelectsWord'); const r27: boolean = t.getOption('rightClickSelectsWord');
const r28: boolean = t.getOption('windowsMode');
} }
{ {
const t: Terminal = new Terminal(); const t: Terminal = new Terminal();
@@ -177,6 +178,7 @@ namespace methods_core {
t.setOption('useFlowControl', true); t.setOption('useFlowControl', true);
t.setOption('allowTransparency', true); t.setOption('allowTransparency', true);
t.setOption('visualBell', true); t.setOption('visualBell', true);
t.setOption('windowsMode', true);
t.setOption('colors', ['a', 'b']); t.setOption('colors', ['a', 'b']);
t.setOption('letterSpacing', 1); t.setOption('letterSpacing', 1);
t.setOption('cols', 1); t.setOption('cols', 1);
+4 -3
View File
@@ -1,7 +1,7 @@
{ {
"name": "xterm", "name": "xterm",
"description": "Full xterm terminal, in your browser", "description": "Full xterm terminal, in your browser",
"version": "3.12.0", "version": "3.13.0",
"main": "lib/public/Terminal.js", "main": "lib/public/Terminal.js",
"types": "typings/xterm.d.ts", "types": "typings/xterm.d.ts",
"repository": "https://github.com/xtermjs/xterm.js", "repository": "https://github.com/xtermjs/xterm.js",
@@ -59,8 +59,9 @@
"mocha": "gulp test", "mocha": "gulp test",
"prebuild": "tsc -b ./src/tsconfig.all.json", "prebuild": "tsc -b ./src/tsconfig.all.json",
"build": "gulp build", "build": "gulp build",
"prepublish": "npm run build", "prepare": "npm run prebuild",
"prepublishOnly": "npm run build",
"coveralls": "nyc report --reporter=text-lcov | coveralls", "coveralls": "nyc report --reporter=text-lcov | coveralls",
"watch": "tsc -b -w ./src/tsconfig.all.json --preserveWatchOutput" "watch": "tsc -b -w ./src/tsconfig.all.json --preserveWatchOutput"
} }
} }
+2 -2
View File
@@ -61,7 +61,7 @@ export class AccessibilityManager extends Disposable {
this._refreshRowsDimensions(); this._refreshRowsDimensions();
this._accessibilityTreeRoot.appendChild(this._rowContainer); this._accessibilityTreeRoot.appendChild(this._rowContainer);
this._renderRowsDebouncer = new RenderDebouncer(this._terminal, this._renderRows.bind(this)); this._renderRowsDebouncer = new RenderDebouncer(this._renderRows.bind(this));
this._refreshRows(); this._refreshRows();
this._liveRegion = document.createElement('div'); this._liveRegion = document.createElement('div');
@@ -239,7 +239,7 @@ export class AccessibilityManager extends Disposable {
} }
private _refreshRows(start?: number, end?: number): void { private _refreshRows(start?: number, end?: number): void {
this._renderRowsDebouncer.refresh(start, end); this._renderRowsDebouncer.refresh(start, end, this._terminal.rows);
} }
private _renderRows(start: number, end: number): void { private _renderRows(start: number, end: number): void {
+3 -3
View File
@@ -5,10 +5,10 @@
import { assert, expect } from 'chai'; import { assert, expect } from 'chai';
import { ITerminal } from './Types'; import { ITerminal } from './Types';
import { Buffer, DEFAULT_ATTR_DATA } from './Buffer'; import { Buffer } from './Buffer';
import { CircularList } from './common/CircularList'; import { CircularList } from './common/CircularList';
import { MockTerminal, TestTerminal } from './ui/TestUtils.test'; import { MockTerminal, TestTerminal } from './TestUtils.test';
import { BufferLine, CellData } from './BufferLine'; import { BufferLine, CellData, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine';
const INIT_COLS = 80; const INIT_COLS = 80;
const INIT_ROWS = 24; const INIT_ROWS = 24;
+4 -30
View File
@@ -4,42 +4,16 @@
*/ */
import { CircularList, IInsertEvent } from './common/CircularList'; import { CircularList, IInsertEvent } from './common/CircularList';
import { ITerminal, IBuffer, IBufferLine, BufferIndex, IBufferStringIterator, IBufferStringIteratorResult, ICellData, IAttributeData } from './Types'; import { ITerminal, IBuffer, BufferIndex, IBufferStringIterator, IBufferStringIteratorResult } from './Types';
import { IBufferLine, ICellData, IAttributeData } from './core/Types';
import { IMarker } from 'xterm'; import { IMarker } from 'xterm';
import { BufferLine, CellData, AttributeData } from './BufferLine'; import { BufferLine, CellData, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_WIDTH, WHITESPACE_CELL_CODE, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine';
import { reflowLargerApplyNewLayout, reflowLargerCreateNewLayout, reflowLargerGetLinesToRemove, reflowSmallerGetNewLineLengths, getWrappedLineTrimmedLength } from './BufferReflow'; import { reflowLargerApplyNewLayout, reflowLargerCreateNewLayout, reflowLargerGetLinesToRemove, reflowSmallerGetNewLineLengths, getWrappedLineTrimmedLength } from './BufferReflow';
import { DEFAULT_COLOR } from './renderer/atlas/Types';
import { EventEmitter2, IEvent } from './common/EventEmitter2'; import { EventEmitter2, IEvent } from './common/EventEmitter2';
import { Disposable } from '../lib/common/Lifecycle'; import { Disposable } from './common/Lifecycle';
export const DEFAULT_ATTR = (0 << 18) | (DEFAULT_COLOR << 9) | (256 << 0);
export const DEFAULT_ATTR_DATA = new AttributeData();
export const CHAR_DATA_ATTR_INDEX = 0;
export const CHAR_DATA_CHAR_INDEX = 1;
export const CHAR_DATA_WIDTH_INDEX = 2;
export const CHAR_DATA_CODE_INDEX = 3;
export const MAX_BUFFER_SIZE = 4294967295; // 2^32 - 1 export const MAX_BUFFER_SIZE = 4294967295; // 2^32 - 1
/**
* Null cell - a real empty cell (containing nothing).
* Note that code should always be 0 for a null cell as
* several test condition of the buffer line rely on this.
*/
export const NULL_CELL_CHAR = '';
export const NULL_CELL_WIDTH = 1;
export const NULL_CELL_CODE = 0;
/**
* Whitespace cell.
* This is meant as a replacement for empty cells when needed
* during rendering lines to preserve correct aligment.
*/
export const WHITESPACE_CELL_CHAR = ' ';
export const WHITESPACE_CELL_WIDTH = 1;
export const WHITESPACE_CELL_CODE = 32;
/** /**
* This class represents a terminal buffer (an internal state of the terminal), where the * This class represents a terminal buffer (an internal state of the terminal), where the
* following information is stored (in high-level): * following information is stored (in high-level):
+1 -2
View File
@@ -3,9 +3,8 @@
* @license MIT * @license MIT
*/ */
import { assert } from 'chai'; import { assert } from 'chai';
import { BufferLine } from './BufferLine'; import { BufferLine, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE } from './core/buffer/BufferLine';
import { reflowSmallerGetNewLineLengths } from './BufferReflow'; import { reflowSmallerGetNewLineLengths } from './BufferReflow';
import { NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE } from './Buffer';
describe('BufferReflow', () => { describe('BufferReflow', () => {
describe('reflowSmallerGetNewLineLengths', () => { describe('reflowSmallerGetNewLineLengths', () => {
+2 -2
View File
@@ -3,9 +3,9 @@
* @license MIT * @license MIT
*/ */
import { BufferLine } from './BufferLine'; import { BufferLine } from './core/buffer/BufferLine';
import { CircularList } from './common/CircularList'; import { CircularList } from './common/CircularList';
import { IBufferLine, ICellData } from './Types'; import { IBufferLine, ICellData } from './core/Types';
export interface INewLayoutResult { export interface INewLayoutResult {
layout: number[]; layout: number[];
+1 -1
View File
@@ -7,7 +7,7 @@ import { assert } from 'chai';
import { ITerminal } from './Types'; import { ITerminal } from './Types';
import { BufferSet } from './BufferSet'; import { BufferSet } from './BufferSet';
import { Buffer } from './Buffer'; import { Buffer } from './Buffer';
import { MockTerminal } from './ui/TestUtils.test'; import { MockTerminal } from './TestUtils.test';
describe('BufferSet', () => { describe('BufferSet', () => {
let terminal: ITerminal; let terminal: ITerminal;
+2 -1
View File
@@ -3,7 +3,8 @@
* @license MIT * @license MIT
*/ */
import { ITerminal, IBufferSet, IAttributeData, IBuffer } from './Types'; import { ITerminal, IBufferSet, IBuffer } from './Types';
import { IAttributeData } from './core/Types';
import { Buffer } from './Buffer'; import { Buffer } from './Buffer';
import { EventEmitter2, IEvent } from './common/EventEmitter2'; import { EventEmitter2, IEvent } from './common/EventEmitter2';
@@ -4,7 +4,7 @@
*/ */
import jsdom = require('jsdom'); import jsdom = require('jsdom');
import { ICharMeasure } from '../Types'; import { ICharMeasure } from './Types';
import { assert } from 'chai'; import { assert } from 'chai';
import { CharMeasure } from './CharMeasure'; import { CharMeasure } from './CharMeasure';
+2 -2
View File
@@ -3,8 +3,8 @@
* @license MIT * @license MIT
*/ */
import { ICharMeasure, ITerminalOptions } from '../Types'; import { ICharMeasure, ITerminalOptions } from './Types';
import { EventEmitter2, IEvent } from '../common/EventEmitter2'; import { EventEmitter2, IEvent } from './common/EventEmitter2';
/** /**
* Utility class that measures the size of a character. Measurements are done in * Utility class that measures the size of a character. Measurements are done in
+2 -3
View File
@@ -3,12 +3,11 @@
* @license MIT * @license MIT
*/ */
import { TestTerminal } from './ui/TestUtils.test'; import { TestTerminal } from './TestUtils.test';
import { assert } from 'chai'; import { assert } from 'chai';
import { getStringCellWidth, wcwidth } from './CharWidth'; import { getStringCellWidth, wcwidth } from './CharWidth';
import { IBuffer } from './Types'; import { IBuffer } from './Types';
import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from './Buffer'; import { CellData, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from './core/buffer/BufferLine';
import { CellData } from './BufferLine';
describe('getStringCellWidth', function(): void { describe('getStringCellWidth', function(): void {
+1 -1
View File
@@ -3,7 +3,7 @@
* @license MIT * @license MIT
*/ */
import { ITerminal, ISelectionManager } from '../Types'; import { ITerminal, ISelectionManager } from './Types';
interface IWindow extends Window { interface IWindow extends Window {
clipboardData?: { clipboardData?: {
+3 -4
View File
@@ -5,11 +5,10 @@
import { assert, expect } from 'chai'; import { assert, expect } from 'chai';
import { InputHandler } from './InputHandler'; import { InputHandler } from './InputHandler';
import { MockInputHandlingTerminal, TestTerminal } from './ui/TestUtils.test'; import { MockInputHandlingTerminal, TestTerminal } from './TestUtils.test';
import { DEFAULT_ATTR_DATA } from './Buffer';
import { Terminal } from './Terminal'; import { Terminal } from './Terminal';
import { IBufferLine } from './Types'; import { IBufferLine } from './core/Types';
import { CellData, Attributes, AttributeData } from './BufferLine'; import { CellData, Attributes, AttributeData, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine';
describe('InputHandler', () => { describe('InputHandler', () => {
describe('save and restore cursor', () => { describe('save and restore cursor', () => {
+3 -4
View File
@@ -7,14 +7,13 @@
import { IInputHandler, IDcsHandler, IEscapeSequenceParser, IInputHandlingTerminal } from './Types'; import { IInputHandler, IDcsHandler, IEscapeSequenceParser, IInputHandlingTerminal } from './Types';
import { C0, C1 } from './common/data/EscapeSequences'; import { C0, C1 } from './common/data/EscapeSequences';
import { CHARSETS, DEFAULT_CHARSET } from './core/data/Charsets'; import { CHARSETS, DEFAULT_CHARSET } from './core/data/Charsets';
import { NULL_CELL_WIDTH, NULL_CELL_CODE, DEFAULT_ATTR_DATA } from './Buffer';
import { wcwidth } from './CharWidth'; import { wcwidth } from './CharWidth';
import { EscapeSequenceParser } from './EscapeSequenceParser'; import { EscapeSequenceParser } from './EscapeSequenceParser';
import { IDisposable } from 'xterm'; import { IDisposable } from 'xterm';
import { Disposable } from './common/Lifecycle'; import { Disposable } from './common/Lifecycle';
import { concat } from './common/TypedArrayUtils'; import { concat } from './common/TypedArrayUtils';
import { StringToUtf32, stringFromCodePoint, Utf8ToUtf32, utf32ToString } from './core/input/TextDecoder'; import { StringToUtf32, stringFromCodePoint, utf32ToString, Utf8ToUtf32 } from './core/input/TextDecoder';
import { CellData, Attributes, FgFlags, BgFlags, AttributeData } from './BufferLine'; import { CellData, Attributes, FgFlags, BgFlags, AttributeData, NULL_CELL_WIDTH, NULL_CELL_CODE, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine';
import { EventEmitter2, IEvent } from './common/EventEmitter2'; import { EventEmitter2, IEvent } from './common/EventEmitter2';
/** /**
@@ -105,7 +104,7 @@ class DECRQSS implements IDcsHandler {
export class InputHandler extends Disposable implements IInputHandler { export class InputHandler extends Disposable implements IInputHandler {
private _parseBuffer: Uint32Array = new Uint32Array(4096); private _parseBuffer: Uint32Array = new Uint32Array(4096);
private _stringDecoder: StringToUtf32 = new StringToUtf32(); private _stringDecoder: StringToUtf32 = new StringToUtf32();
private _utf8Decoder = new Utf8ToUtf32(); private _utf8Decoder: Utf8ToUtf32 = new Utf8ToUtf32();
private _workCell: CellData = new CellData(); private _workCell: CellData = new CellData();
private _onCursorMove = new EventEmitter2<void>(); private _onCursorMove = new EventEmitter2<void>();
+4 -4
View File
@@ -4,12 +4,12 @@
*/ */
import { assert } from 'chai'; import { assert } from 'chai';
import { IMouseZoneManager, IMouseZone } from './ui/Types'; import { IMouseZoneManager, IMouseZone, ILinkMatcher, ITerminal } from './Types';
import { ILinkMatcher, ITerminal, IBufferLine } from './Types'; import { IBufferLine } from './core/Types';
import { Linkifier } from './Linkifier'; import { Linkifier } from './Linkifier';
import { MockBuffer, MockTerminal, TestTerminal } from './ui/TestUtils.test'; import { MockBuffer, MockTerminal, TestTerminal } from './TestUtils.test';
import { CircularList } from './common/CircularList'; import { CircularList } from './common/CircularList';
import { BufferLine, CellData } from './BufferLine'; import { BufferLine, CellData } from './core/buffer/BufferLine';
class TestLinkifier extends Linkifier { class TestLinkifier extends Linkifier {
constructor(terminal: ITerminal) { constructor(terminal: ITerminal) {
+2 -3
View File
@@ -3,9 +3,8 @@
* @license MIT * @license MIT
*/ */
import { IMouseZoneManager } from './ui/Types'; import { ILinkifierEvent, ILinkMatcher, LinkMatcherHandler, ILinkMatcherOptions, ILinkifier, ITerminal, IBufferStringIteratorResult, IMouseZoneManager } from './Types';
import { ILinkifierEvent, ILinkMatcher, LinkMatcherHandler, ILinkMatcherOptions, ILinkifier, ITerminal, IBufferStringIteratorResult } from './Types'; import { MouseZone } from './MouseZoneManager';
import { MouseZone } from './ui/MouseZoneManager';
import { getStringCellWidth } from './CharWidth'; import { getStringCellWidth } from './CharWidth';
import { EventEmitter2, IEvent } from './common/EventEmitter2'; import { EventEmitter2, IEvent } from './common/EventEmitter2';
+2 -2
View File
@@ -3,8 +3,8 @@
* @license MIT * @license MIT
*/ */
import { ICharMeasure, IMouseHelper } from '../Types'; import { ICharMeasure, IMouseHelper } from './Types';
import { IRenderer } from '../renderer/Types'; import { IRenderer } from './renderer/Types';
export class MouseHelper implements IMouseHelper { export class MouseHelper implements IMouseHelper {
constructor(private _renderer: IRenderer) {} constructor(private _renderer: IRenderer) {}
@@ -3,10 +3,9 @@
* @license MIT * @license MIT
*/ */
import { ITerminal } from '../Types'; import { ITerminal, IMouseZoneManager, IMouseZone } from './Types';
import { IMouseZoneManager, IMouseZone } from './Types'; import { Disposable } from './common/Lifecycle';
import { Disposable } from '../common/Lifecycle'; import { addDisposableDomListener } from './ui/Lifecycle';
import { addDisposableDomListener } from './Lifecycle';
const HOVER_DURATION = 500; const HOVER_DURATION = 500;
+5 -4
View File
@@ -4,13 +4,14 @@
*/ */
import { assert } from 'chai'; import { assert } from 'chai';
import { CharMeasure } from './ui/CharMeasure'; import { CharMeasure } from './CharMeasure';
import { SelectionManager, SelectionMode } from './SelectionManager'; import { SelectionManager, SelectionMode } from './SelectionManager';
import { SelectionModel } from './SelectionModel'; import { SelectionModel } from './SelectionModel';
import { BufferSet } from './BufferSet'; import { BufferSet } from './BufferSet';
import { ITerminal, IBuffer, IBufferLine } from './Types'; import { ITerminal, IBuffer } from './Types';
import { MockTerminal } from './ui/TestUtils.test'; import { IBufferLine } from './core/Types';
import { BufferLine, CellData } from './BufferLine'; import { MockTerminal } from './TestUtils.test';
import { BufferLine, CellData } from './core/buffer/BufferLine';
class TestMockTerminal extends MockTerminal { class TestMockTerminal extends MockTerminal {
emit(event: string, data: any): void {} emit(event: string, data: any): void {}
+5 -4
View File
@@ -3,13 +3,14 @@
* @license MIT * @license MIT
*/ */
import { ITerminal, ISelectionManager, IBuffer, IBufferLine, ISelectionRedrawRequestEvent } from './Types'; import { ITerminal, ISelectionManager, IBuffer, ISelectionRedrawRequestEvent } from './Types';
import { MouseHelper } from './ui/MouseHelper'; import { IBufferLine } from './core/Types';
import { MouseHelper } from './MouseHelper';
import * as Browser from './common/Platform'; import * as Browser from './common/Platform';
import { CharMeasure } from './ui/CharMeasure'; import { CharMeasure } from './CharMeasure';
import { SelectionModel } from './SelectionModel'; import { SelectionModel } from './SelectionModel';
import { AltClickHandler } from './handlers/AltClickHandler'; import { AltClickHandler } from './handlers/AltClickHandler';
import { CellData } from './BufferLine'; import { CellData } from './core/buffer/BufferLine';
import { IDisposable } from 'xterm'; import { IDisposable } from 'xterm';
import { EventEmitter2, IEvent } from './common/EventEmitter2'; import { EventEmitter2, IEvent } from './common/EventEmitter2';
+1 -1
View File
@@ -7,7 +7,7 @@ import { assert } from 'chai';
import { ITerminal } from './Types'; import { ITerminal } from './Types';
import { SelectionModel } from './SelectionModel'; import { SelectionModel } from './SelectionModel';
import { BufferSet } from './BufferSet'; import { BufferSet } from './BufferSet';
import { MockTerminal } from './ui/TestUtils.test'; import { MockTerminal } from './TestUtils.test';
class TestSelectionModel extends SelectionModel { class TestSelectionModel extends SelectionModel {
constructor( constructor(
+1 -2
View File
@@ -13,9 +13,8 @@ import * as path from 'path';
import * as pty from 'node-pty'; import * as pty from 'node-pty';
import { assert } from 'chai'; import { assert } from 'chai';
import { Terminal } from './Terminal'; import { Terminal } from './Terminal';
import { WHITESPACE_CELL_CHAR } from './Buffer';
import { IViewport } from './Types'; import { IViewport } from './Types';
import { CellData } from './BufferLine'; import { CellData, WHITESPACE_CELL_CHAR } from './core/buffer/BufferLine';
class TestTerminal extends Terminal { class TestTerminal extends Terminal {
innerWrite(): void { this._innerWrite(); } innerWrite(): void { this._innerWrite(); }
+2 -3
View File
@@ -5,9 +5,8 @@
import { assert, expect } from 'chai'; import { assert, expect } from 'chai';
import { Terminal } from './Terminal'; import { Terminal } from './Terminal';
import { MockViewport, MockCompositionHelper, MockRenderer } from './ui/TestUtils.test'; import { MockViewport, MockCompositionHelper, MockRenderer } from './TestUtils.test';
import { DEFAULT_ATTR_DATA } from './Buffer'; import { CellData, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine';
import { CellData } from './BufferLine';
const INIT_COLS = 80; const INIT_COLS = 80;
const INIT_ROWS = 24; const INIT_ROWS = 24;
+8 -9
View File
@@ -21,27 +21,26 @@
* http://linux.die.net/man/7/urxvt * http://linux.die.net/man/7/urxvt
*/ */
import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminalOptions, ITerminal, IBrowser, ILinkifier, ILinkMatcherOptions, CustomKeyEventHandler, LinkMatcherHandler, CharacterJoinerHandler, IBufferLine, IAttributeData } from './Types'; import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminalOptions, ITerminal, IBrowser, ILinkifier, ILinkMatcherOptions, CustomKeyEventHandler, LinkMatcherHandler, CharacterJoinerHandler, IMouseZoneManager } from './Types';
import { IMouseZoneManager } from './ui/Types';
import { IRenderer } from './renderer/Types'; import { IRenderer } from './renderer/Types';
import { BufferSet } from './BufferSet'; import { BufferSet } from './BufferSet';
import { Buffer, MAX_BUFFER_SIZE, DEFAULT_ATTR_DATA } from './Buffer'; import { Buffer, MAX_BUFFER_SIZE } from './Buffer';
import { CompositionHelper } from './CompositionHelper'; import { CompositionHelper } from './CompositionHelper';
import { EventEmitter } from './common/EventEmitter'; import { EventEmitter } from './common/EventEmitter';
import { Viewport } from './Viewport'; import { Viewport } from './Viewport';
import { rightClickHandler, moveTextAreaUnderMouseCursor, pasteHandler, copyHandler } from './ui/Clipboard'; import { rightClickHandler, moveTextAreaUnderMouseCursor, pasteHandler, copyHandler } from './Clipboard';
import { C0 } from './common/data/EscapeSequences'; import { C0 } from './common/data/EscapeSequences';
import { InputHandler } from './InputHandler'; import { InputHandler } from './InputHandler';
import { Renderer } from './renderer/Renderer'; import { Renderer } from './renderer/Renderer';
import { Linkifier } from './Linkifier'; import { Linkifier } from './Linkifier';
import { SelectionManager } from './SelectionManager'; import { SelectionManager } from './SelectionManager';
import { CharMeasure } from './ui/CharMeasure'; import { CharMeasure } from './CharMeasure';
import * as Browser from './common/Platform'; import * as Browser from './common/Platform';
import { addDisposableDomListener } from './ui/Lifecycle'; import { addDisposableDomListener } from './ui/Lifecycle';
import * as Strings from './Strings'; import * as Strings from './Strings';
import { MouseHelper } from './ui/MouseHelper'; import { MouseHelper } from './MouseHelper';
import { DEFAULT_BELL_SOUND, SoundManager } from './SoundManager'; import { DEFAULT_BELL_SOUND, SoundManager } from './SoundManager';
import { MouseZoneManager } from './ui/MouseZoneManager'; import { MouseZoneManager } from './MouseZoneManager';
import { AccessibilityManager } from './AccessibilityManager'; import { AccessibilityManager } from './AccessibilityManager';
import { ScreenDprMonitor } from './ui/ScreenDprMonitor'; import { ScreenDprMonitor } from './ui/ScreenDprMonitor';
import { ITheme, IMarker, IDisposable } from 'xterm'; import { ITheme, IMarker, IDisposable } from 'xterm';
@@ -49,10 +48,10 @@ import { removeTerminalFromCache } from './renderer/atlas/CharAtlasCache';
import { DomRenderer } from './renderer/dom/DomRenderer'; import { DomRenderer } from './renderer/dom/DomRenderer';
import { IKeyboardEvent } from './common/Types'; import { IKeyboardEvent } from './common/Types';
import { evaluateKeyboardEvent } from './core/input/Keyboard'; import { evaluateKeyboardEvent } from './core/input/Keyboard';
import { KeyboardResultType, ICharset } from './core/Types'; import { KeyboardResultType, ICharset, IBufferLine, IAttributeData } from './core/Types';
import { clone } from './common/Clone'; import { clone } from './common/Clone';
import { EventEmitter2, IEvent } from './common/EventEmitter2'; import { EventEmitter2, IEvent } from './common/EventEmitter2';
import { Attributes } from './BufferLine'; import { Attributes, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine';
import { applyWindowsMode } from './WindowsMode'; import { applyWindowsMode } from './WindowsMode';
// Let it work inside Node.js for automated testing purposes. // Let it work inside Node.js for automated testing purposes.
@@ -3,14 +3,15 @@
* @license MIT * @license MIT
*/ */
import { IColorSet, IRenderer, IRenderDimensions, IColorManager } from '../renderer/Types'; import { IColorSet, IRenderer, IRenderDimensions, IColorManager } from './renderer/Types';
import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, ILinkifier, IMouseHelper, ILinkMatcherOptions, CharacterJoinerHandler, IBufferLine, IBufferStringIterator, ICellData, IAttributeData } from '../Types'; import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, ILinkifier, IMouseHelper, ILinkMatcherOptions, CharacterJoinerHandler, IBufferStringIterator } from './Types';
import { ICircularList, XtermListener } from '../common/Types'; import { IBufferLine, ICellData, IAttributeData } from './core/Types';
import { Buffer } from '../Buffer'; import { ICircularList, XtermListener } from './common/Types';
import * as Browser from '../common/Platform'; import { Buffer } from './Buffer';
import * as Browser from './common/Platform';
import { ITheme, IDisposable, IMarker, IEvent } from 'xterm'; import { ITheme, IDisposable, IMarker, IEvent } from 'xterm';
import { Terminal } from '../Terminal'; import { Terminal } from './Terminal';
import { AttributeData } from '../BufferLine'; import { AttributeData } from './core/buffer/BufferLine';
export class TestTerminal extends Terminal { export class TestTerminal extends Terminal {
writeSync(data: string): void { writeSync(data: string): void {
+14 -78
View File
@@ -5,14 +5,12 @@
import { Terminal as PublicTerminal, ITerminalOptions as IPublicTerminalOptions, IEventEmitter, IDisposable } from 'xterm'; import { Terminal as PublicTerminal, ITerminalOptions as IPublicTerminalOptions, IEventEmitter, IDisposable } from 'xterm';
import { IColorSet, IRenderer } from './renderer/Types'; import { IColorSet, IRenderer } from './renderer/Types';
import { IMouseZoneManager } from './ui/Types'; import { ICharset, IAttributeData, ICellData, IBufferLine, CharData } from './core/Types';
import { ICharset } from './core/Types';
import { ICircularList } from './common/Types'; import { ICircularList } from './common/Types';
import { IEvent } from './common/EventEmitter2'; import { IEvent } from './common/EventEmitter2';
export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean; export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean;
export type CharData = [number, string, number, number];
export type LineData = CharData[]; export type LineData = CharData[];
export type LinkMatcherHandler = (event: MouseEvent, uri: string) => void; export type LinkMatcherHandler = (event: MouseEvent, uri: string) => void;
@@ -527,81 +525,19 @@ export interface IEscapeSequenceParser extends IDisposable {
clearErrorHandler(): void; clearErrorHandler(): void;
} }
/** RGB color type */ export interface IMouseZoneManager extends IDisposable {
export type IColorRGB = [number, number, number]; add(zone: IMouseZone): void;
clearAll(start?: number, end?: number): void;
/** Attribute data */
export interface IAttributeData {
fg: number;
bg: number;
clone(): IAttributeData;
// flags
isInverse(): number;
isBold(): number;
isUnderline(): number;
isBlink(): number;
isInvisible(): number;
isItalic(): number;
isDim(): number;
// color modes
getFgColorMode(): number;
getBgColorMode(): number;
isFgRGB(): boolean;
isBgRGB(): boolean;
isFgPalette(): boolean;
isBgPalette(): boolean;
isFgDefault(): boolean;
isBgDefault(): boolean;
// colors
getFgColor(): number;
getBgColor(): number;
} }
/** Cell data */ export interface IMouseZone {
export interface ICellData extends IAttributeData { x1: number;
content: number; x2: number;
combinedData: string; y1: number;
isCombined(): number; y2: number;
getWidth(): number; clickCallback: (e: MouseEvent) => any;
getChars(): string; hoverCallback: (e: MouseEvent) => any | undefined;
getCode(): number; tooltipCallback: (e: MouseEvent) => any | undefined;
setFromCharData(value: CharData): void; leaveCallback: () => any | undefined;
getAsCharData(): CharData; willLinkActivate: (e: MouseEvent) => boolean;
}
/**
* Interface for a line in the terminal buffer.
*/
export interface IBufferLine {
length: number;
isWrapped: boolean;
get(index: number): CharData;
set(index: number, value: CharData): void;
loadCell(index: number, cell: ICellData): ICellData;
setCell(index: number, cell: ICellData): void;
setCellFromCodePoint(index: number, codePoint: number, width: number, fg: number, bg: number): void;
addCodepointToCell(index: number, codePoint: number): void;
insertCells(pos: number, n: number, ch: ICellData): void;
deleteCells(pos: number, n: number, fill: ICellData): void;
replaceCells(start: number, end: number, fill: ICellData): void;
resize(cols: number, fill: ICellData): void;
fill(fillCellData: ICellData): void;
copyFrom(line: IBufferLine): void;
clone(): IBufferLine;
getTrimmedLength(): number;
translateToString(trimRight?: boolean, startCol?: number, endCol?: number): string;
/* direct access to cell attrs */
getWidth(index: number): number;
hasWidth(index: number): number;
getFg(index: number): number;
getBg(index: number): number;
hasContent(index: number): number;
getCodePoint(index: number): number;
isCombined(index: number): number;
getString(index: number): string;
} }
+1 -1
View File
@@ -5,7 +5,7 @@
import { IColorSet } from './renderer/Types'; import { IColorSet } from './renderer/Types';
import { ITerminal, IViewport } from './Types'; import { ITerminal, IViewport } from './Types';
import { CharMeasure } from './ui/CharMeasure'; import { CharMeasure } from './CharMeasure';
import { Disposable } from './common/Lifecycle'; import { Disposable } from './common/Lifecycle';
import { addDisposableDomListener } from './ui/Lifecycle'; import { addDisposableDomListener } from './ui/Lifecycle';
+1 -1
View File
@@ -5,7 +5,7 @@
import { IDisposable } from 'xterm'; import { IDisposable } from 'xterm';
import { ITerminal } from './Types'; import { ITerminal } from './Types';
import { CHAR_DATA_CODE_INDEX, NULL_CELL_CODE, WHITESPACE_CELL_CODE } from './Buffer'; import { CHAR_DATA_CODE_INDEX, NULL_CELL_CODE, WHITESPACE_CELL_CODE } from './core/buffer/BufferLine';
export function applyWindowsMode(terminal: ITerminal): IDisposable { export function applyWindowsMode(terminal: ITerminal): IDisposable {
// Winpty does not support wraparound mode which means that lines will never // Winpty does not support wraparound mode which means that lines will never
+157 -35
View File
@@ -28,63 +28,185 @@ describe('webLinks addon', () => {
}); });
}); });
it('should allow ~ character in URI path', () => { describe('should allow simple URI path', () => {
const term = new MockTerminal(); it('foo.com', () => {
webLinks.webLinksInit(<any>term); const term = new MockTerminal();
webLinks.webLinksInit(<any>term);
const row = ' http://foo.com/a~b#c~d?e~f '; const row = ' http://foo.com ';
const match = row.match(term.regex); const match = row.match(term.regex);
const uri = match[term.options.matchIndex]; const uri = match[term.options.matchIndex];
assert.equal(uri, 'http://foo.com/a~b#c~d?e~f'); assert.equal(uri, 'http://foo.com');
});
it('bar.io', () => {
const term = new MockTerminal();
webLinks.webLinksInit(<any>term);
const row = ' http://bar.io ';
const match = row.match(term.regex);
const uri = match[term.options.matchIndex];
assert.equal(uri, 'http://bar.io');
});
}); });
it('should allow : character in URI path', () => { describe('should allow ~ character in URI path', () => {
const term = new MockTerminal(); it('foo.com', () => {
webLinks.webLinksInit(<any>term); const term = new MockTerminal();
webLinks.webLinksInit(<any>term);
const row = ' http://foo.com/colon:test '; const row = ' http://foo.com/a~b#c~d?e~f ';
const match = row.match(term.regex); const match = row.match(term.regex);
const uri = match[term.options.matchIndex]; const uri = match[term.options.matchIndex];
assert.equal(uri, 'http://foo.com/colon:test'); assert.equal(uri, 'http://foo.com/a~b#c~d?e~f');
});
it('bar.io', () => {
const term = new MockTerminal();
webLinks.webLinksInit(<any>term);
const row = ' http://bar.io/a~b#c~d?e~f ';
const match = row.match(term.regex);
const uri = match[term.options.matchIndex];
assert.equal(uri, 'http://bar.io/a~b#c~d?e~f');
});
}); });
it('should not allow : character at the end of a URI path', () => { describe('should allow : character in URI path', () => {
const term = new MockTerminal(); it('foo.com', () => {
webLinks.webLinksInit(<any>term); const term = new MockTerminal();
webLinks.webLinksInit(<any>term);
const row = ' http://foo.com/colon:test: '; const row = ' http://foo.com/colon:test ';
const match = row.match(term.regex); const match = row.match(term.regex);
const uri = match[term.options.matchIndex]; const uri = match[term.options.matchIndex];
assert.equal(uri, 'http://foo.com/colon:test'); assert.equal(uri, 'http://foo.com/colon:test');
});
it('bar.io', () => {
const term = new MockTerminal();
webLinks.webLinksInit(<any>term);
const row = ' http://bar.io/colon:test ';
const match = row.match(term.regex);
const uri = match[term.options.matchIndex];
assert.equal(uri, 'http://bar.io/colon:test');
});
}); });
it('should not allow " character at the end of a URI enclosed with ""', () => { describe('should not allow : character at the end of a URI path', () => {
const term = new MockTerminal(); it('foo.com', () => {
webLinks.webLinksInit(<any>term); const term = new MockTerminal();
webLinks.webLinksInit(<any>term);
const row = '"http://foo.com/"'; const row = ' http://foo.com/colon:test: ';
const match = row.match(term.regex); const match = row.match(term.regex);
const uri = match[term.options.matchIndex]; const uri = match[term.options.matchIndex];
assert.equal(uri, 'http://foo.com/'); assert.equal(uri, 'http://foo.com/colon:test');
});
it('bar.io', () => {
const term = new MockTerminal();
webLinks.webLinksInit(<any>term);
const row = ' http://bar.io/colon:test: ';
const match = row.match(term.regex);
const uri = match[term.options.matchIndex];
assert.equal(uri, 'http://bar.io/colon:test');
});
}); });
it('should not allow \' character at the end of a URI enclosed with \'\'', () => { describe('should not allow " character at the end of a URI enclosed with ""', () => {
const term = new MockTerminal(); it('foo.com', () => {
webLinks.webLinksInit(<any>term); const term = new MockTerminal();
webLinks.webLinksInit(<any>term);
const row = '\'http://foo.com/\''; const row = '"http://foo.com/"';
const match = row.match(term.regex); const match = row.match(term.regex);
const uri = match[term.options.matchIndex]; const uri = match[term.options.matchIndex];
assert.equal(uri, 'http://foo.com/'); assert.equal(uri, 'http://foo.com/');
});
it('bar.io', () => {
const term = new MockTerminal();
webLinks.webLinksInit(<any>term);
const row = '"http://bar.io/"';
const match = row.match(term.regex);
const uri = match[term.options.matchIndex];
assert.equal(uri, 'http://bar.io/');
});
});
describe('should not allow \' character at the end of a URI enclosed with \'\'', () => {
it('foo.com', () => {
const term = new MockTerminal();
webLinks.webLinksInit(<any>term);
const row = '\'http://foo.com/\'';
const match = row.match(term.regex);
const uri = match[term.options.matchIndex];
assert.equal(uri, 'http://foo.com/');
});
it('bar.io', () => {
const term = new MockTerminal();
webLinks.webLinksInit(<any>term);
const row = '\'http://bar.io/\'';
const match = row.match(term.regex);
const uri = match[term.options.matchIndex];
assert.equal(uri, 'http://bar.io/');
});
});
describe('should allow + character in URI path', () => {
it('foo.com', () => {
const term = new MockTerminal();
webLinks.webLinksInit(<any>term);
const row = 'http://foo.com/subpath/+/id';
const match = row.match(term.regex);
const uri = match[term.options.matchIndex];
assert.equal(uri, 'http://foo.com/subpath/+/id');
});
it('bar.io', () => {
const term = new MockTerminal();
webLinks.webLinksInit(<any>term);
const row = 'http://bar.io/subpath/+/id';
const match = row.match(term.regex);
const uri = match[term.options.matchIndex];
assert.equal(uri, 'http://bar.io/subpath/+/id');
});
}); });
}); });
+2 -1
View File
@@ -14,7 +14,8 @@ const ipClause = '((\\d{1,3}\\.){3}\\d{1,3})';
const localHostClause = '(localhost)'; const localHostClause = '(localhost)';
const portClause = '(:\\d{1,5})'; const portClause = '(:\\d{1,5})';
const hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + '|' + localHostClause + ')' + portClause + '?'; const hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + '|' + localHostClause + ')' + portClause + '?';
const pathClause = '(\\/[\\/\\w\\.\\-%~:]*)*([^:"\'\\s])'; const pathCharacterSet = '(\\/[\\/\\w\\.\\-%~:+]*)*([^:"\'\\s])';
const pathClause = '(' + pathCharacterSet + ')?';
const queryStringHashFragmentCharacterSet = '[0-9\\w\\[\\]\\(\\)\\/\\?\\!#@$%&\'*+,:;~\\=\\.\\-]*'; const queryStringHashFragmentCharacterSet = '[0-9\\w\\[\\]\\(\\)\\/\\?\\!#@$%&\'*+,:;~\\=\\.\\-]*';
const queryStringClause = '(\\?' + queryStringHashFragmentCharacterSet + ')?'; const queryStringClause = '(\\?' + queryStringHashFragmentCharacterSet + ')?';
const hashFragmentClause = '(#' + queryStringHashFragmentCharacterSet + ')?'; const hashFragmentClause = '(#' + queryStringHashFragmentCharacterSet + ')?';
+2
View File
@@ -6,6 +6,8 @@
import { IEvent, EventEmitter2 } from './EventEmitter2'; import { IEvent, EventEmitter2 } from './EventEmitter2';
import { IDeleteEvent, IInsertEvent } from './CircularList'; import { IDeleteEvent, IInsertEvent } from './CircularList';
export const DEFAULT_COLOR = 256;
export interface IDisposable { export interface IDisposable {
dispose(): void; dispose(): void;
} }
+79
View File
@@ -19,3 +19,82 @@ export interface IKeyboardResult {
export interface ICharset { export interface ICharset {
[key: string]: string; [key: string]: string;
} }
export type CharData = [number, string, number, number];
export type IColorRGB = [number, number, number];
/** Attribute data */
export interface IAttributeData {
fg: number;
bg: number;
clone(): IAttributeData;
// flags
isInverse(): number;
isBold(): number;
isUnderline(): number;
isBlink(): number;
isInvisible(): number;
isItalic(): number;
isDim(): number;
// color modes
getFgColorMode(): number;
getBgColorMode(): number;
isFgRGB(): boolean;
isBgRGB(): boolean;
isFgPalette(): boolean;
isBgPalette(): boolean;
isFgDefault(): boolean;
isBgDefault(): boolean;
// colors
getFgColor(): number;
getBgColor(): number;
}
/** Cell data */
export interface ICellData extends IAttributeData {
content: number;
combinedData: string;
isCombined(): number;
getWidth(): number;
getChars(): string;
getCode(): number;
setFromCharData(value: CharData): void;
getAsCharData(): CharData;
}
/**
* Interface for a line in the terminal buffer.
*/
export interface IBufferLine {
length: number;
isWrapped: boolean;
get(index: number): CharData;
set(index: number, value: CharData): void;
loadCell(index: number, cell: ICellData): ICellData;
setCell(index: number, cell: ICellData): void;
setCellFromCodePoint(index: number, codePoint: number, width: number, fg: number, bg: number): void;
addCodepointToCell(index: number, codePoint: number): void;
insertCells(pos: number, n: number, ch: ICellData): void;
deleteCells(pos: number, n: number, fill: ICellData): void;
replaceCells(start: number, end: number, fill: ICellData): void;
resize(cols: number, fill: ICellData): void;
fill(fillCellData: ICellData): void;
copyFrom(line: IBufferLine): void;
clone(): IBufferLine;
getTrimmedLength(): number;
translateToString(trimRight?: boolean, startCol?: number, endCol?: number): string;
/* direct access to cell attrs */
getWidth(index: number): number;
hasWidth(index: number): number;
getFg(index: number): number;
getBg(index: number): number;
hasContent(index: number): number;
getCodePoint(index: number): number;
isCombined(index: number): number;
getString(index: number): string;
}
@@ -3,10 +3,8 @@
* @license MIT * @license MIT
*/ */
import * as chai from 'chai'; import * as chai from 'chai';
import { BufferLine, CellData, Content } from './BufferLine'; import { BufferLine, CellData, Content, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, DEFAULT_ATTR } from './BufferLine';
import { CharData, IBufferLine } from './Types'; import { CharData, IBufferLine } from '../Types';
import { NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, DEFAULT_ATTR } from './Buffer';
class TestBufferLine extends BufferLine { class TestBufferLine extends BufferLine {
public get combined(): {[index: number]: string} { public get combined(): {[index: number]: string} {
@@ -57,7 +55,7 @@ describe('BufferLine', function(): void {
chai.expect(line.length).equals(10); chai.expect(line.length).equals(10);
chai.expect(line.loadCell(0, new CellData()).getAsCharData()).eql([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]); chai.expect(line.loadCell(0, new CellData()).getAsCharData()).eql([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]);
chai.expect(line.isWrapped).equals(false); chai.expect(line.isWrapped).equals(false);
line = new TestBufferLine(10, null, true); line = new TestBufferLine(10, undefined, true);
chai.expect(line.length).equals(10); chai.expect(line.length).equals(10);
chai.expect(line.loadCell(0, new CellData()).getAsCharData()).eql([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]); chai.expect(line.loadCell(0, new CellData()).getAsCharData()).eql([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]);
chai.expect(line.isWrapped).equals(true); chai.expect(line.isWrapped).equals(true);
@@ -127,7 +125,7 @@ describe('BufferLine', function(): void {
]); ]);
}); });
it('clone', function(): void { it('clone', function(): void {
const line = new TestBufferLine(5, null, true); const line = new TestBufferLine(5, undefined, true);
line.setCell(0, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); line.setCell(0, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]));
line.setCell(1, CellData.fromCharData([2, 'b', 0, 'b'.charCodeAt(0)])); line.setCell(1, CellData.fromCharData([2, 'b', 0, 'b'.charCodeAt(0)]));
line.setCell(2, CellData.fromCharData([3, 'c', 0, 'c'.charCodeAt(0)])); line.setCell(2, CellData.fromCharData([3, 'c', 0, 'c'.charCodeAt(0)]));
@@ -167,27 +165,27 @@ describe('BufferLine', function(): void {
it('enlarge(false)', function(): void { it('enlarge(false)', function(): void {
const line = new TestBufferLine(5, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false); const line = new TestBufferLine(5, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false);
line.resize(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); line.resize(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]));
chai.expect(line.toArray()).eql(Array(10).fill([1, 'a', 0, 'a'.charCodeAt(0)])); chai.expect(line.toArray()).eql((Array(10) as any).fill([1, 'a', 0, 'a'.charCodeAt(0)]));
}); });
it('enlarge(true)', function(): void { it('enlarge(true)', function(): void {
const line = new TestBufferLine(5, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false); const line = new TestBufferLine(5, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false);
line.resize(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); line.resize(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]));
chai.expect(line.toArray()).eql(Array(10).fill([1, 'a', 0, 'a'.charCodeAt(0)])); chai.expect(line.toArray()).eql((Array(10) as any).fill([1, 'a', 0, 'a'.charCodeAt(0)]));
}); });
it('shrink(true) - should apply new size', function(): void { it('shrink(true) - should apply new size', function(): void {
const line = new TestBufferLine(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false); const line = new TestBufferLine(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false);
line.resize(5, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); line.resize(5, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]));
chai.expect(line.toArray()).eql(Array(5).fill([1, 'a', 0, 'a'.charCodeAt(0)])); chai.expect(line.toArray()).eql((Array(5) as any).fill([1, 'a', 0, 'a'.charCodeAt(0)]));
}); });
it('shrink to 0 length', function(): void { it('shrink to 0 length', function(): void {
const line = new TestBufferLine(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false); const line = new TestBufferLine(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false);
line.resize(0, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); line.resize(0, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]));
chai.expect(line.toArray()).eql(Array(0).fill([1, 'a', 0, 'a'.charCodeAt(0)])); chai.expect(line.toArray()).eql((Array(0) as any).fill([1, 'a', 0, 'a'.charCodeAt(0)]));
}); });
it('should remove combining data on replaced cells after shrinking then enlarging', () => { it('should remove combining data on replaced cells after shrinking then enlarging', () => {
const line = new TestBufferLine(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false); const line = new TestBufferLine(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false);
line.set(2, [ null, '😁', 1, '😁'.charCodeAt(0) ]); line.set(2, [ 0, '😁', 1, '😁'.charCodeAt(0) ]);
line.set(9, [ null, '😁', 1, '😁'.charCodeAt(0) ]); line.set(9, [ 0, '😁', 1, '😁'.charCodeAt(0) ]);
chai.expect(line.translateToString()).eql('aa😁aaaaaa😁'); chai.expect(line.translateToString()).eql('aa😁aaaaaa😁');
chai.expect(Object.keys(line.combined).length).eql(2); chai.expect(Object.keys(line.combined).length).eql(2);
line.resize(5, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); line.resize(5, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]));
@@ -224,7 +222,7 @@ describe('BufferLine', function(): void {
const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false);
line.setCell(0, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); line.setCell(0, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)]));
line.setCell(2, CellData.fromCharData([1, '1', 2, '1'.charCodeAt(0)])); line.setCell(2, CellData.fromCharData([1, '1', 2, '1'.charCodeAt(0)]));
line.setCell(3, CellData.fromCharData([0, '', 0, undefined])); line.setCell(3, CellData.fromCharData([0, '', 0, 0]));
chai.expect(line.getTrimmedLength()).equal(4); // also counts null cell after fullwidth chai.expect(line.getTrimmedLength()).equal(4); // also counts null cell after fullwidth
}); });
}); });
@@ -284,11 +282,11 @@ describe('BufferLine', function(): void {
const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false);
line.setCell(0, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); line.setCell(0, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)]));
line.setCell(2, CellData.fromCharData([1, '1', 2, '1'.charCodeAt(0)])); line.setCell(2, CellData.fromCharData([1, '1', 2, '1'.charCodeAt(0)]));
line.setCell(3, CellData.fromCharData([0, '', 0, undefined])); line.setCell(3, CellData.fromCharData([0, '', 0, 0]));
line.setCell(5, CellData.fromCharData([1, '1', 2, '1'.charCodeAt(0)])); line.setCell(5, CellData.fromCharData([1, '1', 2, '1'.charCodeAt(0)]));
line.setCell(6, CellData.fromCharData([0, '', 0, undefined])); line.setCell(6, CellData.fromCharData([0, '', 0, 0]));
line.setCell(7, CellData.fromCharData([1, '1', 2, '1'.charCodeAt(0)])); line.setCell(7, CellData.fromCharData([1, '1', 2, '1'.charCodeAt(0)]));
line.setCell(8, CellData.fromCharData([0, '', 0, undefined])); line.setCell(8, CellData.fromCharData([0, '', 0, 0]));
chai.expect(line.translateToString(false)).equal('a 1 11 '); chai.expect(line.translateToString(false)).equal('a 1 11 ');
chai.expect(line.translateToString(true)).equal('a 1 11'); chai.expect(line.translateToString(true)).equal('a 1 11');
chai.expect(line.translateToString(false, 0, 7)).equal('a 1 1'); chai.expect(line.translateToString(false, 0, 7)).equal('a 1 1');
@@ -2,10 +2,34 @@
* Copyright (c) 2018 The xterm.js authors. All rights reserved. * Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT * @license MIT
*/ */
import { CharData, IBufferLine, ICellData, IColorRGB, IAttributeData } from './Types'; import { CharData, IBufferLine, ICellData, IColorRGB, IAttributeData } from '../Types';
import { NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, WHITESPACE_CELL_CHAR, CHAR_DATA_ATTR_INDEX } from './Buffer'; import { stringFromCodePoint } from '../input/TextDecoder';
import { stringFromCodePoint } from './core/input/TextDecoder'; import { DEFAULT_COLOR } from '../../common/Types';
export const DEFAULT_ATTR = (0 << 18) | (DEFAULT_COLOR << 9) | (256 << 0);
export const CHAR_DATA_ATTR_INDEX = 0;
export const CHAR_DATA_CHAR_INDEX = 1;
export const CHAR_DATA_WIDTH_INDEX = 2;
export const CHAR_DATA_CODE_INDEX = 3;
/**
* Null cell - a real empty cell (containing nothing).
* Note that code should always be 0 for a null cell as
* several test condition of the buffer line rely on this.
*/
export const NULL_CELL_CHAR = '';
export const NULL_CELL_WIDTH = 1;
export const NULL_CELL_CODE = 0;
/**
* Whitespace cell.
* This is meant as a replacement for empty cells when needed
* during rendering lines to preserve correct aligment.
*/
export const WHITESPACE_CELL_CHAR = ' ';
export const WHITESPACE_CELL_WIDTH = 1;
export const WHITESPACE_CELL_CODE = 32;
/** /**
* buffer memory layout: * buffer memory layout:
@@ -193,6 +217,8 @@ export class AttributeData implements IAttributeData {
} }
} }
export const DEFAULT_ATTR_DATA = new AttributeData();
/** /**
* CellData - represents a single Cell in the terminal buffer. * CellData - represents a single Cell in the terminal buffer.
*/ */
@@ -299,17 +325,15 @@ export class CellData extends AttributeData implements ICellData {
* memory allocs / GC pressure can be greatly reduced by reusing the CellData object. * memory allocs / GC pressure can be greatly reduced by reusing the CellData object.
*/ */
export class BufferLine implements IBufferLine { export class BufferLine implements IBufferLine {
protected _data: Uint32Array | null = null; protected _data: Uint32Array;
protected _combined: {[index: number]: string} = {}; protected _combined: {[index: number]: string} = {};
public length: number; public length: number;
constructor(cols: number, fillCellData?: ICellData, public isWrapped: boolean = false) { constructor(cols: number, fillCellData?: ICellData, public isWrapped: boolean = false) {
if (cols) { this._data = new Uint32Array(cols * CELL_SIZE);
this._data = new Uint32Array(cols * CELL_SIZE); const cell = fillCellData || CellData.fromCharData([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]);
const cell = fillCellData || CellData.fromCharData([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]); for (let i = 0; i < cols; ++i) {
for (let i = 0; i < cols; ++i) { this.setCell(i, cell);
this.setCell(i, cell);
}
} }
this.length = cols; this.length = cols;
} }
@@ -547,7 +571,7 @@ export class BufferLine implements IBufferLine {
} }
} }
} else { } else {
this._data = null; this._data = new Uint32Array(0);
this._combined = {}; this._combined = {};
} }
} }
+4
View File
@@ -352,6 +352,10 @@ export function evaluateKeyboardEvent(
} else if (ev.key && !ev.ctrlKey && !ev.altKey && !ev.metaKey && ev.keyCode >= 48 && ev.key.length === 1) { } else if (ev.key && !ev.ctrlKey && !ev.altKey && !ev.metaKey && ev.keyCode >= 48 && ev.key.length === 1) {
// Include only keys that that result in a _single_ character; don't include num lock, volume up, etc. // Include only keys that that result in a _single_ character; don't include num lock, volume up, etc.
result.key = ev.key; result.key = ev.key;
} else if (ev.key && ev.ctrlKey) {
if (ev.key === '_') { // ^_
result.key = C0.US;
}
} }
break; break;
} }
+29 -25
View File
@@ -6,6 +6,10 @@
/** /**
* Polyfill - Convert UTF32 codepoint into JS string. * Polyfill - Convert UTF32 codepoint into JS string.
* Note: The built-in String.fromCodePoint happens to be much slower
* due to additional sanity checks. We can avoid them since
* we always operate on legal UTF32 (granted by the input decoders)
* and use this faster version instead.
*/ */
export function stringFromCodePoint(codePoint: number): string { export function stringFromCodePoint(codePoint: number): string {
if (codePoint > 0xFFFF) { if (codePoint > 0xFFFF) {
@@ -16,6 +20,31 @@ export function stringFromCodePoint(codePoint: number): string {
} }
/**
* Convert UTF32 char codes into JS string.
* Basically the same as `stringFromCodePoint` but for multiple codepoints
* in a loop (which is a lot faster).
*/
export function utf32ToString(data: Uint32Array, start: number = 0, end: number = data.length): string {
let result = '';
for (let i = start; i < end; ++i) {
let codepoint = data[i];
if (codepoint > 0xFFFF) {
// JS string are encoded as UTF16, thus a non BMP codepoint gets converted into a surrogate pair
// conversion rules:
// - subtract 0x10000 from code point, leaving a 20 bit number
// - add high 10 bits to 0xD800 --> first surrogate
// - add low 10 bits to 0xDC00 --> second surrogate
codepoint -= 0x10000;
result += String.fromCharCode((codepoint >> 10) + 0xD800) + String.fromCharCode((codepoint % 0x400) + 0xDC00);
} else {
result += String.fromCharCode(codepoint);
}
}
return result;
}
/** /**
* StringToUtf32 - decodes UTF16 sequences into UTF32 codepoints. * StringToUtf32 - decodes UTF16 sequences into UTF32 codepoints.
* To keep the decoder in line with JS strings it handles single surrogates as UCS2. * To keep the decoder in line with JS strings it handles single surrogates as UCS2.
@@ -315,28 +344,3 @@ export class Utf8ToUtf32 {
return size; return size;
} }
} }
/**
* Convert UTF32 char codes into JS string.
* Basically the same as `stringFromCodePoint` but for multiple codepoints
* in a loop (which is a lot faster).
*/
export function utf32ToString(data: Uint32Array, start: number = 0, end: number = data.length): string {
let result = '';
for (let i = start; i < end; ++i) {
let codepoint = data[i];
if (codepoint > 0xFFFF) {
// JS string are encoded as UTF16, thus a non BMP codepoint gets converted into a surrogate pair
// conversion rules:
// - subtract 0x10000 from code point, leaving a 20 bit number
// - add high 10 bits to 0xD800 --> first surrogate
// - add low 10 bits to 0xDC00 --> second surrogate
codepoint -= 0x10000;
result += String.fromCharCode((codepoint >> 10) + 0xD800) + String.fromCharCode((codepoint % 0x400) + 0xDC00);
} else {
result += String.fromCharCode(codepoint);
}
}
return result;
}
+2 -1
View File
@@ -3,7 +3,8 @@
* @license MIT * @license MIT
*/ */
import { ITerminal, IBufferLine } from '../Types'; import { ITerminal } from '../Types';
import { IBufferLine } from '../core/Types';
import { ICircularList } from '../common/Types'; import { ICircularList } from '../common/Types';
import { C0 } from '../common/data/EscapeSequences'; import { C0 } from '../common/data/EscapeSequences';
+1 -1
View File
@@ -30,7 +30,7 @@ export class Terminal implements ITerminalApi {
public get textarea(): HTMLTextAreaElement { return this._core.textarea; } public get textarea(): HTMLTextAreaElement { return this._core.textarea; }
public get rows(): number { return this._core.rows; } public get rows(): number { return this._core.rows; }
public get cols(): number { return this._core.cols; } public get cols(): number { return this._core.cols; }
public get markers(): IMarker[] { return this._core.markers; } public get markers(): ReadonlyArray<IMarker> { return this._core.markers; }
public blur(): void { public blur(): void {
this._core.blur(); this._core.blur();
} }
+21 -12
View File
@@ -4,12 +4,14 @@
*/ */
import { IRenderLayer, IColorSet, IRenderDimensions } from './Types'; import { IRenderLayer, IColorSet, IRenderDimensions } from './Types';
import { ITerminal, ICellData } from '../Types'; import { ITerminal } from '../Types';
import { DIM_OPACITY, INVERTED_DEFAULT_COLOR, IGlyphIdentifier, DEFAULT_COLOR } from './atlas/Types'; import { ICellData } from '../core/Types';
import { DEFAULT_COLOR } from '../common/Types';
import { DIM_OPACITY, INVERTED_DEFAULT_COLOR, IGlyphIdentifier } from './atlas/Types';
import BaseCharAtlas from './atlas/BaseCharAtlas'; import BaseCharAtlas from './atlas/BaseCharAtlas';
import { acquireCharAtlas } from './atlas/CharAtlasCache'; import { acquireCharAtlas } from './atlas/CharAtlasCache';
import { CellData, AttributeData } from '../BufferLine'; import { CellData, AttributeData, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_CODE } from '../core/buffer/BufferLine';
import { WHITESPACE_CELL_CHAR, WHITESPACE_CELL_CODE } from '../Buffer'; import { JoinedCellData } from './CharacterJoinerRegistry';
export abstract class BaseRenderLayer implements IRenderLayer { export abstract class BaseRenderLayer implements IRenderLayer {
private _canvas: HTMLCanvasElement; private _canvas: HTMLCanvasElement;
@@ -261,7 +263,10 @@ export abstract class BaseRenderLayer implements IRenderLayer {
protected drawChars(terminal: ITerminal, cell: ICellData, x: number, y: number): void { protected drawChars(terminal: ITerminal, cell: ICellData, x: number, y: number): void {
// skip cache right away if we draw in RGB // skip cache right away if we draw in RGB
if (cell.isFgRGB() || cell.isBgRGB()) { // Note: to avoid bad runtime JoinedCellData will be skipped
// in the cache handler (atlasDidDraw == false) itself and
// fall through to uncached later down below
if (cell.isFgRGB() || cell.isBgRGB() || cell instanceof JoinedCellData) {
this._drawUncachedChars(terminal, cell, x, y); this._drawUncachedChars(terminal, cell, x, y);
return; return;
} }
@@ -322,14 +327,18 @@ export abstract class BaseRenderLayer implements IRenderLayer {
} else { } else {
this._ctx.fillStyle = this._colors.ansi[cell.getBgColor()].css; this._ctx.fillStyle = this._colors.ansi[cell.getBgColor()].css;
} }
} else if (cell.isFgRGB()) { } else {
this._ctx.fillStyle = `rgb(${AttributeData.toColorRGB(cell.getFgColor()).join(',')})`; if (cell.isFgDefault()) {
} else if (cell.isFgPalette()) { this._ctx.fillStyle = this._colors.foreground.css;
let fg = cell.getFgColor(); } else if (cell.isFgRGB()) {
if (terminal.options.drawBoldTextInBrightColors && cell.isBold() && fg < 8) { this._ctx.fillStyle = `rgb(${AttributeData.toColorRGB(cell.getFgColor()).join(',')})`;
fg += 8; } else {
let fg = cell.getFgColor();
if (terminal.options.drawBoldTextInBrightColors && cell.isBold() && fg < 8) {
fg += 8;
}
this._ctx.fillStyle = this._colors.ansi[fg].css;
} }
this._ctx.fillStyle = this._colors.ansi[fg].css;
} }
this._clipRow(terminal, y); this._clipRow(terminal, y);
+8 -3
View File
@@ -1,12 +1,17 @@
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { assert } from 'chai'; import { assert } from 'chai';
import { MockTerminal, MockBuffer } from '../ui/TestUtils.test'; import { MockTerminal, MockBuffer } from '../TestUtils.test';
import { CircularList } from '../common/CircularList'; import { CircularList } from '../common/CircularList';
import { ICharacterJoinerRegistry } from './Types'; import { ICharacterJoinerRegistry } from './Types';
import { CharacterJoinerRegistry } from './CharacterJoinerRegistry'; import { CharacterJoinerRegistry } from './CharacterJoinerRegistry';
import { BufferLine, CellData } from '../BufferLine'; import { BufferLine, CellData } from '../core/buffer/BufferLine';
import { IBufferLine } from '../Types'; import { IBufferLine } from '../core/Types';
describe('CharacterJoinerRegistry', () => { describe('CharacterJoinerRegistry', () => {
let registry: ICharacterJoinerRegistry; let registry: ICharacterJoinerRegistry;
+53 -3
View File
@@ -1,7 +1,57 @@
import { ITerminal, IBufferLine } from '../Types'; /**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { ITerminal } from '../Types';
import { IBufferLine, ICellData, CharData } from '../core/Types';
import { ICharacterJoinerRegistry, ICharacterJoiner } from './Types'; import { ICharacterJoinerRegistry, ICharacterJoiner } from './Types';
import { CellData } from '../BufferLine'; import { CellData, Content, AttributeData, WHITESPACE_CELL_CHAR } from '../core/buffer/BufferLine';
import { WHITESPACE_CELL_CHAR } from '../Buffer';
export class JoinedCellData extends AttributeData implements ICellData {
private _width: number;
// .content carries no meaning for joined CellData, simply nullify it
// thus we have to overload all other .content accessors
public content: number = 0;
public fg: number;
public bg: number;
public combinedData: string = '';
constructor(firstCell: ICellData, chars: string, width: number) {
super();
this.fg = firstCell.fg;
this.bg = firstCell.bg;
this.combinedData = chars;
this._width = width;
}
public isCombined(): number {
// always mark joined cell data as combined
return Content.IS_COMBINED_MASK;
}
public getWidth(): number {
return this._width;
}
public getChars(): string {
return this.combinedData;
}
public getCode(): number {
// code always gets the highest possible fake codepoint (read as -1)
// this is needed as code is used by caches as identifier
return 0x1FFFFF;
}
public setFromCharData(value: CharData): void {
throw new Error('not implemented');
}
public getAsCharData(): CharData {
return [this.fg, this.getChars(), this.getWidth(), this.getCode()];
}
}
export class CharacterJoinerRegistry implements ICharacterJoinerRegistry { export class CharacterJoinerRegistry implements ICharacterJoinerRegistry {
+3 -2
View File
@@ -5,8 +5,9 @@
import { IColorSet, IRenderDimensions } from './Types'; import { IColorSet, IRenderDimensions } from './Types';
import { BaseRenderLayer } from './BaseRenderLayer'; import { BaseRenderLayer } from './BaseRenderLayer';
import { ITerminal, ICellData } from '../Types'; import { ITerminal } from '../Types';
import { CellData } from '../BufferLine'; import { ICellData } from '../core/Types';
import { CellData } from '../core/buffer/BufferLine';
interface ICursorState { interface ICursorState {
x: number; x: number;
+2 -2
View File
@@ -68,7 +68,7 @@ export class Renderer extends Disposable implements IRenderer {
this._updateDimensions(); this._updateDimensions();
this.onOptionsChanged(); this.onOptionsChanged();
this._renderDebouncer = new RenderDebouncer(this._terminal, this._renderRows.bind(this)); this._renderDebouncer = new RenderDebouncer(this._renderRows.bind(this));
this._screenDprMonitor = new ScreenDprMonitor(); this._screenDprMonitor = new ScreenDprMonitor();
this._screenDprMonitor.setListener(() => this.onWindowResize(window.devicePixelRatio)); this._screenDprMonitor.setListener(() => this.onWindowResize(window.devicePixelRatio));
this.register(this._screenDprMonitor); this.register(this._screenDprMonitor);
@@ -194,7 +194,7 @@ export class Renderer extends Disposable implements IRenderer {
this._needsFullRefresh = true; this._needsFullRefresh = true;
return; return;
} }
this._renderDebouncer.refresh(start, end); this._renderDebouncer.refresh(start, end, this._terminal.rows);
} }
/** /**
+21 -15
View File
@@ -3,12 +3,13 @@
* @license MIT * @license MIT
*/ */
import { NULL_CELL_CODE } from '../Buffer';
import { IColorSet, IRenderDimensions, ICharacterJoinerRegistry } from './Types'; import { IColorSet, IRenderDimensions, ICharacterJoinerRegistry } from './Types';
import { CharData, ITerminal, ICellData } from '../Types'; import { ITerminal } from '../Types';
import { CharData, ICellData } from '../core/Types';
import { GridCache } from './GridCache'; import { GridCache } from './GridCache';
import { BaseRenderLayer } from './BaseRenderLayer'; import { BaseRenderLayer } from './BaseRenderLayer';
import { CellData, AttributeData, Content } from '../BufferLine'; import { CellData, AttributeData, Content, NULL_CELL_CODE } from '../core/buffer/BufferLine';
import { JoinedCellData } from './CharacterJoinerRegistry';
/** /**
* This CharData looks like a null character, which will forc a clear and render * This CharData looks like a null character, which will forc a clear and render
@@ -89,15 +90,12 @@ export class TextRenderLayer extends BaseRenderLayer {
// We already know the exact start and end column of the joined range, // We already know the exact start and end column of the joined range,
// so we get the string and width representing it directly // so we get the string and width representing it directly
cell = CellData.fromCharData([
0, cell = new JoinedCellData(
this._workCell,
line.translateToString(true, range[0], range[1]), line.translateToString(true, range[0], range[1]),
range[1] - range[0], range[1] - range[0]
0xFFFFFF );
]);
// hacky: patch attrs
cell.fg = this._workCell.fg;
cell.bg = this._workCell.bg;
// Skip over the cells occupied by this range in the loop // Skip over the cells occupied by this range in the loop
lastCharX = range[1] - 1; lastCharX = range[1] - 1;
@@ -217,10 +215,18 @@ export class TextRenderLayer extends BaseRenderLayer {
} else { } else {
this._ctx.fillStyle = this._colors.ansi[cell.getBgColor()].css; this._ctx.fillStyle = this._colors.ansi[cell.getBgColor()].css;
} }
} else if (cell.isFgRGB()) { } else {
this._ctx.fillStyle = `rgb(${AttributeData.toColorRGB(cell.getFgColor()).join(',')})`; if (cell.isFgDefault()) {
} else if (cell.isFgPalette()) { this._ctx.fillStyle = this._colors.foreground.css;
this._ctx.fillStyle = this._colors.ansi[cell.getFgColor()].css; } else if (cell.isFgRGB()) {
this._ctx.fillStyle = `rgb(${AttributeData.toColorRGB(cell.getFgColor()).join(',')})`;
} else {
let fg = cell.getFgColor();
if (terminal.options.drawBoldTextInBrightColors && cell.isBold() && fg < 8) {
fg += 8;
}
this._ctx.fillStyle = this._colors.ansi[fg].css;
}
} }
this.fillBottomLineAtCells(x, y, cell.getWidth()); this.fillBottomLineAtCells(x, y, cell.getWidth());
+2 -1
View File
@@ -5,7 +5,8 @@
import { ITerminal } from '../../Types'; import { ITerminal } from '../../Types';
import { IColorSet } from '../Types'; import { IColorSet } from '../Types';
import { DEFAULT_COLOR, ICharAtlasConfig } from './Types'; import { ICharAtlasConfig } from './Types';
import { DEFAULT_COLOR } from '../../common/Types';
export function generateConfig(scaledCharWidth: number, scaledCharHeight: number, terminal: ITerminal, colors: IColorSet): ICharAtlasConfig { export function generateConfig(scaledCharWidth: number, scaledCharHeight: number, terminal: ITerminal, colors: IColorSet): ICharAtlasConfig {
// null out some fields that don't matter // null out some fields that don't matter
+2 -1
View File
@@ -3,10 +3,11 @@
* @license MIT * @license MIT
*/ */
import { DIM_OPACITY, IGlyphIdentifier, DEFAULT_COLOR, ICharAtlasConfig, CHAR_ATLAS_CELL_SPACING } from './Types'; import { DIM_OPACITY, IGlyphIdentifier, ICharAtlasConfig, CHAR_ATLAS_CELL_SPACING } from './Types';
import { generateStaticCharAtlasTexture } from './CharAtlasGenerator'; import { generateStaticCharAtlasTexture } from './CharAtlasGenerator';
import BaseCharAtlas from './BaseCharAtlas'; import BaseCharAtlas from './BaseCharAtlas';
import { is256Color } from './CharAtlasUtils'; import { is256Color } from './CharAtlasUtils';
import { DEFAULT_COLOR } from '../../common/Types';
export default class StaticCharAtlas extends BaseCharAtlas { export default class StaticCharAtlas extends BaseCharAtlas {
private _texture: HTMLCanvasElement | ImageBitmap; private _texture: HTMLCanvasElement | ImageBitmap;
-1
View File
@@ -6,7 +6,6 @@
import { FontWeight } from 'xterm'; import { FontWeight } from 'xterm';
import { IColorSet } from '../Types'; import { IColorSet } from '../Types';
export const DEFAULT_COLOR = 256;
export const INVERTED_DEFAULT_COLOR = 257; export const INVERTED_DEFAULT_COLOR = 257;
export const DIM_OPACITY = 0.5; export const DIM_OPACITY = 0.5;
+5 -5
View File
@@ -80,7 +80,7 @@ export class DomRenderer extends Disposable implements IRenderer {
}; };
this._updateDimensions(); this._updateDimensions();
this._renderDebouncer = new RenderDebouncer(this._terminal, this._renderRows.bind(this)); this._renderDebouncer = new RenderDebouncer(this._renderRows.bind(this));
this._rowFactory = new DomRendererRowFactory(_terminal.options, document); this._rowFactory = new DomRendererRowFactory(_terminal.options, document);
this._terminal.element.classList.add(TERMINAL_CLASS_PREFIX + this._terminalClass); this._terminal.element.classList.add(TERMINAL_CLASS_PREFIX + this._terminalClass);
@@ -101,7 +101,7 @@ export class DomRenderer extends Disposable implements IRenderer {
} }
private _updateDimensions(): void { private _updateDimensions(): void {
this.dimensions.scaledCharWidth = Math.floor(this._terminal.charMeasure.width * window.devicePixelRatio); this.dimensions.scaledCharWidth = this._terminal.charMeasure.width * window.devicePixelRatio;
this.dimensions.scaledCharHeight = Math.ceil(this._terminal.charMeasure.height * window.devicePixelRatio); this.dimensions.scaledCharHeight = Math.ceil(this._terminal.charMeasure.height * window.devicePixelRatio);
this.dimensions.scaledCellWidth = this.dimensions.scaledCharWidth + Math.round(this._terminal.options.letterSpacing); this.dimensions.scaledCellWidth = this.dimensions.scaledCharWidth + Math.round(this._terminal.options.letterSpacing);
this.dimensions.scaledCellHeight = Math.floor(this.dimensions.scaledCharHeight * this._terminal.options.lineHeight); this.dimensions.scaledCellHeight = Math.floor(this.dimensions.scaledCharHeight * this._terminal.options.lineHeight);
@@ -174,9 +174,9 @@ export class DomRenderer extends Disposable implements IRenderer {
// Blink animation // Blink animation
styles += styles +=
`@keyframes blink {` + `@keyframes blink {` +
` 0 % { opacity: 1.0; }` + ` 0% { opacity: 1.0; }` +
` 50% { opacity: 0.0; }` + ` 50% { opacity: 0.0; }` +
` 100 % { opacity: 1.0; }` + ` 100% { opacity: 1.0; }` +
`}`; `}`;
// Cursor // Cursor
styles += styles +=
@@ -340,7 +340,7 @@ export class DomRenderer extends Disposable implements IRenderer {
} }
public refreshRows(start: number, end: number): void { public refreshRows(start: number, end: number): void {
this._renderDebouncer.refresh(start, end); this._renderDebouncer.refresh(start, end, this._terminal.rows);
} }
private _renderRows(start: number, end: number): void { private _renderRows(start: number, end: number): void {
@@ -6,9 +6,9 @@
import jsdom = require('jsdom'); import jsdom = require('jsdom');
import { assert } from 'chai'; import { assert } from 'chai';
import { DomRendererRowFactory } from './DomRendererRowFactory'; import { DomRendererRowFactory } from './DomRendererRowFactory';
import { DEFAULT_ATTR, NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, DEFAULT_ATTR_DATA } from '../../Buffer'; import { BufferLine, CellData, FgFlags, BgFlags, Attributes, NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, DEFAULT_ATTR, DEFAULT_ATTR_DATA } from '../../core/buffer/BufferLine';
import { BufferLine, CellData, FgFlags, BgFlags, Attributes } from '../../BufferLine'; import { ITerminalOptions } from '../../Types';
import { IBufferLine, ITerminalOptions } from '../../Types'; import { IBufferLine } from '../../core/Types';
describe('DomRendererRowFactory', () => { describe('DomRendererRowFactory', () => {
let dom: jsdom.JSDOM; let dom: jsdom.JSDOM;
+3 -3
View File
@@ -3,10 +3,10 @@
* @license MIT * @license MIT
*/ */
import { NULL_CELL_CODE, WHITESPACE_CELL_CHAR } from '../../Buffer'; import { ITerminalOptions } from '../../Types';
import { IBufferLine, ITerminalOptions } from '../../Types'; import { IBufferLine } from '../../core/Types';
import { INVERTED_DEFAULT_COLOR } from '../atlas/Types'; import { INVERTED_DEFAULT_COLOR } from '../atlas/Types';
import { CellData, AttributeData } from '../../BufferLine'; import { CellData, AttributeData, NULL_CELL_CODE, WHITESPACE_CELL_CHAR } from '../../core/buffer/BufferLine';
export const BOLD_CLASS = 'xterm-bold'; export const BOLD_CLASS = 'xterm-bold';
export const DIM_CLASS = 'xterm-dim'; export const DIM_CLASS = 'xterm-dim';
+2 -1
View File
@@ -24,6 +24,7 @@
], ],
"references": [ "references": [
{ "path": "./common" }, { "path": "./common" },
{ "path": "./core" } { "path": "./core" },
{ "path": "./ui" }
] ]
} }
+1 -3
View File
@@ -3,7 +3,7 @@
* @license MIT * @license MIT
*/ */
import { IDisposable } from 'xterm'; import { IDisposable } from '../common/Types';
/** /**
* Adds a disposable listener to a node in the DOM, returning the disposable. * Adds a disposable listener to a node in the DOM, returning the disposable.
@@ -24,8 +24,6 @@ export function addDisposableDomListener(
return; return;
} }
node.removeEventListener(type, handler, useCapture); node.removeEventListener(type, handler, useCapture);
node = null;
handler = null;
} }
}; };
} }
+28 -21
View File
@@ -1,37 +1,39 @@
import { ITerminal } from '../Types'; /**
import { IDisposable } from 'xterm'; * Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { IDisposable } from '../common/Types';
/** /**
* Debounces calls to render terminal rows using animation frames. * Debounces calls to render terminal rows using animation frames.
*/ */
export class RenderDebouncer implements IDisposable { export class RenderDebouncer implements IDisposable {
private _rowStart: number; private _rowStart: number | undefined;
private _rowEnd: number; private _rowEnd: number | undefined;
private _animationFrame: number = null; private _rowCount: number | undefined;
private _animationFrame: number | undefined;
constructor( constructor(
private _terminal: ITerminal, private _renderCallback: (start: number, end: number) => void
private _callback: (start: number, end: number) => void
) { ) {
} }
public dispose(): void { public dispose(): void {
if (this._animationFrame) { if (this._animationFrame) {
window.cancelAnimationFrame(this._animationFrame); window.cancelAnimationFrame(this._animationFrame);
this._animationFrame = null; this._animationFrame = undefined;
} }
} }
public refresh(rowStart: number, rowEnd: number): void { public refresh(rowStart: number, rowEnd: number, rowCount: number): void {
this._rowCount = rowCount;
// Get the min/max row start/end for the arg values // Get the min/max row start/end for the arg values
rowStart = rowStart !== null && rowStart !== undefined ? rowStart : 0; rowStart = rowStart !== undefined ? rowStart : 0;
rowEnd = rowEnd !== null && rowEnd !== undefined ? rowEnd : this._terminal.rows - 1; rowEnd = rowEnd !== undefined ? rowEnd : this._rowCount - 1;
// Check whether the row start/end values have already been set
const isRowStartSet = this._rowStart !== undefined && this._rowStart !== null;
const isRowEndSet = this._rowEnd !== undefined && this._rowEnd !== null;
// Set the properties to the updated values // Set the properties to the updated values
this._rowStart = isRowStartSet ? Math.min(this._rowStart, rowStart) : rowStart; this._rowStart = this._rowStart !== undefined ? Math.min(this._rowStart, rowStart) : rowStart;
this._rowEnd = isRowEndSet ? Math.max(this._rowEnd, rowEnd) : rowEnd; this._rowEnd = this._rowEnd !== undefined ? Math.max(this._rowEnd, rowEnd) : rowEnd;
if (this._animationFrame) { if (this._animationFrame) {
return; return;
@@ -41,16 +43,21 @@ export class RenderDebouncer implements IDisposable {
} }
private _innerRefresh(): void { private _innerRefresh(): void {
// Make sure values are set
if (this._rowStart === undefined || this._rowEnd === undefined || this._rowCount === undefined) {
return;
}
// Clamp values // Clamp values
this._rowStart = Math.max(this._rowStart, 0); this._rowStart = Math.max(this._rowStart, 0);
this._rowEnd = Math.min(this._rowEnd, this._terminal.rows - 1); this._rowEnd = Math.min(this._rowEnd, this._rowCount - 1);
// Run render callback // Run render callback
this._callback(this._rowStart, this._rowEnd); this._renderCallback(this._rowStart, this._rowEnd);
// Reset debouncer // Reset debouncer
this._rowStart = null; this._rowStart = undefined;
this._rowEnd = null; this._rowEnd = undefined;
this._animationFrame = null; this._animationFrame = undefined;
} }
} }
+17 -10
View File
@@ -18,10 +18,10 @@ export type ScreenDprListener = (newDevicePixelRatio?: number, oldDevicePixelRat
* monitor with a different DPI. * monitor with a different DPI.
*/ */
export class ScreenDprMonitor extends Disposable { export class ScreenDprMonitor extends Disposable {
private _currentDevicePixelRatio: number; private _currentDevicePixelRatio: number = window.devicePixelRatio;
private _outerListener: (this: MediaQueryList, ev: MediaQueryListEvent) => any; private _outerListener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | undefined;
private _listener: ScreenDprListener; private _listener: ScreenDprListener | undefined;
private _resolutionMediaMatchList: MediaQueryList; private _resolutionMediaMatchList: MediaQueryList | undefined;
public setListener(listener: ScreenDprListener): void { public setListener(listener: ScreenDprListener): void {
if (this._listener) { if (this._listener) {
@@ -29,6 +29,9 @@ export class ScreenDprMonitor extends Disposable {
} }
this._listener = listener; this._listener = listener;
this._outerListener = () => { this._outerListener = () => {
if (!this._listener) {
return;
}
this._listener(window.devicePixelRatio, this._currentDevicePixelRatio); this._listener(window.devicePixelRatio, this._currentDevicePixelRatio);
this._updateDpr(); this._updateDpr();
}; };
@@ -41,10 +44,13 @@ export class ScreenDprMonitor extends Disposable {
} }
private _updateDpr(): void { private _updateDpr(): void {
// Clear listeners for old DPR if (!this._resolutionMediaMatchList || !this._outerListener) {
if (this._resolutionMediaMatchList) { return;
this._resolutionMediaMatchList.removeListener(this._outerListener);
} }
// Clear listeners for old DPR
this._resolutionMediaMatchList.removeListener(this._outerListener);
// Add listeners for new DPR // Add listeners for new DPR
this._currentDevicePixelRatio = window.devicePixelRatio; this._currentDevicePixelRatio = window.devicePixelRatio;
this._resolutionMediaMatchList = window.matchMedia(`screen and (resolution: ${window.devicePixelRatio}dppx)`); this._resolutionMediaMatchList = window.matchMedia(`screen and (resolution: ${window.devicePixelRatio}dppx)`);
@@ -52,11 +58,12 @@ export class ScreenDprMonitor extends Disposable {
} }
public clearListener(): void { public clearListener(): void {
if (!this._listener) { if (!this._resolutionMediaMatchList || !this._listener || !this._outerListener) {
return; return;
} }
this._resolutionMediaMatchList.removeListener(this._outerListener); this._resolutionMediaMatchList.removeListener(this._outerListener);
this._listener = null; this._resolutionMediaMatchList = undefined;
this._outerListener = null; this._listener = undefined;
this._outerListener = undefined;
} }
} }
-23
View File
@@ -1,23 +0,0 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { IDisposable } from 'xterm';
export interface IMouseZoneManager extends IDisposable {
add(zone: IMouseZone): void;
clearAll(start?: number, end?: number): void;
}
export interface IMouseZone {
x1: number;
x2: number;
y1: number;
y2: number;
clickCallback: (e: MouseEvent) => any;
hoverCallback: (e: MouseEvent) => any | undefined;
tooltipCallback: (e: MouseEvent) => any | undefined;
leaveCallback: () => any | undefined;
willLinkActivate: (e: MouseEvent) => boolean;
}
+21
View File
@@ -0,0 +1,21 @@
{
"extends": "../tsconfig-library-base",
"compilerOptions": {
"lib": [
"dom",
"es5",
],
"outDir": "../../lib",
"types": [
"../../node_modules/@types/mocha"
]
},
"include": [
"./Lifecycle.ts",
"./RenderDebouncer.ts",
"./ScreenDprMonitor.ts"
],
"references": [
{ "path": "../common" }
]
}
+4 -3
View File
@@ -359,7 +359,7 @@ declare module 'xterm' {
* (EXPERIMENTAL) Get all markers registered against the buffer. If the alt * (EXPERIMENTAL) Get all markers registered against the buffer. If the alt
* buffer is active this will always return []. * buffer is active this will always return [].
*/ */
readonly markers: IMarker[]; readonly markers: ReadonlyArray<IMarker>;
/** /**
* Natural language strings that can be localized. * Natural language strings that can be localized.
@@ -594,6 +594,7 @@ declare module 'xterm' {
* @return An IDisposable you can call to remove this handler. * @return An IDisposable you can call to remove this handler.
*/ */
addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable; addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable;
/** /**
* (EXPERIMENTAL) Registers a link matcher, allowing custom link patterns to * (EXPERIMENTAL) Registers a link matcher, allowing custom link patterns to
* be matched and handled. * be matched and handled.
@@ -752,7 +753,7 @@ declare module 'xterm' {
* Retrieves an option's value from the terminal. * Retrieves an option's value from the terminal.
* @param key The option key. * @param key The option key.
*/ */
getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell'): boolean; getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell' | 'windowsMode'): boolean;
/** /**
* Retrieves an option's value from the terminal. * Retrieves an option's value from the terminal.
* @param key The option key. * @param key The option key.
@@ -803,7 +804,7 @@ declare module 'xterm' {
* @param key The option key. * @param key The option key.
* @param value The option value. * @param value The option value.
*/ */
setOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'popOnBell' | 'rightClickSelectsWord' | 'screenKeys' | 'useFlowControl' | 'visualBell', value: boolean): void; setOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'popOnBell' | 'rightClickSelectsWord' | 'screenKeys' | 'useFlowControl' | 'visualBell' | 'windowsMode', value: boolean): void;
/** /**
* Sets an option on the terminal. * Sets an option on the terminal.
* @param key The option key. * @param key The option key.