Compare commits

...
1689 Commits
Author SHA1 Message Date
Daniel Imms 4809a2e0df Merge pull request #2828 from Tyriar/release45
v4.5.0
2020-04-10 12:53:39 -07:00
Daniel Imms f61d6320a3 v4.5.0 2020-04-10 12:44:39 -07:00
Daniel Imms c66b25b4cc Merge pull request #2827 from Tyriar/eslint_types
Convert eslintrc to json and fix errors
2020-04-10 10:29:46 -07:00
Daniel Imms a66edbdda8 Merge pull request #2713 from JavaCS3/master
expose IBufferSet API
2020-04-10 10:18:51 -07:00
Daniel Imms ef0d834db8 Convert eslintrc to json and fix errors 2020-04-10 10:05:23 -07:00
Daniel Imms 89daacac32 Add missing api docs 2020-04-10 10:02:09 -07:00
Daniel Imms f4f15ee5e9 Add missing line in api 2020-04-10 09:57:10 -07:00
Daniel Imms 4c36ef9d24 Don't pass buffers to BufferApiView 2020-04-10 09:56:26 -07:00
Daniel Imms 886af692e2 Use a separate emitter for BufferNamespaceApi.onBufferChange 2020-04-10 09:53:51 -07:00
Daniel Imms c63949f384 Merge branch 'master' into master 2020-04-10 09:37:51 -07:00
Daniel Imms 34a324f551 Merge pull request #2825 from Tyriar/debug_log
Use debug log level for open not attached to the DOM
2020-04-10 07:50:51 -07:00
Daniel Imms 996694aec4 Use debug log level for open not attached to the DOM
It seems mostly harmless now

Part of microsoft/vscode#88529
2020-04-10 07:50:10 -07:00
Daniel Imms e21060a259 Merge pull request #2725 from Tyriar/webkit
Improve Linux dependencies, remove browser args
2020-04-10 06:45:37 -07:00
Daniel Imms 951d342ed7 Disable webkit 2020-04-10 06:38:54 -07:00
Daniel Imms 74b76704f8 Merge pull request #2746 from jerch/fix_2745
cursor handling in DECSTR
2020-04-10 06:36:39 -07:00
Daniel Imms 6efc37eaf3 Merge branch 'master' into webkit 2020-04-10 06:34:45 -07:00
Daniel Imms 9cf4e68ac4 Merge pull request #2739 from felixse/fix-edge-selection-color
Fix selection color in Legacy Edge
2020-04-10 06:34:05 -07:00
Daniel Imms 1c35c8b617 Merge pull request #2817 from Tyriar/2764
Pause cursor render layer before resuming
2020-04-10 06:25:30 -07:00
Charles Wei 94dabe225b Merge branch 'master' into master 2020-04-10 12:11:17 +08:00
Daniel Imms 21b490f03a Merge pull request #2819 from xtermjs/dependabot/npm_and_yarn/typescript-eslint/parser-2.27.0
Bump @typescript-eslint/parser from 2.26.0 to 2.27.0
2020-04-07 06:31:30 -07:00
dependabot-preview[bot] f8f509a296 Bump @typescript-eslint/parser from 2.26.0 to 2.27.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.26.0 to 2.27.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v2.27.0/packages/parser)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-07 13:17:32 +00:00
Daniel Imms 062b771622 Merge pull request #2820 from xtermjs/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-2.27.0
Bump @typescript-eslint/eslint-plugin from 2.26.0 to 2.27.0
2020-04-07 06:15:48 -07:00
dependabot-preview[bot] adff472011 Bump @typescript-eslint/eslint-plugin from 2.26.0 to 2.27.0
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 2.26.0 to 2.27.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v2.27.0/packages/eslint-plugin)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-07 08:17:08 +00:00
Charles Wei 9c043dbf9f Merge branch 'master' into master 2020-04-07 11:27:32 +08:00
Daniel Imms 59d28e7b99 Use browser types instead of nodejs 2020-04-06 05:33:09 -07:00
Daniel Imms 8b5a133106 Pause cursor render layer before resuming
Fixes #2764
2020-04-06 05:32:11 -07:00
Daniel Imms 86a41dd6dd Merge pull request #2815 from xtermjs/dependabot/npm_and_yarn/nyc-15.0.1
Bump nyc from 15.0.0 to 15.0.1
2020-04-06 04:23:57 -07:00
dependabot-preview[bot] 2d77b25e26 Bump nyc from 15.0.0 to 15.0.1
Bumps [nyc](https://github.com/istanbuljs/nyc) from 15.0.0 to 15.0.1.
- [Release notes](https://github.com/istanbuljs/nyc/releases)
- [Changelog](https://github.com/istanbuljs/nyc/blob/master/CHANGELOG.md)
- [Commits](https://github.com/istanbuljs/nyc/compare/v15.0.0...v15.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-06 08:41:11 +00:00
Daniel Imms 43526c2297 Merge pull request #2814 from Tyriar/role_list
Use role=list in screen reader mode
2020-04-05 09:54:56 -07:00
Daniel Imms 192762add8 Use role=list in screen reader mode 2020-04-05 09:54:19 -07:00
javacs3 0f64847351 fix lint error 2020-04-05 15:31:05 +08:00
Charles Wei 88d2f26269 Merge branch 'master' into master 2020-04-05 12:15:37 +08:00
Daniel Imms 21aabb1215 Merge pull request #2810 from xtermjs/dependabot/npm_and_yarn/deep-equal-2.0.2
Bump deep-equal from 2.0.1 to 2.0.2
2020-04-02 07:58:40 -07:00
dependabot-preview[bot] e6ea51f8cb Bump deep-equal from 2.0.1 to 2.0.2
Bumps [deep-equal](https://github.com/inspect-js/node-deep-equal) from 2.0.1 to 2.0.2.
- [Release notes](https://github.com/inspect-js/node-deep-equal/releases)
- [Changelog](https://github.com/inspect-js/node-deep-equal/blob/master/CHANGELOG.md)
- [Commits](https://github.com/inspect-js/node-deep-equal/compare/v2.0.1...v2.0.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-02 08:07:09 +00:00
Daniel Imms 6d52e1709f Merge pull request #2805 from xtermjs/dependabot/npm_and_yarn/mustache-4.0.1
Bump mustache from 3.2.1 to 4.0.1
2020-04-01 06:59:52 -07:00
dependabot-preview[bot] aaf1fd0256 Bump mustache from 3.2.1 to 4.0.1
Bumps [mustache](https://github.com/janl/mustache.js) from 3.2.1 to 4.0.1.
- [Release notes](https://github.com/janl/mustache.js/releases)
- [Changelog](https://github.com/janl/mustache.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/janl/mustache.js/compare/v3.2.1...v4.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-01 13:27:45 +00:00
Daniel Imms 97ef539a6c Merge pull request #2803 from Tyriar/more_deps
Upgrade more deps
2020-04-01 06:25:58 -07:00
Daniel Imms b630aad44a Namespace window 2020-04-01 05:25:39 -07:00
Daniel Imms 2f6fb4b97c Upgrade jsdom 2020-03-31 11:10:39 -07:00
Daniel Imms 5c99114b02 Upgrade nyc 2020-03-31 11:07:26 -07:00
Daniel Imms 318421df9d Update more types 2020-03-31 11:01:33 -07:00
Daniel Imms 2f42dc6473 Upgrade chai to 4 2020-03-31 10:59:15 -07:00
Daniel Imms 66bcdc3c00 Update some more dependencies 2020-03-31 10:55:55 -07:00
Daniel Imms 8b042caf60 Merge pull request #2792 from xtermjs/dependabot/npm_and_yarn/mocha-7.1.1
Bump mocha from 6.2.3 to 7.1.1
2020-03-31 09:12:50 -07:00
dependabot-preview[bot] b3408f5ad4 Bump mocha from 6.2.3 to 7.1.1
Bumps [mocha](https://github.com/mochajs/mocha) from 6.2.3 to 7.1.1.
- [Release notes](https://github.com/mochajs/mocha/releases)
- [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mochajs/mocha/compare/v6.2.3...v7.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-31 14:33:22 +00:00
Daniel Imms 5558bc1ef3 Merge pull request #2780 from xtermjs/dependabot/npm_and_yarn/types/ws-7.2.3
Bump @types/ws from 6.0.1 to 7.2.3
2020-03-31 07:31:37 -07:00
dependabot-preview[bot] 2426a731fc Bump @types/ws from 6.0.1 to 7.2.3
Bumps [@types/ws](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/ws) from 6.0.1 to 7.2.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/ws)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-31 14:14:25 +00:00
Daniel Imms 47e2b0991a Merge pull request #2801 from xtermjs/dependabot/npm_and_yarn/types/webpack-4.41.10
Bump @types/webpack from 4.41.9 to 4.41.10
2020-03-31 07:12:46 -07:00
dependabot-preview[bot] ceec98ffc3 Bump @types/webpack from 4.41.9 to 4.41.10
Bumps [@types/webpack](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/webpack) from 4.41.9 to 4.41.10.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/webpack)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-31 08:10:36 +00:00
Daniel Imms a24b977f72 Merge pull request #2800 from Tyriar/upgrade_mac
Upgrade mac agent in pipelines
2020-03-30 10:00:29 -07:00
Daniel Imms 4602ffba29 Merge pull request #2799 from Tyriar/enum_like_upper_case
Allow enum-like objects to use upper case naming
2020-03-30 06:46:48 -07:00
Daniel Imms 21d4ee8e2e Upgrade mac agent in pipelines
Looks like capacity has run out for old macOS, this should get builds
green again.
2020-03-30 06:43:45 -07:00
Daniel Imms 8ec41a7128 Merge pull request #2795 from xtermjs/dependabot/npm_and_yarn/types/webpack-4.41.9
Bump @types/webpack from 4.41.8 to 4.41.9
2020-03-30 06:42:12 -07:00
Daniel Imms 8842625bb4 Allow enum-like objects to use upper case naming 2020-03-30 06:17:37 -07:00
dependabot-preview[bot] 586be86b41 Bump @types/webpack from 4.41.8 to 4.41.9
Bumps [@types/webpack](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/webpack) from 4.41.8 to 4.41.9.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/webpack)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-30 08:38:01 +00:00
Daniel Imms 55190fd703 Merge pull request #2786 from Tyriar/eslint
Migrate from tslint to eslint
2020-03-28 08:57:58 -07:00
Daniel Imms 64f7978037 Format eslintrc 2020-03-28 07:50:30 -07:00
Daniel Imms 3f33751ff2 Merge remote-tracking branch 'ups/master' into eslint 2020-03-28 07:45:06 -07:00
Daniel Imms 392f349da1 Remove tslint completely 2020-03-28 07:39:51 -07:00
Daniel Imms bbd83b9dba Migrate whitespace tslint rule 2020-03-28 07:34:49 -07:00
Daniel Imms 2e9b4779c9 Migrate from typedef to explicit-function-return-type 2020-03-28 07:10:08 -07:00
Daniel Imms 8475f95b19 Disable naming convention on CoreMouseService
Until #2787 gets looked at
2020-03-28 07:04:21 -07:00
Daniel Imms 2c0669c865 Fix some naming conventions issues 2020-03-28 06:57:55 -07:00
Daniel Imms 937b551ae4 Migrate naming-convention rules to @typescript/eslint equivalent 2020-03-28 06:53:15 -07:00
Daniel Imms 88a50d3779 Fix most rules 2020-03-28 06:51:36 -07:00
Daniel Imms 57be6616ce Initial eslintrc.js
Generated by tool
2020-03-28 05:10:03 -07:00
Daniel Imms 7e073e6e26 Merge pull request #2783 from Tyriar/deps
Update several dependencies
2020-03-27 18:31:28 -07:00
Daniel Imms 10ff95af6a Update several dependencies 2020-03-27 16:50:49 -07:00
Daniel Imms 378d3e3889 Merge pull request #2772 from xtermjs/dependabot/npm_and_yarn/https-proxy-agent-2.2.4
[Security] Bump https-proxy-agent from 2.2.1 to 2.2.4
2020-03-27 16:06:29 -07:00
dependabot-preview[bot] 88f1353670 [Security] Bump https-proxy-agent from 2.2.1 to 2.2.4
Bumps [https-proxy-agent](https://github.com/TooTallNate/node-https-proxy-agent) from 2.2.1 to 2.2.4. **This update includes security fixes.**
- [Release notes](https://github.com/TooTallNate/node-https-proxy-agent/releases)
- [Commits](https://github.com/TooTallNate/node-https-proxy-agent/compare/2.2.1...2.2.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-27 22:52:12 +00:00
Daniel Imms c229aa8cfe Merge pull request #2760 from xtermjs/dependabot/npm_and_yarn/acorn-5.7.4
Bump acorn from 5.7.1 to 5.7.4
2020-03-27 15:50:55 -07:00
dependabot[bot] 96549a5421 Bump acorn from 5.7.1 to 5.7.4
Bumps [acorn](https://github.com/acornjs/acorn) from 5.7.1 to 5.7.4.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/5.7.1...5.7.4)

Signed-off-by: dependabot[bot] <support@github.com>
2020-03-27 22:45:12 +00:00
Daniel Imms a99c6145a7 Merge pull request #2779 from xtermjs/dependabot/npm_and_yarn/webpack-cli-3.3.11
Bump webpack-cli from 3.1.0 to 3.3.11
2020-03-27 15:44:21 -07:00
dependabot-preview[bot] c85ab8dcb6 Bump webpack-cli from 3.1.0 to 3.3.11
Bumps [webpack-cli](https://github.com/webpack/webpack-cli) from 3.1.0 to 3.3.11.
- [Release notes](https://github.com/webpack/webpack-cli/releases)
- [Changelog](https://github.com/webpack/webpack-cli/blob/next/CHANGELOG_v3.md)
- [Commits](https://github.com/webpack/webpack-cli/compare/v.3.1.0...v3.3.11)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-27 21:32:21 +00:00
Daniel Imms db172b341e Merge pull request #2770 from xtermjs/dependabot/npm_and_yarn/deep-equal-2.0.1
Bump deep-equal from 1.1.0 to 2.0.1
2020-03-27 14:28:06 -07:00
dependabot-preview[bot] 11dbba422f Bump deep-equal from 1.1.0 to 2.0.1
Bumps [deep-equal](https://github.com/inspect-js/node-deep-equal) from 1.1.0 to 2.0.1.
- [Release notes](https://github.com/inspect-js/node-deep-equal/releases)
- [Changelog](https://github.com/inspect-js/node-deep-equal/blob/master/CHANGELOG.md)
- [Commits](https://github.com/inspect-js/node-deep-equal/compare/v1.1.0...v2.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-27 21:01:51 +00:00
Felix Seidl a1e60045d9 Merge branch 'master' into fix-edge-selection-color 2020-03-25 17:53:08 +01:00
Charles Wei b36a9d5af3 Merge branch 'master' into master 2020-03-24 21:15:20 +08:00
Daniel Imms fb5ff49008 Merge pull request #2767 from JavaCS3/fix/addDisposableDomListener-leak
fix: addDisposableDomListener dispose() leaking
2020-03-23 06:42:22 -07:00
javacs3 1b857f743e fix: addDisposableDomListener dispose() leaking 2020-03-22 12:56:50 +08:00
javacs3 c2df14cfa0 reduce BufferApiView object creation times 2020-03-22 12:13:53 +08:00
javacs3 44ff7b0f5f change buffer interface from IBuffer to IBufferNamespace 2020-03-22 12:13:52 +08:00
javacs3 5fdbd7428b expose IBufferSet API 2020-03-22 12:10:02 +08:00
Daniel Imms bc9aaebd04 Merge pull request #2766 from Tyriar/readme
Improve demo warning and add to server.js as well
2020-03-19 18:29:01 -07:00
Daniel Imms d90a0ce910 Improve demo warning and add to server.js as well
Fixes #2765
2020-03-19 18:26:45 -07:00
Daniel Imms 9c19043fed Merge pull request #2761 from slel/patch-1
Add CoCalc to "Real-world uses" in README
2020-03-16 06:59:22 -07:00
Samuel Lelièvre beb39ada0c Add CoCalc at end of list of real-world uses 2020-03-16 13:43:42 +01:00
Samuel Lelièvre 47f3eb28a6 Add CoCalc to "Real-world uses" in README 2020-03-16 04:32:34 +01:00
Daniel Imms 28105af761 Merge pull request #2731 from jerch/fix_2729
Clamp visual cursor to cols - 1
2020-03-13 19:26:46 -07:00
Daniel Imms e0ac87e702 Update xterm.d.ts 2020-03-13 19:17:34 -07:00
Daniel Imms b9ea05f97a Merge branch 'master' into fix_2729 2020-03-13 19:09:13 -07:00
Daniel Imms e348163689 Merge pull request #2758 from Tyriar/acorn
Upgrade acorn due to CVE
2020-03-13 18:53:48 -07:00
Daniel Imms 90375531bc Merge branch 'master' into acorn 2020-03-13 18:42:49 -07:00
Daniel Imms ca85f2d725 Upgrade acorn due to CVE 2020-03-13 18:42:10 -07:00
jerch eaadb75d39 Merge pull request #2754 from jerch/fix_vtfeatures_2
vtfeatures 2nd fix
2020-03-11 00:09:53 +01:00
Jörg Breitbart f6793df94a remove leading empty line 2020-03-10 23:59:41 +01:00
jerch 90e716b932 Merge pull request #2753 from jerch/fix_vtfeatures_template
fix missing jekyll header in vtfeatures template
2020-03-10 23:43:48 +01:00
Jörg Breitbart db2853c8ae add missing jekyll yaml entries 2020-03-10 23:35:08 +01:00
Jörg Breitbart 47d7a71ad0 fix cursor reset in DECSTR, some tests 2020-03-01 13:29:18 +01:00
Felix Seidl 88a6be16af use original css color string 2020-02-27 23:03:23 +01:00
Jörg Breitbart db304513b1 unify naming, adjust addon version, fix interface description 2020-02-22 20:30:36 +01:00
Jörg Breitbart 8d1b4bf78f fix webgl renderer 2020-02-22 20:18:45 +01:00
Jörg Breitbart 1cff37af99 fix dom renderer 2020-02-22 20:08:34 +01:00
jerch ecc7f2d780 Merge branch 'master' into fix_2729 2020-02-22 19:57:53 +01:00
Daniel Imms dbb6610d50 Merge pull request #2730 from Tyriar/ts38
typescript@3.8
2020-02-22 19:53:40 +01:00
Daniel Imms ae135ac181 Merge pull request #2730 from Tyriar/ts38
typescript@3.8
2020-02-22 10:04:07 -08:00
Daniel Imms df1d68b626 typescript@3.8 2020-02-22 09:43:16 -08:00
Daniel Imms a18bac7380 Remove browser args 2020-02-18 07:47:01 -08:00
Daniel Imms 9a1c7953e7 dumpio in browser launch 2020-02-18 07:39:15 -08:00
Daniel Imms 53c526f48c Improve Linux dependencies, enable WebKit 2020-02-18 06:49:11 -08:00
Daniel Imms 49bfd05d7c Merge pull request #2723 from UziTech/patch-1
atom-xterm -> x-terminal
2020-02-18 06:33:24 -08:00
Tony Brix 11ac8da14e Update README.md 2020-02-17 00:04:47 -06:00
Daniel Imms 986baed290 Merge pull request #2722 from Tyriar/linux_tests
Install deps for webkit and firefox on Linux
2020-02-16 08:08:20 -08:00
Daniel Imms 84c5f76b76 Remove webkit tests on Linux 2020-02-16 07:57:28 -08:00
Tony Brix 39c6f41f0e atom-xterm -> x-terminal 2020-02-15 15:16:37 -06:00
Daniel Imms bdb01e6166 Remove DEBUG, test fit addon based on a range 2020-02-15 12:26:59 -08:00
Daniel Imms 35ddcdd266 Upgrade to ubuntu-18.04 2020-02-15 12:13:38 -08:00
Daniel Imms 7e8e1215ad Fix order 2020-02-15 12:09:57 -08:00
Daniel Imms 83abd7ef59 Change pipeline property names 2020-02-15 12:07:19 -08:00
Daniel Imms 26fa6c97bf Install deps for webkit and firefox on Linux
Fixes #2721
2020-02-15 07:38:40 -08:00
Daniel Imms 708c6bdeb8 Merge pull request #2712 from jmbockhorst/playwright
Use playwright instead of puppeteer
2020-02-15 07:22:52 -08:00
Daniel Imms c73adf02bc Disable windows tests 2020-02-15 07:14:09 -08:00
Daniel Imms c36a468561 script -> pwsh 2020-02-15 07:08:42 -08:00
Daniel Imms 83794c433f Tweak windows server start 2020-02-15 07:05:20 -08:00
Daniel Imms eb82346ce7 Add a Windows test job 2020-02-15 06:40:04 -08:00
Daniel Imms 1a6ec0d768 Disable webkit on Linux 2020-02-15 06:39:10 -08:00
Daniel Imms 446f8f93c6 Disable firefox on linux 2020-02-15 06:27:03 -08:00
Daniel Imms 445a801d5d Fix syntax error 2020-02-15 06:21:05 -08:00
Daniel Imms 579a135087 Try firefox deps
https://bugzilla.mozilla.org/show_bug.cgi?id=1372998
2020-02-15 06:17:53 -08:00
Daniel Imms cd1b251cef Up timeout for slower CI agents 2020-02-15 06:07:33 -08:00
Daniel Imms ed23194abd Update macOS version 2020-02-15 06:00:59 -08:00
Daniel Imms 2ac0c0a957 Move playwright-core back to dev 2020-02-15 05:55:01 -08:00
Daniel Imms 477b161ba2 Change browserType back to sync 2020-02-15 05:51:39 -08:00
Daniel Imms cb1353c898 Cache yarn modules on integration test jobs 2020-02-15 05:48:38 -08:00
Daniel Imms 47dc137de0 Download browser at start of test 2020-02-15 05:47:42 -08:00
Daniel Imms 03c6b0c688 Fix typo in firefox job 2020-02-15 05:30:33 -08:00
Daniel Imms ffc5e2f446 Move to playwright-core, download browser if needed 2020-02-15 05:28:21 -08:00
Daniel Imms 4ebb61b580 Adopt playwright breaking changes 2020-02-15 05:18:46 -08:00
Daniel Imms 4ae25e57a3 playwright@0.11.1 2020-02-15 05:14:00 -08:00
Daniel Imms 7bd4f3874e Fix lint 2020-02-15 05:13:52 -08:00
Daniel Imms 2b7080294d Only start server once in pipelines 2020-02-15 05:06:44 -08:00
Daniel Imms 3b51565a13 Fix pipelines file 2020-02-15 05:02:28 -08:00
Daniel Imms 7400b888df Skip mouse wheel-related tests on non-chromium 2020-02-15 05:00:52 -08:00
Daniel Imms 3f15a7251b Skip webgl tests instead of not registering 2020-02-15 04:53:45 -08:00
Daniel Imms a9356fd377 Skip paste test when not Chromium 2020-02-15 04:43:38 -08:00
Daniel Imms f3eb9f79a1 Movee api test timeout into CLI args 2020-02-15 04:29:04 -08:00
Daniel Imms 93026bcae0 Only enable webgl tests on chromium and non-headless firefox
See microsoft/playwright#1032
2020-02-15 04:23:31 -08:00
Daniel Imms 6082c00b1d Fix serialize tests on firefox
Firefox takes longer to start up
2020-02-15 03:58:33 -08:00
Daniel Imms e6e181e6bc Fix firefox tests FitAddon tests 2020-02-15 03:54:30 -08:00
Daniel Imms 502452f58e Enable tests on other browsers 2020-02-15 03:35:08 -08:00
Daniel Imms 1d0cceb2d3 Merge branch 'master' into playwright 2020-02-15 03:26:37 -08:00
Daniel Imms 5f0217cdb0 Merge pull request #2710 from jmbockhorst/linkFix
Fix Link Provider end positions
2020-02-13 08:49:45 -08:00
Daniel Imms 7b40aa89b4 Merge branch 'master' into linkFix 2020-02-13 08:36:43 -08:00
Jon Bockhorst e817a7b6c6 Add Linkifier2 tests 2020-02-13 00:43:24 -06:00
Jon Bockhorst b53c2e1a26 Fix tests 2020-02-13 00:15:12 -06:00
Jon Bockhorst 383e2ed46f Remove duplicate code and clean up after merge 2020-02-13 00:07:07 -06:00
Jon Bockhorst 258b084a62 Merge branch 'master' of https://github.com/xtermjs/xterm.js into playwright 2020-02-12 23:53:53 -06:00
Daniel Imms c5593bde08 Merge pull request #2711 from jmbockhorst/testing
Move openTerminal() to common util file
2020-02-12 16:12:47 -08:00
Daniel Imms 2cd4580154 Merge pull request #2715 from kumaran-14/2586_dom_renderer
Remove multiple usance of background-color in dom renderer
2020-02-12 16:05:38 -08:00
Jon Bockhorst 2442dc09b0 Clean up some stuff based on feedback 2020-02-12 16:00:21 -06:00
Jon Bockhorst d482ca5d68 Merge branch 'master' into testing 2020-02-12 14:34:30 -06:00
Jon Bockhorst 3616b697ec Remove unnecessary composite setting 2020-02-12 14:29:38 -06:00
Kumaran a19dfe608d Merge branch 'master' into 2586_dom_renderer 2020-02-12 23:12:28 +05:30
kumaran-14 0c1e9b6678 Remove multiple usance of background-color in dom renderer 2020-02-12 23:07:12 +05:30
Jon Bockhorst 391313cd39 Revert some formatting and remove puppeteer 2020-02-11 13:32:55 -06:00
Jon Bockhorst 8fb6ded506 Fix mouse tests for chromium 2020-02-11 13:13:03 -06:00
Jon Bockhorst eb7b2f4683 Make addons use common test functions 2020-02-11 11:39:36 -06:00
Jon Bockhorst 520918348e Fix some mouse tests 2020-02-10 18:18:23 -06:00
Jon Bockhorst e7b3910f3d Update CI to node 10 2020-02-10 17:05:18 -06:00
Jon Bockhorst 7515ed6146 Use playwright instead of puppeteer 2020-02-10 16:56:37 -06:00
Jon Bockhorst 901adb38ae Fix linkProvider end positions 2020-02-10 12:39:16 -06:00
Jon Bockhorst 522378a507 Move openTerminal() to common util file 2020-02-10 11:18:23 -06:00
Daniel Imms 1bb2fc912b Merge pull request #2709 from Tyriar/search_bump
Release search
2020-02-10 05:51:49 -08:00
Daniel Imms 423d112dfc Release search
0.4.0 isn't compatible with xterm@4.4
2020-02-10 05:51:02 -08:00
Daniel Imms 63fde03552 Merge pull request #2530 from jmbockhorst/linkParser
Basic link parser for better link detection
2020-02-08 11:12:10 -08:00
Daniel Imms d1d27b5367 Remove logs 2020-02-08 11:04:04 -08:00
Daniel Imms 0e302baa43 Mark link matcher API as deprecated 2020-02-08 10:58:58 -08:00
Daniel Imms a7c2d54e53 Document link provider argument in web links addon 2020-02-08 10:54:29 -08:00
Daniel Imms 54743eda16 Make link matcher API the default for web links addon 2020-02-08 10:52:36 -08:00
Daniel Imms 660cf26e49 Merge branch 'master' into linkParser 2020-02-07 12:47:25 -08:00
Daniel Imms e4875f26ff Add test for absense of hover/leave 2020-02-07 11:54:07 -08:00
Daniel Imms 7f1f22146d Add test for activate 2020-02-07 11:52:58 -08:00
Daniel Imms 0103c689f7 Start registerLinkProvider tests
Bugs fixed:

- Not breaking on first link match for multiple providers
- Hover event wasn't fired when on last character of link
2020-02-07 11:16:41 -08:00
Daniel Imms f4a31251cb handle -> activate 2020-02-07 09:59:25 -08:00
Daniel Imms b18ded0e2d Rename tooltip to hover/leave 2020-02-07 09:55:06 -08:00
Daniel Imms c327116e7f url -> text 2020-02-07 09:39:26 -08:00
Daniel Imms ef071ac7ac Polish API 2020-02-07 09:30:12 -08:00
Daniel Imms 56990f2a29 Merge pull request #2698 from xtermjs/Tyriar-patch-1
Fix grammar in demo
2020-02-07 09:13:58 -08:00
Daniel Imms 4475a82776 Fix grammar in demo 2020-02-07 09:13:03 -08:00
Daniel Imms 560a30662b Merge pull request #2696 from mofux/fix/serialize-addon-peer-dependency
Fix serialize addon peer dependency to xterm
2020-02-07 09:09:13 -08:00
Daniel Imms a066bbe32f 💄 2020-02-07 09:08:07 -08:00
Daniel Imms e252b4b674 Merge branch 'master' into linkParser 2020-02-07 09:04:24 -08:00
Thomas Zilz 3283ffb4e1 Fix serialize addon peer dependency to xterm 2020-02-06 12:27:02 +01:00
Daniel Imms a840db3e79 Merge pull request #2692 from xtermjs/Tyriar-patch-1
v4.4.0
2020-02-04 09:54:10 -08:00
Daniel Imms dc19d7c72c v4.4.0 2020-02-04 09:53:56 -08:00
Jon Bockhorst a95b1b4881 Merge branch 'master' of https://github.com/xtermjs/xterm.js into linkParser 2020-02-04 11:40:48 -06:00
Daniel Imms 4d0fc16fe3 Merge pull request #2691 from Tyriar/bump2
Bump serialize and unciode11 addon versions to trigger publish
2020-02-04 09:39:47 -08:00
Daniel Imms b13c3be92f Bump serialize and unciode11 addon versions to trigger publish 2020-02-04 09:39:18 -08:00
Daniel Imms a3a222c1f1 Merge pull request #2690 from Tyriar/version_bump_publish
Bump attach and webgl addons and automatically publish serialize and unicode11 addons
2020-02-04 09:29:04 -08:00
Daniel Imms 1d7cfcdd99 Bump webgl and attach versions 2020-02-04 09:19:49 -08:00
Daniel Imms 2c05e721fd Publish serialize and unicode11 addons automatically 2020-02-04 09:19:28 -08:00
Daniel Imms 22acf1ec25 Merge pull request #2618 from xtermjs/feat/serialize-addon
Merge serialize addon into master
2020-02-04 08:54:41 -08:00
Daniel Imms 9c8deb1470 Revert "Remove getNullCell"
This reverts commit 0b6a5b7630.
2020-02-04 08:42:24 -08:00
Daniel Imms 9b9cb5c076 Merge branch 'master' into feat/serialize-addon 2020-02-04 08:33:11 -08:00
Daniel Imms 0b6a5b7630 Remove getNullCell
Replace with fetching cell (0,0) and using that as the initial null cell. We
can reconsider adding this back if it's needed
2020-02-04 08:31:06 -08:00
Daniel Imms fac025367b Document IBufferCell members 2020-02-04 08:15:21 -08:00
Daniel Imms e5246f3993 jsdoc IBufferLine.length 2020-02-04 07:55:26 -08:00
Daniel Imms 89370a1f74 Explain why reusing IBufferCell is useful 2020-02-04 07:54:11 -08:00
Daniel Imms 51a564eb9c Remove links to serialize from test/benchmark 2020-02-04 07:45:12 -08:00
Daniel Imms b50b6ccb8b Fix fg used by selection in webgl again
See #2650
2020-02-04 07:41:04 -08:00
Daniel Imms 7a8e2c67b0 Merge pull request #2393 from jerch/window_manipulation
Support for window options
2020-02-04 07:38:51 -08:00
Daniel Imms 1b4a3475e8 Fix demo after bad merge 2020-02-04 07:07:34 -08:00
Daniel Imms 3d2d35f5b6 Pull render service off instantiation service safely 2020-02-04 07:01:25 -08:00
Daniel Imms 489d8110c9 Move windowOptions into public API part 2020-02-04 06:53:17 -08:00
Daniel Imms fc5bf99715 Merge branch 'master' into window_manipulation 2020-02-04 06:52:24 -08:00
Daniel Imms 999bdc9498 Merge branch 'master' into feat/serialize-addon 2020-02-04 06:52:00 -08:00
Daniel Imms 06e3528bc8 Merge pull request #2689 from Tyriar/2607_parser_stable
Make parser stable, remove deprecated APIs
2020-02-04 06:51:38 -08:00
Daniel Imms b06a88b09f Merge pull request #2688 from Tyriar/2608_safe_links
Handle links safely by removing opener from window
2020-02-04 06:51:24 -08:00
Daniel Imms 51aab3eacc Merge branch 'master' into window_manipulation 2020-02-04 06:51:13 -08:00
Daniel Imms 545807755d Merge pull request #2386 from jerch/extract_vt_features
document VT features in docstrings
2020-02-04 06:50:07 -08:00
Daniel Imms b7ae55a07b Make parser stable, remove deprecated APIs
Fixes #2607
2020-02-04 06:46:25 -08:00
Daniel Imms a980b3d132 Handle links safely by removing opener from window
Fixes #2608
2020-02-04 06:43:17 -08:00
Daniel Imms 58047e8b82 Merge branch 'master' into window_manipulation 2020-02-04 06:33:54 -08:00
Daniel Imms 9abeaa74c6 Merge pull request #2687 from JavaCS3/feat/serialize-addon
fix: api test fail due to IBufferCell api changes
2020-02-04 06:18:53 -08:00
javacs3 c512e48c52 fix: api test fail due to IBufferCell api changes 2020-02-04 14:46:03 +08:00
Daniel Imms 8924437fc5 Merge branch 'master' into feat/serialize-addon 2020-02-03 12:00:20 -08:00
Daniel Imms 1d8e242b3c Merge pull request #2369 from JavaCS3/feat/serialize-addon
Add foreground/background color support for SerializeAddon
2020-02-03 11:58:44 -08:00
Daniel Imms cf33f7c281 Merge branch 'feat/serialize-addon' into feat/serialize-addon 2020-02-03 11:54:11 -08:00
Daniel Imms 56ac6f66bf Merge pull request #2685 from Tyriar/2675_remove_options
Remove old unused options from codebase
2020-02-03 11:17:39 -08:00
jerch 5ac649b21a Merge branch 'master' into extract_vt_features 2020-02-03 20:06:33 +01:00
Daniel Imms 4a567c9f5a Remove old unused options from codebase
Fixes #2675
2020-02-03 10:56:46 -08:00
Daniel Imms 479fddfeec Merge branch 'master' into window_manipulation 2020-02-03 10:48:38 -08:00
Daniel Imms cc6f9e9da4 Merge pull request #2684 from Tyriar/2683_cursor_refresh
Refresh cursor row when cursor settings updated
2020-02-03 10:34:46 -08:00
Daniel Imms de9df12ea9 Merge remote-tracking branch 'ups/master' into pr/jerch/2393 2020-02-03 10:34:26 -08:00
Daniel Imms 8145829619 Merge pull request #2568 from jerch/updated_wcwidth
wcwidth rules for unicode 11
2020-02-03 10:27:47 -08:00
Daniel Imms 3bd0cb9a15 Merge branch 'master' into updated_wcwidth 2020-02-03 10:22:29 -08:00
Daniel Imms 412d6fe42c Refresh cursor row when cursor settings updated
Fixes #2683
2020-02-03 10:13:13 -08:00
Daniel Imms 12362cac61 Merge pull request #2679 from jerch/fix_2678
Add/fix chars in DEC graphics charset
2020-02-03 07:15:47 -08:00
Daniel Imms 001d26d73c Merge pull request #2670 from kumaran-14/patch-alt-click
Fixes Alt + click behaviour when rows are wrapped
2020-02-03 07:07:59 -08:00
Daniel Imms 75191982da Merge pull request #2682 from Tyriar/2681_exit_code_ci
Return exit code in Linux unit tests
2020-02-03 07:06:47 -08:00
Daniel Imms 8093a5f419 Fix lint 2020-02-03 07:02:14 -08:00
Daniel Imms 3d53847f30 Return exit code in Linux unit tests
Fixes #2681
2020-02-03 07:00:06 -08:00
Daniel Imms bb944f190e Fix and add more MoveToCell tests 2020-02-03 06:54:35 -08:00
Daniel Imms 7d84083f55 Fix algorithm to move the right amount of cells 2020-02-03 06:43:20 -08:00
kumaran-14 b591ccc40d Fix moveToCell when target is beyond buffer 2020-02-02 23:28:24 +05:30
Daniel Imms 46b95ed639 Merge pull request #2676 from jeffbaier/master
Add _terminalClass identifier to cursor blink animation css
2020-02-02 05:21:03 -08:00
Daniel Imms c050cf305c Merge pull request #2680 from Tyriar/2665_word_ep
Remove ; and : from default wordSeparator
2020-02-02 05:15:13 -08:00
Daniel Imms d5bf8966d9 Remove ; and : from default wordSeparator
Fixes #2665
2020-02-02 05:10:57 -08:00
Jörg Breitbart 49bc27e24f fixing visual repr chars 2020-02-02 13:07:11 +01:00
Jeff Baier 6240a5d7a4 Add _terminalClass identifier to cursor blink animation css
so that multiple DOM rendered instances no longer lose the cursor theme color
Fixes #2674
2020-01-22 14:16:39 -06:00
kumaran-14 af67b72492 Fix unit tests for MoveToCellSequence 2020-01-15 21:32:04 +05:30
Jörg Breitbart d2145368fa several template updates 2020-01-10 18:51:27 +01:00
Jörg Breitbart 4010900e47 simply status column, reason in title 2020-01-09 22:40:08 +01:00
Jörg Breitbart 2d1af70e87 lower header level; fix wrongly escaped sequences 2020-01-09 20:40:18 +01:00
kumaran-14 76d4de225a Run eslint and fix errors 2020-01-10 00:40:49 +05:30
kumaran-14 f5c3b00c42 Fixes Alt + click behaviour when rows are wrapped 2020-01-10 00:02:18 +05:30
Jörg Breitbart f9fddfc43d fix table sorting 2020-01-09 18:47:56 +01:00
Jörg Breitbart 12b912140b use 2 empty lines as end of vt definition 2020-01-09 16:40:35 +01:00
javacs3 56f4c3d6ae remove BufferCellApiView 2020-01-09 21:15:30 +08:00
jerch f560d187c1 Merge branch 'master' into window_manipulation 2020-01-09 00:27:22 +01:00
jerch d4d7446789 Merge branch 'master' into updated_wcwidth 2020-01-09 00:26:48 +01:00
jerch 663da772e0 Merge branch 'master' into extract_vt_features 2020-01-09 00:07:44 +01:00
Jörg Breitbart b51226f76c docs for SM/RM/DECSET/DECRST/SGR 2020-01-09 00:00:19 +01:00
Jörg Breitbart 297ea529a2 make linter happy 2020-01-08 18:08:39 +01:00
Jörg Breitbart 016d176cbd more docs 2020-01-08 17:51:56 +01:00
Daniel Imms 83e582b7ab Merge remote-tracking branch 'origin/master' into feat/serialize-addon 2020-01-07 10:30:21 -08:00
Daniel Imms fbeb45d1da Merge pull request #2667 from Tyriar/2666_windows_cup
Flag lines as wrapped after CUP in windows mode
2020-01-07 09:20:58 -08:00
Daniel Imms be24cdb917 Merge branch 'master' into 2666_windows_cup 2020-01-07 09:16:25 -08:00
Daniel Imms 685d14c4d5 Improve windows mode method name 2020-01-07 09:16:16 -08:00
Daniel Imms c50cd4cc3e Flag lines as wrapped after CUP in windows mode
Fixes #2666
2020-01-07 09:15:04 -08:00
Jörg Breitbart e240160d39 break command definition on new @vt entry 2020-01-07 01:01:46 +01:00
Jörg Breitbart dae8c3599b make linter happy 2020-01-07 00:47:07 +01:00
Jörg Breitbart 7d8c0268ea remove unicodeVersion from options 2020-01-07 00:29:48 +01:00
Jörg Breitbart fc2df6cfd6 all multiple @vt in one multiline comment 2020-01-06 23:58:30 +01:00
Jörg Breitbart 5b2ccdbda7 make linter happy 2020-01-05 23:00:46 +01:00
Jörg Breitbart a0d724c186 move doc to impl 2020-01-05 22:41:36 +01:00
Jörg Breitbart aec2baa7e7 Merge branch 'master' into extract_vt_features 2020-01-05 21:38:21 +01:00
Jörg Breitbart 67bbbd8671 Merge branch 'master' into window_manipulation 2020-01-05 16:40:38 +01:00
Jörg Breitbart 3e1dbd4c39 fix api test 2020-01-04 15:39:00 +01:00
Jörg Breitbart df4b07f9f2 type fixes & docs 2020-01-04 14:47:14 +01:00
Daniel Imms bd4c2da37c Merge branch 'master' into updated_wcwidth 2020-01-03 07:23:44 -08:00
Daniel Imms 1c06e576ae Merge pull request #2663 from thefallentree/patch-1
Adding FluffOS to xtermjs user list
2020-01-03 07:17:16 -08:00
Yucong Sun 5d3629173f Merge branch 'master' into patch-1 2020-01-02 11:58:34 -08:00
Yucong Sun 5f25f40db9 Adding FluffOS to xtermjs user list 2020-01-02 11:57:45 -08:00
javacs3 a4efefbf5e refactor: serialize-addon, move SerializeAddon.benchmark.ts into addons/xterm-addon-serialize and add README.md 2019-12-31 22:06:19 +08:00
jerch 56e77d3106 Merge branch 'master' into updated_wcwidth 2019-12-29 11:21:55 +01:00
Daniel Imms 2a9e16bb8e Merge pull request #2654 from Tyriar/2646_attach_es6
Target es5 in attach addon
2019-12-27 08:37:46 -08:00
Daniel Imms c512485514 Target es5 in attach addon
Fixes #2646
2019-12-27 08:33:42 -08:00
jerch a0fb880ebc Merge branch 'master' into updated_wcwidth 2019-12-26 20:11:18 +01:00
jerch e52eafa7bb Merge pull request #2644 from jerch/fullwidth_erase
Correctly reset cells of previous fullwidth chars during buffer writes
2019-12-26 20:08:50 +01:00
Jörg Breitbart 9f8ea28db4 sanity checks in print wide char handling 2019-12-26 20:04:11 +01:00
Jörg Breitbart 1c1eaa6296 Merge branch 'master' into fullwidth_erase 2019-12-26 19:49:17 +01:00
Daniel Imms b32bfedde9 Merge pull request #2653 from Tyriar/2604_color_naming
Standardize how colors helper lib is structured
2019-12-27 03:22:54 +11:00
Daniel Imms f7d36a670c Merge pull request #2651 from Tyriar/2610_register_add
Use register over add for APIs returning disposables
2019-12-27 03:10:41 +11:00
Daniel Imms 37461c2a5a Merge branch 'master' into 2604_color_naming 2019-12-26 08:10:25 -08:00
Daniel Imms 5a17825b47 Merge pull request #2629 from ivanwonder/convert-color
format color value to style '#rrggbbaa'
2019-12-27 03:07:00 +11:00
Daniel Imms 761c25fa6d Merge pull request #2650 from Tyriar/2599_inverse_selection
Set glyph fg color based on original bg, not selection
2019-12-27 03:06:05 +11:00
Daniel Imms c40df65d13 Merge branch 'master' into convert-color 2019-12-27 03:02:58 +11:00
Daniel Imms 79860e7b15 Remove .only 2019-12-27 02:59:27 +11:00
Daniel Imms ca68a38f2c Merge branch 'master' into 2604_color_naming 2019-12-27 02:58:22 +11:00
Daniel Imms b075cc5e6f Merge branch 'master' into 2599_inverse_selection 2019-12-27 02:55:51 +11:00
Daniel Imms 3e3c51ae53 Add a test for selection
Part of #2600
2019-12-26 14:26:53 +11:00
Daniel Imms 28d7eddcb4 Set glyph fg color based on original bg, not selection
This involves resolving the rgb channels of the original background
color and encoding them using the RGB color mode.

Fixes #2599
2019-12-26 14:04:50 +11:00
Daniel Imms 509327b4c7 Use register over add for APIs returning disposables
Fixes #2610
2019-12-26 12:19:03 +11:00
Daniel Imms ee74130806 Standardize how colors helper lib is structured
Fixes #2604
2019-12-26 12:12:08 +11:00
Jörg Breitbart 0edbbf9fe0 fix print handler; tests 2019-12-21 23:07:12 +01:00
Jörg Breitbart 7ec658a3f8 apply erase attrs in handler methods 2019-12-21 21:57:39 +01:00
Jörg Breitbart 2b4da1f88e add wide char handling to bufferline primitives 2019-12-21 21:40:01 +01:00
Jörg Breitbart 84608256ea Merge branch 'master' into window_manipulation 2019-12-21 17:11:12 +01:00
Jörg Breitbart 0f8a034e8b make linter happy 2019-12-21 16:29:46 +01:00
Jörg Breitbart 0631323bf5 cleanup 2019-12-21 16:27:12 +01:00
Jörg Breitbart 825cc006e5 Merge branch 'master' into updated_wcwidth 2019-12-21 15:28:38 +01:00
Daniel Imms f1e01c7166 Merge pull request #2640 from Tyriar/reset_fix
Move back to reseting parser only on RIS
2019-12-20 06:26:50 +11:00
Daniel Imms 15e3173177 Move back to reseting parser only on RIS
Related #2637
2019-12-20 06:14:26 +11:00
javacs3 34bf2f9a0f refactor: serialize-addon, remove timeout in api test 2019-12-19 22:17:32 +08:00
Daniel Imms 71a78cbf01 Merge pull request #2637 from Tyriar/input_handler
Remove a large portion of InputHandler's dependency on Terminal
2019-12-19 18:45:13 +11:00
Daniel Imms 03fc6c3f97 Don't keep a reference to parent anymore 2019-12-19 16:04:15 +11:00
Daniel Imms e6c095754f Remove old params props from Terminal 2019-12-19 15:59:59 +11:00
Daniel Imms d045d39f88 Move charset service reset out of _setup 2019-12-19 15:58:27 +11:00
Daniel Imms 63bf719067 Merge branch 'master' into input_handler 2019-12-19 15:54:03 +11:00
Daniel Imms 34168bd223 Fix InputHandler resetting 2019-12-19 15:42:23 +11:00
Daniel Imms 4f3e3d9285 Merge pull request #2631 from cmeyer90/master
Added Gus to list of xterm real-world users
2019-12-19 15:20:47 +11:00
Daniel Imms c41f1c3d22 Merge branch 'master' into master 2019-12-19 15:20:23 +11:00
Daniel Imms 7d8086e138 Merge pull request #2636 from phillc/master
Add Linode to real world uses
2019-12-19 15:19:24 +11:00
Phillip Campbell 0727797254 Add Linode to real world uses 2019-12-18 09:05:29 -05:00
javacs3 7a8c3a42cd refactor: serialize-addon, rename some APIs in SerializeAddon 2019-12-18 20:27:44 +08:00
javacs3 84f5f20edb refactor: serialize-addon, remove equalFg(), equalBg(), equalFlags() api from xterm.d.ts 2019-12-18 20:27:39 +08:00
javacs3 b80b5a94f9 refactor: serialize-addon, rename _nextRow() to _rowEnd() 2019-12-18 20:27:33 +08:00
javacs3 a43cc23d67 refactor: serialize-addon, remove _cellFgBgChanged(), _cellFlagsChanged(), _lineStart() functions 2019-12-18 20:27:19 +08:00
javacs3 9e1f607bd9 fix: serialize-addon, remove unused packages in yarn.lock 2019-12-18 20:27:01 +08:00
Daniel Imms 914861503b Remove a bunch of unused interfaces 2019-12-18 12:06:41 +11:00
Daniel Imms 8e996ae571 Remove terminal.bell usage 2019-12-18 12:00:38 +11:00
Daniel Imms 5d351ec8c0 Isolate cast in TestInputHandler 2019-12-18 11:57:16 +11:00
Daniel Imms 33db0203dd Remove terminal.reset usage from input handler 2019-12-18 11:55:25 +11:00
Daniel Imms 7a1bef7daf More cur/erase attr data to input handler 2019-12-18 11:47:45 +11:00
Daniel Imms 2bbda38488 Remove redundant value reset
Done in core service reset
2019-12-18 11:31:08 +11:00
Daniel Imms e3e59c35fc Use optional chaining in InputHandler 2019-12-18 11:28:15 +11:00
Daniel Imms dc61fae12a Move applicationKeypad into core service 2019-12-18 11:23:57 +11:00
Daniel Imms dada7fe728 Move origin mode into core service 2019-12-18 11:20:36 +11:00
Daniel Imms bff74b1d7d Move wraparound mode into core service modes 2019-12-18 11:16:27 +11:00
Daniel Imms 224fb5c6a2 Move charset into own service 2019-12-18 10:53:05 +11:00
Daniel Imms 05e1cd8478 Move charset logic into core service 2019-12-18 10:32:38 +11:00
Daniel Imms a2297a5fa6 Remove Terminal.refresh usage in InputHandler 2019-12-18 10:30:49 +11:00
Daniel Imms 94f5c37884 Support events with 2 args
This will allow higher perf events by avoiding object creation
2019-12-18 09:59:33 +11:00
Clark Meyer ed334fd790 Added Gus to list of xterm real-world users 2019-12-14 21:59:43 -08:00
ivanwonder efb2069500 format color value to style '#rrggbbaa' 2019-12-13 10:57:42 +08:00
Daniel Imms 924526c1e6 Merge pull request #2628 from Tyriar/webgl_pub
Webgl v0.4.1
2019-12-12 09:48:55 +11:00
Daniel Imms 89995fe7ca Webgl v0.4.1 2019-12-11 14:47:26 -08:00
Daniel Imms 929914da5d Merge pull request #2626 from Tyriar/2634_texture_atlas
Expose texture atlas as API and use in demo
2019-12-12 09:45:19 +11:00
Daniel Imms 31669cbad6 Expose texture atlas as API and use in demo
Part of #2623
2019-12-11 14:26:12 -08:00
Daniel Imms a1e73331b8 Merge pull request #2625 from Tyriar/2596_hidden
Implement hidden in DOM and WebGL renderers
2019-12-10 23:07:30 -08:00
Daniel Imms 31da88ad89 Add webgl invisible tests 2019-12-09 19:47:47 -08:00
Daniel Imms 93cdee3bab Support hidden in WebGL renderer
Fixes #2596
2019-12-09 19:39:59 -08:00
Daniel Imms ed7d8e7c3b Support hidden attr in DOM renderer 2019-12-09 19:37:12 -08:00
Daniel Imms 050d9ff04d Merge pull request #2621 from jerch/update_nodepty
update version of node-pty
2019-12-08 10:46:25 -08:00
jerch 512076898d Merge branch 'master' into window_manipulation 2019-12-08 18:58:57 +01:00
Jörg Breitbart a628e427de update version of node-pty 2019-12-08 18:46:40 +01:00
Daniel Imms 05f1887559 Merge branch 'master' into updated_wcwidth 2019-12-07 13:32:13 -08:00
Daniel Imms 266859edf3 Merge pull request #2590 from npezza93/configure-cursor-bar-width
Allow the thickness of the bar cursor to be configured
2019-12-07 13:30:17 -08:00
Daniel Imms 79ea49cafd Floor cursorWidth to ensure it's an integer 2019-12-07 13:25:59 -08:00
Nick Pezza 3cb67f2806 Merge branch 'master' into configure-cursor-bar-width 2019-12-07 15:54:35 -05:00
Nick Pezza fa4de08934 Apply changes to the dom renderer 2019-12-07 15:54:17 -05:00
Nick Pezza 70c8f8733a Sanitize cursorWidth option 2019-12-07 15:42:33 -05:00
Nick Pezza 97dc61e65f s/cursorBarWidth/cursorWidth 2019-12-07 15:40:02 -05:00
Nick Pezza 48aebec01f Remove default width value 2019-12-07 15:39:34 -05:00
Nick PezzaandDaniel Imms 58078459f8 Update cursor width doc
Co-Authored-By: Daniel Imms <tyriar@tyriar.com>
2019-12-07 15:38:12 -05:00
Daniel Imms fb9b19b95e Merge remote-tracking branch 'ups/feat/serialize-addon' into pr/JavaCS3/2369 2019-12-07 10:27:11 -08:00
Daniel Imms 7af6cf450b Merge remote-tracking branch 'origin/master' into feat/serialize-addon 2019-12-07 10:26:38 -08:00
Daniel Imms ca12cf5802 Support serializing tabs 2019-12-07 10:24:22 -08:00
Jörg Breitbart d7737f6c88 cleanup 2019-12-07 13:39:06 +01:00
Jörg Breitbart b5fdd3b8d8 several fixes 2019-12-07 13:23:00 +01:00
Jörg Breitbart 5b95f7e565 Merge branch 'window_manipulation' of github.com:jerch/xterm.js into window_manipulation 2019-12-07 12:26:51 +01:00
Jörg Breitbart be3f3da532 Merge branch 'master' into window_manipulation 2019-12-07 12:26:31 +01:00
Jörg Breitbart f13e52fffb Merge branch 'master' into updated_wcwidth 2019-12-07 12:21:18 +01:00
Daniel Imms ab66cb5d26 Merge pull request #2616 from sdegutis/patch-1
Avoid roundtrip to browser when double-disposing.
2019-12-06 16:18:30 -08:00
Jörg Breitbart 878b762537 Merge branch 'master' into updated_wcwidth 2019-12-06 23:17:09 +01:00
Steven Degutis c5e144f327 Avoid roundtrip to browser when double-disposing. 2019-12-06 15:57:26 -06:00
Jörg Breitbart 92ac99e878 cleanup 2019-12-06 20:41:24 +01:00
Jörg Breitbart 70dabf11db fix failing tests 2019-12-06 17:00:46 +01:00
Jörg Breitbart 0f83d645b6 remove V11 from base repo 2019-12-06 16:46:50 +01:00
Jörg Breitbart 794573969c remove CharWidth.ts 2019-12-06 16:44:20 +01:00
Jörg Breitbart 303abf8a91 unicode11 addon 2019-12-06 16:28:16 +01:00
Daniel Imms bd0d267d97 Merge pull request #2605 from Tyriar/r43
v4.3.0
2019-12-05 12:40:34 -08:00
Daniel Imms c9babb9477 v4.3.0 2019-12-05 12:34:36 -08:00
Jörg Breitbart 43303ba4c1 add interfaces and option handling 2019-12-05 21:30:59 +01:00
Jörg Breitbart 31ccb796ac Merge branch 'master' into updated_wcwidth 2019-12-05 15:45:52 +01:00
Jörg Breitbart 3395ccb943 UnicodeService & provider 2019-12-05 15:42:55 +01:00
Daniel Imms 17cb610ef1 Merge pull request #2602 from Tyriar/fix_dom
Fix minimumContrastRatio on dom/truecolor
2019-12-04 10:59:01 -08:00
Daniel Imms 543b3d6c9f Fix minimumContrastRatio on dom/truecolor
Fixes #2593
2019-12-04 10:54:17 -08:00
Nick Pezza c630b92772 Allow the thickness of the bar cursor to be configured 2019-11-30 14:40:45 -05:00
javacs3 903d75e6d3 Refactor
1. add 8 secs timeout for SerializeAddon API test
2. move demo page's addons control panel into a single div
3. remove unnecessary config in demo page
4. remove v8-profiler-node8 dependency
5. remove duplicate css option
2019-11-28 22:22:04 +08:00
Daniel Imms 0be6d9f048 Merge branch 'master' into window_manipulation 2019-11-26 08:08:28 -08:00
Jörg Breitbart a574591481 Merge branch 'updated_wcwidth' of github.com:jerch/xterm.js into updated_wcwidth 2019-11-26 02:04:36 +01:00
Jörg Breitbart 435d480cf1 unicode service stub 2019-11-26 01:59:10 +01:00
Daniel Imms 8b5c48fe87 Merge pull request #2560 from ivanwonder/reverse-transparency
force alpha to 1 when using background color as inverted foreground color
2019-11-25 15:10:59 -08:00
Daniel Imms 1ff1809ab7 Support opaque inverse background in webgl, add test 2019-11-25 15:06:28 -08:00
Daniel Imms ef05a6a053 Draw transparent background in WebGL renderer
Part of #2252
2019-11-25 14:33:12 -08:00
Daniel Imms bceddfbc28 Cover inverse non-black uncached case in canvas renderer 2019-11-25 14:22:03 -08:00
Daniel Imms 4cd8b22a59 Use toRgba helper 2019-11-25 11:58:26 -08:00
Daniel Imms 1a5c3f9364 Properly set non-black transparency backgrounds
Before it was always set to 0 as the resolved color was pulled from
an ImageData
2019-11-25 11:57:52 -08:00
Daniel Imms cbb8dc7780 Merge remote-tracking branch 'ups/master' into pr/ivanwonder/2560 2019-11-25 11:14:03 -08:00
Daniel Imms 3b1479a02b Merge pull request #2585 from Tyriar/unused
Remove unused imports/functions
2019-11-25 09:24:20 -08:00
Daniel Imms afe6cb6b86 Remove unused imports/functions 2019-11-25 09:12:39 -08:00
Daniel Imms 2173a5399d Merge pull request #2583 from xtermjs/Tyriar-patch-1
Include ` in word separators
2019-11-25 07:50:10 -08:00
Daniel Imms 25f2e66222 Include ` in word separators
See microsoft/vscode#84483
2019-11-25 07:36:06 -08:00
Daniel Imms 397d053e06 Merge pull request #2582 from Tyriar/2581_cursor
Mark before and after cursor rows dirty when changed
2019-11-24 11:22:47 -08:00
Daniel Imms 217bc24235 Mark before and after cursor rows dirty when changed
The DOM renderer renders the cursor as part of the content, not on a
separate layer, so it needs to be marked dirty to draw.

Fixes #2581
2019-11-24 11:15:28 -08:00
Daniel Imms 3969eb9382 Add failing tab test 2019-11-24 10:20:19 -08:00
Daniel Imms 45af02590e Make serialize addon api tests fast 2019-11-24 10:15:38 -08:00
Daniel Imms 709214a414 Add webpacked version to client 2019-11-24 10:06:41 -08:00
Daniel Imms 6dda0c2b97 Merge branch 'feat/serialize-addon' into pr/JavaCS3/2369 2019-11-24 10:05:14 -08:00
Daniel Imms 20578e0a43 Merge remote-tracking branch 'origin/master' into feat/serialize-addon 2019-11-24 09:55:31 -08:00
Daniel Imms 4d2afce5f2 Merge pull request #2580 from Tyriar/puppeteer_release
Skip puppeteer download during release job
2019-11-24 09:47:18 -08:00
Daniel Imms 2da5a7a26b Skip puppeteer download during release job 2019-11-24 09:42:33 -08:00
Daniel Imms fffbec7294 Merge pull request #2579 from Tyriar/publish_fix
Fix publish script for dot separated beta
2019-11-24 09:35:44 -08:00
Daniel Imms c60b822f4b Fix publish script for dot separated beta 2019-11-24 09:34:29 -08:00
Daniel Imms 2882ae76ef Merge pull request #2578 from Tyriar/85048
Don't throw when rendering before atlas is set
2019-11-24 09:26:13 -08:00
Daniel Imms 53fb1ba54d Don't throw when rendering before atlas is set
This fixes a problem when loading the webgl addon before the terminal
is attached.

See microsoft/vscode#85048
2019-11-24 09:22:07 -08:00
jerch 5a1e8484a9 Merge branch 'master' into window_manipulation 2019-11-23 17:37:38 +01:00
Daniel Imms 40d8b606a3 Merge pull request #2577 from Tyriar/beta_dot
Add a . before beta and beta version
2019-11-22 19:38:47 -08:00
Daniel Imms 2f1f2f8785 Add a . before beta and beta version
Fixes #2576
2019-11-22 19:37:55 -08:00
Daniel Imms 1300b7a6b7 Merge pull request #2575 from Tyriar/webgl_exception
Prevent atlas missing exception when opened before attach
2019-11-22 16:06:30 -08:00
Daniel Imms 0bd0f3a364 Prevent atlas missing exception when opened before attach
See microsoft/vscode#85048
2019-11-22 16:00:25 -08:00
Daniel Imms c0da45113f Merge pull request #2574 from Tyriar/question
Direct question issues to Stack Overflow
2019-11-22 09:39:03 -08:00
Daniel Imms 93487d4fb3 Direct question issues to Stack Overflow 2019-11-22 09:34:06 -08:00
javacs3 1093b7c3d3 fix lint error 2019-11-21 20:53:53 +08:00
javacs3 7ec99c2469 update IBufferCell API 2019-11-21 20:41:48 +08:00
javacs3 3543155953 fix typo 2019-11-21 20:41:48 +08:00
javacs3 e2df7dc96c add benchmark for serialize addon 2019-11-21 20:41:48 +08:00
javacs3 cd5f3e9740 update cell color api design 2019-11-21 20:41:47 +08:00
javacs3 ae70ef0fa2 resolve SerializeAddon importing workaround 2019-11-21 20:41:47 +08:00
javacs3 f1a17e3cf5 refactor CellColor constructor 2019-11-21 20:41:47 +08:00
javacs3 22a2496360 fix 'Can't resolve 'xterm' in xterm.js/addons/xterm-addon-serialize/out' 2019-11-21 20:41:47 +08:00
javacs3 7a7f3466f3 refactor ICellColor to CellColor 2019-11-21 20:41:47 +08:00
javacs3 73f9d45fdc refactor use a nicer IBufferCell design 2019-11-21 20:41:47 +08:00
javacs3 3cba961dad refactor SerializeAddon: use public api as much as possible 2019-11-21 20:41:47 +08:00
javacs3 6710c13cc2 fix cell.getFgColor/getBgColor return color256 code even it's color16
mode leading to serialize return wrong sequence
2019-11-21 20:41:47 +08:00
javacs3 f12120b055 fix demo page <code> tag won't display multi space chars 2019-11-21 20:41:46 +08:00
javacs3 693f30477e add trim last empty lines support for SerializeAddon 2019-11-21 20:41:46 +08:00
javacs3 92709110ef add SerializeAddon in demo page 2019-11-21 20:41:46 +08:00
javacs3 d81b4999dc add frontground/background color support for SerializeAddon 2019-11-21 20:41:46 +08:00
javacs3 f088a9953f refactor SerializeAddon extract SerializeHandler 2019-11-21 20:41:46 +08:00
javacs3 a069df7a36 refactor SerializeAddons initial value validation 2019-11-21 20:41:46 +08:00
jerch 7f26b04ea1 Merge branch 'master' into window_manipulation 2019-11-16 00:05:42 +01:00
jerch f81cca67eb Merge branch 'master' into updated_wcwidth 2019-11-16 00:03:45 +01:00
Daniel Imms 70babeacb6 Merge pull request #2569 from Tyriar/layers6
Move WindowsMode to common/
2019-11-15 10:27:55 -08:00
Daniel Imms 12e9dce6c7 Merge pull request #2563 from Tyriar/322_minimum_contrast
Implement minimum contrast ratio
2019-11-15 10:24:35 -08:00
Jörg Breitbart aca6d24e96 change to v11, expose unicodeVersion, fix linkifier 2019-11-15 18:08:17 +01:00
Jörg Breitbart 25bbde2be2 cleanup CharWidth.ts 2019-11-15 14:47:51 +01:00
Jörg Breitbart c7ad4aa460 terminal option unicodeVersion 2019-11-15 13:33:28 +01:00
Daniel Imms 943928c4d1 Move WindowsMode to common/
Part of #1507
2019-11-14 22:26:26 -08:00
Daniel Imms 5aa3157672 Return inverse colors correctly
This probably wasn't causing a bug since the opposite values were
being returned, it was wrong and made the code confusing though.
2019-11-14 22:12:36 -08:00
Daniel Imms e5f4e2ff8f Support min contrast ratio in canvas renderer too: 2019-11-14 22:07:50 -08:00
Daniel Imms c95337a742 Remove unneeded params from webgl funcs 2019-11-14 21:57:15 -08:00
Daniel Imms 023fab9095 Remove unused import 2019-11-14 20:34:01 -08:00
Daniel Imms cc9f649e3a Merge branch 'master' into 322_minimum_contrast 2019-11-14 20:14:17 -08:00
Daniel Imms be9700878b Have inverse bold respect drawBoldTextInBrightColors 2019-11-14 20:02:40 -08:00
Daniel Imms 24dc87af2c Only enter updateBackgounds condition if cell changed
We want to check when the background changed or when the foreground
changed (and either the old or new value was inverse)
2019-11-14 19:46:24 -08:00
Jörg Breitbart 9c9aa68c23 wcwidth rules unicode 10 2019-11-15 01:07:14 +01:00
jerch 6cc6cb5ffd Merge branch 'master' into window_manipulation 2019-11-14 22:43:51 +01:00
jerch c99a096d52 Merge pull request #2566 from jerch/binary_event
onBinary event
2019-11-14 22:39:32 +01:00
Jörg Breitbart 57fe84508c apply empty report rule to all encodings; comments added 2019-11-14 22:29:46 +01:00
Jörg Breitbart 7ad2a68052 cleanup 2019-11-14 13:05:24 +01:00
Jörg Breitbart 8991ed8270 simplify options 2019-11-14 12:59:48 +01:00
Jörg Breitbart 45d1139ab0 windowOptions on ctor options 2019-11-14 12:20:59 +01:00
Jörg Breitbart 26052a2963 fix api test 2019-11-14 11:38:18 +01:00
Jörg Breitbart eeb9270882 change WindowOptions type 2019-11-14 11:23:21 +01:00
Jörg Breitbart 8fc2d22b28 add IWindowOptions to xterm.d.ts 2019-11-14 10:20:51 +01:00
Jörg Breitbart f1f103850c fix tests; fix attach addon 2019-11-14 00:48:16 +01:00
Jörg Breitbart 00d626b6cc add onBinary to interfaces 2019-11-13 23:57:51 +01:00
Jörg Breitbart b780abaf3b add onBinary on CoreService, use for DEFAULT mouse reports 2019-11-13 23:46:01 +01:00
Jörg Breitbart d09e2fbcec stub for window options 2019-11-13 23:09:52 +01:00
Daniel Imms 7652cd8af3 Use hash notation over rgb() for dom colors 2019-11-13 06:59:50 -08:00
Daniel Imms 579d74ee33 jsdoc rgbRelativeLuminance2 2019-11-13 06:53:29 -08:00
Daniel Imms 2c959dfb2e Keep a working AttributeData in WebglCharAtlas 2019-11-13 06:52:17 -08:00
Daniel Imms 20b0a95bb0 Add tests for ensureContrastRatioRgba 2019-11-12 11:05:58 -08:00
Daniel Imms db090c70de Add unit tests for ColorContrastCache 2019-11-12 10:21:23 -08:00
Daniel Imms d1f7d2ef6a Tweak readme to call out min contrast ratio 2019-11-12 10:10:55 -08:00
Daniel Imms 56d12fe846 Fix color manager unit test 2019-11-12 10:09:32 -08:00
Daniel Imms b0c3606207 Add example values to .d.ts 2019-11-12 10:03:38 -08:00
Daniel Imms 032185f8b0 Link webgl directly to browser/Color 2019-11-12 10:00:40 -08:00
Daniel Imms b3f439af09 Remove unused imports 2019-11-12 09:55:09 -08:00
Daniel Imms 647cff53db Lint 2019-11-12 09:53:42 -08:00
Daniel Imms 3b0042fd46 Remove log 2019-11-12 09:46:07 -08:00
Daniel Imms 8a0122f482 Add contrast caching to webgl 2019-11-12 09:42:55 -08:00
Daniel Imms faaa07be68 Add contrast caching for DOM renderer 2019-11-12 09:33:50 -08:00
Daniel Imms c2474626f0 Clear setting as part of run 2019-11-12 09:07:08 -08:00
Daniel Imms f5774fdc70 Merge branch 'master' into 322_minimum_contrast 2019-11-12 08:53:25 -08:00
Daniel Imms ca5cee7e86 Fix contrast tests 2019-11-12 08:53:06 -08:00
Jörg Breitbart 2797faae6f Merge branch 'master' into window_manipulation 2019-11-12 17:05:01 +01:00
Daniel Imms 5ee9bcf2b5 Remove .only 2019-11-11 23:23:33 -08:00
Daniel Imms 6626f9628d Use ceil in both 2019-11-11 23:14:27 -08:00
Daniel Imms 2fc1791dde Fix floor/ceil in luminance methods 2019-11-11 23:11:36 -08:00
Daniel Imms 414eea2a2c Merge pull request #2562 from AndrewSverdrup/change-codevolve-to-next-tech
Update Codevolve to Next Tech
2019-11-11 22:56:35 -08:00
Daniel Imms 9b139a744b Add test for min contrast on white bg 2019-11-11 22:55:08 -08:00
Daniel Imms 531409c2c7 Support minimum contrast ratio in webgl 2019-11-11 22:47:26 -08:00
Daniel Imms 2283ea45a6 Refresh rows after ratio changes 2019-11-11 22:18:39 -08:00
Daniel Imms db775afd70 Support drawBoldTextInBrightColors in webgl again
This broke as part of this PR
2019-11-11 21:35:51 -08:00
Daniel Imms b1bcb899e0 Fix inverse in webgl, add tests 2019-11-11 21:29:02 -08:00
Daniel Imms a6dcb21f1c Fix tests 2019-11-11 19:30:36 -08:00
Daniel Imms 9cd66e72bb Add tests for relative luminance 2019-11-11 19:14:35 -08:00
Daniel Imms e46ff9ec85 Add minimumContrastRatio to DOM renderer
Part of #322
2019-11-11 19:03:12 -08:00
ivanwonder fd868044fd add a helper to make color opaque 2019-11-12 10:06:51 +08:00
Andrew Sverdrup dfc1664d6e Update Codevolve to Next Tech
We changed our name several months back.
2019-11-11 13:23:59 -08:00
Daniel Imms e911656306 Merge pull request #2561 from xtermjs/Tyriar-patch-1
Prefer non-relative imports
2019-11-11 10:54:15 -08:00
Daniel Imms 25f9487239 Prefer non-relative imports
Fixes some auto imports in VS Code, see microsoft/TypeScript#32144
2019-11-11 10:24:54 -08:00
Daniel Imms 339d4d6a73 Merge pull request #2559 from xtermjs/Tyriar-patch-1
Generate coverage report for pipelines
2019-11-10 21:43:41 -08:00
Daniel Imms 94afd1fa38 Generate coverage report for pipelines 2019-11-10 21:38:43 -08:00
ivanwonder 5bc80fdf67 force alpha to 1 when using background color as inverted foreground color. 2019-11-11 11:01:32 +08:00
Daniel Imms 03fe1677b6 Merge pull request #2558 from Tyriar/force_build
Whitespace to force a webgl release
2019-11-10 12:07:01 -08:00
Daniel Imms 6b7e29ea32 Whitespace to force a webgl release 2019-11-10 12:06:20 -08:00
Daniel Imms 9eeb5aac32 Merge pull request #2557 from Tyriar/fix_release
Correct import in Color.ts
2019-11-10 11:49:12 -08:00
Daniel Imms 450a626218 Correct import in Color.ts 2019-11-10 11:48:32 -08:00
Daniel Imms a8ff27ceb9 Merge pull request #2552 from Tyriar/webgl_compat_attr
True color support in WebGL renderer
2019-11-10 11:37:26 -08:00
Daniel Imms e89d79b879 Remove unused code 2019-11-10 11:33:41 -08:00
Daniel Imms 734bd8c96a Factor out toRgba function and test 2019-11-10 11:30:48 -08:00
Daniel Imms 2da77dd5f8 Use opaque selection in webgl, fix selection default rgba 2019-11-10 11:23:34 -08:00
Daniel Imms 51c77568a8 Add tests for Color functions 2019-11-10 11:17:36 -08:00
Daniel Imms 53b0149764 Add selectionOpaque and factor out color into new file 2019-11-10 11:11:26 -08:00
Daniel Imms 2b2bd91e2e Add background true color tests 2019-11-10 10:41:30 -08:00
Daniel Imms 350ca8d5fb Organize tests 2019-11-10 10:39:56 -08:00
Daniel Imms 753ad30dbc Add true color fg tests for webgl 2019-11-10 10:38:23 -08:00
Daniel Imms 8bf837795f Add tests for webgl colors 16-255 2019-11-10 10:29:50 -08:00
Daniel 01628362f5 Support selection color 2019-11-10 01:19:27 -08:00
Daniel 811307562b Use actual default color for rectangle renderer 2019-11-10 00:59:11 -08:00
Daniel Imms 98fe63051d Merge branch 'master' into webgl_compat_attr 2019-11-10 00:53:42 -08:00
Daniel Imms adc631d192 Merge pull request #2553 from Tyriar/retry
Add retries to onRender test
2019-11-10 00:53:36 -08:00
Daniel 2cde011397 Add retries to onRender test
I've seen this flaky locally and in CI
2019-11-10 00:49:10 -08:00
Daniel b56e29a35b Import clean up 2019-11-10 00:39:46 -08:00
Daniel 149cc76803 Avoid extra object creation for foreground fill 2019-11-10 00:30:58 -08:00
Daniel b13e9066bd Use a switch for color mode conditions 2019-11-10 00:29:50 -08:00
Daniel a2da8f9fbb Fix true color glyphs not having background cleared 2019-11-10 00:23:08 -08:00
Daniel 3773b22439 Support true color... mostly 2019-11-09 23:41:00 -08:00
Daniel 39f0e17edf Consolidate constants, fix rectangle rendering 2019-11-09 23:05:39 -08:00
Daniel 2b5d229aab Reduce size of model to 3 by removing attr 2019-11-09 22:56:42 -08:00
Daniel a2bd0e8eaa Remove attr compat from webgl 2019-11-09 22:50:22 -08:00
Daniel 9dd2ccb1ad Fix selection color to set correct mode 2019-11-09 22:48:28 -08:00
Daniel e15476704c Adopt new [bg][fg] map in char cache 2019-11-09 22:43:25 -08:00
Daniel 8f0f8bf827 Remove cache reliance on flags 2019-11-09 22:31:10 -08:00
Daniel e72ee3c58d Move webgl drawing over from compat
Still need to tackle glyph key
2019-11-09 22:28:59 -08:00
Daniel 8a6e0fca07 Move parts over to CellData 2019-11-09 21:15:07 -08:00
Daniel Imms 87d2015793 Merge pull request #2551 from Tyriar/puppeteer_slowmo
Make integration tests very fast by removing slowMo
2019-11-09 19:14:31 -08:00
Daniel Imms 40b3766abc Fix import that got lost in merge 2019-11-09 19:05:20 -08:00
Daniel Imms 0c69b68b4c Merge branch 'master' into puppeteer_slowmo 2019-11-09 19:02:55 -08:00
Daniel Imms 641b5f867b Merge pull request #2548 from Tyriar/2254_webgl_dispose
Implement webgl renderer dispose
2019-11-09 19:01:52 -08:00
Daniel Imms 057d0a16f2 Ensure link hover exists before hovering 2019-11-09 18:54:24 -08:00
Daniel Imms 669622108c Wait for all elements to be rendered in web links 2019-11-09 18:48:09 -08:00
Daniel Imms 971e69f505 Reduce flakiness 2019-11-09 18:43:25 -08:00
Daniel Imms b0640b7705 Remove slowMo param everywhere 2019-11-09 18:28:50 -08:00
Daniel Imms 7ff6e4f493 Fix flaky terminal api tests 2019-11-09 18:28:24 -08:00
Daniel Imms 34e703e472 Fix most of Terminal.api timing issues 2019-11-09 17:29:32 -08:00
Daniel Imms 17677568f9 Fix timing issues in mouse tracking tests 2019-11-09 14:16:57 -08:00
Daniel Imms 2aaa997d39 Fix timing issues in input handler 2019-11-09 14:15:16 -08:00
Daniel Imms 74f04ae92e Fix timing issues in char width test 2019-11-09 14:12:46 -08:00
Daniel Imms b0c0f8701e Fix timing issues in webglrenderer 2019-11-09 14:08:37 -08:00
Daniel Imms d3bf013ceb Fix timing issues in web links addon tests 2019-11-09 13:57:42 -08:00
Daniel Imms 840e56cf1e Fix Attach tests 2019-11-09 11:30:45 -08:00
Daniel Imms b8acdd6e67 Remove slowmo from puppeteer 2019-11-09 11:15:15 -08:00
Daniel Imms 60bda1bbd3 Fix tests hanging 2019-11-09 11:04:55 -08:00
Daniel Imms e4b50d505c Merge pull request #2550 from Tyriar/2549_refresh_options
Refresh rows on options change for all renderers
2019-11-09 10:37:28 -08:00
Daniel Imms 22f4342194 Move options row refresh into render service 2019-11-09 10:07:24 -08:00
Daniel Imms 8adbed84b0 webgl: Refresh rows on options change
Fixes #2549
2019-11-09 09:34:40 -08:00
Daniel Imms d09ac41f75 After tests wait for browser close 2019-11-09 09:29:04 -08:00
Daniel Imms 2aec4e6d29 Add a test for removing canvases 2019-11-09 09:27:30 -08:00
Daniel Imms bcd4c766d6 Implement webgl renderer dispose
Fixes #2254
2019-11-09 09:09:59 -08:00
Jon Bockhorst a1906347b0 Only clear link if it was in the range of onRender and fix tests 2019-11-08 12:10:00 -06:00
Jon Bockhorst 8924aa736e Use onRender() instead of onData() and onScroll() 2019-11-08 11:08:50 -06:00
Daniel f93939ef20 Merge remote-tracking branch 'ups/master' into pr/jmbockhorst/2530 2019-11-08 08:46:09 -08:00
Jon Bockhorst 700c4acf75 Rework link parser to use a single cached link and make other requested changes 2019-11-08 02:14:53 -06:00
Daniel Imms b68a4d27ab Merge pull request #2547 from Tyriar/layering5
Move remaining renderer parts into browser
2019-11-07 21:42:53 -08:00
Daniel Imms 939dcca5bb Merge branch 'master' into layering5 2019-11-07 21:22:06 -08:00
Daniel Imms 3bf149bbc5 Fix webgl cursor 2019-11-07 18:46:56 -08:00
Daniel Imms 3f7238d9dc Move Renderer to browser 2019-11-07 18:45:13 -08:00
Daniel Imms 873de2b127 Move cursor render layer to browser 2019-11-07 18:39:46 -08:00
Daniel Imms c204ab00e0 Move cursorHidden into core service 2019-11-07 18:22:18 -08:00
Daniel Imms 9d7935f8bd Move cursorState into core service 2019-11-07 18:21:06 -08:00
Daniel Imms 1e1038b2c7 Remove renderer circular dep on renderservice
Also fix super.dispose not being called correctly on RenderService
2019-11-07 18:09:40 -08:00
Daniel Imms 509d0e7019 Remove some ITerminal usage from Renderer 2019-11-07 17:44:03 -08:00
Daniel Imms 82e18d7aaa Move DomRenderer to browser, fix strict errors 2019-11-07 17:41:29 -08:00
Daniel Imms 7c39217392 Break DomRenderer dependency on ITerminal
Part of #1507
2019-11-07 17:35:22 -08:00
Daniel Imms dd4eb7bdec Merge pull request #2532 from glneto/2444
#2444: Fix wrapped lines search
2019-11-07 16:49:24 -08:00
Daniel Imms e84469d140 Merge pull request #2546 from Tyriar/polish_pipelines
Reduce duplicate in pipeline, cache in release job
2019-11-07 16:48:29 -08:00
Daniel Imms 1d63be0506 Reduce duplicate in pipeline, cache in release job 2019-11-07 13:52:39 -08:00
Daniel Imms fce7a67c8e Remove type jsdoc 2019-11-07 13:39:42 -08:00
Daniel Imms 94ce037eb8 Add integration tests for regression in #2444 2019-11-07 13:00:43 -08:00
Daniel Imms aad32e9943 Merge branch 'master' into 2444 2019-11-07 12:20:33 -08:00
Jon Bockhorst f18a6fe1eb Fixed bug in link detection for wrapped links 2019-11-06 22:52:09 -06:00
Daniel Imms 16409da517 Merge pull request #2541 from Tyriar/2539
Skip puppeteer download on unit test runs, fix windows tests, polish pipeline
2019-11-06 11:52:45 -08:00
Daniel Imms 0878294964 Skip Terminal2 tests on Windows 2019-11-06 11:24:34 -08:00
Daniel Imms 31afe5b305 test-coverage -> test-unit-coverage 2019-11-06 11:23:42 -08:00
Daniel Imms fe2f1ea4df Get Windows unit tests running again
Fixes #2543
2019-11-06 11:20:52 -08:00
Daniel Imms 48b20e3200 Don't run through nyc on mac and Windows 2019-11-06 11:08:47 -08:00
Daniel Imms 030a8bda80 Set coverage lines threshold to 60% 2019-11-06 11:08:39 -08:00
Daniel Imms d079775690 Merge coverage check into regular unit test check
Fixes #2542
2019-11-06 11:04:37 -08:00
Daniel Imms d4dbdac73f Don't cache integration test modules 2019-11-06 10:53:42 -08:00
Daniel Imms fc0568074f Cache node modules with puppeteer 2019-11-06 10:37:00 -08:00
Jon Bockhorst b07a6d10f1 Add test for multiline links 2019-11-05 23:44:30 -06:00
Jon Bockhorst ac6c8a5bd3 Support multiline links in the WebLinksAddon 2019-11-05 23:35:20 -06:00
Jon Bockhorst b3d95d20dc Merge branch 'master' of https://github.com/xtermjs/xterm.js into linkParser 2019-11-05 16:35:33 -06:00
Daniel Imms 0630baaf02 Don't cache on integration tests 2019-11-05 12:50:37 -08:00
Daniel Imms c974b273d4 Install puppeteer explicitly 2019-11-05 12:41:03 -08:00
Daniel Imms d2164584d5 Fix error in yml 2019-11-05 11:56:44 -08:00
Daniel Imms 2960d5df53 New cache key 2019-11-05 11:55:06 -08:00
Daniel Imms 5411f60f44 Try cache node_modules 2019-11-05 11:54:32 -08:00
Daniel Imms 86264d4763 Specify yarn cache folder 2019-11-05 11:42:35 -08:00
Daniel Imms 70500e31ac Add yarn cache caching 2019-11-05 11:36:54 -08:00
Daniel Imms 3dca46619c Skip puppeteer download on unit test runs
Fixes #2539
2019-11-05 11:33:39 -08:00
Daniel Imms 7f598a3675 Merge pull request #2540 from Tyriar/ts37
Update TS to 3.7 and adopt optional chaining
2019-11-05 11:22:11 -08:00
Daniel Imms 843d5ff53c Adopt optional chaining 2019-11-05 11:09:47 -08:00
Jon Bockhorst 28c43ac2bf Remove link caching 2019-11-05 13:01:53 -06:00
Daniel Imms 267fbc7f5e typescript@3.7 and fix errors 2019-11-05 10:54:02 -08:00
Jon Bockhorst fdfadfefbc Fixed link caching errors 2019-11-04 23:37:05 -06:00
Daniel Imms d259cd7332 Merge pull request #2536 from Tyriar/parse_rows
Only refresh rows that changed during parsing
2019-11-04 11:31:50 -08:00
Daniel Imms 1afffba1d8 Only refresh rows that changed during parsing
Fixes #2534
2019-11-04 11:00:19 -08:00
Geraldo Neto 9358718b5f 2444: Fix no-else-return lint 2019-11-02 19:33:21 -03:00
Geraldo Neto 8667237525 Merge branch '2444' of https://github.com/glneto/xterm.js into 2444 2019-11-02 19:22:09 -03:00
Geraldo Neto 9d50d106e3 2444: Return after calculating startCol in reverse search 2019-11-02 19:21:58 -03:00
Geraldo Neto d53215480a Merge branch 'master' into 2444 2019-11-02 19:14:01 -03:00
Geraldo Neto 1f4780a71a #2444: Fix wrapped lines search 2019-11-02 18:58:04 -03:00
Jon Bockhorst e57cb8bf7e Use regex parser for web links 2019-11-01 17:38:08 -05:00
Jon Bockhorst ec78fc7e7c Remove usage of ! operator 2019-11-01 13:42:02 -05:00
Jon Bockhorst cf082cca04 Fix links when viewport is scrolled 2019-11-01 11:24:21 -05:00
Jon Bockhorst 1e877a0f96 Fix lint errors 2019-11-01 09:18:45 -05:00
Jon Bockhorst 3e2e4ace48 Removed file detection from WebLinkProvider 2019-11-01 01:05:18 -05:00
Jon Bockhorst 0c5962c538 Added support for a basic link parser 2019-11-01 00:54:31 -05:00
Daniel Imms bc9649bfbc Merge pull request #2527 from xtermjs/Tyriar-patch-1
Change to tracking lines in code coverage
2019-10-31 12:23:07 -07:00
Daniel Imms fbb9ef9f7f Change to tracking lines in code coverage 2019-10-31 11:59:04 -07:00
Daniel Imms e8153d929d Merge pull request #2525 from Tyriar/az
Polish pipeline config and add coverage reporting
2019-10-30 21:18:06 -07:00
Daniel 08b10ba651 Add note about unit test coverage in contributing 2019-10-30 21:15:23 -07:00
Daniel 39c0fdb54a Remove report directory 2019-10-30 20:31:40 -07:00
Daniel a450bd52d7 Generate and publish coverage report to pipelines 2019-10-30 20:18:32 -07:00
Daniel 79f3a7343c Don't wrap for single line scripts 2019-10-30 20:07:41 -07:00
Daniel 6c2b34a5c8 Use YarnInstaller 2019-10-30 20:03:53 -07:00
Daniel Imms 80e44f4978 Merge pull request #2518 from Tyriar/2407_toggle_addons
Support check boxes in demo to toggle addons
2019-10-29 14:49:23 -07:00
Jörg Breitbart 98cc17df24 remove leftover .only 2019-10-29 15:57:11 +01:00
Jörg Breitbart 2cad586ccc add integration tests for pixel reports 2019-10-29 15:50:54 +01:00
Jörg Breitbart da3ae79c37 implement 14, 16, 18, 20, 21, 22, 23; restrict DECCOLM to 24 2019-10-29 13:57:36 +01:00
jerch 38f05dabe2 Merge branch 'master' into window_manipulation 2019-10-29 08:28:02 +01:00
Daniel Imms 5b555bacc0 Merge pull request #2521 from alberto/patch-1
Fix typos
2019-10-28 07:28:32 -07:00
alberto cb1cf3cd11 Fix grammar 2019-10-27 22:50:22 +01:00
alberto b880cd3ad3 Fix punctuation mark 2019-10-27 22:43:26 +01:00
alberto ffe2d66aff Remove duplicated punctuation 2019-10-27 22:38:55 +01:00
alberto fe2ac04b85 Fix grammar 2019-10-27 22:34:54 +01:00
alberto 8d0fdc8731 Fix grammar 2019-10-27 22:29:36 +01:00
alberto dca1e0b935 Fix another typo 2019-10-27 22:18:11 +01:00
alberto 56d3366831 Fix typo 2019-10-27 22:08:42 +01:00
Daniel Imms 719fa55dcf Merge pull request #2517 from revanthmahesh/dispose-eventemitters
Support disposing of EventEmitters
2019-10-26 21:52:50 -07:00
Daniel Imms f3bbcb35e4 Clean up 2019-10-26 21:52:11 -07:00
Revanth Mahesh d0e05eb795 Support disposing of EventEmitters 2019-10-27 10:11:43 +05:30
Daniel 2f18edbcac Remove old webgl enable button 2019-10-26 18:12:56 -07:00
Daniel 486fc714b3 Support checkboxes in demo to toggle addons
Fixes #2407
2019-10-26 18:12:20 -07:00
jerch edc09572b5 Merge pull request #2516 from jerch/addon_build
conditional `yarn` for addons
2019-10-26 17:32:08 +02:00
Jörg Breitbart 5b3a093f13 stick to prepare to avoid re-running yarn for addons everytime during build 2019-10-26 17:20:35 +02:00
Jörg Breitbart 03435a9f4d use prebuild instead of postinstall 2019-10-25 22:11:51 +02:00
jerchandDaniel Imms 04f828bc1a Update bin/install-addons.js
Co-Authored-By: Daniel Imms <tyriar@tyriar.com>
2019-10-25 21:46:49 +02:00
Jörg Breitbart d733ce3e63 add copyright note 2019-10-25 19:27:29 +02:00
Jörg Breitbart 6f8cbc56eb skip folder w'o package.json; restrict linter to src folders 2019-10-25 18:07:32 +02:00
Jörg Breitbart 25c18e8e07 conditional build for addons 2019-10-25 17:29:38 +02:00
Daniel Imms f30c38f773 Merge pull request #2515 from Tyriar/r420
v4.2.0
2019-10-25 05:50:45 -07:00
Daniel bfe11b7081 v4.2.0 2019-10-25 05:38:17 -07:00
Daniel Imms a800dd3aab Merge pull request #2514 from Tyriar/scroll
Apply scrollSensitivity on fast scroll too
2019-10-25 05:32:39 -07:00
Daniel a5a0779aa9 Apply scrollSensitivity on fast scroll too
Fixes #2513
2019-10-25 05:22:03 -07:00
Daniel Imms 4fe5a5a0bb Merge pull request #2512 from Tyriar/refine_range
Refine IViewportRange API to use 'cursor positions' for x value
2019-10-25 04:48:51 -07:00
Daniel Imms 974c721f66 Merge pull request #2511 from Tyriar/marker_doc
Clarify marker API docs
2019-10-25 04:45:06 -07:00
Daniel 851fb7ae38 Refine IViewportRange API to use 'cursor positions' for x value
Fixes #2484
2019-10-25 04:43:34 -07:00
jerch 1c72a66567 Merge pull request #2507 from jerch/remove_obsolete_mouseencodings
remove URXVT and UTF8 mouse encoding from codebase
2019-10-25 13:37:00 +02:00
jerch 6f8919ab93 Merge branch 'master' into remove_obsolete_mouseencodings 2019-10-25 13:20:20 +02:00
Daniel dac2da05bf Clarify marker API docs 2019-10-25 04:13:03 -07:00
Daniel Imms 7487d61fe2 Merge pull request #2510 from Tyriar/line_one
Set disposed marker line to -1
2019-10-25 04:08:45 -07:00
Daniel 67e5974eee Set disposed marker line to -1
Another indicator that it's disposed/invalid
2019-10-25 04:04:17 -07:00
jerch 21c3b3243d Merge branch 'master' into remove_obsolete_mouseencodings 2019-10-25 12:53:40 +02:00
Daniel Imms 4bd721c749 Merge pull request #2505 from Tyriar/lgtm_line
Fix lgtm suppression comment line
2019-10-25 03:49:48 -07:00
Jörg Breitbart ee2c1f71ef fix typo in debug msg 2019-10-25 12:43:34 +02:00
Jörg Breitbart a721e4884d Merge branch 'remove_obsolete_mouseencodings' of github.com:jerch/xterm.js into remove_obsolete_mouseencodings 2019-10-25 12:42:17 +02:00
Jörg Breitbart 31be1ebc53 remove DECSET 1005 and 1015 from InputHandler 2019-10-25 12:41:31 +02:00
jerch be59c74eae Merge branch 'master' into remove_obsolete_mouseencodings 2019-10-25 12:02:18 +02:00
jerch c1a0b26150 Merge pull request #2508 from jerch/fix_2423
limit parse buffer size
2019-10-25 12:01:51 +02:00
jerch d0689abd35 Merge branch 'master' into window_manipulation 2019-10-25 00:00:44 +02:00
Jörg Breitbart 13ddaf8f98 limit parse buffer size 2019-10-24 22:32:10 +02:00
jerch 6dc6748876 Merge branch 'master' into remove_obsolete_mouseencodings 2019-10-24 22:07:41 +02:00
jerch 527379d343 Merge pull request #2360 from jerch/left_right_scroll
Support column sequences SL (scroll left), SR (scroll right), DECIC (insert columns) and DECDC (delete columns).
2019-10-24 22:03:30 +02:00
Jörg Breitbart 5ea016d537 remove URXVT and UTF8 encoding from codebase 2019-10-24 21:57:22 +02:00
jerch bb424bd86f Merge branch 'master' into left_right_scroll 2019-10-24 21:46:02 +02:00
Daniel Imms a6f4855f66 Merge pull request #2506 from Tyriar/mp3_sound
Use mp3 audio instead of wav
2019-10-24 12:05:39 -07:00
Daniel Imms fe08f34918 Use mp3 audio instead of wav
wav needs ffmpeg which vscode does not ship with, mp3 is best for compat
2019-10-24 12:04:45 -07:00
Jörg Breitbart 68d6d5576c force screen update for altered lines 2019-10-24 21:01:59 +02:00
Jörg Breitbart a4d561d3b9 xterm testfiles for SL/SR/DECIC/DECDC with DECSTBM 2019-10-24 20:36:01 +02:00
Jörg Breitbart c223524f77 respect DECSTBM 2019-10-24 19:27:35 +02:00
Daniel Imms f8fa962ec7 Fix lgtm suppression comment line 2019-10-24 09:35:12 -07:00
jerch 2a46f5f147 Merge branch 'master' into left_right_scroll 2019-10-24 18:31:51 +02:00
Daniel Imms 080188c468 Merge pull request #2504 from jerch/fix_2495
fix typo in TextDecoder
2019-10-24 09:29:42 -07:00
jerch 1392abb6eb Merge branch 'master' into left_right_scroll 2019-10-24 18:07:35 +02:00
Jörg Breitbart 30d3d46027 make linter happy 2019-10-24 18:04:44 +02:00
Jörg Breitbart 6d620166b4 fix typo in decoder and add a test case 2019-10-24 17:52:03 +02:00
Daniel Imms 276463e95e Merge pull request #2501 from xtermjs/Tyriar-patch-1
Remove double space in dts
2019-10-23 11:37:30 -07:00
Daniel Imms 84e4cf7e9c Remove double space in dts 2019-10-23 11:37:17 -07:00
Daniel Imms d9f58c0dbb Merge pull request #2491 from miggs125/issue#2456
Prevent search result from being deselected if it is the only result
2019-10-22 07:32:26 -07:00
Daniel Imms 3e753f1370 Merge branch 'master' into issue#2456 2019-10-22 07:17:47 -07:00
Daniel Imms 616d341e8c Avoid initializing to undefined 2019-10-22 07:17:37 -07:00
Daniel Imms 15392c6c87 Merge pull request #2493 from leomoty/forbid-only
Forbid only in mocha
2019-10-22 07:15:17 -07:00
Daniel Imms 5e2001f4b5 Space out if 2019-10-22 07:14:32 -07:00
Daniel Imms 5194098f12 Merge pull request #2497 from Tyriar/warn_not_throw
Warn don't throw when open is called on unattached element
2019-10-22 07:02:30 -07:00
Daniel Imms 3ce552cdec Warn don't throw when open is called on unattached element
Related microsoft/vscode#83016
2019-10-22 06:56:05 -07:00
Miguel R 720c8c4623 Merge branch 'master' into issue#2456 2019-10-22 04:14:14 +00:00
Miguel Roncancio 243874c644 change comment 2019-10-21 23:51:47 -04:00
Miguel Roncancio 5d547bffb0 change return value, import ISelectionPosition 2019-10-21 23:49:28 -04:00
Miguel Roncancio 495f97cf95 change return value, import ISelectionPosition 2019-10-21 23:39:01 -04:00
Leonardo Bressan Motyczka 5c2479944e Ensure test-unit fails fast if .only present 2019-10-22 03:00:40 +00:00
Leonardo Bressan Motyczka 51ef0d0680 Update test-unit to allow double dash args 2019-10-22 03:00:18 +00:00
Daniel Imms 2b39887a37 Merge pull request #2492 from jmbockhorst/publicViewportRange
Expose IViewportRange in the public API
2019-10-21 19:18:03 -07:00
Daniel Imms 7c82f9c7d4 Merge pull request #2496 from Tyriar/lgtm_alerts
Fix alerts on lgtm.com
2019-10-21 19:11:23 -07:00
Daniel Imms 1dbe482fcb Suppress server alerts 2019-10-21 19:03:53 -07:00
Daniel Imms cfd158cbff Remove unused imports 2019-10-21 18:48:49 -07:00
Daniel Imms 9826f3a14c Remove unneeded defensive check 2019-10-21 18:47:43 -07:00
Daniel Imms 6f7c91d0cd Remove useless local var assignment 2019-10-21 18:47:18 -07:00
Daniel Imms bcdebe7648 Remove duplicate switch case
Guessing this one was the result of a bad merge?
2019-10-21 18:46:26 -07:00
Daniel Imms 09b244ed2f Fix NaN comparison 2019-10-21 18:44:03 -07:00
Leonardo Bressan Motyczka 7576e8c202 test-api: Fail fast if .only is used 2019-10-21 22:27:25 -03:00
Jon Bockhorst 7b752be68a Expose IViewportRange in the public API 2019-10-21 20:24:03 -05:00
Daniel Imms d02086e5c6 Add test to cover search multiple times 2019-10-21 15:23:59 -07:00
Daniel Imms 5c172c74b2 Merge branch 'master' into issue#2456 2019-10-21 14:34:10 -07:00
Daniel Imms d29fc6d5de Merge pull request #2489 from Tyriar/test_fiix
Remove .only from fit test
2019-10-21 14:31:10 -07:00
miguel 449ede1d57 Prevent search result from being deselected if it is the only result
remove leading whitespace
prevent single search term deselection in findPrevious
2019-10-21 15:58:44 -04:00
Daniel Imms fc10816615 Remove .only from fit test 2019-10-21 11:27:01 -07:00
Daniel Imms 631107698e Merge pull request #2483 from leomoty/fit-tests
Introduce FitAddon tests
2019-10-18 12:13:34 -07:00
Daniel Imms 33d58ec3d2 Merge pull request #2485 from eamodio/feature/scroll-sensitivity
Adds scrollSensitivity option for scrolling speed
2019-10-18 11:42:44 -07:00
Eric Amodio f445bc763b Adds scrollSensitivity option for scrolling speed 2019-10-18 14:30:46 -04:00
Daniel Imms f8a62a23e5 Speed tests up by avoiding page loads 2019-10-18 11:23:11 -07:00
Leonardo Bressan Motyczka a92635b22c Introduce FitAddon tests 2019-10-18 14:53:09 -03:00
Leonardo Bressan Motyczka 44a4bd788f Adjust proposeDimensions to behave like resize 2019-10-18 14:48:56 -03:00
Daniel Imms eb252433ce Merge pull request #2470 from jmbockhorst/linkPosition
Support link position in hover tooltip callback
2019-10-18 08:47:16 -07:00
Daniel Imms 499d6c26f0 Merge branch 'master' into linkPosition 2019-10-17 12:38:14 -07:00
Daniel 8350804858 Adjust to use 1-based, note in API 2019-10-17 12:36:03 -07:00
Daniel Imms 9df547d746 Merge pull request #2482 from Tyriar/2452_website_update
Create a PR for website update after a release
2019-10-17 12:26:45 -07:00
Daniel Imms 7537adfb72 Merge branch 'master' into 2452_website_update 2019-10-17 12:00:13 -07:00
Daniel caf075dcb0 Create a PR for website update after a release 2019-10-17 11:54:32 -07:00
Jon Bockhorst 57581ca4ef Updated IViewportCellPosition wording 2019-10-17 12:40:32 -05:00
Daniel Imms a604389cc0 Merge pull request #2481 from Tyriar/2154_force_release_var
Allow builds to specify a force release var
2019-10-17 10:28:34 -07:00
Jon Bockhorst 08475eb495 Update API to use IViewportRange and IViewportCellPosition 2019-10-17 12:25:42 -05:00
Daniel Imms 91d1f97754 Merge pull request #2476 from Tyriar/2459_win_scroll
Fix scrollback going missing when increase size on Windows
2019-10-17 10:19:46 -07:00
Daniel Imms 990be060f2 Allow builds to specify a force release var
This will let us automate patch releases by queuing a manual build

Fixes #2154
2019-10-17 10:00:45 -07:00
Daniel Imms 29e53c9c11 Merge pull request #2477 from leomoty/devcontainer-hotfix
Allows to run all integration tests inside devcontainer
2019-10-17 09:19:25 -07:00
Daniel Imms da42738881 Merge pull request #2474 from glneto/master
#2463 Add comma as a default word separator
2019-10-17 09:07:06 -07:00
Geraldo Neto 9753a7d425 Merge branch 'master' into master 2019-10-16 20:16:56 -03:00
Leonardo Bressan Motyczka 07308485a4 Update MouseTracking puppeteer window size
This allows all tests to successfully run in devcontainer
2019-10-16 20:08:57 -03:00
Leonardo Bressan Motyczka 3d500ba802 Launch puppeteer without sandbox 2019-10-16 20:07:56 -03:00
Leonardo Bressan Motyczka e8dc563ccf Include puppeteer deps on devcontainer 2019-10-16 20:05:45 -03:00
Daniel Imms ee245230c9 Merge branch 'master' into 2459_win_scroll 2019-10-16 15:44:19 -07:00
Daniel Imms 843ea1b610 Fix scrollback going missing when increase size on Windows
This also forces the scroll bar to sync after a resize early, this may fix
other bugs.

Fixes #2459
2019-10-16 15:41:47 -07:00
Geraldo Neto 9f80ce25c2 Add : and ; to the word separator 2019-10-16 19:23:50 -03:00
Daniel Imms bd57e305e1 Merge pull request #2475 from Tyriar/vsc_82309
Protect against exception when clicking on mouse zones
2019-10-16 11:08:16 -07:00
Daniel Imms 740d261d7a Protect against exception when clicking on mouse zones
Still not sure how this happens but seems harmless to just not use the row as
wrapped here.

See microsoft/vscode#82309
2019-10-16 11:07:22 -07:00
Geraldo Neto 1bc246323c Add comma as a default word separator 2019-10-15 22:42:12 -03:00
Daniel Imms 91cbeecf52 Merge pull request #2473 from Tyriar/2471
Mark element and textarea APIs as | undefined
2019-10-15 16:41:59 -07:00
Daniel Imms cfe8022867 Mark element and textarea APIs as | undefined
Didn't fix all the issues in Terminal.ts as they will be covered in layering
refactor

Fixes #2471
2019-10-15 16:29:13 -07:00
Daniel Imms 99db619a5c Merge pull request #2375 from csurquin/feat/fast-scrolling
Support fast scrolling using a modifier key
2019-10-15 16:23:17 -07:00
Daniel Imms 4f8cda9f3a Remove bad whitespace 2019-10-15 16:22:41 -07:00
Daniel Imms 9fdb674f20 Use min of 1 for fast scroll 2019-10-15 16:22:09 -07:00
Daniel Imms e76b8f86b5 Pull modifier code into helper, apply to lines scrolled 2019-10-15 16:21:20 -07:00
Daniel Imms 0083c23b2d Merge branch 'master' into feat/fast-scrolling 2019-10-15 16:10:44 -07:00
Jon Bockhorst 040f9f49d9 Support link position in hover tooltip callback 2019-10-14 14:25:02 -05:00
Daniel Imms cbb79a77f9 Merge pull request #2467 from Tyriar/2387_dont_do_ctrl_arrow_on_mac
Don't use ctrl+up/down hack on macOS
2019-10-14 11:53:27 -07:00
Daniel Imms a97fe2df1c Merge pull request #2469 from leomoty/dispose-test
Add integration test for terminal dispose
2019-10-14 10:58:07 -07:00
Leonardo Bressan Motyczka ff13f74858 Add integration test for terminal dispose 2019-10-14 13:20:18 -03:00
Daniel Imms 3d6815ca6f Add tests for alt+up/down 2019-10-11 16:05:54 -07:00
Daniel Imms da11e31fe5 Don't use ctrl+up/down hack on macOS
Fixes #2387
2019-10-11 16:01:28 -07:00
Daniel Imms e224b865fd Merge pull request #2465 from syrusakbary/patch-1
Added WebAssembly.sh
2019-10-10 13:54:25 -07:00
Syrus Akbary 821a7afc01 Added WebAssembly.sh 2019-10-10 13:05:28 -07:00
Daniel Imms 84b56b7691 Merge pull request #2453 from Tyriar/2445_reveal_search
Reveal search results in line just below viewport
2019-10-08 07:05:21 -07:00
Daniel Imms 8288a26b49 Merge pull request #2455 from JeffreyCA/unfocused-cursor-style
Update unfocused cursor to match current cursor style
2019-10-08 06:43:03 -07:00
Daniel Imms d87bae374b Merge pull request #2454 from saisandeepvaddi/master
add ten hands to real-world uses list
2019-10-08 06:36:55 -07:00
JeffreyCA 7c982fc0ce Fix lint warnings 2019-10-07 22:51:03 -07:00
JeffreyCA 1eb6e37187 Refresh terminal even if blinking is enabled so cursor changes are immediately visible 2019-10-07 22:36:37 -07:00
JeffreyCA efbdbd3f3b Render non-block cursors as-is when terminal is unfocused 2019-10-07 22:25:47 -07:00
Sai Sandeep Vaddi 7fc57da85a add ten hands to real-world uses list 2019-10-07 23:45:03 -04:00
Daniel Imms 6f5e5215f2 Reveal search results in line just below viewport
Fixes #2445
2019-10-07 14:27:29 -07:00
Daniel Imms cad9477eef Merge pull request #2451 from Tyriar/1416_fit_infinity
Generalize verify integers check
2019-10-07 10:46:07 -07:00
Daniel Imms 4fde8db060 Merge pull request #2450 from Tyriar/1158_throw_bad_open
Throw when open is called on element not on DOM
2019-10-07 10:45:38 -07:00
Daniel Imms 724bcc3766 Generalize verify integers check
Fixes #1416
2019-10-07 10:28:51 -07:00
Daniel Imms 52ae8fc14b Throw when open is called on element not on DOM
Fixes #1158
2019-10-07 10:21:34 -07:00
Daniel Imms e14b1f75fe Merge pull request #2449 from Tyriar/release_41
Release v4.1.0
2019-10-07 09:54:48 -07:00
Daniel Imms da5bf975b4 Merge branch 'master' into release_41 2019-10-07 09:44:30 -07:00
Daniel Imms 22398c0927 v4.1.0 2019-10-07 09:42:20 -07:00
Daniel Imms 43b291112e Merge pull request #2448 from Tyriar/597_cmd_arrow
Don't handle cmd+arrow
2019-10-07 08:27:42 -07:00
Daniel Imms 87a1fca726 Merge pull request #2447 from Tyriar/ts36
Upgrade to typescript 3.6
2019-10-07 08:27:28 -07:00
Daniel Imms 52e211915e Don't handle cmd+arrow
Fixes #597
2019-10-07 08:02:58 -07:00
Daniel Imms 92c991132f Upgrade to typescript 3.6 2019-10-07 07:55:48 -07:00
jerch 50b7fcb90a Merge branch 'master' into window_manipulation 2019-10-04 20:14:14 +02:00
jerch 7e01c833be Merge branch 'master' into extract_vt_features 2019-10-04 20:13:59 +02:00
jerch 89ac2834f1 Merge branch 'master' into left_right_scroll 2019-10-04 20:12:34 +02:00
Daniel Imms 358c09a108 Merge branch 'master' into feat/fast-scrolling 2019-09-28 09:30:23 -07:00
Daniel Imms ff790236c1 Merge pull request #2442 from Tyriar/2441_windows_demo
Fix demo on Windows
2019-09-28 09:29:47 -07:00
Daniel Imms 9014a27d7d Fix demo on Windows
Fixes #2441
2019-09-28 09:25:41 -07:00
Daniel Imms 5236d4aabf Merge branch 'master' into feat/fast-scrolling 2019-09-28 08:51:28 -07:00
Daniel Imms ea922fe548 Merge pull request #2422 from jerch/write_enhancement
write callback support
2019-09-25 17:19:42 -07:00
Daniel Imms 22b06cada7 Merge pull request #2425 from Tyriar/constant_key_board
Use more C0 constants in Keyboard
2019-09-25 17:06:17 -07:00
Daniel Imms 5a65286c54 Merge branch 'master' into write_enhancement 2019-09-25 17:03:00 -07:00
Daniel Imms 0e8883ac99 Strongly type addSocketListener 2019-09-25 17:00:31 -07:00
Daniel Imms 5cb0bcea0f Merge pull request #2437 from kafeg/patch-1
Update README.md
2019-09-24 08:18:38 -07:00
Vitaly Petrov 2fd24849b2 Update README.md 2019-09-24 17:46:12 +03:00
Daniel Imms b81711e3da Merge pull request #2434 from Tyriar/2433_npe
Fix NPE when open called twice (master)
2019-09-23 10:55:21 -07:00
Daniel Imms 0c740213e3 Merge branch 'master' into 2433_npe 2019-09-23 07:49:34 -07:00
Daniel Imms f3b7866a19 Fix NPE when open called twice
Fixes #2433
2019-09-23 07:47:02 -07:00
Jörg Breitbart d34d1f56cb simplify attach addon 2019-09-22 22:33:55 +02:00
Jörg Breitbart 322565807b Merge branch 'master' into write_enhancement 2019-09-22 20:59:28 +02:00
Jörg Breitbart 1178ef2a12 Merge branch 'write_enhancement' of github.com:jerch/xterm.js into write_enhancement 2019-09-22 20:57:26 +02:00
Jörg Breitbart 6aab756ccd integration callback tests 2019-09-22 20:57:00 +02:00
Jörg Breitbart d1bd603382 unit tests 2019-09-22 20:39:09 +02:00
Daniel Imms 191932cce2 Merge pull request #2431 from Tyriar/2117_tests
Add tests for IL, DL and DCH
2019-09-14 14:31:00 -07:00
Daniel Imms bc7ba7bd85 Simplify test 2019-09-14 12:57:41 -07:00
Daniel Imms 74ba282056 Add tests for DCH (CSI Ps P)
Part of #2117
2019-09-14 12:15:16 -07:00
Daniel Imms 96f944522e Add tests for DL (CSI Ps M)
Part of #2117
2019-09-14 12:05:00 -07:00
Daniel Imms bf209fb71f Add tests for IL (CSI Ps L)
Part of #2117
2019-09-14 11:53:42 -07:00
Daniel Imms 3b537c7e9f Improve api jsdoc 2019-09-13 09:32:38 -07:00
Daniel Imms ce39c0633c Merge pull request #2429 from Tyriar/update_addons
Use v4 for addon peer dependency and release
2019-09-13 09:18:11 -07:00
Daniel Imms aba4d76ec6 v0.2.1 of all addons 2019-09-13 09:16:55 -07:00
Daniel Imms 91734f7659 Set addon peer deps to v4
Fixes #2428
2019-09-13 09:16:22 -07:00
Jörg Breitbart 1ac3cf8fca use callback in paste integration test 2019-09-13 16:45:40 +02:00
Jörg Breitbart c2ec16a16c encapsulate deferred writing in WriteBuffer class 2019-09-13 16:31:28 +02:00
Jörg Breitbart e402772cf7 Merge branch 'master' into write_enhancement 2019-09-13 13:30:10 +02:00
Jörg Breitbart d9ba19ba9e remove write sync hack from Terminal.test.ts 2019-09-13 13:23:59 +02:00
Jörg Breitbart a95e451227 add params in doc 2019-09-13 13:19:33 +02:00
Jörg Breitbart fe74b5588d use write callback in benchmark test 2019-09-13 13:11:23 +02:00
Jörg Breitbart dcbc7e1014 remove writeln from core 2019-09-13 13:06:54 +02:00
Jörg Breitbart 50e552262a remove writeUtf8 from core 2019-09-13 13:00:47 +02:00
Jörg Breitbart 597757d0ee use write callbacks in addon integration tests 2019-09-13 12:44:13 +02:00
Daniel Imms 5d3313a8ca Merge pull request #2427 from Tyriar/dist_remove
Remove extra build in publish Release job
2019-09-12 15:33:17 -07:00
Daniel Imms 9d291d1d12 Remove extra build in publish Release job
We no longer publish a dist dir
2019-09-12 15:16:03 -07:00
Daniel Imms 7da361af9f Merge pull request #2424 from Tyriar/logging_data
Improve debug logging by printing character codes
2019-09-12 14:02:58 -07:00
Daniel Imms 761e437c69 Allow lazy evaluated log params 2019-09-12 13:38:30 -07:00
Daniel Imms fc4f345446 Don't transform incoming data
This would run for all data
2019-09-12 11:24:04 -07:00
Daniel Imms 0a4883b2b3 Use more C0 constants in Keyboard 2019-09-12 11:14:41 -07:00
Daniel Imms 293f54e8dd Improve debug logging by printing character codes 2019-09-12 11:06:22 -07:00
Jörg Breitbart 05fad38240 fix private access in integration tests 2019-09-12 13:58:52 +02:00
Jörg Breitbart 75ba717bd7 merge write methods, optional callback 2019-09-12 13:36:58 +02:00
jerch 308c8ba1a5 Merge branch 'master' into extract_vt_features 2019-09-12 10:55:55 +02:00
jerch 19f0fc0aa9 Merge branch 'master' into left_right_scroll 2019-09-12 10:55:36 +02:00
Daniel Imms ffd27dfef0 Merge pull request #2419 from Tyriar/master_changes
Master changes for 4.0.1 fixes
2019-09-11 14:50:58 -07:00
Daniel Imms e042f25b8d Expose ctor at window.Terminal
Fixes #2415
2019-09-11 14:39:26 -07:00
Daniel Imms 7f9f757042 Fix web links addon support in Edge
regex.flags isn't supported on Edge

Fixes #2417
2019-09-11 14:39:11 -07:00
Daniel Imms 6211dcd923 Merge pull request #2412 from Tyriar/v4
Publish v4.0.0
2019-09-10 17:02:57 -07:00
Daniel Imms 2f2d941557 Merge branch 'master' into v4 2019-09-10 17:02:11 -07:00
Daniel Imms 9a13479692 v4.0.0 2019-09-10 17:00:18 -07:00
Daniel Imms e34b557f67 Remove experimental flag from ITerminalAddon.activate 2019-09-10 16:29:25 -07:00
Daniel Imms 26a09f05a5 Merge pull request #2410 from Tyriar/bump_addons
Bump addon versions for v4 release
2019-09-10 15:54:52 -07:00
Daniel Imms 230d26afc7 Bump addon versions for v4 release 2019-09-10 15:54:01 -07:00
Daniel Imms 3aa0599722 Merge pull request #2406 from Tyriar/doc_update
Fix paths in example for v4
2019-09-09 10:27:08 -07:00
Daniel Imms 238d81dbc8 Merge pull request #2405 from Tyriar/sourcemaps
Expose source maps on demo server
2019-09-09 10:26:58 -07:00
Daniel Imms b990eb42c6 Fix paths in example for v4
Fixes #2146
2019-09-09 10:25:07 -07:00
Daniel Imms 1f12d365c8 Expose source maps on demo server
Fixes #2258
2019-09-09 10:21:37 -07:00
Daniel Imms fdfa871b37 Merge pull request #2404 from Tyriar/addon_readmes
Add/polish the readme for all addons
2019-09-09 09:32:44 -07:00
Daniel Imms 87c167a212 Improve logging for addon publish 2019-09-09 09:32:32 -07:00
Daniel Imms f7dade1023 Add/polish the readme for all addons
Fixes #2193
2019-09-09 09:28:33 -07:00
Daniel Imms 5e1de3b062 Merge branch 'master' into feat/fast-scrolling 2019-09-07 13:49:42 -07:00
Daniel Imms 477d1b2569 Merge branch 'master' into window_manipulation 2019-09-06 10:29:00 -07:00
Daniel Imms 91691085f6 Merge pull request #2402 from Tyriar/2401_dont_scroll
Don't execute move to cell when the user has scrolled up
2019-09-06 09:38:59 -07:00
Daniel Imms 81c5fd4988 Don't execute move to cell when the user has scrolled up
Fixes #2401
2019-09-06 09:27:20 -07:00
jerch 5c7a14cfe0 Merge branch 'master' into extract_vt_features 2019-09-05 22:41:35 +02:00
jerch fb9019e0c8 Merge branch 'master' into window_manipulation 2019-09-05 22:41:21 +02:00
jerch 54739d625f Merge branch 'master' into left_right_scroll 2019-09-05 21:54:22 +02:00
Daniel Imms 9fdae76cca Merge pull request #2400 from Tyriar/webpack
webpack@4.39.3
2019-09-05 12:45:54 -07:00
Daniel Imms b6683b7e9f webpack@4.39.3
Fixes security alert on set-value
2019-09-05 12:22:54 -07:00
Daniel Imms 62215ac493 Merge pull request #2399 from xtermjs/dependabot/npm_and_yarn/mixin-deep-1.3.2
Bump mixin-deep from 1.3.1 to 1.3.2
2019-09-05 12:18:34 -07:00
jerch bc5e1e6012 Merge pull request #2323 from jerch/mouse_services
CoreMouseService
2019-09-05 21:08:48 +02:00
jerch 6a5223b9fb Merge branch 'master' into mouse_services 2019-09-05 20:59:11 +02:00
dependabot[bot] b85db39dc4 Bump mixin-deep from 1.3.1 to 1.3.2
Bumps [mixin-deep](https://github.com/jonschlinkert/mixin-deep) from 1.3.1 to 1.3.2.
- [Release notes](https://github.com/jonschlinkert/mixin-deep/releases)
- [Commits](https://github.com/jonschlinkert/mixin-deep/compare/1.3.1...1.3.2)

Signed-off-by: dependabot[bot] <support@github.com>
2019-09-05 18:45:17 +00:00
Daniel Imms aac8f9f76c Merge pull request #2398 from Tyriar/2395_repo
Add repo field to addon package.json
2019-09-05 11:44:04 -07:00
Daniel Imms cc94dfd013 Add repo field to addon package.json
Fixes #2395
2019-09-05 11:27:03 -07:00
jerch 1b832b05a0 Merge pull request #2397 from jerch/fix_function_identifier
fix stacking of multiple intermediates
2019-09-04 13:55:46 +02:00
Jörg Breitbart 6d66c6a0c8 tests for function identifiers; fix stacking of multiple intermediates 2019-09-02 10:07:12 +02:00
Jörg Breitbart b3750bed2d early hack 2019-08-24 11:47:46 +02:00
jerch fa12649642 Merge branch 'master' into extract_vt_features 2019-08-23 20:37:29 +02:00
jerch 97bf796c43 Merge branch 'master' into left_right_scroll 2019-08-23 20:37:13 +02:00
jerch 4fd651f86f Merge branch 'master' into mouse_services 2019-08-23 20:36:36 +02:00
jerch 3938231c16 Merge pull request #2392 from jerch/fix_2389
fix several bugs in Params
2019-08-23 20:33:21 +02:00
Jörg Breitbart 87eb942d32 remove comment 2019-08-23 20:21:58 +02:00
jerch 54ff71f982 Merge branch 'master' into left_right_scroll 2019-08-23 16:45:42 +02:00
Jörg Breitbart 36b3bbd541 Merge branch 'master' into mouse_services 2019-08-23 16:37:16 +02:00
Jörg Breitbart a7e64ad537 fix bugs 2019-08-23 15:32:05 +02:00
Daniel Imms a67f57d693 Merge pull request #2388 from ShahzadUmair/Support-for-bubbling-scroll
Support for bubbling scroll events to parent(s)
2019-08-22 09:12:41 -07:00
Daniel Imms f91aa75c80 Indent second line of if condition 2019-08-22 09:12:04 -07:00
Daniel Imms 211700518f Merge pull request #2391 from Tyriar/2390_paste_api
Expose paste API
2019-08-22 09:06:27 -07:00
Daniel Imms a2d890cf74 Add paste api integration tests 2019-08-22 08:54:28 -07:00
Daniel Imms 9c7cf8e6e6 Cover another paste case 2019-08-22 08:39:50 -07:00
Daniel Imms 441d27cb5a Expose paste API
Fixes #2390
2019-08-22 08:39:02 -07:00
UmairShahzad 582934390d restructured bubble scroll 2019-08-21 00:57:41 +05:00
UmairShahzad e91c1c28d8 Merge remote-tracking branch 'upstream/master' into Support-for-bubbling-scroll 2019-08-21 00:46:07 +05:00
Jörg Breitbart aacc9c86b9 linter 2019-08-19 22:59:14 +02:00
Jörg Breitbart 8b2d85c823 document more commands; long description hook 2019-08-19 22:54:55 +02:00
Jörg Breitbart 66709e6f22 fix OSC list header; general notes 2019-08-18 21:50:17 +02:00
Jörg Breitbart f34edc3116 rename script 2019-08-18 17:57:22 +02:00
Jörg Breitbart 9cd80a2c6b cleanup 2019-08-18 17:52:26 +02:00
Jörg Breitbart 2de22f9356 extract @vt entries from docs 2019-08-18 17:36:06 +02:00
Jörg Breitbart f7827c4df8 add basic tests for commands 2019-08-17 18:52:11 +02:00
Jörg Breitbart 4b5709c68d add DECIC/DECDC to interface 2019-08-17 18:13:56 +02:00
Jörg Breitbart 4fe78dfe34 Merge branch 'master' into left_right_scroll 2019-08-17 17:57:31 +02:00
Jörg Breitbart 64c06d34fa remove any types 2019-08-17 14:45:11 +02:00
Jörg Breitbart a215362764 drop leftover aux button support, cleanup remnants 2019-08-17 13:41:15 +02:00
Jörg Breitbart 82d1bd86da only report on loglevel debug, explain events 2019-08-17 13:30:54 +02:00
Jörg Breitbart ae914c17d8 Merge branch 'master' into mouse_services 2019-08-16 22:06:04 +02:00
jerch 5a9e6fe94b Merge pull request #2346 from jerch/parser_hooks
Parser API
2019-08-16 21:26:33 +02:00
Jörg Breitbart 1c20057ed3 add parser property to interface 2019-08-16 21:14:49 +02:00
Jörg Breitbart 29a6f3f3ca Merge branch 'master' into parser_hooks 2019-08-16 21:00:24 +02:00
Daniel Imms 54d21579dd Merge pull request #2385 from lramos15/viewport-no-scroll
Don't scroll terminal search result if within viewport
2019-08-16 09:39:17 -07:00
Logan Ramos f3d8e74d6f Remove forgotten console .log 2019-08-16 10:55:16 -04:00
Logan Ramos 85444def9f Don't scroll terminal search result if within viewport 2019-08-16 10:50:44 -04:00
UmairShahzad 6c3b084fe9 added scroll bubbling on wheel and touch move events 2019-08-15 07:41:23 +05:00
Daniel Imms 95ff15457b Merge pull request #2381 from Tyriar/2380_links
Ensure selection service mousedown happens after mouse zone manager
2019-08-12 18:10:30 -07:00
Daniel Imms 63fd3be67a Ensure selection service mousedown happens after mouse zone manager
Fixes #2380
2019-08-12 17:56:26 -07:00
Jörg Breitbart a2c266a005 rename handler type aliases to XyType to avoid ambiguity with class based types 2019-08-11 18:45:34 +02:00
Jörg Breitbart 3a5d0bd368 fix escHandlers type and disposing 2019-08-11 18:38:35 +02:00
Jörg Breitbart 7c47fafb07 Merge branch 'parser_hooks' of github.com:jerch/xterm.js into parser_hooks 2019-08-11 17:55:42 +02:00
Jörg Breitbart b35383915d cleanup interfaces 2019-08-11 17:55:24 +02:00
Daniel Imms d05d6e6848 Merge branch 'master' into parser_hooks 2019-08-11 08:38:37 -07:00
Jörg Breitbart f677516e95 better interfaces, cleanup 2019-08-11 16:45:35 +02:00
Daniel Imms f3b9dc00b6 Merge pull request #2378 from Tyriar/2204_refresh
Fix dom -> canvas renderer switch not drawing viewport
2019-08-10 18:23:28 -07:00
Daniel Imms c758d7de55 Merge pull request #2377 from Tyriar/2076_remove_applyAddon
Remove applyAddon, stabilize loadAddon
2019-08-10 17:54:53 -07:00
Daniel Imms 63af42ba38 Merge pull request #2376 from Tyriar/2361
Move buffer tests to Terminal.test.ts and re-enable
2019-08-10 17:53:09 -07:00
Daniel Imms dd42eccb91 Fix dom -> canvas renderer switch not drawing viewport
Fixes #2204
2019-08-10 17:51:17 -07:00
Daniel Imms ba1274ba12 Remove applyAddon, stabilize loadAddon
Fixes #2076
2019-08-10 14:31:14 -07:00
Daniel Imms 13dde8061f Move buffer tests to Terminal.test.ts and re-enable
Fixes #2361
2019-08-10 14:23:17 -07:00
Daniel Imms e58a84df6a Merge branch 'master' into parser_hooks 2019-08-10 14:15:11 -07:00
Corentin Surquin a353a8cffe Allow to disable fast scrolling 2019-08-10 19:45:41 +02:00
Corentin Surquin 73a17cfacb Support fast scrolling using a modifier key 2019-08-10 19:45:41 +02:00
Daniel Imms e254d61c65 Merge pull request #2374 from Tyriar/2373_blink
Fix DOM blink for non-block cursors
2019-08-10 07:52:26 -07:00
Daniel Imms afe08d82d8 Merge branch 'master' into 2373_blink 2019-08-10 07:39:49 -07:00
Daniel Imms 598d37a023 Fix DOM blink for non-block cursors
Fixes #2373
2019-08-10 07:38:44 -07:00
Daniel Imms 30161c3b5a Merge pull request #2371 from Tyriar/2370
Fix mouse events class apply on open
2019-08-09 10:07:43 -07:00
Daniel Imms 0a9de5eb8c Merge branch 'master' into 2370 2019-08-09 09:56:16 -07:00
Daniel Imms 811c24b866 Fix mouse events class apply on open
Fixes #2370
2019-08-09 09:55:31 -07:00
Jörg Breitbart 0469e271da cache ParserApi, remove namespace 2019-08-08 21:58:02 +02:00
Jörg Breitbart 1286eb618a rename to OscHandler and DcsHandler 2019-08-08 19:41:12 +02:00
Jörg Breitbart 20fa447033 namespace parser related stuff 2019-08-08 19:34:00 +02:00
Jörg Breitbart a97742c765 Merge branch 'master' into parser_hooks 2019-08-08 18:51:12 +02:00
Daniel Imms 58e1b0db38 Merge pull request #2355 from jerch/fix_2354
DECSTBM issues
2019-08-07 07:51:18 -07:00
Daniel Imms 61e582969e Merge pull request #2366 from Tyriar/2365_shift_click
Don't throw if first click is incremental
2019-08-07 07:42:45 -07:00
Daniel Imms 29d8493a7a Don't throw if first click is incremental
Fixes #2365
2019-08-07 07:18:27 -07:00
Jörg Breitbart 4200e8356b apply BCE to SU/SD 2019-08-04 17:07:56 +02:00
Jörg Breitbart 8bc0099434 linter nonsense 2019-08-04 15:37:47 +02:00
Jörg Breitbart 9a903ca1c5 add DECIC/DECDC 2019-08-04 15:32:32 +02:00
Jörg Breitbart 5483a052cc always reset wrapped flag 2019-08-04 15:15:59 +02:00
Jörg Breitbart bd132d1f74 implement left/right scroll 2019-08-04 15:04:40 +02:00
Jörg Breitbart 6285cbf976 fix IL/DL test 2019-08-04 13:46:37 +02:00
Jörg Breitbart 00298531ed respect scroll margins in CUU/CUD/CPL/CNL; test files 2019-08-04 12:20:44 +02:00
Jörg Breitbart 2a533e7236 map DECEL back to eraseInLine 2019-08-04 09:00:07 +02:00
Jörg Breitbart 4e8a1c5656 Merge remote-tracking branch 'upstream/master' into parser_hooks 2019-08-04 08:56:34 +02:00
Jörg Breitbart eccd6d7bdf enable NEL test 2019-08-03 15:05:44 +02:00
Jörg Breitbart 497a5e6e84 fix DECSTBM with IND 2019-08-03 15:00:30 +02:00
Daniel Imms 2e237cc449 Merge pull request #2298 from JavaCS3/master
add SerializeAddon
2019-08-02 14:32:03 -07:00
Jörg Breitbart 84d7591506 increase test timeout 2019-08-02 21:06:16 +02:00
Daniel Imms bb734706fc Merge branch 'master' into master 2019-08-02 11:37:09 -07:00
Jörg Breitbart 0958f0ef91 fix DECSTBM with LF 2019-08-02 15:29:26 +02:00
Jörg Breitbart d28b601066 doc multi button tests as not doable 2019-08-01 16:52:19 +02:00
Jörg Breitbart bf2cc23eb0 tests for DECSET 1003 2019-08-01 16:15:55 +02:00
Jörg Breitbart b8b3cdbc3e increase test timeout 2019-08-01 12:08:07 +02:00
Jörg Breitbart 565b0791d8 fix osx tests 2019-08-01 11:50:15 +02:00
Jörg Breitbart 51feff3330 Merge branch 'mouse_services' of github.com:jerch/xterm.js into mouse_services 2019-08-01 01:16:49 +02:00
Jörg Breitbart 4dec88212e fix mouse tests 2019-08-01 01:16:29 +02:00
Jörg Breitbart aa8165a756 Merge branch 'master' into mouse_services 2019-07-31 23:12:05 +02:00
jerch a89771a8de Merge pull request #2321 from jerch/mouse_report_tests
Mouse tracking tests
2019-07-31 23:06:44 +02:00
Daniel Imms 6840f51b52 Merge branch 'master' into mouse_report_tests 2019-07-31 12:21:18 -07:00
Daniel Imms d20068c2db Merge pull request #2353 from Tyriar/multiple_dispose
Make dispose idempotent
2019-07-31 11:02:59 -07:00
Daniel Imms efaa78faee Make dispose idempotent
Fixes #2351
2019-07-31 10:55:39 -07:00
Jörg Breitbart bbd7275ad7 make linter happy 2019-07-31 14:44:50 +02:00
Jörg Breitbart 7252a5921d cleanup parser rules and docs 2019-07-31 14:20:36 +02:00
Jörg Breitbart 83a1340cc4 abort and cleanup subparsers for CAN and SUB 2019-07-31 12:03:12 +02:00
Jörg Breitbart 812fc5e6ec register functions by prefix/intermediate/final bytes 2019-07-31 04:49:01 +02:00
jerch 9d32dc4522 Merge branch 'master' into mouse_services 2019-07-26 18:23:57 +02:00
jerch 54586f75eb Merge branch 'master' into mouse_report_tests 2019-07-26 18:19:37 +02:00
Jörg Breitbart d78c062169 Merge branch 'master' into parser_hooks 2019-07-26 18:15:43 +02:00
Jörg Breitbart 0106bdcb73 parser tests for addDcsHandler 2019-07-26 18:11:31 +02:00
Jörg Breitbart 0a2d9a2120 addOscHandler integration test 2019-07-26 17:48:36 +02:00
Jörg Breitbart bffa78585e test cases for payload limits 2019-07-26 17:35:37 +02:00
Jörg Breitbart a9b2728c07 add DCS interface, payload limits for DCS/OSC 2019-07-26 15:59:24 +02:00
Jörg Breitbart 82aaef29f1 dcs parser tests 2019-07-26 15:07:24 +02:00
Jörg Breitbart c9b7aefb88 reset internal state on unhook 2019-07-26 02:56:48 +02:00
Jörg Breitbart 229a7ec755 Merge branch 'parser_hooks' of github.com:jerch/xterm.js into parser_hooks 2019-07-26 01:58:59 +02:00
Jörg Breitbart 6606024c2b support for multiple DCS handler 2019-07-26 01:58:42 +02:00
Daniel Imms 689fb6b6ad Merge pull request #2348 from xtermjs/Tyriar-patch-1
Fix NPE on dispose when it hasn't been opened
2019-07-25 16:53:25 -07:00
Daniel Imms 3dc52184e5 Fix NPE on dispose when it hasn't been opened 2019-07-25 16:49:26 -07:00
Daniel Imms 41331150ff Merge branch 'master' into parser_hooks 2019-07-25 14:43:53 -07:00
Daniel Imms 26948f044d Merge pull request #2345 from xtermjs/Tyriar-patch-1
Remove describe.only
2019-07-25 14:31:12 -07:00
Jörg Breitbart f985c30847 add addEscHandler 2019-07-25 22:44:08 +02:00
Jörg Breitbart 1f4dde601e remove experimental from addCsiHandler 2019-07-25 21:38:50 +02:00
Jörg Breitbart c87b3fd942 integration test for addOscHandler 2019-07-25 21:37:51 +02:00
Jörg Breitbart f626e1c93d fix OSC parsing 2019-07-25 20:38:14 +02:00
Daniel Imms 3f53f0ed29 Remove describe.only 2019-07-25 10:57:03 -07:00
Daniel Imms 378982a3ff Merge pull request #2344 from lramos15/search-tests
Puppeteer Tests for the Search Addon
2019-07-25 10:54:06 -07:00
Daniel Imms dc8f9f0a6d Merge branch 'master' into search-tests 2019-07-25 10:50:42 -07:00
Logan Ramos dcb39a658c Case sensitivity enabled 2019-07-25 10:41:55 -07:00
Logan Ramos 6869184864 More RegEx tests 2019-07-25 10:39:11 -07:00
Logan Ramos bb4c694f8d More search tests 2019-07-25 10:33:33 -07:00
Daniel Imms 33d4e08eba Merge pull request #2343 from Tyriar/cancel_events
Cancel keydown events when not in screenReaderMode
2019-07-25 10:19:53 -07:00
Daniel Imms 41f418e91e Revert tests to how they used to be 2019-07-25 10:13:50 -07:00
Daniel Imms bc30182752 Merge branch 'master' into cancel_events 2019-07-25 10:10:17 -07:00
Daniel Imms 7479131747 Cancel keydown events when not in screenReaderMode
This caused issues with embedder keybinding systems firing when they
shouldn't be. The fix is to only allow it in screenReaderMode as a
compromise so keys are echoed.
2019-07-25 10:08:41 -07:00
Daniel Imms 9715bdc45c Merge pull request #2340 from lramos15/lramos15/searchaddon-change
Changes default search addon behavior
2019-07-25 09:18:06 -07:00
Logan Ramos badfac2091 Merge branch 'lramos15/searchaddon-change' into search-tests 2019-07-25 09:10:06 -07:00
Logan Ramos a1be1f0b35 Code cleanup 2019-07-25 09:02:32 -07:00
Logan Ramos ea72a3b594 Fix incremental search bug 2019-07-25 08:50:37 -07:00
Jörg Breitbart d8364d749c remove null type from dcsHandler 2019-07-25 01:15:18 +02:00
Daniel Imms db936701f4 Include incremental in getSearchOptions 2019-07-24 16:09:57 -07:00
Logan Ramos d104f39a9d Incremental previous search 2019-07-24 16:01:07 -07:00
Logan Ramos 9ff5dc5858 Merge remote-tracking branch 'origin/lramos15/searchaddon-change' into search-tests 2019-07-24 15:33:26 -07:00
Jörg Breitbart 20a8e56201 Merge branch 'mouse_report_tests' of github.com:jerch/xterm.js into mouse_report_tests 2019-07-25 00:30:51 +02:00
Jörg Breitbart 113847aedf Merge branch 'master' into mouse_report_tests 2019-07-25 00:30:31 +02:00
Logan Ramos f3f52e6920 Changed default Search Addon behavior 2019-07-24 15:30:09 -07:00
Jörg Breitbart e32dbc6137 Merge branch 'master' into mouse_services 2019-07-25 00:29:06 +02:00
Logan Ramos cae3d59e23 Change search addon behavior 2019-07-24 15:09:59 -07:00
Daniel Imms 4ee0e3fec4 Merge branch 'master' into mouse_report_tests 2019-07-24 15:04:34 -07:00
Logan Ramos 7860dccdcf Search addon tests 2019-07-24 14:53:14 -07:00
Logan Ramos 79dcef0e6c Merge remote-tracking branch 'xterm/master' into search-tests 2019-07-24 14:05:00 -07:00
Daniel Imms 52c562d4b1 Merge pull request #2338 from Tyriar/debug_log
Move verbose logs in InputHandler to debug level
2019-07-24 12:27:44 -07:00
Daniel Imms 8447bcbb3b Merge branch 'master' into debug_log 2019-07-24 12:21:41 -07:00
Daniel Imms 8d76998df3 Merge pull request #2315 from Tyriar/layering4
Move renderer into browser
2019-07-24 12:21:27 -07:00
Daniel Imms 752243d95f Move verbose logs in InputHandler to debug level 2019-07-24 12:21:10 -07:00
Daniel Imms 1c0a263b03 Merge branch 'master' into layering4 2019-07-24 11:46:20 -07:00
Jörg Breitbart 4fba080d34 deactivate wheel left/right, docs 2019-07-24 15:14:37 +02:00
Jörg Breitbart f68769e5f3 Merge branch 'master' into mouse_services 2019-07-24 14:14:19 +02:00
Jörg Breitbart fb38bd13cd fix general purpose test script 2019-07-24 12:51:24 +02:00
Jörg Breitbart 6391742951 Merge branch 'master' into mouse_report_tests 2019-07-24 11:22:14 +02:00
Daniel Imms cb094b27a6 Merge pull request #2335 from Tyriar/unit_exit_code
Fix unit tests and the returned exit code
2019-07-23 14:41:41 -07:00
Daniel Imms ac8107d1df Fix lint errors 2019-07-23 14:32:13 -07:00
Daniel Imms edfef95bb3 Get tests passing 2019-07-23 14:22:49 -07:00
Daniel Imms ca0b8fdd8c Exit with correct exit code in test-unit 2019-07-23 14:19:07 -07:00
Jörg Breitbart 776c6dffea refactor buttons, wheel with left right 2019-07-23 20:16:42 +02:00
Jörg Breitbart 88faf1bcfe Merge branch 'master' into mouse_services 2019-07-23 18:27:34 +02:00
Jörg Breitbart 6463a1fe51 increase mouse test timeout 2019-07-23 17:15:30 +02:00
Jörg Breitbart 595465ec4f fix azure tasks 2019-07-23 17:04:38 +02:00
Jörg Breitbart edf881b19c macOS integration tests 2019-07-23 17:02:23 +02:00
Jörg Breitbart 711865f19a sanitize code extraction 2019-07-23 16:57:56 +02:00
Jörg Breitbart 50e5eb63df macos fix part4 2019-07-23 16:27:15 +02:00
Jörg Breitbart 2c3f9c9ca5 macos fix part3 2019-07-23 16:08:44 +02:00
Jörg Breitbart 10c61d47a2 macos fix part2 2019-07-23 16:03:15 +02:00
Jörg Breitbart 5b3d2fcef9 Merge branch 'mouse_report_tests' of github.com:jerch/xterm.js into mouse_report_tests 2019-07-23 15:52:08 +02:00
Jörg Breitbart 435cb3bd0a partial fix macos 2019-07-23 15:51:57 +02:00
Daniel Imms 62c25b0bba Fix all auto-fixable tslint issues 2019-07-22 14:08:34 -07:00
Daniel Imms d63985a50f Merge branch 'master' into mouse_report_tests 2019-07-22 14:06:59 -07:00
Daniel Imms 7db22c2408 Merge pull request #2329 from Tyriar/announce_input
Announce characters in screen readers when typing and using backspace
2019-07-22 12:40:50 -07:00
Jörg Breitbart bca69a75b4 fix report eval for buttons > 5 2019-07-22 20:18:06 +02:00
Daniel Imms 9e3ca6af18 Merge branch 'master' into announce_input 2019-07-22 10:52:29 -07:00
Daniel Imms ea019e8e66 Merge pull request #2328 from Tyriar/log_data_sent
Debug log data being sent
2019-07-22 10:49:47 -07:00
Daniel Imms c8a719b64a Clear textarea when ^C or enter is pressed 2019-07-22 10:49:40 -07:00
Daniel Imms d2a311b128 Debug log data being sent 2019-07-22 10:42:40 -07:00
Daniel Imms 6a68a24739 Debug log data being sent 2019-07-22 10:42:18 -07:00
Daniel Imms cabd0ca3bc Announce character when typing
Fixes #2327
2019-07-22 10:34:06 -07:00
Jörg Breitbart 3e5b075a0a remove modifier restriction for 1000 2019-07-22 16:32:24 +02:00
Jörg Breitbart 25ed7f7a7f added modifier tests 2019-07-22 15:22:14 +02:00
Logan Ramos ab9e92fcf1 Initial search tests 2019-07-19 17:45:39 -07:00
Jörg Breitbart 986bdac191 create wheel event remote 2019-07-20 00:45:12 +02:00
Jörg Breitbart 044476ae4f Merge branch 'master' into mouse_report_tests 2019-07-20 00:05:38 +02:00
Jörg Breitbart e5b28d4e72 Merge branch 'mouse_services' of github.com:jerch/xterm.js into mouse_services 2019-07-19 23:58:02 +02:00
Jörg Breitbart f239e10ed6 use enums instead 2019-07-19 23:55:18 +02:00
Daniel Imms 6465ab960e Merge branch 'master' into mouse_services 2019-07-19 12:08:10 -07:00
Daniel Imms 9a433e90e8 Merge pull request #2322 from elisescu/master
Add tty-share to the list of real world uses
2019-07-19 08:58:36 -07:00
Jörg Breitbart b64ed4f540 cleanup sendEvent, switch reported button during move 2019-07-19 17:04:12 +02:00
Jörg Breitbart cbddbc6e83 some changes in mouse event handling:
- use onProtocolChange
- remove mouse states from Terminal.ts
- remove selectionService from InputHandler
- fix up events in VT200 mode
- fix move event with no buttons in ANY mode
2019-07-19 16:21:30 +02:00
Jörg Breitbart df0cf253ac debounce only move events 2019-07-19 02:56:24 +02:00
Jörg Breitbart e38a68e396 debounce events at grid level 2019-07-19 02:46:03 +02:00
Jörg Breitbart 4858bdc464 CoreMouseService 2019-07-19 01:45:27 +02:00
Jörg Breitbart ee3cbae35a modifier test examples 2019-07-18 00:00:41 +02:00
Vasile Popescu 2b43731270 Add tty-share to the list of real world uses 2019-07-17 21:16:27 +02:00
Jörg Breitbart d4f65b7d0e remove copied over bug comments 2019-07-17 18:42:04 +02:00
Jörg Breitbart 27e8f7aa31 mixed col/row in report parser 2019-07-17 18:10:09 +02:00
Jörg Breitbart 4e56eed914 basic mousing tracking api tests 2019-07-17 18:07:44 +02:00
jerch d55fb1e922 Merge pull request #2316 from jerch/mouse_modes
Mouse modes test script
2019-07-16 22:38:12 +02:00
jerch 48109cac6b Merge branch 'master' into mouse_modes 2019-07-16 22:06:14 +02:00
Jörg Breitbart 78c1569a6e cleanup 2019-07-16 22:05:06 +02:00
Charles Wei 09ede0221a Merge branch 'master' into master 2019-07-16 20:03:57 +08:00
javacs3 f859bffa74 fix lint error 2019-07-15 09:42:56 +08:00
Jörg Breitbart 5b52094aa2 respect protocol and modifiers 2019-07-14 23:58:07 +02:00
Daniel Imms 2b7be05da3 Move 3 render layers to browser 2019-07-14 12:36:37 -07:00
Daniel Imms 9830a077c1 Move BaseRenderLayer into browser 2019-07-14 12:22:11 -07:00
Daniel Imms cdefb3e7f2 Remove more terminal from render layers and cache 2019-07-14 12:07:43 -07:00
Daniel Imms 60ae9add3f Remove most terminal refs from BaseRenderLayer 2019-07-14 11:48:44 -07:00
Jörg Breitbart e5728ca78f test script for mouse modes 2019-07-14 20:34:51 +02:00
Daniel Imms a48260279c Fix import in webgl addon 2019-07-14 11:20:25 -07:00
Daniel Imms bd95c83ca2 Start using services in most render layers 2019-07-14 10:15:58 -07:00
Daniel Imms 868125f258 Don't pass terminal around within render layers
Will ease migration to services
2019-07-14 10:04:51 -07:00
Daniel Imms 60194179f8 Move CharAtlasCache to browser 2019-07-14 09:43:54 -07:00
Daniel Imms 64062d1a25 Move CharAtlasUtils into browser 2019-07-14 09:38:49 -07:00
Daniel Imms c0253c1093 Move DynamicCharAtlas to browser 2019-07-14 09:31:04 -07:00
Daniel Imms 58dbc98361 Move BaseCharAtlas to browser 2019-07-14 09:26:09 -07:00
Daniel Imms 4edae7c7ae Merge pull request #2314 from Tyriar/sec
Update some dev dependencies
2019-07-14 09:08:30 -07:00
Daniel Imms 8b3a649d65 Update express-ws, ts-loader and webpack 2019-07-14 09:02:29 -07:00
Daniel Imms 94b77aaf8c Update express
Fixes security issue in negotiator
2019-07-14 08:57:09 -07:00
Daniel Imms a94a361e1c Merge pull request #2311 from Tyriar/layering3
Move range updating to DirtyRowService and add dependency injection
2019-07-14 08:55:50 -07:00
Daniel Imms 2c50af356a Remove note in readme 2019-07-14 08:53:03 -07:00
javacs3 bca90245c8 serialize from the bottom of the terminal 2019-07-14 23:28:08 +08:00
Daniel Imms 5e0b1b251f Merge branch 'master' into layering3 2019-07-14 00:44:28 -07:00
Daniel Imms ff017f8960 Merge pull request #2313 from xtermjs/dependabot/npm_and_yarn/extend-3.0.2
Bump extend from 3.0.1 to 3.0.2
2019-07-14 00:41:56 -07:00
Daniel Imms 1df737c394 Fix decorator error 2019-07-14 00:41:37 -07:00
dependabot[bot] b97c704c21 Bump extend from 3.0.1 to 3.0.2
Bumps [extend](https://github.com/justmoon/node-extend) from 3.0.1 to 3.0.2.
- [Release notes](https://github.com/justmoon/node-extend/releases)
- [Changelog](https://github.com/justmoon/node-extend/blob/master/CHANGELOG.md)
- [Commits](https://github.com/justmoon/node-extend/compare/v3.0.1...v3.0.2)

Signed-off-by: dependabot[bot] <support@github.com>
2019-07-14 07:19:39 +00:00
Daniel Imms 05992e093b Merge branch 'master' into layering3 2019-07-14 00:17:48 -07:00
Daniel Imms 8deef83c60 Add tslint rule to prevent import from out
Fixes #1996
2019-07-14 00:16:20 -07:00
Daniel Imms fb6d4e2bfe Remove imports from out 2019-07-13 23:54:44 -07:00
Daniel Imms a0e2c9b270 Fix naming issue with serviceBrand 2019-07-13 23:45:25 -07:00
Daniel Imms 358a707835 Fix most lint and tests 2019-07-13 23:44:08 -07:00
Daniel Imms 9315b50897 Use createInstance on service hungry objects 2019-07-13 22:56:54 -07:00
Daniel Imms 88c88f1141 Adopt DI in browser services 2019-07-13 22:26:13 -07:00
Daniel Imms f4208d0389 Merge pull request #2312 from xtermjs/dependabot/npm_and_yarn/lodash-4.17.14
Bump lodash from 4.17.10 to 4.17.14
2019-07-13 22:20:15 -07:00
dependabot[bot] 283d1b1105 Bump lodash from 4.17.10 to 4.17.14
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.10 to 4.17.14.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.10...4.17.14)

Signed-off-by: dependabot[bot] <support@github.com>
2019-07-14 05:04:11 +00:00
Daniel Imms 5cc8ad802c Get type safety in DI, fix character joiner not using buffer service 2019-07-13 22:02:13 -07:00
Daniel Imms 8359605951 Add license and credit to VS Code 2019-07-13 19:54:01 -07:00
Daniel Imms 21fbe25858 Dependency Injection prototype 2019-07-13 19:50:16 -07:00
Daniel Imms c078f3db48 Move range updating to DirtyRowService 2019-07-13 18:25:22 -07:00
Daniel Imms 5709e5ff30 Merge pull request #2310 from Tyriar/layering2
Move MouseZoneManager and Viewport into browser
2019-07-13 18:13:13 -07:00
Daniel Imms 9aaaf6d8db Move Viewport to browser 2019-07-13 17:50:43 -07:00
Daniel Imms 8aa296933d Break Viewport's dependency on ITerminal 2019-07-13 17:49:44 -07:00
Daniel Imms 4dfe3a6079 Move MouseZoneManager to browser 2019-07-13 17:43:23 -07:00
Daniel Imms ca4e3d3fc4 Merge pull request #2309 from Tyriar/layering
Move several components to sub-projects
2019-07-13 17:40:19 -07:00
Daniel Imms 78f015308a Re-enable linkifier unicode tests in Terminal.test.ts 2019-07-13 17:28:09 -07:00
Daniel Imms 2eec18e7f5 Remove ITerminal from MouseZoneManager 2019-07-13 14:35:31 -07:00
Daniel Imms 0cd4093e53 Move Linkifier to browser 2019-07-13 14:15:28 -07:00
Daniel Imms f0a02e3188 Move linkifier types into browser 2019-07-13 13:53:16 -07:00
Daniel Imms 1ffa568a2f Remove ITerminal from Linkifier 2019-07-13 13:47:17 -07:00
Daniel Imms a696f4747a Move clipboard to browser 2019-07-13 13:18:44 -07:00
Daniel Imms 4d9d6fbd86 Merge pull request #2304 from Tyriar/inputhandler_bufferservice
Use IBufferService for buffer access in InputHandler
2019-07-13 11:09:04 -07:00
Daniel Imms 46002599d3 Prefix all logging with 'xterm.js'
This makes it easier to differentiate messages in large apps
2019-07-13 10:11:02 -07:00
Daniel Imms 0c038352f3 Remove debug internal option completely and add option APIs 2019-07-13 10:00:15 -07:00
Daniel Imms f314543135 Log bad linkifier instead of throwing 2019-07-13 09:48:16 -07:00
Daniel Imms cd01d8ad56 Lint 2019-07-13 09:47:11 -07:00
Daniel Imms 2977a53cc1 Use log service everywhere, fix log printing
Fixes #1560
2019-07-13 09:44:16 -07:00
Daniel Imms 94199ae124 Introduce logLevel option
Part of #1560
2019-07-13 09:36:21 -07:00
javacs3 fe3520c685 change exception message 2019-07-13 17:25:18 +08:00
Daniel Imms af9c050e93 Remove ITerminal usage in DECRQSS 2019-07-13 01:46:01 -07:00
Daniel Imms 49fa86d6bb Get rows/cols in input hander from buffer service 2019-07-13 01:38:02 -07:00
Daniel Imms dd239b9811 Use IBufferService for buffer access in InputHandler 2019-07-13 00:52:54 -07:00
Daniel Imms 61b219ce22 Merge pull request #2303 from Tyriar/compositionhelper_browser
Move CompositionHelper into browser
2019-07-13 00:30:27 -07:00
Daniel Imms 27a946286a Make browser import absolute 2019-07-13 00:25:37 -07:00
Daniel Imms b929f82101 Move CompositionHelper into browser 2019-07-13 00:23:56 -07:00
javacs3 31f812cf94 add missing api docs and refactor serialize implementation by using list join instead and some code clean up 2019-07-12 23:23:06 +08:00
javacs3 57a8255654 add test files from addons folder 2019-07-12 23:23:06 +08:00
Daniel Imms 4a442888ce Merge pull request #2288 from jerch/cleanup_sequences_files
fix edge cases in inputhandler methods
2019-07-11 15:37:42 -07:00
Daniel Imms b658f7ba44 Merge branch 'master' into cleanup_sequences_files 2019-07-11 15:25:17 -07:00
Daniel Imms e99de7a910 Merge pull request #2302 from Tyriar/2301_mouse_events
Don't trigger selection when mouse events are on
2019-07-11 11:12:21 -07:00
Daniel Imms 7a37bd880e Add test for mouse events 2019-07-11 11:07:03 -07:00
Daniel Imms da9b4b1a69 Don't trigger selection when mouse events are on
Fixes #2301
2019-07-11 09:34:45 -07:00
Jörg Breitbart eb707bb1d7 better typing in test file 2019-07-11 02:41:20 +02:00
Daniel Imms a71ed7b5b7 Merge branch 'master' into master 2019-07-10 17:14:13 -07:00
Jörg Breitbart 6ec093a717 Merge branch 'cleanup_sequences_files' of github.com:jerch/xterm.js into cleanup_sequences_files 2019-07-10 23:39:20 +02:00
Jörg Breitbart 24b26c7311 force closing of pty 2019-07-10 23:39:05 +02:00
Daniel Imms c2a4ff1c72 Merge branch 'master' into cleanup_sequences_files 2019-07-10 11:57:33 -07:00
Daniel Imms a9961c867d Merge pull request #2297 from qwefgh90/master
Add NgTerminal to the users list
2019-07-10 11:48:51 -07:00
Daniel Imms a32c46758f Improve grammar 2019-07-10 11:48:30 -07:00
javacs3 3ba6ffe5f4 fix lint error 2019-07-10 21:57:50 +08:00
javacs3 2571a0654f add SerializeAddon 2019-07-10 21:46:51 +08:00
Jörg Breitbart cc3bb83ced getting rid of native access in test file 2019-07-10 14:57:49 +02:00
Changwon Choe 6f58572d1f Add NgTerminal to the users list 2019-07-10 12:48:18 +09:00
Jörg Breitbart ab25997192 change to max/min 2019-07-09 22:30:00 +02:00
Jörg Breitbart 9d2418ece6 remove comment 2019-07-09 21:41:17 +02:00
Jörg Breitbart d8650ad722 Merge branch 'master' into cleanup_sequences_files 2019-07-09 00:44:12 +02:00
Daniel Imms 44a843bbe6 Merge pull request #2294 from Tyriar/fix_keyup
Don't handle keyup that is handled by custom handler
2019-07-08 15:36:54 -07:00
Daniel Imms bf35ee8016 Fix lint 2019-07-08 15:29:09 -07:00
Daniel Imms cf3cf38e60 Don't handle keyup that is handled by custom handler
Fixes #2293
2019-07-08 15:25:30 -07:00
Jörg Breitbart 691a8addfc cleanup; doc; move cursor methods next to each other 2019-07-08 23:59:46 +02:00
Jörg Breitbart 3d6f87ea7f reset cursor on DECOM 2019-07-08 23:22:46 +02:00
Jörg Breitbart e91c223bb0 respect DECSTBM margins in DECOM mode 2019-07-08 23:09:53 +02:00
Jörg Breitbart cb25e2d4e0 save/restore charset in DECSC/DECRC 2019-07-08 02:42:02 +02:00
Jörg Breitbart bc867bf12b partial fix DECSTBM IL/DL 2019-07-08 02:11:46 +02:00
Jörg Breitbart 5122fdc441 document wonky usage of Terminal.reset 2019-07-08 00:55:26 +02:00
Jörg Breitbart 8654133b15 move leftover sequence methods to InputHandler 2019-07-08 00:39:05 +02:00
Jörg Breitbart 41cc99a919 DECSTBM SU/SD 2019-07-08 00:19:21 +02:00
Jörg Breitbart e2366fa83d rewrite DECSTBM 2019-07-07 23:37:02 +02:00
Jörg Breitbart 46f89cd4ff fix NPE 2019-07-07 22:22:19 +02:00
Jörg Breitbart ef58f1fef8 add vttest wrapping testfile 2019-07-07 22:19:45 +02:00
Jörg Breitbart 9d4cafc4c9 fix ICH 2019-07-07 21:18:03 +02:00
Jörg Breitbart 7e7730d176 fix ECH 2019-07-07 21:15:14 +02:00
Jörg Breitbart 926c298371 fix DCH 2019-07-07 21:10:38 +02:00
Jörg Breitbart 9a64c549f8 fix ED3 test 2019-07-07 20:54:12 +02:00
Jörg Breitbart d26a643727 use fill for _resetBufferLine 2019-07-07 20:45:54 +02:00
Jörg Breitbart cd1d194dbd apply cursor restrictions 2019-07-07 20:40:27 +02:00
Jörg Breitbart 204847b134 fix DECSC 2019-07-07 19:54:47 +02:00
Jörg Breitbart fe59e632a9 Merge branch 'cleanup_sequences_files' of github.com:jerch/xterm.js into cleanup_sequences_files 2019-07-06 20:46:30 +02:00
Jörg Breitbart e6ac138620 Merge branch 'master' into cleanup_sequences_files 2019-07-06 20:45:50 +02:00
jerch 68694dab9d Merge pull request #2241 from jerch/parser_colon_notation
colon notation for the parser
2019-07-06 20:04:00 +02:00
Daniel Imms 6665a06b01 Merge branch 'master' into cleanup_sequences_files 2019-07-06 10:22:20 -07:00
jerch be6226785f Merge branch 'master' into parser_colon_notation 2019-07-06 18:22:43 +02:00
Jörg Breitbart 6d22772d16 fix REP to be in line with vttest 2019-07-06 18:09:38 +02:00
Jörg Breitbart fa9857aedf simplify cursor movements 2019-07-06 16:47:48 +02:00
Jörg Breitbart a2bf5fe975 fix typo 2019-07-06 16:13:21 +02:00
Jörg Breitbart eb7b8f9020 restrict cursor movements 2019-07-06 15:59:18 +02:00
Jörg Breitbart d18b799624 fix HT, HTS, CHT 2019-07-05 02:04:42 +02:00
Jörg Breitbart 44035d14ab fix no wraparound mode 2019-07-05 00:56:57 +02:00
Jörg Breitbart 82ff113107 add DECALN 2019-07-04 23:50:56 +02:00
Daniel Imms f889796852 Merge pull request #2289 from Tyriar/sound_browser
Move sound into browser
2019-07-04 14:09:40 -07:00
Daniel Imms 49b5eda160 Merge branch 'master' into sound_browser 2019-07-04 13:14:01 -07:00
Daniel Imms 47164d2f68 Move sound into browser 2019-07-04 12:31:21 -07:00
Daniel Imms fb6ec7ffb8 Merge pull request #2287 from Tyriar/webgl_simplify_atlas
Enable strict mode in webgl addon
2019-07-04 09:21:44 -07:00
Daniel Imms bc07225394 Enable strict mode in webgl addon
Fixes #2286
2019-07-04 09:08:56 -07:00
Daniel Imms 40bc62c383 Enable strict null checks in webgl addon
Part of #2286
2019-07-04 08:58:42 -07:00
Daniel Imms ff82d35a3d Merge pull request #2285 from Tyriar/webgl_simplify_atlas
Simplify webgl atlas and ensure it exists in GlyphRenderer to prevent NPE
2019-07-04 08:49:39 -07:00
Jörg Breitbart d858022f23 fix several escape sequence files 2019-07-04 17:45:10 +02:00
Daniel Imms 0898de147f Ensure GlyphRenderer._atlas exists on beginFrame
This should fix an exception breaking it in vscode
2019-07-04 08:36:44 -07:00
Daniel Imms 38f2e7a81d Simplify webgl atlas by removing BaseCharAtlas 2019-07-04 08:28:21 -07:00
Jörg Breitbart 5f8d07ac62 cleanup Types.ts, docs for ZDM 2019-07-04 13:50:03 +02:00
Jörg Breitbart 6a691f2548 fix parser docs 2019-07-04 13:01:18 +02:00
Jörg Breitbart 7bd0325128 remove example snippet from docs 2019-07-04 12:42:43 +02:00
Jörg Breitbart 009b3c6ef8 simply error parsing state 2019-07-04 12:38:14 +02:00
Jörg Breitbart 75d41abf33 re-enable commented out tests 2019-07-04 12:37:32 +02:00
Jörg Breitbart 6bcd8e3bfd ParamsArray to Types.ts 2019-07-04 12:12:11 +02:00
Daniel Imms 69dcabbfce Merge branch 'master' into parser_colon_notation 2019-07-03 16:58:37 -07:00
Daniel Imms f235d70f30 Merge pull request #2284 from Tyriar/blank_line
Remove blankLine localized string
2019-07-03 10:42:35 -07:00
Daniel Imms 048e95e34b Remove blankLine localized string
Using a nbsp is more correct and lets the screen reader handle how it wants

Fixes #2260
2019-07-03 10:23:53 -07:00
Daniel Imms c55e938ce9 Merge pull request #2283 from lramos15/lramos15/select-fix
Double wide characters could have halves selected
2019-07-03 08:48:11 -07:00
Logan Ramos 2a405d5f97 Fix scroll bar logic 2019-07-03 08:37:59 -07:00
Daniel Imms 1bab14aef6 Merge pull request #2281 from lramos15/lramos15/centered-scroll
Centers search scroll in viewport
2019-07-02 16:03:21 -07:00
Logan Ramos 345bf11389 Remove extra import 2019-07-02 15:57:23 -07:00
Logan Ramos 60c2248cb4 Centers scroll in viewport 2019-07-02 15:09:30 -07:00
Jörg Breitbart 17ca958542 js array integration test for addCsiHandler 2019-07-02 22:38:20 +02:00
Jörg Breitbart 65b757bc19 fix typos in docs 2019-07-02 22:04:12 +02:00
Jörg Breitbart f276150ce4 remove IParams from public API 2019-07-02 20:41:21 +02:00
Jörg Breitbart 357faa71df value range restrictions: clamp max, reject < -1 2019-07-02 18:27:13 +02:00
Jörg Breitbart a1acd4b318 Merge branch 'master' into parser_colon_notation 2019-07-02 16:44:43 +02:00
Jörg Breitbart 7dd5dfab7a make params mandatory 2019-07-02 16:14:28 +02:00
Jörg Breitbart 5827b4b0d1 change to int32_t 2019-07-02 15:18:39 +02:00
Daniel Imms d691327cb5 Merge pull request #2279 from Tyriar/selection_manager_browser
Make SelectionManager a service and move into browser
2019-06-30 10:21:36 -07:00
Daniel Imms 47b6756ead isMSWindows -> isWindows 2019-06-29 18:57:59 -07:00
Daniel Imms 79d8f05528 Make Terminal.selectionService private 2019-06-29 18:50:54 -07:00
Daniel Imms 3806f67fc0 Move SelectionService into browser (+strict) 2019-06-29 18:41:48 -07:00
Daniel Imms 48f68a7702 Add used members from SelectionService to interface 2019-06-29 14:34:48 -07:00
Daniel Imms 7ee2219314 Rename SelectionManager to SelectionService 2019-06-29 14:27:50 -07:00
Daniel Imms 4d22d1d008 Reset modes on reset 2019-06-29 14:15:04 -07:00
Daniel Imms a706dd9de9 Merge branch 'master' into selection_manager_browser 2019-06-29 14:09:54 -07:00
Daniel Imms b4ae5e1aff Merge branch 'master' into parser_colon_notation 2019-06-29 13:54:02 -07:00
Daniel Imms 73be720ecc Merge pull request #2277 from Tyriar/guard
Guard integer only APIs when floats are used
2019-06-29 13:52:21 -07:00
Daniel Imms a61fbf7a51 Merge pull request #2278 from MaxRis/to-master/reset-wrapped-line-flag
Reset isWrapped line flag.
2019-06-29 08:38:57 -07:00
Max Risuhin f9e8334141 Reset isWrapped line flag. 2019-06-29 16:02:15 +03:00
Daniel Imms b4886df796 Guard integer only APIs when floats are used
Fixes #2261
2019-06-28 16:42:42 -07:00
Daniel Imms 6fb7a06f19 Merge pull request #2276 from Tyriar/2275_lower_zIndex
Lower z-indexes
2019-06-28 12:52:56 -07:00
Daniel Imms d8099f7fe9 Lower z-indexes
Canvas layers: 0-4
Helpers: 5
A11y tree: 10

Fixes #2275
2019-06-28 12:46:57 -07:00
Daniel Imms f9eeea5917 Merge pull request #2274 from Tyriar/out-test
Git ignore out-test
2019-06-27 18:44:59 -07:00
Daniel Imms 7e09ac7f04 Merge pull request #2273 from Tyriar/tslint_celan
Enforce underscore prefix for protected members
2019-06-27 18:44:41 -07:00
Daniel Imms 788ab83ac1 Merge branch 'master' into tslint_celan 2019-06-27 18:37:43 -07:00
Daniel Imms 10fedf4ccf Enforce underscore prefix for protected members 2019-06-27 18:36:44 -07:00
Daniel Imms 8cf5a7ee40 Git ignore out-test 2019-06-27 18:26:02 -07:00
Daniel Imms 48b915459a Merge pull request #2269 from Tyriar/d_map
Use TS declarationMap
2019-06-27 11:46:45 -07:00
Daniel Imms 7f4e1a7e97 Add explicit blacklist entry for .d.ts.map 2019-06-27 11:40:39 -07:00
Daniel Imms c107f3c5f7 Merge branch 'master' into d_map 2019-06-27 11:32:13 -07:00
Daniel Imms a96734220a Use TS declarationMap
This will make go to definition go to the implementation instead of
the .d.ts file
2019-06-27 11:31:36 -07:00
Daniel Imms 73521390d2 Merge pull request #2268 from termius/include-css
Include CSS into the package
2019-06-27 07:57:03 -07:00
Vadim Zakondyrin 6c8f88754b Include CSS into the package 2019-06-27 10:21:58 +06:00
Jörg Breitbart 63a4e8ffde Merge branch 'master' into parser_colon_notation 2019-06-25 16:07:50 +02:00
Daniel Imms c50a6ef415 Merge pull request #2262 from Tyriar/word_sep
Add wordSeparator to demo
2019-06-24 20:27:45 -07:00
Daniel Imms b138d6574e Merge branch 'master' into word_sep 2019-06-24 20:27:39 -07:00
Daniel Imms 5459c48525 Add wordSeparator to demo 2019-06-24 20:20:08 -07:00
Daniel Imms 6b036e1222 Merge pull request #2190 from jerch/benchmark_integration
inital integration of xterm-benchmark
2019-06-24 19:50:58 -07:00
Jörg Breitbart 00d4c8162d remove azure job, change api test path 2019-06-24 22:53:13 +02:00
Jörg Breitbart b6b810b625 Merge branch 'benchmark_integration' of github.com:jerch/xterm.js into benchmark_integration 2019-06-24 22:47:37 +02:00
Jörg Breitbart 901b995a21 Merge branch 'master' into benchmark_integration 2019-06-24 22:47:20 +02:00
Daniel Imms 88308f058c Remove ITerminal dependency in SelectionManager 2019-06-23 14:29:59 -07:00
Daniel Imms 4ecd0d2053 Merge branch 'master' into selection_manager_browser 2019-06-23 14:28:12 -07:00
Daniel Imms 479010d29e Merge pull request #2256 from Tyriar/tests
Fix composition tests
2019-06-23 14:27:42 -07:00
Daniel Imms 83b8e1bd30 Fix composition tests 2019-06-23 14:21:05 -07:00
Daniel Imms 33a640a7a8 Move applicationCursor into core service 2019-06-23 14:06:06 -07:00
Daniel Imms 99a31b3862 Merge pull request #1790 from Tyriar/webgl2
WebGL Renderer
2019-06-23 13:28:35 -07:00
Daniel Imms 533f3bd0dc Remove unneeded TODOs 2019-06-23 13:12:49 -07:00
Daniel Imms fdae27e7ea Remove unused Platform.ts in webgl 2019-06-23 13:11:25 -07:00
Daniel Imms e10adaf3d2 Have yarn clean also delete addon out/ 2019-06-23 13:10:37 -07:00
Daniel Imms fb420d70e4 Merge branch 'master' into webgl2 2019-06-23 13:01:42 -07:00
Daniel Imms f4f1e0276e Merge pull request #2247 from Tyriar/core_service
Move handler into CoreService and adopt
2019-06-23 13:01:27 -07:00
Daniel Imms 910ece4f09 Merge branch 'master' into benchmark_integration 2019-06-23 10:26:33 -07:00
Daniel Imms bfa7a2df76 Move handler into CoreService and adopt
This also fine tunes some of the data events to not clear selection
and scroll to the bottom of the viewport anymore.

Part of #1507
Fixes #2112
2019-06-23 10:10:17 -07:00
Daniel Imms 94a2ad9416 Merge pull request #2246 from Tyriar/alt_click_functional
Change alt click to functional and move into browser
2019-06-22 19:37:00 -07:00
Daniel Imms 87897a7ee5 Move selection manager types into browser 2019-06-22 18:27:25 -07:00
Daniel Imms f903dbde45 Add some tests for MoveToCell 2019-06-22 18:16:33 -07:00
Daniel Imms 22a7e48f04 Move alt click into browser 2019-06-22 18:00:03 -07:00
Daniel Imms 13a63efdab Change AltClickHandler to be functional 2019-06-22 17:55:59 -07:00
Daniel Imms 7454701c0b Remove AltHandler member usage 2019-06-22 17:53:11 -07:00
Daniel Imms da1484ac47 Return a sequence from AltClickHandler 2019-06-22 09:44:25 -07:00
Daniel Imms 00969508d9 Remove some private member deps in AltClickHandler 2019-06-22 09:40:11 -07:00
Daniel Imms 731070fdc2 Merge pull request #2245 from Tyriar/clipboard_term_dep
Remove some terminal dependencies in Clipboard and SelectionManager
2019-06-21 20:39:06 -07:00
Daniel Imms 9174f60d94 Move screen element into ctor 2019-06-21 20:20:48 -07:00
Daniel Imms 0ba90a9349 Adopt options service in selection manager 2019-06-21 20:12:17 -07:00
Daniel Imms 72f615da14 Remove some of terminal dependency in SelectionManager 2019-06-21 20:08:58 -07:00
Daniel Imms 0bb2b3446d Merge branch 'master' into clipboard_term_dep 2019-06-21 20:02:07 -07:00
Daniel Imms 62e2b00bd5 Remove terminal dep in clipboard 2019-06-21 19:54:11 -07:00
Daniel Imms b7dba18847 Merge branch 'master' into webgl2 2019-06-21 19:38:44 -07:00
Daniel Imms 60eb13e223 Merge pull request #2244 from MaxRis/word-separator-option
Define wordSeparator option
2019-06-21 11:53:36 -07:00
Max Risuhin 1b2811075c Define wordSeparator option 2019-06-21 16:35:26 +03:00
Daniel Imms 96eafd32db Merge pull request #2242 from VivaLosDoyers/readme_typo_fix
Fix a typo in the README
2019-06-18 19:13:21 -07:00
Jörg Breitbart 1dc4e36972 fix CSI bug, cleanup test 2019-06-19 00:42:20 +02:00
Michael Miller a0ccc9b78b Fix a type in the README
"Perfomant" should be "Performant"
2019-06-18 15:28:41 -07:00
Jörg Breitbart a28761bf3e restructured test folder 2019-06-19 00:07:09 +02:00
Jörg Breitbart 8ce67cb880 add COLORTERM to env in demo 2019-06-18 18:55:24 +02:00
Jörg Breitbart c80ff1e1d1 cleanup interface 2019-06-18 15:37:53 +02:00
Jörg Breitbart fc778c76c2 add usage example for action handler 2019-06-18 15:23:36 +02:00
Jörg Breitbart f984204570 parser tests 2019-06-18 14:56:32 +02:00
Jörg Breitbart 069e51064a remove as number[] type conversions from tests 2019-06-18 14:47:35 +02:00
Jörg Breitbart 6f047aa7ea SGR tests, fix bug in 38:5 handling 2019-06-18 14:40:15 +02:00
Jörg Breitbart e8290af194 Merge branch 'master' into benchmark_integration 2019-06-18 03:08:07 +02:00
Jörg Breitbart c558d485e0 apply colon handling to SGR 2019-06-18 03:00:53 +02:00
Jörg Breitbart 62007c3be4 comment storable amount of params in parser 2019-06-17 23:42:56 +02:00
Jörg Breitbart 1dd63a6d66 apply type over codebase 2019-06-17 23:31:54 +02:00
Daniel Imms 5321f0373f Fix quote and comma 2019-06-17 13:42:44 -07:00
Jörg Breitbart c5385a640d add ":" to param transitions, fix parse loop and tests 2019-06-17 21:54:51 +02:00
Jörg Breitbart cec1aa3f33 interfaces, add test for clone 2019-06-17 21:17:56 +02:00
Jörg Breitbart 24c39f664d remove unused import 2019-06-17 20:55:29 +02:00
Jörg Breitbart 383849b36f Params type implementation 2019-06-17 20:49:12 +02:00
Daniel Imms 1b7862ce8a Move slice typed array util into webgl addon 2019-06-17 07:35:52 -07:00
Daniel Imms 5100c7a30d Use Constants from core 2019-06-16 00:17:14 -07:00
Daniel Imms bc24a6cdd1 Merge branch 'master' into webgl2 2019-06-16 00:13:15 -07:00
Daniel Imms 795ca2af2e Merge pull request #2239 from Tyriar/charjoiner_layer
Move some parts of renderer to browser
2019-06-16 00:12:55 -07:00
Daniel Imms de86d140c5 Fix absolute imports 2019-06-16 00:02:10 -07:00
Daniel Imms a6f4931810 Move DomRendererRowFactory to browser 2019-06-15 23:59:32 -07:00
Daniel Imms c4f903e283 Move atlas/Constants to browser 2019-06-15 23:53:45 -07:00
Daniel Imms c0e27b98e8 Move LRUMap to browser 2019-06-15 23:51:36 -07:00
Daniel Imms b5093e0c29 Move GridCache to browser 2019-06-15 23:47:35 -07:00
Daniel Imms e35d911fd1 Move char joiner registry to browser layer 2019-06-15 23:45:03 -07:00
Daniel Imms 308cf8247a Remove terminal dep in char joiner registry 2019-06-15 23:40:31 -07:00
Daniel Imms d4e50293a1 Merge pull request #2238 from Tyriar/selection_layering
Move SelectionModel to browser
2019-06-15 23:34:39 -07:00
Daniel Imms 6e90b7371b Move SelectionModel to browser, fix strict 2019-06-15 23:28:51 -07:00
Daniel Imms 9980457eef Remove terminal dep from SelectionModel 2019-06-15 23:10:25 -07:00
Daniel Imms b1004f2007 Merge branch 'master' into benchmark_integration 2019-06-15 22:47:33 -07:00
Daniel Imms 26c854db49 Merge pull request #2237 from Tyriar/mouse_service
Introduce mouse service
2019-06-15 21:07:44 -07:00
Daniel Imms 702ecb185f Merge branch 'master' into mouse_service 2019-06-15 19:42:24 -07:00
Daniel Imms 8a59389358 Merge pull request #2236 from Tyriar/fix_broken_tests
Fix restore cursor related tests
2019-06-15 19:41:45 -07:00
Daniel Imms a4d18a3b23 Introduce mouse service 2019-06-15 19:40:51 -07:00
Daniel Imms 9bb16e4b16 Fix restore cursor related tests
Weird failure happening sometimes after #2217, not sure why pipelines
didn't pick it up.
2019-06-15 19:24:14 -07:00
Daniel Imms 8b4901e8f3 Reduce diff 2019-06-15 16:43:01 -07:00
Daniel Imms 7148358acf Prevent crash on true color, add TODOs for it 2019-06-15 16:40:45 -07:00
Daniel Imms 1ebae41a8b Pull attribute compat stuff into addon 2019-06-15 16:35:38 -07:00
Daniel Imms 45ec3b1e57 Merge branch 'master' into webgl2 2019-06-15 14:50:23 -07:00
Daniel Imms 20809a042f Merge pull request #2235 from Tyriar/webgl_prep
Pulling unrelated changes in from WebGL PR
2019-06-15 14:49:42 -07:00
Daniel Imms 6e04058783 Reduce diff 2019-06-15 14:47:44 -07:00
Daniel Imms 29db1a2b2b Refresh viewport after setting renderer and set correct end refresh row 2019-06-15 14:44:05 -07:00
Daniel Imms ed9000cb1d Clarify ITheme.selection color 2019-06-15 14:42:30 -07:00
Daniel Imms 2bd043b664 Remove FLAGS constant
Only WebGL uses this
2019-06-15 14:42:04 -07:00
Daniel Imms 04ba3510e4 Adopt automated released in webgl addon 2019-06-15 14:37:44 -07:00
Daniel Imms 05188a985c Merge branch 'master' into webgl2 2019-06-15 14:37:04 -07:00
Daniel Imms 49ba3c8068 Merge pull request #2234 from Tyriar/trigger_build
npmignore webpack.config.js (test automated release)
2019-06-15 14:30:21 -07:00
Daniel Imms a46c723020 npmignore webpack.config.js (test automated release)
Part of #2165
2019-06-15 14:29:41 -07:00
Daniel Imms c68f413c48 Merge pull request #2233 from Tyriar/publish_improvements_2
Publish addons with right cwd and don't exit
2019-06-15 14:27:43 -07:00
Daniel Imms 91c4ca5e0d Publish addons with right cwd and don't exit
Part of #2165
2019-06-15 14:27:04 -07:00
Daniel Imms 8de555d7d9 Merge pull request #2232 from Tyriar/publish_improvements
Add publish dry run feature and automate addon released based on changed files
2019-06-15 14:16:38 -07:00
Daniel Imms d06fd04465 Move addon const under addon comment 2019-06-15 14:10:48 -07:00
Daniel Imms 64403f2dca Publish addons and xterm based on whether files changed
Fixes #2165
2019-06-15 14:06:45 -07:00
Daniel Imms 15c99869f5 Start of publishing addons
Part of #2165
2019-06-15 13:51:13 -07:00
Daniel Imms 2e83483e08 Support dry run publishing using --dry 2019-06-15 13:42:52 -07:00
Daniel Imms 846a1897e9 Merge pull request #2217 from termius/fix-cursor
Fix saved cursor position on resize of alt screen
2019-06-15 13:22:19 -07:00
Daniel Imms 699e721c45 Add a test for DECRC 2019-06-15 13:17:43 -07:00
Daniel Imms 173c4d83b3 Merge branch 'master' into fix-cursor 2019-06-15 13:04:28 -07:00
Daniel Imms 07b6b69be7 Remove old comment 2019-06-15 00:30:45 -07:00
Daniel Imms 15647a0301 Speed up webgl tests 2019-06-15 00:27:12 -07:00
Daniel Imms dd9b755329 Fix webgl api tests 2019-06-15 00:17:48 -07:00
Daniel Imms 765297e67c Add addon typings 2019-06-15 00:11:34 -07:00
Daniel Imms d272422c0b Fix webgl addon version 2019-06-15 00:06:04 -07:00
Daniel Imms eae0ab9e02 Add a webgl button to the demo 2019-06-15 00:04:02 -07:00
Daniel Imms 50d6711fc8 Fix webgl packaging 2019-06-15 00:01:00 -07:00
Daniel Imms d7daa53b50 Move webgl renderer into addon dir 2019-06-14 23:55:17 -07:00
Daniel Imms 535c8a5d4b Merge branch 'master' into webgl2 2019-06-14 23:20:03 -07:00
Daniel Imms 27d724a13a Merge pull request #2231 from Tyriar/refactor_buffer_line
Pull types and classes out of BufferLine
2019-06-14 23:15:08 -07:00
Daniel Imms 91598814c6 Fix lint 2019-06-14 23:00:48 -07:00
Daniel Imms ae216c3088 Move AttributeData into separate file 2019-06-14 23:00:33 -07:00
Daniel Imms 45682f0e76 Move Content to Constants 2019-06-14 22:55:06 -07:00
Daniel Imms 4330741c5d Move CellData into new file 2019-06-14 22:51:08 -07:00
Daniel Imms 3adddbf95a Move some buffer constants into buffer/Constants 2019-06-14 22:39:35 -07:00
Daniel Imms b7cdbb99ca Remove default exports in webgl char atlas files 2019-06-14 22:27:07 -07:00
Daniel Imms ddb9fbd1d6 Improve type safety in webgl 2019-06-14 22:25:43 -07:00
Daniel Imms 3a7aa77950 Remove remaining parts of renderer API, fix webgl tests 2019-06-14 22:18:53 -07:00
Daniel Imms 6c232a0e11 Remove renderer API 2019-06-14 22:03:55 -07:00
Daniel Imms 6ff90451ff Merge branch 'master' into webgl2 2019-06-14 21:52:46 -07:00
Daniel Imms d2f800f6a9 Merge pull request #2229 from Tyriar/types_constants
Split Types.ts into Types.d.ts and Constants.ts
2019-06-14 21:46:59 -07:00
Daniel Imms 7b6dd9fe9d Rename browser Types.ts to .d.ts 2019-06-14 21:39:22 -07:00
Daniel Imms 913faef3b8 Split src/ Types.ts into d.ts and Constants 2019-06-14 21:38:19 -07:00
Daniel Imms 0b2df9d611 Split common/ Types.ts into .d.ts and Constants.ts 2019-06-14 21:30:51 -07:00
Daniel Imms 6e9c7888d2 Merge pull request #2228 from Tyriar/fix_dpr_change
Fix screen dpr change not refreshing canvas renderer
2019-06-14 21:08:11 -07:00
Daniel Imms 332cc3901d Merge pull request #2222 from Tyriar/2220_setTheme
Fix NPE in _setTheme
2019-06-14 20:57:33 -07:00
Daniel Imms c94183a5a1 Merge branch 'master' into fix_dpr_change 2019-06-14 20:56:51 -07:00
Daniel Imms 4daf67245d Merge branch 'master' into webgl2 2019-06-14 20:56:27 -07:00
Daniel Imms 2584de8630 Clear webgl model after theme or dpr change 2019-06-14 20:55:52 -07:00
Daniel Imms 4b4b58e662 Fix screen dpr change not refreshing canvas renderer 2019-06-14 20:38:35 -07:00
Daniel Imms e53cae8c69 Fix screen dpr change not refreshing canvas renderer 2019-06-14 20:37:58 -07:00
Daniel Imms e959cce899 Remove webgl LRUMap 2019-06-14 19:35:05 -07:00
Daniel Imms 21d07d1f0e Remove unused portion of CharAtlasGenerator 2019-06-14 19:34:31 -07:00
Daniel Imms d4169f3538 Fix tests 2019-06-14 19:31:42 -07:00
Daniel Imms a19ea1ec52 Remove forked LifeCycle and TypedArray files 2019-06-14 15:46:07 -07:00
Daniel Imms cdc9f792a5 Merge pull request #2227 from Tyriar/2224_dom_cursor
Show text when cursor blinks in DOM renderer
2019-06-14 12:57:11 -07:00
Daniel Imms 1a44e3634a Show text when cursor blinks in DOM renderer
Fixes #2224
2019-06-14 12:39:01 -07:00
Daniel Imms a5e466869c Fix lint 2019-06-13 09:51:22 -07:00
Daniel Imms 57eaa24ea0 Fix NPE in _setTheme
Fixes #2220
2019-06-13 08:51:42 -07:00
Daniel Imms ee81f50f3a Fix conflicts 2019-06-12 18:25:05 -07:00
Daniel Imms 7c6db2ef5b Merge branch 'master' into webgl2 2019-06-12 18:20:39 -07:00
Daniel Imms 26f967ec3f Merge pull request #2221 from blink1073/style-field
Add a style field to package.json
2019-06-12 14:04:48 -07:00
Steven Silvester d2c32c6f2d declare style field 2019-06-12 04:45:11 -05:00
Daniel Imms 68db0661fc Merge pull request #2219 from Tyriar/addon_webpack
Webpack addons
2019-06-10 15:14:54 -07:00
Daniel Imms c4311cb88a Merge pull request #2216 from Tyriar/drop_ie_support
Partially support IE11
2019-06-10 15:14:38 -07:00
Daniel Imms 3e91f08e34 Bump addon versions 2019-06-10 14:51:09 -07:00
Daniel Imms d9ce9e96f5 Remove packageAddons step on install
It's not needed when the demo doesn't use it
2019-06-10 14:47:10 -07:00
Daniel Imms b657a1f30e Use addon tsc output in the demo, similar to the core lib 2019-06-10 14:41:43 -07:00
Daniel Imms 989610e8c3 Webpack the addons 2019-06-10 14:28:07 -07:00
Vadim Zakondyrin 311f6b6e84 Fix saved cursor position on resize of alt screen 2019-06-10 14:27:48 +06:00
Daniel Imms 044a7e327f Clarify partial support 2019-06-09 19:35:47 -07:00
Daniel Imms f9b92f8865 Add note about partial support for IE11 2019-06-09 16:19:03 -07:00
Daniel Imms 1bbb51fc17 Fix compile 2019-06-09 15:57:24 -07:00
Daniel Imms 02868c1033 Remove support for IE11
Fixes #1889
2019-06-09 15:52:37 -07:00
Jörg Breitbart 5f8b7cda04 Merge branch 'master' into benchmark_integration 2019-06-09 23:09:57 +02:00
Jörg Breitbart e77969372b setup benchmark pipeline with eval run 2019-06-09 23:00:11 +02:00
Daniel Imms 566f5944dd Merge pull request #2214 from Tyriar/strings_browser
Move Strings to browser
2019-06-09 13:33:25 -07:00
Jörg Breitbart b559a5a39b lower resources needed for test 2019-06-09 22:23:15 +02:00
Jörg Breitbart 1794532cb1 test pipeline 2019-06-09 22:08:41 +02:00
Jörg Breitbart e0d69db23e better separation of benchmarks 2019-06-09 21:53:24 +02:00
Daniel Imms 46ce3d29c3 API polish/grammar/wrapping 2019-06-09 12:07:27 -07:00
Daniel Imms 39cff978df Add missing docs to xterm.d.ts
Fixes #2215
2019-06-09 12:03:00 -07:00
Daniel Imms f59b3f000d Move Strings to browser 2019-06-09 11:46:20 -07:00
Jörg Breitbart 03839f06b8 remove remnants 2019-06-09 18:02:17 +02:00
Jörg Breitbart fc7411c807 remove wrong d.ts 2019-06-09 17:35:25 +02:00
Jörg Breitbart e920f1db86 cleaner approach 2019-06-09 17:31:57 +02:00
Jörg Breitbart 3204d9d7c9 fix benchmark script 2019-06-09 15:19:48 +02:00
Jörg Breitbart 674914bbb7 moving benchmarks out of './src':
Harder than I thought for several reasons:
- need access to common to tests the subparts, thus the unified tsconfig
  in tests does not work (need the path translation to those parts)
- moving next to src I cannot use direct imports anymore (source files
  are out of rootDir), thus have to rely on d.ts files in out which is
  quite suboptimal as many parts do not expose the declaration files
  (can only type Terminal as any atm)
- compiler output has to resemble the '../out/..' import logic of the TS
  files or require fails, thus moved the ouput to './benchmark' for now

Conclusion: Not yet there, maybe not a good idea at all to move those
tests out of './src' as they heavily rely on not exported internals.
Needs more fiddling with the repo structure.
2019-06-09 14:51:44 +02:00
Jörg Breitbart 1b31c01b75 Merge branch 'master' into benchmark_integration 2019-06-09 12:37:06 +02:00
Daniel Imms 16217003aa Merge pull request #2211 from Tyriar/remove_ee
Remove old event emitter, rename new one to EventEmitter
2019-06-08 21:55:57 -07:00
Daniel Imms 07cef1ec9e Increase attach addon timeouts 2019-06-08 21:51:24 -07:00
Daniel Imms 73a08f7850 Consolidate service init 2019-06-08 21:46:13 -07:00
Daniel Imms 5aeb70bea4 Merge branch 'master' into remove_ee 2019-06-08 21:45:30 -07:00
Daniel Imms 58ec3f9973 Merge pull request #2210 from Tyriar/buffer_owner
Move buffer ownership to IBufferService
2019-06-08 21:43:32 -07:00
Daniel Imms 1b07a03b2f Properly reset buffer after Terminal.reset 2019-06-08 21:39:10 -07:00
Daniel Imms 80ce33f9ef Rename EventEmitter2 to EventEmitter
Fixes #2029
2019-06-08 21:33:02 -07:00
Daniel Imms 447fc4f3fa Remove old event emitter
Fixes #2029
2019-06-08 21:30:31 -07:00
Daniel Imms f49daf02a3 Fix tests and imports 2019-06-08 20:52:37 -07:00
Daniel Imms 09b0bbed32 Move buffer/buffers ownership to BufferService 2019-06-08 20:21:29 -07:00
Daniel Imms c5c370801c Merge pull request #2209 from Tyriar/render_service
Create RenderService in browser (previously RenderCoordinator)
2019-06-08 20:04:19 -07:00
Daniel Imms e21826f6cb Move MouseHelper.test into browser 2019-06-08 19:40:18 -07:00
Daniel Imms 5dbab76bed Move MouseHelper into browser 2019-06-08 19:34:38 -07:00
Daniel Imms cbfbe232d0 Rename coordinator to service 2019-06-08 19:28:43 -07:00
Daniel Imms 54d7bb0b38 Move RenderService into browser 2019-06-08 19:26:31 -07:00
Daniel Imms 9ad01080f3 Introduce RenderService
Used to be RenderCoordinator
2019-06-08 19:24:48 -07:00
Daniel Imms c314eaaf86 Merge pull request #2208 from Tyriar/buffer_common
Move buffer to common
2019-06-08 19:08:43 -07:00
Daniel Imms b1eecf10ff Remove relative imports with common 2019-06-08 18:05:12 -07:00
Daniel Imms f2e60d4c43 Remove ! in Buffer ctor 2019-06-08 18:01:27 -07:00
Daniel Imms 9a237cb205 Move BufferSet* into common 2019-06-08 18:00:04 -07:00
Daniel Imms 62ff97c82d Move BufferSet deps to common 2019-06-08 17:58:56 -07:00
Daniel Imms 658cd987d9 Move Buffer.test and test utils to common 2019-06-08 17:56:55 -07:00
Daniel Imms 50378403cf Move Buffer to common 2019-06-08 17:43:40 -07:00
Daniel Imms 5c93f2971e Move buffer types to common 2019-06-08 17:17:17 -07:00
Daniel Imms 291fc7368d Fix remaining tests 2019-06-08 17:12:18 -07:00
Daniel Imms c44524b553 Use MockBufferService in tests 2019-06-08 17:06:43 -07:00
Daniel Imms 0dfc1afc21 Create BufferService 2019-06-08 16:59:28 -07:00
Daniel Imms a6540c8d06 Freeze DEFAULT_OPTIONS to prevent accidental edits 2019-06-08 16:48:12 -07:00
Daniel Imms cd61f95612 Adopt options service in buffer 2019-06-08 16:46:03 -07:00
Daniel Imms e2cea7578b Adopt options service in buffer 2019-06-08 16:24:36 -07:00
Daniel Imms 00501bd2e8 Merge pull request #2207 from Tyriar/common_browser
Merge core into common, rename ui to browser
2019-06-08 16:19:21 -07:00
Daniel Imms 6e91875bc4 Rename ui to browser 2019-06-08 16:14:29 -07:00
Daniel Imms 98cda5ca86 Remove duplicate imports 2019-06-08 16:12:20 -07:00
Daniel Imms f8e7ff24d9 Merge core into common
Part of #1507
2019-06-08 16:09:27 -07:00
Daniel Imms df4a96493c Merge pull request #2206 from Tyriar/options_move
Move OptionsService into services folder
2019-06-08 16:04:22 -07:00
Daniel Imms 1704548b46 Move OptionsService into services folder 2019-06-08 15:58:44 -07:00
Daniel Imms b9954ec643 Merge pull request #2205 from Tyriar/char_dim_service
Create CharSizeService
2019-06-08 15:53:25 -07:00
Daniel Imms 9df3a3671d Adopt CharSizeService in RenderCoordinator 2019-06-08 15:46:12 -07:00
Daniel Imms 6375d9b88e Fix event firing 2019-06-08 15:45:07 -07:00
Daniel Imms 47fab14efc Adopt in Terminal 2019-06-08 15:29:16 -07:00
Daniel Imms 0f2d560e01 Adopt in SelectionManager 2019-06-08 15:26:53 -07:00
Daniel Imms 53c3151de6 Adopt in Viewport 2019-06-08 15:25:34 -07:00
Daniel Imms 760128e0f6 Adopt in renderers 2019-06-08 15:24:30 -07:00
Daniel Imms bfcd2b52c2 Adopt CharSizeService in CompositionHelper 2019-06-08 15:22:17 -07:00
Daniel Imms 6246bb5026 Adopt CharSizeService in MouseHelper 2019-06-08 15:20:03 -07:00
Daniel Imms 38bb122bbd CharDimensions -> CharSize 2019-06-08 15:09:55 -07:00
Daniel Imms 2e243feebe Create ICharDimensionsService 2019-06-08 14:54:05 -07:00
Daniel Imms 395530da96 Merge branch 'master' into benchmark_integration 2019-06-08 14:24:33 -07:00
Daniel Imms 2eb77cc4da Merge pull request #2203 from Tyriar/char_width
Move CharWidth into common and move API tests into ./test
2019-06-08 14:24:14 -07:00
Daniel Imms a1e4cd6931 Remove node folder 2019-06-08 14:19:47 -07:00
Daniel Imms 4493ed2575 Rename .integration to .test, this fixes debugging that test 2019-06-08 11:58:52 -07:00
Daniel Imms a29c0fa095 Move other api tests into test folder 2019-06-08 11:50:35 -07:00
Daniel Imms a365b57361 Move node to root-level tests folder 2019-06-08 11:49:14 -07:00
Daniel Imms 0917ce34c6 Move CharWidth.api into node module 2019-06-08 11:39:16 -07:00
Daniel Imms 1546e0c12d Move CharWidth into common 2019-06-08 11:35:52 -07:00
Daniel Imms e758a78f2e Move integration tests into CharWidth.api 2019-06-08 11:32:32 -07:00
Daniel Imms 75d4890e7d Fix debugging launch targets 2019-06-08 11:32:22 -07:00
Jörg Breitbart cb6f3b3be4 Merge branch 'benchmark_integration' of github.com:jerch/xterm.js into benchmark_integration 2019-06-07 22:43:06 +02:00
Daniel Imms 3e3eb4cd76 Merge branch 'master' into benchmark_integration 2019-06-07 12:57:50 -07:00
Jörg Breitbart 1e06af15ac Merge branch 'master' into benchmark_integration 2019-06-07 21:48:24 +02:00
Jörg Breitbart 8e1ebe42b1 fix import, set copyright note 2019-06-07 21:39:07 +02:00
Daniel Imms 7139ee1192 Merge pull request #2199 from jerch/fix_REP
fix repeat preceding character sequence (REP)
2019-06-07 11:02:35 -07:00
Jörg Breitbart 15215a97ff Merge branch 'master' into benchmark_integration 2019-06-07 19:25:01 +02:00
Jörg Breitbart ce91fba1d9 fix typo 2019-06-07 19:14:52 +02:00
Jörg Breitbart b17164520c skip benchmark folders in git 2019-06-07 19:14:04 +02:00
Jörg Breitbart 925e58deb1 remove private access 2019-06-07 18:51:57 +02:00
Jörg Breitbart 5f0e024404 fix REP 2019-06-07 14:45:14 +02:00
Daniel Imms 4cfba558fa Merge pull request #2198 from jerch/2189_terminfo_issue
change TERM to xterm-256color in demo
2019-06-06 20:45:04 -07:00
Jörg Breitbart f3977afe77 change TERM to xterm-256color in demo 2019-06-07 00:36:30 +02:00
Daniel Imms 5c21a6c532 Merge pull request #2197 from xtermjs/fix_soft_reset
Properly clone default attr data on DECSTR
2019-06-06 15:13:54 -07:00
Daniel Imms d271095e28 Freeze DEFAULT_ATTR_DATA to hard fail when not cloned 2019-06-06 15:05:34 -07:00
Daniel Imms 767eec3a2c Properly clone default attr data on DECSTR
Fixes #2196
2019-06-06 14:59:31 -07:00
Daniel Imms 357e6dcd02 Merge pull request #2195 from xtermjs/Tyriar-patch-1
Fix addon import quotes
2019-06-06 12:56:30 -07:00
Daniel Imms f5ee335a43 Fix addon import quotes 2019-06-06 12:56:04 -07:00
Daniel Imms 7f4ba5bf57 Merge pull request #2194 from Tyriar/addon_docs
Add addon docs to README
2019-06-06 12:55:10 -07:00
Daniel Imms c4db8879ac Improve grammar, add old addon link 2019-06-06 12:54:50 -07:00
Daniel Imms 1473afd1b6 Add addon docs to README
Fixes #2192
2019-06-06 12:40:06 -07:00
Daniel Imms 65ba5f06de Merge pull request #2191 from xtermjs/dependabot/npm_and_yarn/js-yaml-3.13.1
Bump js-yaml from 3.12.0 to 3.13.1
2019-06-06 11:35:12 -07:00
dependabot[bot] 678433a92f Bump js-yaml from 3.12.0 to 3.13.1
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 3.12.0 to 3.13.1.
- [Release notes](https://github.com/nodeca/js-yaml/releases)
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/3.12.0...3.13.1)

Signed-off-by: dependabot[bot] <support@github.com>
2019-06-06 18:22:16 +00:00
Jörg Breitbart 3ff3a5d78d add benchmark for write and writeUtf8 2019-06-06 15:46:52 +02:00
Jörg Breitbart e1f7c8a2df link against npm package 2019-06-06 02:59:42 +02:00
Jörg Breitbart 06949df560 make linter happy 2019-06-06 02:43:22 +02:00
Jörg Breitbart e05ae83d6a inital integration of xterm-benchmark 2019-06-06 02:31:41 +02:00
jerch 69ad7554bd Merge pull request #2187 from jerch/parser_inner_loops
relocate parser look ahead loops
2019-06-05 16:19:59 +02:00
Jörg Breitbart cc05dcf763 Merge branch 'parser_inner_loops' of github.com:jerch/xterm.js into parser_inner_loops 2019-06-05 16:15:21 +02:00
Jörg Breitbart d1ec40016c Merge branch 'master' into parser_inner_loops 2019-06-05 16:15:09 +02:00
Jörg Breitbart 489cbfc3da delete remnants 2019-06-05 16:14:16 +02:00
Daniel Imms c35ea040c7 Merge branch 'master' into parser_inner_loops 2019-06-05 06:51:42 -07:00
Daniel Imms 91ec163b4f Merge pull request #2183 from Tyriar/search_strict
Turn on TS strict mode in search addon
2019-06-05 06:26:48 -07:00
Daniel Imms 2526b2d76d Merge branch 'master' into search_strict 2019-06-05 06:22:05 -07:00
Daniel Imms 360bf64562 Merge pull request #2188 from Tyriar/test_warning
Fix test warning
2019-06-05 06:21:46 -07:00
Daniel Imms c1c55aeb78 Merge pull request #2186 from Tyriar/typings_test
Remove typings test
2019-06-05 06:13:05 -07:00
Daniel Imms 4e9163fee4 Fix test warning 2019-06-05 05:35:48 -07:00
Jörg Breitbart 97b11164c1 cleanup code 2019-06-05 10:21:37 +02:00
Jörg Breitbart bf6c684652 relocate loop shortcuts, cleanup parse 2019-06-05 10:15:12 +02:00
Daniel Imms 0ab72d5ce9 Merge branch 'master' into search_strict 2019-06-04 23:54:11 -07:00
Daniel Imms 155d552b35 Merge pull request #2184 from Tyriar/typings_buffer_cell
Correct IBufferLine.getCell API
2019-06-04 23:53:51 -07:00
Daniel Imms 9994047dc7 Remove typings test
Fixes #2185
2019-06-04 23:52:17 -07:00
Daniel Imms c8cd47b51a Correct IBufferLine.getCell API
Fixes #2182
2019-06-04 23:38:39 -07:00
Daniel Imms 031fbde580 Turn on TS strict in search addon
Fixes #2163
2019-06-04 23:37:12 -07:00
Daniel Imms be2c29c95a Remove old redeclared xterm types in search addon 2019-06-04 23:19:26 -07:00
Daniel Imms 27f040f145 Merge pull request #2180 from xtermjs/remove_package_scope
Remove @xtermjs package scope
2019-06-04 15:35:52 -07:00
Daniel Imms 7cc00e09ac Fix typings location 2019-06-04 11:38:44 -07:00
Daniel Imms fee08d74e0 Remove old ITerminalAddon def 2019-06-04 11:34:55 -07:00
Daniel Imms 1a8c7ef596 Bump versions
A lot of them were wrong, updating and publishing on this
2019-06-04 11:11:03 -07:00
Daniel Imms d4be839d8d Remove @xtermjs package scope
Too big of a change for now, I think we should do this when/if we
move to GH package registry (we would have to I think).
2019-06-04 11:07:11 -07:00
jerch d5fddae788 Merge pull request #2177 from jerch/1823_parser_cleanup
parser cleanup
2019-06-03 01:28:06 +02:00
Jörg Breitbart 9442d6e7ff enum for table packing 2019-06-03 01:23:54 +02:00
Jörg Breitbart e1243473e8 use NON_ASCII_PRINTABLE, cleanup ERROR action 2019-06-03 00:28:32 +02:00
Jörg Breitbart 4f412cb6b0 use fill for default transition; create r from blueprint 2019-06-03 00:11:25 +02:00
Jörg Breitbart 9bd7c49003 remove transition table Array fallback, cleanup tests 2019-06-02 23:10:59 +02:00
Daniel Imms e1353c1912 Merge pull request #2164 from Tyriar/addons_in_repo
Move new format addons into repo, remove old addons
2019-06-02 13:06:41 -07:00
Daniel Imms 2b96be0506 Merge branch 'master' into addons_in_repo 2019-06-02 12:58:54 -07:00
jerch 35df028136 Merge pull request #2176 from jerch/single_testfile_argument
ability to inject particular testfile to yarn test
2019-06-02 21:54:37 +02:00
Jörg Breitbart 9b6e182bf6 simplify arg handling 2019-06-02 21:38:24 +02:00
Jörg Breitbart 21bad6b974 ability to inject particular testfile to yarn test 2019-06-02 21:27:48 +02:00
Daniel Imms ad909929cf Merge branch 'master' into addons_in_repo 2019-06-02 10:21:34 -07:00
Daniel Imms c8e267334d Merge pull request #2172 from Tyriar/bracketed_paste_test
Add test for bracketed paste
2019-06-01 19:52:48 -07:00
Daniel Imms c202773f6a Fix prepublishOnly again for new path 2019-06-01 15:14:13 -07:00
Daniel Imms d464341630 Rename to GH org for scope @xtermjs 2019-06-01 15:10:29 -07:00
Daniel Imms 6c18f5c1fe Use scoped packages, fix some typing issues 2019-06-01 15:07:59 -07:00
Daniel Imms 6817a20092 Fix addon prepublish scripts 2019-06-01 14:49:20 -07:00
Daniel Imms eafb322db3 Merge branch 'master' into webgl2 2019-06-01 14:36:59 -07:00
Daniel Imms b5be5c06ad Merge branch 'master' into addons_in_repo 2019-06-01 14:36:55 -07:00
Daniel Imms db2e2f6d7c Merge pull request #2171 from Tyriar/options_service
Introduce options service, move options handling code into common
2019-06-01 14:36:39 -07:00
Daniel Imms 9abb9ddf76 Merge branch 'master' into bracketed_paste_test 2019-06-01 14:31:59 -07:00
Daniel Imms 86d410bfe9 Also test exit bracketed paste mode 2019-06-01 14:31:36 -07:00
Daniel Imms 2925e976e0 Add test for bracketed paste
Part of #2170
Part of #2117
2019-06-01 14:29:26 -07:00
Daniel Imms df411c9308 Merge branch 'master' into webgl2 2019-06-01 11:13:49 -07:00
Daniel Imms d955873787 Merge branch 'master' into addons_in_repo 2019-06-01 11:13:46 -07:00
Daniel Imms ba758ad800 Merge branch 'master' into options_service 2019-06-01 11:13:42 -07:00
Daniel Imms 67db5884d5 Merge pull request #2168 from Tyriar/parser_core
Move EscapeSequenceParser to core
2019-06-01 10:59:48 -07:00
Daniel Imms 22c6a879bb Merge branch 'master' into parser_core 2019-06-01 10:11:31 -07:00
Daniel Imms 463b427000 Merge branch 'master' into addons_in_repo 2019-06-01 09:42:45 -07:00
Daniel Imms fb022eeae5 Merge branch 'master' into options_service 2019-06-01 09:38:36 -07:00
Daniel Imms 8a3c60d495 Clean up 2019-06-01 09:38:09 -07:00
Daniel Imms 041bd7a5d1 Move RenderCoordinator options listener out of Terminal 2019-06-01 09:34:13 -07:00
Daniel Imms 3ba7069787 Introduce options service 2019-06-01 09:29:11 -07:00
Daniel Imms 919c53a4b4 Merge pull request #2169 from Tyriar/dont_path_map_self
Remove path mapping to self modules
2019-06-01 08:52:40 -07:00
Daniel Imms 343d4c3348 Remove path mapping to self modules
This would cause imports in the common module to reference out/ instead
of src/, this leads to weird behavior when errors are introduced.
2019-06-01 08:38:58 -07:00
Daniel Imms 9068107f5a Remove path mapping to self modules
This would cause imports in the common module to reference out/ instead
of src/, this leads to weird behavior when errors are introduced.
2019-06-01 08:37:37 -07:00
jerch cedc8640b5 cleanup transition table class 2019-06-01 10:01:10 +02:00
Daniel Imms 4163b13be0 Move EscapeSequenceParser to core 2019-05-31 22:34:51 -07:00
Daniel Imms 087a40ff07 Fix AttachAddon test name 2019-05-31 21:51:17 -07:00
Daniel Imms 65189e0f28 Don't publish yarnrc 2019-05-31 21:49:46 -07:00
Daniel Imms 8e1f0697b9 Remove zmodem npm script, move scripts above deps 2019-05-31 21:47:37 -07:00
Daniel Imms 38ea4d1d1d Fix lint 2019-05-31 21:40:15 -07:00
Daniel Imms 27fc4d1639 Remove old style addon test 2019-05-31 21:39:37 -07:00
Daniel Imms 42d2ed0d3a Make addon tsconfigs more consistent 2019-05-31 21:29:44 -07:00
Daniel Imms 27b8cf9785 Remove old fit addon 2019-05-31 21:25:53 -07:00
Daniel Imms df72c70800 Add new fit addon 2019-05-31 21:25:35 -07:00
Daniel Imms 9637ee8d76 Make addons use consistent structure 2019-05-31 21:08:05 -07:00
Daniel Imms 42eb5e6b97 Remove all old addons except fit (no replacement yet) 2019-05-31 21:04:17 -07:00
Daniel Imms d9a074899b Remove temporary ITerminalAddon declarations 2019-05-31 20:09:38 -07:00
Daniel Imms 8235bf5dad Add search addon 2019-05-31 20:07:12 -07:00
Daniel Imms a1a63f99ff Add attach addon 2019-05-31 19:58:12 -07:00
Daniel Imms 1cde8a3167 Get tests passing 2019-05-31 19:34:10 -07:00
Daniel Imms ba5fe4bac2 Remove dependency on real web-links addon 2019-05-31 19:24:31 -07:00
Daniel Imms 3fa55475aa Remove unused coveralls npm script 2019-05-31 19:23:38 -07:00
Daniel Imms 65d420486d Clean up included web-links files 2019-05-31 19:23:19 -07:00
Daniel Imms 887b34110c Common web links sources 2019-05-31 19:02:54 -07:00
Daniel Imms 996555c556 Remove accidental sub-module 2019-05-31 19:02:30 -07:00
Daniel Imms 413f9ca3a1 Import web links into demo via node path 2019-05-31 18:58:48 -07:00
Daniel Imms 96b96cfcf8 Move tsconfig.all.json out of src 2019-05-31 18:14:10 -07:00
Daniel Imms 5b86f9291e Fix conflicts in webgl renderer 2019-05-31 18:10:46 -07:00
Daniel Imms 9feaf628b3 Merge remote-tracking branch 'origin/master' into webgl2 2019-05-31 18:06:42 -07:00
Daniel Imms 7a0ed764bd Merge pull request #2157 from Tyriar/1576_remove_static_atlas
Remove experimentalCharAtlas, make dynamic default
2019-05-31 16:08:15 -07:00
Daniel Imms b7a8519173 Merge branch 'master' into 1576_remove_static_atlas 2019-05-31 16:03:33 -07:00
Daniel Imms 0b70083e8f Merge pull request #2162 from Tyriar/remove_xterm_ts
Remove old browserify entry point
2019-05-31 12:28:57 -07:00
Daniel Imms c0ec7d1e6e Remove old browserify entry point
No longer needed after webpack refactor

Missed in #2132
2019-05-31 12:15:31 -07:00
Daniel Imms 653d38b19f Merge pull request #2149 from Tyriar/2148_update_after_ech
Update cells after an ECH
2019-05-31 12:03:42 -07:00
Daniel Imms dea12055de Merge branch 'master' into 2148_update_after_ech 2019-05-31 11:54:07 -07:00
Daniel Imms 468efed19d Merge pull request #2160 from Tyriar/clean_npmignore
Remove webpack config and out from package
2019-05-31 11:50:25 -07:00
Daniel Imms 1c3e7117de Merge pull request #2156 from Tyriar/1237_remove_enableBold
Remove enableBold
2019-05-31 11:12:24 -07:00
Daniel Imms fc91b954f2 Merge pull request #2159 from Tyriar/2158_wp_sourcemaps
Build sourcemaps in lib
2019-05-31 11:11:43 -07:00
Daniel Imms cdaf9d6f63 Remove webpack config and out from package
Part of #2152
2019-05-31 11:11:11 -07:00
Daniel Imms f8c311b59f Build sourcemaps in lib
Fixes #2158
2019-05-31 11:06:41 -07:00
Daniel Imms 53c71b3579 Remove experimentalCharAtlas, make dynamic default
The NoneCharAtlas is still available to swap in if we need it.

Fixes #1576
2019-05-31 10:54:23 -07:00
Daniel Imms b0986494a2 Merge pull request #2155 from Tyriar/1371_remove_destroy
Remove deprecated destroy API
2019-05-31 10:45:31 -07:00
Daniel Imms 94fc2064c2 Remove enableBold
fontWeightBold is the new way to do this

Fixes #1237
2019-05-31 10:43:52 -07:00
Daniel Imms b6b10b7ef6 Remove deprecated destroy API
Fixes #1371
2019-05-31 10:36:51 -07:00
Daniel Imms c08dcac183 Merge pull request #2153 from Tyriar/2152_npmignore
Exclude tslint and devcontainer from npm package
2019-05-31 09:49:02 -07:00
Daniel Imms e4099be954 Exclude tslint and devcontainer from npm package
Fixes #2152
2019-05-31 09:37:51 -07:00
Daniel Imms ac66444c65 Update cells after an ECH
Fixes #2148
2019-05-30 19:53:13 -07:00
Daniel Imms 32d6613811 Merge pull request #2147 from Tyriar/mocha_dev
Move mocha to dev dependencies
2019-05-30 18:01:10 -07:00
Daniel Imms e94812cef1 Move mocha to dev dependencies 2019-05-30 17:33:58 -07:00
Daniel Imms fad6e0f9f0 Merge pull request #2132 from Tyriar/ts_wp
Enable absolute imports and minify distributable
2019-05-30 17:01:10 -07:00
Daniel Imms 5a6287c77c Merge branch 'master' into ts_wp 2019-05-30 16:55:37 -07:00
Daniel Imms 64686b5865 Merge branch 'master' into ts_wp 2019-05-28 11:58:58 -07:00
Daniel Imms 8f89ebfe7c Merge branch 'master' into ts_wp 2019-05-26 13:30:53 -07:00
Daniel Imms 746b0169a9 Fix pipelines test script 2019-05-26 13:25:05 -07:00
Daniel Imms efee29d342 Quote test paths 2019-05-26 13:21:01 -07:00
Daniel Imms be11b4fc53 Remove prebuild step 2019-05-26 13:17:57 -07:00
Daniel Imms 6ec3a5c1d8 Add mocha
(we never actually declared this)
2019-05-26 13:11:25 -07:00
Daniel Imms 27af4dfa65 Remove nodemon coveralls zmodem.js 2019-05-26 13:06:20 -07:00
Daniel Imms 8ad89f153f Remove test coverage
Doesn't add much or tell the full story now with the integration tests
2019-05-26 13:05:10 -07:00
Daniel Imms a804685f85 Remove gulp and related deps 2019-05-26 13:03:58 -07:00
Daniel Imms c14fd03808 Test addons, don't use gulp 2019-05-26 13:00:08 -07:00
Daniel Imms 5998d22d14 Move css to css/, don't move it around 2019-05-26 12:49:08 -07:00
Daniel Imms eb6e3ab7f7 Fix tests on Windows (hopefully) 2019-05-26 12:43:33 -07:00
Daniel Imms 9f77de42eb Fix unit tests for mac/linux, remove -suite and -debug scripts 2019-05-26 12:37:24 -07:00
Daniel Imms 6cd774ae51 Merge branch 'master' into ts_wp 2019-05-26 12:18:10 -07:00
Daniel Imms c5d5ede15a Build addons and sources before package script 2019-05-26 12:17:57 -07:00
Daniel Imms d7cfd83a84 Explain addon imports in start.js 2019-05-26 12:00:02 -07:00
Daniel Imms 946fbf4a7d Document how the build works 2019-05-26 11:55:46 -07:00
Daniel Imms 4ed3b07199 Remove old dev watch package 2019-05-26 11:48:25 -07:00
Daniel Imms 49c8270b1c Use absolute paths for modules in root project 2019-05-26 11:46:58 -07:00
Daniel Imms d675de0b93 ui project absolute, tweak demo build 2019-05-26 11:38:48 -07:00
Daniel Imms 9ddf83ef26 Create a prod webpack config 2019-05-26 11:23:31 -07:00
Daniel Imms 873f0de0ec Get webpack build working 2019-05-26 11:19:42 -07:00
Daniel Imms 38afe991b2 Kind of working setup 2019-05-26 11:05:23 -07:00
Daniel Imms 10aae5d68a Merge branch 'master' into webgl2 2019-05-21 16:23:05 -07:00
Daniel Imms 493e8ad758 Remove webgl dependence on DEFAULT_ANSI_COLORS 2019-05-19 18:06:25 -07:00
Daniel Imms b79d73d7c0 Add foreground tests 2019-05-19 15:54:49 -07:00
Daniel Imms 4beea9b704 Add tests for webgl bg colors 2019-05-19 15:44:13 -07:00
Daniel Imms 250683364f Use more API in WebglRenderer 2019-05-19 02:23:07 -07:00
Daniel Imms 510985fb4e Add a basic test 2019-05-19 01:49:42 -07:00
Daniel Imms 20dfaae500 Fix runtime error 2019-05-19 00:59:21 -07:00
Daniel Imms 061854b535 Remove more dependencies on rest of project 2019-05-19 00:55:02 -07:00
Daniel Imms 134c2ff859 Move parts of webgl renderer to public API 2019-05-19 00:21:07 -07:00
Daniel Imms 29d3b8281b Copy over typed array utils to webgl 2019-05-18 23:38:49 -07:00
Daniel Imms 6922156d07 Move atlas parts into webgl/ 2019-05-18 23:30:10 -07:00
Daniel Imms f42e53f15a Update for recent changes 2019-05-18 21:56:42 -07:00
Daniel Imms e0ff44441e Merge remote-tracking branch 'origin/master' into webgl2 2019-05-18 21:24:39 -07:00
Daniel Imms cf867602d1 Use IColorSet instead of IColorManager 2019-05-18 18:24:54 -07:00
Daniel Imms 3df91268c6 Merge remote-tracking branch 'origin/master' into webgl2 2019-05-18 18:24:30 -07:00
Daniel Imms 2a155d5fb0 Merge branch 'master' into webgl2 2019-05-18 14:38:42 -07:00
Daniel Imms 1e564fdf33 Merge commit 'd261862' into webgl2 2019-05-18 14:27:22 -07:00
Daniel Imms 30567ec3cf Fix event emitter in webgl renderer 2019-05-18 14:24:25 -07:00
Daniel Imms 707d8baddb Merge commit 'fa70aa0983947e4444bcc9c1eeaaa516c1f88fe8' into webgl2 2019-05-18 14:23:40 -07:00
Daniel Imms 72719a6d69 Fix WebGL rendering after UTF-32 by fixing get chardata attr 2019-05-18 14:22:47 -07:00
Daniel Imms 440e097fe3 Merge commit '25745777c653acb53a7bf3864603c1ad7aaaa637' into webgl2 2019-05-18 14:03:29 -07:00
Daniel Imms 542c109b99 Merge branch 'master' into webgl2 2019-04-02 06:39:25 -07:00
Daniel Imms 4527e92333 Merge pull request #6 from juancampa/selection-simple-2
Only apply the selection hack for the WebGL renderer
2019-03-08 12:18:45 -08:00
Daniel Imms 5ebb4e82d1 Clarify comment 2019-03-08 12:18:27 -08:00
Daniel Imms 1ce75cd4e9 Encapsulate hacks inside WebglRenderer 2019-03-08 12:16:27 -08:00
Daniel Imms b0299acd9f Merge remote-tracking branch 'origin/webgl2' into pr/juancampa/6-1 2019-03-08 12:09:30 -08:00
Daniel Imms 9abe46fe34 Merge branch 'master' into webgl2 2019-03-08 11:53:48 -08:00
Daniel Imms 1ecc9dc832 Merge branch 'master' into webgl2 2019-03-04 10:38:20 -08:00
Daniel Imms f5d901944d Merge branch 'master' into webgl2 2019-01-31 14:10:35 -08:00
Daniel Imms 15ef5bee8f Merge branch 'master' into webgl2 2019-01-25 21:48:20 -08:00
Daniel Imms 1927bc899a Fix lint 2019-01-25 20:51:19 -08:00
Juan Campa 3077ae5311 Only apply the selection hack for the WebGL renderer 2019-01-21 18:56:54 -05:00
Daniel Imms 62ac714d38 Merge pull request #3 from juancampa/selection-simple-webgl2
Use bg luminance to determine background color
2019-01-19 09:35:25 -08:00
Juan Campa e387b20b56 Adding missing parameter to GlyphRenderer 2019-01-18 15:25:58 -05:00
Daniel Imms c43568283c Merge remote-tracking branch 'origin/master' into webgl2 2019-01-16 11:17:07 -08:00
Daniel Imms 4181321377 Add super.dispose to WebglRenderer.dispose 2019-01-16 11:15:45 -08:00
Daniel Imms a92c0c1414 Merge pull request #4 from juancampa/no-aa-depth
Disable antialiasing and depth buffer for WebGL2 contexts
2019-01-15 15:56:45 -08:00
Juan Campa 1d7a39bcfd Disable antialiasing and depth buffer for WebGL2 contexts 2019-01-15 16:36:38 -05:00
Juan Campa 98706aa7d2 Use bg luminance to determine background color 2019-01-08 16:44:57 -05:00
Daniel Imms 66735ba671 Merge branch 'master' into webgl2 2019-01-02 15:09:52 -08:00
Daniel Imms b0e51b9ec9 Fix build error 2019-01-02 15:09:38 -08:00
Daniel Imms 408388130d Merge branch 'master' into webgl2 2018-12-31 19:46:36 -08:00
Daniel Imms 1227497951 Merge branch 'master' into webgl2 2018-12-27 17:10:43 -08:00
Daniel Imms 01b37b2fef Document how GlyphRenderer.render works 2018-12-27 17:10:18 -08:00
Daniel Imms 9cf3d14d8a Clean up loop that sets cell coordinates 2018-12-27 17:01:13 -08:00
Daniel Imms 5f9144dfd7 Fix null/whitespace early exit 2018-12-27 16:56:20 -08:00
Daniel Imms 0ed0bfa5ab Merge branch 'master' into webgl2 2018-12-27 14:17:34 -08:00
Daniel Imms 26db71d296 Merge branch 'master' into webgl2 2018-12-26 11:09:24 -08:00
Daniel Imms 1b1b641670 Merge branch 'master' into webgl2 2018-12-20 16:40:03 -08:00
Daniel Imms bb9ccf40b6 Reduce diff with master 2018-12-09 09:28:04 -08:00
Daniel Imms 3d8b304af4 Reduce precision of floats in fragment shader
~0.43ms/frame -> ~0.37ms/frame
2018-12-09 08:31:49 -08:00
Daniel Imms c16d70ec06 Merge remote-tracking branch 'origin/master' into webgl2 2018-12-09 08:26:33 -08:00
Daniel Imms 6bc9b9b14d Improve constructor use in sliceFallback 2018-11-29 10:26:04 -08:00
Daniel Imms fe7941034e Merge branch 'master' into webgl2 2018-11-27 09:19:17 -08:00
Daniel Imms b8b111f4a6 Only pass a subset of the attributes buffer to GPU 2018-11-25 10:18:14 -08:00
Daniel Imms 60e3ddbfd0 Update color codes after merging the move to constants 2018-11-24 05:52:23 -08:00
Daniel Imms 186b2be4b9 Fix imports 2018-11-24 05:48:05 -08:00
Daniel Imms 569abde8c7 Merge remote-tracking branch 'ups/master' into webgl2 2018-11-24 05:46:58 -08:00
Daniel Imms 53dc2af2b7 Use polyfill for TypedArray.slice 2018-11-23 08:00:27 -08:00
Daniel Imms 128b1b0a48 Use polyfill for TypedArray.fill 2018-11-23 07:14:56 -08:00
Daniel Imms 1567b41d6e Merge branch 'master' into webgl2 2018-11-23 06:59:43 -08:00
Daniel Imms 43721160d7 Merge branch 'master' into webgl2 2018-11-22 12:46:30 -08:00
Daniel Imms 928abdb0c3 Merge branch 'master' into webgl2 2018-11-22 11:10:08 -08:00
Daniel Imms 42eda149c7 Set theme in ctor 2018-11-22 10:57:45 -08:00
Daniel Imms 5c1e5a1787 Merge branch 'master' into webgl2 2018-11-20 09:14:31 -08:00
Daniel Imms e6d339a289 Fix wide char caching in webgl renderer 2018-11-19 16:54:53 -08:00
Daniel Imms c97feab05c Initial webgl renderer implementation 2018-11-16 14:34:12 -08:00
353 changed files with 33670 additions and 19214 deletions
+9 -2
View File
@@ -8,12 +8,19 @@ RUN apt-get update \
# Verify git and process tools are installed
RUN apt-get install -y git procps
# Install yarn
# Install yarn, puppeteer deps
RUN apt-get install -y curl apt-transport-https lsb-release \
&& curl -sS https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/pubkey.gpg | apt-key add - 2>/dev/null \
&& echo "deb https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
&& apt-get update \
&& apt-get -y install --no-install-recommends yarn
&& apt-get -y install --no-install-recommends \
yarn fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst ttf-freefont \
# https://github.com/Googlechrome/puppeteer/issues/290#issuecomment-322921352
gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \
libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 \
libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 \
libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 \
ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget
# Clean up
RUN apt-get autoremove -y \
+2 -2
View File
@@ -3,7 +3,7 @@
"dockerFile": "Dockerfile",
"appPort": 3000,
"extensions": [
"editorconfig.editorconfig",
"ms-vscode.vscode-typescript-tslint-plugin"
"dbaeumer.vscode-eslint",
"editorconfig.editorconfig"
]
}
+150
View File
@@ -0,0 +1,150 @@
{
"env": {
"browser": true,
"es6": true,
"node": true
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": [
"src/browser/tsconfig.json",
"src/common/tsconfig.json",
"src/tsconfig.json",
"test/api/tsconfig.json",
"test/benchmark/tsconfig.json",
"addons/xterm-addon-attach/src/tsconfig.json",
"addons/xterm-addon-fit/src/tsconfig.json",
"addons/xterm-addon-search/src/tsconfig.json",
"addons/xterm-addon-unicode11/src/tsconfig.json",
"addons/xterm-addon-web-links/src/tsconfig.json",
"addons/xterm-addon-webgl/src/tsconfig.json",
"addons/xterm-addon-serialize/src/tsconfig.json",
"addons/xterm-addon-serialize/benchmark/tsconfig.json"
],
"sourceType": "module"
},
"ignorePatterns": [
"**/typings/*.d.ts"
],
"plugins": [
"@typescript-eslint"
],
"rules": {
"@typescript-eslint/array-type": [
"error",
{
"default": "array-simple",
"readonly": "generic"
}
],
"@typescript-eslint/class-name-casing": "error",
"@typescript-eslint/consistent-type-definitions": "error",
"@typescript-eslint/explicit-function-return-type": [
"error",
{
"allowExpressions": true
}
],
"@typescript-eslint/indent": [
"error",
2
],
"@typescript-eslint/interface-name-prefix": [
"error",
"always"
],
"@typescript-eslint/member-delimiter-style": [
"error",
{
"multiline": {
"delimiter": "semi",
"requireLast": true
},
"singleline": {
"delimiter": "comma",
"requireLast": false
}
}
],
"@typescript-eslint/naming-convention": [
"error",
{ "selector": "default", "format": ["camelCase"] },
// variableLike
{ "selector": "variable", "format": ["camelCase", "UPPER_CASE"] },
{ "selector": "variable", "filter": "^I.+Service$", "format": ["PascalCase"], "prefix": ["I"] },
// memberLike
{ "selector": "memberLike", "modifiers": ["private"], "format": ["camelCase"], "leadingUnderscore": "require" },
{ "selector": "memberLike", "modifiers": ["protected"], "format": ["camelCase"], "leadingUnderscore": "require" },
{ "selector": "enumMember", "format": ["UPPER_CASE"] },
// memberLike - Allow enum-like objects to use UPPER_CASE
{ "selector": "property", "modifiers": ["public"], "format": ["camelCase", "UPPER_CASE"] },
{ "selector": "method", "modifiers": ["public"], "format": ["camelCase", "UPPER_CASE"] },
// typeLike
{ "selector": "typeLike", "format": ["PascalCase"] },
{ "selector": "interface", "format": ["PascalCase"], "prefix": ["I"] }
],
"@typescript-eslint/prefer-namespace-keyword": "error",
"@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/quotes": [
"error",
"single",
{ "allowTemplateLiterals": true }
],
"@typescript-eslint/semi": [
"error",
"always"
],
"comma-dangle": [
"error",
{
"objects": "never",
"arrays": "never",
"functions": "never"
}
],
"curly": [
"error",
"multi-line"
],
"eol-last": "error",
"eqeqeq": [
"error",
"always"
],
"keyword-spacing": "error",
"new-parens": "error",
"no-duplicate-imports": "error",
"no-else-return": [
"error",
{
"allowElseIf": false
}
],
"no-eval": "error",
"no-irregular-whitespace": "error",
"no-restricted-imports": [
"error",
{
"patterns": [
".*\\/out\\/.*"
]
}
],
"no-trailing-spaces": "error",
"no-unsafe-finally": "error",
"no-var": "error",
"one-var": [
"error",
"never"
],
"prefer-const": "error",
"spaced-comment": [
"error",
"always",
{
"markers": ["/"],
"exceptions": ["-"]
}
]
}
}
+5
View File
@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Question
url: https://stackoverflow.com/questions/tagged/xtermjs
about: Please ask and answer questions here.
-8
View File
@@ -1,8 +0,0 @@
---
name: Question
about: The issue tracker is not for questions. Please ask questions on https://stackoverflow.com/questions/tagged/xtermjs
---
🛑 The issue tracker is not for questions 🛑
If you have a question, please ask it on https://stackoverflow.com/questions/tagged/xtermjs.
+7 -5
View File
@@ -2,6 +2,9 @@ node_modules/
*.swp
.lock-wscript
lib/
out/
out-test/
.nyc_output/
Makefile.gyp
*.Makefile
*.target.gyp.mk
@@ -13,13 +16,12 @@ npm-debug.log
.env
build/
.DS_Store
fixtures/typings-test/*.js
package-lock.json
# Directories needed for code coverage
coverage/
.nyc_output/
# Keep bundled code out of Git
dist/
demo/dist/
# dont commit benchmark folders
.benchmark/
timeline/
+8 -1
View File
@@ -6,6 +6,9 @@
!*.js
!*.json
# Whitelist - css/
!css/**/*.css
# Whitelist - dist/
!dist/**/*.js
!dist/**/*.js.map
@@ -33,11 +36,13 @@
!typings/*.d.ts
# Blacklist - (normal behavior) these will override any whitelist
*.d.ts.map
*.test.ts
*.test.d.ts
*.test.js
*.test.js.map
lib/test/
webpack.config.js
docs/
/.idea/
@@ -45,5 +50,7 @@ docs/
bin/
build/
fixtures/
coverage/
demo/
.devcontainer/
out/
addons/
+6 -3
View File
@@ -13,10 +13,13 @@
"runtimeArgs": [
"--colors",
"--recursive",
"${workspaceRoot}/lib/**/*.test.js"
"${workspaceRoot}/out/**/*.test.js"
],
"env": {
"NODE_PATH": "${workspaceRoot}/out"
},
"sourceMaps": true,
"outFiles": [ "${workspaceRoot}/lib/**/*.js" ],
"outFiles": [ "${workspaceRoot}/out/**/*.js" ],
"internalConsoleOptions": "openOnSessionStart"
},
{
@@ -31,7 +34,7 @@
"runtimeArgs": [
"--colors",
"--recursive",
"${workspaceRoot}/lib/**/*.api.js"
"${workspaceRoot}/out/**/*.api.js"
],
"sourceMaps": true,
"outFiles": [ "${workspaceRoot}/lib/**/*.js" ],
+2 -1
View File
@@ -1,3 +1,4 @@
{
"typescript.preferences.quoteStyle": "single"
"typescript.preferences.importModuleSpecifier": "non-relative",
"typescript.preferences.quoteStyle": "single"
}
+4
View File
@@ -52,3 +52,7 @@ By contributing code to xterm.js you:
holder has explicitly granted the right to use it like this,
through a compatible open source license or through a direct
agreement with you.)
### Test coverage
One area that always needs attention is improving out unit test coverage, you can view the code coverage report on [Azure Pipelines](https://dev.azure.com/xtermjs/xterm.js/_build/latest?definitionId=3) by clicking the Code Coverage tab.
+34 -31
View File
@@ -1,17 +1,16 @@
# [![xterm.js logo](logo-full.png)](https://xtermjs.org)
[![Build Status](https://dev.azure.com/xtermjs/xterm.js/_apis/build/status/xtermjs.xterm.js)](https://dev.azure.com/xtermjs/xterm.js/_build/latest?definitionId=3)
[![Coverage Status](https://coveralls.io/repos/github/xtermjs/xterm.js/badge.svg?branch=master)](https://coveralls.io/github/xtermjs/xterm.js?branch=master)
Xterm.js is a front-end component written in TypeScript that lets applications bring fully-featured terminals to their users in the browser. It's used by popular projects such as VS Code, Hyper and Theia.
## Features
- **Terminal apps just work**: Xterm.js works with most terminal apps such as `bash`, `vim` and `tmux`, this includes support for curses-based apps and mouse event support.
- **Perfomant**: Xterm.js is *really* fast, it even includes a GPU-accelerated renderer.
- **Performant**: Xterm.js is *really* fast, it even includes a GPU-accelerated renderer.
- **Rich unicode support**: Supports CJK, emojis and IMEs.
- **Self-contained**: Requires zero dependencies to work.
- **Accessible**: Screen reader support can be turned on using the `screenReaderMode` option.
- **Accessible**: Screen reader and minimum contrast ratio support can be turned on
- **And much more**: Links, theming, addons, well documented API, etc.
## What xterm.js is not
@@ -33,8 +32,8 @@ To start using xterm.js on your browser, add the `xterm.js` and `xterm.css` to t
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="node_modules/xterm/dist/xterm.css" />
<script src="node_modules/xterm/dist/xterm.js"></script>
<link rel="stylesheet" href="node_modules/xterm/css/xterm.css" />
<script src="node_modules/xterm/lib/xterm.js"></script>
</head>
<body>
<div id="terminal"></div>
@@ -57,43 +56,38 @@ import { Terminal } from 'xterm';
### Addons
Addons are JavaScript modules that extend the `Terminal` prototype with new methods and attributes to provide additional functionality. There are a handful available in the main repository in the `src/addons` directory and you can even write your own by using the [public API](https://github.com/xtermjs/xterm.js/blob/master/typings/xterm.d.ts).
⚠️ *This section describes the new addon format introduced in v3.14.0, see [here](https://github.com/xtermjs/xterm.js/blob/3.14.2/README.md#addons) for the instructions on the old format*
To use an addon, just import the JavaScript module and pass it to `Terminal`'s `applyAddon` method:
Addons are separate modules that extend the `Terminal` by building on the [xterm.js API](https://github.com/xtermjs/xterm.js/blob/master/typings/xterm.d.ts). To use an addon you first need to install it in your project:
```javascript
import { Terminal } from 'xterm';
import * as fit from 'xterm/lib/addons/fit/fit';
Terminal.applyAddon(fit);
var xterm = new Terminal(); // Instantiate the terminal
xterm.fit(); // Use the `fit` method, provided by the `fit` addon
```bash
npm i -S xterm-addon-web-links
```
You will also need to include the addon's CSS file if it has one in the folder.
Then import the addon, instantiate it and call `Terminal.loadAddon`:
#### Importing Addons in TypeScript
There are currently no typings for addons if they are accessed via extending Terminal prototype, so you will need to upcast if using TypeScript, eg. `(xterm as any).fit()`. Alternatively, you can import the addon function and enhance the terminal on demand. This has better typing support and is friendly to treeshaking.
```typescript
```ts
import { Terminal } from 'xterm';
import { fit } from 'xterm/lib/addons/fit/fit';
const xterm = new Terminal();
import { WebLinksAddon } from 'xterm-addon-web-links';
fit(xterm); // Fit the terminal when necessary
const terminal = new Terminal();
// Load WebLinksAddon on terminal, this is all that's needed to get web links
// working in the terminal.
terminal.loadAddon(new WebLinksAddon());
```
The xterm.js team maintains the following addons but they can be built by anyone:
- [`xterm-addon-attach`](https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-attach): Attaches to a server running a process via a websocket
- [`xterm-addon-fit`](https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-fit): Fits the terminal to the containing element
- [`xterm-addon-search`](https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-search): Adds search functionality
- [`xterm-addon-web-links`](https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-web-links): Adds web link detection and interaction
## Browser Support
Since xterm.js is typically implemented as a developer tool, only modern browsers are supported officially. Here is a list of the versions we aim to support:
Since xterm.js is typically implemented as a developer tool, only modern browsers are supported officially. Specifically the latest versions of *Chrome*, *Edge*, *Firefox* and *Safari*.
- Chrome latest
- Edge latest
- Firefox latest
- Safari latest
- IE11
We also partially support *Intenet Explorer 11*, meaning xterm.js should work for the most part, but we reserve the right to not provide workarounds specifically for it unless it's absolutely necessary to get the basic input/output flow working.
Xterm.js works seamlessly in [Electron](https://electronjs.org/) apps and may even work on earlier versions of the browsers, these are the versions we strive to keep working.
@@ -116,7 +110,7 @@ Xterm.js is used in several world-class applications to provide great terminal e
- [**WebSSH2**](https://github.com/billchurch/WebSSH2): A web based SSH2 client using xterm.js, socket.io, and ssh2.
- [**Spyder Terminal**](https://github.com/spyder-ide/spyder-terminal): A full fledged system terminal embedded on Spyder IDE.
- [**Cloud Commander**](https://cloudcmd.io "Cloud Commander"): Orthodox web file manager with console and editor.
- [**Codevolve**](https://www.codevolve.com "Codevolve"): Online platform for interactive coding and web development courses. Live container-backed terminal uses xterm.js.
- [**Next Tech**](https://next.tech "Next Tech"): Online platform for interactive coding and web development courses. Live container-backed terminal uses xterm.js.
- [**RStudio**](https://www.rstudio.com/products/RStudio "RStudio"): RStudio is an integrated development environment (IDE) for R.
- [**Terminal for Atom**](https://github.com/jsmecham/atom-terminal-tab): A simple terminal for the Atom text editor.
- [**Eclipse Orion**](https://orionhub.org): A modern, open source software development environment that runs in the cloud. Code, deploy and run in the cloud.
@@ -158,6 +152,15 @@ Xterm.js is used in several world-class applications to provide great terminal e
- [**CodeInterview.io**](https://codeinterview.io): A coding interview platform in 25+ languages and many web frameworks. Uses xterm.js to provide shell access.
- [**Bastillion**](https://www.bastillion.io): Bastillion is an open-source web-based SSH console that centrally manages administrative access to systems.
- [**PHP App Server**](https://github.com/cubiclesoft/php-app-server/): Create lightweight, installable almost-native applications for desktop OSes. ExecTerminal (nicely wraps the xterm.js Terminal), TerminalManager, and RunProcessSDK are self-contained, reusable ES5+ compliant Javascript components.
- [**NgTerminal**](https://github.com/qwefgh90/ng-terminal): NgTerminal is a web terminal that leverages xterm.js on Angular 7+. You can easily add it into your application by adding `<ng-terminal></ng-terminal>` into your component.
- [**tty-share**](https://tty-share.com): Extremely simple terminal sharing over the Internet.
- [**Ten Hands**](https://github.com/saisandeepvaddi/ten-hands): One place to run your command-line tasks.
- [**WebAssembly.sh**](https://webassembly.sh): A WebAssembly WASI browser terminal
- [**Gus**](https://gus.jp): A shared coding pad where you can run Python with xterm.js
- [**Linode**](https://linode.com): Linode uses xterm.js to provide users a web console for their Linode instances.
- [**FluffOS**](https://www.fluffos.info): Active maintained LPMUD driver with websocket support.
- [**x-terminal**](https://atom.io/packages/x-terminal): Atom plugin for providing terminals inside your Atom workspace.
- [**CoCalc**](https://cocalc.com/): Lots of free software pre-installed, to chat, collaborate, develop, program, publish, research, share, teach, in C++, HTML, Julia, Jupyter, LaTeX, Markdown, Python, R, SageMath, Scala, ...
[And much more...](https://github.com/xtermjs/xterm.js/network/dependents)
+2
View File
@@ -0,0 +1,2 @@
lib
node_modules
+5
View File
@@ -0,0 +1,5 @@
**/*.api.js
**/*.api.ts
tsconfig.json
.yarnrc
webpack.config.js
+19
View File
@@ -0,0 +1,19 @@
Copyright (c) 2017, The xterm.js authors (https://github.com/xtermjs/xterm.js)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+22
View File
@@ -0,0 +1,22 @@
## xterm-addon-attach
An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables attaching to a web socket. This addon requires xterm.js v4+.
### Install
```bash
npm install --save xterm-addon-attach
```
### Usage
```ts
import { Terminal } from 'xterm';
import { AttachAddon } from 'xterm-addon-attach';
const terminal = new Terminal();
const attachAddon = new AttachAddon(webSocket);
terminal.loadAddon(attachAddon);
```
See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/xterm-addon-attach/typings/xterm-addon-attach.d.ts) for more advanced usage.
+21
View File
@@ -0,0 +1,21 @@
{
"name": "xterm-addon-attach",
"version": "0.5.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
},
"main": "lib/xterm-addon-attach.js",
"types": "typings/xterm-addon-attach.d.ts",
"repository": "https://github.com/xtermjs/xterm.js",
"license": "MIT",
"scripts": {
"build": "../../node_modules/.bin/tsc -p src",
"prepackage": "npm run build",
"package": "../../node_modules/.bin/webpack",
"prepublishOnly": "npm run package"
},
"peerDependencies": {
"xterm": "^4.0.0"
}
}
@@ -0,0 +1,53 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import WebSocket = require('ws');
import { openTerminal, pollFor, getBrowserType } from '../../../out-test/api/TestUtils';
import { Browser, Page } from 'playwright-core';
const APP = 'http://127.0.0.1:3000/test';
let browser: Browser;
let page: Page;
const width = 800;
const height = 600;
describe('AttachAddon', () => {
before(async function(): Promise<any> {
const browserType = getBrowserType();
browser = await browserType.launch({ dumpio: true,
headless: process.argv.indexOf('--headless') !== -1
});
page = await (await browser.newContext()).newPage();
await page.setViewportSize({ width, height });
});
after(async () => {
await browser.close();
});
beforeEach(async () => await page.goto(APP));
it('string', async function(): Promise<any> {
await openTerminal(page, { rendererType: 'dom' });
const port = 8080;
const server = new WebSocket.Server({ port });
server.on('connection', socket => socket.send('foo'));
await page.evaluate(`window.term.loadAddon(new window.AttachAddon(new WebSocket('ws://localhost:${port}')))`);
await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foo');
server.close();
});
it('utf8', async function(): Promise<any> {
await openTerminal(page, { rendererType: 'dom' });
const port = 8080;
const server = new WebSocket.Server({ port });
const data = new Uint8Array([102, 111, 111]);
server.on('connection', socket => socket.send(data));
await page.evaluate(`window.term.loadAddon(new window.AttachAddon(new WebSocket('ws://localhost:${port}')))`);
await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foo');
server.close();
});
});
@@ -0,0 +1,79 @@
/**
* Copyright (c) 2014, 2019 The xterm.js authors. All rights reserved.
* @license MIT
*
* Implements the attach method, that attaches the terminal to a WebSocket stream.
*/
import { Terminal, IDisposable, ITerminalAddon } from 'xterm';
interface IAttachOptions {
bidirectional?: boolean;
}
export class AttachAddon implements ITerminalAddon {
private _socket: WebSocket;
private _bidirectional: boolean;
private _disposables: IDisposable[] = [];
constructor(socket: WebSocket, options?: IAttachOptions) {
this._socket = socket;
// always set binary type to arraybuffer, we do not handle blobs
this._socket.binaryType = 'arraybuffer';
this._bidirectional = (options && options.bidirectional === false) ? false : true;
}
public activate(terminal: Terminal): void {
this._disposables.push(
addSocketListener(this._socket, 'message', ev => {
const data: ArrayBuffer | string = ev.data;
terminal.write(typeof data === 'string' ? data : new Uint8Array(data));
})
);
if (this._bidirectional) {
this._disposables.push(terminal.onData(data => this._sendData(data)));
this._disposables.push(terminal.onBinary(data => this._sendBinary(data)));
}
this._disposables.push(addSocketListener(this._socket, 'close', () => this.dispose()));
this._disposables.push(addSocketListener(this._socket, 'error', () => this.dispose()));
}
public dispose(): void {
this._disposables.forEach(d => d.dispose());
}
private _sendData(data: string): void {
// TODO: do something better than just swallowing
// the data if the socket is not in a working condition
if (this._socket.readyState !== 1) {
return;
}
this._socket.send(data);
}
private _sendBinary(data: string): void {
if (this._socket.readyState !== 1) {
return;
}
const buffer = new Uint8Array(data.length);
for (let i = 0; i < data.length; ++i) {
buffer[i] = data.charCodeAt(i) & 255;
}
this._socket.send(buffer);
}
}
function addSocketListener<K extends keyof WebSocketEventMap>(socket: WebSocket, type: K, handler: (this: WebSocket, ev: WebSocketEventMap[K]) => any): IDisposable {
socket.addEventListener(type, handler);
return {
dispose: () => {
if (!handler) {
// Already disposed
return;
}
socket.removeEventListener(type, handler);
}
};
}
@@ -4,19 +4,20 @@
"target": "es5",
"lib": [
"dom",
"es5"
"es2015"
],
"rootDir": ".",
"outDir": "../../../lib/addons/fullscreen/",
"outDir": "../out",
"sourceMap": true,
"removeComments": true,
"declaration": true,
"strict": true,
"types": [
"../../node_modules/@types/mocha"
"../../../node_modules/@types/mocha",
"../../../out-test/api/TestUtils"
]
},
"include": [
"**/*.ts",
"./**/*",
"../../../typings/xterm.d.ts"
]
}
@@ -0,0 +1,21 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { Terminal, ILinkMatcherOptions, ITerminalAddon } from 'xterm';
declare module 'xterm-addon-attach' {
export interface IAttachOptions {
/**
* Whether input should be written to the backend. Defaults to `true`.
*/
bidirectional?: boolean;
}
export class AttachAddon implements ITerminalAddon {
constructor(socket: WebSocket, options?: IAttachOptions);
public activate(terminal: Terminal): void;
public dispose(): void;
}
}
@@ -0,0 +1,31 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
const path = require('path');
const addonName = 'AttachAddon';
const mainFile = 'xterm-addon-attach.js';
module.exports = {
entry: `./out/${addonName}.js`,
devtool: 'source-map',
module: {
rules: [
{
test: /\.js$/,
use: ["source-map-loader"],
enforce: "pre",
exclude: /node_modules/
}
]
},
output: {
filename: mainFile,
path: path.resolve('./lib'),
library: addonName,
libraryTarget: 'umd'
},
mode: 'production'
};
+2
View File
@@ -0,0 +1,2 @@
lib
node_modules
+5
View File
@@ -0,0 +1,5 @@
**/*.api.js
**/*.api.ts
tsconfig.json
.yarnrc
webpack.config.js
+19
View File
@@ -0,0 +1,19 @@
Copyright (c) 2019, The xterm.js authors (https://github.com/xtermjs/xterm.js)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+24
View File
@@ -0,0 +1,24 @@
## xterm-addon-fit
An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables fitting the terminal's dimensions to a containing element. This addon requires xterm.js v4+.
### Install
```bash
npm install --save xterm-addon-fit
```
### Usage
```ts
import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
const terminal = new Terminal();
const fitAddon = new FitAddon();
terminal.loadAddon(fitAddon);
terminal.open(containerElement);
fitAddon.fit();
```
See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/xterm-addon-fit/typings/xterm-addon-fit.d.ts) for more advanced usage.
+21
View File
@@ -0,0 +1,21 @@
{
"name": "xterm-addon-fit",
"version": "0.3.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
},
"main": "lib/xterm-addon-fit.js",
"types": "typings/xterm-addon-fit.d.ts",
"repository": "https://github.com/xtermjs/xterm.js",
"license": "MIT",
"scripts": {
"build": "../../node_modules/.bin/tsc -p src",
"prepackage": "npm run build",
"package": "../../node_modules/.bin/webpack",
"prepublishOnly": "npm run package"
},
"peerDependencies": {
"xterm": "^4.0.0"
}
}
+113
View File
@@ -0,0 +1,113 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { assert } from 'chai';
import { openTerminal, getBrowserType } from '../../../out-test/api/TestUtils';
import { Browser, Page } from 'playwright-core';
const APP = 'http://127.0.0.1:3000/test';
let browser: Browser;
let page: Page;
const width = 1024;
const height = 768;
describe('FitAddon', () => {
before(async function(): Promise<any> {
const browserType = getBrowserType();
browser = await browserType.launch({ dumpio: true,
headless: process.argv.indexOf('--headless') !== -1
});
page = await (await browser.newContext()).newPage();
await page.setViewportSize({ width, height });
await page.goto(APP);
await openTerminal(page);
});
after(async () => {
await browser.close();
});
it('no terminal', async function(): Promise<any> {
await page.evaluate(`window.fit = new FitAddon();`);
assert.equal(await page.evaluate(`window.fit.proposeDimensions()`), undefined);
});
describe('proposeDimensions', () => {
afterEach(async () => {
return unloadFit();
});
it('default', async function(): Promise<any> {
await loadFit();
const dimensions: {cols: number, rows: number} = await page.evaluate(`window.fit.proposeDimensions()`);
assert.equal(dimensions.cols, 87);
assert.isAbove(dimensions.rows, 24);
assert.isBelow(dimensions.rows, 29);
});
it('width', async function(): Promise<any> {
await loadFit(1008);
const dimensions: {cols: number, rows: number} = await page.evaluate(`window.fit.proposeDimensions()`);
assert.equal(dimensions.cols, 110);
assert.isAbove(dimensions.rows, 24);
assert.isBelow(dimensions.rows, 29);
});
it('small', async function(): Promise<any> {
await loadFit(1, 1);
assert.deepEqual(await page.evaluate(`window.fit.proposeDimensions()`), {
cols: 2,
rows: 1
});
});
});
describe('fit', () => {
afterEach(async () => {
return unloadFit();
});
it('default', async function(): Promise<any> {
await loadFit();
await page.evaluate(`window.fit.fit()`);
const cols: number = await page.evaluate(`window.term.cols`);
const rows: number = await page.evaluate(`window.term.rows`);
assert.equal(cols, 87);
assert.isAbove(rows, 24);
assert.isBelow(rows, 29);
});
it('width', async function(): Promise<any> {
await loadFit(1008);
await page.evaluate(`window.fit.fit()`);
const cols: number = await page.evaluate(`window.term.cols`);
const rows: number = await page.evaluate(`window.term.rows`);
assert.equal(cols, 110);
assert.isAbove(rows, 24);
assert.isBelow(rows, 29);
});
it('small', async function(): Promise<any> {
await loadFit(1, 1);
await page.evaluate(`window.fit.fit()`);
assert.equal(await page.evaluate(`window.term.cols`), 2);
assert.equal(await page.evaluate(`window.term.rows`), 1);
});
});
});
async function loadFit(width: number = 800, height: number = 450): Promise<void> {
await page.evaluate(`
window.fit = new FitAddon();
window.term.loadAddon(window.fit);
document.querySelector('#terminal-container').style.width='${width}px';
document.querySelector('#terminal-container').style.height='${height}px';
`);
}
async function unloadFit(): Promise<void> {
await page.evaluate(`window.fit.dispose();`);
}
+82
View File
@@ -0,0 +1,82 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { Terminal, ITerminalAddon } from 'xterm';
interface ITerminalDimensions {
/**
* The number of rows in the terminal.
*/
rows: number;
/**
* The number of columns in the terminal.
*/
cols: number;
}
const MINIMUM_COLS = 2;
const MINIMUM_ROWS = 1;
export class FitAddon implements ITerminalAddon {
private _terminal: Terminal | undefined;
constructor() {}
public activate(terminal: Terminal): void {
this._terminal = terminal;
}
public dispose(): void {}
public fit(): void {
const dims = this.proposeDimensions();
if (!dims || !this._terminal) {
return;
}
// TODO: Remove reliance on private API
const core = (this._terminal as any)._core;
// Force a full render
if (this._terminal.rows !== dims.rows || this._terminal.cols !== dims.cols) {
core._renderService.clear();
this._terminal.resize(dims.cols, dims.rows);
}
}
public proposeDimensions(): ITerminalDimensions | undefined {
if (!this._terminal) {
return undefined;
}
if (!this._terminal.element || !this._terminal.element.parentElement) {
return undefined;
}
// TODO: Remove reliance on private API
const core = (this._terminal as any)._core;
const parentElementStyle = window.getComputedStyle(this._terminal.element.parentElement);
const parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height'));
const parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')));
const elementStyle = window.getComputedStyle(this._terminal.element);
const elementPadding = {
top: parseInt(elementStyle.getPropertyValue('padding-top')),
bottom: parseInt(elementStyle.getPropertyValue('padding-bottom')),
right: parseInt(elementStyle.getPropertyValue('padding-right')),
left: parseInt(elementStyle.getPropertyValue('padding-left'))
};
const elementPaddingVer = elementPadding.top + elementPadding.bottom;
const elementPaddingHor = elementPadding.right + elementPadding.left;
const availableHeight = parentElementHeight - elementPaddingVer;
const availableWidth = parentElementWidth - elementPaddingHor - core.viewport.scrollBarWidth;
const geometry = {
cols: Math.max(MINIMUM_COLS, Math.floor(availableWidth / core._renderService.dimensions.actualCellWidth)),
rows: Math.max(MINIMUM_ROWS, Math.floor(availableHeight / core._renderService.dimensions.actualCellHeight))
};
return geometry;
}
}
@@ -4,19 +4,20 @@
"target": "es5",
"lib": [
"dom",
"es5",
"es2015"
],
"rootDir": ".",
"outDir": "../../../lib/addons/webLinks/",
"outDir": "../out",
"sourceMap": true,
"removeComments": true,
"declaration": true,
"strict": true,
"types": [
"../../node_modules/@types/mocha"
"../../../node_modules/@types/mocha",
"../../../out-test/api/TestUtils"
]
},
"include": [
"**/*.ts",
"./**/*",
"../../../typings/xterm.d.ts"
]
}
+55
View File
@@ -0,0 +1,55 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { Terminal, ITerminalAddon } from 'xterm';
declare module 'xterm-addon-fit' {
/**
* An xterm.js addon that enables resizing the terminal to the dimensions of
* its containing element.
*/
export class FitAddon implements ITerminalAddon {
/**
* Creates a new fit addon.
*/
constructor();
/**
* Activates the addon
* @param terminal The terminal the addon is being loaded in.
*/
public activate(terminal: Terminal): void;
/**
* Disposes the addon.
*/
public dispose(): void;
/**
* Resizes the terminal to the dimensions of its containing element.
*/
public fit(): void;
/**
* Gets the proposed dimensions that will be used for a fit.
*/
public proposeDimensions(): ITerminalDimensions;
}
/**
* Reprepresents the dimensions of a terminal.
*/
export interface ITerminalDimensions {
/**
* The number of rows in the terminal.
*/
rows: number;
/**
* The number of columns in the terminal.
*/
cols: number;
}
}
+31
View File
@@ -0,0 +1,31 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
const path = require('path');
const addonName = 'FitAddon';
const mainFile = 'xterm-addon-fit.js';
module.exports = {
entry: `./out/${addonName}.js`,
devtool: 'source-map',
module: {
rules: [
{
test: /\.js$/,
use: ["source-map-loader"],
enforce: "pre",
exclude: /node_modules/
}
]
},
output: {
filename: mainFile,
path: path.resolve('./lib'),
library: addonName,
libraryTarget: 'umd'
},
mode: 'production'
};
+2
View File
@@ -0,0 +1,2 @@
lib
node_modules
+5
View File
@@ -0,0 +1,5 @@
**/*.api.js
**/*.api.ts
tsconfig.json
.yarnrc
webpack.config.js
+19
View File
@@ -0,0 +1,19 @@
Copyright (c) 2017, The xterm.js authors (https://github.com/xtermjs/xterm.js)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+23
View File
@@ -0,0 +1,23 @@
## xterm-addon-search
An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables searching the buffer. This addon requires xterm.js v4+.
### Install
```bash
npm install --save xterm-addon-search
```
### Usage
```ts
import { Terminal } from 'xterm';
import { SearchAddon } from 'xterm-addon-search';
const terminal = new Terminal();
const searchAddon = new SearchAddon();
terminal.loadAddon(searchAddon);
searchAddon.findNext('foo');
```
See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/xterm-addon-search/typings/xterm-addon-search.d.ts) for more advanced usage.
@@ -0,0 +1,70 @@
/usr/bin/cmake -E cmake_progress_report /home/yan/ssd/searchtrunk/tmp/release/CMakeFiles
make[3]: Entering directory `/home/yan/ssd/searchtrunk/tmp/release'
make[3]: Nothing to be done for `libsrc/wrap_curl/CMakeFiles/wrap_curl.dir/build'.
make[3]: Leaving directory `/home/yan/ssd/searchtrunk/tmp/release'
[ 0%] /usr/bin/cmake -E cmake_progress_report /home/yan/ssd/searchtrunk/tmp/release/CMakeFiles
[ 0%] [ 0%] /usr/bin/cmake -E cmake_progress_report /home/yan/ssd/searchtrunk/tmp/release/CMakeFiles
Built target config_utils
[ 0%] make[3]: Entering directory `/home/yan/ssd/searchtrunk/tmp/release'
/usr/bin/cmake -E cmake_progress_report /home/yan/ssd/searchtrunk/tmp/release/CMakeFiles
Built target omega
make[3]: Entering directory `/home/yan/ssd/searchtrunk/tmp/release'
cd /home/yan/ssd/searchtrunk/tmp/release && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/yan/ssd/searchtrunk /home/yan/ssd/searchtrunk/projects/protogen/cpp /home/yan/ssd/searchtrunk/tmp/release /home/yan/ssd/searchtrunk/tmp/release/projects/protogen/cpp /home/yan/ssd/searchtrunk/tmp/release/projects/protogen/cpp/CMakeFiles/protogen.dir/DependInfo.cmake --color=
/usr/bin/cmake -E cmake_progress_report /home/yan/ssd/searchtrunk/tmp/release/CMakeFiles
Built target morpheus
make[3]: Leaving directory `/home/yan/ssd/searchtrunk/tmp/release'
make -f libsrc/base/CMakeFiles/base.dir/build.make libsrc/base/CMakeFiles/base.dir/build
make[3]: Entering directory `/home/yan/ssd/searchtrunk/tmp/release'
make[3]: Nothing to be done for `libsrc/coroutine/CMakeFiles/coroutine.dir/build'.
Built target wrap_curl
make[3]: Leaving directory `/home/yan/ssd/searchtrunk/tmp/release'
/usr/bin/cmake -E cmake_progress_report /home/yan/ssd/searchtrunk/tmp/release/CMakeFiles
/usr/bin/cmake -E cmake_progress_report /home/yan/ssd/searchtrunk/tmp/release/CMakeFiles
[ 0%] [ 0%] [ 0%] [ 0%] Building CXX object libsrc/image_crop/CMakeFiles/image_crop.dir/src/crop_context.cpp.o
cd /home/yan/ssd/searchtrunk/tmp/release/libsrc/image_crop && /opt/rh/devtoolset-7/root/usr/bin/c++ -DGOGO_USE_LIBEVENT2=1 -DGOGO_USE_OPENSSL_SNI=1 -DHAVE_BOOST -DHAVE_GLIBC -DHAVE_MALLOC_TRIM -DHAVE_PREAD -DHAVE_READAHEAD -D_FILE_OFFSET_BITS=64 -D_STAT_LEMM -pipe -Wall -Wextra -Werror=multichar -Wno-deprecated -Wno-unused-parameter -pthread -fPIC -Woverloaded-virtual -Wnon-virtual-dtor -Werror -std=gnu++11 -Wno-unknown-pragmas -DBOOST_FILESYSTEM_VERSION=3 -DBOOST_NO_CXX11_HDR_CODECVT -DMAGICKCORE_QUANTUM_DEPTH=8 -DMAGICKCORE_HDRI_ENABLE=0 -Wno-unused-local-typedefs -D_GLIBCXX_USE_CXX11_ABI=0 -std=gnu++14 -DCXXHASH128_EXIST -static-libstdc++ -Wno-implicit-fallthrough -Wno-stringop-overflow -O3 -DNDEBUG -DBOOST_UBLAS_NDEBUG -g0 -march=core2 -mssse3 -msse4.1 -I/home/yan/ssd/searchtrunk/tmp/release/__inc -I/home/yan/ssd/searchtrunk/libsrc/image_crop/src -I/home/yan/ssd/searchtrunk/include -isystem /home/yan/ssd/searchtrunk/tmp/release/contrib/boost_1_69_0/include -isystem /home/yan/ssd/searchtrunk/tmp/release/contrib/icu-49.1.2/include -isystem /home/yan/ssd/searchtrunk/tmp/release/contrib/protobuf-3.4.0/include -I/home/yan/ssd/searchtrunk/tmp/release -isystem /home/yan/ssd/searchtrunk/tmp/release/contrib/opencv-3.0.0m2/include -isystem /home/yan/ssd/searchtrunk/tmp/release/contrib/dlib-19.7p1/include -Wno-array-bounds -o CMakeFiles/image_crop.dir/src/crop_context.cpp.o -c /home/yan/ssd/searchtrunk/libsrc/image_crop/src/crop_context.cpp
Building CXX object libsrc/image_crop/CMakeFiles/image_crop.dir/src/detector.cpp.o
Building CXX object libsrc/image_crop/CMakeFiles/image_crop.dir/src/image_crop.cpp.o
cd /home/yan/ssd/searchtrunk/tmp/release/libsrc/image_crop && /opt/rh/devtoolset-7/root/usr/bin/c++ -DGOGO_USE_LIBEVENT2=1 -DGOGO_USE_OPENSSL_SNI=1 -DHAVE_BOOST -DHAVE_GLIBC -DHAVE_MALLOC_TRIM -DHAVE_PREAD -DHAVE_READAHEAD -D_FILE_OFFSET_BITS=64 -D_STAT_LEMM -pipe -Wall -Wextra -Werror=multichar -Wno-deprecated -Wno-unused-parameter -pthread -fPIC -Woverloaded-virtual -Wnon-virtual-dtor -Werror -std=gnu++11 -Wno-unknown-pragmas -DBOOST_FILESYSTEM_VERSION=3 -DBOOST_NO_CXX11_HDR_CODECVT -DMAGICKCORE_QUANTUM_DEPTH=8 -DMAGICKCORE_HDRI_ENABLE=0 -Wno-unused-local-typedefs -D_GLIBCXX_USE_CXX11_ABI=0 -std=gnu++14 -DCXXHASH128_EXIST -static-libstdc++ -Wno-implicit-fallthrough -Wno-stringop-overflow -O3 -DNDEBUG -DBOOST_UBLAS_NDEBUG -g0 -march=core2 -mssse3 -msse4.1 -I/home/yan/ssd/searchtrunk/tmp/release/__inc -I/home/yan/ssd/searchtrunk/libsrc/image_crop/src -I/home/yan/ssd/searchtrunk/include -isystem /home/yan/ssd/searchtrunk/tmp/release/contrib/boost_1_69_0/include -isystem /home/yan/ssd/searchtrunk/tmp/release/contrib/icu-49.1.2/include -isystem /home/yan/ssd/searchtrunk/tmp/release/contrib/protobuf-3.4.0/include -I/home/yan/ssd/searchtrunk/tmp/release -isystem /home/yan/ssd/searchtrunk/tmp/release/contrib/opencv-3.0.0m2/include -isystem /home/yan/ssd/searchtrunk/tmp/release/contrib/dlib-19.7p1/include -Wno-array-bounds -o CMakeFiles/image_crop.dir/src/detector.cpp.o -c /home/yan/ssd/searchtrunk/libsrc/image_crop/src/detector.cpp
Built target coroutine
cd /home/yan/ssd/searchtrunk/tmp/release/libsrc/image_crop && /opt/rh/devtoolset-7/root/usr/bin/c++ -DGOGO_USE_LIBEVENT2=1 -DGOGO_USE_OPENSSL_SNI=1 -DHAVE_BOOST -DHAVE_GLIBC -DHAVE_MALLOC_TRIM -DHAVE_PREAD -DHAVE_READAHEAD -D_FILE_OFFSET_BITS=64 -D_STAT_LEMM -pipe -Wall -Wextra -Werror=multichar -Wno-deprecated -Wno-unused-parameter -pthread -fPIC -Woverloaded-virtual -Wnon-virtual-dtor -Werror -std=gnu++11 -Wno-unknown-pragmas -DBOOST_FILESYSTEM_VERSION=3 -DBOOST_NO_CXX11_HDR_CODECVT -DMAGICKCORE_QUANTUM_DEPTH=8 -DMAGICKCORE_HDRI_ENABLE=0 -Wno-unused-local-typedefs -D_GLIBCXX_USE_CXX11_ABI=0 -std=gnu++14 -DCXXHASH128_EXIST -static-libstdc++ -Wno-implicit-fallthrough -Wno-stringop-overflow -O3 -DNDEBUG -DBOOST_UBLAS_NDEBUG -g0 -march=core2 -mssse3 -msse4.1 -I/home/yan/ssd/searchtrunk/tmp/release/__inc -I/home/yan/ssd/searchtrunk/libsrc/image_crop/src -I/home/yan/ssd/searchtrunk/include -isystem /home/yan/ssd/searchtrunk/tmp/release/contrib/boost_1_69_0/include -isystem /home/yan/ssd/searchtrunk/tmp/release/contrib/icu-49.1.2/include -isystem /home/yan/ssd/searchtrunk/tmp/release/contrib/protobuf-3.4.0/include -I/home/yan/ssd/searchtrunk/tmp/release -isystem /home/yan/ssd/searchtrunk/tmp/release/contrib/opencv-3.0.0m2/include -isystem /home/yan/ssd/searchtrunk/tmp/release/contrib/dlib-19.7p1/include -Wno-array-bounds -o CMakeFiles/image_crop.dir/src/image_crop.cpp.o -c /home/yan/ssd/searchtrunk/libsrc/image_crop/src/image_crop.cpp
make[3]: Entering directory `/home/yan/ssd/searchtrunk/tmp/release'
make[3]: Nothing to be done for `libsrc/base/CMakeFiles/base.dir/build'.
make[3]: Leaving directory `/home/yan/ssd/searchtrunk/tmp/release'
/usr/bin/cmake -E cmake_progress_report /home/yan/ssd/searchtrunk/tmp/release/CMakeFiles
make[3]: Leaving directory `/home/yan/ssd/searchtrunk/tmp/release'
make -f projects/protogen/cpp/CMakeFiles/protogen.dir/build.make projects/protogen/cpp/CMakeFiles/protogen.dir/build
[ 0%] Built target base
In file included from /home/yan/ssd/searchtrunk/include/image_crop/detector.hpp:3:0,
from /home/yan/ssd/searchtrunk/libsrc/image_crop/src/detector.cpp:2:
/home/yan/ssd/searchtrunk/include/image_crop/crop_context.hpp:6:10: fatal error: opencv2/dnn.hpp: No such file or directory
#include <opencv2/dnn.hpp>
^~~~~~~~~~~~~~~~~
compilation terminated.
make[3]: *** [libsrc/image_crop/CMakeFiles/image_crop.dir/src/detector.cpp.o] Error 1
make[3]: *** Waiting for unfinished jobs....
In file included from /home/yan/ssd/searchtrunk/include/image_crop/image_crop.hpp:3:0,
from /home/yan/ssd/searchtrunk/libsrc/image_crop/src/image_crop.cpp:1:
/home/yan/ssd/searchtrunk/include/image_crop/crop_context.hpp:6:10: fatal error: opencv2/dnn.hpp: No such file or directory
#include <opencv2/dnn.hpp>
^~~~~~~~~~~~~~~~~
compilation terminated.
make[3]: *** [libsrc/image_crop/CMakeFiles/image_crop.dir/src/image_crop.cpp.o] Error 1
In file included from /home/yan/ssd/searchtrunk/libsrc/image_crop/src/crop_context.cpp:1:0:
/home/yan/ssd/searchtrunk/include/image_crop/crop_context.hpp:6:10: fatal error: opencv2/dnn.hpp: No such file or directory
#include <opencv2/dnn.hpp>
^~~~~~~~~~~~~~~~~
compilation terminated.
make[3]: *** [libsrc/image_crop/CMakeFiles/image_crop.dir/src/crop_context.cpp.o] Error 1
make[3]: Leaving directory `/home/yan/ssd/searchtrunk/tmp/release'
make[2]: *** [libsrc/image_crop/CMakeFiles/image_crop.dir/all] Error 2
make[2]: *** Waiting for unfinished jobs....
make[3]: Entering directory `/home/yan/ssd/searchtrunk/tmp/release'
make[3]: Nothing to be done for `projects/protogen/cpp/CMakeFiles/protogen.dir/build'.
make[3]: Leaving directory `/home/yan/ssd/searchtrunk/tmp/release'
/usr/bin/cmake -E cmake_progress_report /home/yan/ssd/searchtrunk/tmp/release/CMakeFiles 63 64 65 66
[ 25%] Built target protogen
make[2]: Leaving directory `/home/yan/ssd/searchtrunk/tmp/release'
make[1]: *** [all] Error 2
make[1]: Leaving directory `/home/yan/ssd/searchtrunk/tmp/release/projects/projectX'
make: *** [install] Error 2
yan@yPC:~/ssd/searchtrunk/projects/projectX$
+21
View File
@@ -0,0 +1,21 @@
{
"name": "xterm-addon-search",
"version": "0.6.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
},
"main": "lib/xterm-addon-search.js",
"types": "typings/xterm-addon-search.d.ts",
"repository": "https://github.com/xtermjs/xterm.js",
"license": "MIT",
"scripts": {
"build": "../../node_modules/.bin/tsc -p src",
"prepackage": "npm run build",
"package": "../../node_modules/.bin/webpack",
"prepublishOnly": "npm run package"
},
"peerDependencies": {
"xterm": "^4.0.0"
}
}
@@ -0,0 +1,197 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { assert } from 'chai';
import { readFile } from 'fs';
import { resolve } from 'path';
import { openTerminal, writeSync, getBrowserType } from '../../../out-test/api/TestUtils';
import { Browser, Page } from 'playwright-core';
const APP = 'http://127.0.0.1:3000/test';
let browser: Browser;
let page: Page;
const width = 800;
const height = 600;
describe('Search Tests', function(): void {
before(async function(): Promise<any> {
const browserType = getBrowserType();
browser = await browserType.launch({ dumpio: true,
headless: process.argv.indexOf('--headless') !== -1
});
page = await (await browser.newContext()).newPage();
await page.setViewportSize({ width, height });
await page.goto(APP);
await openTerminal(page);
await page.evaluate(`window.search = new SearchAddon();`);
await page.evaluate(`window.term.loadAddon(window.search);`);
});
after(() => {
browser.close();
});
beforeEach(async () => {
await page.evaluate(`window.term.reset()`);
});
it('Simple Search', async () => {
await writeSync(page, 'dafhdjfldshafhldsahfkjhldhjkftestlhfdsakjfhdjhlfdsjkafhjdlk');
assert.deepEqual(await page.evaluate(`window.search.findNext('test')`), true);
assert.deepEqual(await page.evaluate(`window.term.getSelection()`), 'test');
});
it('Scrolling Search', async () => {
let dataString = '';
for (let i = 0; i < 100; i++) {
if (i === 52) {
dataString += '$^1_3{}test$#';
}
dataString += makeData(50);
}
await writeSync(page, dataString);
assert.deepEqual(await page.evaluate(`window.search.findNext('$^1_3{}test$#')`), true);
assert.deepEqual(await page.evaluate(`window.term.getSelection()`), '$^1_3{}test$#');
});
it('Incremental Find Previous', async () => {
await page.evaluate(`window.term.writeln('package.jsonc\\n')`);
await writeSync(page, 'package.json pack package.lock');
await page.evaluate(`window.search.findPrevious('pack', {incremental: true})`);
let line: string = await page.evaluate(`window.term.buffer.active.getLine(window.term.getSelectionPosition().startRow).translateToString()`);
let selectionPosition: { startColumn: number, startRow: number, endColumn: number, endRow: number } = await page.evaluate(`window.term.getSelectionPosition()`);
// We look further ahead in the line to ensure that pack was selected from package.lock
assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn + 8), 'package.lock');
await page.evaluate(`window.search.findPrevious('package.j', {incremental: true})`);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn + 3), 'package.json');
await page.evaluate(`window.search.findPrevious('package.jsonc', {incremental: true})`);
// We have to reevaluate line because it should have switched starting rows at this point
line = await page.evaluate(`window.term.buffer.active.getLine(window.term.getSelectionPosition().startRow).translateToString()`);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn), 'package.jsonc');
});
it('Incremental Find Next', async () => {
await page.evaluate(`window.term.writeln('package.lock pack package.json package.ups\\n')`);
await writeSync(page, 'package.jsonc');
await page.evaluate(`window.search.findNext('pack', {incremental: true})`);
let line: string = await page.evaluate(`window.term.buffer.active.getLine(window.term.getSelectionPosition().startRow).translateToString()`);
let selectionPosition: { startColumn: number, startRow: number, endColumn: number, endRow: number } = await page.evaluate(`window.term.getSelectionPosition()`);
// We look further ahead in the line to ensure that pack was selected from package.lock
assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn + 8), 'package.lock');
await page.evaluate(`window.search.findNext('package.j', {incremental: true})`);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn + 3), 'package.json');
await page.evaluate(`window.search.findNext('package.jsonc', {incremental: true})`);
// We have to reevaluate line because it should have switched starting rows at this point
line = await page.evaluate(`window.term.buffer.active.getLine(window.term.getSelectionPosition().startRow).translateToString()`);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn), 'package.jsonc');
});
it('Simple Regex', async () => {
await writeSync(page, 'abc123defABCD');
await page.evaluate(`window.search.findNext('[a-z]+', {regex: true})`);
assert.deepEqual(await page.evaluate(`window.term.getSelection()`), 'abc');
await page.evaluate(`window.search.findNext('[A-Z]+', {regex: true, caseSensitive: true})`);
assert.deepEqual(await page.evaluate(`window.term.getSelection()`), 'ABCD');
});
it('Search for single result twice should not unselect it', async () => {
await writeSync(page, 'abc def');
assert.deepEqual(await page.evaluate(`window.search.findNext('abc')`), true);
assert.deepEqual(await page.evaluate(`window.term.getSelection()`), 'abc');
assert.deepEqual(await page.evaluate(`window.search.findNext('abc')`), true);
assert.deepEqual(await page.evaluate(`window.term.getSelection()`), 'abc');
});
describe('Regression tests', () => {
describe('#2444 wrapped line content not being found', () => {
let fixture: string;
before(async () => {
const rawFixture = await new Promise<Buffer>(r => readFile(resolve(__dirname, '../fixtures/issue-2444'), (err, data) => r(data)));
fixture = rawFixture.toString()
.replace(/\n/g, '\\n\\r')
.replace(/'/g, '\\\'');
});
it('should find all occurrences using findNext', async () => {
await writeSync(page, fixture);
assert.deepEqual(await page.evaluate(`window.search.findNext('opencv')`), true);
let selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 24, startRow: 53, endColumn: 30, endRow: 53 });
assert.deepEqual(await page.evaluate(`window.search.findNext('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 24, startRow: 76, endColumn: 30, endRow: 76 });
assert.deepEqual(await page.evaluate(`window.search.findNext('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 24, startRow: 96, endColumn: 30, endRow: 96 });
assert.deepEqual(await page.evaluate(`window.search.findNext('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 1, startRow: 114, endColumn: 7, endRow: 114 });
assert.deepEqual(await page.evaluate(`window.search.findNext('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 11, startRow: 115, endColumn: 17, endRow: 115 });
assert.deepEqual(await page.evaluate(`window.search.findNext('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 1, startRow: 126, endColumn: 7, endRow: 126 });
assert.deepEqual(await page.evaluate(`window.search.findNext('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 11, startRow: 127, endColumn: 17, endRow: 127 });
assert.deepEqual(await page.evaluate(`window.search.findNext('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 1, startRow: 135, endColumn: 7, endRow: 135 });
assert.deepEqual(await page.evaluate(`window.search.findNext('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 11, startRow: 136, endColumn: 17, endRow: 136 });
// Wrap around to first result
assert.deepEqual(await page.evaluate(`window.search.findNext('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 24, startRow: 53, endColumn: 30, endRow: 53 });
});
it('should find all occurrences using findPrevious', async () => {
await writeSync(page, fixture);
assert.deepEqual(await page.evaluate(`window.search.findPrevious('opencv')`), true);
let selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 11, startRow: 136, endColumn: 17, endRow: 136 });
assert.deepEqual(await page.evaluate(`window.search.findPrevious('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 1, startRow: 135, endColumn: 7, endRow: 135 });
assert.deepEqual(await page.evaluate(`window.search.findPrevious('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 11, startRow: 127, endColumn: 17, endRow: 127 });
assert.deepEqual(await page.evaluate(`window.search.findPrevious('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 1, startRow: 126, endColumn: 7, endRow: 126 });
assert.deepEqual(await page.evaluate(`window.search.findPrevious('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 11, startRow: 115, endColumn: 17, endRow: 115 });
assert.deepEqual(await page.evaluate(`window.search.findPrevious('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 1, startRow: 114, endColumn: 7, endRow: 114 });
assert.deepEqual(await page.evaluate(`window.search.findPrevious('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 24, startRow: 96, endColumn: 30, endRow: 96 });
assert.deepEqual(await page.evaluate(`window.search.findPrevious('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 24, startRow: 76, endColumn: 30, endRow: 76 });
assert.deepEqual(await page.evaluate(`window.search.findPrevious('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 24, startRow: 53, endColumn: 30, endRow: 53 });
// Wrap around to first result
assert.deepEqual(await page.evaluate(`window.search.findPrevious('opencv')`), true);
selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`);
assert.deepEqual(selectionPosition, { startColumn: 11, startRow: 136, endColumn: 17, endRow: 136 });
});
});
});
});
function makeData(length: number): string {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * characters.length));
}
return result;
}
@@ -3,30 +3,48 @@
* @license MIT
*/
import { ISearchHelper, ISearchAddonTerminal, ISearchOptions, ISearchResult } from './Interfaces';
import { IDisposable } from 'xterm';
import { Terminal, IDisposable, ITerminalAddon, ISelectionPosition } from 'xterm';
export interface ISearchOptions {
regex?: boolean;
wholeWord?: boolean;
caseSensitive?: boolean;
incremental?: boolean;
}
export interface ISearchPosition {
startCol: number;
startRow: number;
}
export interface ISearchResult {
term: string;
col: number;
row: number;
}
const NON_WORD_CHARACTERS = ' ~!@#$%^&*()+`-=[]{}|\;:"\',./<>?';
const LINES_CACHE_TIME_TO_LIVE = 15 * 1000; // 15 secs
/**
* A class that knows how to search the terminal and how to display the results.
*/
export class SearchHelper implements ISearchHelper {
export class SearchAddon implements ITerminalAddon {
private _terminal: Terminal | undefined;
/**
* translateBufferLineToStringWithWrap is a fairly expensive call.
* We memoize the calls into an array that has a time based ttl.
* _linesCache is also invalidated when the terminal cursor moves.
*/
private _linesCache: string[] = null;
private _linesCache: string[] | undefined;
private _linesCacheTimeoutId = 0;
private _cursorMoveListener: IDisposable | undefined;
private _resizeListener: IDisposable | undefined;
constructor(private _terminal: ISearchAddonTerminal) {
this._destroyLinesCache = this._destroyLinesCache.bind(this);
public activate(terminal: Terminal): void {
this._terminal = terminal;
}
public dispose(): void { }
/**
* Find the next instance of the term, then scroll to and select it. If it
* doesn't exist, do nothing.
@@ -35,65 +53,65 @@ export class SearchHelper implements ISearchHelper {
* @return Whether a result was found.
*/
public findNext(term: string, searchOptions?: ISearchOptions): boolean {
const {incremental} = searchOptions;
let result: ISearchResult;
if (!this._terminal) {
throw new Error('Cannot use addon until it has been loaded');
}
if (!term || term.length === 0) {
this._terminal.clearSelection();
return false;
}
let startCol: number = 0;
let startRow = this._terminal.buffer.viewportY;
let startCol = 0;
let startRow = 0;
let currentSelection: ISelectionPosition | undefined;
if (this._terminal.hasSelection()) {
const incremental = searchOptions ? searchOptions.incremental : false;
// Start from the selection end if there is a selection
// For incremental search, use existing row
const currentSelection = this._terminal.getSelectionPosition();
currentSelection = this._terminal.getSelectionPosition()!;
startRow = incremental ? currentSelection.startRow : currentSelection.endRow;
startCol = incremental ? currentSelection.startColumn : currentSelection.endColumn;
}
this._initLinesCache();
// A row that has isWrapped = false
let findingRow = startRow;
// index of beginning column that _findInLine need to scan.
let cumulativeCols = startCol;
// If startRow is wrapped row, scan for unwrapped row above.
// So we can start matching on wrapped line from long unwrapped line.
while (this._terminal.buffer.getLine(findingRow).isWrapped) {
findingRow--;
cumulativeCols += this._terminal.cols;
}
const searchPosition: ISearchPosition = {
startRow,
startCol
};
// Search startRow
result = this._findInLine(term, findingRow, cumulativeCols, searchOptions);
let result = this._findInLine(term, searchPosition, searchOptions);
// Search from startRow + 1 to end
if (!result) {
for (let y = startRow + 1; y < this._terminal.buffer.baseY + this._terminal.rows; y++) {
for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) {
searchPosition.startRow = y;
searchPosition.startCol = 0;
// If the current line is wrapped line, increase index of column to ignore the previous scan
// Otherwise, reset beginning column index to zero with set new unwrapped line index
result = this._findInLine(term, y, 0, searchOptions);
result = this._findInLine(term, searchPosition, searchOptions);
if (result) {
break;
}
}
}
// If we hit the bottom and didn't search from the very top wrap back up
if (!result && startRow !== 0) {
for (let y = 0; y < startRow; y++) {
searchPosition.startRow = y;
searchPosition.startCol = 0;
result = this._findInLine(term, searchPosition, searchOptions);
if (result) {
break;
}
}
}
// Search from the top to the startRow (search the whole startRow again in
// case startCol > 0)
if (!result) {
for (let y = 0; y < findingRow; y++) {
result = this._findInLine(term, y, 0, searchOptions);
if (result) {
break;
}
}
}
// If there is only one result, return true.
if (!result && currentSelection) return true;
// Set selection and scroll if a result was found
return this._selectResult(result);
@@ -107,7 +125,9 @@ export class SearchHelper implements ISearchHelper {
* @return Whether a result was found.
*/
public findPrevious(term: string, searchOptions?: ISearchOptions): boolean {
let result: ISearchResult;
if (!this._terminal) {
throw new Error('Cannot use addon until it has been loaded');
}
if (!term || term.length === 0) {
this._terminal.clearSelection();
@@ -115,61 +135,57 @@ export class SearchHelper implements ISearchHelper {
}
const isReverseSearch = true;
let startRow = this._terminal.buffer.viewportY + this._terminal.rows - 1;
let startRow = this._terminal.buffer.active.baseY + this._terminal.rows;
let startCol = this._terminal.cols;
let result: ISearchResult | undefined;
const incremental = searchOptions ? searchOptions.incremental : false;
let currentSelection: ISelectionPosition | undefined;
if (this._terminal.hasSelection()) {
// Start from the selection start if there is a selection
const currentSelection = this._terminal.getSelectionPosition();
currentSelection = this._terminal.getSelectionPosition()!;
// Start from selection start if there is a selection
startRow = currentSelection.startRow;
startCol = currentSelection.startColumn;
}
this._initLinesCache();
const searchPosition: ISearchPosition = {
startRow,
startCol
};
// Search startRow
result = this._findInLine(term, startRow, startCol, searchOptions, isReverseSearch);
if (incremental) {
result = this._findInLine(term, searchPosition, searchOptions, false);
if (!(result && result.row === startRow && result.col === startCol)) {
result = this._findInLine(term, searchPosition, searchOptions, true);
}
} else {
result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);
}
// Search from startRow - 1 to top
if (!result) {
// If the line is wrapped line, increase number of columns that is needed to be scanned
// Se we can scan on wrapped line from unwrapped line
let cumulativeCols = this._terminal.cols;
if (this._terminal.buffer.getLine(startRow).isWrapped) {
cumulativeCols += startCol;
}
searchPosition.startCol = Math.max(searchPosition.startCol, this._terminal.cols);
for (let y = startRow - 1; y >= 0; y--) {
result = this._findInLine(term, y, cumulativeCols, searchOptions, isReverseSearch);
searchPosition.startRow = y;
result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);
if (result) {
break;
}
// If the current line is wrapped line, increase scanning range,
// preparing for scanning on unwrapped line
if (this._terminal.buffer.getLine(y).isWrapped) {
cumulativeCols += this._terminal.cols;
} else {
cumulativeCols = this._terminal.cols;
}
}
// If we hit the top and didn't search from the very bottom wrap back down
if (!result && startRow !== (this._terminal.buffer.active.baseY + this._terminal.rows)) {
for (let y = (this._terminal.buffer.active.baseY + this._terminal.rows); y > startRow; y--) {
searchPosition.startRow = y;
result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);
if (result) {
break;
}
}
}
// Search from the bottom to startRow (search the whole startRow again in
// case startCol > 0)
if (!result) {
const searchFrom = this._terminal.buffer.baseY + this._terminal.rows - 1;
let cumulativeCols = this._terminal.cols;
for (let y = searchFrom; y >= startRow; y--) {
result = this._findInLine(term, y, cumulativeCols, searchOptions, isReverseSearch);
if (result) {
break;
}
if (this._terminal.buffer.getLine(y).isWrapped) {
cumulativeCols += this._terminal.cols;
} else {
cumulativeCols = this._terminal.cols;
}
}
}
// If there is only one result, return true.
if (!result && currentSelection) return true;
// Set selection and scroll if a result was found
return this._selectResult(result);
@@ -179,10 +195,11 @@ export class SearchHelper implements ISearchHelper {
* Sets up a line cache with a ttl
*/
private _initLinesCache(): void {
const terminal = this._terminal!;
if (!this._linesCache) {
this._linesCache = new Array(this._terminal.buffer.length);
this._cursorMoveListener = this._terminal.onCursorMove(() => this._destroyLinesCache());
this._resizeListener = this._terminal.onResize(() => this._destroyLinesCache());
this._linesCache = new Array(terminal.buffer.active.length);
this._cursorMoveListener = terminal.onCursorMove(() => this._destroyLinesCache());
this._resizeListener = terminal.onResize(() => this._destroyLinesCache());
}
window.clearTimeout(this._linesCacheTimeoutId);
@@ -190,7 +207,7 @@ export class SearchHelper implements ISearchHelper {
}
private _destroyLinesCache(): void {
this._linesCache = null;
this._linesCache = undefined;
if (this._cursorMoveListener) {
this._cursorMoveListener.dispose();
this._cursorMoveListener = undefined;
@@ -213,7 +230,7 @@ export class SearchHelper implements ISearchHelper {
*/
private _isWholeWord(searchIndex: number, line: string, term: string): boolean {
return (((searchIndex === 0) || (NON_WORD_CHARACTERS.indexOf(line[searchIndex - 1]) !== -1)) &&
(((searchIndex + term.length) === line.length) || (NON_WORD_CHARACTERS.indexOf(line[searchIndex + term.length]) !== -1)));
(((searchIndex + term.length) === line.length) || (NON_WORD_CHARACTERS.indexOf(line[searchIndex + term.length]) !== -1)));
}
/**
@@ -222,20 +239,32 @@ export class SearchHelper implements ISearchHelper {
* started on an earlier line then it is skipped since it will be properly searched when the terminal line that the
* text starts on is searched.
* @param term The search term.
* @param row The line to start the search from.
* @param col The column to start the search from.
* @param position The position to start the search.
* @param searchOptions Search options.
* @return The search result if it was found.
*/
protected _findInLine(term: string, row: number, col: number, searchOptions: ISearchOptions = {}, isReverseSearch: boolean = false): ISearchResult {
protected _findInLine(term: string, searchPosition: ISearchPosition, searchOptions: ISearchOptions = {}, isReverseSearch: boolean = false): ISearchResult | undefined {
const terminal = this._terminal!;
let row = searchPosition.startRow;
const col = searchPosition.startCol;
// Ignore wrapped lines, only consider on unwrapped line (first row of command string).
if (this._terminal.buffer.getLine(row).isWrapped) {
return;
const firstLine = terminal.buffer.active.getLine(row);
if (firstLine && firstLine.isWrapped) {
if (isReverseSearch) {
searchPosition.startCol += terminal.cols;
return;
}
// This will iterate until we find the line start.
// When we find it, we will search using the calculated start column.
searchPosition.startRow--;
searchPosition.startCol += terminal.cols;
return this._findInLine(term, searchPosition, searchOptions);
}
let stringLine = this._linesCache ? this._linesCache[row] : void 0;
if (stringLine === void 0) {
stringLine = this.translateBufferLineToStringWithWrap(row, true);
stringLine = this._translateBufferLineToStringWithWrap(row, true);
if (this._linesCache) {
this._linesCache[row] = stringLine;
}
@@ -247,7 +276,7 @@ export class SearchHelper implements ISearchHelper {
let resultIndex = -1;
if (searchOptions.regex) {
const searchRegex = RegExp(searchTerm, 'g');
let foundTerm: RegExpExecArray;
let foundTerm: RegExpExecArray | null;
if (isReverseSearch) {
// This loop will get the resultIndex of the _last_ regex match in the range 0..col
while (foundTerm = searchRegex.exec(searchStringLine.slice(0, col))) {
@@ -274,28 +303,33 @@ export class SearchHelper implements ISearchHelper {
if (resultIndex >= 0) {
// Adjust the row number and search index if needed since a "line" of text can span multiple rows
if (resultIndex >= this._terminal.cols) {
row += Math.floor(resultIndex / this._terminal.cols);
resultIndex = resultIndex % this._terminal.cols;
if (resultIndex >= terminal.cols) {
row += Math.floor(resultIndex / terminal.cols);
resultIndex = resultIndex % terminal.cols;
}
if (searchOptions.wholeWord && !this._isWholeWord(resultIndex, searchStringLine, term)) {
return;
}
const line = this._terminal.buffer.getLine(row);
const line = terminal.buffer.active.getLine(row);
for (let i = 0; i < resultIndex; i++) {
const cell = line.getCell(i);
// Adjust the searchIndex to normalize emoji into single chars
const char = cell.char;
if (char.length > 1) {
resultIndex -= char.length - 1;
}
// Adjust the searchIndex for empty characters following wide unicode
// chars (eg. CJK)
const charWidth = cell.width;
if (charWidth === 0) {
resultIndex++;
if (line) {
for (let i = 0; i < resultIndex; i++) {
const cell = line.getCell(i);
if (!cell) {
break;
}
// Adjust the searchIndex to normalize emoji into single chars
const char = cell.getChars();
if (char.length > 1) {
resultIndex -= char.length - 1;
}
// Adjust the searchIndex for empty characters following wide unicode
// chars (eg. CJK)
const charWidth = cell.getWidth();
if (charWidth === 0) {
resultIndex++;
}
}
}
return {
@@ -305,6 +339,7 @@ export class SearchHelper implements ISearchHelper {
};
}
}
/**
* Translates a buffer line to a string, including subsequent lines if they are wraps.
* Wide characters will count as two columns in the resulting string. This
@@ -313,14 +348,19 @@ export class SearchHelper implements ISearchHelper {
* @param line The line being translated.
* @param trimRight Whether to trim whitespace to the right.
*/
public translateBufferLineToStringWithWrap(lineIndex: number, trimRight: boolean): string {
private _translateBufferLineToStringWithWrap(lineIndex: number, trimRight: boolean): string {
const terminal = this._terminal!;
let lineString = '';
let lineWrapsToNext: boolean;
do {
const nextLine = this._terminal.buffer.getLine(lineIndex + 1);
const nextLine = terminal.buffer.active.getLine(lineIndex + 1);
lineWrapsToNext = nextLine ? nextLine.isWrapped : false;
lineString += this._terminal.buffer.getLine(lineIndex).translateToString(!lineWrapsToNext && trimRight).substring(0, this._terminal.cols);
const line = terminal.buffer.active.getLine(lineIndex);
if (!line) {
break;
}
lineString += line.translateToString(!lineWrapsToNext && trimRight).substring(0, terminal.cols);
lineIndex++;
} while (lineWrapsToNext);
@@ -332,13 +372,19 @@ export class SearchHelper implements ISearchHelper {
* @param result The result to select.
* @return Whethera result was selected.
*/
private _selectResult(result: ISearchResult): boolean {
private _selectResult(result: ISearchResult | undefined): boolean {
const terminal = this._terminal!;
if (!result) {
this._terminal.clearSelection();
terminal.clearSelection();
return false;
}
this._terminal.select(result.col, result.row, result.term.length);
this._terminal.scrollLines(result.row - this._terminal.buffer.viewportY);
terminal.select(result.col, result.row, result.term.length);
// If it is not in the viewport then we scroll else it just gets selected
if (result.row >= (terminal.buffer.active.viewportY + terminal.rows) || result.row < terminal.buffer.active.viewportY) {
let scroll = result.row - terminal.buffer.active.viewportY;
scroll = scroll - Math.floor(terminal.rows / 2);
terminal.scrollLines(scroll);
}
return true;
}
}
@@ -4,19 +4,20 @@
"target": "es5",
"lib": [
"dom",
"es5"
"es6",
],
"rootDir": ".",
"outDir": "../../../lib/addons/search/",
"outDir": "../out",
"sourceMap": true,
"removeComments": true,
"declaration": true,
"strict": true,
"types": [
"../../node_modules/@types/mocha"
"../../../node_modules/@types/mocha",
"../../../out-test/api/TestUtils"
]
},
"include": [
"**/*.ts",
"./**/*",
"../../../typings/xterm.d.ts"
]
}
@@ -0,0 +1,68 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { Terminal, ILinkMatcherOptions, IDisposable, ITerminalAddon } from 'xterm';
declare module 'xterm-addon-search' {
/**
* Options for a search.
*/
export interface ISearchOptions {
/**
* Whether the search term is a regex.
*/
regex?: boolean;
/**
* Whether to search for a whole word, the result is only valid if it's
* surrounded in "non-word" characters such as `_`, `(`, `)` or space.
*/
wholeWord?: boolean;
/**
* Whether the search is case sensitive.
*/
caseSensitive?: boolean;
/**
* Whether to do an incremental search, this will expand the selection if it
* still matches the term the user typed. Note that this only affects
* `findNext`, not `findPrevious`.
*/
incremental?: boolean;
}
/**
* An xterm.js addon that provides search functionality.
*/
export class SearchAddon implements ITerminalAddon {
/**
* Activates the addon
* @param terminal The terminal the addon is being loaded in.
*/
public activate(terminal: Terminal): void;
/**
* Disposes the addon.
*/
public dispose(): void;
/**
* Search forwards for the next result that matches the search term and
* options.
* @param term The search term.
* @param searchOptions The options for the search.
*/
public findNext(term: string, searchOptions?: ISearchOptions): boolean;
/**
* Search backwards for the previous result that matches the search term and
* options.
* @param term The search term.
* @param searchOptions The options for the search.
*/
public findPrevious(term: string, searchOptions?: ISearchOptions): boolean;
}
}
@@ -0,0 +1,31 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
const path = require('path');
const addonName = 'SearchAddon';
const mainFile = 'xterm-addon-search.js';
module.exports = {
entry: `./out/${addonName}.js`,
devtool: 'source-map',
module: {
rules: [
{
test: /\.js$/,
use: ["source-map-loader"],
enforce: "pre",
exclude: /node_modules/
}
]
},
output: {
filename: mainFile,
path: path.resolve('./lib'),
library: addonName,
libraryTarget: 'umd'
},
mode: 'production'
};
+3
View File
@@ -0,0 +1,3 @@
lib
node_modules
out-benchmark
+5
View File
@@ -0,0 +1,5 @@
**/*.api.js
**/*.api.ts
tsconfig.json
.yarnrc
webpack.config.js
+42
View File
@@ -0,0 +1,42 @@
## xterm-addon-serialize
An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables xterm.js to serialize a terminal framebuffer into string or html. This addon requires xterm.js v4+.
⚠️ This is an experimental addon that is still under construction ⚠️
### Install
```bash
npm install --save xterm-addon-serialize
```
### Usage
```ts
import { Terminal } from "xterm";
import { SerializeAddon } from "xterm-addon-serialize";
const terminal = new Terminal();
const serializeAddon = new SerializeAddon();
terminal.loadAddon(serializeAddon);
terminal.write("something...", () => {
console.log(serializeAddon.serialize());
});
```
See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts) for more advanced usage.
### Benchmark
⚠️ Ensure you have `lolcat`, `hexdump` programs installed in your computer
```shell
$ git clone https://github.com/xtermjs/xterm.js.git
$ cd xterm.js
$ yarn
$ cd addons/xterm-addon-serialize
$ yarn benchmark && yarn benchmark-baseline
$ # change some code in `xterm-addon-serialize`
$ yarn benchmark-eval
```
@@ -0,0 +1,65 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { perfContext, before, ThroughputRuntimeCase } from 'xterm-benchmark';
import { spawn } from 'node-pty';
import { Utf8ToUtf32, stringFromCodePoint } from 'common/input/TextDecoder';
import { Terminal } from 'public/Terminal';
import { SerializeAddon } from 'SerializeAddon';
class TestTerminal extends Terminal {
writeSync(data: string): void {
(this as any)._core.writeSync(data);
}
}
perfContext('Terminal: sh -c "dd if=/dev/random count=40 bs=1k | hexdump | lolcat -f"', () => {
let content = '';
let contentUtf8: Uint8Array;
before(async () => {
const p = spawn('sh', ['-c', 'dd if=/dev/random count=40 bs=1k | hexdump | lolcat -f'], {
name: 'xterm-256color',
cols: 80,
rows: 25,
cwd: process.env.HOME,
env: process.env,
encoding: (null as unknown as string) // needs to be fixed in node-pty
});
const chunks: Buffer[] = [];
let length = 0;
p.on('data', data => {
chunks.push(data as unknown as Buffer);
length += data.length;
});
await new Promise(resolve => p.on('exit', () => resolve()));
contentUtf8 = Buffer.concat(chunks, length);
// translate to content string
const buffer = new Uint32Array(contentUtf8.length);
const decoder = new Utf8ToUtf32();
const codepoints = decoder.decode(contentUtf8, buffer);
for (let i = 0; i < codepoints; ++i) {
content += stringFromCodePoint(buffer[i]);
// peek into content to force flat repr in v8
if (!(i % 10000000)) {
content[i];
}
}
});
perfContext('serialize', () => {
let terminal: TestTerminal;
const serializeAddon = new SerializeAddon();
before(() => {
terminal = new TestTerminal({ cols: 80, rows: 25, scrollback: 5000 });
serializeAddon.activate(terminal);
terminal.writeSync(content);
});
new ThroughputRuntimeCase('', () => {
return { payloadSize: serializeAddon.serialize().length };
}, { fork: false }).showAverageThroughput();
});
});
@@ -0,0 +1,19 @@
{
"APP_PATH": ".benchmark",
"evalConfig": {
"tolerance": {
"*": [0.75, 1.5],
"*.dev": [0.01, 1.5],
"*.cv": [0.01, 1.5],
"EscapeSequenceParser.benchmark.js.*.averageThroughput.mean": [0.9, 5]
},
"skip": [
"*.median",
"*.runs",
"*.dev",
"*.cv",
"EscapeSequenceParser.benchmark.js.*.averageRuntime",
"Terminal.benchmark.js.*.averageRuntime"
]
}
}
@@ -0,0 +1,25 @@
{
"compilerOptions": {
"lib": ["dom", "es6"],
"outDir": "../out-benchmark",
"types": ["../../../node_modules/@types/node"],
"moduleResolution": "node",
"strict": false,
"target": "es2015",
"module": "commonjs",
"baseUrl": ".",
"paths": {
"common/*": ["../../../src/common/*"],
"browser/*": ["../../../src/browser/*"],
"public/*": ["../../../src/public/*"],
"Terminal": ["../../../src/Terminal"],
"SerializeAddon": ["../src/SerializeAddon"]
}
},
"include": ["../**/*", "../../../typings/xterm.d.ts", "../../../out/**/*"],
"exclude": ["../../../**/*test.ts", "../../**/*api.ts"],
"references": [
{ "path": "../../../src/common" },
{ "path": "../../../src/browser" }
]
}
+23
View File
@@ -0,0 +1,23 @@
{
"name": "xterm-addon-serialize",
"version": "0.2.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
},
"main": "lib/xterm-addon-serialize.js",
"types": "typings/xterm-addon-serialize.d.ts",
"license": "MIT",
"scripts": {
"build": "../../node_modules/.bin/tsc -p src",
"prepackage": "npm run build",
"package": "../../node_modules/.bin/webpack",
"prepublishOnly": "npm run package",
"benchmark": "NODE_PATH=../../out:./out:./out-benchmark/ ../../node_modules/.bin/xterm-benchmark -r 5 -c benchmark/benchmark.json",
"benchmark-baseline": "NODE_PATH=../../out:./out:./out-benchmark/ ../../node_modules/.bin/xterm-benchmark -r 5 -c benchmark/benchmark.json --baseline out-benchmark/addons/xterm-addon-serialize/benchmark/*benchmark.js",
"benchmark-eval": "NODE_PATH=../../out:./out:./out-benchmark/ ../../node_modules/.bin/xterm-benchmark -r 5 -c benchmark/benchmark.json --eval out-benchmark/addons/xterm-addon-serialize/benchmark/*benchmark.js"
},
"peerDependencies": {
"xterm": "^4.0.0"
}
}
@@ -0,0 +1,340 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { assert } from 'chai';
import { openTerminal, writeSync, getBrowserType } from '../../../out-test/api/TestUtils';
import { Browser, Page } from 'playwright-core';
const APP = 'http://127.0.0.1:3000/test';
let browser: Browser;
let page: Page;
const width = 800;
const height = 600;
describe('SerializeAddon', () => {
before(async function(): Promise<any> {
const browserType = getBrowserType();
browser = await browserType.launch({ dumpio: true,
headless: process.argv.indexOf('--headless') !== -1
});
page = await (await browser.newContext()).newPage();
await page.setViewportSize({ width, height });
await page.goto(APP);
await openTerminal(page, { rows: 10, cols: 10, rendererType: 'dom' });
await page.evaluate(`
window.serializeAddon = new SerializeAddon();
window.term.loadAddon(window.serializeAddon);
`);
});
after(async () => await browser.close());
beforeEach(async () => await page.evaluate(`window.term.reset()`));
it('empty content', async function(): Promise<any> {
const rows = 10;
const cols = 10;
assert.equal(await page.evaluate(`serializeAddon.serialize();`), '');
});
it('trim last empty lines', async function(): Promise<any> {
const cols = 10;
const lines = [
'',
'',
digitsString(cols),
digitsString(cols),
'',
'',
digitsString(cols),
digitsString(cols),
'',
'',
''
];
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.slice(0, 8).join('\r\n'));
});
it('digits content', async function(): Promise<any> {
const rows = 10;
const cols = 10;
const digitsLine = digitsString(cols);
const lines = newArray<string>(digitsLine, rows);
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n'));
});
it('serialize half rows of content', async function(): Promise<any> {
const rows = 10;
const halfRows = rows >> 1;
const cols = 10;
const lines = newArray<string>((index: number) => digitsString(cols, index), rows);
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize(${halfRows});`), lines.slice(halfRows, 2 * halfRows).join('\r\n'));
});
it('serialize 0 rows of content', async function(): Promise<any> {
const rows = 10;
const cols = 10;
const lines = newArray<string>((index: number) => digitsString(cols, index), rows);
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize(0);`), '');
});
it('serialize all rows of content with color16', async function(): Promise<any> {
const cols = 10;
const color16 = [
30, 31, 32, 33, 34, 35, 36, 37, // Set foreground color
90, 91, 92, 93, 94, 95, 96, 97,
40, 41, 42, 43, 44, 45, 46, 47, // Set background color
100, 101, 103, 104, 105, 106, 107
];
const rows = color16.length;
const lines = newArray<string>(
(index: number) => digitsString(cols, index, `\x1b[${color16[index % color16.length]}m`),
rows
);
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n'));
});
it('serialize all rows of content with fg/bg flags', async function(): Promise<any> {
const cols = 10;
const line = '+'.repeat(cols);
const lines: string[] = [
mkSGR(FG_P16_GREEN) + line, // Workaround: If we clear all flags a the end, serialize will use \x1b[0m to clear instead of the sepcific disable sequence
mkSGR(INVERSE) + line,
mkSGR(BOLD) + line,
mkSGR(UNDERLINED) + line,
mkSGR(BLINK) + line,
mkSGR(INVISIBLE) + line,
mkSGR(NO_INVERSE) + line,
mkSGR(NO_BOLD) + line,
mkSGR(NO_UNDERLINED) + line,
mkSGR(NO_BLINK) + line,
mkSGR(NO_INVISIBLE) + line
];
const rows = lines.length;
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n'));
});
it('serialize all rows of content with color256', async function(): Promise<any> {
const rows = 32;
const cols = 10;
const lines = newArray<string>(
(index: number) => digitsString(cols, index, `\x1b[38;5;${16 + index}m`),
rows
);
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n'));
});
it('serialize all rows of content with color16 and style separately', async function(): Promise<any> {
const cols = 10;
const line = '+'.repeat(cols);
const lines: string[] = [
mkSGR(FG_P16_RED) + line, // fg Red,
mkSGR(UNDERLINED) + line, // fg Red, Underlined
mkSGR(FG_P16_GREEN) + line, // fg Green, Underlined
mkSGR(INVERSE) + line, // fg Green, Underlined, Inverse
mkSGR(NO_INVERSE) + line, // fg Green, Underlined
mkSGR(INVERSE) + line, // fg Green, Underlined, Inverse
mkSGR(BG_P16_YELLOW) + line, // fg Green, bg Yellow, Underlined, Inverse
mkSGR(FG_RESET) + line, // bg Yellow, Underlined, Inverse
mkSGR(BG_RESET) + line, // Underlined, Inverse
mkSGR(NORMAL) + line // Back to normal
];
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n'));
});
it('serialize all rows of content with color16 and style together', async function(): Promise<any> {
const cols = 10;
const line = '+'.repeat(cols);
const lines: string[] = [
mkSGR(FG_P16_RED) + line, // fg Red
mkSGR(FG_P16_GREEN, BG_P16_YELLOW) + line, // fg Green, bg Yellow
mkSGR(UNDERLINED, ITALIC) + line, // fg Green, bg Yellow, Underlined, Italic
mkSGR(NO_UNDERLINED, NO_ITALIC) + line, // fg Green, bg Yellow
mkSGR(FG_RESET, ITALIC) + line, // bg Yellow, Italic
mkSGR(BG_RESET) + line, // Italic
mkSGR(NORMAL) + line, // Back to normal
mkSGR(FG_P16_RED) + line, // fg Red
mkSGR(FG_P16_GREEN, BG_P16_YELLOW) + line, // fg Green, bg Yellow
mkSGR(UNDERLINED, ITALIC) + line, // fg Green, bg Yellow, Underlined, Italic
mkSGR(NO_UNDERLINED, NO_ITALIC) + line, // fg Green, bg Yellow
mkSGR(FG_RESET, ITALIC) + line, // bg Yellow, Italic
mkSGR(BG_RESET) + line // Italic
];
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n'));
});
it('serialize all rows of content with color256 and style separately', async function(): Promise<any> {
const cols = 10;
const line = '+'.repeat(cols);
const lines: string[] = [
mkSGR(FG_P256_RED) + line, // fg Red 256,
mkSGR(UNDERLINED) + line, // fg Red 256, Underlined
mkSGR(FG_P256_GREEN) + line, // fg Green 256, Underlined
mkSGR(INVERSE) + line, // fg Green 256, Underlined, Inverse
mkSGR(NO_INVERSE) + line, // fg Green 256, Underlined
mkSGR(INVERSE) + line, // fg Green 256, Underlined, Inverse
mkSGR(BG_P256_YELLOW) + line, // fg Green 256, bg Yellow 256, Underlined, Inverse
mkSGR(FG_RESET) + line, // bg Yellow 256, Underlined, Inverse
mkSGR(BG_RESET) + line, // Underlined, Inverse
mkSGR(NORMAL) + line // Back to normal
];
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n'));
});
it('serialize all rows of content with color256 and style together', async function(): Promise<any> {
const cols = 10;
const line = '+'.repeat(cols);
const lines: string[] = [
mkSGR(FG_P256_RED) + line, // fg Red 256
mkSGR(FG_P256_GREEN, BG_P256_YELLOW) + line, // fg Green 256, bg Yellow 256
mkSGR(UNDERLINED, ITALIC) + line, // fg Green 256, bg Yellow 256, Underlined, Italic
mkSGR(NO_UNDERLINED, NO_ITALIC) + line, // fg Green 256, bg Yellow 256
mkSGR(FG_RESET, ITALIC) + line, // bg Yellow 256, Italic
mkSGR(BG_RESET) + line, // Italic
mkSGR(NORMAL) + line, // Back to normal
mkSGR(FG_P256_RED) + line, // fg Red 256
mkSGR(FG_P256_GREEN, BG_P256_YELLOW) + line, // fg Green 256, bg Yellow 256
mkSGR(UNDERLINED, ITALIC) + line, // fg Green 256, bg Yellow 256, Underlined, Italic
mkSGR(NO_UNDERLINED, NO_ITALIC) + line, // fg Green 256, bg Yellow 256
mkSGR(FG_RESET, ITALIC) + line, // bg Yellow 256, Italic
mkSGR(BG_RESET) + line // Italic
];
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n'));
});
it('serialize all rows of content with colorRGB and style separately', async function(): Promise<any> {
const cols = 10;
const line = '+'.repeat(cols);
const lines: string[] = [
mkSGR(FG_RGB_RED) + line, // fg Red RGB,
mkSGR(UNDERLINED) + line, // fg Red RGB, Underlined
mkSGR(FG_RGB_GREEN) + line, // fg Green RGB, Underlined
mkSGR(INVERSE) + line, // fg Green RGB, Underlined, Inverse
mkSGR(NO_INVERSE) + line, // fg Green RGB, Underlined
mkSGR(INVERSE) + line, // fg Green RGB, Underlined, Inverse
mkSGR(BG_RGB_YELLOW) + line, // fg Green RGB, bg Yellow RGB, Underlined, Inverse
mkSGR(FG_RESET) + line, // bg Yellow RGB, Underlined, Inverse
mkSGR(BG_RESET) + line, // Underlined, Inverse
mkSGR(NORMAL) + line // Back to normal
];
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n'));
});
it('serialize all rows of content with colorRGB and style together', async function(): Promise<any> {
const cols = 10;
const line = '+'.repeat(cols);
const lines: string[] = [
mkSGR(FG_RGB_RED) + line, // fg Red RGB
mkSGR(FG_RGB_GREEN, BG_RGB_YELLOW) + line, // fg Green RGB, bg Yellow RGB
mkSGR(UNDERLINED, ITALIC) + line, // fg Green RGB, bg Yellow RGB, Underlined, Italic
mkSGR(NO_UNDERLINED, NO_ITALIC) + line, // fg Green RGB, bg Yellow RGB
mkSGR(FG_RESET, ITALIC) + line, // bg Yellow RGB, Italic
mkSGR(BG_RESET) + line, // Italic
mkSGR(NORMAL) + line, // Back to normal
mkSGR(FG_RGB_RED) + line, // fg Red RGB
mkSGR(FG_RGB_GREEN, BG_RGB_YELLOW) + line, // fg Green RGB, bg Yellow RGB
mkSGR(UNDERLINED, ITALIC) + line, // fg Green RGB, bg Yellow RGB, Underlined, Italic
mkSGR(NO_UNDERLINED, NO_ITALIC) + line, // fg Green RGB, bg Yellow RGB
mkSGR(FG_RESET, ITALIC) + line, // bg Yellow RGB, Italic
mkSGR(BG_RESET) + line // Italic
];
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n'));
});
it('serialize tabs correctly', async () => {
const lines = [
'a\tb',
'aa\tc',
'aaa\td'
];
const expected = [
'a\x1b[7Cb',
'aa\x1b[6Cc',
'aaa\x1b[5Cd'
];
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), expected.join('\r\n'));
});
});
function newArray<T>(initial: T | ((index: number) => T), count: number): T[] {
const array: T[] = new Array<T>(count);
for (let i = 0; i < array.length; i++) {
if (typeof initial === 'function') {
array[i] = (<(index: number) => T>initial)(i);
} else {
array[i] = <T>initial;
}
}
return array;
}
function digitsString(length: number, from: number = 0, sgr: string = ''): string {
let s = sgr;
for (let i = 0; i < length; i++) {
s += `${(from++) % 10}`;
}
return s;
}
function mkSGR(...seq: string[]): string {
return `\x1b[${seq.join(';')}m`;
}
const NORMAL = '0';
const FG_P16_RED = '31';
const FG_P16_GREEN = '32';
const FG_P16_YELLOW = '33';
const FG_P256_RED = '38;5;196';
const FG_P256_GREEN = '38;5;46';
const FG_P256_YELLOW = '38;5;226';
const FG_RGB_RED = '38;2;255;0;0';
const FG_RGB_GREEN = '38;2;0;255;0';
const FG_RGB_YELLOW = '38;2;255;255;0';
const FG_RESET = '39';
const BG_P16_RED = '41';
const BG_P16_GREEN = '42';
const BG_P16_YELLOW = '43';
const BG_P256_RED = '48;5;196';
const BG_P256_GREEN = '48;5;46';
const BG_P256_YELLOW = '48;5;226';
const BG_RGB_RED = '48;2;255;0;0';
const BG_RGB_GREEN = '48;2;0;255;0';
const BG_RGB_YELLOW = '48;2;255;255;0';
const BG_RESET = '49';
const INVERSE = '7';
const BOLD = '1';
const UNDERLINED = '4';
const BLINK = '5';
const INVISIBLE = '8';
const NO_INVERSE = '27';
const NO_BOLD = '22';
const NO_UNDERLINED = '24';
const NO_BLINK = '25';
const NO_INVISIBLE = '28';
const ITALIC = '3';
const DIM = '2';
const NO_ITALIC = '23';
const NO_DIM = '22';
@@ -0,0 +1,187 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*
* (EXPERIMENTAL) This Addon is still under development
*/
import { Terminal, ITerminalAddon, IBuffer, IBufferCell } from 'xterm';
function constrain(value: number, low: number, high: number): number {
return Math.max(low, Math.min(value, high));
}
// TODO: Refine this template class later
abstract class BaseSerializeHandler {
constructor(private _buffer: IBuffer) { }
serialize(startRow: number, endRow: number): string {
// we need two of them to flip between old and new cell
const cell1 = this._buffer.getNullCell();
const cell2 = this._buffer.getNullCell();
let oldCell = cell1;
this._beforeSerialize(endRow - startRow);
for (let row = startRow; row < endRow; row++) {
const line = this._buffer.getLine(row);
if (line) {
for (let col = 0; col < line.length; col++) {
const c = line.getCell(col, oldCell === cell1 ? cell2 : cell1);
if (!c) {
console.warn(`Can't get cell at row=${row}, col=${col}`);
continue;
}
this._nextCell(c, oldCell, row, col);
oldCell = c;
}
}
this._rowEnd(row);
}
this._afterSerialize();
return this._serializeString();
}
protected _nextCell(cell: IBufferCell, oldCell: IBufferCell, row: number, col: number): void { }
protected _rowEnd(row: number): void { }
protected _beforeSerialize(rows: number): void { }
protected _afterSerialize(): void { }
protected _serializeString(): string { return ''; }
}
function equalFg(cell1: IBufferCell, cell2: IBufferCell): boolean {
return cell1.getFgColorMode() === cell2.getFgColorMode()
&& cell1.getFgColor() === cell2.getFgColor();
}
function equalBg(cell1: IBufferCell, cell2: IBufferCell): boolean {
return cell1.getBgColorMode() === cell2.getBgColorMode()
&& cell1.getBgColor() === cell2.getBgColor();
}
function equalFlags(cell1: IBufferCell, cell2: IBufferCell): boolean {
return cell1.isInverse() === cell2.isInverse()
&& cell1.isBold() === cell2.isBold()
&& cell1.isUnderline() === cell2.isUnderline()
&& cell1.isBlink() === cell2.isBlink()
&& cell1.isInvisible() === cell2.isInvisible()
&& cell1.isItalic() === cell2.isItalic()
&& cell1.isDim() === cell2.isDim();
}
class StringSerializeHandler extends BaseSerializeHandler {
private _rowIndex: number = 0;
private _allRows: string[] = new Array<string>();
private _currentRow: string = '';
private _nullCellCount: number = 0;
constructor(buffer: IBuffer) {
super(buffer);
}
protected _beforeSerialize(rows: number): void {
this._allRows = new Array<string>(rows);
}
protected _rowEnd(row: number): void {
this._allRows[this._rowIndex++] = this._currentRow;
this._currentRow = '';
this._nullCellCount = 0;
}
protected _nextCell(cell: IBufferCell, oldCell: IBufferCell, row: number, col: number): void {
const sgrSeq: number[] = [];
const fgChanged = !equalFg(cell, oldCell);
const bgChanged = !equalBg(cell, oldCell);
const flagsChanged = !equalFlags(cell, oldCell);
if (fgChanged || bgChanged || flagsChanged) {
if (cell.isAttributeDefault()) {
this._currentRow += '\x1b[0m';
} else {
if (fgChanged) {
const color = cell.getFgColor();
if (cell.isFgRGB()) { sgrSeq.push(38, 2, (color >>> 16) & 0xFF, (color >>> 8) & 0xFF, color & 0xFF); }
else if (cell.isFgPalette()) {
if (color >= 16) { sgrSeq.push(38, 5, color); }
else { sgrSeq.push(color & 8 ? 90 + (color & 7) : 30 + (color & 7)); }
}
else { sgrSeq.push(39); }
}
if (bgChanged) {
const color = cell.getBgColor();
if (cell.isBgRGB()) { sgrSeq.push(48, 2, (color >>> 16) & 0xFF, (color >>> 8) & 0xFF, color & 0xFF); }
else if (cell.isBgPalette()) {
if (color >= 16) { sgrSeq.push(48, 5, color); }
else { sgrSeq.push(color & 8 ? 100 + (color & 7) : 40 + (color & 7)); }
}
else { sgrSeq.push(49); }
}
if (flagsChanged) {
if (cell.isInverse() !== oldCell.isInverse()) { sgrSeq.push(cell.isInverse() ? 7 : 27); }
if (cell.isBold() !== oldCell.isBold()) { sgrSeq.push(cell.isBold() ? 1 : 22); }
if (cell.isUnderline() !== oldCell.isUnderline()) { sgrSeq.push(cell.isUnderline() ? 4 : 24); }
if (cell.isBlink() !== oldCell.isBlink()) { sgrSeq.push(cell.isBlink() ? 5 : 25); }
if (cell.isInvisible() !== oldCell.isInvisible()) { sgrSeq.push(cell.isInvisible() ? 8 : 28); }
if (cell.isItalic() !== oldCell.isItalic()) { sgrSeq.push(cell.isItalic() ? 3 : 23); }
if (cell.isDim() !== oldCell.isDim()) { sgrSeq.push(cell.isDim() ? 2 : 22); }
}
}
}
if (sgrSeq.length) {
this._currentRow += `\x1b[${sgrSeq.join(';')}m`;
}
// Count number of null cells encountered after the last non-null cell and move the cursor
// if a non-null cell is found (eg. \t or cursor move)
if (cell.getChars() === '') {
this._nullCellCount++;
} else if (this._nullCellCount > 0) {
this._currentRow += `\x1b[${this._nullCellCount}C`;
this._nullCellCount = 0;
}
this._currentRow += cell.getChars();
}
protected _serializeString(): string {
let rowEnd = this._allRows.length;
for (; rowEnd > 0; rowEnd--) {
if (this._allRows[rowEnd - 1]) {
break;
}
}
return this._allRows.slice(0, rowEnd).join('\r\n');
}
}
export class SerializeAddon implements ITerminalAddon {
private _terminal: Terminal | undefined;
constructor() { }
public activate(terminal: Terminal): void {
this._terminal = terminal;
}
public serialize(rows?: number): string {
// TODO: Add re-position cursor support
// TODO: Add word wrap mode support
// TODO: Add combinedData support
if (!this._terminal) {
throw new Error('Cannot use addon until it has been loaded');
}
const maxRows = this._terminal.buffer.active.length;
const handler = new StringSerializeHandler(this._terminal.buffer.active);
rows = (rows === undefined) ? maxRows : constrain(rows, 0, maxRows);
return handler.serialize(maxRows - rows, maxRows);
}
public dispose(): void { }
}
@@ -0,0 +1,34 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": [
"dom",
"es2015"
],
"rootDir": ".",
"outDir": "../out",
"sourceMap": true,
"removeComments": true,
"baseUrl": ".",
"paths": {
"common/*": [
"../../../src/common/*"
]
},
"strict": true,
"types": [
"../../../node_modules/@types/mocha",
"../../../out-test/api/TestUtils"
]
},
"include": [
"./**/*",
"../../../typings/xterm.d.ts"
],
"references": [
{
"path": "../../../src/common"
}
]
}
@@ -0,0 +1,38 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { Terminal, ITerminalAddon } from 'xterm';
declare module 'xterm-addon-serialize' {
/**
* An xterm.js addon that enables web links.
*/
export class SerializeAddon implements ITerminalAddon {
constructor();
/**
* Activates the addon
* @param terminal The terminal the addon is being loaded in.
*/
public activate(terminal: Terminal): void;
/**
* Serializes terminal rows into a string that can be written back to the terminal
* to restore 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 incomplete frames.
* @param rows The number of rows to serialize, starting from the bottom of the
* terminal. This defaults to the number of rows in the viewport.
*/
public serialize(rows?: number): string;
/**
* Disposes the addon.
*/
public dispose(): void;
}
}
@@ -0,0 +1,31 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
const path = require('path');
const addonName = 'SerializeAddon';
const mainFile = 'xterm-addon-serialize.js';
module.exports = {
entry: `./out/${addonName}.js`,
devtool: 'source-map',
module: {
rules: [
{
test: /\.js$/,
use: ["source-map-loader"],
enforce: "pre",
exclude: /node_modules/
}
]
},
output: {
filename: mainFile,
path: path.resolve('./lib'),
library: addonName,
libraryTarget: 'umd'
},
mode: 'production'
};
+2
View File
@@ -0,0 +1,2 @@
lib
node_modules
+5
View File
@@ -0,0 +1,5 @@
**/*.api.js
**/*.api.ts
tsconfig.json
.yarnrc
webpack.config.js
+19
View File
@@ -0,0 +1,19 @@
Copyright (c) 2019, The xterm.js authors (https://github.com/xtermjs/xterm.js)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+23
View File
@@ -0,0 +1,23 @@
## xterm-addon-unicode11
An addon providing Unicode version 11 rules for xterm.js.
### Install
```bash
npm install --save xterm-addon-unicode11
```
### Usage
```ts
import { Terminal } from 'xterm';
import { Unicode11Addon } from 'xterm-addon-unicode11';
const terminal = new Terminal();
const unicode11Addon = new Unicode11Addon();
terminal.loadAddon(unicode11Addon);
// activate the new version
terminal.unicode.activeVersion = '11';
```
+21
View File
@@ -0,0 +1,21 @@
{
"name": "xterm-addon-unicode11",
"version": "0.1.1",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
},
"main": "lib/xterm-addon-unicode11.js",
"types": "typings/xterm-addon-unicode11.d.ts",
"repository": "https://github.com/xtermjs/xterm.js",
"license": "MIT",
"scripts": {
"build": "../../node_modules/.bin/tsc -p src",
"prepackage": "npm run build",
"package": "../../node_modules/.bin/webpack",
"prepublishOnly": "npm run package"
},
"peerDependencies": {
"xterm": "^4.0.0"
}
}
@@ -0,0 +1,49 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { assert } from 'chai';
import { openTerminal, getBrowserType } from '../../../out-test/api/TestUtils';
import { Browser, Page } from 'playwright-core';
const APP = 'http://127.0.0.1:3000/test';
let browser: Browser;
let page: Page;
const width = 800;
const height = 600;
describe('Unicode11Addon', () => {
before(async function(): Promise<any> {
const browserType = getBrowserType();
browser = await browserType.launch({ dumpio: true,
headless: process.argv.indexOf('--headless') !== -1
});
page = await (await browser.newContext()).newPage();
await page.setViewportSize({ width, height });
});
after(async () => {
await browser.close();
});
beforeEach(async function(): Promise<any> {
await page.goto(APP);
await openTerminal(page);
});
it('wcwidth V11 emoji test', async () => {
await page.evaluate(`
window.unicode11 = new Unicode11Addon();
window.term.loadAddon(window.unicode11);
`);
// should have loaded '11'
assert.deepEqual(await page.evaluate(`window.term.unicode.versions`), ['6', '11']);
// switch should not throw
await page.evaluate(`window.term.unicode.activeVersion = '11';`);
assert.deepEqual(await page.evaluate(`window.term.unicode.activeVersion`), '11');
// v6: 10, V11: 20
assert.deepEqual(await page.evaluate(`window.term._core.unicodeService.getStringCellWidth('🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣')`), 20);
});
});
@@ -0,0 +1,16 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*
* UnicodeVersionProvider for V11.
*/
import { Terminal, ITerminalAddon } from 'xterm';
import { UnicodeV11 } from './UnicodeV11';
export class Unicode11Addon implements ITerminalAddon {
public activate(terminal: Terminal): void {
terminal.unicode.register(new UnicodeV11());
}
public dispose(): void { }
}
@@ -0,0 +1,222 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { IUnicodeVersionProvider } from 'xterm';
import { fill } from 'common/TypedArrayUtils';
type CharWidth = 0 | 1 | 2;
const BMP_COMBINING = [
[0x0300, 0x036F], [0x0483, 0x0489], [0x0591, 0x05BD],
[0x05BF, 0x05BF], [0x05C1, 0x05C2], [0x05C4, 0x05C5],
[0x05C7, 0x05C7], [0x0600, 0x0605], [0x0610, 0x061A],
[0x061C, 0x061C], [0x064B, 0x065F], [0x0670, 0x0670],
[0x06D6, 0x06DD], [0x06DF, 0x06E4], [0x06E7, 0x06E8],
[0x06EA, 0x06ED], [0x070F, 0x070F], [0x0711, 0x0711],
[0x0730, 0x074A], [0x07A6, 0x07B0], [0x07EB, 0x07F3],
[0x07FD, 0x07FD], [0x0816, 0x0819], [0x081B, 0x0823],
[0x0825, 0x0827], [0x0829, 0x082D], [0x0859, 0x085B],
[0x08D3, 0x0902], [0x093A, 0x093A], [0x093C, 0x093C],
[0x0941, 0x0948], [0x094D, 0x094D], [0x0951, 0x0957],
[0x0962, 0x0963], [0x0981, 0x0981], [0x09BC, 0x09BC],
[0x09C1, 0x09C4], [0x09CD, 0x09CD], [0x09E2, 0x09E3],
[0x09FE, 0x09FE], [0x0A01, 0x0A02], [0x0A3C, 0x0A3C],
[0x0A41, 0x0A42], [0x0A47, 0x0A48], [0x0A4B, 0x0A4D],
[0x0A51, 0x0A51], [0x0A70, 0x0A71], [0x0A75, 0x0A75],
[0x0A81, 0x0A82], [0x0ABC, 0x0ABC], [0x0AC1, 0x0AC5],
[0x0AC7, 0x0AC8], [0x0ACD, 0x0ACD], [0x0AE2, 0x0AE3],
[0x0AFA, 0x0AFF], [0x0B01, 0x0B01], [0x0B3C, 0x0B3C],
[0x0B3F, 0x0B3F], [0x0B41, 0x0B44], [0x0B4D, 0x0B4D],
[0x0B56, 0x0B56], [0x0B62, 0x0B63], [0x0B82, 0x0B82],
[0x0BC0, 0x0BC0], [0x0BCD, 0x0BCD], [0x0C00, 0x0C00],
[0x0C04, 0x0C04], [0x0C3E, 0x0C40], [0x0C46, 0x0C48],
[0x0C4A, 0x0C4D], [0x0C55, 0x0C56], [0x0C62, 0x0C63],
[0x0C81, 0x0C81], [0x0CBC, 0x0CBC], [0x0CBF, 0x0CBF],
[0x0CC6, 0x0CC6], [0x0CCC, 0x0CCD], [0x0CE2, 0x0CE3],
[0x0D00, 0x0D01], [0x0D3B, 0x0D3C], [0x0D41, 0x0D44],
[0x0D4D, 0x0D4D], [0x0D62, 0x0D63], [0x0DCA, 0x0DCA],
[0x0DD2, 0x0DD4], [0x0DD6, 0x0DD6], [0x0E31, 0x0E31],
[0x0E34, 0x0E3A], [0x0E47, 0x0E4E], [0x0EB1, 0x0EB1],
[0x0EB4, 0x0EBC], [0x0EC8, 0x0ECD], [0x0F18, 0x0F19],
[0x0F35, 0x0F35], [0x0F37, 0x0F37], [0x0F39, 0x0F39],
[0x0F71, 0x0F7E], [0x0F80, 0x0F84], [0x0F86, 0x0F87],
[0x0F8D, 0x0F97], [0x0F99, 0x0FBC], [0x0FC6, 0x0FC6],
[0x102D, 0x1030], [0x1032, 0x1037], [0x1039, 0x103A],
[0x103D, 0x103E], [0x1058, 0x1059], [0x105E, 0x1060],
[0x1071, 0x1074], [0x1082, 0x1082], [0x1085, 0x1086],
[0x108D, 0x108D], [0x109D, 0x109D], [0x1160, 0x11FF],
[0x135D, 0x135F], [0x1712, 0x1714], [0x1732, 0x1734],
[0x1752, 0x1753], [0x1772, 0x1773], [0x17B4, 0x17B5],
[0x17B7, 0x17BD], [0x17C6, 0x17C6], [0x17C9, 0x17D3],
[0x17DD, 0x17DD], [0x180B, 0x180E], [0x1885, 0x1886],
[0x18A9, 0x18A9], [0x1920, 0x1922], [0x1927, 0x1928],
[0x1932, 0x1932], [0x1939, 0x193B], [0x1A17, 0x1A18],
[0x1A1B, 0x1A1B], [0x1A56, 0x1A56], [0x1A58, 0x1A5E],
[0x1A60, 0x1A60], [0x1A62, 0x1A62], [0x1A65, 0x1A6C],
[0x1A73, 0x1A7C], [0x1A7F, 0x1A7F], [0x1AB0, 0x1ABE],
[0x1B00, 0x1B03], [0x1B34, 0x1B34], [0x1B36, 0x1B3A],
[0x1B3C, 0x1B3C], [0x1B42, 0x1B42], [0x1B6B, 0x1B73],
[0x1B80, 0x1B81], [0x1BA2, 0x1BA5], [0x1BA8, 0x1BA9],
[0x1BAB, 0x1BAD], [0x1BE6, 0x1BE6], [0x1BE8, 0x1BE9],
[0x1BED, 0x1BED], [0x1BEF, 0x1BF1], [0x1C2C, 0x1C33],
[0x1C36, 0x1C37], [0x1CD0, 0x1CD2], [0x1CD4, 0x1CE0],
[0x1CE2, 0x1CE8], [0x1CED, 0x1CED], [0x1CF4, 0x1CF4],
[0x1CF8, 0x1CF9], [0x1DC0, 0x1DF9], [0x1DFB, 0x1DFF],
[0x200B, 0x200F], [0x202A, 0x202E], [0x2060, 0x2064],
[0x2066, 0x206F], [0x20D0, 0x20F0], [0x2CEF, 0x2CF1],
[0x2D7F, 0x2D7F], [0x2DE0, 0x2DFF], [0x302A, 0x302D],
[0x3099, 0x309A], [0xA66F, 0xA672], [0xA674, 0xA67D],
[0xA69E, 0xA69F], [0xA6F0, 0xA6F1], [0xA802, 0xA802],
[0xA806, 0xA806], [0xA80B, 0xA80B], [0xA825, 0xA826],
[0xA8C4, 0xA8C5], [0xA8E0, 0xA8F1], [0xA8FF, 0xA8FF],
[0xA926, 0xA92D], [0xA947, 0xA951], [0xA980, 0xA982],
[0xA9B3, 0xA9B3], [0xA9B6, 0xA9B9], [0xA9BC, 0xA9BD],
[0xA9E5, 0xA9E5], [0xAA29, 0xAA2E], [0xAA31, 0xAA32],
[0xAA35, 0xAA36], [0xAA43, 0xAA43], [0xAA4C, 0xAA4C],
[0xAA7C, 0xAA7C], [0xAAB0, 0xAAB0], [0xAAB2, 0xAAB4],
[0xAAB7, 0xAAB8], [0xAABE, 0xAABF], [0xAAC1, 0xAAC1],
[0xAAEC, 0xAAED], [0xAAF6, 0xAAF6], [0xABE5, 0xABE5],
[0xABE8, 0xABE8], [0xABED, 0xABED], [0xFB1E, 0xFB1E],
[0xFE00, 0xFE0F], [0xFE20, 0xFE2F], [0xFEFF, 0xFEFF],
[0xFFF9, 0xFFFB]
];
const HIGH_COMBINING = [
[0x101FD, 0x101FD], [0x102E0, 0x102E0],
[0x10376, 0x1037A], [0x10A01, 0x10A03], [0x10A05, 0x10A06],
[0x10A0C, 0x10A0F], [0x10A38, 0x10A3A], [0x10A3F, 0x10A3F],
[0x10AE5, 0x10AE6], [0x10D24, 0x10D27], [0x10F46, 0x10F50],
[0x11001, 0x11001], [0x11038, 0x11046], [0x1107F, 0x11081],
[0x110B3, 0x110B6], [0x110B9, 0x110BA], [0x110BD, 0x110BD],
[0x110CD, 0x110CD], [0x11100, 0x11102], [0x11127, 0x1112B],
[0x1112D, 0x11134], [0x11173, 0x11173], [0x11180, 0x11181],
[0x111B6, 0x111BE], [0x111C9, 0x111CC], [0x1122F, 0x11231],
[0x11234, 0x11234], [0x11236, 0x11237], [0x1123E, 0x1123E],
[0x112DF, 0x112DF], [0x112E3, 0x112EA], [0x11300, 0x11301],
[0x1133B, 0x1133C], [0x11340, 0x11340], [0x11366, 0x1136C],
[0x11370, 0x11374], [0x11438, 0x1143F], [0x11442, 0x11444],
[0x11446, 0x11446], [0x1145E, 0x1145E], [0x114B3, 0x114B8],
[0x114BA, 0x114BA], [0x114BF, 0x114C0], [0x114C2, 0x114C3],
[0x115B2, 0x115B5], [0x115BC, 0x115BD], [0x115BF, 0x115C0],
[0x115DC, 0x115DD], [0x11633, 0x1163A], [0x1163D, 0x1163D],
[0x1163F, 0x11640], [0x116AB, 0x116AB], [0x116AD, 0x116AD],
[0x116B0, 0x116B5], [0x116B7, 0x116B7], [0x1171D, 0x1171F],
[0x11722, 0x11725], [0x11727, 0x1172B], [0x1182F, 0x11837],
[0x11839, 0x1183A], [0x119D4, 0x119D7], [0x119DA, 0x119DB],
[0x119E0, 0x119E0], [0x11A01, 0x11A0A], [0x11A33, 0x11A38],
[0x11A3B, 0x11A3E], [0x11A47, 0x11A47], [0x11A51, 0x11A56],
[0x11A59, 0x11A5B], [0x11A8A, 0x11A96], [0x11A98, 0x11A99],
[0x11C30, 0x11C36], [0x11C38, 0x11C3D], [0x11C3F, 0x11C3F],
[0x11C92, 0x11CA7], [0x11CAA, 0x11CB0], [0x11CB2, 0x11CB3],
[0x11CB5, 0x11CB6], [0x11D31, 0x11D36], [0x11D3A, 0x11D3A],
[0x11D3C, 0x11D3D], [0x11D3F, 0x11D45], [0x11D47, 0x11D47],
[0x11D90, 0x11D91], [0x11D95, 0x11D95], [0x11D97, 0x11D97],
[0x11EF3, 0x11EF4], [0x13430, 0x13438], [0x16AF0, 0x16AF4],
[0x16B30, 0x16B36], [0x16F4F, 0x16F4F], [0x16F8F, 0x16F92],
[0x1BC9D, 0x1BC9E], [0x1BCA0, 0x1BCA3], [0x1D167, 0x1D169],
[0x1D173, 0x1D182], [0x1D185, 0x1D18B], [0x1D1AA, 0x1D1AD],
[0x1D242, 0x1D244], [0x1DA00, 0x1DA36], [0x1DA3B, 0x1DA6C],
[0x1DA75, 0x1DA75], [0x1DA84, 0x1DA84], [0x1DA9B, 0x1DA9F],
[0x1DAA1, 0x1DAAF], [0x1E000, 0x1E006], [0x1E008, 0x1E018],
[0x1E01B, 0x1E021], [0x1E023, 0x1E024], [0x1E026, 0x1E02A],
[0x1E130, 0x1E136], [0x1E2EC, 0x1E2EF], [0x1E8D0, 0x1E8D6],
[0x1E944, 0x1E94A], [0xE0001, 0xE0001], [0xE0020, 0xE007F],
[0xE0100, 0xE01EF]
];
const BMP_WIDE = [
[0x1100, 0x115F], [0x231A, 0x231B], [0x2329, 0x232A],
[0x23E9, 0x23EC], [0x23F0, 0x23F0], [0x23F3, 0x23F3],
[0x25FD, 0x25FE], [0x2614, 0x2615], [0x2648, 0x2653],
[0x267F, 0x267F], [0x2693, 0x2693], [0x26A1, 0x26A1],
[0x26AA, 0x26AB], [0x26BD, 0x26BE], [0x26C4, 0x26C5],
[0x26CE, 0x26CE], [0x26D4, 0x26D4], [0x26EA, 0x26EA],
[0x26F2, 0x26F3], [0x26F5, 0x26F5], [0x26FA, 0x26FA],
[0x26FD, 0x26FD], [0x2705, 0x2705], [0x270A, 0x270B],
[0x2728, 0x2728], [0x274C, 0x274C], [0x274E, 0x274E],
[0x2753, 0x2755], [0x2757, 0x2757], [0x2795, 0x2797],
[0x27B0, 0x27B0], [0x27BF, 0x27BF], [0x2B1B, 0x2B1C],
[0x2B50, 0x2B50], [0x2B55, 0x2B55], [0x2E80, 0x2E99],
[0x2E9B, 0x2EF3], [0x2F00, 0x2FD5], [0x2FF0, 0x2FFB],
[0x3000, 0x3029], [0x302E, 0x303E], [0x3041, 0x3096],
[0x309B, 0x30FF], [0x3105, 0x312F], [0x3131, 0x318E],
[0x3190, 0x31BA], [0x31C0, 0x31E3], [0x31F0, 0x321E],
[0x3220, 0x3247], [0x3250, 0x4DBF], [0x4E00, 0xA48C],
[0xA490, 0xA4C6], [0xA960, 0xA97C], [0xAC00, 0xD7A3],
[0xF900, 0xFAFF], [0xFE10, 0xFE19], [0xFE30, 0xFE52],
[0xFE54, 0xFE66], [0xFE68, 0xFE6B], [0xFF01, 0xFF60],
[0xFFE0, 0xFFE6]
];
const HIGH_WIDE = [
[0x16FE0, 0x16FE3], [0x17000, 0x187F7],
[0x18800, 0x18AF2], [0x1B000, 0x1B11E], [0x1B150, 0x1B152],
[0x1B164, 0x1B167], [0x1B170, 0x1B2FB], [0x1F004, 0x1F004],
[0x1F0CF, 0x1F0CF], [0x1F18E, 0x1F18E], [0x1F191, 0x1F19A],
[0x1F200, 0x1F202], [0x1F210, 0x1F23B], [0x1F240, 0x1F248],
[0x1F250, 0x1F251], [0x1F260, 0x1F265], [0x1F300, 0x1F320],
[0x1F32D, 0x1F335], [0x1F337, 0x1F37C], [0x1F37E, 0x1F393],
[0x1F3A0, 0x1F3CA], [0x1F3CF, 0x1F3D3], [0x1F3E0, 0x1F3F0],
[0x1F3F4, 0x1F3F4], [0x1F3F8, 0x1F43E], [0x1F440, 0x1F440],
[0x1F442, 0x1F4FC], [0x1F4FF, 0x1F53D], [0x1F54B, 0x1F54E],
[0x1F550, 0x1F567], [0x1F57A, 0x1F57A], [0x1F595, 0x1F596],
[0x1F5A4, 0x1F5A4], [0x1F5FB, 0x1F64F], [0x1F680, 0x1F6C5],
[0x1F6CC, 0x1F6CC], [0x1F6D0, 0x1F6D2], [0x1F6D5, 0x1F6D5],
[0x1F6EB, 0x1F6EC], [0x1F6F4, 0x1F6FA], [0x1F7E0, 0x1F7EB],
[0x1F90D, 0x1F971], [0x1F973, 0x1F976], [0x1F97A, 0x1F9A2],
[0x1F9A5, 0x1F9AA], [0x1F9AE, 0x1F9CA], [0x1F9CD, 0x1F9FF],
[0x1FA70, 0x1FA73], [0x1FA78, 0x1FA7A], [0x1FA80, 0x1FA82],
[0x1FA90, 0x1FA95], [0x20000, 0x2FFFD], [0x30000, 0x3FFFD]
];
// BMP lookup table, lazy initialized during first addon loading
let table: Uint8Array;
function bisearch(ucs: number, data: number[][]): boolean {
let min = 0;
let max = data.length - 1;
let mid;
if (ucs < data[0][0] || ucs > data[max][1]) {
return false;
}
while (max >= min) {
mid = (min + max) >> 1;
if (ucs > data[mid][1]) {
min = mid + 1;
} else if (ucs < data[mid][0]) {
max = mid - 1;
} else {
return true;
}
}
return false;
}
export class UnicodeV11 implements IUnicodeVersionProvider {
public readonly version = '11';
constructor() {
if (!table) {
table = new Uint8Array(65536);
fill(table, 1);
table[0] = 0;
fill(table, 0, 1, 32);
fill(table, 0, 0x7f, 0xa0);
for (let r = 0; r < BMP_COMBINING.length; ++r) {
fill(table, 0, BMP_COMBINING[r][0], BMP_COMBINING[r][1] + 1);
}
for (let r = 0; r < BMP_WIDE.length; ++r) {
fill(table, 2, BMP_WIDE[r][0], BMP_WIDE[r][1] + 1);
}
}
}
public wcwidth(num: number): CharWidth {
if (num < 32) return 0;
if (num < 127) return 1;
if (num < 65536) return table[num] as CharWidth;
if (bisearch(num, HIGH_COMBINING)) return 0;
if (bisearch(num, HIGH_WIDE)) return 2;
return 1;
}
}
@@ -0,0 +1,34 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es2015",
"lib": [
"dom",
"es2015"
],
"rootDir": ".",
"outDir": "../out",
"sourceMap": true,
"removeComments": true,
"strict": true,
"baseUrl": ".",
"paths": {
"common/*": [
"../../../src/common/*"
]
},
"types": [
"../../../node_modules/@types/mocha",
"../../../out-test/api/TestUtils"
]
},
"include": [
"./**/*",
"../../../typings/xterm.d.ts"
],
"references": [
{
"path": "../../../src/common"
}
]
}
@@ -0,0 +1,14 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { Terminal, ITerminalAddon } from 'xterm';
declare module 'xterm-addon-unicode11' {
export class Unicode11Addon implements ITerminalAddon {
constructor();
public activate(terminal: Terminal): void;
public dispose(): void;
}
}
@@ -0,0 +1,38 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
const path = require('path');
const addonName = 'Unicode11Addon';
const mainFile = 'xterm-addon-unicode11.js';
module.exports = {
entry: `./out/${addonName}.js`,
devtool: 'source-map',
module: {
rules: [
{
test: /\.js$/,
use: ["source-map-loader"],
enforce: "pre",
exclude: /node_modules/
}
]
},
resolve: {
modules: ['./node_modules'],
extensions: [ '.js' ],
alias: {
common: path.resolve('../../out/common')
}
},
output: {
filename: mainFile,
path: path.resolve('./lib'),
library: addonName,
libraryTarget: 'umd'
},
mode: 'production'
};
+2
View File
@@ -0,0 +1,2 @@
lib
node_modules
+5
View File
@@ -0,0 +1,5 @@
**/*.api.js
**/*.api.ts
tsconfig.json
.yarnrc
webpack.config.js
+19
View File
@@ -0,0 +1,19 @@
Copyright (c) 2017, The xterm.js authors (https://github.com/xtermjs/xterm.js)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+21
View File
@@ -0,0 +1,21 @@
## xterm-addon-web-links
An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables web links. This addon requires xterm.js v4+.
### Install
```bash
npm install --save xterm-addon-web-links
```
### Usage
```ts
import { Terminal } from 'xterm';
import { WebLinksAddon } from 'xterm-addon-web-links';
const terminal = new Terminal();
terminal.loadAddon(new WebLinksAddon());
```
See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/xterm-addon-web-links/typings/xterm-addon-web-links.d.ts) for more advanced usage.
+21
View File
@@ -0,0 +1,21 @@
{
"name": "xterm-addon-web-links",
"version": "0.3.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
},
"main": "lib/xterm-addon-web-links.js",
"types": "typings/xterm-addon-web-links.d.ts",
"repository": "https://github.com/xtermjs/xterm.js",
"license": "MIT",
"scripts": {
"build": "../../node_modules/.bin/tsc -p src",
"prepackage": "npm run build",
"package": "../../node_modules/.bin/webpack",
"prepublishOnly": "npm run package"
},
"peerDependencies": {
"xterm": "^4.0.0"
}
}
@@ -0,0 +1,114 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { ILinkProvider, IBufferCellPosition, ILink, Terminal, IBuffer } from 'xterm';
export class WebLinkProvider implements ILinkProvider {
constructor(
private readonly _terminal: Terminal,
private readonly _regex: RegExp,
private readonly _handler: (event: MouseEvent, uri: string) => void
) {
}
provideLink(position: IBufferCellPosition, callback: (link: ILink | undefined) => void): void {
callback(LinkComputer.computeLink(position, this._regex, this._terminal, this._handler));
}
}
export class LinkComputer {
public static computeLink(position: IBufferCellPosition, regex: RegExp, terminal: Terminal, handler: (event: MouseEvent, uri: string) => void): ILink | undefined {
const rex = new RegExp(regex.source, (regex.flags || '') + 'g');
const [line, startLineIndex] = LinkComputer._translateBufferLineToStringWithWrap(position.y - 1, false, terminal);
let match;
let stringIndex = -1;
while ((match = rex.exec(line)) !== null) {
const text = match[1];
if (!text) {
// something matched but does not comply with the given matchIndex
// since this is most likely a bug the regex itself we simply do nothing here
console.log('match found without corresponding matchIndex');
break;
}
// Get index, match.index is for the outer match which includes negated chars
// therefore we cannot use match.index directly, instead we search the position
// of the match group in text again
// also correct regex and string search offsets for the next loop run
stringIndex = line.indexOf(text, stringIndex + 1);
rex.lastIndex = stringIndex + text.length;
if (stringIndex < 0) {
// invalid stringIndex (should not have happened)
break;
}
let endX = stringIndex + text.length;
let endY = startLineIndex + 1;
while (endX > terminal.cols) {
endX -= terminal.cols;
endY++;
}
const range = {
start: {
x: stringIndex + 1,
y: startLineIndex + 1
},
end: {
x: endX,
y: endY
}
};
return { range, text, activate: handler };
}
}
/**
* Gets the entire line for the buffer line
* @param line The line being translated.
* @param trimRight Whether to trim whitespace to the right.
* @param terminal The terminal
*/
private static _translateBufferLineToStringWithWrap(lineIndex: number, trimRight: boolean, terminal: Terminal): [string, number] {
let lineString = '';
let lineWrapsToNext: boolean;
let prevLinesToWrap: boolean;
do {
const line = terminal.buffer.active.getLine(lineIndex);
if (!line) {
break;
}
if (line.isWrapped) {
lineIndex--;
}
prevLinesToWrap = line.isWrapped;
} while (prevLinesToWrap);
const startLineIndex = lineIndex;
do {
const nextLine = terminal.buffer.active.getLine(lineIndex + 1);
lineWrapsToNext = nextLine ? nextLine.isWrapped : false;
const line = terminal.buffer.active.getLine(lineIndex);
if (!line) {
break;
}
lineString += line.translateToString(!lineWrapsToNext && trimRight).substring(0, terminal.cols);
lineIndex++;
} while (lineWrapsToNext);
return [lineString, startLineIndex];
}
}
@@ -0,0 +1,69 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { assert } from 'chai';
import { openTerminal, pollFor, writeSync, getBrowserType } from '../../../out-test/api/TestUtils';
import { Browser, Page } from 'playwright-core';
const APP = 'http://127.0.0.1:3000/test';
let browser: Browser;
let page: Page;
const width = 800;
const height = 600;
describe('WebLinksAddon', () => {
before(async function(): Promise<any> {
const browserType = getBrowserType();
browser = await browserType.launch({ dumpio: true,
headless: process.argv.indexOf('--headless') !== -1
});
page = await (await browser.newContext()).newPage();
await page.setViewportSize({ width, height });
});
after(async () => await browser.close());
beforeEach(async () => await page.goto(APP));
it('.com', async function(): Promise<any> {
await testHostName('foo.com');
});
it('.com.au', async function(): Promise<any> {
await testHostName('foo.com.au');
});
it('.io', async function(): Promise<any> {
await testHostName('foo.io');
});
});
async function testHostName(hostname: string): Promise<void> {
await openTerminal(page, { rendererType: 'dom', cols: 40 });
await page.evaluate(`window.term.loadAddon(new window.WebLinksAddon())`);
const data = ` http://${hostname} \\r\\n` +
` http://${hostname}/a~b#c~d?e~f \\r\\n` +
` http://${hostname}/colon:test \\r\\n` +
` http://${hostname}/colon:test: \\r\\n` +
`"http://${hostname}/"\\r\\n` +
`\\'http://${hostname}/\\'\\r\\n` +
`http://${hostname}/subpath/+/id`;
await writeSync(page, data);
await pollForLinkAtCell(3, 1, `http://${hostname}`);
await pollForLinkAtCell(3, 2, `http://${hostname}/a~b#c~d?e~f`);
await pollForLinkAtCell(3, 3, `http://${hostname}/colon:test`);
await pollForLinkAtCell(3, 4, `http://${hostname}/colon:test`);
await pollForLinkAtCell(2, 5, `http://${hostname}/`);
await pollForLinkAtCell(2, 6, `http://${hostname}/`);
await pollForLinkAtCell(1, 7, `http://${hostname}/subpath/+/id`);
}
async function pollForLinkAtCell(col: number, row: number, value: string): Promise<void> {
const rowSelector = `.xterm-rows > :nth-child(${row})`;
// Ensure the hover element exists before trying to hover it
await pollFor(page, `!!document.querySelector('${rowSelector} > :nth-child(${col})')`, true);
await pollFor(page, `document.querySelectorAll('${rowSelector} > span[style]').length >= ${value.length}`, true, async () => page.hover(`${rowSelector} > :nth-child(${col})`));
assert.equal(await page.evaluate(`Array.prototype.reduce.call(document.querySelectorAll('${rowSelector} > span[style]'), (a, b) => a + b.textContent, '');`), value);
}
@@ -0,0 +1,70 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { Terminal, ILinkMatcherOptions, ITerminalAddon, ILinkProvider, IDisposable } from 'xterm';
import { WebLinkProvider } from './WebLinkProvider';
const protocolClause = '(https?:\\/\\/)';
const domainCharacterSet = '[\\da-z\\.-]+';
const negatedDomainCharacterSet = '[^\\da-z\\.-]+';
const domainBodyClause = '(' + domainCharacterSet + ')';
const tldClause = '([a-z\\.]{2,6})';
const ipClause = '((\\d{1,3}\\.){3}\\d{1,3})';
const localHostClause = '(localhost)';
const portClause = '(:\\d{1,5})';
const hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + '|' + localHostClause + ')' + portClause + '?';
const pathCharacterSet = '(\\/[\\/\\w\\.\\-%~:+]*)*([^:"\'\\s])';
const pathClause = '(' + pathCharacterSet + ')?';
const queryStringHashFragmentCharacterSet = '[0-9\\w\\[\\]\\(\\)\\/\\?\\!#@$%&\'*+,:;~\\=\\.\\-]*';
const queryStringClause = '(\\?' + queryStringHashFragmentCharacterSet + ')?';
const hashFragmentClause = '(#' + queryStringHashFragmentCharacterSet + ')?';
const negatedPathCharacterSet = '[^\\/\\w\\.\\-%]+';
const bodyClause = hostClause + pathClause + queryStringClause + hashFragmentClause;
const start = '(?:^|' + negatedDomainCharacterSet + ')(';
const end = ')($|' + negatedPathCharacterSet + ')';
const strictUrlRegex = new RegExp(start + protocolClause + bodyClause + end);
function handleLink(event: MouseEvent, uri: string): void {
const newWindow = window.open();
if (newWindow) {
newWindow.opener = null;
newWindow.location.href = uri;
} else {
console.warn('Opening link blocked as opener could not be cleared');
}
}
export class WebLinksAddon implements ITerminalAddon {
private _linkMatcherId: number | undefined;
private _terminal: Terminal | undefined;
private _linkProvider: IDisposable | undefined;
constructor(
private _handler: (event: MouseEvent, uri: string) => void = handleLink,
private _options: ILinkMatcherOptions = {},
private _useLinkProvider: boolean = false
) {
this._options.matchIndex = 1;
}
public activate(terminal: Terminal): void {
this._terminal = terminal;
if (this._useLinkProvider && 'registerLinkProvider' in this._terminal) {
this._linkProvider = this._terminal.registerLinkProvider(new WebLinkProvider(this._terminal, strictUrlRegex, this._handler));
} else {
// TODO: This should be removed eventually
this._linkMatcherId = (this._terminal as Terminal).registerLinkMatcher(strictUrlRegex, this._handler, this._options);
}
}
public dispose(): void {
if (this._linkMatcherId !== undefined && this._terminal !== undefined) {
this._terminal.deregisterLinkMatcher(this._linkMatcherId);
}
this._linkProvider?.dispose();
}
}
@@ -4,19 +4,20 @@
"target": "es5",
"lib": [
"dom",
"es5"
"es2015"
],
"rootDir": ".",
"outDir": "../../../lib/addons/fit/",
"outDir": "../out",
"sourceMap": true,
"removeComments": true,
"declaration": true,
"strict": true,
"types": [
"../../node_modules/@types/mocha"
"../../../node_modules/@types/mocha",
"../../../out-test/api/TestUtils"
]
},
"include": [
"**/*.ts",
"./**/*",
"../../../typings/xterm.d.ts"
]
}
@@ -0,0 +1,36 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { Terminal, ILinkMatcherOptions, ITerminalAddon } from 'xterm';
declare module 'xterm-addon-web-links' {
/**
* An xterm.js addon that enables web links.
*/
export class WebLinksAddon implements ITerminalAddon {
/**
* Creates a new web links addon.
* @param handler The callback when the link is called.
* @param options Options for the link matcher.
* @param useLinkProvider Whether to use the new link provider API to create
* the links. This is an option because use of both link matcher (old) and
* link provider (new) may cause issues. Link provider will eventually be
* the default and only option.
*/
constructor(handler?: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions, useLinkProvider?: boolean);
/**
* Activates the addon
* @param terminal The terminal the addon is being loaded in.
*/
public activate(terminal: Terminal): void;
/**
* Disposes the addon.
*/
public dispose(): void;
}
}
@@ -0,0 +1,31 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
const path = require('path');
const addonName = 'WebLinksAddon';
const mainFile = 'xterm-addon-web-links.js';
module.exports = {
entry: `./out/${addonName}.js`,
devtool: 'source-map',
module: {
rules: [
{
test: /\.js$/,
use: ["source-map-loader"],
enforce: "pre",
exclude: /node_modules/
}
]
},
output: {
filename: mainFile,
path: path.resolve('./lib'),
library: addonName,
libraryTarget: 'umd'
},
mode: 'production'
};
+2
View File
@@ -0,0 +1,2 @@
lib
node_modules
+5
View File
@@ -0,0 +1,5 @@
**/*.api.js
**/*.api.ts
tsconfig.json
.yarnrc
webpack.config.js
+19
View File
@@ -0,0 +1,19 @@
Copyright (c) 2018, The xterm.js authors (https://github.com/xtermjs/xterm.js)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+23
View File
@@ -0,0 +1,23 @@
## xterm-addon-webgl
An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables a WebGL-based renderer. This addon requires xterm.js v4+.
⚠️ This is an experimental addon that is [missing some features and may be unstable](https://github.com/xtermjs/xterm.js/issues?q=is%3Aopen+is%3Aissue+label%3Aarea%2Faddon%2Fwebgl) ⚠️
### Install
```bash
npm install --save xterm-addon-webgl
```
### Usage
```ts
import { Terminal } from 'xterm';
import { WebglAddon } from 'xterm-addon-webgl';
const terminal = new Terminal();
terminal.loadAddon(new WebglAddon());
```
See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/xterm-addon-webgl/typings/xterm-addon-webgl.d.ts) for more advanced usage.
+21
View File
@@ -0,0 +1,21 @@
{
"name": "xterm-addon-webgl",
"version": "0.6.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
},
"main": "lib/xterm-addon-webgl.js",
"types": "typings/xterm-addon-webgl.d.ts",
"repository": "https://github.com/xtermjs/xterm.js",
"license": "MIT",
"scripts": {
"build": "../../node_modules/.bin/tsc -p src",
"prepackage": "npm run build",
"package": "../../node_modules/.bin/webpack",
"prepublishOnly": "npm run package"
},
"peerDependencies": {
"xterm": "^4.0.0"
}
}
@@ -0,0 +1,393 @@
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { createProgram, PROJECTION_MATRIX, throwIfFalsy } from './WebglUtils';
import { WebglCharAtlas } from './atlas/WebglCharAtlas';
import { IWebGL2RenderingContext, IWebGLVertexArrayObject, IRenderModel, IRasterizedGlyph } from './Types';
import { COMBINED_CHAR_BIT_MASK, RENDER_MODEL_INDICIES_PER_CELL, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_BG_OFFSET } from './RenderModel';
import { fill } from 'common/TypedArrayUtils';
import { slice } from './TypedArray';
import { NULL_CELL_CODE, WHITESPACE_CELL_CODE, Attributes, FgFlags } from 'common/buffer/Constants';
import { Terminal, IBufferLine } from 'xterm';
import { IColorSet, IColor } from 'browser/Types';
import { IRenderDimensions } from 'browser/renderer/Types';
import { AttributeData } from 'common/buffer/AttributeData';
interface IVertices {
attributes: Float32Array;
/**
* These buffers are the ones used to bind to WebGL, the reason there are
* multiple is to allow double buffering to work as you cannot modify the
* buffer while it's being used by the GPU. Having multiple lets us start
* working on the next frame.
*/
attributesBuffers: Float32Array[];
selectionAttributes: Float32Array;
count: number;
}
const enum VertexAttribLocations {
UNIT_QUAD = 0,
CELL_POSITION = 1,
OFFSET = 2,
SIZE = 3,
TEXCOORD = 4,
TEXSIZE = 5
}
const vertexShaderSource = `#version 300 es
layout (location = ${VertexAttribLocations.UNIT_QUAD}) in vec2 a_unitquad;
layout (location = ${VertexAttribLocations.CELL_POSITION}) in vec2 a_cellpos;
layout (location = ${VertexAttribLocations.OFFSET}) in vec2 a_offset;
layout (location = ${VertexAttribLocations.SIZE}) in vec2 a_size;
layout (location = ${VertexAttribLocations.TEXCOORD}) in vec2 a_texcoord;
layout (location = ${VertexAttribLocations.TEXSIZE}) in vec2 a_texsize;
uniform mat4 u_projection;
uniform vec2 u_resolution;
out vec2 v_texcoord;
void main() {
vec2 zeroToOne = (a_offset / u_resolution) + a_cellpos + (a_unitquad * a_size);
gl_Position = u_projection * vec4(zeroToOne, 0.0, 1.0);
v_texcoord = a_texcoord + a_unitquad * a_texsize;
}`;
const fragmentShaderSource = `#version 300 es
precision lowp float;
in vec2 v_texcoord;
uniform sampler2D u_texture;
out vec4 outColor;
void main() {
outColor = texture(u_texture, v_texcoord);
}`;
const INDICES_PER_CELL = 10;
const BYTES_PER_CELL = INDICES_PER_CELL * Float32Array.BYTES_PER_ELEMENT;
const CELL_POSITION_INDICES = 2;
export class GlyphRenderer {
private _atlas: WebglCharAtlas | undefined;
private _program: WebGLProgram;
private _vertexArrayObject: IWebGLVertexArrayObject;
private _projectionLocation: WebGLUniformLocation;
private _resolutionLocation: WebGLUniformLocation;
private _textureLocation: WebGLUniformLocation;
private _atlasTexture: WebGLTexture;
private _attributesBuffer: WebGLBuffer;
private _activeBuffer: number = 0;
private _vertices: IVertices = {
count: 0,
attributes: new Float32Array(0),
attributesBuffers: [
new Float32Array(0),
new Float32Array(0)
],
selectionAttributes: new Float32Array(0)
};
constructor(
private _terminal: Terminal,
private _colors: IColorSet,
private _gl: IWebGL2RenderingContext,
private _dimensions: IRenderDimensions
) {
const gl = this._gl;
const program = throwIfFalsy(createProgram(gl, vertexShaderSource, fragmentShaderSource));
this._program = program;
// Uniform locations
this._projectionLocation = throwIfFalsy(gl.getUniformLocation(this._program, 'u_projection'));
this._resolutionLocation = throwIfFalsy(gl.getUniformLocation(this._program, 'u_resolution'));
this._textureLocation = throwIfFalsy(gl.getUniformLocation(this._program, 'u_texture'));
// Create and set the vertex array object
this._vertexArrayObject = gl.createVertexArray();
gl.bindVertexArray(this._vertexArrayObject);
// Setup a_unitquad, this defines the 4 vertices of a rectangle
const unitQuadVertices = new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]);
const unitQuadVerticesBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, unitQuadVerticesBuffer);
gl.bufferData(gl.ARRAY_BUFFER, unitQuadVertices, gl.STATIC_DRAW);
gl.enableVertexAttribArray(VertexAttribLocations.UNIT_QUAD);
gl.vertexAttribPointer(VertexAttribLocations.UNIT_QUAD, 2, this._gl.FLOAT, false, 0, 0);
// Setup the unit quad element array buffer, this points to indices in
// unitQuadVertuces to allow is to draw 2 triangles from the vertices
const unitQuadElementIndices = new Uint8Array([0, 1, 3, 0, 2, 3]);
const elementIndicesBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementIndicesBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, unitQuadElementIndices, gl.STATIC_DRAW);
// Setup attributes
this._attributesBuffer = throwIfFalsy(gl.createBuffer());
gl.bindBuffer(gl.ARRAY_BUFFER, this._attributesBuffer);
gl.enableVertexAttribArray(VertexAttribLocations.OFFSET);
gl.vertexAttribPointer(VertexAttribLocations.OFFSET, 2, gl.FLOAT, false, BYTES_PER_CELL, 0);
gl.vertexAttribDivisor(VertexAttribLocations.OFFSET, 1);
gl.enableVertexAttribArray(VertexAttribLocations.SIZE);
gl.vertexAttribPointer(VertexAttribLocations.SIZE, 2, gl.FLOAT, false, BYTES_PER_CELL, 2 * Float32Array.BYTES_PER_ELEMENT);
gl.vertexAttribDivisor(VertexAttribLocations.SIZE, 1);
gl.enableVertexAttribArray(VertexAttribLocations.TEXCOORD);
gl.vertexAttribPointer(VertexAttribLocations.TEXCOORD, 2, gl.FLOAT, false, BYTES_PER_CELL, 4 * Float32Array.BYTES_PER_ELEMENT);
gl.vertexAttribDivisor(VertexAttribLocations.TEXCOORD, 1);
gl.enableVertexAttribArray(VertexAttribLocations.TEXSIZE);
gl.vertexAttribPointer(VertexAttribLocations.TEXSIZE, 2, gl.FLOAT, false, BYTES_PER_CELL, 6 * Float32Array.BYTES_PER_ELEMENT);
gl.vertexAttribDivisor(VertexAttribLocations.TEXSIZE, 1);
gl.enableVertexAttribArray(VertexAttribLocations.CELL_POSITION);
gl.vertexAttribPointer(VertexAttribLocations.CELL_POSITION, 2, gl.FLOAT, false, BYTES_PER_CELL, 8 * Float32Array.BYTES_PER_ELEMENT);
gl.vertexAttribDivisor(VertexAttribLocations.CELL_POSITION, 1);
// Setup empty texture atlas
this._atlasTexture = throwIfFalsy(gl.createTexture());
gl.bindTexture(gl.TEXTURE_2D, this._atlasTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 255, 255]));
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
// Allow drawing of transparent texture
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
// Set viewport
this.onResize();
}
public beginFrame(): boolean {
return this._atlas ? this._atlas.beginFrame() : true;
}
public updateCell(x: number, y: number, code: number, bg: number, fg: number, chars: string): void {
this._updateCell(this._vertices.attributes, x, y, code, bg, fg, chars);
}
private _updateCell(array: Float32Array, x: number, y: number, code: number | undefined, bg: number, fg: number, chars?: string): void {
const terminal = this._terminal;
const i = (y * terminal.cols + x) * INDICES_PER_CELL;
// Exit early if this is a null/space character
if (code === NULL_CELL_CODE || code === WHITESPACE_CELL_CODE || code === undefined/* This is used for the right side of wide chars */) {
fill(array, 0, i, i + INDICES_PER_CELL - 1 - CELL_POSITION_INDICES);
return;
}
let rasterizedGlyph: IRasterizedGlyph;
if (!this._atlas) {
return;
}
if (chars && chars.length > 1) {
rasterizedGlyph = this._atlas.getRasterizedGlyphCombinedChar(chars, bg, fg);
} else {
rasterizedGlyph = this._atlas.getRasterizedGlyph(code, bg, fg);
}
// Fill empty if no glyph was found
if (!rasterizedGlyph) {
fill(array, 0, i, i + INDICES_PER_CELL - 1 - CELL_POSITION_INDICES);
return;
}
// a_origin
array[i ] = -rasterizedGlyph.offset.x + this._dimensions.scaledCharLeft;
array[i + 1] = -rasterizedGlyph.offset.y + this._dimensions.scaledCharTop;
// a_size
array[i + 2] = rasterizedGlyph.size.x / this._dimensions.scaledCanvasWidth;
array[i + 3] = rasterizedGlyph.size.y / this._dimensions.scaledCanvasHeight;
// a_texcoord
array[i + 4] = rasterizedGlyph.texturePositionClipSpace.x;
array[i + 5] = rasterizedGlyph.texturePositionClipSpace.y;
// a_texsize
array[i + 6] = rasterizedGlyph.sizeClipSpace.x;
array[i + 7] = rasterizedGlyph.sizeClipSpace.y;
// a_cellpos only changes on resize
}
public updateSelection(model: IRenderModel, columnSelectMode: boolean): void {
const terminal = this._terminal;
this._vertices.selectionAttributes = slice(this._vertices.attributes, 0);
const bg = (this._colors.selectionOpaque.rgba >>> 8) | Attributes.CM_RGB;
if (columnSelectMode) {
const startCol = model.selection.startCol;
const width = model.selection.endCol - startCol;
const height = model.selection.viewportCappedEndRow - model.selection.viewportCappedStartRow + 1;
for (let y = model.selection.viewportCappedStartRow; y < model.selection.viewportCappedStartRow + height; y++) {
this._updateSelectionRange(startCol, startCol + width, y, model, bg);
}
} else {
// Draw first row
const startCol = model.selection.viewportStartRow === model.selection.viewportCappedStartRow ? model.selection.startCol : 0;
const startRowEndCol = model.selection.viewportCappedStartRow === model.selection.viewportCappedEndRow ? model.selection.endCol : terminal.cols;
this._updateSelectionRange(startCol, startRowEndCol, model.selection.viewportCappedStartRow, model, bg);
// Draw middle rows
const middleRowsCount = Math.max(model.selection.viewportCappedEndRow - model.selection.viewportCappedStartRow - 1, 0);
for (let y = model.selection.viewportCappedStartRow + 1; y <= model.selection.viewportCappedStartRow + middleRowsCount; y++) {
this._updateSelectionRange(0, startRowEndCol, y, model, bg);
}
// Draw final row
if (model.selection.viewportCappedStartRow !== model.selection.viewportCappedEndRow) {
// Only draw viewportEndRow if it's not the same as viewportStartRow
const endCol = model.selection.viewportEndRow === model.selection.viewportCappedEndRow ? model.selection.endCol : terminal.cols;
this._updateSelectionRange(0, endCol, model.selection.viewportCappedEndRow, model, bg);
}
}
}
private _updateSelectionRange(startCol: number, endCol: number, y: number, model: IRenderModel, bg: number): void {
const terminal = this._terminal;
const row = y + terminal.buffer.active.viewportY;
let line: IBufferLine | undefined;
for (let x = startCol; x < endCol; x++) {
const offset = (y * this._terminal.cols + x) * RENDER_MODEL_INDICIES_PER_CELL;
const code = model.cells[offset];
let fg = model.cells[offset + RENDER_MODEL_FG_OFFSET];
if (fg & FgFlags.INVERSE) {
const workCell = new AttributeData();
workCell.fg = fg;
workCell.bg = model.cells[offset + RENDER_MODEL_BG_OFFSET];
// Get attributes from fg (excluding inverse) and resolve inverse by pullibng rgb colors
// from bg. This is needed since the inverse fg color should be based on the original bg
// color, not on the selection color
fg = (fg & ~(Attributes.CM_MASK | Attributes.RGB_MASK | FgFlags.INVERSE));
switch (workCell.getBgColorMode()) {
case Attributes.CM_P16:
case Attributes.CM_P256:
const c = this._getColorFromAnsiIndex(workCell.getBgColor()).rgba;
fg |= (c >> 8) & Attributes.RED_MASK | (c >> 8) & Attributes.GREEN_MASK | (c >> 8) & Attributes.BLUE_MASK;
case Attributes.CM_RGB:
const arr = AttributeData.toColorRGB(workCell.getBgColor());
fg |= arr[0] << Attributes.RED_SHIFT | arr[1] << Attributes.GREEN_SHIFT | arr[2] << Attributes.BLUE_SHIFT;
case Attributes.CM_DEFAULT:
default:
const c2 = this._colors.background.rgba;
fg |= (c2 >> 8) & Attributes.RED_MASK | (c2 >> 8) & Attributes.GREEN_MASK | (c2 >> 8) & Attributes.BLUE_MASK;
}
fg |= Attributes.CM_RGB;
}
if (code & COMBINED_CHAR_BIT_MASK) {
if (!line) {
line = terminal.buffer.active.getLine(row);
}
const chars = line!.getCell(x)!.getChars();
this._updateCell(this._vertices.selectionAttributes, x, y, model.cells[offset], bg, fg, chars);
} else {
this._updateCell(this._vertices.selectionAttributes, x, y, model.cells[offset], bg, fg);
}
}
}
private _getColorFromAnsiIndex(idx: number): IColor {
if (idx >= this._colors.ansi.length) {
throw new Error('No color found for idx ' + idx);
}
return this._colors.ansi[idx];
}
public onResize(): void {
const terminal = this._terminal;
const gl = this._gl;
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
// Update vertices
const newCount = terminal.cols * terminal.rows * INDICES_PER_CELL;
if (this._vertices.count !== newCount) {
this._vertices.count = newCount;
this._vertices.attributes = new Float32Array(newCount);
for (let i = 0; i < this._vertices.attributesBuffers.length; i++) {
this._vertices.attributesBuffers[i] = new Float32Array(newCount);
}
let i = 0;
for (let y = 0; y < terminal.rows; y++) {
for (let x = 0; x < terminal.cols; x++) {
this._vertices.attributes[i + 8] = x / terminal.cols;
this._vertices.attributes[i + 9] = y / terminal.rows;
i += INDICES_PER_CELL;
}
}
}
}
public setColors(): void {
}
public render(renderModel: IRenderModel, isSelectionVisible: boolean): void {
if (!this._atlas) {
return;
}
const gl = this._gl;
gl.useProgram(this._program);
gl.bindVertexArray(this._vertexArrayObject);
// Alternate buffers each frame as the active buffer gets locked while it's in use by the GPU
this._activeBuffer = (this._activeBuffer + 1) % 2;
const activeBuffer = this._vertices.attributesBuffers[this._activeBuffer];
// Copy data for each cell of each line up to its line length (the last non-whitespace cell)
// from the attributes buffer into activeBuffer, which is the one that gets bound to the GPU.
// The reasons for this are as follows:
// - So the active buffer can be alternated so we don't get blocked on rendering finishing
// - To copy either the normal attributes buffer or the selection attributes buffer when there
// is a selection
// - So we don't send vertices for all the line-ending whitespace to the GPU
let bufferLength = 0;
for (let y = 0; y < renderModel.lineLengths.length; y++) {
const si = y * this._terminal.cols * INDICES_PER_CELL;
const sub = (isSelectionVisible ? this._vertices.selectionAttributes : this._vertices.attributes).subarray(si, si + renderModel.lineLengths[y] * INDICES_PER_CELL);
activeBuffer.set(sub, bufferLength);
bufferLength += sub.length;
}
// Bind the attributes buffer
gl.bindBuffer(gl.ARRAY_BUFFER, this._attributesBuffer);
gl.bufferData(gl.ARRAY_BUFFER, activeBuffer.subarray(0, bufferLength), gl.STREAM_DRAW);
// Bind the texture atlas if it's changed
if (this._atlas.hasCanvasChanged) {
this._atlas.hasCanvasChanged = false;
gl.uniform1i(this._textureLocation, 0);
gl.activeTexture(gl.TEXTURE0 + 0);
gl.bindTexture(gl.TEXTURE_2D, this._atlasTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._atlas.cacheCanvas);
gl.generateMipmap(gl.TEXTURE_2D);
}
// Set uniforms
gl.uniformMatrix4fv(this._projectionLocation, false, PROJECTION_MATRIX);
gl.uniform2f(this._resolutionLocation, gl.canvas.width, gl.canvas.height);
// Draw the viewport
gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, bufferLength / INDICES_PER_CELL);
}
public setAtlas(atlas: WebglCharAtlas): void {
const gl = this._gl;
this._atlas = atlas;
gl.bindTexture(gl.TEXTURE_2D, this._atlasTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, atlas.cacheCanvas);
gl.generateMipmap(gl.TEXTURE_2D);
}
public setDimensions(dimensions: IRenderDimensions): void {
this._dimensions = dimensions;
}
}
@@ -0,0 +1,350 @@
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { createProgram, expandFloat32Array, PROJECTION_MATRIX, throwIfFalsy } from './WebglUtils';
import { IRenderModel, IWebGLVertexArrayObject, IWebGL2RenderingContext, ISelectionRenderModel } from './Types';
import { fill } from 'common/TypedArrayUtils';
import { Attributes, FgFlags } from 'common/buffer/Constants';
import { Terminal } from 'xterm';
import { IColorSet, IColor } from 'browser/Types';
import { IRenderDimensions } from 'browser/renderer/Types';
import { RENDER_MODEL_BG_OFFSET, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_INDICIES_PER_CELL } from './RenderModel';
const enum VertexAttribLocations {
POSITION = 0,
SIZE = 1,
COLOR = 2,
UNIT_QUAD = 3
}
const vertexShaderSource = `#version 300 es
layout (location = ${VertexAttribLocations.POSITION}) in vec2 a_position;
layout (location = ${VertexAttribLocations.SIZE}) in vec2 a_size;
layout (location = ${VertexAttribLocations.COLOR}) in vec4 a_color;
layout (location = ${VertexAttribLocations.UNIT_QUAD}) in vec2 a_unitquad;
uniform mat4 u_projection;
uniform vec2 u_resolution;
out vec4 v_color;
void main() {
vec2 zeroToOne = (a_position + (a_unitquad * a_size)) / u_resolution;
gl_Position = u_projection * vec4(zeroToOne, 0.0, 1.0);
v_color = a_color;
}`;
const fragmentShaderSource = `#version 300 es
precision lowp float;
in vec4 v_color;
out vec4 outColor;
void main() {
outColor = v_color;
}`;
interface IVertices {
attributes: Float32Array;
selection: Float32Array;
count: number;
}
const INDICES_PER_RECTANGLE = 8;
const BYTES_PER_RECTANGLE = INDICES_PER_RECTANGLE * Float32Array.BYTES_PER_ELEMENT;
const INITIAL_BUFFER_RECTANGLE_CAPACITY = 20 * INDICES_PER_RECTANGLE;
export class RectangleRenderer {
private _program: WebGLProgram;
private _vertexArrayObject: IWebGLVertexArrayObject;
private _resolutionLocation: WebGLUniformLocation;
private _attributesBuffer: WebGLBuffer;
private _projectionLocation: WebGLUniformLocation;
private _bgFloat!: Float32Array;
private _selectionFloat!: Float32Array;
private _vertices: IVertices = {
count: 0,
attributes: new Float32Array(INITIAL_BUFFER_RECTANGLE_CAPACITY),
selection: new Float32Array(3 * INDICES_PER_RECTANGLE)
};
constructor(
private _terminal: Terminal,
private _colors: IColorSet,
private _gl: IWebGL2RenderingContext,
private _dimensions: IRenderDimensions
) {
const gl = this._gl;
this._program = throwIfFalsy(createProgram(gl, vertexShaderSource, fragmentShaderSource));
// Uniform locations
this._resolutionLocation = throwIfFalsy(gl.getUniformLocation(this._program, 'u_resolution'));
this._projectionLocation = throwIfFalsy(gl.getUniformLocation(this._program, 'u_projection'));
// Create and set the vertex array object
this._vertexArrayObject = gl.createVertexArray();
gl.bindVertexArray(this._vertexArrayObject);
// Setup a_unitquad, this defines the 4 vertices of a rectangle
const unitQuadVertices = new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]);
const unitQuadVerticesBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, unitQuadVerticesBuffer);
gl.bufferData(gl.ARRAY_BUFFER, unitQuadVertices, gl.STATIC_DRAW);
gl.enableVertexAttribArray(VertexAttribLocations.UNIT_QUAD);
gl.vertexAttribPointer(VertexAttribLocations.UNIT_QUAD, 2, this._gl.FLOAT, false, 0, 0);
// Setup the unit quad element array buffer, this points to indices in
// unitQuadVertuces to allow is to draw 2 triangles from the vertices
const unitQuadElementIndices = new Uint8Array([0, 1, 3, 0, 2, 3]);
const elementIndicesBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementIndicesBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, unitQuadElementIndices, gl.STATIC_DRAW);
// Setup attributes
this._attributesBuffer = throwIfFalsy(gl.createBuffer());
gl.bindBuffer(gl.ARRAY_BUFFER, this._attributesBuffer);
gl.enableVertexAttribArray(VertexAttribLocations.POSITION);
gl.vertexAttribPointer(VertexAttribLocations.POSITION, 2, gl.FLOAT, false, BYTES_PER_RECTANGLE, 0);
gl.vertexAttribDivisor(VertexAttribLocations.POSITION, 1);
gl.enableVertexAttribArray(VertexAttribLocations.SIZE);
gl.vertexAttribPointer(VertexAttribLocations.SIZE, 2, gl.FLOAT, false, BYTES_PER_RECTANGLE, 2 * Float32Array.BYTES_PER_ELEMENT);
gl.vertexAttribDivisor(VertexAttribLocations.SIZE, 1);
gl.enableVertexAttribArray(VertexAttribLocations.COLOR);
gl.vertexAttribPointer(VertexAttribLocations.COLOR, 4, gl.FLOAT, false, BYTES_PER_RECTANGLE, 4 * Float32Array.BYTES_PER_ELEMENT);
gl.vertexAttribDivisor(VertexAttribLocations.COLOR, 1);
this._updateCachedColors();
}
public render(): void {
const gl = this._gl;
gl.useProgram(this._program);
gl.bindVertexArray(this._vertexArrayObject);
gl.uniformMatrix4fv(this._projectionLocation, false, PROJECTION_MATRIX);
gl.uniform2f(this._resolutionLocation, gl.canvas.width, gl.canvas.height);
// Bind attributes buffer and draw
gl.bindBuffer(gl.ARRAY_BUFFER, this._attributesBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this._vertices.attributes, gl.DYNAMIC_DRAW);
gl.drawElementsInstanced(this._gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, this._vertices.count);
// Bind selection buffer and draw
gl.bindBuffer(gl.ARRAY_BUFFER, this._attributesBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this._vertices.selection, gl.DYNAMIC_DRAW);
gl.drawElementsInstanced(this._gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, 3);
}
public onResize(): void {
this._updateViewportRectangle();
}
public setColors(): void {
this._updateCachedColors();
this._updateViewportRectangle();
}
private _updateCachedColors(): void {
this._bgFloat = this._colorToFloat32Array(this._colors.background);
this._selectionFloat = this._colorToFloat32Array(this._colors.selectionOpaque);
}
private _updateViewportRectangle(): void {
// Set first rectangle that clears the screen
this._addRectangleFloat(
this._vertices.attributes,
0,
0,
0,
this._terminal.cols * this._dimensions.scaledCellWidth,
this._terminal.rows * this._dimensions.scaledCellHeight,
this._bgFloat
);
}
public updateSelection(model: ISelectionRenderModel, columnSelectMode: boolean): void {
const terminal = this._terminal;
if (!model.hasSelection) {
fill(this._vertices.selection, 0, 0);
return;
}
if (columnSelectMode) {
const startCol = model.startCol;
const width = model.endCol - startCol;
const height = model.viewportCappedEndRow - model.viewportCappedStartRow + 1;
this._addRectangleFloat(
this._vertices.selection,
0,
startCol * this._dimensions.scaledCellWidth,
model.viewportCappedStartRow * this._dimensions.scaledCellHeight,
width * this._dimensions.scaledCellWidth,
height * this._dimensions.scaledCellHeight,
this._selectionFloat
);
fill(this._vertices.selection, 0, INDICES_PER_RECTANGLE);
} else {
// Draw first row
const startCol = model.viewportStartRow === model.viewportCappedStartRow ? model.startCol : 0;
const startRowEndCol = model.viewportCappedStartRow === model.viewportCappedEndRow ? model.endCol : terminal.cols;
this._addRectangleFloat(
this._vertices.selection,
0,
startCol * this._dimensions.scaledCellWidth,
model.viewportCappedStartRow * this._dimensions.scaledCellHeight,
(startRowEndCol - startCol) * this._dimensions.scaledCellWidth,
this._dimensions.scaledCellHeight,
this._selectionFloat
);
// Draw middle rows
const middleRowsCount = Math.max(model.viewportCappedEndRow - model.viewportCappedStartRow - 1, 0);
this._addRectangleFloat(
this._vertices.selection,
INDICES_PER_RECTANGLE,
0,
(model.viewportCappedStartRow + 1) * this._dimensions.scaledCellHeight,
terminal.cols * this._dimensions.scaledCellWidth,
middleRowsCount * this._dimensions.scaledCellHeight,
this._selectionFloat
);
// Draw final row
if (model.viewportCappedStartRow !== model.viewportCappedEndRow) {
// Only draw viewportEndRow if it's not the same as viewportStartRow
const endCol = model.viewportEndRow === model.viewportCappedEndRow ? model.endCol : terminal.cols;
this._addRectangleFloat(
this._vertices.selection,
INDICES_PER_RECTANGLE * 2,
0,
model.viewportCappedEndRow * this._dimensions.scaledCellHeight,
endCol * this._dimensions.scaledCellWidth,
this._dimensions.scaledCellHeight,
this._selectionFloat
);
} else {
fill(this._vertices.selection, 0, INDICES_PER_RECTANGLE * 2);
}
}
}
public updateBackgrounds(model: IRenderModel): void {
const terminal = this._terminal;
const vertices = this._vertices;
let rectangleCount = 1;
for (let y = 0; y < terminal.rows; y++) {
let currentStartX = -1;
let currentBg = 0;
let currentFg = 0;
let currentInverse = false;
for (let x = 0; x < terminal.cols; x++) {
const modelIndex = ((y * terminal.cols) + x) * RENDER_MODEL_INDICIES_PER_CELL;
const bg = model.cells[modelIndex + RENDER_MODEL_BG_OFFSET];
const fg = model.cells[modelIndex + RENDER_MODEL_FG_OFFSET];
const inverse = !!(fg & FgFlags.INVERSE);
if (bg !== currentBg || (fg !== currentFg && (currentInverse || inverse))) {
// A rectangle needs to be drawn if going from non-default to another color
if (currentBg !== 0 || (currentInverse && currentFg !== 0)) {
const offset = rectangleCount++ * INDICES_PER_RECTANGLE;
this._updateRectangle(vertices, offset, currentFg, currentBg, currentStartX, x, y);
}
currentStartX = x;
currentBg = bg;
currentFg = fg;
currentInverse = inverse;
}
}
// Finish rectangle if it's still going
if (currentBg !== 0 || (currentInverse && currentFg !== 0)) {
const offset = rectangleCount++ * INDICES_PER_RECTANGLE;
this._updateRectangle(vertices, offset, currentFg, currentBg, currentStartX, terminal.cols, y);
}
}
vertices.count = rectangleCount;
}
private _updateRectangle(vertices: IVertices, offset: number, fg: number, bg: number, startX: number, endX: number, y: number): void {
let rgba: number | undefined;
if (fg & FgFlags.INVERSE) {
switch (fg & Attributes.CM_MASK) {
case Attributes.CM_P16:
case Attributes.CM_P256:
rgba = this._colors.ansi[fg & Attributes.PCOLOR_MASK].rgba;
break;
case Attributes.CM_RGB:
rgba = (fg & Attributes.RGB_MASK) << 8;
break;
case Attributes.CM_DEFAULT:
default:
rgba = this._colors.foreground.rgba;
}
} else {
switch (bg & Attributes.CM_MASK) {
case Attributes.CM_P16:
case Attributes.CM_P256:
rgba = this._colors.ansi[bg & Attributes.PCOLOR_MASK].rgba;
break;
case Attributes.CM_RGB:
rgba = (bg & Attributes.RGB_MASK) << 8;
break;
case Attributes.CM_DEFAULT:
default:
rgba = this._colors.background.rgba;
}
}
if (vertices.attributes.length < offset + 4) {
vertices.attributes = expandFloat32Array(vertices.attributes, this._terminal.rows * this._terminal.cols * INDICES_PER_RECTANGLE);
}
const x1 = startX * this._dimensions.scaledCellWidth;
const y1 = y * this._dimensions.scaledCellHeight;
const r = ((rgba >> 24) & 0xFF) / 255;
const g = ((rgba >> 16) & 0xFF) / 255;
const b = ((rgba >> 8 ) & 0xFF) / 255;
this._addRectangle(vertices.attributes, offset, x1, y1, (endX - startX) * this._dimensions.scaledCellWidth, this._dimensions.scaledCellHeight, r, g, b, 1);
}
private _addRectangle(array: Float32Array, offset: number, x1: number, y1: number, width: number, height: number, r: number, g: number, b: number, a: number): void {
array[offset ] = x1;
array[offset + 1] = y1;
array[offset + 2] = width;
array[offset + 3] = height;
array[offset + 4] = r;
array[offset + 5] = g;
array[offset + 6] = b;
array[offset + 7] = a;
}
private _addRectangleFloat(array: Float32Array, offset: number, x1: number, y1: number, width: number, height: number, color: Float32Array): void {
array[offset ] = x1;
array[offset + 1] = y1;
array[offset + 2] = width;
array[offset + 3] = height;
array[offset + 4] = color[0];
array[offset + 5] = color[1];
array[offset + 6] = color[2];
array[offset + 7] = color[3];
}
private _colorToFloat32Array(color: IColor): Float32Array {
return new Float32Array([
((color.rgba >> 24) & 0xFF) / 255,
((color.rgba >> 16) & 0xFF) / 255,
((color.rgba >> 8 ) & 0xFF) / 255,
((color.rgba ) & 0xFF) / 255
]);
}
}
@@ -0,0 +1,57 @@
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { IRenderModel, ISelectionRenderModel } from './Types';
import { fill } from 'common/TypedArrayUtils';
export const RENDER_MODEL_INDICIES_PER_CELL = 3;
export const RENDER_MODEL_BG_OFFSET = 1;
export const RENDER_MODEL_FG_OFFSET = 2;
export const COMBINED_CHAR_BIT_MASK = 0x80000000;
export class RenderModel implements IRenderModel {
public cells: Uint32Array;
public lineLengths: Uint32Array;
public selection: ISelectionRenderModel;
constructor() {
this.cells = new Uint32Array(0);
this.lineLengths = new Uint32Array(0);
this.selection = {
hasSelection: false,
viewportStartRow: 0,
viewportEndRow: 0,
viewportCappedStartRow: 0,
viewportCappedEndRow: 0,
startCol: 0,
endCol: 0
};
}
public resize(cols: number, rows: number): void {
const indexCount = cols * rows * RENDER_MODEL_INDICIES_PER_CELL;
if (indexCount !== this.cells.length) {
this.cells = new Uint32Array(indexCount);
this.lineLengths = new Uint32Array(rows);
}
}
public clear(): void {
fill(this.cells, 0, 0);
fill(this.lineLengths, 0, 0);
this.clearSelection();
}
public clearSelection(): void {
this.selection.hasSelection = false;
this.selection.viewportStartRow = 0;
this.selection.viewportEndRow = 0;
this.selection.viewportCappedStartRow = 0;
this.selection.viewportCappedEndRow = 0;
this.selection.startCol = 0;
this.selection.endCol = 0;
}
}
@@ -0,0 +1,120 @@
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { assert } from 'chai';
import { sliceFallback } from './TypedArray';
type TypedArray = Uint8Array | Uint16Array | Uint32Array | Uint8ClampedArray | Int8Array | Int16Array | Int32Array | Float32Array | Float64Array;
function deepEquals(a: TypedArray, b: TypedArray): void {
assert.equal(a.length, b.length);
for (let i = 0; i < a.length; ++i) {
assert.equal(a[i], b[i]);
}
}
describe('polyfill conformance tests', function(): void {
describe('TypedArray.slice', () => {
describe('should work with all typed array types', () => {
it('Uint8Array', () => {
const a = new Uint8Array(5);
deepEquals(sliceFallback(a, 2), a.slice(2));
deepEquals(sliceFallback(a, 65535), a.slice(65535));
deepEquals(sliceFallback(a, -1), a.slice(-1));
});
it('Uint16Array', () => {
const u161 = new Uint16Array(5);
const u162 = new Uint16Array(5);
deepEquals(sliceFallback(u161, 2), u162.slice(2));
deepEquals(sliceFallback(u161, 65535), u162.slice(65535));
deepEquals(sliceFallback(u161, -1), u162.slice(-1));
});
it('Uint32Array', () => {
const u321 = new Uint32Array(5);
const u322 = new Uint32Array(5);
deepEquals(sliceFallback(u321, 2), u322.slice(2));
deepEquals(sliceFallback(u321, 65537), u322.slice(65537));
deepEquals(sliceFallback(u321, -1), u322.slice(-1));
});
it('Int8Array', () => {
const i81 = new Int8Array(5);
const i82 = new Int8Array(5);
deepEquals(sliceFallback(i81, 2), i82.slice(2));
deepEquals(sliceFallback(i81, 65537), i82.slice(65537));
deepEquals(sliceFallback(i81, -1), i82.slice(-1));
});
it('Int16Array', () => {
const i161 = new Int16Array(5);
const i162 = new Int16Array(5);
deepEquals(sliceFallback(i161, 2), i162.slice(2));
deepEquals(sliceFallback(i161, 65535), i162.slice(65535));
deepEquals(sliceFallback(i161, -1), i162.slice(-1));
});
it('Int32Array', () => {
const i321 = new Int32Array(5);
const i322 = new Int32Array(5);
deepEquals(sliceFallback(i321, 2), i322.slice(2));
deepEquals(sliceFallback(i321, 65537), i322.slice(65537));
deepEquals(sliceFallback(i321, -1), i322.slice(-1));
});
it('Float32Array', () => {
const f321 = new Float32Array(5);
const f322 = new Float32Array(5);
deepEquals(sliceFallback(f321, 2), f322.slice(2));
deepEquals(sliceFallback(f321, 65537), f322.slice(65537));
deepEquals(sliceFallback(f321, -1), f322.slice(-1));
});
it('Float64Array', () => {
const f641 = new Float64Array(5);
const f642 = new Float64Array(5);
deepEquals(sliceFallback(f641, 2), f642.slice(2));
deepEquals(sliceFallback(f641, 65537), f642.slice(65537));
deepEquals(sliceFallback(f641, -1), f642.slice(-1));
});
it('Uint8ClampedArray', () => {
const u8Clamped1 = new Uint8ClampedArray(5);
const u8Clamped2 = new Uint8ClampedArray(5);
deepEquals(sliceFallback(u8Clamped1, 2), u8Clamped2.slice(2));
deepEquals(sliceFallback(u8Clamped1, 65537), u8Clamped2.slice(65537));
deepEquals(sliceFallback(u8Clamped1, -1), u8Clamped2.slice(-1));
});
});
it('start', () => {
const arr = new Uint32Array([1, 2, 3, 4, 5]);
deepEquals(sliceFallback(arr, -1), arr.slice(-1));
deepEquals(sliceFallback(arr, 0), arr.slice(0));
deepEquals(sliceFallback(arr, 1), arr.slice(1));
deepEquals(sliceFallback(arr, 2), arr.slice(2));
deepEquals(sliceFallback(arr, 3), arr.slice(3));
deepEquals(sliceFallback(arr, 4), arr.slice(4));
deepEquals(sliceFallback(arr, 5), arr.slice(5));
});
it('end', () => {
const arr = new Uint32Array([1, 2, 3, 4, 5]);
deepEquals(sliceFallback(arr, -1, -2), arr.slice(-1, -2));
deepEquals(sliceFallback(arr, 0, -2), arr.slice(0, -2));
deepEquals(sliceFallback(arr, 1, -2), arr.slice(1, -2));
deepEquals(sliceFallback(arr, 2, -2), arr.slice(2, -2));
deepEquals(sliceFallback(arr, 3, -2), arr.slice(3, -2));
deepEquals(sliceFallback(arr, 4, -2), arr.slice(4, -2));
deepEquals(sliceFallback(arr, 5, -2), arr.slice(5, -2));
deepEquals(sliceFallback(arr, -1, 3), arr.slice(-1, 3));
deepEquals(sliceFallback(arr, 0, 3), arr.slice(0, 3));
deepEquals(sliceFallback(arr, 1, 3), arr.slice(1, 3));
deepEquals(sliceFallback(arr, 2, 3), arr.slice(2, 3));
deepEquals(sliceFallback(arr, 3, 3), arr.slice(3, 3));
deepEquals(sliceFallback(arr, 4, 3), arr.slice(4, 3));
deepEquals(sliceFallback(arr, 5, 3), arr.slice(5, 3));
deepEquals(sliceFallback(arr, -1, 8), arr.slice(-1, 8));
deepEquals(sliceFallback(arr, 0, 8), arr.slice(0, 8));
deepEquals(sliceFallback(arr, 1, 8), arr.slice(1, 8));
deepEquals(sliceFallback(arr, 2, 8), arr.slice(2, 8));
deepEquals(sliceFallback(arr, 3, 8), arr.slice(3, 8));
deepEquals(sliceFallback(arr, 4, 8), arr.slice(4, 8));
deepEquals(sliceFallback(arr, 5, 8), arr.slice(5, 8));
});
});
});
@@ -0,0 +1,32 @@
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
export type TypedArray = Uint8Array | Uint16Array | Uint32Array | Uint8ClampedArray | Int8Array | Int16Array | Int32Array | Float32Array | Float64Array;
export function slice<T extends TypedArray>(array: T, start?: number, end?: number): T {
// all modern engines that support .slice
if (array.slice) {
return array.slice(start, end) as T;
}
return sliceFallback(array, start, end);
}
export function sliceFallback<T extends TypedArray>(array: T, start: number = 0, end: number = array.length): T {
if (start < 0) {
start = (array.length + start) % array.length;
}
if (end >= array.length) {
end = array.length;
} else {
end = (array.length + end) % array.length;
}
start = Math.min(start, end);
const result: T = new (array.constructor as any)(end - start);
for (let i = 0; i < end - start; ++i) {
result[i] = array[i + start];
}
return result;
}
+75
View File
@@ -0,0 +1,75 @@
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
export interface IRasterizedGlyphSet {
[bg: number]: { [fg: number]: IRasterizedGlyph } | undefined;
}
/**
* Represents a rasterized glyph within a texture atlas. Some numbers are
* tracked in CSS pixels as well in order to reduce calculations during the
* render loop.
*/
export interface IRasterizedGlyph {
/**
* The x and y offset between the glyph's top/left and the top/left of a cell
* in pixels.
*/
offset: IVector;
/**
* the x and y position of the glyph in the texture in pixels.
*/
texturePosition: IVector;
/**
* the x and y position of the glyph in the texture in clip space coordinates.
*/
texturePositionClipSpace: IVector;
/**
* The width and height of the glyph in the texture in pixels.
*/
size: IVector;
/**
* The width and height of the glyph in the texture in clip space coordinates.
*/
sizeClipSpace: IVector;
}
export interface IVector {
x: number;
y: number;
}
export interface IBoundingBox {
top: number;
left: number;
right: number;
bottom: number;
}
export interface IRenderModel {
cells: Uint32Array;
lineLengths: Uint32Array;
selection: ISelectionRenderModel;
}
export interface ISelectionRenderModel {
hasSelection: boolean;
viewportStartRow: number;
viewportEndRow: number;
viewportCappedStartRow: number;
viewportCappedEndRow: number;
startCol: number;
endCol: number;
}
export interface IWebGL2RenderingContext extends WebGLRenderingContext {
vertexAttribDivisor(index: number, divisor: number): void;
createVertexArray(): IWebGLVertexArrayObject;
bindVertexArray(vao: IWebGLVertexArrayObject): void;
drawElementsInstanced(mode: number, count: number, type: number, offset: number, instanceCount: number): void;
}
export interface IWebGLVertexArrayObject {
}
@@ -0,0 +1,43 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { Terminal, ITerminalAddon } from 'xterm';
import { WebglRenderer } from './WebglRenderer';
import { IRenderService } from 'browser/services/Services';
import { IColorSet } from 'browser/Types';
export class WebglAddon implements ITerminalAddon {
private _terminal?: Terminal;
private _renderer?: WebglRenderer;
constructor(
private _preserveDrawingBuffer?: boolean
) {}
public activate(terminal: Terminal): void {
if (!terminal.element) {
throw new Error('Cannot activate WebglAddon before Terminal.open');
}
this._terminal = terminal;
const renderService: IRenderService = (<any>terminal)._core._renderService;
const colors: IColorSet = (<any>terminal)._core._colorManager.colors;
this._renderer = new WebglRenderer(terminal, colors, this._preserveDrawingBuffer);
renderService.setRenderer(this._renderer);
}
public dispose(): void {
if (!this._terminal) {
throw new Error('Cannot dispose WebglAddon because it is activated');
}
const renderService: IRenderService = (this._terminal as any)._core._renderService;
renderService.setRenderer((this._terminal as any)._core._createRenderer());
renderService.onResize(this._terminal.cols, this._terminal.rows);
this._renderer = undefined;
}
public get textureAtlas(): HTMLCanvasElement | undefined {
return this._renderer?.textureAtlas;
}
}
@@ -0,0 +1,931 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { ITerminalOptions } from '../../../src/Types';
import { ITheme } from 'xterm';
import { assert } from 'chai';
import { openTerminal, pollFor, writeSync, getBrowserType } from '../../../out-test/api/TestUtils';
import { Browser, Page } from 'playwright-core';
const APP = 'http://127.0.0.1:3000/test';
let browser: Browser;
let page: Page;
const width = 800;
const height = 600;
let itWebgl: (expectation: string, callback?: (this: Mocha.ITestCallbackContext, done: MochaDone) => any) => Mocha.ITest | void;
describe('WebGL Renderer Integration Tests', async () => {
const browserType = getBrowserType();
const isHeadless = process.argv.indexOf('--headless') !== -1;
// Firefox works only in non-headless mode https://github.com/microsoft/playwright/issues/1032
const areTestsEnabled = browserType.name() === 'chromium' || (browserType.name() === 'firefox' && !isHeadless);
itWebgl = areTestsEnabled ? it : it.skip;
itWebgl('dispose removes renderer canvases', async function(): Promise<void> {
await setupBrowser();
assert.equal(await page.evaluate(`document.querySelectorAll('.xterm canvas').length`), 3);
await page.evaluate(`addon.dispose()`);
assert.equal(await page.evaluate(`document.querySelectorAll('.xterm canvas').length`), 0);
await browser.close();
});
describe('colors', () => {
if (areTestsEnabled) {
before(async () => setupBrowser());
after(async () => browser.close());
beforeEach(async () => page.evaluate(`window.term.reset()`));
}
itWebgl('foreground 0-15', async () => {
const theme: ITheme = {
black: '#010203',
red: '#040506',
green: '#070809',
yellow: '#0a0b0c',
blue: '#0d0e0f',
magenta: '#101112',
cyan: '#131415',
white: '#161718'
};
await page.evaluate(`window.term.setOption('theme', ${JSON.stringify(theme)});`);
await writeSync(page, `\\x1b[30m█\\x1b[31m█\\x1b[32m█\\x1b[33m█\\x1b[34m█\\x1b[35m█\\x1b[36m█\\x1b[37m█`);
await pollFor(page, () => getCellColor(1, 1), [1, 2, 3, 255]);
await pollFor(page, () => getCellColor(2, 1), [4, 5, 6, 255]);
await pollFor(page, () => getCellColor(3, 1), [7, 8, 9, 255]);
await pollFor(page, () => getCellColor(4, 1), [10, 11, 12, 255]);
await pollFor(page, () => getCellColor(5, 1), [13, 14, 15, 255]);
await pollFor(page, () => getCellColor(6, 1), [16, 17, 18, 255]);
await pollFor(page, () => getCellColor(7, 1), [19, 20, 21, 255]);
await pollFor(page, () => getCellColor(8, 1), [22, 23, 24, 255]);
});
itWebgl('foreground 0-7 drawBoldTextInBrightColors', async () => {
const theme: ITheme = {
brightBlack: '#010203',
brightRed: '#040506',
brightGreen: '#070809',
brightYellow: '#0a0b0c',
brightBlue: '#0d0e0f',
brightMagenta: '#101112',
brightCyan: '#131415',
brightWhite: '#161718'
};
await page.evaluate(`
window.term.setOption('theme', ${JSON.stringify(theme)});
window.term.setOption('drawBoldTextInBrightColors', true);
`);
await writeSync(page, `\\x1b[1;30m█\\x1b[1;31m█\\x1b[1;32m█\\x1b[1;33m█\\x1b[1;34m█\\x1b[1;35m█\\x1b[1;36m█\\x1b[1;37m█`);
await pollFor(page, () => getCellColor(1, 1), [1, 2, 3, 255]);
await pollFor(page, () => getCellColor(2, 1), [4, 5, 6, 255]);
await pollFor(page, () => getCellColor(3, 1), [7, 8, 9, 255]);
await pollFor(page, () => getCellColor(4, 1), [10, 11, 12, 255]);
await pollFor(page, () => getCellColor(5, 1), [13, 14, 15, 255]);
await pollFor(page, () => getCellColor(6, 1), [16, 17, 18, 255]);
await pollFor(page, () => getCellColor(7, 1), [19, 20, 21, 255]);
await pollFor(page, () => getCellColor(8, 1), [22, 23, 24, 255]);
});
itWebgl('background 0-15', async () => {
const theme: ITheme = {
black: '#010203',
red: '#040506',
green: '#070809',
yellow: '#0a0b0c',
blue: '#0d0e0f',
magenta: '#101112',
cyan: '#131415',
white: '#161718'
};
await page.evaluate(`window.term.setOption('theme', ${JSON.stringify(theme)});`);
await writeSync(page, `\\x1b[40m \\x1b[41m \\x1b[42m \\x1b[43m \\x1b[44m \\x1b[45m \\x1b[46m \\x1b[47m `);
await pollFor(page, () => getCellColor(1, 1), [1, 2, 3, 255]);
await pollFor(page, () => getCellColor(2, 1), [4, 5, 6, 255]);
await pollFor(page, () => getCellColor(3, 1), [7, 8, 9, 255]);
await pollFor(page, () => getCellColor(4, 1), [10, 11, 12, 255]);
await pollFor(page, () => getCellColor(5, 1), [13, 14, 15, 255]);
await pollFor(page, () => getCellColor(6, 1), [16, 17, 18, 255]);
await pollFor(page, () => getCellColor(7, 1), [19, 20, 21, 255]);
await pollFor(page, () => getCellColor(8, 1), [22, 23, 24, 255]);
});
itWebgl('foreground 0-15 inverse', async () => {
const theme: ITheme = {
black: '#010203',
red: '#040506',
green: '#070809',
yellow: '#0a0b0c',
blue: '#0d0e0f',
magenta: '#101112',
cyan: '#131415',
white: '#161718'
};
await page.evaluate(`window.term.setOption('theme', ${JSON.stringify(theme)});`);
await writeSync(page, `\\x1b[7;30m \\x1b[7;31m \\x1b[7;32m \\x1b[7;33m \\x1b[7;34m \\x1b[7;35m \\x1b[7;36m \\x1b[7;37m `);
await pollFor(page, () => getCellColor(1, 1), [1, 2, 3, 255]);
await pollFor(page, () => getCellColor(2, 1), [4, 5, 6, 255]);
await pollFor(page, () => getCellColor(3, 1), [7, 8, 9, 255]);
await pollFor(page, () => getCellColor(4, 1), [10, 11, 12, 255]);
await pollFor(page, () => getCellColor(5, 1), [13, 14, 15, 255]);
await pollFor(page, () => getCellColor(6, 1), [16, 17, 18, 255]);
await pollFor(page, () => getCellColor(7, 1), [19, 20, 21, 255]);
await pollFor(page, () => getCellColor(8, 1), [22, 23, 24, 255]);
});
itWebgl('background 0-15 inverse', async () => {
const theme: ITheme = {
black: '#010203',
red: '#040506',
green: '#070809',
yellow: '#0a0b0c',
blue: '#0d0e0f',
magenta: '#101112',
cyan: '#131415',
white: '#161718'
};
await page.evaluate(`window.term.setOption('theme', ${JSON.stringify(theme)});`);
await writeSync(page, `\\x1b[7;40m█\\x1b[7;41m█\\x1b[7;42m█\\x1b[7;43m█\\x1b[7;44m█\\x1b[7;45m█\\x1b[7;46m█\\x1b[7;47m█`);
await pollFor(page, () => getCellColor(1, 1), [1, 2, 3, 255]);
await pollFor(page, () => getCellColor(2, 1), [4, 5, 6, 255]);
await pollFor(page, () => getCellColor(3, 1), [7, 8, 9, 255]);
await pollFor(page, () => getCellColor(4, 1), [10, 11, 12, 255]);
await pollFor(page, () => getCellColor(5, 1), [13, 14, 15, 255]);
await pollFor(page, () => getCellColor(6, 1), [16, 17, 18, 255]);
await pollFor(page, () => getCellColor(7, 1), [19, 20, 21, 255]);
await pollFor(page, () => getCellColor(8, 1), [22, 23, 24, 255]);
});
itWebgl('foreground 0-15 inivisible', async () => {
const theme: ITheme = {
black: '#010203',
red: '#040506',
green: '#070809',
yellow: '#0a0b0c',
blue: '#0d0e0f',
magenta: '#101112',
cyan: '#131415',
white: '#161718'
};
await page.evaluate(`window.term.setOption('theme', ${JSON.stringify(theme)});`);
await writeSync(page, `\\x1b[8;30m \\x1b[8;31m \\x1b[8;32m \\x1b[8;33m \\x1b[8;34m \\x1b[8;35m \\x1b[8;36m \\x1b[8;37m `);
await pollFor(page, () => getCellColor(1, 1), [0, 0, 0, 255]);
await pollFor(page, () => getCellColor(2, 1), [0, 0, 0, 255]);
await pollFor(page, () => getCellColor(3, 1), [0, 0, 0, 255]);
await pollFor(page, () => getCellColor(4, 1), [0, 0, 0, 255]);
await pollFor(page, () => getCellColor(5, 1), [0, 0, 0, 255]);
await pollFor(page, () => getCellColor(6, 1), [0, 0, 0, 255]);
await pollFor(page, () => getCellColor(7, 1), [0, 0, 0, 255]);
await pollFor(page, () => getCellColor(8, 1), [0, 0, 0, 255]);
});
itWebgl('background 0-15 inivisible', async () => {
const theme: ITheme = {
black: '#010203',
red: '#040506',
green: '#070809',
yellow: '#0a0b0c',
blue: '#0d0e0f',
magenta: '#101112',
cyan: '#131415',
white: '#161718'
};
await page.evaluate(`window.term.setOption('theme', ${JSON.stringify(theme)});`);
await writeSync(page, `\\x1b[8;40m█\\x1b[8;41m█\\x1b[8;42m█\\x1b[8;43m█\\x1b[8;44m█\\x1b[8;45m█\\x1b[8;46m█\\x1b[8;47m█`);
await pollFor(page, () => getCellColor(1, 1), [1, 2, 3, 255]);
await pollFor(page, () => getCellColor(2, 1), [4, 5, 6, 255]);
await pollFor(page, () => getCellColor(3, 1), [7, 8, 9, 255]);
await pollFor(page, () => getCellColor(4, 1), [10, 11, 12, 255]);
await pollFor(page, () => getCellColor(5, 1), [13, 14, 15, 255]);
await pollFor(page, () => getCellColor(6, 1), [16, 17, 18, 255]);
await pollFor(page, () => getCellColor(7, 1), [19, 20, 21, 255]);
await pollFor(page, () => getCellColor(8, 1), [22, 23, 24, 255]);
});
itWebgl('foreground 0-15 bright', async () => {
const theme: ITheme = {
brightBlack: '#010203',
brightRed: '#040506',
brightGreen: '#070809',
brightYellow: '#0a0b0c',
brightBlue: '#0d0e0f',
brightMagenta: '#101112',
brightCyan: '#131415',
brightWhite: '#161718'
};
await page.evaluate(`window.term.setOption('theme', ${JSON.stringify(theme)});`);
await writeSync(page, `\\x1b[90m█\\x1b[91m█\\x1b[92m█\\x1b[93m█\\x1b[94m█\\x1b[95m█\\x1b[96m█\\x1b[97m█`);
await pollFor(page, () => getCellColor(1, 1), [1, 2, 3, 255]);
await pollFor(page, () => getCellColor(2, 1), [4, 5, 6, 255]);
await pollFor(page, () => getCellColor(3, 1), [7, 8, 9, 255]);
await pollFor(page, () => getCellColor(4, 1), [10, 11, 12, 255]);
await pollFor(page, () => getCellColor(5, 1), [13, 14, 15, 255]);
await pollFor(page, () => getCellColor(6, 1), [16, 17, 18, 255]);
await pollFor(page, () => getCellColor(7, 1), [19, 20, 21, 255]);
await pollFor(page, () => getCellColor(8, 1), [22, 23, 24, 255]);
});
itWebgl('background 0-15 bright', async () => {
const theme: ITheme = {
brightBlack: '#010203',
brightRed: '#040506',
brightGreen: '#070809',
brightYellow: '#0a0b0c',
brightBlue: '#0d0e0f',
brightMagenta: '#101112',
brightCyan: '#131415',
brightWhite: '#161718'
};
await page.evaluate(`window.term.setOption('theme', ${JSON.stringify(theme)});`);
await writeSync(page, `\\x1b[100m \\x1b[101m \\x1b[102m \\x1b[103m \\x1b[104m \\x1b[105m \\x1b[106m \\x1b[107m `);
await pollFor(page, () => getCellColor(1, 1), [1, 2, 3, 255]);
await pollFor(page, () => getCellColor(2, 1), [4, 5, 6, 255]);
await pollFor(page, () => getCellColor(3, 1), [7, 8, 9, 255]);
await pollFor(page, () => getCellColor(4, 1), [10, 11, 12, 255]);
await pollFor(page, () => getCellColor(5, 1), [13, 14, 15, 255]);
await pollFor(page, () => getCellColor(6, 1), [16, 17, 18, 255]);
await pollFor(page, () => getCellColor(7, 1), [19, 20, 21, 255]);
await pollFor(page, () => getCellColor(8, 1), [22, 23, 24, 255]);
});
itWebgl('foreground 16-255', async () => {
let data = '';
for (let y = 0; y < 240 / 16; y++) {
for (let x = 0; x < 16; x++) {
data += `\\x1b[38;5;${16 + y * 16 + x}m█\x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 240 / 16; y++) {
for (let x = 0; x < 16; x++) {
const cssColor = COLORS_16_TO_255[y * 16 + x];
const r = parseInt(cssColor.substr(1, 2), 16);
const g = parseInt(cssColor.substr(3, 2), 16);
const b = parseInt(cssColor.substr(5, 2), 16);
await pollFor(page, () => getCellColor(x + 1, y + 1), [r, g, b, 255]);
}
}
});
itWebgl('background 16-255', async () => {
let data = '';
for (let y = 0; y < 240 / 16; y++) {
for (let x = 0; x < 16; x++) {
data += `\\x1b[48;5;${16 + y * 16 + x}m \x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 240 / 16; y++) {
for (let x = 0; x < 16; x++) {
const cssColor = COLORS_16_TO_255[y * 16 + x];
const r = parseInt(cssColor.substr(1, 2), 16);
const g = parseInt(cssColor.substr(3, 2), 16);
const b = parseInt(cssColor.substr(5, 2), 16);
await pollFor(page, () => getCellColor(x + 1, y + 1), [r, g, b, 255]);
}
}
});
itWebgl('foreground 16-255 inverse', async () => {
let data = '';
for (let y = 0; y < 240 / 16; y++) {
for (let x = 0; x < 16; x++) {
data += `\\x1b[7;38;5;${16 + y * 16 + x}m \x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 240 / 16; y++) {
for (let x = 0; x < 16; x++) {
const cssColor = COLORS_16_TO_255[y * 16 + x];
const r = parseInt(cssColor.substr(1, 2), 16);
const g = parseInt(cssColor.substr(3, 2), 16);
const b = parseInt(cssColor.substr(5, 2), 16);
await pollFor(page, () => getCellColor(x + 1, y + 1), [r, g, b, 255]);
}
}
});
itWebgl('background 16-255 inverse', async () => {
let data = '';
for (let y = 0; y < 240 / 16; y++) {
for (let x = 0; x < 16; x++) {
data += `\\x1b[7;48;5;${16 + y * 16 + x}m█\x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 240 / 16; y++) {
for (let x = 0; x < 16; x++) {
const cssColor = COLORS_16_TO_255[y * 16 + x];
const r = parseInt(cssColor.substr(1, 2), 16);
const g = parseInt(cssColor.substr(3, 2), 16);
const b = parseInt(cssColor.substr(5, 2), 16);
await pollFor(page, () => getCellColor(x + 1, y + 1), [r, g, b, 255]);
}
}
});
itWebgl('foreground 16-255 invisible', async () => {
let data = '';
for (let y = 0; y < 240 / 16; y++) {
for (let x = 0; x < 16; x++) {
data += `\\x1b[8;38;5;${16 + y * 16 + x}m \x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 240 / 16; y++) {
for (let x = 0; x < 16; x++) {
const cssColor = COLORS_16_TO_255[y * 16 + x];
const r = parseInt(cssColor.substr(1, 2), 16);
const g = parseInt(cssColor.substr(3, 2), 16);
const b = parseInt(cssColor.substr(5, 2), 16);
await pollFor(page, () => getCellColor(x + 1, y + 1), [0, 0, 0, 255]);
}
}
});
itWebgl('background 16-255 invisible', async () => {
let data = '';
for (let y = 0; y < 240 / 16; y++) {
for (let x = 0; x < 16; x++) {
data += `\\x1b[8;48;5;${16 + y * 16 + x}m█\x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 240 / 16; y++) {
for (let x = 0; x < 16; x++) {
const cssColor = COLORS_16_TO_255[y * 16 + x];
const r = parseInt(cssColor.substr(1, 2), 16);
const g = parseInt(cssColor.substr(3, 2), 16);
const b = parseInt(cssColor.substr(5, 2), 16);
await pollFor(page, () => getCellColor(x + 1, y + 1), [r, g, b, 255]);
}
}
});
itWebgl('foreground true color red', async () => {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\\x1b[38;2;${i};0;0m█\x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [i, 0, 0, 255]);
}
}
});
itWebgl('background true color red', async () => {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\\x1b[48;2;${i};0;0m \x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [i, 0, 0, 255]);
}
}
});
itWebgl('foreground true color green', async () => {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\\x1b[38;2;0;${i};0m█\x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [0, i, 0, 255]);
}
}
});
itWebgl('background true color green', async () => {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\\x1b[48;2;0;${i};0m \x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [0, i, 0, 255]);
}
}
});
itWebgl('foreground true color blue', async () => {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\\x1b[38;2;0;0;${i}m█\x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [0, 0, i, 255]);
}
}
});
itWebgl('background true color blue', async () => {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\\x1b[48;2;0;0;${i}m \x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [0, 0, i, 255]);
}
}
});
itWebgl('foreground true color grey', async () => {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\\x1b[38;2;${i};${i};${i}m█\x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [i, i, i, 255]);
}
}
});
itWebgl('background true color grey', async () => {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\\x1b[48;2;${i};${i};${i}m \x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [i, i, i, 255]);
}
}
});
itWebgl('foreground true color red inverse', async function(): Promise<void> {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\x1b[7;38;2;${i};0;0m \x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [i, 0, 0, 255]);
}
}
});
itWebgl('background true color red inverse', async function(): Promise<void> {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\\x1b[7;48;2;${i};0;0m█\\x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [i, 0, 0, 255]);
}
}
});
itWebgl('foreground true color green inverse', async () => {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\\x1b[7;38;2;0;${i};0m \x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [0, i, 0, 255]);
}
}
});
itWebgl('background true color green inverse', async () => {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\\x1b[7;48;2;0;${i};0m█\x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [0, i, 0, 255]);
}
}
});
itWebgl('foreground true color blue inverse', async () => {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\\x1b[7;38;2;0;0;${i}m \x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [0, 0, i, 255]);
}
}
});
itWebgl('background true color blue inverse', async () => {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\\x1b[7;48;2;0;0;${i}m█\x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [0, 0, i, 255]);
}
}
});
itWebgl('foreground true color grey inverse', async () => {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\\x1b[7;38;2;${i};${i};${i}m \x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [i, i, i, 255]);
}
}
});
itWebgl('background true color grey inverse', async () => {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\\x1b[7;48;2;${i};${i};${i}m█\x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [i, i, i, 255]);
}
}
});
itWebgl('foreground true color grey invisible', async () => {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\\x1b[8;38;2;${i};${i};${i}m \x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [0, 0, 0, 255]);
}
}
});
itWebgl('background true color grey invisible', async () => {
let data = '';
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
data += `\\x1b[8;48;2;${i};${i};${i}m█\x1b[0m`;
}
data += '\\r\\n';
}
await writeSync(page, data);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(page, () => getCellColor(x + 1, y + 1), [i, i, i, 255]);
}
}
});
});
describe('minimumContrastRatio', async () => {
if (areTestsEnabled) {
before(async () => setupBrowser());
after(async () => browser.close());
beforeEach(async () => page.evaluate(`window.term.reset()`));
}
itWebgl('should adjust 0-15 colors on black background', async () => {
const theme: ITheme = {
black: '#2e3436',
red: '#cc0000',
green: '#4e9a06',
yellow: '#c4a000',
blue: '#3465a4',
magenta: '#75507b',
cyan: '#06989a',
white: '#d3d7cf',
brightBlack: '#555753',
brightRed: '#ef2929',
brightGreen: '#8ae234',
brightYellow: '#fce94f',
brightBlue: '#729fcf',
brightMagenta: '#ad7fa8',
brightCyan: '#34e2e2',
brightWhite: '#eeeeec'
};
await page.evaluate(`
window.term.setOption('theme', ${JSON.stringify(theme)});
window.term.setOption('minimumContrastRatio', 1);
`);
await writeSync(page,
`\\x1b[30m█\\x1b[31m█\\x1b[32m█\\x1b[33m█\\x1b[34m█\\x1b[35m█\\x1b[36m█\\x1b[37m█\\r\\n` +
`\\x1b[90m█\\x1b[91m█\\x1b[92m█\\x1b[93m█\\x1b[94m█\\x1b[95m█\\x1b[96m█\\x1b[97m█`
);
// Validate before minimumContrastRatio is applied
await pollFor(page, () => getCellColor(1, 1), [0x2e, 0x34, 0x36, 255]);
await pollFor(page, () => getCellColor(2, 1), [0xcc, 0x00, 0x00, 255]);
await pollFor(page, () => getCellColor(3, 1), [0x4e, 0x9a, 0x06, 255]);
await pollFor(page, () => getCellColor(4, 1), [0xc4, 0xa0, 0x00, 255]);
await pollFor(page, () => getCellColor(5, 1), [0x34, 0x65, 0xa4, 255]);
await pollFor(page, () => getCellColor(6, 1), [0x75, 0x50, 0x7b, 255]);
await pollFor(page, () => getCellColor(7, 1), [0x06, 0x98, 0x9a, 255]);
await pollFor(page, () => getCellColor(8, 1), [0xd3, 0xd7, 0xcf, 255]);
await pollFor(page, () => getCellColor(1, 2), [0x55, 0x57, 0x53, 255]);
await pollFor(page, () => getCellColor(2, 2), [0xef, 0x29, 0x29, 255]);
await pollFor(page, () => getCellColor(3, 2), [0x8a, 0xe2, 0x34, 255]);
await pollFor(page, () => getCellColor(4, 2), [0xfc, 0xe9, 0x4f, 255]);
await pollFor(page, () => getCellColor(5, 2), [0x72, 0x9f, 0xcf, 255]);
await pollFor(page, () => getCellColor(6, 2), [0xad, 0x7f, 0xa8, 255]);
await pollFor(page, () => getCellColor(7, 2), [0x34, 0xe2, 0xe2, 255]);
await pollFor(page, () => getCellColor(8, 2), [0xee, 0xee, 0xec, 255]);
// Setting and check for minimum contrast values, note that these are note
// exact to the contrast ratio, if the increase luminance algorithm
// changes then these will probably fail
await page.evaluate(`window.term.setOption('minimumContrastRatio', 10);`);
await pollFor(page, () => getCellColor(1, 1), [176, 180, 180, 255]);
await pollFor(page, () => getCellColor(2, 1), [238, 158, 158, 255]);
await pollFor(page, () => getCellColor(3, 1), [197, 223, 171, 255]);
await pollFor(page, () => getCellColor(4, 1), [235, 221, 158, 255]);
await pollFor(page, () => getCellColor(5, 1), [124, 156, 198, 255]);
await pollFor(page, () => getCellColor(6, 1), [183, 165, 187, 255]);
await pollFor(page, () => getCellColor(7, 1), [110, 197, 198, 255]);
await pollFor(page, () => getCellColor(8, 1), [211, 215, 207, 255]);
await pollFor(page, () => getCellColor(1, 2), [183, 185, 183, 255]);
await pollFor(page, () => getCellColor(2, 2), [249, 156, 156, 255]);
await pollFor(page, () => getCellColor(3, 2), [138, 226, 52, 255]);
await pollFor(page, () => getCellColor(4, 2), [252, 233, 79, 255]);
await pollFor(page, () => getCellColor(5, 2), [114, 159, 207, 255]);
await pollFor(page, () => getCellColor(6, 2), [190, 152, 185, 255]);
// Unchanged
await pollFor(page, () => getCellColor(7, 2), [0x34, 0xe2, 0xe2, 255]);
await pollFor(page, () => getCellColor(8, 2), [0xee, 0xee, 0xec, 255]);
});
itWebgl('should adjust 0-15 colors on white background', async () => {
const theme: ITheme = {
background: '#ffffff',
black: '#2e3436',
red: '#cc0000',
green: '#4e9a06',
yellow: '#c4a000',
blue: '#3465a4',
magenta: '#75507b',
cyan: '#06989a',
white: '#d3d7cf',
brightBlack: '#555753',
brightRed: '#ef2929',
brightGreen: '#8ae234',
brightYellow: '#fce94f',
brightBlue: '#729fcf',
brightMagenta: '#ad7fa8',
brightCyan: '#34e2e2',
brightWhite: '#eeeeec'
};
await page.evaluate(`
window.term.setOption('theme', ${JSON.stringify(theme)});
window.term.setOption('minimumContrastRatio', 1);
`);
await writeSync(page,
`\\x1b[30m█\\x1b[31m█\\x1b[32m█\\x1b[33m█\\x1b[34m█\\x1b[35m█\\x1b[36m█\\x1b[37m█\\r\\n` +
`\\x1b[90m█\\x1b[91m█\\x1b[92m█\\x1b[93m█\\x1b[94m█\\x1b[95m█\\x1b[96m█\\x1b[97m█`
);
// Validate before minimumContrastRatio is applied
await pollFor(page, () => getCellColor(1, 1), [0x2e, 0x34, 0x36, 255]);
await pollFor(page, () => getCellColor(2, 1), [0xcc, 0x00, 0x00, 255]);
await pollFor(page, () => getCellColor(3, 1), [0x4e, 0x9a, 0x06, 255]);
await pollFor(page, () => getCellColor(4, 1), [0xc4, 0xa0, 0x00, 255]);
await pollFor(page, () => getCellColor(5, 1), [0x34, 0x65, 0xa4, 255]);
await pollFor(page, () => getCellColor(6, 1), [0x75, 0x50, 0x7b, 255]);
await pollFor(page, () => getCellColor(7, 1), [0x06, 0x98, 0x9a, 255]);
await pollFor(page, () => getCellColor(8, 1), [0xd3, 0xd7, 0xcf, 255]);
await pollFor(page, () => getCellColor(1, 2), [0x55, 0x57, 0x53, 255]);
await pollFor(page, () => getCellColor(2, 2), [0xef, 0x29, 0x29, 255]);
await pollFor(page, () => getCellColor(3, 2), [0x8a, 0xe2, 0x34, 255]);
await pollFor(page, () => getCellColor(4, 2), [0xfc, 0xe9, 0x4f, 255]);
await pollFor(page, () => getCellColor(5, 2), [0x72, 0x9f, 0xcf, 255]);
await pollFor(page, () => getCellColor(6, 2), [0xad, 0x7f, 0xa8, 255]);
await pollFor(page, () => getCellColor(7, 2), [0x34, 0xe2, 0xe2, 255]);
await pollFor(page, () => getCellColor(8, 2), [0xee, 0xee, 0xec, 255]);
// Setting and check for minimum contrast values, note that these are note
// exact to the contrast ratio, if the increase luminance algorithm
// changes then these will probably fail
await page.evaluate(`window.term.setOption('minimumContrastRatio', 10);`);
await pollFor(page, () => getCellColor(1, 1), [46, 52, 54, 255]);
await pollFor(page, () => getCellColor(2, 1), [132, 0, 0, 255]);
await pollFor(page, () => getCellColor(3, 1), [78, 154, 6, 255]);
await pollFor(page, () => getCellColor(4, 1), [114, 93, 0, 255]);
await pollFor(page, () => getCellColor(5, 1), [19, 40, 68, 255]);
await pollFor(page, () => getCellColor(6, 1), [60, 40, 64, 255]);
await pollFor(page, () => getCellColor(7, 1), [0, 71, 72, 255]);
await pollFor(page, () => getCellColor(8, 1), [64, 64, 63, 255]);
await pollFor(page, () => getCellColor(1, 2), [61, 63, 59, 255]);
await pollFor(page, () => getCellColor(2, 2), [125, 19, 19, 255]);
await pollFor(page, () => getCellColor(3, 2), [89, 146, 32, 255]);
await pollFor(page, () => getCellColor(4, 2), [105, 98, 32, 255]);
await pollFor(page, () => getCellColor(5, 2), [36, 52, 70, 255]);
await pollFor(page, () => getCellColor(6, 2), [64, 45, 63, 255]);
await pollFor(page, () => getCellColor(7, 2), [13, 67, 67, 255]);
await pollFor(page, () => getCellColor(8, 2), [64, 64, 64, 255]);
});
});
describe('selection', async () => {
if (areTestsEnabled) {
before(async () => setupBrowser());
after(async () => browser.close());
beforeEach(async () => page.evaluate(`window.term.reset()`));
}
itWebgl('should resolve the inverse foreground color based on the original background color, not the selection', async () => {
const theme: ITheme = {
foreground: '#FF0000',
background: '#00FF00',
selection: '#0000FF'
};
await page.evaluate(`window.term.setOption('theme', ${JSON.stringify(theme)});`);
await writeSync(page, ` █\\x1b[7m█\\x1b[0m`);
await pollFor(page, () => getCellColor(1, 1), [0, 255, 0, 255]);
await pollFor(page, () => getCellColor(2, 1), [255, 0, 0, 255]);
await pollFor(page, () => getCellColor(3, 1), [0, 255, 0, 255]);
await page.evaluate(`window.term.selectAll()`);
// Selection only cell needs to be first to ensure renderer has kicked in
await pollFor(page, () => getCellColor(1, 1), [0, 0, 255, 255]);
await pollFor(page, () => getCellColor(2, 1), [255, 0, 0, 255]);
await pollFor(page, () => getCellColor(3, 1), [0, 255, 0, 255]);
});
});
describe('allowTransparency', async () => {
if (areTestsEnabled) {
before(async () => setupBrowser({ rendererType: 'dom', allowTransparency: true }));
after(async () => browser.close());
beforeEach(async () => page.evaluate(`window.term.reset()`));
}
itWebgl('transparent background inverse', async () => {
const theme: ITheme = {
background: '#ff000080'
};
await page.evaluate(`window.term.setOption('theme', ${JSON.stringify(theme)});`);
const data = `\\x1b[7m█\x1b[0m`;
await writeSync(page, data);
// Inverse background should be opaque
await pollFor(page, () => getCellColor(1, 1), [255, 0, 0, 255]);
});
});
});
async function getCellColor(col: number, row: number): Promise<number[]> {
await page.evaluate(`
window.gl = window.term._core._renderService._renderer._gl;
window.result = new Uint8Array(4);
window.d = window.term._core._renderService.dimensions;
window.gl.readPixels(
Math.floor((${col - 0.5}) * window.d.scaledCellWidth),
Math.floor(window.gl.drawingBufferHeight - 1 - (${row - 0.5}) * window.d.scaledCellHeight),
1, 1, window.gl.RGBA, window.gl.UNSIGNED_BYTE, window.result
);
`);
return await page.evaluate(`Array.from(window.result)`);
}
async function setupBrowser(options: ITerminalOptions = { rendererType: 'dom' }): Promise<void> {
const browserType = getBrowserType();
browser = await browserType.launch({ dumpio: true,
headless: process.argv.indexOf('--headless') !== -1
});
page = await (await browser.newContext()).newPage();
await page.setViewportSize({ width, height });
await page.goto(APP);
await openTerminal(page, options);
await page.evaluate(`
window.addon = new WebglAddon(true);
window.term.loadAddon(window.addon);
`);
}
const COLORS_16_TO_255 = [
'#000000', '#00005f', '#000087', '#0000af', '#0000d7', '#0000ff', '#005f00', '#005f5f', '#005f87', '#005faf', '#005fd7', '#005fff', '#008700', '#00875f', '#008787', '#0087af',
'#0087d7', '#0087ff', '#00af00', '#00af5f', '#00af87', '#00afaf', '#00afd7', '#00afff', '#00d700', '#00d75f', '#00d787', '#00d7af', '#00d7d7', '#00d7ff', '#00ff00', '#00ff5f',
'#00ff87', '#00ffaf', '#00ffd7', '#00ffff', '#5f0000', '#5f005f', '#5f0087', '#5f00af', '#5f00d7', '#5f00ff', '#5f5f00', '#5f5f5f', '#5f5f87', '#5f5faf', '#5f5fd7', '#5f5fff',
'#5f8700', '#5f875f', '#5f8787', '#5f87af', '#5f87d7', '#5f87ff', '#5faf00', '#5faf5f', '#5faf87', '#5fafaf', '#5fafd7', '#5fafff', '#5fd700', '#5fd75f', '#5fd787', '#5fd7af',
'#5fd7d7', '#5fd7ff', '#5fff00', '#5fff5f', '#5fff87', '#5fffaf', '#5fffd7', '#5fffff', '#870000', '#87005f', '#870087', '#8700af', '#8700d7', '#8700ff', '#875f00', '#875f5f',
'#875f87', '#875faf', '#875fd7', '#875fff', '#878700', '#87875f', '#878787', '#8787af', '#8787d7', '#8787ff', '#87af00', '#87af5f', '#87af87', '#87afaf', '#87afd7', '#87afff',
'#87d700', '#87d75f', '#87d787', '#87d7af', '#87d7d7', '#87d7ff', '#87ff00', '#87ff5f', '#87ff87', '#87ffaf', '#87ffd7', '#87ffff', '#af0000', '#af005f', '#af0087', '#af00af',
'#af00d7', '#af00ff', '#af5f00', '#af5f5f', '#af5f87', '#af5faf', '#af5fd7', '#af5fff', '#af8700', '#af875f', '#af8787', '#af87af', '#af87d7', '#af87ff', '#afaf00', '#afaf5f',
'#afaf87', '#afafaf', '#afafd7', '#afafff', '#afd700', '#afd75f', '#afd787', '#afd7af', '#afd7d7', '#afd7ff', '#afff00', '#afff5f', '#afff87', '#afffaf', '#afffd7', '#afffff',
'#d70000', '#d7005f', '#d70087', '#d700af', '#d700d7', '#d700ff', '#d75f00', '#d75f5f', '#d75f87', '#d75faf', '#d75fd7', '#d75fff', '#d78700', '#d7875f', '#d78787', '#d787af',
'#d787d7', '#d787ff', '#d7af00', '#d7af5f', '#d7af87', '#d7afaf', '#d7afd7', '#d7afff', '#d7d700', '#d7d75f', '#d7d787', '#d7d7af', '#d7d7d7', '#d7d7ff', '#d7ff00', '#d7ff5f',
'#d7ff87', '#d7ffaf', '#d7ffd7', '#d7ffff', '#ff0000', '#ff005f', '#ff0087', '#ff00af', '#ff00d7', '#ff00ff', '#ff5f00', '#ff5f5f', '#ff5f87', '#ff5faf', '#ff5fd7', '#ff5fff',
'#ff8700', '#ff875f', '#ff8787', '#ff87af', '#ff87d7', '#ff87ff', '#ffaf00', '#ffaf5f', '#ffaf87', '#ffafaf', '#ffafd7', '#ffafff', '#ffd700', '#ffd75f', '#ffd787', '#ffd7af',
'#ffd7d7', '#ffd7ff', '#ffff00', '#ffff5f', '#ffff87', '#ffffaf', '#ffffd7', '#ffffff', '#080808', '#121212', '#1c1c1c', '#262626', '#303030', '#3a3a3a', '#444444', '#4e4e4e',
'#585858', '#626262', '#6c6c6c', '#767676', '#808080', '#8a8a8a', '#949494', '#9e9e9e', '#a8a8a8', '#b2b2b2', '#bcbcbc', '#c6c6c6', '#d0d0d0', '#dadada', '#e4e4e4', '#eeeeee'
];
@@ -0,0 +1,396 @@
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { ITerminal } from '../../../src/Types';
import { GlyphRenderer } from './GlyphRenderer';
import { LinkRenderLayer } from './renderLayer/LinkRenderLayer';
import { CursorRenderLayer } from './renderLayer/CursorRenderLayer';
import { acquireCharAtlas } from './atlas/CharAtlasCache';
import { WebglCharAtlas } from './atlas/WebglCharAtlas';
import { RectangleRenderer } from './RectangleRenderer';
import { IWebGL2RenderingContext } from './Types';
import { RenderModel, COMBINED_CHAR_BIT_MASK, RENDER_MODEL_BG_OFFSET, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_INDICIES_PER_CELL } from './RenderModel';
import { Disposable } from 'common/Lifecycle';
import { NULL_CELL_CODE } from 'common/buffer/Constants';
import { Terminal, IEvent } from 'xterm';
import { IRenderLayer } from './renderLayer/Types';
import { IRenderDimensions, IRenderer, IRequestRefreshRowsEvent } from 'browser/renderer/Types';
import { IColorSet } from 'browser/Types';
import { EventEmitter } from 'common/EventEmitter';
import { CellData } from 'common/buffer/CellData';
export class WebglRenderer extends Disposable implements IRenderer {
private _renderLayers: IRenderLayer[];
private _charAtlas: WebglCharAtlas | undefined;
private _devicePixelRatio: number;
private _model: RenderModel = new RenderModel();
private _workCell: CellData = new CellData();
private _canvas: HTMLCanvasElement;
private _gl: IWebGL2RenderingContext;
private _rectangleRenderer: RectangleRenderer;
private _glyphRenderer: GlyphRenderer;
public dimensions: IRenderDimensions;
private _core: ITerminal;
private _isAttached: boolean;
private _onRequestRefreshRows = new EventEmitter<IRequestRefreshRowsEvent>();
public get onRequestRefreshRows(): IEvent<IRequestRefreshRowsEvent> { return this._onRequestRefreshRows.event; }
constructor(
private _terminal: Terminal,
private _colors: IColorSet,
preserveDrawingBuffer?: boolean
) {
super();
this._core = (this._terminal as any)._core;
this._renderLayers = [
new LinkRenderLayer(this._core.screenElement, 2, this._colors, this._core),
new CursorRenderLayer(this._core.screenElement, 3, this._colors, this._onRequestRefreshRows)
];
this.dimensions = {
scaledCharWidth: 0,
scaledCharHeight: 0,
scaledCellWidth: 0,
scaledCellHeight: 0,
scaledCharLeft: 0,
scaledCharTop: 0,
scaledCanvasWidth: 0,
scaledCanvasHeight: 0,
canvasWidth: 0,
canvasHeight: 0,
actualCellWidth: 0,
actualCellHeight: 0
};
this._devicePixelRatio = window.devicePixelRatio;
this._updateDimensions();
this._canvas = document.createElement('canvas');
const contextAttributes = {
antialias: false,
depth: false,
preserveDrawingBuffer
};
this._gl = this._canvas.getContext('webgl2', contextAttributes) as IWebGL2RenderingContext;
if (!this._gl) {
throw new Error('WebGL2 not supported ' + this._gl);
}
this._core.screenElement.appendChild(this._canvas);
this._rectangleRenderer = new RectangleRenderer(this._terminal, this._colors, this._gl, this.dimensions);
this._glyphRenderer = new GlyphRenderer(this._terminal, this._colors, this._gl, this.dimensions);
// Update dimensions and acquire char atlas
this.onCharSizeChanged();
this._isAttached = document.body.contains(this._core.screenElement);
}
public dispose(): void {
this._renderLayers.forEach(l => l.dispose());
this._core.screenElement.removeChild(this._canvas);
super.dispose();
}
public get textureAtlas(): HTMLCanvasElement | undefined {
return this._charAtlas?.cacheCanvas;
}
public setColors(colors: IColorSet): void {
this._colors = colors;
// Clear layers and force a full render
this._renderLayers.forEach(l => {
l.setColors(this._terminal, this._colors);
l.reset(this._terminal);
});
this._rectangleRenderer.setColors();
this._glyphRenderer.setColors();
this._refreshCharAtlas();
// Force a full refresh
this._model.clear();
}
public onDevicePixelRatioChange(): void {
// If the device pixel ratio changed, the char atlas needs to be regenerated
// and the terminal needs to refreshed
if (this._devicePixelRatio !== window.devicePixelRatio) {
this._devicePixelRatio = window.devicePixelRatio;
this.onResize(this._terminal.cols, this._terminal.rows);
}
}
public onResize(cols: number, rows: number): void {
// Update character and canvas dimensions
this._updateDimensions();
this._model.resize(this._terminal.cols, this._terminal.rows);
this._rectangleRenderer.onResize();
// Resize all render layers
this._renderLayers.forEach(l => l.resize(this._terminal, this.dimensions));
// Resize the canvas
this._canvas.width = this.dimensions.scaledCanvasWidth;
this._canvas.height = this.dimensions.scaledCanvasHeight;
this._canvas.style.width = `${this.dimensions.canvasWidth}px`;
this._canvas.style.height = `${this.dimensions.canvasHeight}px`;
// Resize the screen
this._core.screenElement.style.width = `${this.dimensions.canvasWidth}px`;
this._core.screenElement.style.height = `${this.dimensions.canvasHeight}px`;
this._glyphRenderer.setDimensions(this.dimensions);
this._glyphRenderer.onResize();
this._refreshCharAtlas();
// Force a full refresh
this._model.clear();
}
public onCharSizeChanged(): void {
this.onResize(this._terminal.cols, this._terminal.rows);
}
public onBlur(): void {
this._renderLayers.forEach(l => l.onBlur(this._terminal));
}
public onFocus(): void {
this._renderLayers.forEach(l => l.onFocus(this._terminal));
}
public onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void {
this._renderLayers.forEach(l => l.onSelectionChanged(this._terminal, start, end, columnSelectMode));
this._updateSelectionModel(start, end);
this._rectangleRenderer.updateSelection(this._model.selection, columnSelectMode);
this._glyphRenderer.updateSelection(this._model, columnSelectMode);
this._onRequestRefreshRows.fire({ start: 0, end: this._terminal.rows - 1 });
}
public onCursorMove(): void {
this._renderLayers.forEach(l => l.onCursorMove(this._terminal));
}
public onOptionsChanged(): void {
this._renderLayers.forEach(l => l.onOptionsChanged(this._terminal));
this._updateDimensions();
this._refreshCharAtlas();
}
/**
* Refreshes the char atlas, aquiring a new one if necessary.
* @param terminal The terminal.
* @param colorSet The color set to use for the char atlas.
*/
private _refreshCharAtlas(): void {
if (this.dimensions.scaledCharWidth <= 0 && this.dimensions.scaledCharHeight <= 0) {
// Mark as not attached so char atlas gets refreshed on next render
this._isAttached = false;
return;
}
const atlas = acquireCharAtlas(this._terminal, this._colors, this.dimensions.scaledCharWidth, this.dimensions.scaledCharHeight);
if (!('getRasterizedGlyph' in atlas)) {
throw new Error('The webgl renderer only works with the webgl char atlas');
}
this._charAtlas = atlas as WebglCharAtlas;
this._charAtlas.warmUp();
this._glyphRenderer.setAtlas(this._charAtlas);
}
public clear(): void {
this._renderLayers.forEach(l => l.reset(this._terminal));
}
public registerCharacterJoiner(handler: (text: string) => [number, number][]): number {
return -1;
}
public deregisterCharacterJoiner(joinerId: number): boolean {
return false;
}
public renderRows(start: number, end: number): void {
if (!this._isAttached) {
if (document.body.contains(this._core.screenElement) && (this._core as any)._charSizeService.width && (this._core as any)._charSizeService.height) {
this._updateDimensions();
this._refreshCharAtlas();
this._isAttached = true;
} else {
return;
}
}
// Update render layers
this._renderLayers.forEach(l => l.onGridChanged(this._terminal, start, end));
// Tell renderer the frame is beginning
if (this._glyphRenderer.beginFrame()) {
this._model.clear();
}
// Update model to reflect what's drawn
this._updateModel(start, end);
// Render
this._rectangleRenderer.render();
this._glyphRenderer.render(this._model, this._model.selection.hasSelection);
}
private _updateModel(start: number, end: number): void {
const terminal = this._core;
for (let y = start; y <= end; y++) {
const row = y + terminal.buffer.ydisp;
const line = terminal.buffer.lines.get(row)!;
this._model.lineLengths[y] = 0;
for (let x = 0; x < terminal.cols; x++) {
line.loadCell(x, this._workCell);
const chars = this._workCell.getChars();
let code = this._workCell.getCode();
const i = ((y * terminal.cols) + x) * RENDER_MODEL_INDICIES_PER_CELL;
if (code !== NULL_CELL_CODE) {
this._model.lineLengths[y] = x + 1;
}
// Nothing has changed, no updates needed
if (this._model.cells[i] === code &&
this._model.cells[i + RENDER_MODEL_BG_OFFSET] === this._workCell.bg &&
this._model.cells[i + RENDER_MODEL_FG_OFFSET] === this._workCell.fg) {
continue;
}
// Flag combined chars with a bit mask so they're easily identifiable
if (chars.length > 1) {
code = code | COMBINED_CHAR_BIT_MASK;
}
// Cache the results in the model
this._model.cells[i] = code;
this._model.cells[i + RENDER_MODEL_BG_OFFSET] = this._workCell.bg;
this._model.cells[i + RENDER_MODEL_FG_OFFSET] = this._workCell.fg;
this._glyphRenderer.updateCell(x, y, code, this._workCell.bg, this._workCell.fg, chars);
}
}
this._rectangleRenderer.updateBackgrounds(this._model);
}
private _updateSelectionModel(start: [number, number], end: [number, number]): void {
const terminal = this._terminal;
// Selection does not exist
if (!start || !end || (start[0] === end[0] && start[1] === end[1])) {
this._model.clearSelection();
return;
}
// Translate from buffer position to viewport position
const viewportStartRow = start[1] - terminal.buffer.active.viewportY;
const viewportEndRow = end[1] - terminal.buffer.active.viewportY;
const viewportCappedStartRow = Math.max(viewportStartRow, 0);
const viewportCappedEndRow = Math.min(viewportEndRow, terminal.rows - 1);
// No need to draw the selection
if (viewportCappedStartRow >= terminal.rows || viewportCappedEndRow < 0) {
this._model.clearSelection();
return;
}
this._model.selection.hasSelection = true;
this._model.selection.viewportStartRow = viewportStartRow;
this._model.selection.viewportEndRow = viewportEndRow;
this._model.selection.viewportCappedStartRow = viewportCappedStartRow;
this._model.selection.viewportCappedEndRow = viewportCappedEndRow;
this._model.selection.startCol = start[0];
this._model.selection.endCol = end[0];
}
/**
* Recalculates the character and canvas dimensions.
*/
private _updateDimensions(): void {
// TODO: Acquire CharSizeService properly
// Perform a new measure if the CharMeasure dimensions are not yet available
if (!(this._core as any)._charSizeService.width || !(this._core as any)._charSizeService.height) {
return;
}
// Calculate the scaled character width. Width is floored as it must be
// drawn to an integer grid in order for the CharAtlas "stamps" to not be
// blurry. When text is drawn to the grid not using the CharAtlas, it is
// clipped to ensure there is no overlap with the next cell.
// NOTE: ceil fixes sometime, floor does others :s
this.dimensions.scaledCharWidth = Math.floor((this._core as any)._charSizeService.width * this._devicePixelRatio);
// Calculate the scaled character height. Height is ceiled in case
// devicePixelRatio is a floating point number in order to ensure there is
// enough space to draw the character to the cell.
this.dimensions.scaledCharHeight = Math.ceil((this._core as any)._charSizeService.height * this._devicePixelRatio);
// Calculate the scaled cell height, if lineHeight is not 1 then the value
// will be floored because since lineHeight can never be lower then 1, there
// is a guarentee that the scaled line height will always be larger than
// scaled char height.
this.dimensions.scaledCellHeight = Math.floor(this.dimensions.scaledCharHeight * this._terminal.getOption('lineHeight'));
// Calculate the y coordinate within a cell that text should draw from in
// order to draw in the center of a cell.
this.dimensions.scaledCharTop = this._terminal.getOption('lineHeight') === 1 ? 0 : Math.round((this.dimensions.scaledCellHeight - this.dimensions.scaledCharHeight) / 2);
// Calculate the scaled cell width, taking the letterSpacing into account.
this.dimensions.scaledCellWidth = this.dimensions.scaledCharWidth + Math.round(this._terminal.getOption('letterSpacing'));
// Calculate the x coordinate with a cell that text should draw from in
// order to draw in the center of a cell.
this.dimensions.scaledCharLeft = Math.floor(this._terminal.getOption('letterSpacing') / 2);
// Recalculate the canvas dimensions; scaled* define the actual number of
// pixel in the canvas
this.dimensions.scaledCanvasHeight = this._terminal.rows * this.dimensions.scaledCellHeight;
this.dimensions.scaledCanvasWidth = this._terminal.cols * this.dimensions.scaledCellWidth;
// The the size of the canvas on the page. It's very important that this
// rounds to nearest integer and not ceils as browsers often set
// window.devicePixelRatio as something like 1.100000023841858, when it's
// actually 1.1. Ceiling causes blurriness as the backing canvas image is 1
// pixel too large for the canvas element size.
this.dimensions.canvasHeight = Math.round(this.dimensions.scaledCanvasHeight / this._devicePixelRatio);
this.dimensions.canvasWidth = Math.round(this.dimensions.scaledCanvasWidth / this._devicePixelRatio);
// this.dimensions.scaledCanvasHeight = this.dimensions.canvasHeight * devicePixelRatio;
// this.dimensions.scaledCanvasWidth = this.dimensions.canvasWidth * devicePixelRatio;
// Get the _actual_ dimensions of an individual cell. This needs to be
// derived from the canvasWidth/Height calculated above which takes into
// account window.devicePixelRatio. CharMeasure.width/height by itself is
// insufficient when the page is not at 100% zoom level as CharMeasure is
// measured in CSS pixels, but the actual char size on the canvas can
// differ.
// this.dimensions.actualCellHeight = this.dimensions.canvasHeight / this._terminal.rows;
// this.dimensions.actualCellWidth = this.dimensions.canvasWidth / this._terminal.cols;
// This fixes 110% and 125%, not 150% or 175% though
this.dimensions.actualCellHeight = this.dimensions.scaledCellHeight / this._devicePixelRatio;
this.dimensions.actualCellWidth = this.dimensions.scaledCellWidth / this._devicePixelRatio;
}
}
@@ -0,0 +1,58 @@
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
/**
* A matrix that when multiplies will translate 0-1 coordinates (left to right,
* top to bottom) to clip space.
*/
export const PROJECTION_MATRIX = new Float32Array([
2, 0, 0, 0,
0, -2, 0, 0,
0, 0, 1, 0,
-1, 1, 0, 1
]);
export function createProgram(gl: WebGLRenderingContext, vertexSource: string, fragmentSource: string): WebGLProgram | undefined {
const program = throwIfFalsy(gl.createProgram());
gl.attachShader(program, throwIfFalsy(createShader(gl, gl.VERTEX_SHADER, vertexSource)));
gl.attachShader(program, throwIfFalsy(createShader(gl, gl.FRAGMENT_SHADER, fragmentSource)));
gl.linkProgram(program);
const success = gl.getProgramParameter(program, gl.LINK_STATUS);
if (success) {
return program;
}
console.error(gl.getProgramInfoLog(program));
gl.deleteProgram(program);
}
export function createShader(gl: WebGLRenderingContext, type: number, source: string): WebGLShader | undefined {
const shader = throwIfFalsy(gl.createShader(type));
gl.shaderSource(shader, source);
gl.compileShader(shader);
const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (success) {
return shader;
}
console.error(gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
}
export function expandFloat32Array(source: Float32Array, max: number): Float32Array {
const newLength = Math.min(source.length * 2, max);
const newArray = new Float32Array(newLength);
for (let i = 0; i < source.length; i++) {
newArray[i] = source[i];
}
return newArray;
}
export function throwIfFalsy<T>(value: T | undefined | null): T {
if (!value) {
throw new Error('value must not be falsy');
}
return value;
}
@@ -3,27 +3,18 @@
* @license MIT
*/
import { ITerminal } from '../../Types';
import { generateConfig, configEquals } from './CharAtlasUtils';
import BaseCharAtlas from './BaseCharAtlas';
import DynamicCharAtlas from './DynamicCharAtlas';
import NoneCharAtlas from './NoneCharAtlas';
import StaticCharAtlas from './StaticCharAtlas';
import { WebglCharAtlas } from './WebglCharAtlas';
import { ICharAtlasConfig } from './Types';
import { IColorSet } from '../../ui/Types';
const charAtlasImplementations = {
'none': NoneCharAtlas,
'static': StaticCharAtlas,
'dynamic': DynamicCharAtlas
};
import { Terminal } from 'xterm';
import { IColorSet } from 'browser/Types';
interface ICharAtlasCacheEntry {
atlas: BaseCharAtlas;
atlas: WebglCharAtlas;
config: ICharAtlasConfig;
// N.B. This implementation potentially holds onto copies of the terminal forever, so
// this may cause memory leaks.
ownedBy: ITerminal[];
ownedBy: Terminal[];
}
const charAtlasCache: ICharAtlasCacheEntry[] = [];
@@ -35,11 +26,11 @@ const charAtlasCache: ICharAtlasCacheEntry[] = [];
* @param colors The colors to use.
*/
export function acquireCharAtlas(
terminal: ITerminal,
terminal: Terminal,
colors: IColorSet,
scaledCharWidth: number,
scaledCharHeight: number
): BaseCharAtlas {
): WebglCharAtlas {
const newConfig = generateConfig(scaledCharWidth, scaledCharHeight, terminal, colors);
// Check to see if the terminal already owns this config
@@ -72,10 +63,7 @@ export function acquireCharAtlas(
}
const newEntry: ICharAtlasCacheEntry = {
atlas: new charAtlasImplementations[terminal.options.experimentalCharAtlas](
document,
newConfig
),
atlas: new WebglCharAtlas(document, newConfig),
config: newConfig,
ownedBy: [terminal]
};
@@ -87,7 +75,7 @@ export function acquireCharAtlas(
* Removes a terminal reference from the cache, allowing its memory to be freed.
* @param terminal The terminal to remove.
*/
export function removeTerminalFromCache(terminal: ITerminal): void {
export function removeTerminalFromCache(terminal: Terminal): void {
for (let i = 0; i < charAtlasCache.length; i++) {
const index = charAtlasCache[i].ownedBy.indexOf(terminal);
if (index !== -1) {
@@ -0,0 +1,67 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { ICharAtlasConfig } from './Types';
import { Attributes } from 'common/buffer/Constants';
import { Terminal, FontWeight } from 'xterm';
import { IColorSet, IColor } from 'browser/Types';
const NULL_COLOR: IColor = {
css: '',
rgba: 0
};
export function generateConfig(scaledCharWidth: number, scaledCharHeight: number, terminal: Terminal, colors: IColorSet): ICharAtlasConfig {
// null out some fields that don't matter
const clonedColors: IColorSet = {
foreground: colors.foreground,
background: colors.background,
cursor: NULL_COLOR,
cursorAccent: NULL_COLOR,
selection: NULL_COLOR,
selectionOpaque: NULL_COLOR,
// For the static char atlas, we only use the first 16 colors, but we need all 256 for the
// dynamic character atlas.
ansi: colors.ansi.slice(),
contrastCache: colors.contrastCache
};
return {
devicePixelRatio: window.devicePixelRatio,
scaledCharWidth,
scaledCharHeight,
fontFamily: terminal.getOption('fontFamily'),
fontSize: terminal.getOption('fontSize'),
fontWeight: terminal.getOption('fontWeight') as FontWeight,
fontWeightBold: terminal.getOption('fontWeightBold') as FontWeight,
allowTransparency: terminal.getOption('allowTransparency'),
drawBoldTextInBrightColors: terminal.getOption('drawBoldTextInBrightColors'),
minimumContrastRatio: terminal.getOption('minimumContrastRatio'),
colors: clonedColors
};
}
export function configEquals(a: ICharAtlasConfig, b: ICharAtlasConfig): boolean {
for (let i = 0; i < a.colors.ansi.length; i++) {
if (a.colors.ansi[i].rgba !== b.colors.ansi[i].rgba) {
return false;
}
}
return a.devicePixelRatio === b.devicePixelRatio &&
a.fontFamily === b.fontFamily &&
a.fontSize === b.fontSize &&
a.fontWeight === b.fontWeight &&
a.fontWeightBold === b.fontWeightBold &&
a.allowTransparency === b.allowTransparency &&
a.scaledCharWidth === b.scaledCharWidth &&
a.scaledCharHeight === b.scaledCharHeight &&
a.drawBoldTextInBrightColors === b.drawBoldTextInBrightColors &&
a.minimumContrastRatio === b.minimumContrastRatio &&
a.colors.foreground === b.colors.foreground &&
a.colors.background === b.colors.background;
}
export function is256Color(colorCode: number): boolean {
return (colorCode & Attributes.CM_MASK) === Attributes.CM_P16 || (colorCode & Attributes.CM_MASK) === Attributes.CM_P256;
}
@@ -4,12 +4,7 @@
*/
import { FontWeight } from 'xterm';
import { IColorSet } from '../../ui/Types';
export const INVERTED_DEFAULT_COLOR = 257;
export const DIM_OPACITY = 0.5;
export const CHAR_ATLAS_CELL_SPACING = 1;
import { IColorSet } from 'browser/Types';
export interface IGlyphIdentifier {
chars: string;
@@ -22,7 +17,6 @@ export interface IGlyphIdentifier {
}
export interface ICharAtlasConfig {
type: 'none' | 'static' | 'dynamic';
devicePixelRatio: number;
fontSize: number;
fontFamily: string;
@@ -31,5 +25,7 @@ export interface ICharAtlasConfig {
scaledCharWidth: number;
scaledCharHeight: number;
allowTransparency: boolean;
drawBoldTextInBrightColors: boolean;
minimumContrastRatio: number;
colors: IColorSet;
}
@@ -0,0 +1,539 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { ICharAtlasConfig } from './Types';
import { DIM_OPACITY } from 'browser/renderer/atlas/Constants';
import { IRasterizedGlyph, IBoundingBox, IRasterizedGlyphSet } from '../Types';
import { DEFAULT_COLOR, Attributes } from 'common/buffer/Constants';
import { throwIfFalsy } from '../WebglUtils';
import { IColor } from 'browser/Types';
import { IDisposable } from 'xterm';
import { AttributeData } from 'common/buffer/AttributeData';
import { channels, rgba } from 'browser/Color';
// In practice we're probably never going to exhaust a texture this large. For debugging purposes,
// however, it can be useful to set this to a really tiny value, to verify that LRU eviction works.
const TEXTURE_WIDTH = 1024;
const TEXTURE_HEIGHT = 1024;
/**
* The amount of the texture to be filled before throwing it away and starting
* again. Since the throw away and individual glyph draws don't cost too much,
* this prevent juggling multiple textures in the GL context.
*/
const TEXTURE_CAPACITY = Math.floor(TEXTURE_HEIGHT * 0.8);
const TRANSPARENT_COLOR = {
css: 'rgba(0, 0, 0, 0)',
rgba: 0
};
/**
* A shared object which is used to draw nothing for a particular cell.
*/
const NULL_RASTERIZED_GLYPH: IRasterizedGlyph = {
offset: { x: 0, y: 0 },
texturePosition: { x: 0, y: 0 },
texturePositionClipSpace: { x: 0, y: 0 },
size: { x: 0, y: 0 },
sizeClipSpace: { x: 0, y: 0 }
};
const TMP_CANVAS_GLYPH_PADDING = 2;
export class WebglCharAtlas implements IDisposable {
private _didWarmUp: boolean = false;
private _cacheMap: { [code: number]: IRasterizedGlyphSet } = {};
private _cacheMapCombined: { [chars: string]: IRasterizedGlyphSet } = {};
// The texture that the atlas is drawn to
public cacheCanvas: HTMLCanvasElement;
private _cacheCtx: CanvasRenderingContext2D;
private _tmpCanvas: HTMLCanvasElement;
// A temporary context that glyphs are drawn to before being transfered to the atlas.
private _tmpCtx: CanvasRenderingContext2D;
// Since glyphs are expected to be around the same height, the packing
// strategy used it to fill a row with glyphs while keeping track of the
// tallest glyph in the row. Once the row is full a new row is started at
// (0,lastRow+lastRowTallestGlyph).
private _currentRowY: number = 0;
private _currentRowX: number = 0;
private _currentRowHeight: number = 0;
public hasCanvasChanged = false;
private _workBoundingBox: IBoundingBox = { top: 0, left: 0, bottom: 0, right: 0 };
private _workAttributeData: AttributeData = new AttributeData();
constructor(
document: Document,
private _config: ICharAtlasConfig
) {
this.cacheCanvas = document.createElement('canvas');
this.cacheCanvas.width = TEXTURE_WIDTH;
this.cacheCanvas.height = TEXTURE_HEIGHT;
// The canvas needs alpha because we use clearColor to convert the background color to alpha.
// It might also contain some characters with transparent backgrounds if allowTransparency is
// set.
this._cacheCtx = throwIfFalsy(this.cacheCanvas.getContext('2d', {alpha: true}));
this._tmpCanvas = document.createElement('canvas');
this._tmpCanvas.width = this._config.scaledCharWidth * 2 + TMP_CANVAS_GLYPH_PADDING * 2;
this._tmpCanvas.height = this._config.scaledCharHeight + TMP_CANVAS_GLYPH_PADDING * 2;
this._tmpCtx = throwIfFalsy(this._tmpCanvas.getContext('2d', {alpha: this._config.allowTransparency}));
}
public dispose(): void {
if (this.cacheCanvas.parentElement) {
this.cacheCanvas.parentElement.removeChild(this.cacheCanvas);
}
}
public warmUp(): void {
if (!this._didWarmUp) {
this._doWarmUp();
this._didWarmUp = true;
}
}
protected _doWarmUp(): void {
// Pre-fill with ASCII 33-126
for (let i = 33; i < 126; i++) {
const rasterizedGlyph = this._drawToCache(i, DEFAULT_COLOR, DEFAULT_COLOR);
this._cacheMap[i] = {
[DEFAULT_COLOR]: {
[DEFAULT_COLOR]: rasterizedGlyph
}
};
}
}
public beginFrame(): boolean {
if (this._currentRowY > TEXTURE_CAPACITY) {
this._cacheCtx.clearRect(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
this._cacheMap = {};
this._currentRowHeight = 0;
this._currentRowX = 0;
this._currentRowY = 0;
this._doWarmUp();
return true;
}
return false;
}
public getRasterizedGlyphCombinedChar(chars: string, bg: number, fg: number): IRasterizedGlyph {
let rasterizedGlyphSet = this._cacheMapCombined[chars];
if (!rasterizedGlyphSet) {
rasterizedGlyphSet = {};
this._cacheMapCombined[chars] = rasterizedGlyphSet;
}
let rasterizedGlyph: IRasterizedGlyph | undefined;
const rasterizedGlyphSetBg = rasterizedGlyphSet[bg];
if (rasterizedGlyphSetBg) {
rasterizedGlyph = rasterizedGlyphSetBg[fg];
}
if (!rasterizedGlyph) {
rasterizedGlyph = this._drawToCache(chars, bg, fg);
if (!rasterizedGlyphSet[bg]) {
rasterizedGlyphSet[bg] = {};
}
rasterizedGlyphSet[bg]![fg] = rasterizedGlyph;
}
return rasterizedGlyph;
}
/**
* Gets the glyphs texture coords, drawing the texture if it's not already
*/
public getRasterizedGlyph(code: number, bg: number, fg: number): IRasterizedGlyph {
let rasterizedGlyphSet = this._cacheMap[code];
if (!rasterizedGlyphSet) {
rasterizedGlyphSet = {};
this._cacheMap[code] = rasterizedGlyphSet;
}
let rasterizedGlyph: IRasterizedGlyph | undefined;
const rasterizedGlyphSetBg = rasterizedGlyphSet[bg];
if (rasterizedGlyphSetBg) {
rasterizedGlyph = rasterizedGlyphSetBg[fg];
}
if (!rasterizedGlyph) {
rasterizedGlyph = this._drawToCache(code, bg, fg);
if (!rasterizedGlyphSet[bg]) {
rasterizedGlyphSet[bg] = {};
}
rasterizedGlyphSet[bg]![fg] = rasterizedGlyph;
}
return rasterizedGlyph;
}
private _getColorFromAnsiIndex(idx: number): IColor {
if (idx >= this._config.colors.ansi.length) {
throw new Error('No color found for idx ' + idx);
}
return this._config.colors.ansi[idx];
}
private _getBackgroundColor(bgColorMode: number, bgColor: number, inverse: boolean): IColor {
if (this._config.allowTransparency) {
// The background color might have some transparency, so we need to render it as fully
// transparent in the atlas. Otherwise we'd end up drawing the transparent background twice
// around the anti-aliased edges of the glyph, and it would look too dark.
return TRANSPARENT_COLOR;
}
switch (bgColorMode) {
case Attributes.CM_P16:
case Attributes.CM_P256:
return this._getColorFromAnsiIndex(bgColor);
case Attributes.CM_RGB:
const arr = AttributeData.toColorRGB(bgColor);
// TODO: This object creation is slow
return {
rgba: bgColor << 8,
css: `#${toPaddedHex(arr[0])}${toPaddedHex(arr[1])}${toPaddedHex(arr[2])}`
};
case Attributes.CM_DEFAULT:
default:
if (inverse) {
return this._config.colors.foreground;
}
return this._config.colors.background;
}
}
private _getForegroundCss(bg: number, bgColorMode: number, bgColor: number, fg: number, fgColorMode: number, fgColor: number, inverse: boolean, bold: boolean): string {
const minimumContrastCss = this._getMinimumContrastCss(bg, bgColorMode, bgColor, fg, fgColorMode, fgColor, inverse, bold);
if (minimumContrastCss) {
return minimumContrastCss;
}
switch (fgColorMode) {
case Attributes.CM_P16:
case Attributes.CM_P256:
if (this._config.drawBoldTextInBrightColors && bold && fgColor < 8) {
fgColor += 8;
}
return this._getColorFromAnsiIndex(fgColor).css;
case Attributes.CM_RGB:
const arr = AttributeData.toColorRGB(fgColor);
return channels.toCss(arr[0], arr[1], arr[2]);
case Attributes.CM_DEFAULT:
default:
if (inverse) {
const bg = this._config.colors.background.css;
if (bg.length === 9) {
// Remove bg alpha channel if present
return bg.substr(0, 7);
}
return bg;
}
return this._config.colors.foreground.css;
}
}
private _resolveBackgroundRgba(bgColorMode: number, bgColor: number, inverse: boolean): number {
switch (bgColorMode) {
case Attributes.CM_P16:
case Attributes.CM_P256:
return this._getColorFromAnsiIndex(bgColor).rgba;
case Attributes.CM_RGB:
return bgColor << 8;
case Attributes.CM_DEFAULT:
default:
if (inverse) {
return this._config.colors.foreground.rgba;
}
return this._config.colors.background.rgba;
}
}
private _resolveForegroundRgba(fgColorMode: number, fgColor: number, inverse: boolean, bold: boolean): number {
switch (fgColorMode) {
case Attributes.CM_P16:
case Attributes.CM_P256:
if (this._config.drawBoldTextInBrightColors && bold && fgColor < 8) {
fgColor += 8;
}
return this._getColorFromAnsiIndex(fgColor).rgba;
case Attributes.CM_RGB:
return fgColor << 8;
case Attributes.CM_DEFAULT:
default:
if (inverse) {
return this._config.colors.background.rgba;
}
return this._config.colors.foreground.rgba;
}
}
private _getMinimumContrastCss(bg: number, bgColorMode: number, bgColor: number, fg: number, fgColorMode: number, fgColor: number, inverse: boolean, bold: boolean): string | undefined {
if (this._config.minimumContrastRatio === 1) {
return undefined;
}
// Try get from cache first
const adjustedColor = this._config.colors.contrastCache.getCss(bg, fg);
if (adjustedColor !== undefined) {
return adjustedColor || undefined;
}
const bgRgba = this._resolveBackgroundRgba(bgColorMode, bgColor, inverse);
const fgRgba = this._resolveForegroundRgba(fgColorMode, fgColor, inverse, bold);
const result = rgba.ensureContrastRatio(bgRgba, fgRgba, this._config.minimumContrastRatio);
if (!result) {
this._config.colors.contrastCache.setCss(bg, fg, null);
return undefined;
}
const css = channels.toCss(
(result >> 24) & 0xFF,
(result >> 16) & 0xFF,
(result >> 8) & 0xFF
);
this._config.colors.contrastCache.setCss(bg, fg, css);
return css;
}
private _drawToCache(code: number, bg: number, fg: number): IRasterizedGlyph;
private _drawToCache(chars: string, bg: number, fg: number): IRasterizedGlyph;
private _drawToCache(codeOrChars: number | string, bg: number, fg: number): IRasterizedGlyph {
const chars = typeof codeOrChars === 'number' ? String.fromCharCode(codeOrChars) : codeOrChars;
this.hasCanvasChanged = true;
this._tmpCtx.save();
this._workAttributeData.fg = fg;
this._workAttributeData.bg = bg;
const invisible = !!this._workAttributeData.isInvisible();
if (invisible) {
return NULL_RASTERIZED_GLYPH;
}
const bold = !!this._workAttributeData.isBold();
const inverse = !!this._workAttributeData.isInverse();
const dim = !!this._workAttributeData.isDim();
const italic = !!this._workAttributeData.isItalic();
let fgColor = this._workAttributeData.getFgColor();
let fgColorMode = this._workAttributeData.getFgColorMode();
let bgColor = this._workAttributeData.getBgColor();
let bgColorMode = this._workAttributeData.getBgColorMode();
if (inverse) {
const temp = fgColor;
fgColor = bgColor;
bgColor = temp;
const temp2 = fgColorMode;
fgColorMode = bgColorMode;
bgColorMode = temp2;
}
// draw the background
const backgroundColor = this._getBackgroundColor(bgColorMode, bgColor, inverse);
// Use a 'copy' composite operation to clear any existing glyph out of _tmpCtxWithAlpha, regardless of
// transparency in backgroundColor
this._tmpCtx.globalCompositeOperation = 'copy';
this._tmpCtx.fillStyle = backgroundColor.css;
this._tmpCtx.fillRect(0, 0, this._tmpCanvas.width, this._tmpCanvas.height);
this._tmpCtx.globalCompositeOperation = 'source-over';
// draw the foreground/glyph
const fontWeight = bold ? this._config.fontWeightBold : this._config.fontWeight;
const fontStyle = italic ? 'italic' : '';
this._tmpCtx.font =
`${fontStyle} ${fontWeight} ${this._config.fontSize * this._config.devicePixelRatio}px ${this._config.fontFamily}`;
this._tmpCtx.textBaseline = 'top';
this._tmpCtx.fillStyle = this._getForegroundCss(bg, bgColorMode, bgColor, fg, fgColorMode, fgColor, inverse, bold);
// Apply alpha to dim the character
if (dim) {
this._tmpCtx.globalAlpha = DIM_OPACITY;
}
// Draw the character
this._tmpCtx.fillText(chars, TMP_CANVAS_GLYPH_PADDING, TMP_CANVAS_GLYPH_PADDING);
this._tmpCtx.restore();
// clear the background from the character to avoid issues with drawing over the previous
// character if it extends past it's bounds
const imageData = this._tmpCtx.getImageData(
0, 0, this._tmpCanvas.width, this._tmpCanvas.height
);
// TODO: Support transparency
// let isEmpty = false;
// if (!this._config.allowTransparency) {
// isEmpty = clearColor(imageData, backgroundColor);
// }
// Clear out the background color and determine if the glyph is empty.
const isEmpty = clearColor(imageData, backgroundColor);
// Handle empty glyphs
if (isEmpty) {
return NULL_RASTERIZED_GLYPH;
}
const rasterizedGlyph = this._findGlyphBoundingBox(imageData, this._workBoundingBox);
const clippedImageData = this._clipImageData(imageData, this._workBoundingBox);
// Check if there is enough room in the current row and go to next if needed
if (this._currentRowX + this._config.scaledCharWidth > TEXTURE_WIDTH) {
this._currentRowX = 0;
this._currentRowY += this._currentRowHeight;
this._currentRowHeight = 0;
}
// Record texture position
rasterizedGlyph.texturePosition.x = this._currentRowX;
rasterizedGlyph.texturePosition.y = this._currentRowY;
rasterizedGlyph.texturePositionClipSpace.x = this._currentRowX / TEXTURE_WIDTH;
rasterizedGlyph.texturePositionClipSpace.y = this._currentRowY / TEXTURE_HEIGHT;
// Update atlas current row
this._currentRowHeight = Math.max(this._currentRowHeight, rasterizedGlyph.size.y);
this._currentRowX += rasterizedGlyph.size.x;
// putImageData doesn't do any blending, so it will overwrite any existing cache entry for us
this._cacheCtx.putImageData(clippedImageData, rasterizedGlyph.texturePosition.x, rasterizedGlyph.texturePosition.y);
return rasterizedGlyph;
}
/**
* Given an ImageData object, find the bounding box of the non-transparent
* portion of the texture and return an IRasterizedGlyph with these
* dimensions.
* @param imageData The image data to read.
* @param boundingBox An IBoundingBox to put the clipped bounding box values.
*/
private _findGlyphBoundingBox(imageData: ImageData, boundingBox: IBoundingBox): IRasterizedGlyph {
boundingBox.top = 0;
let found = false;
for (let y = 0; y < this._tmpCanvas.height; y++) {
for (let x = 0; x < this._tmpCanvas.width; x++) {
const alphaOffset = y * this._tmpCanvas.width * 4 + x * 4 + 3;
if (imageData.data[alphaOffset] !== 0) {
boundingBox.top = y;
found = true;
break;
}
}
if (found) {
break;
}
}
boundingBox.left = 0;
found = false;
for (let x = 0; x < this._tmpCanvas.width; x++) {
for (let y = 0; y < this._tmpCanvas.height; y++) {
const alphaOffset = y * this._tmpCanvas.width * 4 + x * 4 + 3;
if (imageData.data[alphaOffset] !== 0) {
boundingBox.left = x;
found = true;
break;
}
}
if (found) {
break;
}
}
boundingBox.right = this._tmpCanvas.width;
found = false;
for (let x = this._tmpCanvas.width - 1; x >= 0; x--) {
for (let y = 0; y < this._tmpCanvas.height; y++) {
const alphaOffset = y * this._tmpCanvas.width * 4 + x * 4 + 3;
if (imageData.data[alphaOffset] !== 0) {
boundingBox.right = x;
found = true;
break;
}
}
if (found) {
break;
}
}
boundingBox.bottom = this._tmpCanvas.height;
found = false;
for (let y = this._tmpCanvas.height - 1; y >= 0; y--) {
for (let x = 0; x < this._tmpCanvas.width; x++) {
const alphaOffset = y * this._tmpCanvas.width * 4 + x * 4 + 3;
if (imageData.data[alphaOffset] !== 0) {
boundingBox.bottom = y;
found = true;
break;
}
}
if (found) {
break;
}
}
return {
texturePosition: { x: 0, y: 0 },
texturePositionClipSpace: { x: 0, y: 0 },
size: {
x: boundingBox.right - boundingBox.left + 1,
y: boundingBox.bottom - boundingBox.top + 1
},
sizeClipSpace: {
x: (boundingBox.right - boundingBox.left + 1) / TEXTURE_WIDTH,
y: (boundingBox.bottom - boundingBox.top + 1) / TEXTURE_HEIGHT
},
offset: {
x: -boundingBox.left + TMP_CANVAS_GLYPH_PADDING,
y: -boundingBox.top + TMP_CANVAS_GLYPH_PADDING
}
};
}
private _clipImageData(imageData: ImageData, boundingBox: IBoundingBox): ImageData {
const width = boundingBox.right - boundingBox.left + 1;
const height = boundingBox.bottom - boundingBox.top + 1;
const clippedData = new Uint8ClampedArray(width * height * 4);
for (let y = boundingBox.top; y <= boundingBox.bottom; y++) {
for (let x = boundingBox.left; x <= boundingBox.right; x++) {
const oldOffset = y * this._tmpCanvas.width * 4 + x * 4;
const newOffset = (y - boundingBox.top) * width * 4 + (x - boundingBox.left) * 4;
clippedData[newOffset] = imageData.data[oldOffset];
clippedData[newOffset + 1] = imageData.data[oldOffset + 1];
clippedData[newOffset + 2] = imageData.data[oldOffset + 2];
clippedData[newOffset + 3] = imageData.data[oldOffset + 3];
}
}
return new ImageData(clippedData, width, height);
}
}
/**
* Makes a partiicular rgb color in an ImageData completely transparent.
* @returns True if the result is "empty", meaning all pixels are fully transparent.
*/
function clearColor(imageData: ImageData, color: IColor): boolean {
let isEmpty = true;
const r = color.rgba >>> 24;
const g = color.rgba >>> 16 & 0xFF;
const b = color.rgba >>> 8 & 0xFF;
for (let offset = 0; offset < imageData.data.length; offset += 4) {
if (imageData.data[offset] === r &&
imageData.data[offset + 1] === g &&
imageData.data[offset + 2] === b) {
imageData.data[offset + 3] = 0;
} else {
isEmpty = false;
}
}
return isEmpty;
}
function toPaddedHex(c: number): string {
const s = c.toString(16);
return s.length < 2 ? '0' + s : s;
}
@@ -0,0 +1,262 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { IRenderLayer } from './Types';
import { acquireCharAtlas } from '../atlas/CharAtlasCache';
import { Terminal } from 'xterm';
import { IColorSet } from 'browser/Types';
import { IRenderDimensions } from 'browser/renderer/Types';
import { CellData } from 'common/buffer/CellData';
import { WebglCharAtlas } from 'atlas/WebglCharAtlas';
import { throwIfFalsy } from '../WebglUtils';
export abstract class BaseRenderLayer implements IRenderLayer {
private _canvas: HTMLCanvasElement;
protected _ctx!: CanvasRenderingContext2D;
private _scaledCharWidth: number = 0;
private _scaledCharHeight: number = 0;
private _scaledCellWidth: number = 0;
private _scaledCellHeight: number = 0;
private _scaledCharLeft: number = 0;
private _scaledCharTop: number = 0;
protected _charAtlas: WebglCharAtlas | undefined;
constructor(
private _container: HTMLElement,
id: string,
zIndex: number,
private _alpha: boolean,
protected _colors: IColorSet
) {
this._canvas = document.createElement('canvas');
this._canvas.classList.add(`xterm-${id}-layer`);
this._canvas.style.zIndex = zIndex.toString();
this._initCanvas();
this._container.appendChild(this._canvas);
}
public dispose(): void {
this._container.removeChild(this._canvas);
if (this._charAtlas) {
this._charAtlas.dispose();
}
}
private _initCanvas(): void {
this._ctx = throwIfFalsy(this._canvas.getContext('2d', {alpha: this._alpha}));
// Draw the background if this is an opaque layer
if (!this._alpha) {
this._clearAll();
}
}
public onOptionsChanged(terminal: Terminal): void {}
public onBlur(terminal: Terminal): void {}
public onFocus(terminal: Terminal): void {}
public onCursorMove(terminal: Terminal): void {}
public onGridChanged(terminal: Terminal, startRow: number, endRow: number): void {}
public onSelectionChanged(terminal: Terminal, start: [number, number], end: [number, number], columnSelectMode: boolean = false): void {}
public setColors(terminal: Terminal, colorSet: IColorSet): void {
this._refreshCharAtlas(terminal, colorSet);
}
protected _setTransparency(terminal: Terminal, alpha: boolean): void {
// Do nothing when alpha doesn't change
if (alpha === this._alpha) {
return;
}
// Create new canvas and replace old one
const oldCanvas = this._canvas;
this._alpha = alpha;
// Cloning preserves properties
this._canvas = this._canvas.cloneNode() as HTMLCanvasElement;
this._initCanvas();
this._container.replaceChild(this._canvas, oldCanvas);
// Regenerate char atlas and force a full redraw
this._refreshCharAtlas(terminal, this._colors);
this.onGridChanged(terminal, 0, terminal.rows - 1);
}
/**
* Refreshes the char atlas, aquiring a new one if necessary.
* @param terminal The terminal.
* @param colorSet The color set to use for the char atlas.
*/
private _refreshCharAtlas(terminal: Terminal, colorSet: IColorSet): void {
if (this._scaledCharWidth <= 0 && this._scaledCharHeight <= 0) {
return;
}
this._charAtlas = acquireCharAtlas(terminal, colorSet, this._scaledCharWidth, this._scaledCharHeight);
this._charAtlas.warmUp();
}
public resize(terminal: Terminal, dim: IRenderDimensions): void {
this._scaledCellWidth = dim.scaledCellWidth;
this._scaledCellHeight = dim.scaledCellHeight;
this._scaledCharWidth = dim.scaledCharWidth;
this._scaledCharHeight = dim.scaledCharHeight;
this._scaledCharLeft = dim.scaledCharLeft;
this._scaledCharTop = dim.scaledCharTop;
this._canvas.width = dim.scaledCanvasWidth;
this._canvas.height = dim.scaledCanvasHeight;
this._canvas.style.width = `${dim.canvasWidth}px`;
this._canvas.style.height = `${dim.canvasHeight}px`;
// Draw the background if this is an opaque layer
if (!this._alpha) {
this._clearAll();
}
this._refreshCharAtlas(terminal, this._colors);
}
public abstract reset(terminal: Terminal): void;
/**
* Fills 1+ cells completely. This uses the existing fillStyle on the context.
* @param x The column to start at.
* @param y The row to start at
* @param width The number of columns to fill.
* @param height The number of rows to fill.
*/
protected _fillCells(x: number, y: number, width: number, height: number): void {
this._ctx.fillRect(
x * this._scaledCellWidth,
y * this._scaledCellHeight,
width * this._scaledCellWidth,
height * this._scaledCellHeight);
}
/**
* Fills a 1px line (2px on HDPI) at the bottom of the cell. This uses the
* existing fillStyle on the context.
* @param x The column to fill.
* @param y The row to fill.
*/
protected _fillBottomLineAtCells(x: number, y: number, width: number = 1): void {
this._ctx.fillRect(
x * this._scaledCellWidth,
(y + 1) * this._scaledCellHeight - window.devicePixelRatio - 1 /* Ensure it's drawn within the cell */,
width * this._scaledCellWidth,
window.devicePixelRatio);
}
/**
* Fills a 1px line (2px on HDPI) at the left of the cell. This uses the
* existing fillStyle on the context.
* @param x The column to fill.
* @param y The row to fill.
*/
protected _fillLeftLineAtCell(x: number, y: number, width: number): void {
this._ctx.fillRect(
x * this._scaledCellWidth,
y * this._scaledCellHeight,
window.devicePixelRatio * width,
this._scaledCellHeight);
}
/**
* Strokes a 1px rectangle (2px on HDPI) around a cell. This uses the existing
* strokeStyle on the context.
* @param x The column to fill.
* @param y The row to fill.
*/
protected _strokeRectAtCell(x: number, y: number, width: number, height: number): void {
this._ctx.lineWidth = window.devicePixelRatio;
this._ctx.strokeRect(
x * this._scaledCellWidth + window.devicePixelRatio / 2,
y * this._scaledCellHeight + (window.devicePixelRatio / 2),
width * this._scaledCellWidth - window.devicePixelRatio,
(height * this._scaledCellHeight) - window.devicePixelRatio);
}
/**
* Clears the entire canvas.
*/
protected _clearAll(): void {
if (this._alpha) {
this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
} else {
this._ctx.fillStyle = this._colors.background.css;
this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height);
}
}
/**
* Clears 1+ cells completely.
* @param x The column to start at.
* @param y The row to start at.
* @param width The number of columns to clear.
* @param height The number of rows to clear.
*/
protected _clearCells(x: number, y: number, width: number, height: number): void {
if (this._alpha) {
this._ctx.clearRect(
x * this._scaledCellWidth,
y * this._scaledCellHeight,
width * this._scaledCellWidth,
height * this._scaledCellHeight);
} else {
this._ctx.fillStyle = this._colors.background.css;
this._ctx.fillRect(
x * this._scaledCellWidth,
y * this._scaledCellHeight,
width * this._scaledCellWidth,
height * this._scaledCellHeight);
}
}
/**
* Draws a truecolor character at the cell. The character will be clipped to
* ensure that it fits with the cell, including the cell to the right if it's
* a wide character. This uses the existing fillStyle on the context.
* @param terminal The terminal.
* @param cell The cell data for the character to draw.
* @param x The column to draw at.
* @param y The row to draw at.
* @param color The color of the character.
*/
protected _fillCharTrueColor(terminal: Terminal, cell: CellData, x: number, y: number): void {
this._ctx.font = this._getFont(terminal, false, false);
this._ctx.textBaseline = 'middle';
this._clipRow(terminal, y);
this._ctx.fillText(
cell.getChars(),
x * this._scaledCellWidth + this._scaledCharLeft,
y * this._scaledCellHeight + this._scaledCharTop + this._scaledCharHeight / 2);
}
/**
* Clips a row to ensure no pixels will be drawn outside the cells in the row.
* @param terminal The terminal.
* @param y The row to clip.
*/
private _clipRow(terminal: Terminal, y: number): void {
this._ctx.beginPath();
this._ctx.rect(
0,
y * this._scaledCellHeight,
terminal.cols * this._scaledCellWidth,
this._scaledCellHeight);
this._ctx.clip();
}
/**
* Gets the current font.
* @param terminal The terminal.
* @param isBold If we should use the bold fontWeight.
*/
protected _getFont(terminal: Terminal, isBold: boolean, isItalic: boolean): string {
const fontWeight = isBold ? terminal.getOption('fontWeightBold') : terminal.getOption('fontWeight');
const fontStyle = isItalic ? 'italic' : '';
return `${fontStyle} ${fontWeight} ${terminal.getOption('fontSize') * window.devicePixelRatio}px ${terminal.getOption('fontFamily')}`;
}
}
@@ -3,12 +3,13 @@
* @license MIT
*/
import { IRenderDimensions } from './Types';
import { Terminal } from 'xterm';
import { BaseRenderLayer } from './BaseRenderLayer';
import { ITerminal } from '../Types';
import { ICellData } from '../core/Types';
import { CellData } from '../core/buffer/BufferLine';
import { IColorSet } from '../ui/Types';
import { ICellData } from 'common/Types';
import { CellData } from 'common/buffer/CellData';
import { IColorSet } from 'browser/Types';
import { IRenderDimensions, IRequestRefreshRowsEvent } from 'browser/renderer/Types';
import { IEventEmitter } from 'common/EventEmitter';
interface ICursorState {
x: number;
@@ -25,18 +26,23 @@ const BLINK_INTERVAL = 600;
export class CursorRenderLayer extends BaseRenderLayer {
private _state: ICursorState;
private _cursorRenderers: {[key: string]: (terminal: ITerminal, x: number, y: number, cell: ICellData) => void};
private _cursorBlinkStateManager: CursorBlinkStateManager;
private _cursorRenderers: {[key: string]: (terminal: Terminal, x: number, y: number, cell: ICellData) => void};
private _cursorBlinkStateManager: CursorBlinkStateManager | undefined;
private _cell: ICellData = new CellData();
constructor(container: HTMLElement, zIndex: number, colors: IColorSet) {
constructor(
container: HTMLElement,
zIndex: number,
colors: IColorSet,
private _onRequestRefreshRowsEvent: IEventEmitter<IRequestRefreshRowsEvent>
) {
super(container, 'cursor', zIndex, true, colors);
this._state = {
x: null,
y: null,
isFocused: null,
style: null,
width: null
x: 0,
y: 0,
isFocused: false,
style: '',
width: 0
};
this._cursorRenderers = {
'bar': this._renderBarCursor.bind(this),
@@ -46,67 +52,64 @@ export class CursorRenderLayer extends BaseRenderLayer {
// TODO: Consider initial options? Maybe onOptionsChanged should be called at the end of open?
}
public resize(terminal: ITerminal, dim: IRenderDimensions): void {
public resize(terminal: Terminal, dim: IRenderDimensions): void {
super.resize(terminal, dim);
// Resizing the canvas discards the contents of the canvas so clear state
this._state = {
x: null,
y: null,
isFocused: null,
style: null,
width: null
x: 0,
y: 0,
isFocused: false,
style: '',
width: 0
};
}
public reset(terminal: ITerminal): void {
public reset(terminal: Terminal): void {
this._clearCursor();
if (this._cursorBlinkStateManager) {
this._cursorBlinkStateManager.dispose();
this._cursorBlinkStateManager = null;
this.onOptionsChanged(terminal);
}
}
public onBlur(terminal: ITerminal): void {
public onBlur(terminal: Terminal): void {
if (this._cursorBlinkStateManager) {
this._cursorBlinkStateManager.pause();
}
terminal.refresh(terminal.buffer.y, terminal.buffer.y);
this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.active.cursorY, end: terminal.buffer.active.cursorY });
}
public onFocus(terminal: ITerminal): void {
public onFocus(terminal: Terminal): void {
if (this._cursorBlinkStateManager) {
this._cursorBlinkStateManager.resume(terminal);
} else {
terminal.refresh(terminal.buffer.y, terminal.buffer.y);
this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.active.cursorY, end: terminal.buffer.active.cursorY });
}
}
public onOptionsChanged(terminal: ITerminal): void {
if (terminal.options.cursorBlink) {
public onOptionsChanged(terminal: Terminal): void {
if (terminal.getOption('cursorBlink')) {
if (!this._cursorBlinkStateManager) {
this._cursorBlinkStateManager = new CursorBlinkStateManager(terminal, () => {
this._render(terminal, true);
});
}
} else {
if (this._cursorBlinkStateManager) {
this._cursorBlinkStateManager.dispose();
this._cursorBlinkStateManager = null;
}
// Request a refresh from the terminal as management of rendering is being
// moved back to the terminal
terminal.refresh(terminal.buffer.y, terminal.buffer.y);
this._cursorBlinkStateManager?.dispose();
this._cursorBlinkStateManager = undefined;
}
// Request a refresh from the terminal as management of rendering is being
// moved back to the terminal
this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.active.cursorY, end: terminal.buffer.active.cursorY });
}
public onCursorMove(terminal: ITerminal): void {
public onCursorMove(terminal: Terminal): void {
if (this._cursorBlinkStateManager) {
this._cursorBlinkStateManager.restartBlinkAnimation(terminal);
}
}
public onGridChanged(terminal: ITerminal, startRow: number, endRow: number): void {
public onGridChanged(terminal: Terminal, startRow: number, endRow: number): void {
if (!this._cursorBlinkStateManager || this._cursorBlinkStateManager.isPaused) {
this._render(terminal, false);
} else {
@@ -114,15 +117,19 @@ export class CursorRenderLayer extends BaseRenderLayer {
}
}
private _render(terminal: ITerminal, triggeredByAnimationFrame: boolean): void {
private _render(terminal: Terminal, triggeredByAnimationFrame: boolean): void {
// Don't draw the cursor if it's hidden
if (!terminal.cursorState || terminal.cursorHidden) {
// TODO: Need to expose API for this
if (!(terminal as any)._core._coreService.isCursorInitialized || (terminal as any)._core._coreService.isCursorHidden) {
this._clearCursor();
return;
}
const cursorY = terminal.buffer.ybase + terminal.buffer.y;
const viewportRelativeCursorY = cursorY - terminal.buffer.ydisp;
const cursorY = terminal.buffer.active.baseY + terminal.buffer.active.cursorY;
const viewportRelativeCursorY = cursorY - terminal.buffer.active.viewportY;
// in case cursor.x == cols adjust visual cursor to cols - 1
const cursorX = Math.min(terminal.buffer.active.cursorX, terminal.cols - 1);
// Don't draw the cursor if it's off-screen
if (viewportRelativeCursorY < 0 || viewportRelativeCursorY >= terminal.rows) {
@@ -130,21 +137,27 @@ export class CursorRenderLayer extends BaseRenderLayer {
return;
}
terminal.buffer.lines.get(cursorY).loadCell(terminal.buffer.x, this._cell);
// TODO: Need fast buffer API for loading cell
(terminal as any)._core.buffer.lines.get(cursorY).loadCell(cursorX, this._cell);
if (this._cell.content === undefined) {
return;
}
if (!terminal.isFocused) {
if (!isTerminalFocused(terminal)) {
this._clearCursor();
this._ctx.save();
this._ctx.fillStyle = this._colors.cursor.css;
this._renderBlurCursor(terminal, terminal.buffer.x, viewportRelativeCursorY, this._cell);
const cursorStyle = terminal.getOption('cursorStyle');
if (cursorStyle && cursorStyle !== 'block') {
this._cursorRenderers[cursorStyle](terminal, cursorX, viewportRelativeCursorY, this._cell);
} else {
this._renderBlurCursor(terminal, cursorX, viewportRelativeCursorY, this._cell);
}
this._ctx.restore();
this._state.x = terminal.buffer.x;
this._state.x = cursorX;
this._state.y = viewportRelativeCursorY;
this._state.isFocused = false;
this._state.style = terminal.options.cursorStyle;
this._state.style = cursorStyle;
this._state.width = this._cell.getWidth();
return;
}
@@ -157,10 +170,10 @@ export class CursorRenderLayer extends BaseRenderLayer {
if (this._state) {
// The cursor is already in the correct spot, don't redraw
if (this._state.x === terminal.buffer.x &&
if (this._state.x === cursorX &&
this._state.y === viewportRelativeCursorY &&
this._state.isFocused === terminal.isFocused &&
this._state.style === terminal.options.cursorStyle &&
this._state.isFocused === isTerminalFocused(terminal) &&
this._state.style === terminal.getOption('cursorStyle') &&
this._state.width === this._cell.getWidth()) {
return;
}
@@ -168,56 +181,56 @@ export class CursorRenderLayer extends BaseRenderLayer {
}
this._ctx.save();
this._cursorRenderers[terminal.options.cursorStyle || 'block'](terminal, terminal.buffer.x, viewportRelativeCursorY, this._cell);
this._cursorRenderers[terminal.getOption('cursorStyle') || 'block'](terminal, cursorX, viewportRelativeCursorY, this._cell);
this._ctx.restore();
this._state.x = terminal.buffer.x;
this._state.x = cursorX;
this._state.y = viewportRelativeCursorY;
this._state.isFocused = false;
this._state.style = terminal.options.cursorStyle;
this._state.style = terminal.getOption('cursorStyle');
this._state.width = this._cell.getWidth();
}
private _clearCursor(): void {
if (this._state) {
this.clearCells(this._state.x, this._state.y, this._state.width, 1);
this._clearCells(this._state.x, this._state.y, this._state.width, 1);
this._state = {
x: null,
y: null,
isFocused: null,
style: null,
width: null
x: 0,
y: 0,
isFocused: false,
style: '',
width: 0
};
}
}
private _renderBarCursor(terminal: ITerminal, x: number, y: number, cell: ICellData): void {
private _renderBarCursor(terminal: Terminal, x: number, y: number, cell: ICellData): void {
this._ctx.save();
this._ctx.fillStyle = this._colors.cursor.css;
this.fillLeftLineAtCell(x, y);
this._fillLeftLineAtCell(x, y, terminal.getOption('cursorWidth'));
this._ctx.restore();
}
private _renderBlockCursor(terminal: ITerminal, x: number, y: number, cell: ICellData): void {
private _renderBlockCursor(terminal: Terminal, x: number, y: number, cell: ICellData): void {
this._ctx.save();
this._ctx.fillStyle = this._colors.cursor.css;
this.fillCells(x, y, cell.getWidth(), 1);
this._fillCells(x, y, cell.getWidth(), 1);
this._ctx.fillStyle = this._colors.cursorAccent.css;
this.fillCharTrueColor(terminal, cell, x, y);
this._fillCharTrueColor(terminal, cell, x, y);
this._ctx.restore();
}
private _renderUnderlineCursor(terminal: ITerminal, x: number, y: number, cell: ICellData): void {
private _renderUnderlineCursor(terminal: Terminal, x: number, y: number, cell: ICellData): void {
this._ctx.save();
this._ctx.fillStyle = this._colors.cursor.css;
this.fillBottomLineAtCells(x, y);
this._fillBottomLineAtCells(x, y);
this._ctx.restore();
}
private _renderBlurCursor(terminal: ITerminal, x: number, y: number, cell: ICellData): void {
private _renderBlurCursor(terminal: Terminal, x: number, y: number, cell: ICellData): void {
this._ctx.save();
this._ctx.strokeStyle = this._colors.cursor.css;
this.strokeRectAtCell(x, y, cell.getWidth(), 1);
this._strokeRectAtCell(x, y, cell.getWidth(), 1);
this._ctx.restore();
}
}
@@ -225,23 +238,23 @@ export class CursorRenderLayer extends BaseRenderLayer {
class CursorBlinkStateManager {
public isCursorVisible: boolean;
private _animationFrame: number;
private _blinkStartTimeout: number;
private _blinkInterval: number;
private _animationFrame: number | undefined;
private _blinkStartTimeout: number | undefined;
private _blinkInterval: number | undefined;
/**
* The time at which the animation frame was restarted, this is used on the
* next render to restart the timers so they don't need to restart the timers
* multiple times over a short period.
*/
private _animationTimeRestarted: number;
private _animationTimeRestarted: number | undefined;
constructor(
terminal: ITerminal,
terminal: Terminal,
private _renderCallback: () => void
) {
this.isCursorVisible = true;
if (terminal.isFocused) {
if (isTerminalFocused(terminal)) {
this._restartInterval();
}
}
@@ -251,19 +264,19 @@ class CursorBlinkStateManager {
public dispose(): void {
if (this._blinkInterval) {
window.clearInterval(this._blinkInterval);
this._blinkInterval = null;
this._blinkInterval = undefined;
}
if (this._blinkStartTimeout) {
window.clearTimeout(this._blinkStartTimeout);
this._blinkStartTimeout = null;
this._blinkStartTimeout = undefined;
}
if (this._animationFrame) {
window.cancelAnimationFrame(this._animationFrame);
this._animationFrame = null;
this._animationFrame = undefined;
}
}
public restartBlinkAnimation(terminal: ITerminal): void {
public restartBlinkAnimation(terminal: Terminal): void {
if (this.isPaused) {
return;
}
@@ -274,7 +287,7 @@ class CursorBlinkStateManager {
if (!this._animationFrame) {
this._animationFrame = window.requestAnimationFrame(() => {
this._renderCallback();
this._animationFrame = null;
this._animationFrame = undefined;
});
}
}
@@ -289,12 +302,12 @@ class CursorBlinkStateManager {
// the regular interval is setup in order to support restarting the blink
// animation in a lightweight way (without thrashing clearInterval and
// setInterval).
this._blinkStartTimeout = <number><any>setTimeout(() => {
this._blinkStartTimeout = window.setTimeout(() => {
// Check if another animation restart was requested while this was being
// started
if (this._animationTimeRestarted) {
const time = BLINK_INTERVAL - (Date.now() - this._animationTimeRestarted);
this._animationTimeRestarted = null;
this._animationTimeRestarted = undefined;
if (time > 0) {
this._restartInterval(time);
return;
@@ -305,17 +318,17 @@ class CursorBlinkStateManager {
this.isCursorVisible = false;
this._animationFrame = window.requestAnimationFrame(() => {
this._renderCallback();
this._animationFrame = null;
this._animationFrame = undefined;
});
// Setup the blink interval
this._blinkInterval = <number><any>setInterval(() => {
this._blinkInterval = window.setInterval(() => {
// Adjust the animation time if it was restarted
if (this._animationTimeRestarted) {
// calc time diff
// Make restart interval do a setTimeout initially?
const time = BLINK_INTERVAL - (Date.now() - this._animationTimeRestarted);
this._animationTimeRestarted = null;
this._animationTimeRestarted = undefined;
this._restartInterval(time);
return;
}
@@ -324,7 +337,7 @@ class CursorBlinkStateManager {
this.isCursorVisible = !this.isCursorVisible;
this._animationFrame = window.requestAnimationFrame(() => {
this._renderCallback();
this._animationFrame = null;
this._animationFrame = undefined;
});
}, BLINK_INTERVAL);
}, timeToStart);
@@ -334,21 +347,28 @@ class CursorBlinkStateManager {
this.isCursorVisible = true;
if (this._blinkInterval) {
window.clearInterval(this._blinkInterval);
this._blinkInterval = null;
this._blinkInterval = undefined;
}
if (this._blinkStartTimeout) {
window.clearTimeout(this._blinkStartTimeout);
this._blinkStartTimeout = null;
this._blinkStartTimeout = undefined;
}
if (this._animationFrame) {
window.cancelAnimationFrame(this._animationFrame);
this._animationFrame = null;
this._animationFrame = undefined;
}
}
public resume(terminal: ITerminal): void {
this._animationTimeRestarted = null;
public resume(terminal: Terminal): void {
// Clear out any existing timers just in case
this.pause();
this._animationTimeRestarted = undefined;
this._restartInterval();
this.restartBlinkAnimation(terminal);
}
}
function isTerminalFocused(terminal: Terminal): boolean {
return document.activeElement === terminal.textarea && document.hasFocus();
}
@@ -3,64 +3,68 @@
* @license MIT
*/
import { ILinkifierEvent, ITerminal, ILinkifierAccessor } from '../Types';
import { IRenderDimensions } from './Types';
import { ILinkifierAccessor } from '../../../../src/Types';
import { Terminal } from 'xterm';
import { BaseRenderLayer } from './BaseRenderLayer';
import { INVERTED_DEFAULT_COLOR } from './atlas/Types';
import { is256Color } from './atlas/CharAtlasUtils';
import { IColorSet } from '../ui/Types';
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
import { is256Color } from '../atlas/CharAtlasUtils';
import { IColorSet, ILinkifierEvent } from 'browser/Types';
import { IRenderDimensions } from 'browser/renderer/Types';
export class LinkRenderLayer extends BaseRenderLayer {
private _state: ILinkifierEvent = null;
private _state: ILinkifierEvent | undefined;
constructor(container: HTMLElement, zIndex: number, colors: IColorSet, terminal: ILinkifierAccessor) {
super(container, 'link', zIndex, true, colors);
terminal.linkifier.onLinkHover(e => this._onLinkHover(e));
terminal.linkifier.onLinkLeave(e => this._onLinkLeave(e));
terminal.linkifier2.onLinkHover(e => this._onLinkHover(e));
terminal.linkifier2.onLinkLeave(e => this._onLinkLeave(e));
}
public resize(terminal: ITerminal, dim: IRenderDimensions): void {
public resize(terminal: Terminal, dim: IRenderDimensions): void {
super.resize(terminal, dim);
// Resizing the canvas discards the contents of the canvas so clear state
this._state = null;
this._state = undefined;
}
public reset(terminal: ITerminal): void {
public reset(terminal: Terminal): void {
this._clearCurrentLink();
}
private _clearCurrentLink(): void {
if (this._state) {
this.clearCells(this._state.x1, this._state.y1, this._state.cols - this._state.x1, 1);
this._clearCells(this._state.x1, this._state.y1, this._state.cols - this._state.x1, 1);
const middleRowCount = this._state.y2 - this._state.y1 - 1;
if (middleRowCount > 0) {
this.clearCells(0, this._state.y1 + 1, this._state.cols, middleRowCount);
this._clearCells(0, this._state.y1 + 1, this._state.cols, middleRowCount);
}
this.clearCells(0, this._state.y2, this._state.x2, 1);
this._state = null;
this._clearCells(0, this._state.y2, this._state.x2, 1);
this._state = undefined;
}
}
private _onLinkHover(e: ILinkifierEvent): void {
if (e.fg === INVERTED_DEFAULT_COLOR) {
this._ctx.fillStyle = this._colors.background.css;
} else if (is256Color(e.fg)) {
} else if (e.fg !== undefined && is256Color(e.fg)) {
// 256 color support
this._ctx.fillStyle = this._colors.ansi[e.fg].css;
this._ctx.fillStyle = this._colors.ansi[e.fg!].css;
} else {
this._ctx.fillStyle = this._colors.foreground.css;
}
if (e.y1 === e.y2) {
// Single line link
this.fillBottomLineAtCells(e.x1, e.y1, e.x2 - e.x1);
this._fillBottomLineAtCells(e.x1, e.y1, e.x2 - e.x1);
} else {
// Multi-line link
this.fillBottomLineAtCells(e.x1, e.y1, e.cols - e.x1);
this._fillBottomLineAtCells(e.x1, e.y1, e.cols - e.x1);
for (let y = e.y1 + 1; y < e.y2; y++) {
this.fillBottomLineAtCells(0, y, e.cols);
this._fillBottomLineAtCells(0, y, e.cols);
}
this.fillBottomLineAtCells(0, e.y2, e.x2);
this._fillBottomLineAtCells(0, e.y2, e.x2);
}
this._state = e;
}
@@ -0,0 +1,66 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { IDisposable, Terminal } from 'xterm';
import { IColorSet } from 'browser/Types';
import { IRenderDimensions } from 'browser/renderer/Types';
export interface IRenderLayer extends IDisposable {
/**
* Called when the terminal loses focus.
*/
onBlur(terminal: Terminal): void;
/**
* * Called when the terminal gets focus.
*/
onFocus(terminal: Terminal): void;
/**
* Called when the cursor is moved.
*/
onCursorMove(terminal: Terminal): void;
/**
* Called when options change.
*/
onOptionsChanged(terminal: Terminal): void;
/**
* Called when the theme changes.
*/
setColors(terminal: Terminal, colorSet: IColorSet): void;
/**
* Called when the data in the grid has changed (or needs to be rendered
* again).
*/
onGridChanged(terminal: Terminal, startRow: number, endRow: number): void;
/**
* Calls when the selection changes.
*/
onSelectionChanged(terminal: Terminal, start: [number, number], end: [number, number], columnSelectMode: boolean): void;
/**
* Registers a handler to join characters to render as a group
*/
registerCharacterJoiner?(handler: (text: string) => [number, number][]): void;
/**
* Deregisters the specified character joiner handler
*/
deregisterCharacterJoiner?(joinerId: number): void;
/**
* Resize the render layer.
*/
resize(terminal: Terminal, dim: IRenderDimensions): void;
/**
* Clear the state of the render layer.
*/
reset(terminal: Terminal): void;
}
@@ -0,0 +1,40 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": [
"dom",
"es6",
],
"rootDir": ".",
"outDir": "../out",
"sourceMap": true,
"removeComments": true,
"baseUrl": ".",
"paths": {
"common/*": [
"../../../src/common/*"
],
"browser/*": [
"../../../src/browser/*"
]
},
"strict": true,
"types": [
"../../../node_modules/@types/mocha",
"../../../out-test/api/TestUtils"
]
},
"include": [
"./**/*",
"../../../typings/xterm.d.ts"
],
"references": [
{
"path": "../../../src/common"
},
{
"path": "../../../src/browser"
}
]
}

Some files were not shown because too many files have changed in this diff Show More