Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e40cf8043a | ||
|
|
32cb95c7fb | ||
|
|
b2068531dd | ||
|
|
b29d7d2c8d | ||
|
|
b684929d1e | ||
|
|
07ba3dc197 | ||
|
|
5c9adeef93 | ||
|
|
394d7a2ee6 | ||
|
|
987bb8dd35 | ||
|
|
ce314844d2 | ||
|
|
645263b0ac | ||
|
|
6978fafd28 | ||
|
|
c7ee362ae7 | ||
|
|
57e6cfd500 | ||
|
|
33bbc4f4b8 | ||
|
|
8549915afa | ||
|
|
59f940c19c | ||
|
|
ed1aecb251 | ||
|
|
7deb01267b | ||
|
|
4b9ab81848 | ||
|
|
6c8d801894 | ||
|
|
1a9de5f227 | ||
|
|
9b1eec8ade | ||
|
|
1a697bd844 | ||
|
|
b23e100266 | ||
|
|
c9e8db38b6 | ||
|
|
0a7ac8b978 | ||
|
|
780b48db53 | ||
|
|
82d09ec909 | ||
|
|
b876639429 | ||
|
|
afe19e96fe | ||
|
|
c599fbb7a1 | ||
|
|
c63e9ef876 | ||
|
|
d6e828a2f3 | ||
|
|
2445f35a32 | ||
|
|
d2bcbc73d3 | ||
|
|
f46ed82d7e | ||
|
|
4222dfb69d | ||
|
|
1b3eb412b8 | ||
|
|
e9f6636df1 | ||
|
|
472e410205 | ||
|
|
581272ee51 | ||
|
|
e8e21e9d0b | ||
|
|
80d4742ded | ||
|
|
50939e0b1d | ||
|
|
5d5f34f65f | ||
|
|
d3b762eb97 | ||
|
|
0c60478953 | ||
|
|
3b23921a41 | ||
|
|
e3422eda58 | ||
|
|
37a4100220 | ||
|
|
8592c5cca3 | ||
|
|
014530f582 | ||
|
|
a994fbc865 | ||
|
|
0d14336ec5 | ||
|
|
c20c07c6d8 | ||
|
|
3a71b3f11e | ||
|
|
f2384694a1 | ||
|
|
ca46b8c805 | ||
|
|
189ff56224 | ||
|
|
ef6516e561 | ||
|
|
1d1fffdabc | ||
|
|
3fe32c0724 | ||
|
|
2e4e29ad73 | ||
|
|
9c4a08a55a | ||
|
|
5188633458 | ||
|
|
a8a24eba51 | ||
|
|
6493edcddf | ||
|
|
c186fbeafc | ||
|
|
d32c6db967 | ||
|
|
db6b3c4bcc | ||
|
|
50c5579c83 | ||
|
|
5a65fd9c6a | ||
|
|
be7fcbe485 | ||
|
|
99239e9160 | ||
|
|
662154123d | ||
|
|
72a557cc1a |
@@ -4,6 +4,7 @@
|
|||||||
"appPort": 3000,
|
"appPort": 3000,
|
||||||
"extensions": [
|
"extensions": [
|
||||||
"dbaeumer.vscode-eslint",
|
"dbaeumer.vscode-eslint",
|
||||||
"editorconfig.editorconfig"
|
"editorconfig.editorconfig",
|
||||||
|
"hbenl.vscode-mocha-test-adapter"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-22
@@ -2,10 +2,6 @@
|
|||||||
*
|
*
|
||||||
!*/
|
!*/
|
||||||
|
|
||||||
# Whitelist - entries to be included must be negated with "!"
|
|
||||||
!*.js
|
|
||||||
!*.json
|
|
||||||
|
|
||||||
# Whitelist - css/
|
# Whitelist - css/
|
||||||
!css/**/*.css
|
!css/**/*.css
|
||||||
|
|
||||||
@@ -32,25 +28,15 @@
|
|||||||
|
|
||||||
!src/**/*.css
|
!src/**/*.css
|
||||||
|
|
||||||
|
# Blacklist - src/ test files
|
||||||
|
src/**/*.test.ts
|
||||||
|
src/**/*.test.d.ts
|
||||||
|
src/**/*.test.js
|
||||||
|
src/**/*.test.js.map
|
||||||
|
|
||||||
# Whitelist - typings/
|
# Whitelist - typings/
|
||||||
!typings/*.d.ts
|
!typings/*.d.ts
|
||||||
|
|
||||||
# Blacklist - (normal behavior) these will override any whitelist
|
# Blacklist - (normal behavior) these will override any whitelist
|
||||||
*.d.ts.map
|
headless/
|
||||||
*.test.ts
|
typings/xterm-headless.d.ts
|
||||||
*.test.d.ts
|
|
||||||
*.test.js
|
|
||||||
*.test.js.map
|
|
||||||
lib/test/
|
|
||||||
webpack.config.js
|
|
||||||
|
|
||||||
docs/
|
|
||||||
/.idea/
|
|
||||||
.vscode/
|
|
||||||
bin/
|
|
||||||
build/
|
|
||||||
fixtures/
|
|
||||||
demo/
|
|
||||||
.devcontainer/
|
|
||||||
out/
|
|
||||||
addons/
|
|
||||||
|
|||||||
@@ -183,6 +183,8 @@ Xterm.js is used in several world-class applications to provide great terminal e
|
|||||||
- [**HashiCorp Nomad**](https://www.nomadproject.io/): A container orchestrator with the ability to connect to remote tasks via a web interface using websockets and xterm.js.
|
- [**HashiCorp Nomad**](https://www.nomadproject.io/): A container orchestrator with the ability to connect to remote tasks via a web interface using websockets and xterm.js.
|
||||||
- [**TermPair**](https://github.com/cs01/termpair): View and control terminals from your browser with end-to-end encryption
|
- [**TermPair**](https://github.com/cs01/termpair): View and control terminals from your browser with end-to-end encryption
|
||||||
- [**gdbgui**](https://github.com/cs01/gdbgui): Browser-based frontend to gdb (gnu debugger)
|
- [**gdbgui**](https://github.com/cs01/gdbgui): Browser-based frontend to gdb (gnu debugger)
|
||||||
|
- [**goormIDE**](https://ide.goorm.io/): Run almost every programming languages with real-time collaboration, live pair programming, and built-in messenger.
|
||||||
|
- [**FleetDeck**](https://fleetdeck.io): Remote desktop & virtual terminal
|
||||||
- [And much more...](https://github.com/xtermjs/xterm.js/network/dependents)
|
- [And much more...](https://github.com/xtermjs/xterm.js/network/dependents)
|
||||||
|
|
||||||
Do you use xterm.js in your application as well? Please [open a Pull Request](https://github.com/sourcelair/xterm.js/pulls) to include it here. We would love to have it on our list. Note: Please add any new contributions to the end of the list only.
|
Do you use xterm.js in your application as well? Please [open a Pull Request](https://github.com/sourcelair/xterm.js/pulls) to include it here. We would love to have it on our list. Note: Please add any new contributions to the end of the list only.
|
||||||
|
|||||||
@@ -1,5 +1,29 @@
|
|||||||
**/*.api.js
|
# Blacklist - exclude everything except npm defaults such as LICENSE, etc
|
||||||
**/*.api.ts
|
*
|
||||||
tsconfig.json
|
!*/
|
||||||
.yarnrc
|
|
||||||
webpack.config.js
|
# Whitelist - lib/
|
||||||
|
!lib/**/*.d.ts
|
||||||
|
|
||||||
|
!lib/**/*.js
|
||||||
|
!lib/**/*.js.map
|
||||||
|
|
||||||
|
!lib/**/*.css
|
||||||
|
|
||||||
|
# Whitelist - src/
|
||||||
|
!src/**/*.ts
|
||||||
|
!src/**/*.d.ts
|
||||||
|
|
||||||
|
!src/**/*.js
|
||||||
|
!src/**/*.js.map
|
||||||
|
|
||||||
|
!src/**/*.css
|
||||||
|
|
||||||
|
# Blacklist - src/ test files
|
||||||
|
src/**/*.test.ts
|
||||||
|
src/**/*.test.d.ts
|
||||||
|
src/**/*.test.js
|
||||||
|
src/**/*.test.js.map
|
||||||
|
|
||||||
|
# Whitelist - typings/
|
||||||
|
!typings/*.d.ts
|
||||||
|
|||||||
@@ -1,5 +1,29 @@
|
|||||||
**/*.api.js
|
# Blacklist - exclude everything except npm defaults such as LICENSE, etc
|
||||||
**/*.api.ts
|
*
|
||||||
tsconfig.json
|
!*/
|
||||||
.yarnrc
|
|
||||||
webpack.config.js
|
# Whitelist - lib/
|
||||||
|
!lib/**/*.d.ts
|
||||||
|
|
||||||
|
!lib/**/*.js
|
||||||
|
!lib/**/*.js.map
|
||||||
|
|
||||||
|
!lib/**/*.css
|
||||||
|
|
||||||
|
# Whitelist - src/
|
||||||
|
!src/**/*.ts
|
||||||
|
!src/**/*.d.ts
|
||||||
|
|
||||||
|
!src/**/*.js
|
||||||
|
!src/**/*.js.map
|
||||||
|
|
||||||
|
!src/**/*.css
|
||||||
|
|
||||||
|
# Blacklist - src/ test files
|
||||||
|
src/**/*.test.ts
|
||||||
|
src/**/*.test.d.ts
|
||||||
|
src/**/*.test.js
|
||||||
|
src/**/*.test.js.map
|
||||||
|
|
||||||
|
# Whitelist - typings/
|
||||||
|
!typings/*.d.ts
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export class FitAddon implements ITerminalAddon {
|
|||||||
|
|
||||||
public fit(): void {
|
public fit(): void {
|
||||||
const dims = this.proposeDimensions();
|
const dims = this.proposeDimensions();
|
||||||
if (!dims || !this._terminal) {
|
if (!dims || !this._terminal || isNaN(dims.cols) || isNaN(dims.rows)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,21 +2,13 @@
|
|||||||
*
|
*
|
||||||
!*/
|
!*/
|
||||||
|
|
||||||
# Whitelist - entries to be included must be negated with "!"
|
|
||||||
!*.js
|
|
||||||
!*.json
|
|
||||||
|
|
||||||
# Whitelist - lib/
|
# Whitelist - lib/
|
||||||
!lib/**/*.d.ts
|
!lib/**/*.d.ts
|
||||||
|
|
||||||
!lib/**/*.js
|
!lib/**/*.js
|
||||||
!lib/**/*.js.map
|
!lib/**/*.js.map
|
||||||
|
|
||||||
# Whitelist - out/
|
!lib/**/*.css
|
||||||
!out/**/*.d.ts
|
|
||||||
|
|
||||||
!out/**/*.js
|
|
||||||
!out/**/*.js.map
|
|
||||||
|
|
||||||
# Whitelist - src/
|
# Whitelist - src/
|
||||||
!src/**/*.ts
|
!src/**/*.ts
|
||||||
@@ -25,24 +17,13 @@
|
|||||||
!src/**/*.js
|
!src/**/*.js
|
||||||
!src/**/*.js.map
|
!src/**/*.js.map
|
||||||
|
|
||||||
|
!src/**/*.css
|
||||||
|
|
||||||
|
# Blacklist - src/ test files
|
||||||
|
src/**/*.test.ts
|
||||||
|
src/**/*.test.d.ts
|
||||||
|
src/**/*.test.js
|
||||||
|
src/**/*.test.js.map
|
||||||
|
|
||||||
# Whitelist - typings/
|
# Whitelist - typings/
|
||||||
!typings/**/*.d.ts
|
!typings/*.d.ts
|
||||||
|
|
||||||
# Blacklist - (normal behavior) these will override any whitelist
|
|
||||||
*.test.ts
|
|
||||||
*.test.d.ts
|
|
||||||
*.test.js
|
|
||||||
*.test.js.map
|
|
||||||
|
|
||||||
docs/
|
|
||||||
/.idea/
|
|
||||||
.vscode/
|
|
||||||
coverage/
|
|
||||||
.nyc_output/
|
|
||||||
fonts/
|
|
||||||
|
|
||||||
**/*.api.js
|
|
||||||
**/*.api.ts
|
|
||||||
tsconfig.json
|
|
||||||
.yarnrc
|
|
||||||
webpack.config.js
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/sinon": "^5.0.1",
|
"@types/sinon": "^5.0.1",
|
||||||
"axios": "^0.18.0",
|
"axios": "^0.21.2",
|
||||||
"mkdirp": "0.5.5",
|
"mkdirp": "0.5.5",
|
||||||
"sinon": "6.3.5",
|
"sinon": "6.3.5",
|
||||||
"yauzl": "^2.10.0"
|
"yauzl": "^2.10.0"
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export default async function load(fontFamily: string, cacheSize: number): Promi
|
|||||||
if (status && status.state !== 'granted') {
|
if (status && status.state !== 'granted') {
|
||||||
throw new Error('Permission to access local fonts not granted.');
|
throw new Error('Permission to access local fonts not granted.');
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err: any) {
|
||||||
// A `TypeError` indicates the 'local-fonts'
|
// A `TypeError` indicates the 'local-fonts'
|
||||||
// permission is not yet implemented, so
|
// permission is not yet implemented, so
|
||||||
// only `throw` if this is _not_ the problem.
|
// only `throw` if this is _not_ the problem.
|
||||||
@@ -61,7 +61,7 @@ export default async function load(fontFamily: string, cacheSize: number): Promi
|
|||||||
fonts[metadata.family].push(metadata);
|
fonts[metadata.family].push(metadata);
|
||||||
}
|
}
|
||||||
fontsPromise = Promise.resolve(fonts);
|
fontsPromise = Promise.resolve(fonts);
|
||||||
} catch (err) {
|
} catch (err: any) {
|
||||||
console.error(err.name, err.message);
|
console.error(err.name, err.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,23 +45,17 @@ array-from@^2.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/array-from/-/array-from-2.1.1.tgz#cfe9d8c26628b9dc5aecc62a9f5d8f1f352c1195"
|
resolved "https://registry.yarnpkg.com/array-from/-/array-from-2.1.1.tgz#cfe9d8c26628b9dc5aecc62a9f5d8f1f352c1195"
|
||||||
integrity sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=
|
integrity sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=
|
||||||
|
|
||||||
axios@^0.18.0:
|
axios@^0.21.2:
|
||||||
version "0.18.1"
|
version "0.21.2"
|
||||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.1.tgz#ff3f0de2e7b5d180e757ad98000f1081b87bcea3"
|
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.2.tgz#21297d5084b2aeeb422f5d38e7be4fbb82239017"
|
||||||
|
integrity sha512-87otirqUw3e8CzHTMO+/9kh/FSgXt/eVDvipijwDtEuwbkySWZ9SBm6VEubmJ/kLKEoLQV/POhxXFb66bfekfg==
|
||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects "1.5.10"
|
follow-redirects "^1.14.0"
|
||||||
is-buffer "^2.0.2"
|
|
||||||
|
|
||||||
buffer-crc32@~0.2.3:
|
buffer-crc32@~0.2.3:
|
||||||
version "0.2.13"
|
version "0.2.13"
|
||||||
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
|
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
|
||||||
|
|
||||||
debug@=3.1.0:
|
|
||||||
version "3.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
|
||||||
dependencies:
|
|
||||||
ms "2.0.0"
|
|
||||||
|
|
||||||
diff@^3.5.0:
|
diff@^3.5.0:
|
||||||
version "3.5.0"
|
version "3.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
|
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
|
||||||
@@ -72,11 +66,10 @@ fd-slicer@~1.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
pend "~1.2.0"
|
pend "~1.2.0"
|
||||||
|
|
||||||
follow-redirects@1.5.10:
|
follow-redirects@^1.14.0:
|
||||||
version "1.5.10"
|
version "1.14.3"
|
||||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
|
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.3.tgz#6ada78118d8d24caee595595accdc0ac6abd022e"
|
||||||
dependencies:
|
integrity sha512-3MkHxknWMUtb23apkgz/83fDoe+y+qr0TdgacGIA7bew+QLBo3vdgEN2xEsuXNivpFy4CyDhBBZnNZOtalmenw==
|
||||||
debug "=3.1.0"
|
|
||||||
|
|
||||||
font-finder@^1.0.3:
|
font-finder@^1.0.3:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
@@ -110,10 +103,6 @@ has-flag@^3.0.0:
|
|||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||||
|
|
||||||
is-buffer@^2.0.2:
|
|
||||||
version "2.0.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725"
|
|
||||||
|
|
||||||
isarray@0.0.1:
|
isarray@0.0.1:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
|
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
|
||||||
@@ -163,10 +152,6 @@ mkdirp@0.5.5:
|
|||||||
dependencies:
|
dependencies:
|
||||||
minimist "^1.2.5"
|
minimist "^1.2.5"
|
||||||
|
|
||||||
ms@2.0.0:
|
|
||||||
version "2.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
|
||||||
|
|
||||||
nise@^1.4.5:
|
nise@^1.4.5:
|
||||||
version "1.5.3"
|
version "1.5.3"
|
||||||
resolved "https://registry.yarnpkg.com/nise/-/nise-1.5.3.tgz#9d2cfe37d44f57317766c6e9408a359c5d3ac1f7"
|
resolved "https://registry.yarnpkg.com/nise/-/nise-1.5.3.tgz#9d2cfe37d44f57317766c6e9408a359c5d3ac1f7"
|
||||||
|
|||||||
@@ -1,5 +1,29 @@
|
|||||||
**/*.api.js
|
# Blacklist - exclude everything except npm defaults such as LICENSE, etc
|
||||||
**/*.api.ts
|
*
|
||||||
tsconfig.json
|
!*/
|
||||||
.yarnrc
|
|
||||||
webpack.config.js
|
# Whitelist - lib/
|
||||||
|
!lib/**/*.d.ts
|
||||||
|
|
||||||
|
!lib/**/*.js
|
||||||
|
!lib/**/*.js.map
|
||||||
|
|
||||||
|
!lib/**/*.css
|
||||||
|
|
||||||
|
# Whitelist - src/
|
||||||
|
!src/**/*.ts
|
||||||
|
!src/**/*.d.ts
|
||||||
|
|
||||||
|
!src/**/*.js
|
||||||
|
!src/**/*.js.map
|
||||||
|
|
||||||
|
!src/**/*.css
|
||||||
|
|
||||||
|
# Blacklist - src/ test files
|
||||||
|
src/**/*.test.ts
|
||||||
|
src/**/*.test.d.ts
|
||||||
|
src/**/*.test.js
|
||||||
|
src/**/*.test.js.map
|
||||||
|
|
||||||
|
# Whitelist - typings/
|
||||||
|
!typings/*.d.ts
|
||||||
|
|||||||
@@ -1,5 +1,29 @@
|
|||||||
**/*.api.js
|
# Blacklist - exclude everything except npm defaults such as LICENSE, etc
|
||||||
**/*.api.ts
|
*
|
||||||
tsconfig.json
|
!*/
|
||||||
.yarnrc
|
|
||||||
webpack.config.js
|
# Whitelist - lib/
|
||||||
|
!lib/**/*.d.ts
|
||||||
|
|
||||||
|
!lib/**/*.js
|
||||||
|
!lib/**/*.js.map
|
||||||
|
|
||||||
|
!lib/**/*.css
|
||||||
|
|
||||||
|
# Whitelist - src/
|
||||||
|
!src/**/*.ts
|
||||||
|
!src/**/*.d.ts
|
||||||
|
|
||||||
|
!src/**/*.js
|
||||||
|
!src/**/*.js.map
|
||||||
|
|
||||||
|
!src/**/*.css
|
||||||
|
|
||||||
|
# Blacklist - src/ test files
|
||||||
|
src/**/*.test.ts
|
||||||
|
src/**/*.test.d.ts
|
||||||
|
src/**/*.test.js
|
||||||
|
src/**/*.test.js.map
|
||||||
|
|
||||||
|
# Whitelist - typings/
|
||||||
|
!typings/*.d.ts
|
||||||
|
|||||||
@@ -72,7 +72,8 @@ function equalFlags(cell1: IBufferCell, cell2: IBufferCell): boolean {
|
|||||||
&& cell1.isBlink() === cell2.isBlink()
|
&& cell1.isBlink() === cell2.isBlink()
|
||||||
&& cell1.isInvisible() === cell2.isInvisible()
|
&& cell1.isInvisible() === cell2.isInvisible()
|
||||||
&& cell1.isItalic() === cell2.isItalic()
|
&& cell1.isItalic() === cell2.isItalic()
|
||||||
&& cell1.isDim() === cell2.isDim();
|
&& cell1.isDim() === cell2.isDim()
|
||||||
|
&& cell1.isStrikethrough() === cell2.isStrikethrough();
|
||||||
}
|
}
|
||||||
|
|
||||||
class StringSerializeHandler extends BaseSerializeHandler {
|
class StringSerializeHandler extends BaseSerializeHandler {
|
||||||
@@ -160,7 +161,7 @@ class StringSerializeHandler extends BaseSerializeHandler {
|
|||||||
if (
|
if (
|
||||||
// you must output character to cause overflow, control sequence can't do this
|
// you must output character to cause overflow, control sequence can't do this
|
||||||
nextRowFirstChar.getChars() &&
|
nextRowFirstChar.getChars() &&
|
||||||
isNextRowFirstCharDoubleWidth ? this._nullCellCount <= 1 : this._nullCellCount <= 0
|
isNextRowFirstCharDoubleWidth ? this._nullCellCount <= 1 : this._nullCellCount <= 0
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
// the last character can't be null,
|
// the last character can't be null,
|
||||||
@@ -259,6 +260,7 @@ class StringSerializeHandler extends BaseSerializeHandler {
|
|||||||
if (cell.isInvisible() !== oldCell.isInvisible()) { sgrSeq.push(cell.isInvisible() ? 8 : 28); }
|
if (cell.isInvisible() !== oldCell.isInvisible()) { sgrSeq.push(cell.isInvisible() ? 8 : 28); }
|
||||||
if (cell.isItalic() !== oldCell.isItalic()) { sgrSeq.push(cell.isItalic() ? 3 : 23); }
|
if (cell.isItalic() !== oldCell.isItalic()) { sgrSeq.push(cell.isItalic() ? 3 : 23); }
|
||||||
if (cell.isDim() !== oldCell.isDim()) { sgrSeq.push(cell.isDim() ? 2 : 22); }
|
if (cell.isDim() !== oldCell.isDim()) { sgrSeq.push(cell.isDim() ? 2 : 22); }
|
||||||
|
if (cell.isStrikethrough() !== oldCell.isStrikethrough()) { sgrSeq.push(cell.isStrikethrough() ? 9 : 29); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -433,26 +435,37 @@ export class SerializeAddon implements ITerminalAddon {
|
|||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
public serialize(scrollback?: number): string {
|
public serialize(options?: ISerializeOptions): string {
|
||||||
// TODO: Add combinedData support
|
// TODO: Add combinedData support
|
||||||
if (!this._terminal) {
|
if (!this._terminal) {
|
||||||
throw new Error('Cannot use addon until it has been loaded');
|
throw new Error('Cannot use addon until it has been loaded');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normal buffer
|
// Normal buffer
|
||||||
let content = this._serializeBuffer(this._terminal, this._terminal.buffer.normal, scrollback);
|
let content = this._serializeBuffer(this._terminal, this._terminal.buffer.normal, options?.scrollback);
|
||||||
|
|
||||||
// Alternate buffer
|
// Alternate buffer
|
||||||
if (this._terminal.buffer.active.type === 'alternate') {
|
if (!options?.excludeAltBuffer) {
|
||||||
const alternativeScreenContent = this._serializeBuffer(this._terminal, this._terminal.buffer.alternate, undefined);
|
if (this._terminal.buffer.active.type === 'alternate') {
|
||||||
content += `\u001b[?1049h\u001b[H${alternativeScreenContent}`;
|
const alternativeScreenContent = this._serializeBuffer(this._terminal, this._terminal.buffer.alternate, undefined);
|
||||||
|
content += `\u001b[?1049h\u001b[H${alternativeScreenContent}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modes
|
// Modes
|
||||||
content += this._serializeModes(this._terminal);
|
if (!options?.excludeModes) {
|
||||||
|
content += this._serializeModes(this._terminal);
|
||||||
|
}
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose(): void { }
|
public dispose(): void { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface ISerializeOptions {
|
||||||
|
scrollback?: number;
|
||||||
|
excludeModes?: boolean;
|
||||||
|
excludeAltBuffer?: boolean;
|
||||||
|
}
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ describe('SerializeAddon', () => {
|
|||||||
const cols = 10;
|
const cols = 10;
|
||||||
const lines = newArray<string>((index: number) => digitsString(cols, index), rows);
|
const lines = newArray<string>((index: number) => digitsString(cols, index), rows);
|
||||||
await writeSync(page, lines.join('\\r\\n'));
|
await writeSync(page, lines.join('\\r\\n'));
|
||||||
assert.equal(await page.evaluate(`serializeAddon.serialize(${halfScrollback});`), lines.slice(halfScrollback, rows).join('\r\n'));
|
assert.equal(await page.evaluate(`serializeAddon.serialize({ scrollback: ${halfScrollback} });`), lines.slice(halfScrollback, rows).join('\r\n'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('serialize 0 rows of scrollback', async function(): Promise<any> {
|
it('serialize 0 rows of scrollback', async function(): Promise<any> {
|
||||||
@@ -154,7 +154,19 @@ describe('SerializeAddon', () => {
|
|||||||
const cols = 10;
|
const cols = 10;
|
||||||
const lines = newArray<string>((index: number) => digitsString(cols, index), rows);
|
const lines = newArray<string>((index: number) => digitsString(cols, index), rows);
|
||||||
await writeSync(page, lines.join('\\r\\n'));
|
await writeSync(page, lines.join('\\r\\n'));
|
||||||
assert.equal(await page.evaluate(`serializeAddon.serialize(0);`), lines.slice(rows - 10, rows).join('\r\n'));
|
assert.equal(await page.evaluate(`serializeAddon.serialize({ scrollback: 0 });`), lines.slice(rows - 10, rows).join('\r\n'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('serialize exclude modes', async () => {
|
||||||
|
await writeSync(page, 'before\\x1b[?1hafter');
|
||||||
|
assert.equal(await page.evaluate(`serializeAddon.serialize();`), 'beforeafter\x1b[?1h');
|
||||||
|
assert.equal(await page.evaluate(`serializeAddon.serialize({ excludeModes: true });`), 'beforeafter');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('serialize exclude alt buffer', async () => {
|
||||||
|
await writeSync(page, 'normal\\x1b[?1049h\\x1b[Halt');
|
||||||
|
assert.equal(await page.evaluate(`serializeAddon.serialize();`), 'normal\x1b[?1049h\x1b[Halt');
|
||||||
|
assert.equal(await page.evaluate(`serializeAddon.serialize({ excludeAltBuffer: true });`), 'normal');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('serialize all rows of content with color16', async function(): Promise<any> {
|
it('serialize all rows of content with color16', async function(): Promise<any> {
|
||||||
@@ -184,11 +196,13 @@ describe('SerializeAddon', () => {
|
|||||||
sgr(UNDERLINED) + line,
|
sgr(UNDERLINED) + line,
|
||||||
sgr(BLINK) + line,
|
sgr(BLINK) + line,
|
||||||
sgr(INVISIBLE) + line,
|
sgr(INVISIBLE) + line,
|
||||||
|
sgr(STRIKETHROUGH) + line,
|
||||||
sgr(NO_INVERSE) + line,
|
sgr(NO_INVERSE) + line,
|
||||||
sgr(NO_BOLD) + line,
|
sgr(NO_BOLD) + line,
|
||||||
sgr(NO_UNDERLINED) + line,
|
sgr(NO_UNDERLINED) + line,
|
||||||
sgr(NO_BLINK) + line,
|
sgr(NO_BLINK) + line,
|
||||||
sgr(NO_INVISIBLE) + line
|
sgr(NO_INVISIBLE) + line,
|
||||||
|
sgr(NO_STRIKETHROUGH) + line
|
||||||
];
|
];
|
||||||
const rows = lines.length;
|
const rows = lines.length;
|
||||||
await writeSync(page, lines.join('\\r\\n'));
|
await writeSync(page, lines.join('\\r\\n'));
|
||||||
@@ -579,20 +593,20 @@ const BG_RGB_GREEN = '48;2;0;255;0';
|
|||||||
const BG_RGB_YELLOW = '48;2;255;255;0';
|
const BG_RGB_YELLOW = '48;2;255;255;0';
|
||||||
const BG_RESET = '49';
|
const BG_RESET = '49';
|
||||||
|
|
||||||
const INVERSE = '7';
|
|
||||||
const BOLD = '1';
|
const BOLD = '1';
|
||||||
|
const DIM = '2';
|
||||||
|
const ITALIC = '3';
|
||||||
const UNDERLINED = '4';
|
const UNDERLINED = '4';
|
||||||
const BLINK = '5';
|
const BLINK = '5';
|
||||||
|
const INVERSE = '7';
|
||||||
const INVISIBLE = '8';
|
const INVISIBLE = '8';
|
||||||
|
const STRIKETHROUGH = '9';
|
||||||
|
|
||||||
const NO_INVERSE = '27';
|
|
||||||
const NO_BOLD = '22';
|
const NO_BOLD = '22';
|
||||||
|
const NO_DIM = '22';
|
||||||
|
const NO_ITALIC = '23';
|
||||||
const NO_UNDERLINED = '24';
|
const NO_UNDERLINED = '24';
|
||||||
const NO_BLINK = '25';
|
const NO_BLINK = '25';
|
||||||
|
const NO_INVERSE = '27';
|
||||||
const NO_INVISIBLE = '28';
|
const NO_INVISIBLE = '28';
|
||||||
|
const NO_STRIKETHROUGH = '29';
|
||||||
const ITALIC = '3';
|
|
||||||
const DIM = '2';
|
|
||||||
|
|
||||||
const NO_ITALIC = '23';
|
|
||||||
const NO_DIM = '22';
|
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ import { Terminal, ITerminalAddon } from 'xterm';
|
|||||||
|
|
||||||
declare module 'xterm-addon-serialize' {
|
declare module 'xterm-addon-serialize' {
|
||||||
/**
|
/**
|
||||||
* An xterm.js addon that enables web links.
|
* An xterm.js addon that enables serialization of terminal contents.
|
||||||
*/
|
*/
|
||||||
export class SerializeAddon implements ITerminalAddon {
|
export class SerializeAddon implements ITerminalAddon {
|
||||||
|
|
||||||
constructor();
|
constructor();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activates the addon
|
* Activates the addon.
|
||||||
* @param terminal The terminal the addon is being loaded in.
|
* @param terminal The terminal the addon is being loaded in.
|
||||||
*/
|
*/
|
||||||
public activate(terminal: Terminal): void;
|
public activate(terminal: Terminal): void;
|
||||||
@@ -24,15 +24,36 @@ declare module 'xterm-addon-serialize' {
|
|||||||
* the state. The cursor will also be positioned to the correct cell. When restoring a terminal
|
* the state. The cursor will also be positioned to the correct cell. When restoring a terminal
|
||||||
* it is best to do before `Terminal.open` is called to avoid wasting CPU cycles rendering
|
* it is best to do before `Terminal.open` is called to avoid wasting CPU cycles rendering
|
||||||
* incomplete frames.
|
* incomplete frames.
|
||||||
* @param scrollback The number of rows in scrollback buffer to serialize, starting from the
|
*
|
||||||
* bottom of the scrollback buffer. This defaults to the all available rows in the scrollback
|
* It's recommended that you write the serialized data into a terminal of the same size in which
|
||||||
* buffer.
|
* it originated from and then resize it after if needed.
|
||||||
|
*
|
||||||
|
* @param options Custom options to allow control over what gets serialized.
|
||||||
*/
|
*/
|
||||||
public serialize(scrollback?: number): string;
|
public serialize(options?: ISerializeOptions): string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disposes the addon.
|
* Disposes the addon.
|
||||||
*/
|
*/
|
||||||
public dispose(): void;
|
public dispose(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ISerializeOptions {
|
||||||
|
/**
|
||||||
|
* The number of rows in the scrollback buffer to serialize, starting from the bottom of the
|
||||||
|
* scrollback buffer. When not specified, all available rows in the scrollback buffer will be
|
||||||
|
* serialized.
|
||||||
|
*/
|
||||||
|
scrollback?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to exclude the terminal modes from the serialization. False by default.
|
||||||
|
*/
|
||||||
|
excludeModes?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to exclude the alt buffer from the serialization. False by default.
|
||||||
|
*/
|
||||||
|
excludeAltBuffer?: boolean;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,29 @@
|
|||||||
**/*.api.js
|
# Blacklist - exclude everything except npm defaults such as LICENSE, etc
|
||||||
**/*.api.ts
|
*
|
||||||
tsconfig.json
|
!*/
|
||||||
.yarnrc
|
|
||||||
webpack.config.js
|
# Whitelist - lib/
|
||||||
|
!lib/**/*.d.ts
|
||||||
|
|
||||||
|
!lib/**/*.js
|
||||||
|
!lib/**/*.js.map
|
||||||
|
|
||||||
|
!lib/**/*.css
|
||||||
|
|
||||||
|
# Whitelist - src/
|
||||||
|
!src/**/*.ts
|
||||||
|
!src/**/*.d.ts
|
||||||
|
|
||||||
|
!src/**/*.js
|
||||||
|
!src/**/*.js.map
|
||||||
|
|
||||||
|
!src/**/*.css
|
||||||
|
|
||||||
|
# Blacklist - src/ test files
|
||||||
|
src/**/*.test.ts
|
||||||
|
src/**/*.test.d.ts
|
||||||
|
src/**/*.test.js
|
||||||
|
src/**/*.test.js.map
|
||||||
|
|
||||||
|
# Whitelist - typings/
|
||||||
|
!typings/*.d.ts
|
||||||
|
|||||||
@@ -1,5 +1,29 @@
|
|||||||
**/*.api.js
|
# Blacklist - exclude everything except npm defaults such as LICENSE, etc
|
||||||
**/*.api.ts
|
*
|
||||||
tsconfig.json
|
!*/
|
||||||
.yarnrc
|
|
||||||
webpack.config.js
|
# Whitelist - lib/
|
||||||
|
!lib/**/*.d.ts
|
||||||
|
|
||||||
|
!lib/**/*.js
|
||||||
|
!lib/**/*.js.map
|
||||||
|
|
||||||
|
!lib/**/*.css
|
||||||
|
|
||||||
|
# Whitelist - src/
|
||||||
|
!src/**/*.ts
|
||||||
|
!src/**/*.d.ts
|
||||||
|
|
||||||
|
!src/**/*.js
|
||||||
|
!src/**/*.js.map
|
||||||
|
|
||||||
|
!src/**/*.css
|
||||||
|
|
||||||
|
# Blacklist - src/ test files
|
||||||
|
src/**/*.test.ts
|
||||||
|
src/**/*.test.d.ts
|
||||||
|
src/**/*.test.js
|
||||||
|
src/**/*.test.js.map
|
||||||
|
|
||||||
|
# Whitelist - typings/
|
||||||
|
!typings/*.d.ts
|
||||||
|
|||||||
@@ -29,7 +29,11 @@ const strictUrlRegex = new RegExp(start + protocolClause + bodyClause + end);
|
|||||||
function handleLink(event: MouseEvent, uri: string): void {
|
function handleLink(event: MouseEvent, uri: string): void {
|
||||||
const newWindow = window.open();
|
const newWindow = window.open();
|
||||||
if (newWindow) {
|
if (newWindow) {
|
||||||
newWindow.opener = null;
|
try {
|
||||||
|
newWindow.opener = null;
|
||||||
|
} catch {
|
||||||
|
// no-op, Electron can throw
|
||||||
|
}
|
||||||
newWindow.location.href = uri;
|
newWindow.location.href = uri;
|
||||||
} else {
|
} else {
|
||||||
console.warn('Opening link blocked as opener could not be cleared');
|
console.warn('Opening link blocked as opener could not be cleared');
|
||||||
|
|||||||
@@ -1,7 +1,29 @@
|
|||||||
**/*.api.js
|
# Blacklist - exclude everything except npm defaults such as LICENSE, etc
|
||||||
**/*.api.ts
|
*
|
||||||
tsconfig.json
|
!*/
|
||||||
.yarnrc
|
|
||||||
webpack.config.js
|
# Whitelist - lib/
|
||||||
out-test/
|
!lib/**/*.d.ts
|
||||||
test/
|
|
||||||
|
!lib/**/*.js
|
||||||
|
!lib/**/*.js.map
|
||||||
|
|
||||||
|
!lib/**/*.css
|
||||||
|
|
||||||
|
# Whitelist - src/
|
||||||
|
!src/**/*.ts
|
||||||
|
!src/**/*.d.ts
|
||||||
|
|
||||||
|
!src/**/*.js
|
||||||
|
!src/**/*.js.map
|
||||||
|
|
||||||
|
!src/**/*.css
|
||||||
|
|
||||||
|
# Blacklist - src/ test files
|
||||||
|
src/**/*.test.ts
|
||||||
|
src/**/*.test.d.ts
|
||||||
|
src/**/*.test.js
|
||||||
|
src/**/*.test.js.map
|
||||||
|
|
||||||
|
# Whitelist - typings/
|
||||||
|
!typings/*.d.ts
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { WebglRenderer } from './WebglRenderer';
|
|||||||
import { ICharacterJoinerService, IRenderService } from 'browser/services/Services';
|
import { ICharacterJoinerService, IRenderService } from 'browser/services/Services';
|
||||||
import { IColorSet } from 'browser/Types';
|
import { IColorSet } from 'browser/Types';
|
||||||
import { EventEmitter } from 'common/EventEmitter';
|
import { EventEmitter } from 'common/EventEmitter';
|
||||||
|
import { isSafari } from 'common/Platform';
|
||||||
|
|
||||||
export class WebglAddon implements ITerminalAddon {
|
export class WebglAddon implements ITerminalAddon {
|
||||||
private _terminal?: Terminal;
|
private _terminal?: Terminal;
|
||||||
@@ -23,6 +24,9 @@ export class WebglAddon implements ITerminalAddon {
|
|||||||
if (!terminal.element) {
|
if (!terminal.element) {
|
||||||
throw new Error('Cannot activate WebglAddon before Terminal.open');
|
throw new Error('Cannot activate WebglAddon before Terminal.open');
|
||||||
}
|
}
|
||||||
|
if (isSafari) {
|
||||||
|
throw new Error('Webgl is not currently supported on Safari');
|
||||||
|
}
|
||||||
this._terminal = terminal;
|
this._terminal = terminal;
|
||||||
const renderService: IRenderService = (terminal as any)._core._renderService;
|
const renderService: IRenderService = (terminal as any)._core._renderService;
|
||||||
const characterJoinerService: ICharacterJoinerService = (terminal as any)._core._characterJoinerService;
|
const characterJoinerService: ICharacterJoinerService = (terminal as any)._core._characterJoinerService;
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
|||||||
|
|
||||||
this._renderLayers = [
|
this._renderLayers = [
|
||||||
new LinkRenderLayer(this._core.screenElement!, 2, this._colors, this._core),
|
new LinkRenderLayer(this._core.screenElement!, 2, this._colors, this._core),
|
||||||
new CursorRenderLayer(this._core.screenElement!, 3, this._colors, this._core, this._onRequestRedraw)
|
new CursorRenderLayer(_terminal, this._core.screenElement!, 3, this._colors, this._core, this._onRequestRedraw)
|
||||||
];
|
];
|
||||||
this.dimensions = {
|
this.dimensions = {
|
||||||
scaledCharWidth: 0,
|
scaledCharWidth: 0,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ICharAtlasConfig } from './Types';
|
import { ICharAtlasConfig } from './Types';
|
||||||
import { DIM_OPACITY } from 'browser/renderer/atlas/Constants';
|
import { DIM_OPACITY, TEXT_BASELINE } from 'browser/renderer/atlas/Constants';
|
||||||
import { IRasterizedGlyph, IBoundingBox, IRasterizedGlyphSet } from '../Types';
|
import { IRasterizedGlyph, IBoundingBox, IRasterizedGlyphSet } from '../Types';
|
||||||
import { DEFAULT_COLOR, Attributes } from 'common/buffer/Constants';
|
import { DEFAULT_COLOR, Attributes } from 'common/buffer/Constants';
|
||||||
import { throwIfFalsy } from '../WebglUtils';
|
import { throwIfFalsy } from '../WebglUtils';
|
||||||
@@ -368,7 +368,7 @@ export class WebglCharAtlas implements IDisposable {
|
|||||||
const fontStyle = italic ? 'italic' : '';
|
const fontStyle = italic ? 'italic' : '';
|
||||||
this._tmpCtx.font =
|
this._tmpCtx.font =
|
||||||
`${fontStyle} ${fontWeight} ${this._config.fontSize * this._config.devicePixelRatio}px ${this._config.fontFamily}`;
|
`${fontStyle} ${fontWeight} ${this._config.fontSize * this._config.devicePixelRatio}px ${this._config.fontFamily}`;
|
||||||
this._tmpCtx.textBaseline = 'ideographic';
|
this._tmpCtx.textBaseline = TEXT_BASELINE;
|
||||||
|
|
||||||
this._tmpCtx.fillStyle = this._getForegroundCss(bg, bgColorMode, bgColor, fg, fgColorMode, fgColor, inverse, bold);
|
this._tmpCtx.fillStyle = this._getForegroundCss(bg, bgColorMode, bgColor, fg, fgColorMode, fgColor, inverse, bold);
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { IRenderLayer } from './Types';
|
|||||||
import { acquireCharAtlas } from '../atlas/CharAtlasCache';
|
import { acquireCharAtlas } from '../atlas/CharAtlasCache';
|
||||||
import { Terminal } from 'xterm';
|
import { Terminal } from 'xterm';
|
||||||
import { IColorSet } from 'browser/Types';
|
import { IColorSet } from 'browser/Types';
|
||||||
|
import { TEXT_BASELINE } from 'browser/renderer/atlas/Constants';
|
||||||
import { IRenderDimensions } from 'browser/renderer/Types';
|
import { IRenderDimensions } from 'browser/renderer/Types';
|
||||||
import { CellData } from 'common/buffer/CellData';
|
import { CellData } from 'common/buffer/CellData';
|
||||||
import { WebglCharAtlas } from 'atlas/WebglCharAtlas';
|
import { WebglCharAtlas } from 'atlas/WebglCharAtlas';
|
||||||
@@ -224,7 +225,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
|
|||||||
*/
|
*/
|
||||||
protected _fillCharTrueColor(terminal: Terminal, cell: CellData, x: number, y: number): void {
|
protected _fillCharTrueColor(terminal: Terminal, cell: CellData, x: number, y: number): void {
|
||||||
this._ctx.font = this._getFont(terminal, false, false);
|
this._ctx.font = this._getFont(terminal, false, false);
|
||||||
this._ctx.textBaseline = 'ideographic';
|
this._ctx.textBaseline = TEXT_BASELINE;
|
||||||
this._clipRow(terminal, y);
|
this._clipRow(terminal, y);
|
||||||
this._ctx.fillText(
|
this._ctx.fillText(
|
||||||
cell.getChars(),
|
cell.getChars(),
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ export class CursorRenderLayer extends BaseRenderLayer {
|
|||||||
private _cell: ICellData = new CellData();
|
private _cell: ICellData = new CellData();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
terminal: Terminal,
|
||||||
container: HTMLElement,
|
container: HTMLElement,
|
||||||
zIndex: number,
|
zIndex: number,
|
||||||
colors: IColorSet,
|
colors: IColorSet,
|
||||||
@@ -50,7 +51,7 @@ export class CursorRenderLayer extends BaseRenderLayer {
|
|||||||
'block': this._renderBlockCursor.bind(this),
|
'block': this._renderBlockCursor.bind(this),
|
||||||
'underline': this._renderUnderlineCursor.bind(this)
|
'underline': this._renderUnderlineCursor.bind(this)
|
||||||
};
|
};
|
||||||
// TODO: Consider initial options? Maybe onOptionsChanged should be called at the end of open?
|
this.onOptionsChanged(terminal);
|
||||||
}
|
}
|
||||||
|
|
||||||
public resize(terminal: Terminal, dim: IRenderDimensions): void {
|
public resize(terminal: Terminal, dim: IRenderDimensions): void {
|
||||||
@@ -67,25 +68,18 @@ export class CursorRenderLayer extends BaseRenderLayer {
|
|||||||
|
|
||||||
public reset(terminal: Terminal): void {
|
public reset(terminal: Terminal): void {
|
||||||
this._clearCursor();
|
this._clearCursor();
|
||||||
if (this._cursorBlinkStateManager) {
|
this._cursorBlinkStateManager?.restartBlinkAnimation(terminal);
|
||||||
this._cursorBlinkStateManager.dispose();
|
this.onOptionsChanged(terminal);
|
||||||
this.onOptionsChanged(terminal);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public onBlur(terminal: Terminal): void {
|
public onBlur(terminal: Terminal): void {
|
||||||
if (this._cursorBlinkStateManager) {
|
this._cursorBlinkStateManager?.pause();
|
||||||
this._cursorBlinkStateManager.pause();
|
|
||||||
}
|
|
||||||
this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.active.cursorY, end: terminal.buffer.active.cursorY });
|
this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.active.cursorY, end: terminal.buffer.active.cursorY });
|
||||||
}
|
}
|
||||||
|
|
||||||
public onFocus(terminal: Terminal): void {
|
public onFocus(terminal: Terminal): void {
|
||||||
if (this._cursorBlinkStateManager) {
|
this._cursorBlinkStateManager?.resume(terminal);
|
||||||
this._cursorBlinkStateManager.resume(terminal);
|
this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.active.cursorY, end: terminal.buffer.active.cursorY });
|
||||||
} else {
|
|
||||||
this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.active.cursorY, end: terminal.buffer.active.cursorY });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public onOptionsChanged(terminal: Terminal): void {
|
public onOptionsChanged(terminal: Terminal): void {
|
||||||
@@ -105,9 +99,7 @@ export class CursorRenderLayer extends BaseRenderLayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onCursorMove(terminal: Terminal): void {
|
public onCursorMove(terminal: Terminal): void {
|
||||||
if (this._cursorBlinkStateManager) {
|
this._cursorBlinkStateManager?.restartBlinkAnimation(terminal);
|
||||||
this._cursorBlinkStateManager.restartBlinkAnimation(terminal);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public onGridChanged(terminal: Terminal, startRow: number, endRow: number): void {
|
public onGridChanged(terminal: Terminal, startRow: number, endRow: number): void {
|
||||||
@@ -302,6 +294,7 @@ class CursorBlinkStateManager {
|
|||||||
// Clear any existing interval
|
// Clear any existing interval
|
||||||
if (this._blinkInterval) {
|
if (this._blinkInterval) {
|
||||||
window.clearInterval(this._blinkInterval);
|
window.clearInterval(this._blinkInterval);
|
||||||
|
this._blinkInterval = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup the initial timeout which will hide the cursor, this is done before
|
// Setup the initial timeout which will hide the cursor, this is done before
|
||||||
|
|||||||
+3
-3
@@ -59,7 +59,7 @@ jobs:
|
|||||||
|
|
||||||
- job: Windows
|
- job: Windows
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'vs2017-win2016'
|
vmImage: 'windows-2019'
|
||||||
steps:
|
steps:
|
||||||
- task: NodeTool@0
|
- task: NodeTool@0
|
||||||
inputs:
|
inputs:
|
||||||
@@ -124,7 +124,7 @@ jobs:
|
|||||||
|
|
||||||
- job: Windows_IntegrationTests
|
- job: Windows_IntegrationTests
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'vs2017-win2016'
|
vmImage: 'windows-2019'
|
||||||
steps:
|
steps:
|
||||||
- task: NodeTool@0
|
- task: NodeTool@0
|
||||||
inputs:
|
inputs:
|
||||||
@@ -147,7 +147,7 @@ jobs:
|
|||||||
- Windows_IntegrationTests
|
- Windows_IntegrationTests
|
||||||
condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq(variables['FORCE_RELEASE'], 'true')))
|
condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq(variables['FORCE_RELEASE'], 'true')))
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'ubuntu-16.04'
|
vmImage: 'ubuntu-18.04'
|
||||||
steps:
|
steps:
|
||||||
- task: NodeTool@0
|
- task: NodeTool@0
|
||||||
inputs:
|
inputs:
|
||||||
|
|||||||
+15
-12
@@ -293,11 +293,11 @@ function initOptions(term: TerminalType): void {
|
|||||||
rendererType: ['dom', 'canvas'],
|
rendererType: ['dom', 'canvas'],
|
||||||
wordSeparator: null
|
wordSeparator: null
|
||||||
};
|
};
|
||||||
const options = Object.keys((<any>term)._core.options);
|
const options = Object.keys(term.options);
|
||||||
const booleanOptions = [];
|
const booleanOptions = [];
|
||||||
const numberOptions = [];
|
const numberOptions = [];
|
||||||
options.filter(o => blacklistedOptions.indexOf(o) === -1).forEach(o => {
|
options.filter(o => blacklistedOptions.indexOf(o) === -1).forEach(o => {
|
||||||
switch (typeof term.getOption(o)) {
|
switch (typeof term.options[o]) {
|
||||||
case 'boolean':
|
case 'boolean':
|
||||||
booleanOptions.push(o);
|
booleanOptions.push(o);
|
||||||
break;
|
break;
|
||||||
@@ -314,18 +314,18 @@ function initOptions(term: TerminalType): void {
|
|||||||
let html = '';
|
let html = '';
|
||||||
html += '<div class="option-group">';
|
html += '<div class="option-group">';
|
||||||
booleanOptions.forEach(o => {
|
booleanOptions.forEach(o => {
|
||||||
html += `<div class="option"><label><input id="opt-${o}" type="checkbox" ${term.getOption(o) ? 'checked' : ''}/> ${o}</label></div>`;
|
html += `<div class="option"><label><input id="opt-${o}" type="checkbox" ${term.options[o] ? 'checked' : ''}/> ${o}</label></div>`;
|
||||||
});
|
});
|
||||||
html += '</div><div class="option-group">';
|
html += '</div><div class="option-group">';
|
||||||
numberOptions.forEach(o => {
|
numberOptions.forEach(o => {
|
||||||
html += `<div class="option"><label>${o} <input id="opt-${o}" type="number" value="${term.getOption(o)}" step="${o === 'lineHeight' || o === 'scrollSensitivity' ? '0.1' : '1'}"/></label></div>`;
|
html += `<div class="option"><label>${o} <input id="opt-${o}" type="number" value="${term.options[o]}" step="${o === 'lineHeight' || o === 'scrollSensitivity' ? '0.1' : '1'}"/></label></div>`;
|
||||||
});
|
});
|
||||||
html += '</div><div class="option-group">';
|
html += '</div><div class="option-group">';
|
||||||
Object.keys(stringOptions).forEach(o => {
|
Object.keys(stringOptions).forEach(o => {
|
||||||
if (stringOptions[o]) {
|
if (stringOptions[o]) {
|
||||||
html += `<div class="option"><label>${o} <select id="opt-${o}">${stringOptions[o].map(v => `<option ${term.getOption(o) === v ? 'selected' : ''}>${v}</option>`).join('')}</select></label></div>`;
|
html += `<div class="option"><label>${o} <select id="opt-${o}">${stringOptions[o].map(v => `<option ${term.options[o] === v ? 'selected' : ''}>${v}</option>`).join('')}</select></label></div>`;
|
||||||
} else {
|
} else {
|
||||||
html += `<div class="option"><label>${o} <input id="opt-${o}" type="text" value="${term.getOption(o)}"/></label></div>`;
|
html += `<div class="option"><label>${o} <input id="opt-${o}" type="text" value="${term.options[o]}"/></label></div>`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
@@ -338,7 +338,7 @@ function initOptions(term: TerminalType): void {
|
|||||||
const input = <HTMLInputElement>document.getElementById(`opt-${o}`);
|
const input = <HTMLInputElement>document.getElementById(`opt-${o}`);
|
||||||
addDomListener(input, 'change', () => {
|
addDomListener(input, 'change', () => {
|
||||||
console.log('change', o, input.checked);
|
console.log('change', o, input.checked);
|
||||||
term.setOption(o, input.checked);
|
term.options[o] = input.checked;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
numberOptions.forEach(o => {
|
numberOptions.forEach(o => {
|
||||||
@@ -347,14 +347,17 @@ 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' || o === 'scrollSensitivity') {
|
} else if (o === 'lineHeight') {
|
||||||
term.setOption(o, parseFloat(input.value));
|
term.options.lineHeight = parseFloat(input.value);
|
||||||
|
updateTerminalSize();
|
||||||
|
} else if (o === 'scrollSensitivity') {
|
||||||
|
term.options.scrollSensitivity = parseFloat(input.value);
|
||||||
updateTerminalSize();
|
updateTerminalSize();
|
||||||
} else if(o === 'scrollback') {
|
} else if(o === 'scrollback') {
|
||||||
term.setOption(o, parseInt(input.value));
|
term.options.scrollback = parseInt(input.value);
|
||||||
setTimeout(() => updateTerminalSize(), 5);
|
setTimeout(() => updateTerminalSize(), 5);
|
||||||
} else {
|
} else {
|
||||||
term.setOption(o, parseInt(input.value));
|
term.options[o] = parseInt(input.value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -362,7 +365,7 @@ function initOptions(term: TerminalType): void {
|
|||||||
const input = <HTMLInputElement>document.getElementById(`opt-${o}`);
|
const input = <HTMLInputElement>document.getElementById(`opt-${o}`);
|
||||||
addDomListener(input, 'change', () => {
|
addDomListener(input, 'change', () => {
|
||||||
console.log('change', o, input.value);
|
console.log('change', o, input.value);
|
||||||
term.setOption(o, input.value);
|
term.options[o] = input.value;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-5
@@ -1,6 +1,29 @@
|
|||||||
# Include
|
# Blacklist - exclude everything except npm defaults such as LICENSE, etc
|
||||||
!typings/*.d.ts
|
*
|
||||||
!lib-headless/
|
!*/
|
||||||
|
|
||||||
# Exclude
|
# Whitelist - lib-headless/
|
||||||
test/
|
!lib-headless/**/*.d.ts
|
||||||
|
|
||||||
|
!lib-headless/**/*.js
|
||||||
|
!lib-headless/**/*.js.map
|
||||||
|
|
||||||
|
!lib-headless/**/*.css
|
||||||
|
|
||||||
|
# Whitelist - src/
|
||||||
|
!src/**/*.ts
|
||||||
|
!src/**/*.d.ts
|
||||||
|
|
||||||
|
!src/**/*.js
|
||||||
|
!src/**/*.js.map
|
||||||
|
|
||||||
|
!src/**/*.css
|
||||||
|
|
||||||
|
# Blacklist - src/ test files
|
||||||
|
src/**/*.test.ts
|
||||||
|
src/**/*.test.d.ts
|
||||||
|
src/**/*.test.js
|
||||||
|
src/**/*.test.js.map
|
||||||
|
|
||||||
|
# Whitelist - typings/
|
||||||
|
!typings/*.d.ts
|
||||||
|
|||||||
+23
-23
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "xterm",
|
"name": "xterm",
|
||||||
"description": "Full xterm terminal, in your browser",
|
"description": "Full xterm terminal, in your browser",
|
||||||
"version": "4.14.0",
|
"version": "4.14.1",
|
||||||
"main": "lib/xterm.js",
|
"main": "lib/xterm.js",
|
||||||
"style": "css/xterm.css",
|
"style": "css/xterm.css",
|
||||||
"types": "typings/xterm.d.ts",
|
"types": "typings/xterm.d.ts",
|
||||||
@@ -37,39 +37,39 @@
|
|||||||
"vtfeatures": "node bin/extract_vtfeatures.js src/**/*.ts src/*.ts"
|
"vtfeatures": "node bin/extract_vtfeatures.js src/**/*.ts src/*.ts"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chai": "^4.2.18",
|
"@types/chai": "^4.2.22",
|
||||||
"@types/debug": "^4.1.5",
|
"@types/debug": "^4.1.7",
|
||||||
"@types/deep-equal": "^1.0.1",
|
"@types/deep-equal": "^1.0.1",
|
||||||
"@types/glob": "^7.1.3",
|
"@types/glob": "^7.2.0",
|
||||||
"@types/jsdom": "^16.2.10",
|
"@types/jsdom": "^16.2.13",
|
||||||
"@types/mocha": "^8.2.2",
|
"@types/mocha": "^9.0.0",
|
||||||
"@types/node": "^14.14.44",
|
"@types/node": "^14.14.44",
|
||||||
"@types/utf8": "^2.1.6",
|
"@types/utf8": "^3.0.0",
|
||||||
"@types/webpack": "^5.28.0",
|
"@types/webpack": "^5.28.0",
|
||||||
"@types/ws": "^7.4.4",
|
"@types/ws": "^8.2.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.23.0",
|
"@typescript-eslint/eslint-plugin": "^5.3.0",
|
||||||
"@typescript-eslint/parser": "^4.23.0",
|
"@typescript-eslint/parser": "^5.3.0",
|
||||||
"chai": "^4.3.4",
|
"chai": "^4.3.4",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"deep-equal": "^2.0.5",
|
"deep-equal": "^2.0.5",
|
||||||
"eslint": "^7.26.0",
|
"eslint": "^8.1.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-ws": "^4.0.0",
|
"express-ws": "^5.0.2",
|
||||||
"glob": "^7.1.7",
|
"glob": "^7.2.0",
|
||||||
"jsdom": "^16.5.3",
|
"jsdom": "^18.0.1",
|
||||||
"mocha": "^8.4.0",
|
"mocha": "^9.1.3",
|
||||||
"mustache": "^4.2.0",
|
"mustache": "^4.2.0",
|
||||||
"node-pty": "^0.10.1",
|
"node-pty": "^0.10.1",
|
||||||
"nyc": "^15.1.0",
|
"nyc": "^15.1.0",
|
||||||
"playwright": "^1.11.0",
|
"playwright": "^1.16.2",
|
||||||
"source-map-loader": "^2.0.1",
|
"source-map-loader": "^3.0.0",
|
||||||
"source-map-support": "^0.5.19",
|
"source-map-support": "^0.5.20",
|
||||||
"ts-loader": "^9.1.2",
|
"ts-loader": "^9.1.2",
|
||||||
"typescript": "^4.2.4",
|
"typescript": "^4.4.4",
|
||||||
"utf8": "^3.0.0",
|
"utf8": "^3.0.0",
|
||||||
"webpack": "^5.37.0",
|
"webpack": "^5.61.0",
|
||||||
"webpack-cli": "^4.7.0",
|
"webpack-cli": "^4.9.1",
|
||||||
"ws": "^7.4.5",
|
"ws": "^8.2.3",
|
||||||
"xterm-benchmark": "^0.2.1"
|
"xterm-benchmark": "^0.3.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ export class AccessibilityManager extends Disposable {
|
|||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this._accessibilityTreeRoot = document.createElement('div');
|
this._accessibilityTreeRoot = document.createElement('div');
|
||||||
|
this._accessibilityTreeRoot.setAttribute('role', 'document');
|
||||||
this._accessibilityTreeRoot.classList.add('xterm-accessibility');
|
this._accessibilityTreeRoot.classList.add('xterm-accessibility');
|
||||||
|
|
||||||
this._rowContainer = document.createElement('div');
|
this._rowContainer = document.createElement('div');
|
||||||
|
|||||||
+40
-27
@@ -152,7 +152,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|||||||
* @alias module:xterm/src/xterm
|
* @alias module:xterm/src/xterm
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
options: ITerminalOptions = {}
|
options: Partial<ITerminalOptions> = {}
|
||||||
) {
|
) {
|
||||||
super(options);
|
super(options);
|
||||||
|
|
||||||
@@ -164,6 +164,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|||||||
// Setup InputHandler listeners
|
// Setup InputHandler listeners
|
||||||
this.register(this._inputHandler.onRequestBell(() => this.bell()));
|
this.register(this._inputHandler.onRequestBell(() => this.bell()));
|
||||||
this.register(this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end)));
|
this.register(this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end)));
|
||||||
|
this.register(this._inputHandler.onRequestSendFocus(() => this._reportFocus()));
|
||||||
this.register(this._inputHandler.onRequestReset(() => this.reset()));
|
this.register(this._inputHandler.onRequestReset(() => this.reset()));
|
||||||
this.register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type)));
|
this.register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type)));
|
||||||
this.register(this._inputHandler.onAnsiColorChange((event) => this._changeAnsiColor(event)));
|
this.register(this._inputHandler.onAnsiColorChange((event) => this._changeAnsiColor(event)));
|
||||||
@@ -493,7 +494,8 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|||||||
this.viewport = this._instantiationService.createInstance(Viewport,
|
this.viewport = this._instantiationService.createInstance(Viewport,
|
||||||
(amount: number) => this.scrollLines(amount, true, ScrollSource.VIEWPORT),
|
(amount: number) => this.scrollLines(amount, true, ScrollSource.VIEWPORT),
|
||||||
this._viewportElement,
|
this._viewportElement,
|
||||||
this._viewportScrollArea
|
this._viewportScrollArea,
|
||||||
|
this.element
|
||||||
);
|
);
|
||||||
this.viewport.onThemeChange(this._colorManager.colors);
|
this.viewport.onThemeChange(this._colorManager.colors);
|
||||||
this.register(this._inputHandler.onRequestSyncScrollBar(() => this.viewport!.syncScrollArea()));
|
this.register(this._inputHandler.onRequestSyncScrollBar(() => this.viewport!.syncScrollArea()));
|
||||||
@@ -698,8 +700,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|||||||
},
|
},
|
||||||
wheel: (ev: WheelEvent) => {
|
wheel: (ev: WheelEvent) => {
|
||||||
sendEvent(ev);
|
sendEvent(ev);
|
||||||
ev.preventDefault();
|
return this.cancel(ev, true);
|
||||||
return this.cancel(ev);
|
|
||||||
},
|
},
|
||||||
mousedrag: (ev: MouseEvent) => {
|
mousedrag: (ev: MouseEvent) => {
|
||||||
// deal only with move while a button is held
|
// deal only with move while a button is held
|
||||||
@@ -794,33 +795,31 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
this.register(addDisposableDomListener(el, 'wheel', (ev: WheelEvent) => {
|
this.register(addDisposableDomListener(el, 'wheel', (ev: WheelEvent) => {
|
||||||
if (!requestedEvents.wheel) {
|
// do nothing, if app side handles wheel itself
|
||||||
|
if (requestedEvents.wheel) return;
|
||||||
|
|
||||||
|
if (!this.buffer.hasScrollback) {
|
||||||
// Convert wheel events into up/down events when the buffer does not have scrollback, this
|
// Convert wheel events into up/down events when the buffer does not have scrollback, this
|
||||||
// enables scrolling in apps hosted in the alt buffer such as vim or tmux.
|
// enables scrolling in apps hosted in the alt buffer such as vim or tmux.
|
||||||
if (!this.buffer.hasScrollback) {
|
const amount = this.viewport!.getLinesScrolled(ev);
|
||||||
const amount = this.viewport!.getLinesScrolled(ev);
|
|
||||||
|
|
||||||
// Do nothing if there's no vertical scroll
|
// Do nothing if there's no vertical scroll
|
||||||
if (amount === 0) {
|
if (amount === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// Construct and send sequences
|
|
||||||
const sequence = C0.ESC + (this.coreService.decPrivateModes.applicationCursorKeys ? 'O' : '[') + (ev.deltaY < 0 ? 'A' : 'B');
|
|
||||||
let data = '';
|
|
||||||
for (let i = 0; i < Math.abs(amount); i++) {
|
|
||||||
data += sequence;
|
|
||||||
}
|
|
||||||
this.coreService.triggerDataEvent(data, true);
|
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
}, { passive: true }));
|
|
||||||
|
|
||||||
// allow wheel scrolling in
|
// Construct and send sequences
|
||||||
// the shell for example
|
const sequence = C0.ESC + (this.coreService.decPrivateModes.applicationCursorKeys ? 'O' : '[') + (ev.deltaY < 0 ? 'A' : 'B');
|
||||||
this.register(addDisposableDomListener(el, 'wheel', (ev: WheelEvent) => {
|
let data = '';
|
||||||
if (requestedEvents.wheel) return;
|
for (let i = 0; i < Math.abs(amount); i++) {
|
||||||
|
data += sequence;
|
||||||
|
}
|
||||||
|
this.coreService.triggerDataEvent(data, true);
|
||||||
|
return this.cancel(ev, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// normal viewport scrolling
|
||||||
|
// conditionally stop event, if the viewport still had rows to scroll within
|
||||||
if (!this.viewport!.onWheel(ev)) {
|
if (!this.viewport!.onWheel(ev)) {
|
||||||
return this.cancel(ev);
|
return this.cancel(ev);
|
||||||
}
|
}
|
||||||
@@ -1180,7 +1179,9 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|||||||
* @param ev The input event to be handled.
|
* @param ev The input event to be handled.
|
||||||
*/
|
*/
|
||||||
protected _inputEvent(ev: InputEvent): boolean {
|
protected _inputEvent(ev: InputEvent): boolean {
|
||||||
if (ev.data && ev.inputType === 'insertText') {
|
// Only support emoji IMEs when screen reader mode is disabled as the event must bubble up to
|
||||||
|
// support reading out character input which can doubling up input characters
|
||||||
|
if (ev.data && ev.inputType === 'insertText' && !this.optionsService.options.screenReaderMode) {
|
||||||
if (this._keyPressHandled) {
|
if (this._keyPressHandled) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1290,6 +1291,18 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|||||||
this.viewport?.syncScrollArea();
|
this.viewport?.syncScrollArea();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clearTextureAtlas(): void {
|
||||||
|
this._renderService?.clearTextureAtlas();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _reportFocus(): void {
|
||||||
|
if (this.element?.classList.contains('focus')) {
|
||||||
|
this.coreService.triggerDataEvent(C0.ESC + '[I');
|
||||||
|
} else {
|
||||||
|
this.coreService.triggerDataEvent(C0.ESC + '[O');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private _reportWindowsOptions(type: WindowsOptionsReportType): void {
|
private _reportWindowsOptions(type: WindowsOptionsReportType): void {
|
||||||
if (!this._renderService) {
|
if (!this._renderService) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -195,6 +195,9 @@ export class MockTerminal implements ITerminal {
|
|||||||
public reset(): void {
|
public reset(): void {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
public clearTextureAtlas(): void {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
public refresh(start: number, end: number): void {
|
public refresh(start: number, end: number): void {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
@@ -374,6 +377,9 @@ export class MockRenderService implements IRenderService {
|
|||||||
public refreshRows(start: number, end: number): void {
|
public refreshRows(start: number, end: number): void {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
public clearTextureAtlas(): void {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
public resize(cols: number, rows: number): void {
|
public resize(cols: number, rows: number): void {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
@@ -79,6 +79,7 @@ export interface IPublicTerminal extends IDisposable {
|
|||||||
write(data: string | Uint8Array, callback?: () => void): void;
|
write(data: string | Uint8Array, callback?: () => void): void;
|
||||||
paste(data: string): void;
|
paste(data: string): void;
|
||||||
refresh(start: number, end: number): void;
|
refresh(start: number, end: number): void;
|
||||||
|
clearTextureAtlas(): void;
|
||||||
reset(): void;
|
reset(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ export class Viewport extends Disposable implements IViewport {
|
|||||||
private readonly _scrollLines: (amount: number) => void,
|
private readonly _scrollLines: (amount: number) => void,
|
||||||
private readonly _viewportElement: HTMLElement,
|
private readonly _viewportElement: HTMLElement,
|
||||||
private readonly _scrollArea: HTMLElement,
|
private readonly _scrollArea: HTMLElement,
|
||||||
|
private readonly _element: HTMLElement,
|
||||||
@IBufferService private readonly _bufferService: IBufferService,
|
@IBufferService private readonly _bufferService: IBufferService,
|
||||||
@IOptionsService private readonly _optionsService: IOptionsService,
|
@IOptionsService private readonly _optionsService: IOptionsService,
|
||||||
@ICharSizeService private readonly _charSizeService: ICharSizeService,
|
@ICharSizeService private readonly _charSizeService: ICharSizeService,
|
||||||
@@ -116,7 +117,9 @@ export class Viewport extends Disposable implements IViewport {
|
|||||||
}
|
}
|
||||||
this._lastHadScrollBar = this.scrollBarWidth > 0;
|
this._lastHadScrollBar = this.scrollBarWidth > 0;
|
||||||
|
|
||||||
this._viewportElement.style.width = (this._renderService.dimensions.actualCellWidth * (this._bufferService.cols) + this.scrollBarWidth).toString() + 'px';
|
const elementStyle = window.getComputedStyle(this._element);
|
||||||
|
const elementPadding = parseInt(elementStyle.paddingLeft) + parseInt(elementStyle.paddingRight);
|
||||||
|
this._viewportElement.style.width = (this._renderService.dimensions.actualCellWidth * (this._bufferService.cols) + this.scrollBarWidth + (this._lastHadScrollBar ? elementPadding : 0)).toString() + 'px';
|
||||||
this._refreshAnimationFrame = null;
|
this._refreshAnimationFrame = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -89,6 +89,9 @@ export class Terminal implements ITerminalApi {
|
|||||||
wraparoundMode: m.wraparound
|
wraparoundMode: m.wraparound
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
public get options(): ITerminalOptions {
|
||||||
|
return this._core.options;
|
||||||
|
}
|
||||||
public blur(): void {
|
public blur(): void {
|
||||||
this._core.blur();
|
this._core.blur();
|
||||||
}
|
}
|
||||||
@@ -222,6 +225,9 @@ export class Terminal implements ITerminalApi {
|
|||||||
public reset(): void {
|
public reset(): void {
|
||||||
this._core.reset();
|
this._core.reset();
|
||||||
}
|
}
|
||||||
|
public clearTextureAtlas(): void {
|
||||||
|
this._core.clearTextureAtlas();
|
||||||
|
}
|
||||||
public loadAddon(addon: ITerminalAddon): void {
|
public loadAddon(addon: ITerminalAddon): void {
|
||||||
return this._addonManager.loadAddon(this, addon);
|
return this._addonManager.loadAddon(this, addon);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { IRenderDimensions, IRenderLayer } from 'browser/renderer/Types';
|
|||||||
import { ICellData } from 'common/Types';
|
import { ICellData } from 'common/Types';
|
||||||
import { DEFAULT_COLOR, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_CODE, Attributes } from 'common/buffer/Constants';
|
import { DEFAULT_COLOR, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_CODE, Attributes } from 'common/buffer/Constants';
|
||||||
import { IGlyphIdentifier } from 'browser/renderer/atlas/Types';
|
import { IGlyphIdentifier } from 'browser/renderer/atlas/Types';
|
||||||
import { DIM_OPACITY, INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
|
import { DIM_OPACITY, INVERTED_DEFAULT_COLOR, TEXT_BASELINE } from 'browser/renderer/atlas/Constants';
|
||||||
import { BaseCharAtlas } from 'browser/renderer/atlas/BaseCharAtlas';
|
import { BaseCharAtlas } from 'browser/renderer/atlas/BaseCharAtlas';
|
||||||
import { acquireCharAtlas } from 'browser/renderer/atlas/CharAtlasCache';
|
import { acquireCharAtlas } from 'browser/renderer/atlas/CharAtlasCache';
|
||||||
import { AttributeData } from 'common/buffer/AttributeData';
|
import { AttributeData } from 'common/buffer/AttributeData';
|
||||||
@@ -138,6 +138,10 @@ export abstract class BaseRenderLayer implements IRenderLayer {
|
|||||||
|
|
||||||
public abstract reset(): void;
|
public abstract reset(): void;
|
||||||
|
|
||||||
|
public clearTextureAtlas(): void {
|
||||||
|
this._charAtlas?.clear();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fills 1+ cells completely. This uses the existing fillStyle on the context.
|
* Fills 1+ cells completely. This uses the existing fillStyle on the context.
|
||||||
* @param x The column to start at.
|
* @param x The column to start at.
|
||||||
@@ -258,7 +262,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
|
|||||||
*/
|
*/
|
||||||
protected _fillCharTrueColor(cell: CellData, x: number, y: number): void {
|
protected _fillCharTrueColor(cell: CellData, x: number, y: number): void {
|
||||||
this._ctx.font = this._getFont(false, false);
|
this._ctx.font = this._getFont(false, false);
|
||||||
this._ctx.textBaseline = 'ideographic';
|
this._ctx.textBaseline = TEXT_BASELINE;
|
||||||
this._clipRow(y);
|
this._clipRow(y);
|
||||||
|
|
||||||
// Draw custom characters if applicable
|
// Draw custom characters if applicable
|
||||||
@@ -346,7 +350,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
|
|||||||
private _drawUncachedChars(cell: ICellData, x: number, y: number, fgOverride?: IColor): void {
|
private _drawUncachedChars(cell: ICellData, x: number, y: number, fgOverride?: IColor): void {
|
||||||
this._ctx.save();
|
this._ctx.save();
|
||||||
this._ctx.font = this._getFont(!!cell.isBold(), !!cell.isItalic());
|
this._ctx.font = this._getFont(!!cell.isBold(), !!cell.isItalic());
|
||||||
this._ctx.textBaseline = 'ideographic';
|
this._ctx.textBaseline = TEXT_BASELINE;
|
||||||
|
|
||||||
if (cell.isInverse()) {
|
if (cell.isInverse()) {
|
||||||
if (fgOverride) {
|
if (fgOverride) {
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ export class CursorRenderLayer extends BaseRenderLayer {
|
|||||||
'block': this._renderBlockCursor.bind(this),
|
'block': this._renderBlockCursor.bind(this),
|
||||||
'underline': this._renderUnderlineCursor.bind(this)
|
'underline': this._renderUnderlineCursor.bind(this)
|
||||||
};
|
};
|
||||||
// TODO: Consider initial options? Maybe onOptionsChanged should be called at the end of open?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose(): void {
|
public dispose(): void {
|
||||||
@@ -80,26 +79,18 @@ export class CursorRenderLayer extends BaseRenderLayer {
|
|||||||
|
|
||||||
public reset(): void {
|
public reset(): void {
|
||||||
this._clearCursor();
|
this._clearCursor();
|
||||||
if (this._cursorBlinkStateManager) {
|
this._cursorBlinkStateManager?.restartBlinkAnimation();
|
||||||
this._cursorBlinkStateManager.dispose();
|
this.onOptionsChanged();
|
||||||
this._cursorBlinkStateManager = undefined;
|
|
||||||
this.onOptionsChanged();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public onBlur(): void {
|
public onBlur(): void {
|
||||||
if (this._cursorBlinkStateManager) {
|
this._cursorBlinkStateManager?.pause();
|
||||||
this._cursorBlinkStateManager.pause();
|
|
||||||
}
|
|
||||||
this._onRequestRedraw.fire({ start: this._bufferService.buffer.y, end: this._bufferService.buffer.y });
|
this._onRequestRedraw.fire({ start: this._bufferService.buffer.y, end: this._bufferService.buffer.y });
|
||||||
}
|
}
|
||||||
|
|
||||||
public onFocus(): void {
|
public onFocus(): void {
|
||||||
if (this._cursorBlinkStateManager) {
|
this._cursorBlinkStateManager?.resume();
|
||||||
this._cursorBlinkStateManager.resume();
|
this._onRequestRedraw.fire({ start: this._bufferService.buffer.y, end: this._bufferService.buffer.y });
|
||||||
} else {
|
|
||||||
this._onRequestRedraw.fire({ start: this._bufferService.buffer.y, end: this._bufferService.buffer.y });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public onOptionsChanged(): void {
|
public onOptionsChanged(): void {
|
||||||
@@ -119,9 +110,7 @@ export class CursorRenderLayer extends BaseRenderLayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onCursorMove(): void {
|
public onCursorMove(): void {
|
||||||
if (this._cursorBlinkStateManager) {
|
this._cursorBlinkStateManager?.restartBlinkAnimation();
|
||||||
this._cursorBlinkStateManager.restartBlinkAnimation();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public onGridChanged(startRow: number, endRow: number): void {
|
public onGridChanged(startRow: number, endRow: number): void {
|
||||||
@@ -313,6 +302,7 @@ class CursorBlinkStateManager {
|
|||||||
// Clear any existing interval
|
// Clear any existing interval
|
||||||
if (this._blinkInterval) {
|
if (this._blinkInterval) {
|
||||||
window.clearInterval(this._blinkInterval);
|
window.clearInterval(this._blinkInterval);
|
||||||
|
this._blinkInterval = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup the initial timeout which will hide the cursor, this is done before
|
// Setup the initial timeout which will hide the cursor, this is done before
|
||||||
|
|||||||
@@ -149,6 +149,12 @@ export class Renderer extends Disposable implements IRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clearTextureAtlas(): void {
|
||||||
|
for (const layer of this._renderLayers) {
|
||||||
|
layer.clearTextureAtlas();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recalculates the character and canvas dimensions.
|
* Recalculates the character and canvas dimensions.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Vendored
+6
@@ -52,6 +52,7 @@ export interface IRenderer extends IDisposable {
|
|||||||
onOptionsChanged(): void;
|
onOptionsChanged(): void;
|
||||||
clear(): void;
|
clear(): void;
|
||||||
renderRows(start: number, end: number): void;
|
renderRows(start: number, end: number): void;
|
||||||
|
clearTextureAtlas?(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IRenderLayer extends IDisposable {
|
export interface IRenderLayer extends IDisposable {
|
||||||
@@ -100,4 +101,9 @@ export interface IRenderLayer extends IDisposable {
|
|||||||
* Clear the state of the render layer.
|
* Clear the state of the render layer.
|
||||||
*/
|
*/
|
||||||
reset(): void;
|
reset(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the texture atlas.
|
||||||
|
*/
|
||||||
|
clearTextureAtlas(): void;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ export abstract class BaseCharAtlas implements IDisposable {
|
|||||||
*/
|
*/
|
||||||
private _doWarmUp(): void { }
|
private _doWarmUp(): void { }
|
||||||
|
|
||||||
|
public clear(): void { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when we start drawing a new frame.
|
* Called when we start drawing a new frame.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -3,7 +3,13 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { isFirefox } from 'common/Platform';
|
||||||
|
|
||||||
export const INVERTED_DEFAULT_COLOR = 257;
|
export const INVERTED_DEFAULT_COLOR = 257;
|
||||||
export const DIM_OPACITY = 0.5;
|
export const DIM_OPACITY = 0.5;
|
||||||
|
// The text baseline is set conditionally by browser. Using 'ideographic' for Firefox would
|
||||||
|
// result in truncated text (Issue 3353). Using 'bottom' for Chrome would result in slightly
|
||||||
|
// unaligned Powerline fonts (PR 3356#issuecomment-850928179).
|
||||||
|
export const TEXT_BASELINE: CanvasTextBaseline = isFirefox ? 'bottom' : 'ideographic';
|
||||||
|
|
||||||
export const CHAR_ATLAS_CELL_SPACING = 1;
|
export const CHAR_ATLAS_CELL_SPACING = 1;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { DIM_OPACITY, INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
|
import { DIM_OPACITY, INVERTED_DEFAULT_COLOR, TEXT_BASELINE } from 'browser/renderer/atlas/Constants';
|
||||||
import { IGlyphIdentifier, ICharAtlasConfig } from 'browser/renderer/atlas/Types';
|
import { IGlyphIdentifier, ICharAtlasConfig } from 'browser/renderer/atlas/Types';
|
||||||
import { BaseCharAtlas } from 'browser/renderer/atlas/BaseCharAtlas';
|
import { BaseCharAtlas } from 'browser/renderer/atlas/BaseCharAtlas';
|
||||||
import { DEFAULT_ANSI_COLORS } from 'browser/ColorManager';
|
import { DEFAULT_ANSI_COLORS } from 'browser/ColorManager';
|
||||||
@@ -119,6 +119,16 @@ export class DynamicCharAtlas extends BaseCharAtlas {
|
|||||||
this._drawToCacheCount = 0;
|
this._drawToCacheCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clear(): void {
|
||||||
|
if (this._cacheMap.size > 0) {
|
||||||
|
const capacity = this._width * this._height;
|
||||||
|
this._cacheMap = new LRUMap(capacity);
|
||||||
|
this._cacheMap.prealloc(capacity);
|
||||||
|
}
|
||||||
|
this._cacheCtx.clearRect(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
|
||||||
|
this._tmpCtx.clearRect(0, 0, this._config.scaledCharWidth, this._config.scaledCharHeight);
|
||||||
|
}
|
||||||
|
|
||||||
public draw(
|
public draw(
|
||||||
ctx: CanvasRenderingContext2D,
|
ctx: CanvasRenderingContext2D,
|
||||||
glyph: IGlyphIdentifier,
|
glyph: IGlyphIdentifier,
|
||||||
@@ -256,7 +266,7 @@ export class DynamicCharAtlas extends BaseCharAtlas {
|
|||||||
const fontStyle = glyph.italic ? 'italic' : '';
|
const fontStyle = glyph.italic ? 'italic' : '';
|
||||||
this._tmpCtx.font =
|
this._tmpCtx.font =
|
||||||
`${fontStyle} ${fontWeight} ${this._config.fontSize * this._config.devicePixelRatio}px ${this._config.fontFamily}`;
|
`${fontStyle} ${fontWeight} ${this._config.fontSize * this._config.devicePixelRatio}px ${this._config.fontFamily}`;
|
||||||
this._tmpCtx.textBaseline = 'ideographic';
|
this._tmpCtx.textBaseline = TEXT_BASELINE;
|
||||||
|
|
||||||
this._tmpCtx.fillStyle = this._getForegroundColor(glyph).css;
|
this._tmpCtx.fillStyle = this._getForegroundColor(glyph).css;
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, DEFAULT_ATTR, FgFlags,
|
|||||||
import { BufferLine, DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
|
import { BufferLine, DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
|
||||||
import { IBufferLine } from 'common/Types';
|
import { IBufferLine } from 'common/Types';
|
||||||
import { CellData } from 'common/buffer/CellData';
|
import { CellData } from 'common/buffer/CellData';
|
||||||
import { MockOptionsService } from 'common/TestUtils.test';
|
import { MockCoreService, MockOptionsService } from 'common/TestUtils.test';
|
||||||
import { css } from 'browser/Color';
|
import { css } from 'browser/Color';
|
||||||
import { MockCharacterJoinerService } from 'browser/TestUtils.test';
|
import { MockCharacterJoinerService } from 'browser/TestUtils.test';
|
||||||
|
|
||||||
@@ -21,30 +21,36 @@ describe('DomRendererRowFactory', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
dom = new jsdom.JSDOM('');
|
dom = new jsdom.JSDOM('');
|
||||||
rowFactory = new DomRendererRowFactory(dom.window.document, {
|
rowFactory = new DomRendererRowFactory(
|
||||||
background: css.toColor('#010101'),
|
dom.window.document,
|
||||||
foreground: css.toColor('#020202'),
|
{
|
||||||
ansi: [
|
background: css.toColor('#010101'),
|
||||||
// dark:
|
foreground: css.toColor('#020202'),
|
||||||
css.toColor('#2e3436'),
|
ansi: [
|
||||||
css.toColor('#cc0000'),
|
// dark:
|
||||||
css.toColor('#4e9a06'),
|
css.toColor('#2e3436'),
|
||||||
css.toColor('#c4a000'),
|
css.toColor('#cc0000'),
|
||||||
css.toColor('#3465a4'),
|
css.toColor('#4e9a06'),
|
||||||
css.toColor('#75507b'),
|
css.toColor('#c4a000'),
|
||||||
css.toColor('#06989a'),
|
css.toColor('#3465a4'),
|
||||||
css.toColor('#d3d7cf'),
|
css.toColor('#75507b'),
|
||||||
// bright:
|
css.toColor('#06989a'),
|
||||||
css.toColor('#555753'),
|
css.toColor('#d3d7cf'),
|
||||||
css.toColor('#ef2929'),
|
// bright:
|
||||||
css.toColor('#8ae234'),
|
css.toColor('#555753'),
|
||||||
css.toColor('#fce94f'),
|
css.toColor('#ef2929'),
|
||||||
css.toColor('#729fcf'),
|
css.toColor('#8ae234'),
|
||||||
css.toColor('#ad7fa8'),
|
css.toColor('#fce94f'),
|
||||||
css.toColor('#34e2e2'),
|
css.toColor('#729fcf'),
|
||||||
css.toColor('#eeeeec')
|
css.toColor('#ad7fa8'),
|
||||||
]
|
css.toColor('#34e2e2'),
|
||||||
} as any, new MockCharacterJoinerService(), new MockOptionsService({ drawBoldTextInBrightColors: true }));
|
css.toColor('#eeeeec')
|
||||||
|
]
|
||||||
|
} as any,
|
||||||
|
new MockCharacterJoinerService(),
|
||||||
|
new MockOptionsService({ drawBoldTextInBrightColors: true }),
|
||||||
|
new MockCoreService()
|
||||||
|
);
|
||||||
lineData = createEmptyLineData(2);
|
lineData = createEmptyLineData(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { IBufferLine } from 'common/Types';
|
|||||||
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
|
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
|
||||||
import { NULL_CELL_CODE, WHITESPACE_CELL_CHAR, Attributes } from 'common/buffer/Constants';
|
import { NULL_CELL_CODE, WHITESPACE_CELL_CHAR, Attributes } from 'common/buffer/Constants';
|
||||||
import { CellData } from 'common/buffer/CellData';
|
import { CellData } from 'common/buffer/CellData';
|
||||||
import { IOptionsService } from 'common/services/Services';
|
import { ICoreService, IOptionsService } from 'common/services/Services';
|
||||||
import { color, rgba } from 'browser/Color';
|
import { color, rgba } from 'browser/Color';
|
||||||
import { IColorSet, IColor } from 'browser/Types';
|
import { IColorSet, IColor } from 'browser/Types';
|
||||||
import { ICharacterJoinerService } from 'browser/services/Services';
|
import { ICharacterJoinerService } from 'browser/services/Services';
|
||||||
@@ -31,7 +31,8 @@ export class DomRendererRowFactory {
|
|||||||
private readonly _document: Document,
|
private readonly _document: Document,
|
||||||
private _colors: IColorSet,
|
private _colors: IColorSet,
|
||||||
@ICharacterJoinerService private readonly _characterJoinerService: ICharacterJoinerService,
|
@ICharacterJoinerService private readonly _characterJoinerService: ICharacterJoinerService,
|
||||||
@IOptionsService private readonly _optionsService: IOptionsService
|
@IOptionsService private readonly _optionsService: IOptionsService,
|
||||||
|
@ICoreService private readonly _coreService: ICoreService
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +111,7 @@ export class DomRendererRowFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCursorRow && x === cursorX) {
|
if (!this._coreService.isCursorHidden && isCursorRow && x === cursorX) {
|
||||||
charElement.classList.add(CURSOR_CLASS);
|
charElement.classList.add(CURSOR_CLASS);
|
||||||
|
|
||||||
if (cursorBlink) {
|
if (cursorBlink) {
|
||||||
|
|||||||
@@ -168,6 +168,11 @@ export class RenderService extends Disposable implements IRenderService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clearTextureAtlas(): void {
|
||||||
|
this._renderer?.clearTextureAtlas?.();
|
||||||
|
this._fullRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
public setColors(colors: IColorSet): void {
|
public setColors(colors: IColorSet): void {
|
||||||
this._renderer.setColors(colors);
|
this._renderer.setColors(colors);
|
||||||
this._fullRefresh();
|
this._fullRefresh();
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ export interface IRenderService extends IDisposable {
|
|||||||
dimensions: IRenderDimensions;
|
dimensions: IRenderDimensions;
|
||||||
|
|
||||||
refreshRows(start: number, end: number): void;
|
refreshRows(start: number, end: number): void;
|
||||||
|
clearTextureAtlas(): void;
|
||||||
resize(cols: number, rows: number): void;
|
resize(cols: number, rows: number): void;
|
||||||
changeOptions(): void;
|
changeOptions(): void;
|
||||||
setRenderer(renderer: IRenderer): void;
|
setRenderer(renderer: IRenderer): void;
|
||||||
|
|||||||
@@ -86,9 +86,10 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
|
|||||||
public get cols(): number { return this._bufferService.cols; }
|
public get cols(): number { return this._bufferService.cols; }
|
||||||
public get rows(): number { return this._bufferService.rows; }
|
public get rows(): number { return this._bufferService.rows; }
|
||||||
public get buffers(): IBufferSet { return this._bufferService.buffers; }
|
public get buffers(): IBufferSet { return this._bufferService.buffers; }
|
||||||
|
public get options(): ITerminalOptions { return this.optionsService.publicOptions; }
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
options: ITerminalOptions
|
options: Partial<ITerminalOptions>
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
|||||||
@@ -77,54 +77,54 @@ describe('InputHandler', () => {
|
|||||||
optionsService.options.scrollback = 1;
|
optionsService.options.scrollback = 1;
|
||||||
bufferService.reset();
|
bufferService.reset();
|
||||||
});
|
});
|
||||||
it('SL (scrollLeft)', () => {
|
it('SL (scrollLeft)', async () => {
|
||||||
inputHandler.parseP('12345'.repeat(6));
|
await inputHandler.parseP('12345'.repeat(6));
|
||||||
inputHandler.parseP('\x1b[ @');
|
await inputHandler.parseP('\x1b[ @');
|
||||||
assert.deepEqual(getLines(bufferService, 6), ['12345', '2345', '2345', '2345', '2345', '2345']);
|
assert.deepEqual(getLines(bufferService, 6), ['12345', '2345', '2345', '2345', '2345', '2345']);
|
||||||
inputHandler.parseP('\x1b[0 @');
|
await inputHandler.parseP('\x1b[0 @');
|
||||||
assert.deepEqual(getLines(bufferService, 6), ['12345', '345', '345', '345', '345', '345']);
|
assert.deepEqual(getLines(bufferService, 6), ['12345', '345', '345', '345', '345', '345']);
|
||||||
inputHandler.parseP('\x1b[2 @');
|
await inputHandler.parseP('\x1b[2 @');
|
||||||
assert.deepEqual(getLines(bufferService, 6), ['12345', '5', '5', '5', '5', '5']);
|
assert.deepEqual(getLines(bufferService, 6), ['12345', '5', '5', '5', '5', '5']);
|
||||||
});
|
});
|
||||||
it('SR (scrollRight)', () => {
|
it('SR (scrollRight)', async () => {
|
||||||
inputHandler.parseP('12345'.repeat(6));
|
await inputHandler.parseP('12345'.repeat(6));
|
||||||
inputHandler.parseP('\x1b[ A');
|
await inputHandler.parseP('\x1b[ A');
|
||||||
assert.deepEqual(getLines(bufferService, 6), ['12345', ' 1234', ' 1234', ' 1234', ' 1234', ' 1234']);
|
assert.deepEqual(getLines(bufferService, 6), ['12345', ' 1234', ' 1234', ' 1234', ' 1234', ' 1234']);
|
||||||
inputHandler.parseP('\x1b[0 A');
|
await inputHandler.parseP('\x1b[0 A');
|
||||||
assert.deepEqual(getLines(bufferService, 6), ['12345', ' 123', ' 123', ' 123', ' 123', ' 123']);
|
assert.deepEqual(getLines(bufferService, 6), ['12345', ' 123', ' 123', ' 123', ' 123', ' 123']);
|
||||||
inputHandler.parseP('\x1b[2 A');
|
await inputHandler.parseP('\x1b[2 A');
|
||||||
assert.deepEqual(getLines(bufferService, 6), ['12345', ' 1', ' 1', ' 1', ' 1', ' 1']);
|
assert.deepEqual(getLines(bufferService, 6), ['12345', ' 1', ' 1', ' 1', ' 1', ' 1']);
|
||||||
});
|
});
|
||||||
it('insertColumns (DECIC)', () => {
|
it('insertColumns (DECIC)', async () => {
|
||||||
inputHandler.parseP('12345'.repeat(6));
|
await inputHandler.parseP('12345'.repeat(6));
|
||||||
inputHandler.parseP('\x1b[3;3H');
|
await inputHandler.parseP('\x1b[3;3H');
|
||||||
inputHandler.parseP('\x1b[\'}');
|
await inputHandler.parseP('\x1b[\'}');
|
||||||
assert.deepEqual(getLines(bufferService, 6), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']);
|
assert.deepEqual(getLines(bufferService, 6), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']);
|
||||||
bufferService.reset();
|
bufferService.reset();
|
||||||
inputHandler.parseP('12345'.repeat(6));
|
await inputHandler.parseP('12345'.repeat(6));
|
||||||
inputHandler.parseP('\x1b[3;3H');
|
await inputHandler.parseP('\x1b[3;3H');
|
||||||
inputHandler.parseP('\x1b[1\'}');
|
await inputHandler.parseP('\x1b[1\'}');
|
||||||
assert.deepEqual(getLines(bufferService, 6), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']);
|
assert.deepEqual(getLines(bufferService, 6), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']);
|
||||||
bufferService.reset();
|
bufferService.reset();
|
||||||
inputHandler.parseP('12345'.repeat(6));
|
await inputHandler.parseP('12345'.repeat(6));
|
||||||
inputHandler.parseP('\x1b[3;3H');
|
await inputHandler.parseP('\x1b[3;3H');
|
||||||
inputHandler.parseP('\x1b[2\'}');
|
await inputHandler.parseP('\x1b[2\'}');
|
||||||
assert.deepEqual(getLines(bufferService, 6), ['12345', '12 3', '12 3', '12 3', '12 3', '12 3']);
|
assert.deepEqual(getLines(bufferService, 6), ['12345', '12 3', '12 3', '12 3', '12 3', '12 3']);
|
||||||
});
|
});
|
||||||
it('deleteColumns (DECDC)', () => {
|
it('deleteColumns (DECDC)', async () => {
|
||||||
inputHandler.parseP('12345'.repeat(6));
|
await inputHandler.parseP('12345'.repeat(6));
|
||||||
inputHandler.parseP('\x1b[3;3H');
|
await inputHandler.parseP('\x1b[3;3H');
|
||||||
inputHandler.parseP('\x1b[\'~');
|
await inputHandler.parseP('\x1b[\'~');
|
||||||
assert.deepEqual(getLines(bufferService, 6), ['12345', '1245', '1245', '1245', '1245', '1245']);
|
assert.deepEqual(getLines(bufferService, 6), ['12345', '1245', '1245', '1245', '1245', '1245']);
|
||||||
bufferService.reset();
|
bufferService.reset();
|
||||||
inputHandler.parseP('12345'.repeat(6));
|
await inputHandler.parseP('12345'.repeat(6));
|
||||||
inputHandler.parseP('\x1b[3;3H');
|
await inputHandler.parseP('\x1b[3;3H');
|
||||||
inputHandler.parseP('\x1b[1\'~');
|
await inputHandler.parseP('\x1b[1\'~');
|
||||||
assert.deepEqual(getLines(bufferService, 6), ['12345', '1245', '1245', '1245', '1245', '1245']);
|
assert.deepEqual(getLines(bufferService, 6), ['12345', '1245', '1245', '1245', '1245', '1245']);
|
||||||
bufferService.reset();
|
bufferService.reset();
|
||||||
inputHandler.parseP('12345'.repeat(6));
|
await inputHandler.parseP('12345'.repeat(6));
|
||||||
inputHandler.parseP('\x1b[3;3H');
|
await inputHandler.parseP('\x1b[3;3H');
|
||||||
inputHandler.parseP('\x1b[2\'~');
|
await inputHandler.parseP('\x1b[2\'~');
|
||||||
assert.deepEqual(getLines(bufferService, 6), ['12345', '125', '125', '125', '125', '125']);
|
assert.deepEqual(getLines(bufferService, 6), ['12345', '125', '125', '125', '125', '125']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -137,41 +137,41 @@ describe('InputHandler', () => {
|
|||||||
bufferService.reset();
|
bufferService.reset();
|
||||||
});
|
});
|
||||||
describe('reverseWraparound set', () => {
|
describe('reverseWraparound set', () => {
|
||||||
it('should not reverse outside of scroll margins', () => {
|
it('should not reverse outside of scroll margins', async () => {
|
||||||
// prepare buffer content
|
// prepare buffer content
|
||||||
inputHandler.parseP('#####abcdefghijklmnopqrstuvwxy');
|
await inputHandler.parseP('#####abcdefghijklmnopqrstuvwxy');
|
||||||
assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', 'uvwxy']);
|
assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', 'uvwxy']);
|
||||||
assert.equal(bufferService.buffers.active.ydisp, 1);
|
assert.equal(bufferService.buffers.active.ydisp, 1);
|
||||||
assert.equal(bufferService.buffers.active.x, 5);
|
assert.equal(bufferService.buffers.active.x, 5);
|
||||||
assert.equal(bufferService.buffers.active.y, 4);
|
assert.equal(bufferService.buffers.active.y, 4);
|
||||||
inputHandler.parseP(ttyBS.repeat(100));
|
await inputHandler.parseP(ttyBS.repeat(100));
|
||||||
assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' y']);
|
assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' y']);
|
||||||
|
|
||||||
inputHandler.parseP('\x1b[?45h');
|
await inputHandler.parseP('\x1b[?45h');
|
||||||
inputHandler.parseP('uvwxy');
|
await inputHandler.parseP('uvwxy');
|
||||||
|
|
||||||
// set top/bottom to 1/3 (0-based)
|
// set top/bottom to 1/3 (0-based)
|
||||||
inputHandler.parseP('\x1b[2;4r');
|
await inputHandler.parseP('\x1b[2;4r');
|
||||||
// place cursor below scroll bottom
|
// place cursor below scroll bottom
|
||||||
bufferService.buffers.active.x = 5;
|
bufferService.buffers.active.x = 5;
|
||||||
bufferService.buffers.active.y = 4;
|
bufferService.buffers.active.y = 4;
|
||||||
inputHandler.parseP(ttyBS.repeat(100));
|
await inputHandler.parseP(ttyBS.repeat(100));
|
||||||
assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' ']);
|
assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' ']);
|
||||||
|
|
||||||
inputHandler.parseP('uvwxy');
|
await inputHandler.parseP('uvwxy');
|
||||||
// place cursor within scroll margins
|
// place cursor within scroll margins
|
||||||
bufferService.buffers.active.x = 5;
|
bufferService.buffers.active.x = 5;
|
||||||
bufferService.buffers.active.y = 3;
|
bufferService.buffers.active.y = 3;
|
||||||
inputHandler.parseP(ttyBS.repeat(100));
|
await inputHandler.parseP(ttyBS.repeat(100));
|
||||||
assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', ' ', ' ', ' ', 'uvwxy']);
|
assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', ' ', ' ', ' ', 'uvwxy']);
|
||||||
assert.equal(bufferService.buffers.active.x, 0);
|
assert.equal(bufferService.buffers.active.x, 0);
|
||||||
assert.equal(bufferService.buffers.active.y, bufferService.buffers.active.scrollTop); // stops at 0, scrollTop
|
assert.equal(bufferService.buffers.active.y, bufferService.buffers.active.scrollTop); // stops at 0, scrollTop
|
||||||
|
|
||||||
inputHandler.parseP('fghijklmnopqrst');
|
await inputHandler.parseP('fghijklmnopqrst');
|
||||||
// place cursor above scroll top
|
// place cursor above scroll top
|
||||||
bufferService.buffers.active.x = 5;
|
bufferService.buffers.active.x = 5;
|
||||||
bufferService.buffers.active.y = 0;
|
bufferService.buffers.active.y = 0;
|
||||||
inputHandler.parseP(ttyBS.repeat(100));
|
await inputHandler.parseP(ttyBS.repeat(100));
|
||||||
assert.deepEqual(getLines(bufferService, 6), ['#####', ' ', 'fghij', 'klmno', 'pqrst', 'uvwxy']);
|
assert.deepEqual(getLines(bufferService, 6), ['#####', ' ', 'fghij', 'klmno', 'pqrst', 'uvwxy']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -243,6 +243,8 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|||||||
public get onRequestRefreshRows(): IEvent<number, number> { return this._onRequestRefreshRows.event; }
|
public get onRequestRefreshRows(): IEvent<number, number> { return this._onRequestRefreshRows.event; }
|
||||||
private _onRequestReset = new EventEmitter<void>();
|
private _onRequestReset = new EventEmitter<void>();
|
||||||
public get onRequestReset(): IEvent<void> { return this._onRequestReset.event; }
|
public get onRequestReset(): IEvent<void> { return this._onRequestReset.event; }
|
||||||
|
private _onRequestSendFocus = new EventEmitter<void>();
|
||||||
|
public get onRequestSendFocus(): IEvent<void> { return this._onRequestSendFocus.event; }
|
||||||
private _onRequestSyncScrollBar = new EventEmitter<void>();
|
private _onRequestSyncScrollBar = new EventEmitter<void>();
|
||||||
public get onRequestSyncScrollBar(): IEvent<void> { return this._onRequestSyncScrollBar.event; }
|
public get onRequestSyncScrollBar(): IEvent<void> { return this._onRequestSyncScrollBar.event; }
|
||||||
private _onRequestWindowsOptionsReport = new EventEmitter<WindowsOptionsReportType>();
|
private _onRequestWindowsOptionsReport = new EventEmitter<WindowsOptionsReportType>();
|
||||||
@@ -1956,6 +1958,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|||||||
// focusin: ^[[I
|
// focusin: ^[[I
|
||||||
// focusout: ^[[O
|
// focusout: ^[[O
|
||||||
this._coreService.decPrivateModes.sendFocus = true;
|
this._coreService.decPrivateModes.sendFocus = true;
|
||||||
|
this._onRequestSendFocus.fire();
|
||||||
break;
|
break;
|
||||||
case 1005: // utf8 ext mode mouse - removed in #2507
|
case 1005: // utf8 ext mode mouse - removed in #2507
|
||||||
this._logService.debug('DECSET 1005 not supported (see #2507)');
|
this._logService.debug('DECSET 1005 not supported (see #2507)');
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { IBufferService, ICoreService, ILogService, IOptionsService, ITerminalOptions, IPartialTerminalOptions, IDirtyRowService, ICoreMouseService, ICharsetService, IUnicodeService, IUnicodeVersionProvider, LogLevelEnum } from 'common/services/Services';
|
import { IBufferService, ICoreService, ILogService, IOptionsService, ITerminalOptions, IDirtyRowService, ICoreMouseService, ICharsetService, IUnicodeService, IUnicodeVersionProvider, LogLevelEnum } from 'common/services/Services';
|
||||||
import { IEvent, EventEmitter } from 'common/EventEmitter';
|
import { IEvent, EventEmitter } from 'common/EventEmitter';
|
||||||
import { clone } from 'common/Clone';
|
import { clone } from 'common/Clone';
|
||||||
import { DEFAULT_OPTIONS } from 'common/services/OptionsService';
|
import { DEFAULT_OPTIONS } from 'common/services/OptionsService';
|
||||||
@@ -121,11 +121,13 @@ export class MockLogService implements ILogService {
|
|||||||
export class MockOptionsService implements IOptionsService {
|
export class MockOptionsService implements IOptionsService {
|
||||||
public serviceBrand: any;
|
public serviceBrand: any;
|
||||||
public options: ITerminalOptions = clone(DEFAULT_OPTIONS);
|
public options: ITerminalOptions = clone(DEFAULT_OPTIONS);
|
||||||
|
public publicOptions: ITerminalOptions = clone(DEFAULT_OPTIONS);
|
||||||
public onOptionChange: IEvent<string> = new EventEmitter<string>().event;
|
public onOptionChange: IEvent<string> = new EventEmitter<string>().event;
|
||||||
constructor(testOptions?: IPartialTerminalOptions) {
|
constructor(testOptions?: Partial<ITerminalOptions>) {
|
||||||
if (testOptions) {
|
if (testOptions) {
|
||||||
for (const key of Object.keys(testOptions)) {
|
for (const key of Object.keys(testOptions)) {
|
||||||
this.options[key] = (testOptions as any)[key];
|
this.options[key] = testOptions[key];
|
||||||
|
this.publicOptions[key] = testOptions[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
@@ -16,6 +16,7 @@ export interface ICoreTerminal {
|
|||||||
optionsService: IOptionsService;
|
optionsService: IOptionsService;
|
||||||
unicodeService: IUnicodeService;
|
unicodeService: IUnicodeService;
|
||||||
buffers: IBufferSet;
|
buffers: IBufferSet;
|
||||||
|
options: ITerminalOptions;
|
||||||
registerCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean | Promise<boolean>): IDisposable;
|
registerCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean | Promise<boolean>): IDisposable;
|
||||||
registerDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean | Promise<boolean>): IDisposable;
|
registerDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean | Promise<boolean>): IDisposable;
|
||||||
registerEscHandler(id: IFunctionIdentifier, callback: () => boolean | Promise<boolean>): IDisposable;
|
registerEscHandler(id: IFunctionIdentifier, callback: () => boolean | Promise<boolean>): IDisposable;
|
||||||
|
|||||||
@@ -3,10 +3,9 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { IOptionsService, ITerminalOptions, IPartialTerminalOptions, FontWeight } from 'common/services/Services';
|
import { IOptionsService, ITerminalOptions, FontWeight } from 'common/services/Services';
|
||||||
import { EventEmitter, IEvent } from 'common/EventEmitter';
|
import { EventEmitter, IEvent } from 'common/EventEmitter';
|
||||||
import { isMac } from 'common/Platform';
|
import { isMac } from 'common/Platform';
|
||||||
import { clone } from 'common/Clone';
|
|
||||||
|
|
||||||
// Source: https://freesound.org/people/altemark/sounds/45759/
|
// Source: https://freesound.org/people/altemark/sounds/45759/
|
||||||
// This sound is released under the Creative Commons Attribution 3.0 Unported
|
// This sound is released under the Creative Commons Attribution 3.0 Unported
|
||||||
@@ -14,15 +13,14 @@ import { clone } from 'common/Clone';
|
|||||||
// made, apart from the conversion to base64.
|
// made, apart from the conversion to base64.
|
||||||
export const DEFAULT_BELL_SOUND = 'data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4LjMyLjEwNAAAAAAAAAAAAAAA//tQxAADB8AhSmxhIIEVCSiJrDCQBTcu3UrAIwUdkRgQbFAZC1CQEwTJ9mjRvBA4UOLD8nKVOWfh+UlK3z/177OXrfOdKl7pyn3Xf//WreyTRUoAWgBgkOAGbZHBgG1OF6zM82DWbZaUmMBptgQhGjsyYqc9ae9XFz280948NMBWInljyzsNRFLPWdnZGWrddDsjK1unuSrVN9jJsK8KuQtQCtMBjCEtImISdNKJOopIpBFpNSMbIHCSRpRR5iakjTiyzLhchUUBwCgyKiweBv/7UsQbg8isVNoMPMjAAAA0gAAABEVFGmgqK////9bP/6XCykxBTUUzLjEwMKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq';
|
export const DEFAULT_BELL_SOUND = 'data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4LjMyLjEwNAAAAAAAAAAAAAAA//tQxAADB8AhSmxhIIEVCSiJrDCQBTcu3UrAIwUdkRgQbFAZC1CQEwTJ9mjRvBA4UOLD8nKVOWfh+UlK3z/177OXrfOdKl7pyn3Xf//WreyTRUoAWgBgkOAGbZHBgG1OF6zM82DWbZaUmMBptgQhGjsyYqc9ae9XFz280948NMBWInljyzsNRFLPWdnZGWrddDsjK1unuSrVN9jJsK8KuQtQCtMBjCEtImISdNKJOopIpBFpNSMbIHCSRpRR5iakjTiyzLhchUUBwCgyKiweBv/7UsQbg8isVNoMPMjAAAA0gAAABEVFGmgqK////9bP/6XCykxBTUUzLjEwMKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq';
|
||||||
|
|
||||||
// TODO: Freeze?
|
export const DEFAULT_OPTIONS: Readonly<ITerminalOptions> = {
|
||||||
export const DEFAULT_OPTIONS: ITerminalOptions = Object.freeze({
|
|
||||||
cols: 80,
|
cols: 80,
|
||||||
rows: 24,
|
rows: 24,
|
||||||
cursorBlink: false,
|
cursorBlink: false,
|
||||||
cursorStyle: 'block',
|
cursorStyle: 'block',
|
||||||
cursorWidth: 1,
|
cursorWidth: 1,
|
||||||
customGlyphs: true,
|
customGlyphs: true,
|
||||||
bellSound: DEFAULT_BELL_SOUND,
|
bellSound: DEFAULT_BELL_SOUND,
|
||||||
bellStyle: 'none',
|
bellStyle: 'none',
|
||||||
drawBoldTextInBrightColors: true,
|
drawBoldTextInBrightColors: true,
|
||||||
fastScrollModifier: 'alt',
|
fastScrollModifier: 'alt',
|
||||||
@@ -55,7 +53,7 @@ export const DEFAULT_OPTIONS: ITerminalOptions = Object.freeze({
|
|||||||
convertEol: false,
|
convertEol: false,
|
||||||
termName: 'xterm',
|
termName: 'xterm',
|
||||||
cancelEvents: false
|
cancelEvents: false
|
||||||
});
|
};
|
||||||
|
|
||||||
const FONT_WEIGHT_OPTIONS: Extract<FontWeight, string>[] = ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'];
|
const FONT_WEIGHT_OPTIONS: Extract<FontWeight, string>[] = ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'];
|
||||||
|
|
||||||
@@ -67,45 +65,68 @@ const CONSTRUCTOR_ONLY_OPTIONS = ['cols', 'rows'];
|
|||||||
export class OptionsService implements IOptionsService {
|
export class OptionsService implements IOptionsService {
|
||||||
public serviceBrand: any;
|
public serviceBrand: any;
|
||||||
|
|
||||||
|
private _options: ITerminalOptions;
|
||||||
public options: ITerminalOptions;
|
public options: ITerminalOptions;
|
||||||
|
public publicOptions: ITerminalOptions;
|
||||||
|
|
||||||
private _onOptionChange = new EventEmitter<string>();
|
private _onOptionChange = new EventEmitter<string>();
|
||||||
public get onOptionChange(): IEvent<string> { return this._onOptionChange.event; }
|
public get onOptionChange(): IEvent<string> { return this._onOptionChange.event; }
|
||||||
|
|
||||||
constructor(options: IPartialTerminalOptions) {
|
constructor(options: Partial<ITerminalOptions>) {
|
||||||
this.options = clone(DEFAULT_OPTIONS);
|
// set the default value of each option
|
||||||
for (const k of Object.keys(options)) {
|
this._options = { ...DEFAULT_OPTIONS };
|
||||||
if (k in this.options) {
|
for (const key in options) {
|
||||||
|
if (key in this._options) {
|
||||||
try {
|
try {
|
||||||
const newValue = options[k as keyof IPartialTerminalOptions] as any;
|
const newValue = options[key];
|
||||||
this.options[k] = this._sanitizeAndValidateOption(k, newValue);
|
this._options[key] = this._sanitizeAndValidateOption(key, newValue);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set up getters and setters for each option
|
||||||
|
this.options = this._setupOptions(this._options, false);
|
||||||
|
this.publicOptions = this._setupOptions(this._options, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setupOptions(options: ITerminalOptions, isPublic: boolean): ITerminalOptions {
|
||||||
|
const copiedOptions = { ... options };
|
||||||
|
for (const propName in copiedOptions) {
|
||||||
|
Object.defineProperty(copiedOptions, propName, {
|
||||||
|
get: () => {
|
||||||
|
if (!(propName in DEFAULT_OPTIONS)) {
|
||||||
|
throw new Error(`No option with key "${propName}"`);
|
||||||
|
}
|
||||||
|
return this._options[propName];
|
||||||
|
},
|
||||||
|
set: (value: any) => {
|
||||||
|
if (!(propName in DEFAULT_OPTIONS)) {
|
||||||
|
throw new Error(`No option with key "${propName}"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Throw an error if any constructor only option is modified
|
||||||
|
// from terminal.options
|
||||||
|
// Modifications from anywhere else are allowed
|
||||||
|
if (isPublic && CONSTRUCTOR_ONLY_OPTIONS.includes(propName)) {
|
||||||
|
throw new Error(`Option "${propName}" can only be set in the constructor`);
|
||||||
|
}
|
||||||
|
|
||||||
|
value = this._sanitizeAndValidateOption(propName, value);
|
||||||
|
// Don't fire an option change event if they didn't change
|
||||||
|
if (this._options[propName] !== value) {
|
||||||
|
this._options[propName] = value;
|
||||||
|
this._onOptionChange.fire(propName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return copiedOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setOption(key: string, value: any): void {
|
public setOption(key: string, value: any): void {
|
||||||
if (!(key in DEFAULT_OPTIONS)) {
|
this.publicOptions[key] = value;
|
||||||
throw new Error('No option with key "' + key + '"');
|
|
||||||
}
|
|
||||||
if (CONSTRUCTOR_ONLY_OPTIONS.includes(key)) {
|
|
||||||
throw new Error(`Option "${key}" can only be set in the constructor`);
|
|
||||||
}
|
|
||||||
if (this.options[key] === value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = this._sanitizeAndValidateOption(key, value);
|
|
||||||
|
|
||||||
// Don't fire an option change event if they didn't change
|
|
||||||
if (this.options[key] === value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.options[key] = value;
|
|
||||||
this._onOptionChange.fire(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _sanitizeAndValidateOption(key: string, value: any): any {
|
private _sanitizeAndValidateOption(key: string, value: any): any {
|
||||||
@@ -160,9 +181,6 @@ export class OptionsService implements IOptionsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getOption(key: string): any {
|
public getOption(key: string): any {
|
||||||
if (!(key in DEFAULT_OPTIONS)) {
|
return this.publicOptions[key];
|
||||||
throw new Error(`No option with key "${key}"`);
|
|
||||||
}
|
|
||||||
return this.options[key];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ export interface IOptionsService {
|
|||||||
serviceBrand: undefined;
|
serviceBrand: undefined;
|
||||||
|
|
||||||
readonly options: ITerminalOptions;
|
readonly options: ITerminalOptions;
|
||||||
|
readonly publicOptions: ITerminalOptions;
|
||||||
|
|
||||||
readonly onOptionChange: IEvent<string>;
|
readonly onOptionChange: IEvent<string>;
|
||||||
|
|
||||||
@@ -199,41 +200,6 @@ export enum LogLevelEnum {
|
|||||||
}
|
}
|
||||||
export type RendererType = 'dom' | 'canvas';
|
export type RendererType = 'dom' | 'canvas';
|
||||||
|
|
||||||
export interface IPartialTerminalOptions {
|
|
||||||
altClickMovesCursor?: boolean;
|
|
||||||
allowTransparency?: boolean;
|
|
||||||
bellSound?: string;
|
|
||||||
bellStyle?: 'none' | 'sound' /* | 'visual' | 'both' */;
|
|
||||||
cols?: number;
|
|
||||||
cursorBlink?: boolean;
|
|
||||||
cursorStyle?: 'block' | 'underline' | 'bar';
|
|
||||||
cursorWidth?: number;
|
|
||||||
disableStdin?: boolean;
|
|
||||||
drawBoldTextInBrightColors?: boolean;
|
|
||||||
fastScrollModifier?: 'alt' | 'ctrl' | 'shift';
|
|
||||||
fastScrollSensitivity?: number;
|
|
||||||
fontSize?: number;
|
|
||||||
fontFamily?: string;
|
|
||||||
fontWeight?: FontWeight;
|
|
||||||
fontWeightBold?: FontWeight;
|
|
||||||
letterSpacing?: number;
|
|
||||||
lineHeight?: number;
|
|
||||||
logLevel?: LogLevel;
|
|
||||||
macOptionIsMeta?: boolean;
|
|
||||||
macOptionClickForcesSelection?: boolean;
|
|
||||||
rendererType?: RendererType;
|
|
||||||
rightClickSelectsWord?: boolean;
|
|
||||||
rows?: number;
|
|
||||||
screenReaderMode?: boolean;
|
|
||||||
scrollback?: number;
|
|
||||||
scrollSensitivity?: number;
|
|
||||||
tabStopWidth?: number;
|
|
||||||
theme?: ITheme;
|
|
||||||
windowsMode?: boolean;
|
|
||||||
wordSeparator?: string;
|
|
||||||
windowOptions?: IWindowOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ITerminalOptions {
|
export interface ITerminalOptions {
|
||||||
allowProposedApi: boolean;
|
allowProposedApi: boolean;
|
||||||
allowTransparency: boolean;
|
allowTransparency: boolean;
|
||||||
|
|||||||
Vendored
+7
-5
@@ -84,7 +84,7 @@ declare module 'xterm-headless' {
|
|||||||
* line height and letter spacing is used. Note that this doesn't work with the DOM renderer
|
* line height and letter spacing is used. Note that this doesn't work with the DOM renderer
|
||||||
* which renders all characters using the font. The default is true.
|
* which renders all characters using the font. The default is true.
|
||||||
*/
|
*/
|
||||||
customGlyphs?: boolean;
|
customGlyphs?: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether input should be disabled.
|
* Whether input should be disabled.
|
||||||
@@ -1085,18 +1085,20 @@ declare module 'xterm-headless' {
|
|||||||
|
|
||||||
/** Whether the cell has the bold attribute (CSI 1 m). */
|
/** Whether the cell has the bold attribute (CSI 1 m). */
|
||||||
isBold(): number;
|
isBold(): number;
|
||||||
/** Whether the cell has the inverse attribute (CSI 3 m). */
|
/** Whether the cell has the italic attribute (CSI 3 m). */
|
||||||
isItalic(): number;
|
isItalic(): number;
|
||||||
/** Whether the cell has the inverse attribute (CSI 2 m). */
|
/** Whether the cell has the dim attribute (CSI 2 m). */
|
||||||
isDim(): number;
|
isDim(): number;
|
||||||
/** Whether the cell has the underline attribute (CSI 4 m). */
|
/** Whether the cell has the underline attribute (CSI 4 m). */
|
||||||
isUnderline(): number;
|
isUnderline(): number;
|
||||||
/** Whether the cell has the inverse attribute (CSI 5 m). */
|
/** Whether the cell has the blink attribute (CSI 5 m). */
|
||||||
isBlink(): number;
|
isBlink(): number;
|
||||||
/** Whether the cell has the inverse attribute (CSI 7 m). */
|
/** Whether the cell has the inverse attribute (CSI 7 m). */
|
||||||
isInverse(): number;
|
isInverse(): number;
|
||||||
/** Whether the cell has the inverse attribute (CSI 8 m). */
|
/** Whether the cell has the invisible attribute (CSI 8 m). */
|
||||||
isInvisible(): number;
|
isInvisible(): number;
|
||||||
|
/** Whether the cell has the strikethrough attribute (CSI 9 m). */
|
||||||
|
isStrikethrough(): number;
|
||||||
|
|
||||||
/** Whether the cell is using the RGB foreground color mode. */
|
/** Whether the cell is using the RGB foreground color mode. */
|
||||||
isFgRGB(): boolean;
|
isFgRGB(): boolean;
|
||||||
|
|||||||
Vendored
+45
-13
@@ -635,6 +635,11 @@ declare module 'xterm' {
|
|||||||
*/
|
*/
|
||||||
readonly modes: IModes;
|
readonly modes: IModes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the terminal options
|
||||||
|
*/
|
||||||
|
readonly options: ITerminalOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Natural language strings that can be localized.
|
* Natural language strings that can be localized.
|
||||||
*/
|
*/
|
||||||
@@ -964,26 +969,31 @@ 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.
|
||||||
|
* @deprecated Use `options` instead.
|
||||||
*/
|
*/
|
||||||
getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'logLevel' | 'rendererType' | 'termName' | 'wordSeparator'): string;
|
getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'logLevel' | 'rendererType' | 'termName' | 'wordSeparator'): string;
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
|
* @deprecated Use `options` instead.
|
||||||
*/
|
*/
|
||||||
getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'visualBell' | 'windowsMode'): boolean;
|
getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | '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.
|
||||||
|
* @deprecated Use `options` instead.
|
||||||
*/
|
*/
|
||||||
getOption(key: 'cols' | 'fontSize' | 'letterSpacing' | 'lineHeight' | 'rows' | 'tabStopWidth' | 'scrollback'): number;
|
getOption(key: 'cols' | 'fontSize' | 'letterSpacing' | 'lineHeight' | 'rows' | 'tabStopWidth' | 'scrollback'): number;
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
|
* @deprecated Use `options` instead.
|
||||||
*/
|
*/
|
||||||
getOption(key: 'fontWeight' | 'fontWeightBold'): FontWeight;
|
getOption(key: 'fontWeight' | 'fontWeightBold'): FontWeight;
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
|
* @deprecated Use `options` instead.
|
||||||
*/
|
*/
|
||||||
getOption(key: string): any;
|
getOption(key: string): any;
|
||||||
|
|
||||||
@@ -991,60 +1001,70 @@ declare module 'xterm' {
|
|||||||
* Sets an option on the terminal.
|
* Sets an option on the terminal.
|
||||||
* @param key The option key.
|
* @param key The option key.
|
||||||
* @param value The option value.
|
* @param value The option value.
|
||||||
|
* @deprecated Use `options` instead.
|
||||||
*/
|
*/
|
||||||
setOption(key: 'fontFamily' | 'termName' | 'bellSound' | 'wordSeparator', value: string): void;
|
setOption(key: 'fontFamily' | 'termName' | 'bellSound' | 'wordSeparator', value: string): void;
|
||||||
/**
|
/**
|
||||||
* Sets an option on the terminal.
|
* Sets an option on the terminal.
|
||||||
* @param key The option key.
|
* @param key The option key.
|
||||||
* @param value The option value.
|
* @param value The option value.
|
||||||
*/
|
* @deprecated Use `options` instead.
|
||||||
|
*/
|
||||||
setOption(key: 'fontWeight' | 'fontWeightBold', value: null | 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900' | number): void;
|
setOption(key: 'fontWeight' | 'fontWeightBold', value: null | 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900' | number): void;
|
||||||
/**
|
/**
|
||||||
* Sets an option on the terminal.
|
* Sets an option on the terminal.
|
||||||
* @param key The option key.
|
* @param key The option key.
|
||||||
* @param value The option value.
|
* @param value The option value.
|
||||||
*/
|
* @deprecated Use `options` instead.
|
||||||
|
*/
|
||||||
setOption(key: 'logLevel', value: LogLevel): void;
|
setOption(key: 'logLevel', value: LogLevel): void;
|
||||||
/**
|
/**
|
||||||
* Sets an option on the terminal.
|
* Sets an option on the terminal.
|
||||||
* @param key The option key.
|
* @param key The option key.
|
||||||
* @param value The option value.
|
* @param value The option value.
|
||||||
|
* @deprecated Use `options` instead.
|
||||||
*/
|
*/
|
||||||
setOption(key: 'bellStyle', value: null | 'none' | 'visual' | 'sound' | 'both'): void;
|
setOption(key: 'bellStyle', value: null | 'none' | 'visual' | 'sound' | 'both'): void;
|
||||||
/**
|
/**
|
||||||
* Sets an option on the terminal.
|
* Sets an option on the terminal.
|
||||||
* @param key The option key.
|
* @param key The option key.
|
||||||
* @param value The option value.
|
* @param value The option value.
|
||||||
|
* @deprecated Use `options` instead.
|
||||||
*/
|
*/
|
||||||
setOption(key: 'cursorStyle', value: null | 'block' | 'underline' | 'bar'): void;
|
setOption(key: 'cursorStyle', value: null | 'block' | 'underline' | 'bar'): void;
|
||||||
/**
|
/**
|
||||||
* Sets an option on the terminal.
|
* Sets an option on the terminal.
|
||||||
* @param key The option key.
|
* @param key The option key.
|
||||||
* @param value The option value.
|
* @param value The option value.
|
||||||
|
* @deprecated Use `options` instead.
|
||||||
*/
|
*/
|
||||||
setOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'disableStdin' | 'macOptionIsMeta' | 'popOnBell' | 'rightClickSelectsWord' | 'visualBell' | 'windowsMode', value: boolean): void;
|
setOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'disableStdin' | 'macOptionIsMeta' | 'popOnBell' | 'rightClickSelectsWord' | '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.
|
||||||
* @param value The option value.
|
* @param value The option value.
|
||||||
|
* @deprecated Use `options` instead.
|
||||||
*/
|
*/
|
||||||
setOption(key: 'fontSize' | 'letterSpacing' | 'lineHeight' | 'tabStopWidth' | 'scrollback', value: number): void;
|
setOption(key: 'fontSize' | 'letterSpacing' | 'lineHeight' | 'tabStopWidth' | 'scrollback', value: number): void;
|
||||||
/**
|
/**
|
||||||
* Sets an option on the terminal.
|
* Sets an option on the terminal.
|
||||||
* @param key The option key.
|
* @param key The option key.
|
||||||
* @param value The option value.
|
* @param value The option value.
|
||||||
|
* @deprecated Use `options` instead.
|
||||||
*/
|
*/
|
||||||
setOption(key: 'theme', value: ITheme): void;
|
setOption(key: 'theme', value: ITheme): void;
|
||||||
/**
|
/**
|
||||||
* Sets an option on the terminal.
|
* Sets an option on the terminal.
|
||||||
* @param key The option key.
|
* @param key The option key.
|
||||||
* @param value The option value.
|
* @param value The option value.
|
||||||
|
* @deprecated Use `options` instead.
|
||||||
*/
|
*/
|
||||||
setOption(key: 'cols' | 'rows', value: number): void;
|
setOption(key: 'cols' | 'rows', value: number): void;
|
||||||
/**
|
/**
|
||||||
* Sets an option on the terminal.
|
* Sets an option on the terminal.
|
||||||
* @param key The option key.
|
* @param key The option key.
|
||||||
* @param value The option value.
|
* @param value The option value.
|
||||||
|
* @deprecated Use `options` instead.
|
||||||
*/
|
*/
|
||||||
setOption(key: string, value: any): void;
|
setOption(key: string, value: any): void;
|
||||||
|
|
||||||
@@ -1056,6 +1076,14 @@ declare module 'xterm' {
|
|||||||
*/
|
*/
|
||||||
refresh(start: number, end: number): void;
|
refresh(start: number, end: number): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the texture atlas of the canvas renderer if it's active. Doing this will force a
|
||||||
|
* redraw of all glyphs which can workaround issues causing the texture to become corrupt, for
|
||||||
|
* example Chromium/Nvidia has an issue where the texture gets messed up when resuming the OS
|
||||||
|
* from sleep.
|
||||||
|
*/
|
||||||
|
clearTextureAtlas(): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a full reset (RIS, aka '\x1bc').
|
* Perform a full reset (RIS, aka '\x1bc').
|
||||||
*/
|
*/
|
||||||
@@ -1343,7 +1371,9 @@ declare module 'xterm' {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The length of the line, all call to getCell beyond the length will result
|
* The length of the line, all call to getCell beyond the length will result
|
||||||
* in `undefined`.
|
* in `undefined`. Note that this may exceed columns as the line array may
|
||||||
|
* not be trimmed after a resize, compare against {@link Terminal.cols} to
|
||||||
|
* get the actual maximum length of a line.
|
||||||
*/
|
*/
|
||||||
readonly length: number;
|
readonly length: number;
|
||||||
|
|
||||||
@@ -1444,18 +1474,20 @@ declare module 'xterm' {
|
|||||||
|
|
||||||
/** Whether the cell has the bold attribute (CSI 1 m). */
|
/** Whether the cell has the bold attribute (CSI 1 m). */
|
||||||
isBold(): number;
|
isBold(): number;
|
||||||
/** Whether the cell has the inverse attribute (CSI 3 m). */
|
/** Whether the cell has the italic attribute (CSI 3 m). */
|
||||||
isItalic(): number;
|
isItalic(): number;
|
||||||
/** Whether the cell has the inverse attribute (CSI 2 m). */
|
/** Whether the cell has the dim attribute (CSI 2 m). */
|
||||||
isDim(): number;
|
isDim(): number;
|
||||||
/** Whether the cell has the underline attribute (CSI 4 m). */
|
/** Whether the cell has the underline attribute (CSI 4 m). */
|
||||||
isUnderline(): number;
|
isUnderline(): number;
|
||||||
/** Whether the cell has the inverse attribute (CSI 5 m). */
|
/** Whether the cell has the blink attribute (CSI 5 m). */
|
||||||
isBlink(): number;
|
isBlink(): number;
|
||||||
/** Whether the cell has the inverse attribute (CSI 7 m). */
|
/** Whether the cell has the inverse attribute (CSI 7 m). */
|
||||||
isInverse(): number;
|
isInverse(): number;
|
||||||
/** Whether the cell has the inverse attribute (CSI 8 m). */
|
/** Whether the cell has the invisible attribute (CSI 8 m). */
|
||||||
isInvisible(): number;
|
isInvisible(): number;
|
||||||
|
/** Whether the cell has the strikethrough attribute (CSI 9 m). */
|
||||||
|
isStrikethrough(): number;
|
||||||
|
|
||||||
/** Whether the cell is using the RGB foreground color mode. */
|
/** Whether the cell is using the RGB foreground color mode. */
|
||||||
isFgRGB(): boolean;
|
isFgRGB(): boolean;
|
||||||
|
|||||||
Reference in New Issue
Block a user