@xterm/xterm 5.6.0-beta.4 → 5.6.0-beta.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/css/xterm.css +6 -0
- package/lib/xterm.js +1 -1
- package/lib/xterm.js.map +1 -1
- package/lib/xterm.mjs +26 -0
- package/lib/xterm.mjs.map +7 -0
- package/package.json +37 -28
- package/src/browser/AccessibilityManager.ts +39 -11
- package/src/browser/{Terminal.ts → CoreBrowserTerminal.ts} +2 -2
- package/src/browser/LocalizableStrings.ts +15 -4
- package/src/browser/{Types.d.ts → Types.ts} +53 -4
- package/src/browser/Viewport.ts +7 -1
- package/src/browser/decorations/BufferDecorationRenderer.ts +6 -1
- package/src/browser/public/Terminal.ts +14 -6
- package/src/browser/renderer/dom/DomRenderer.ts +3 -5
- package/src/browser/renderer/shared/CustomGlyphs.ts +6 -0
- package/src/browser/services/CoreBrowserService.ts +7 -3
- package/src/browser/services/ThemeService.ts +2 -50
- package/src/common/EventEmitter.ts +6 -11
- package/src/common/InputHandler.ts +11 -7
- package/src/common/SortedList.ts +86 -10
- package/src/common/{Types.d.ts → Types.ts} +2 -2
- package/src/common/buffer/Buffer.ts +1 -1
- package/src/common/services/DecorationService.ts +2 -1
- package/typings/xterm.d.ts +5 -3
- /package/src/browser/renderer/shared/{Types.d.ts → Types.ts} +0 -0
- /package/src/browser/selection/{Types.d.ts → Types.ts} +0 -0
- /package/src/common/buffer/{Types.d.ts → Types.ts} +0 -0
- /package/src/common/parser/{Types.d.ts → Types.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xterm/xterm",
|
|
3
3
|
"description": "Full xterm terminal, in your browser",
|
|
4
|
-
"version": "5.6.0-beta.
|
|
4
|
+
"version": "5.6.0-beta.40",
|
|
5
5
|
"main": "lib/xterm.js",
|
|
6
|
+
"module": "lib/xterm.mjs",
|
|
6
7
|
"style": "css/xterm.css",
|
|
7
8
|
"types": "typings/xterm.d.ts",
|
|
8
9
|
"repository": "https://github.com/xtermjs/xterm.js",
|
|
@@ -23,44 +24,51 @@
|
|
|
23
24
|
"xterm"
|
|
24
25
|
],
|
|
25
26
|
"scripts": {
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"postpackage-headless": "node ./bin/package_headless.js",
|
|
27
|
+
"setup": "npm run build",
|
|
28
|
+
"presetup": "npm run install-addons",
|
|
29
|
+
"install-addons": "node ./bin/install-addons.js",
|
|
30
30
|
"start": "node demo/start",
|
|
31
|
-
"start-server-only": "node demo/start-server-only",
|
|
32
31
|
"build-demo": "webpack --config ./demo/webpack.config.js",
|
|
33
|
-
"
|
|
34
|
-
"
|
|
32
|
+
"build": "npm run tsc",
|
|
33
|
+
"watch": "npm run tsc-watch",
|
|
34
|
+
"tsc": "tsc -b ./tsconfig.all.json",
|
|
35
|
+
"tsc-watch": "tsc -b -w ./tsconfig.all.json --preserveWatchOutput",
|
|
36
|
+
"esbuild": "node bin/esbuild_all.mjs",
|
|
37
|
+
"esbuild-watch": "node bin/esbuild_all.mjs --watch",
|
|
38
|
+
"esbuild-package": "node bin/esbuild_all.mjs --prod",
|
|
39
|
+
"esbuild-package-watch": "node bin/esbuild_all.mjs --prod --watch",
|
|
40
|
+
"esbuild-package-headless-only": "node bin/esbuild.mjs --prod --headless",
|
|
41
|
+
"esbuild-demo": "node bin/esbuild.mjs --demo-client",
|
|
42
|
+
"esbuild-demo-watch": "node bin/esbuild.mjs --demo-client --watch",
|
|
35
43
|
"test": "npm run test-unit",
|
|
36
44
|
"posttest": "npm run lint",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"test-api-firefox": "node ./bin/test_api.js --browser=firefox --timeout=20000",
|
|
40
|
-
"test-api-webkit": "node ./bin/test_api.js --browser=webkit --timeout=20000",
|
|
41
|
-
"test-playwright": "node ./bin/test_playwright.js --workers=75%",
|
|
42
|
-
"test-playwright-chromium": "node ./bin/test_playwright.js --workers=75% \"--project=Chrome Stable\"",
|
|
43
|
-
"test-playwright-firefox": "node ./bin/test_playwright.js --workers=75% \"--project=Firefox Stable\"",
|
|
44
|
-
"test-playwright-webkit": "node ./bin/test_playwright.js --workers=75% \"--project=WebKit\"",
|
|
45
|
-
"test-playwright-debug": "node ./bin/test_playwright.js --workers=1 --headed --timeout=30000",
|
|
45
|
+
"lint": "eslint -c .eslintrc.json --max-warnings 0 --ext .ts src/ addons/",
|
|
46
|
+
"lint-api": "eslint --no-eslintrc -c .eslintrc.json.typings --max-warnings 0 --no-ignore --ext .d.ts typings/",
|
|
46
47
|
"test-unit": "node ./bin/test.js",
|
|
47
48
|
"test-unit-coverage": "node ./bin/test.js --coverage",
|
|
48
49
|
"test-unit-dev": "cross-env NODE_PATH='./out' mocha",
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"watch": "tsc -b -w ./tsconfig.all.json --preserveWatchOutput",
|
|
50
|
+
"test-integration": "node ./bin/test_playwright.js --workers=75%",
|
|
51
|
+
"test-integration-chromium": "node ./bin/test_playwright.js --workers=75% \"--project=ChromeStable\"",
|
|
52
|
+
"test-integration-firefox": "node ./bin/test_playwright.js --workers=75% \"--project=FirefoxStable\"",
|
|
53
|
+
"test-integration-webkit": "node ./bin/test_playwright.js --workers=75% \"--project=WebKit\"",
|
|
54
|
+
"test-integration-debug": "node ./bin/test_playwright.js --workers=1 --headed --timeout=30000",
|
|
55
55
|
"benchmark": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json",
|
|
56
|
-
"benchmark-baseline": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --baseline out-test
|
|
57
|
-
"benchmark-eval": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --eval out-test
|
|
56
|
+
"benchmark-baseline": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --baseline out-tsc/test-benchmark/test/benchmark/*benchmark.js",
|
|
57
|
+
"benchmark-eval": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --eval out-tsc/test-benchmark/test/benchmark/*benchmark.js",
|
|
58
58
|
"clean": "rm -rf lib out addons/*/lib addons/*/out",
|
|
59
|
-
"vtfeatures": "node bin/extract_vtfeatures.js src/**/*.ts src/*.ts"
|
|
59
|
+
"vtfeatures": "node bin/extract_vtfeatures.js src/**/*.ts src/*.ts",
|
|
60
|
+
"prepackage": "npm run build",
|
|
61
|
+
"package": "webpack",
|
|
62
|
+
"postpackage": "npm run esbuild-package",
|
|
63
|
+
"prepackage-headless": "npm run esbuild-package-headless-only",
|
|
64
|
+
"package-headless": "webpack --config ./webpack.config.headless.js",
|
|
65
|
+
"postpackage-headless": "node ./bin/package_headless.js",
|
|
66
|
+
"prepublishOnly": "npm run package"
|
|
60
67
|
},
|
|
61
68
|
"devDependencies": {
|
|
62
69
|
"@lunapaint/png-codec": "^0.2.0",
|
|
63
70
|
"@playwright/test": "^1.37.1",
|
|
71
|
+
"@stylistic/eslint-plugin": "^2.3.0",
|
|
64
72
|
"@types/chai": "^4.2.22",
|
|
65
73
|
"@types/debug": "^4.1.7",
|
|
66
74
|
"@types/deep-equal": "^1.0.1",
|
|
@@ -78,9 +86,10 @@
|
|
|
78
86
|
"chai": "^4.3.4",
|
|
79
87
|
"cross-env": "^7.0.3",
|
|
80
88
|
"deep-equal": "^2.0.5",
|
|
89
|
+
"esbuild": "^0.23.0",
|
|
81
90
|
"eslint": "^8.56.0",
|
|
82
91
|
"eslint-plugin-jsdoc": "^46.9.1",
|
|
83
|
-
"express": "^4.
|
|
92
|
+
"express": "^4.19.2",
|
|
84
93
|
"express-ws": "^5.0.2",
|
|
85
94
|
"glob": "^7.2.0",
|
|
86
95
|
"jsdom": "^18.0.1",
|
|
@@ -91,7 +100,7 @@
|
|
|
91
100
|
"source-map-loader": "^3.0.0",
|
|
92
101
|
"source-map-support": "^0.5.20",
|
|
93
102
|
"ts-loader": "^9.3.1",
|
|
94
|
-
"typescript": "
|
|
103
|
+
"typescript": "5.5",
|
|
95
104
|
"utf8": "^3.0.0",
|
|
96
105
|
"webpack": "^5.61.0",
|
|
97
106
|
"webpack-cli": "^4.9.1",
|
|
@@ -58,10 +58,11 @@ export class AccessibilityManager extends Disposable {
|
|
|
58
58
|
@IRenderService private readonly _renderService: IRenderService
|
|
59
59
|
) {
|
|
60
60
|
super();
|
|
61
|
-
|
|
61
|
+
const doc = this._coreBrowserService.mainDocument;
|
|
62
|
+
this._accessibilityContainer = doc.createElement('div');
|
|
62
63
|
this._accessibilityContainer.classList.add('xterm-accessibility');
|
|
63
64
|
|
|
64
|
-
this._rowContainer =
|
|
65
|
+
this._rowContainer = doc.createElement('div');
|
|
65
66
|
this._rowContainer.setAttribute('role', 'list');
|
|
66
67
|
this._rowContainer.classList.add('xterm-accessibility-tree');
|
|
67
68
|
this._rowElements = [];
|
|
@@ -75,10 +76,9 @@ export class AccessibilityManager extends Disposable {
|
|
|
75
76
|
this._rowElements[0].addEventListener('focus', this._topBoundaryFocusListener);
|
|
76
77
|
this._rowElements[this._rowElements.length - 1].addEventListener('focus', this._bottomBoundaryFocusListener);
|
|
77
78
|
|
|
78
|
-
this._refreshRowsDimensions();
|
|
79
79
|
this._accessibilityContainer.appendChild(this._rowContainer);
|
|
80
80
|
|
|
81
|
-
this._liveRegion =
|
|
81
|
+
this._liveRegion = doc.createElement('div');
|
|
82
82
|
this._liveRegion.classList.add('live-region');
|
|
83
83
|
this._liveRegion.setAttribute('aria-live', 'assertive');
|
|
84
84
|
this._accessibilityContainer.appendChild(this._liveRegion);
|
|
@@ -93,12 +93,12 @@ export class AccessibilityManager extends Disposable {
|
|
|
93
93
|
this._rowContainer.classList.add('debug');
|
|
94
94
|
|
|
95
95
|
// Use a `<div class="xterm">` container so that the css will still apply.
|
|
96
|
-
this._debugRootContainer =
|
|
96
|
+
this._debugRootContainer = doc.createElement('div');
|
|
97
97
|
this._debugRootContainer.classList.add('xterm');
|
|
98
98
|
|
|
99
|
-
this._debugRootContainer.appendChild(
|
|
99
|
+
this._debugRootContainer.appendChild(doc.createTextNode('------start a11y------'));
|
|
100
100
|
this._debugRootContainer.appendChild(this._accessibilityContainer);
|
|
101
|
-
this._debugRootContainer.appendChild(
|
|
101
|
+
this._debugRootContainer.appendChild(doc.createTextNode('------end a11y------'));
|
|
102
102
|
|
|
103
103
|
this._terminal.element.insertAdjacentElement('afterend', this._debugRootContainer);
|
|
104
104
|
} else {
|
|
@@ -115,9 +115,10 @@ export class AccessibilityManager extends Disposable {
|
|
|
115
115
|
this.register(this._terminal.onKey(e => this._handleKey(e.key)));
|
|
116
116
|
this.register(this._terminal.onBlur(() => this._clearLiveRegion()));
|
|
117
117
|
this.register(this._renderService.onDimensionsChange(() => this._refreshRowsDimensions()));
|
|
118
|
-
this.register(addDisposableDomListener(
|
|
118
|
+
this.register(addDisposableDomListener(doc, 'selectionchange', () => this._handleSelectionChange()));
|
|
119
119
|
this.register(this._coreBrowserService.onDprChange(() => this._refreshRowsDimensions()));
|
|
120
120
|
|
|
121
|
+
this._refreshRowsDimensions();
|
|
121
122
|
this._refreshRows();
|
|
122
123
|
this.register(toDisposable(() => {
|
|
123
124
|
if (DEBUG) {
|
|
@@ -150,7 +151,7 @@ export class AccessibilityManager extends Disposable {
|
|
|
150
151
|
if (char === '\n') {
|
|
151
152
|
this._liveRegionLineCount++;
|
|
152
153
|
if (this._liveRegionLineCount === MAX_ROWS_TO_READ + 1) {
|
|
153
|
-
this._liveRegion.textContent += Strings.tooMuchOutput;
|
|
154
|
+
this._liveRegion.textContent += Strings.tooMuchOutput.get();
|
|
154
155
|
}
|
|
155
156
|
}
|
|
156
157
|
}
|
|
@@ -192,6 +193,7 @@ export class AccessibilityManager extends Disposable {
|
|
|
192
193
|
}
|
|
193
194
|
element.setAttribute('aria-posinset', posInSet);
|
|
194
195
|
element.setAttribute('aria-setsize', setSize);
|
|
196
|
+
this._alignRowWidth(element);
|
|
195
197
|
}
|
|
196
198
|
}
|
|
197
199
|
this._announceCharacters();
|
|
@@ -270,7 +272,7 @@ export class AccessibilityManager extends Disposable {
|
|
|
270
272
|
return;
|
|
271
273
|
}
|
|
272
274
|
|
|
273
|
-
const selection =
|
|
275
|
+
const selection = this._coreBrowserService.mainDocument.getSelection();
|
|
274
276
|
if (!selection) {
|
|
275
277
|
return;
|
|
276
278
|
}
|
|
@@ -389,19 +391,45 @@ export class AccessibilityManager extends Disposable {
|
|
|
389
391
|
this._refreshRowDimensions(element);
|
|
390
392
|
return element;
|
|
391
393
|
}
|
|
394
|
+
|
|
392
395
|
private _refreshRowsDimensions(): void {
|
|
393
396
|
if (!this._renderService.dimensions.css.cell.height) {
|
|
394
397
|
return;
|
|
395
398
|
}
|
|
396
|
-
this._accessibilityContainer.style
|
|
399
|
+
Object.assign(this._accessibilityContainer.style, {
|
|
400
|
+
width: `${this._renderService.dimensions.css.canvas.width}px`,
|
|
401
|
+
fontSize: `${this._terminal.options.fontSize}px`
|
|
402
|
+
});
|
|
397
403
|
if (this._rowElements.length !== this._terminal.rows) {
|
|
398
404
|
this._handleResize(this._terminal.rows);
|
|
399
405
|
}
|
|
400
406
|
for (let i = 0; i < this._terminal.rows; i++) {
|
|
401
407
|
this._refreshRowDimensions(this._rowElements[i]);
|
|
408
|
+
this._alignRowWidth(this._rowElements[i]);
|
|
402
409
|
}
|
|
403
410
|
}
|
|
411
|
+
|
|
404
412
|
private _refreshRowDimensions(element: HTMLElement): void {
|
|
405
413
|
element.style.height = `${this._renderService.dimensions.css.cell.height}px`;
|
|
406
414
|
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Scale the width of a row so that each of the character is (mostly) aligned
|
|
418
|
+
* with the actual rendering. This will allow the screen reader to draw
|
|
419
|
+
* selection outline at the correct position.
|
|
420
|
+
*
|
|
421
|
+
* On top of using the "monospace" font and correct font size, the scaling
|
|
422
|
+
* here is necessary to handle characters that are not covered by the font
|
|
423
|
+
* (e.g. CJK).
|
|
424
|
+
*/
|
|
425
|
+
private _alignRowWidth(element: HTMLElement): void {
|
|
426
|
+
element.style.transform = '';
|
|
427
|
+
const width = element.getBoundingClientRect().width;
|
|
428
|
+
const lastColumn = this._rowColumns.get(element)?.slice(-1)?.[0];
|
|
429
|
+
if (!lastColumn) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
const targetWidth = lastColumn * this._renderService.dimensions.css.cell.width;
|
|
433
|
+
element.style.transform = `scaleX(${targetWidth / width})`;
|
|
434
|
+
}
|
|
407
435
|
}
|
|
@@ -59,7 +59,7 @@ import { WindowsOptionsReportType } from '../common/InputHandler';
|
|
|
59
59
|
import { AccessibilityManager } from './AccessibilityManager';
|
|
60
60
|
import { LinkProviderService } from 'browser/services/LinkProviderService';
|
|
61
61
|
|
|
62
|
-
export class
|
|
62
|
+
export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
|
63
63
|
public textarea: HTMLTextAreaElement | undefined;
|
|
64
64
|
public element: HTMLElement | undefined;
|
|
65
65
|
public screenElement: HTMLElement | undefined;
|
|
@@ -443,7 +443,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|
|
443
443
|
|
|
444
444
|
this.textarea = this._document.createElement('textarea');
|
|
445
445
|
this.textarea.classList.add('xterm-helper-textarea');
|
|
446
|
-
this.textarea.setAttribute('aria-label', Strings.promptLabel);
|
|
446
|
+
this.textarea.setAttribute('aria-label', Strings.promptLabel.get());
|
|
447
447
|
if (!Browser.isChromeOS) {
|
|
448
448
|
// ChromeVox on ChromeOS does not like this. See
|
|
449
449
|
// https://issuetracker.google.com/issues/260170397
|
|
@@ -5,8 +5,19 @@
|
|
|
5
5
|
|
|
6
6
|
// This file contains strings that get exported in the API so they can be localized
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
let promptLabelInternal = 'Terminal input';
|
|
9
|
+
const promptLabel = {
|
|
10
|
+
get: () => promptLabelInternal,
|
|
11
|
+
set: (value: string) => promptLabelInternal = value
|
|
12
|
+
};
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
let tooMuchOutputInternal = 'Too much output to announce, navigate to rows manually to read';
|
|
15
|
+
const tooMuchOutput = {
|
|
16
|
+
get: () => tooMuchOutputInternal,
|
|
17
|
+
set: (value: string) => tooMuchOutputInternal = value
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
promptLabel,
|
|
22
|
+
tooMuchOutput
|
|
23
|
+
};
|
|
@@ -7,6 +7,7 @@ import { IEvent } from 'common/EventEmitter';
|
|
|
7
7
|
import { CharData, IColor, ICoreTerminal, ITerminalOptions } from 'common/Types';
|
|
8
8
|
import { IBuffer } from 'common/buffer/Types';
|
|
9
9
|
import { IDisposable, Terminal as ITerminalApi } from '@xterm/xterm';
|
|
10
|
+
import { channels, css } from 'common/Color';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* A portion of the public API that are implemented identially internally and simply passed through.
|
|
@@ -129,7 +130,7 @@ export interface ILinkifier2 extends IDisposable {
|
|
|
129
130
|
readonly currentLink: ILinkWithState | undefined;
|
|
130
131
|
}
|
|
131
132
|
|
|
132
|
-
interface ILink {
|
|
133
|
+
export interface ILink {
|
|
133
134
|
range: IBufferRange;
|
|
134
135
|
text: string;
|
|
135
136
|
decorations?: ILinkDecorations;
|
|
@@ -139,17 +140,17 @@ interface ILink {
|
|
|
139
140
|
dispose?(): void;
|
|
140
141
|
}
|
|
141
142
|
|
|
142
|
-
interface ILinkDecorations {
|
|
143
|
+
export interface ILinkDecorations {
|
|
143
144
|
pointerCursor: boolean;
|
|
144
145
|
underline: boolean;
|
|
145
146
|
}
|
|
146
147
|
|
|
147
|
-
interface IBufferRange {
|
|
148
|
+
export interface IBufferRange {
|
|
148
149
|
start: IBufferCellPosition;
|
|
149
150
|
end: IBufferCellPosition;
|
|
150
151
|
}
|
|
151
152
|
|
|
152
|
-
interface IBufferCellPosition {
|
|
153
|
+
export interface IBufferCellPosition {
|
|
153
154
|
x: number;
|
|
154
155
|
y: number;
|
|
155
156
|
}
|
|
@@ -172,3 +173,51 @@ export interface IRenderDebouncerWithCallback extends IRenderDebouncer {
|
|
|
172
173
|
export interface IBufferElementProvider {
|
|
173
174
|
provideBufferElements(): DocumentFragment | HTMLElement;
|
|
174
175
|
}
|
|
176
|
+
|
|
177
|
+
// An IIFE to generate DEFAULT_ANSI_COLORS.
|
|
178
|
+
export const DEFAULT_ANSI_COLORS = Object.freeze((() => {
|
|
179
|
+
const colors = [
|
|
180
|
+
// dark:
|
|
181
|
+
css.toColor('#2e3436'),
|
|
182
|
+
css.toColor('#cc0000'),
|
|
183
|
+
css.toColor('#4e9a06'),
|
|
184
|
+
css.toColor('#c4a000'),
|
|
185
|
+
css.toColor('#3465a4'),
|
|
186
|
+
css.toColor('#75507b'),
|
|
187
|
+
css.toColor('#06989a'),
|
|
188
|
+
css.toColor('#d3d7cf'),
|
|
189
|
+
// bright:
|
|
190
|
+
css.toColor('#555753'),
|
|
191
|
+
css.toColor('#ef2929'),
|
|
192
|
+
css.toColor('#8ae234'),
|
|
193
|
+
css.toColor('#fce94f'),
|
|
194
|
+
css.toColor('#729fcf'),
|
|
195
|
+
css.toColor('#ad7fa8'),
|
|
196
|
+
css.toColor('#34e2e2'),
|
|
197
|
+
css.toColor('#eeeeec')
|
|
198
|
+
];
|
|
199
|
+
|
|
200
|
+
// Fill in the remaining 240 ANSI colors.
|
|
201
|
+
// Generate colors (16-231)
|
|
202
|
+
const v = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff];
|
|
203
|
+
for (let i = 0; i < 216; i++) {
|
|
204
|
+
const r = v[(i / 36) % 6 | 0];
|
|
205
|
+
const g = v[(i / 6) % 6 | 0];
|
|
206
|
+
const b = v[i % 6];
|
|
207
|
+
colors.push({
|
|
208
|
+
css: channels.toCss(r, g, b),
|
|
209
|
+
rgba: channels.toRgba(r, g, b)
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Generate greys (232-255)
|
|
214
|
+
for (let i = 0; i < 24; i++) {
|
|
215
|
+
const c = 8 + i * 10;
|
|
216
|
+
colors.push({
|
|
217
|
+
css: channels.toCss(c, c, c),
|
|
218
|
+
rgba: channels.toRgba(c, c, c)
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return colors;
|
|
223
|
+
})());
|
package/src/browser/Viewport.ts
CHANGED
|
@@ -51,6 +51,8 @@ export class Viewport extends Disposable implements IViewport {
|
|
|
51
51
|
target: -1
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
+
private _ensureTimeout: number;
|
|
55
|
+
|
|
54
56
|
private readonly _onRequestScrollLines = this.register(new EventEmitter<{ amount: number, suppressScrollEvent: boolean }>());
|
|
55
57
|
public readonly onRequestScrollLines = this._onRequestScrollLines.event;
|
|
56
58
|
|
|
@@ -83,7 +85,7 @@ export class Viewport extends Disposable implements IViewport {
|
|
|
83
85
|
this.register(this._optionsService.onSpecificOptionChange('scrollback', () => this.syncScrollArea()));
|
|
84
86
|
|
|
85
87
|
// Perform this async to ensure the ICharSizeService is ready.
|
|
86
|
-
setTimeout(() => this.syncScrollArea());
|
|
88
|
+
this._ensureTimeout = window.setTimeout(() => this.syncScrollArea());
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
private _handleThemeChange(colors: ReadonlyColorSet): void {
|
|
@@ -405,4 +407,8 @@ export class Viewport extends Disposable implements IViewport {
|
|
|
405
407
|
this._viewportElement.scrollTop += deltaY;
|
|
406
408
|
return this._bubbleScroll(ev, deltaY);
|
|
407
409
|
}
|
|
410
|
+
|
|
411
|
+
public dispose(): void {
|
|
412
|
+
clearTimeout(this._ensureTimeout);
|
|
413
|
+
}
|
|
408
414
|
}
|
|
@@ -108,8 +108,13 @@ export class BufferDecorationRenderer extends Disposable {
|
|
|
108
108
|
element!.remove();
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
|
-
element.style.top = `${line * this._renderService.dimensions.css.cell.height}px`;
|
|
112
111
|
element.style.display = this._altBufferIsActive ? 'none' : 'block';
|
|
112
|
+
if (!this._altBufferIsActive) {
|
|
113
|
+
element.style.width = `${Math.round((decoration.options.width || 1) * this._renderService.dimensions.css.cell.width)}px`;
|
|
114
|
+
element.style.height = `${(decoration.options.height || 1) * this._renderService.dimensions.css.cell.height}px`;
|
|
115
|
+
element.style.top = `${line * this._renderService.dimensions.css.cell.height}px`;
|
|
116
|
+
element.style.lineHeight = `${this._renderService.dimensions.css.cell.height}px`;
|
|
117
|
+
}
|
|
113
118
|
decoration.onRenderEmitter.fire(element);
|
|
114
119
|
}
|
|
115
120
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import * as Strings from 'browser/LocalizableStrings';
|
|
7
|
-
import {
|
|
7
|
+
import { CoreBrowserTerminal as TerminalCore } from 'browser/CoreBrowserTerminal';
|
|
8
8
|
import { IBufferRange, ITerminal } from 'browser/Types';
|
|
9
9
|
import { IEvent } from 'common/EventEmitter';
|
|
10
10
|
import { Disposable } from 'common/Lifecycle';
|
|
@@ -20,6 +20,8 @@ import { IBufferNamespace as IBufferNamespaceApi, IDecoration, IDecorationOption
|
|
|
20
20
|
*/
|
|
21
21
|
const CONSTRUCTOR_ONLY_OPTIONS = ['cols', 'rows'];
|
|
22
22
|
|
|
23
|
+
let $value = 0;
|
|
24
|
+
|
|
23
25
|
export class Terminal extends Disposable implements ITerminalApi {
|
|
24
26
|
private _core: ITerminal;
|
|
25
27
|
private _addonManager: AddonManager;
|
|
@@ -245,20 +247,26 @@ export class Terminal extends Disposable implements ITerminalApi {
|
|
|
245
247
|
this._addonManager.loadAddon(this, addon);
|
|
246
248
|
}
|
|
247
249
|
public static get strings(): ILocalizableStrings {
|
|
248
|
-
|
|
250
|
+
// A wrapper is required here because esbuild prevents setting an `export let`
|
|
251
|
+
return {
|
|
252
|
+
get promptLabel(): string { return Strings.promptLabel.get(); },
|
|
253
|
+
set promptLabel(value: string) { Strings.promptLabel.set(value); },
|
|
254
|
+
get tooMuchOutput(): string { return Strings.tooMuchOutput.get(); },
|
|
255
|
+
set tooMuchOutput(value: string) { Strings.tooMuchOutput.set(value); }
|
|
256
|
+
};
|
|
249
257
|
}
|
|
250
258
|
|
|
251
259
|
private _verifyIntegers(...values: number[]): void {
|
|
252
|
-
for (
|
|
253
|
-
if (value === Infinity || isNaN(value) || value % 1 !== 0) {
|
|
260
|
+
for ($value of values) {
|
|
261
|
+
if ($value === Infinity || isNaN($value) || $value % 1 !== 0) {
|
|
254
262
|
throw new Error('This API only accepts integers');
|
|
255
263
|
}
|
|
256
264
|
}
|
|
257
265
|
}
|
|
258
266
|
|
|
259
267
|
private _verifyPositiveIntegers(...values: number[]): void {
|
|
260
|
-
for (
|
|
261
|
-
if (value && (value === Infinity || isNaN(value) || value % 1 !== 0 || value < 0)) {
|
|
268
|
+
for ($value of values) {
|
|
269
|
+
if ($value && ($value === Infinity || isNaN($value) || $value % 1 !== 0 || $value < 0)) {
|
|
262
270
|
throw new Error('This API only accepts positive integers');
|
|
263
271
|
}
|
|
264
272
|
}
|
|
@@ -343,6 +343,9 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
343
343
|
}
|
|
344
344
|
|
|
345
345
|
this._selectionRenderModel.update(this._terminal, start, end, columnSelectMode);
|
|
346
|
+
if (!this._selectionRenderModel.hasSelection) {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
346
349
|
|
|
347
350
|
// Translate from buffer position to viewport position
|
|
348
351
|
const viewportStartRow = this._selectionRenderModel.viewportStartRow;
|
|
@@ -350,11 +353,6 @@ export class DomRenderer extends Disposable implements IRenderer {
|
|
|
350
353
|
const viewportCappedStartRow = this._selectionRenderModel.viewportCappedStartRow;
|
|
351
354
|
const viewportCappedEndRow = this._selectionRenderModel.viewportCappedEndRow;
|
|
352
355
|
|
|
353
|
-
// No need to draw the selection
|
|
354
|
-
if (viewportCappedStartRow >= this._bufferService.rows || viewportCappedEndRow < 0) {
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
356
|
// Create the selections
|
|
359
357
|
const documentFragment = this._document.createDocumentFragment();
|
|
360
358
|
|
|
@@ -355,6 +355,12 @@ const enum VectorType {
|
|
|
355
355
|
* Original symbols defined in https://github.com/powerline/fontpatcher
|
|
356
356
|
*/
|
|
357
357
|
export const powerlineDefinitions: { [index: string]: IVectorShape } = {
|
|
358
|
+
// Git branch
|
|
359
|
+
'\u{E0A0}': { d: 'M.3,1 L.03,1 L.03,.88 C.03,.82,.06,.78,.11,.73 C.15,.7,.2,.68,.28,.65 L.43,.6 C.49,.58,.53,.56,.56,.53 C.59,.5,.6,.47,.6,.43 L.6,.27 L.4,.27 L.69,.1 L.98,.27 L.78,.27 L.78,.46 C.78,.52,.76,.56,.72,.61 C.68,.66,.63,.67,.56,.7 L.48,.72 C.42,.74,.38,.76,.35,.78 C.32,.8,.31,.84,.31,.88 L.31,1 M.3,.5 L.03,.59 L.03,.09 L.3,.09 L.3,.655', type: VectorType.FILL },
|
|
360
|
+
// L N
|
|
361
|
+
'\u{E0A1}': { d: 'M.7,.4 L.7,.47 L.2,.47 L.2,.03 L.355,.03 L.355,.4 L.705,.4 M.7,.5 L.86,.5 L.86,.95 L.69,.95 L.44,.66 L.46,.86 L.46,.95 L.3,.95 L.3,.49 L.46,.49 L.71,.78 L.69,.565 L.69,.5', type: VectorType.FILL },
|
|
362
|
+
// Lock
|
|
363
|
+
'\u{E0A2}': { d: 'M.25,.94 C.16,.94,.11,.92,.11,.87 L.11,.53 C.11,.48,.15,.455,.23,.45 L.23,.3 C.23,.25,.26,.22,.31,.19 C.36,.16,.43,.15,.51,.15 C.59,.15,.66,.16,.71,.19 C.77,.22,.79,.26,.79,.3 L.79,.45 C.87,.45,.91,.48,.91,.53 L.91,.87 C.91,.92,.86,.94,.77,.94 L.24,.94 M.53,.2 C.49,.2,.45,.21,.42,.23 C.39,.25,.38,.27,.38,.3 L.38,.45 L.68,.45 L.68,.3 C.68,.27,.67,.25,.64,.23 C.61,.21,.58,.2,.53,.2 M.58,.82 L.58,.66 C.63,.65,.65,.63,.65,.6 C.65,.58,.64,.57,.61,.56 C.58,.55,.56,.54,.52,.54 C.48,.54,.46,.55,.43,.56 C.4,.57,.39,.59,.39,.6 C.39,.63,.41,.64,.46,.66 L.46,.82 L.57,.82', type: VectorType.FILL },
|
|
358
364
|
// Right triangle solid
|
|
359
365
|
'\u{E0B0}': { d: 'M0,0 L1,.5 L0,1', type: VectorType.FILL, rightPadding: 2 },
|
|
360
366
|
// Right triangle line
|
|
@@ -13,7 +13,7 @@ export class CoreBrowserService extends Disposable implements ICoreBrowserServic
|
|
|
13
13
|
|
|
14
14
|
private _isFocused = false;
|
|
15
15
|
private _cachedIsFocused: boolean | undefined = undefined;
|
|
16
|
-
private _screenDprMonitor = new ScreenDprMonitor(this._window);
|
|
16
|
+
private _screenDprMonitor = this.register(new ScreenDprMonitor(this._window));
|
|
17
17
|
|
|
18
18
|
private readonly _onDprChange = this.register(new EventEmitter<number>());
|
|
19
19
|
public readonly onDprChange = this._onDprChange.event;
|
|
@@ -31,8 +31,12 @@ export class CoreBrowserService extends Disposable implements ICoreBrowserServic
|
|
|
31
31
|
this.register(this.onWindowChange(w => this._screenDprMonitor.setWindow(w)));
|
|
32
32
|
this.register(forwardEvent(this._screenDprMonitor.onDprChange, this._onDprChange));
|
|
33
33
|
|
|
34
|
-
this.
|
|
35
|
-
|
|
34
|
+
this.register(
|
|
35
|
+
addDisposableDomListener(this._textarea, 'focus', () => (this._isFocused = true))
|
|
36
|
+
);
|
|
37
|
+
this.register(
|
|
38
|
+
addDisposableDomListener(this._textarea, 'blur', () => (this._isFocused = false))
|
|
39
|
+
);
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
public get window(): Window & typeof globalThis {
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
import { ColorContrastCache } from 'browser/ColorContrastCache';
|
|
7
7
|
import { IThemeService } from 'browser/services/Services';
|
|
8
|
-
import { IColorContrastCache, IColorSet, ReadonlyColorSet } from 'browser/Types';
|
|
9
|
-
import {
|
|
8
|
+
import { DEFAULT_ANSI_COLORS, IColorContrastCache, IColorSet, ReadonlyColorSet } from 'browser/Types';
|
|
9
|
+
import { color, css, NULL_COLOR } from 'common/Color';
|
|
10
10
|
import { EventEmitter } from 'common/EventEmitter';
|
|
11
11
|
import { Disposable } from 'common/Lifecycle';
|
|
12
12
|
import { IOptionsService, ITheme } from 'common/services/Services';
|
|
@@ -29,54 +29,6 @@ const DEFAULT_SELECTION = {
|
|
|
29
29
|
rgba: 0xFFFFFF4D
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
-
// An IIFE to generate DEFAULT_ANSI_COLORS.
|
|
33
|
-
export const DEFAULT_ANSI_COLORS = Object.freeze((() => {
|
|
34
|
-
const colors = [
|
|
35
|
-
// dark:
|
|
36
|
-
css.toColor('#2e3436'),
|
|
37
|
-
css.toColor('#cc0000'),
|
|
38
|
-
css.toColor('#4e9a06'),
|
|
39
|
-
css.toColor('#c4a000'),
|
|
40
|
-
css.toColor('#3465a4'),
|
|
41
|
-
css.toColor('#75507b'),
|
|
42
|
-
css.toColor('#06989a'),
|
|
43
|
-
css.toColor('#d3d7cf'),
|
|
44
|
-
// bright:
|
|
45
|
-
css.toColor('#555753'),
|
|
46
|
-
css.toColor('#ef2929'),
|
|
47
|
-
css.toColor('#8ae234'),
|
|
48
|
-
css.toColor('#fce94f'),
|
|
49
|
-
css.toColor('#729fcf'),
|
|
50
|
-
css.toColor('#ad7fa8'),
|
|
51
|
-
css.toColor('#34e2e2'),
|
|
52
|
-
css.toColor('#eeeeec')
|
|
53
|
-
];
|
|
54
|
-
|
|
55
|
-
// Fill in the remaining 240 ANSI colors.
|
|
56
|
-
// Generate colors (16-231)
|
|
57
|
-
const v = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff];
|
|
58
|
-
for (let i = 0; i < 216; i++) {
|
|
59
|
-
const r = v[(i / 36) % 6 | 0];
|
|
60
|
-
const g = v[(i / 6) % 6 | 0];
|
|
61
|
-
const b = v[i % 6];
|
|
62
|
-
colors.push({
|
|
63
|
-
css: channels.toCss(r, g, b),
|
|
64
|
-
rgba: channels.toRgba(r, g, b)
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Generate greys (232-255)
|
|
69
|
-
for (let i = 0; i < 24; i++) {
|
|
70
|
-
const c = 8 + i * 10;
|
|
71
|
-
colors.push({
|
|
72
|
-
css: channels.toCss(c, c, c),
|
|
73
|
-
rgba: channels.toRgba(c, c, c)
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return colors;
|
|
78
|
-
})());
|
|
79
|
-
|
|
80
32
|
export class ThemeService extends Disposable implements IThemeService {
|
|
81
33
|
public serviceBrand: undefined;
|
|
82
34
|
|
|
@@ -20,23 +20,18 @@ export interface IEventEmitter<T, U = void> {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export class EventEmitter<T, U = void> implements IEventEmitter<T, U> {
|
|
23
|
-
private _listeners: IListener<T, U
|
|
23
|
+
private _listeners: Set<IListener<T, U>> = new Set();
|
|
24
24
|
private _event?: IEvent<T, U>;
|
|
25
25
|
private _disposed: boolean = false;
|
|
26
26
|
|
|
27
27
|
public get event(): IEvent<T, U> {
|
|
28
28
|
if (!this._event) {
|
|
29
29
|
this._event = (listener: (arg1: T, arg2: U) => any) => {
|
|
30
|
-
this._listeners.
|
|
30
|
+
this._listeners.add(listener);
|
|
31
31
|
const disposable = {
|
|
32
32
|
dispose: () => {
|
|
33
33
|
if (!this._disposed) {
|
|
34
|
-
|
|
35
|
-
if (this._listeners[i] === listener) {
|
|
36
|
-
this._listeners.splice(i, 1);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
34
|
+
this._listeners.delete(listener);
|
|
40
35
|
}
|
|
41
36
|
}
|
|
42
37
|
};
|
|
@@ -48,8 +43,8 @@ export class EventEmitter<T, U = void> implements IEventEmitter<T, U> {
|
|
|
48
43
|
|
|
49
44
|
public fire(arg1: T, arg2: U): void {
|
|
50
45
|
const queue: IListener<T, U>[] = [];
|
|
51
|
-
for (
|
|
52
|
-
queue.push(
|
|
46
|
+
for (const l of this._listeners.values()) {
|
|
47
|
+
queue.push(l);
|
|
53
48
|
}
|
|
54
49
|
for (let i = 0; i < queue.length; i++) {
|
|
55
50
|
queue[i].call(undefined, arg1, arg2);
|
|
@@ -63,7 +58,7 @@ export class EventEmitter<T, U = void> implements IEventEmitter<T, U> {
|
|
|
63
58
|
|
|
64
59
|
public clearListeners(): void {
|
|
65
60
|
if (this._listeners) {
|
|
66
|
-
this._listeners.
|
|
61
|
+
this._listeners.clear();
|
|
67
62
|
}
|
|
68
63
|
}
|
|
69
64
|
}
|