Compare commits

..
1464 Commits
Author SHA1 Message Date
Daniel Imms 7d19769bd0 Merge pull request #2436 from Tyriar/r4_0_release
v4.0.2
2019-09-24 06:13:16 -07:00
Daniel Imms a5e43ad8cc v4.0.2 2019-09-24 06:10:43 -07:00
Daniel Imms ac69ef5e01 Merge pull request #2435 from Tyriar/r4_0_2433
Fix NPE when open called twice (release/4.0)
2019-09-23 10:55:26 -07:00
Daniel Imms b28be877bd Fix NPE when open called twice
Fixes #2433
2019-09-23 07:48:31 -07:00
Daniel Imms 217ed05606 Merge pull request #2426 from Tyriar/r401
v4.0.1
2019-09-12 14:57:08 -07:00
Daniel Imms 02aa803889 v4.0.1 2019-09-12 14:53:56 -07:00
Daniel Imms 9489bd8c5c Merge pull request #2418 from Tyriar/2417_edge_links
Fix web links addon support in Edge
2019-09-11 14:37:54 -07:00
Daniel Imms 324dc8d4dc Fix web links addon support in Edge
regex.flags isn't supported on Edge

Fixes #2417
2019-09-11 14:35:36 -07:00
Daniel Imms 70ecec3c92 Merge pull request #2416 from Tyriar/window_export
Expose ctor at window.Terminal
2019-09-11 08:54:18 -07:00
Daniel Imms e0997b51e1 Expose ctor at window.Terminal
Fixes #2415
2019-09-11 08:51:01 -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 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
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
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
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 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
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 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
Jörg Breitbart 84d7591506 increase test timeout 2019-08-02 21:06:16 +02: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
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
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
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
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
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
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 0ed75dc100 Merge pull request #2145 from xtermjs/Tyriar-patch-1
v3.14.0
2019-05-30 16:37:12 -07:00
Daniel Imms b3a631750d v3.14.0 2019-05-30 16:26:37 -07:00
Daniel Imms 9643de4c01 Merge pull request #2141 from Tyriar/ts_3.5
typescript@3.5
2019-05-29 16:38:37 -07:00
Daniel Imms ab1263f669 typescript@3.5 2019-05-29 16:10:54 -07:00
Daniel Imms 64686b5865 Merge branch 'master' into ts_wp 2019-05-28 11:58:58 -07:00
Daniel Imms 9ebe094a2f Merge pull request #2140 from Tyriar/2136_fix_dom_renderer
Fix DOM renderer
2019-05-28 11:56:31 -07:00
Daniel Imms 0c3f2d7222 Revert "Revert "fix: don't use Math.floor in DomRenderer charWidth computation""
This reverts commit 1feb0a27e9.
2019-05-28 09:49:14 -07:00
Daniel Imms a39da0f0d5 Ensure DOM renderer has styles injected on ctor
Fixes #2136
2019-05-28 09:49:03 -07:00
Daniel Imms adac12eded Merge pull request #2134 from Tyriar/fix_underline
Draw underline over char glyph
2019-05-28 08:49:01 -07:00
Daniel Imms 030fb78712 Merge branch 'master' into fix_underline 2019-05-26 21:19:03 -07:00
Daniel Imms 96b3eb982b Draw underline over char glyph 2019-05-26 21:12:36 -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 5276ad8146 Merge pull request #2133 from Tyriar/remove_scripts
Remove release scripts
2019-05-26 13:17:19 -07:00
Daniel Imms 6ec3a5c1d8 Add mocha
(we never actually declared this)
2019-05-26 13:11:25 -07:00
Daniel Imms 4c42393aa4 Remove release scripts
They're no longer used, azure-pipelines.yml does this now
2019-05-26 13:07:37 -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 1942b4ad51 Merge pull request #2130 from Tyriar/2117_J_tests
Tests for erase in display
2019-05-25 21:34:11 -07:00
Daniel Imms 05ca1cb7dc Up timeouts 2019-05-25 21:25:56 -07:00
Daniel Imms 2f4c5b93fa Merge pull request #2131 from Tyriar/72149_npe
Fix NPE in reflow
2019-05-25 21:23:19 -07:00
Daniel Imms de8d9a720a Fix NPE in reflow
See microsoft/vscode#72149
2019-05-25 21:17:36 -07:00
Daniel Imms 7c2bc70aac Tests for erase in display
Part of #2117
2019-05-25 21:13:47 -07:00
Daniel Imms 44e01ba006 Merge pull request #2128 from Tyriar/1965_optimize_a11y
Only update a11y announcements on animation frame
2019-05-25 19:03:22 -07:00
Daniel Imms 8ffdc14143 Only update a11y announcements on animation frame
Fixes #1965
2019-05-25 11:46:02 -07:00
Daniel Imms fda964b3ea Merge pull request #2127 from jerch/2126_fix
fix losing data after RIS command
2019-05-24 16:39:40 -07:00
Jörg Breitbart b748eca980 fix losing data behind RIS 2019-05-24 23:17:40 +02:00
jerch bbefedb6eb Merge pull request #2125 from jerch/2124_fix_colormode_switches
fix colormode switches
2019-05-24 21:13:59 +02:00
Jörg Breitbart c387180a47 add color mode transition tests 2019-05-24 21:09:11 +02:00
Jörg Breitbart 0e1704f563 cleanup 2019-05-24 20:50:25 +02:00
Daniel Imms b8f55f1c8f Merge pull request #2123 from Tyriar/revert_floor
Revert "fix: don't use Math.floor in DomRenderer charWidth computation"
2019-05-24 06:55:26 -07:00
Daniel Imms a428193424 Merge branch 'master' into revert_floor 2019-05-24 06:50:37 -07:00
Daniel Imms 1feb0a27e9 Revert "fix: don't use Math.floor in DomRenderer charWidth computation"
This reverts commit 23bdb2a6c2.
2019-05-24 06:48:48 -07:00
jerch a92e4adfe2 Merge pull request #2120 from jerch/2108_memory_exhaustion
trim processed chunks from write buffer
2019-05-22 22:28:01 +02:00
Jörg Breitbart 7716e9abda trim already processed chunks 2019-05-22 14:12:15 +02:00
Daniel Imms 6e196da59c Merge pull request #2118 from Tyriar/2117_csi_tests
Add tests for CSI @-I
2019-05-21 22:53:48 -07:00
Daniel Imms 69e8f62149 Make tests way faster by avoiding page reload 2019-05-21 22:43:02 -07:00
Daniel Imms b46757010f Boost timeout of xterm output tests 2019-05-21 22:34:04 -07:00
Daniel Imms a74173adf2 Add tests for CSI @-I
Part of #2117
2019-05-21 22:29:39 -07:00
Daniel Imms c10b18113e Merge pull request #2116 from Tyriar/2097_fix_addon_dispose
Fix new addon dispose
2019-05-21 16:35:28 -07:00
Daniel Imms 7786e59c77 Fix new addon dispose
Fixes #2097
2019-05-21 16:26:50 -07:00
Daniel Imms 10aae5d68a Merge branch 'master' into webgl2 2019-05-21 16:23:05 -07:00
Daniel Imms 9dfac7e674 Merge pull request #2114 from Tyriar/consolidate_api_test_timeout
Move API test timeout to top-level describe
2019-05-21 14:58:37 -07:00
Daniel Imms 922e594fcf Fix lint 2019-05-21 14:51:48 -07:00
Daniel Imms c73aa07135 Merge branch 'master' into consolidate_api_test_timeout 2019-05-21 14:48:22 -07:00
Daniel Imms acea979fe0 Move API test timeout to top-level describe
I learned a thing.
2019-05-21 14:48:03 -07:00
Daniel Imms e4f626e3b6 Merge pull request #2110 from Tyriar/split_out_integration
Split out integration tests into its own job
2019-05-21 14:39:35 -07:00
Daniel Imms 9a4f419820 Merge branch 'master' into split_out_integration 2019-05-21 14:33:27 -07:00
Daniel Imms 209c44898d Merge pull request #2113 from Tyriar/2111_automate_patch_release
Run release against builds on release/* branches
2019-05-21 14:32:12 -07:00
Daniel Imms d3ff32da72 Run release against builds on release/* branches
Fixes #2111
2019-05-21 14:26:28 -07:00
Daniel Imms f81d1cb1cf Increase integration test sleep 2019-05-21 14:20:58 -07:00
Daniel Imms 8f09f58119 Merge branch 'master' into split_out_integration 2019-05-21 12:39:22 -07:00
Daniel Imms ab0eedc513 Fix job name 2019-05-21 11:19:54 -07:00
Daniel Imms 8e460dfe55 Merge pull request #2109 from Tyriar/2107_cursor_report
Fix status reporting
2019-05-21 11:13:32 -07:00
Daniel Imms 37ed1e4796 Split out integration tests into its own job
This will make Linux finish faster and release trigger faster
2019-05-21 11:12:34 -07:00
Daniel Imms d0a3164e99 Fix lint 2019-05-21 11:01:40 -07:00
Daniel Imms 968dd93ba7 Fix status reporting
Fixes #2107
2019-05-21 10:57:26 -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 739723fe92 Merge pull request #2101 from Tyriar/bad_comment_
Remove old comment
2019-05-18 21:21:34 -07:00
Daniel Imms 2f08b87d95 Remove old comment 2019-05-18 21:21:02 -07:00
Daniel Imms eb70ddcba5 Merge pull request #2100 from Tyriar/2099_pausing
Support pausing in RenderCoordinator
2019-05-18 21:19:51 -07:00
Daniel Imms 43015f85f4 Move Renderer ownership to RenderCoordinator 2019-05-18 21:15:18 -07:00
Daniel Imms 87dca56dee Support pausing in RenderCoordinator
This actually removes the pause rendering functionality when the resize
and theme changes but simplifies it as a result, they also rarely happen
especially when off screen/hidden.

Fixes #2099
2019-05-18 20:20:46 -07:00
Daniel Imms 72e6863a7f Merge pull request #2098 from Tyriar/2093_logo_demo
Use logo in demo
2019-05-18 20:05:33 -07:00
Daniel Imms e83aa64794 Merge pull request #2096 from Tyriar/render_coordinator
Introduce RenderCoordinator
2019-05-18 20:03:20 -07:00
Daniel Imms c7416a6eaa Use logo in demo
Fixes #2093
2019-05-18 19:56:28 -07:00
Daniel Imms 9ed5920275 Add some basic fg/bg renderer tests 2019-05-18 19:51:44 -07:00
Daniel Imms 497d31bec3 onThemeChange -> setColors 2019-05-18 19:31:35 -07:00
Daniel Imms 24de302d2f onWindowResize -> onDevicePixelRatioChange 2019-05-18 19:27:06 -07:00
Daniel Imms 5f70b3f3be Move window resize listener to render coordinator 2019-05-18 19:22:51 -07:00
Daniel Imms b64cc0a9de Fix ui project build 2019-05-18 19:16:06 -07:00
Daniel Imms 3e4c1b5a21 Move ScreenDprMonitor to be owned by RenderCoordinator
(and a11y manager)
2019-05-18 19:12:37 -07:00
Daniel Imms f698cafccb Move the renderer events to RenderCoordinator 2019-05-18 19:02:42 -07:00
Daniel Imms 8792bb5f36 Introduce a RenderCoordinator that owns common Renderer logic
Part of #2005
2019-05-18 18:47:44 -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 ac48ef977b Merge pull request #2094 from Tyriar/2005_colormanager
Move ColorManager to ui
2019-05-18 18:16:47 -07:00
Daniel Imms 4119c7d1d7 Move ColorManager ownership to Terminal 2019-05-18 18:10:04 -07:00
Daniel Imms 000fefdead Move ColorManager to ui
Part of #2005
Part of #1507
2019-05-18 17:49:48 -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 33955398e7 Merge pull request #2092 from Tyriar/layering
Move BufferReflow and Marker to core
2019-05-18 09:59:54 -07:00
Daniel Imms dbafc793da Move Marker to core 2019-05-17 23:41:26 -07:00
Daniel Imms 88c1ff6f11 Move BufferReflow to core 2019-05-17 23:37:44 -07:00
Daniel Imms 610c4c9726 Merge pull request #2088 from Tyriar/fix_coveralls
Fix what branch coverage is sent with
2019-05-16 10:47:34 -07:00
Daniel Imms e2214b0239 Fix what branch coverage is sent with 2019-05-16 10:39:53 -07:00
Daniel Imms 23d3a27a6f Merge pull request #2085 from Tyriar/a11y_fix
Add sanity check in AccessibilityManager
2019-05-16 09:58:02 -07:00
Daniel Imms d04016d51f Merge branch 'master' into a11y_fix 2019-05-16 09:52:54 -07:00
Daniel Imms fede301f5f Merge pull request #2081 from Tyriar/xterm-tests
Support debugging integration tests
2019-05-16 09:52:42 -07:00
Daniel Imms a62ec679bd Move readFileSync out of test 2019-05-15 12:49:13 -07:00
Daniel Imms da79fec5c2 Disable failing test on Linux 2019-05-15 11:57:32 -07:00
Daniel Imms 80025804b3 Add sanity check in AccessibilityManager
Fixes #2082
2019-05-15 11:47:15 -07:00
Daniel Imms 955c45906b Merge branch 'master' into xterm-tests 2019-05-13 21:30:33 -07:00
Daniel Imms f331269ef4 Support debugging integration tests 2019-05-13 21:11:56 -07:00
Daniel Imms 9cb6706e2d Merge pull request #2080 from jerch/demo_update
apply attach changes to demo
2019-05-13 21:07:48 -07:00
Daniel Imms b9cfbbea8f xterm-addon-attach@0.1.0-beta8 2019-05-13 20:34:14 -07:00
Jörg Breitbart 58d461bb90 optimize Buffer.concat 2019-05-13 15:33:54 +02:00
Jörg Breitbart 69411916cb make linter happy 2019-05-13 01:45:21 +02:00
Jörg Breitbart 1a596f9608 default to string transport 2019-05-13 01:41:51 +02:00
Jörg Breitbart 67be8c36e7 utf8 switch in server.js 2019-05-13 01:40:54 +02:00
Jörg Breitbart 0b50c06810 Merge branch 'master' into demo_update 2019-05-13 01:25:51 +02:00
Jörg Breitbart 53167df1a8 document utf8 switch in client.ts 2019-05-13 01:24:41 +02:00
jerch eef855601b Merge pull request #1904 from jerch/utf8_input
Support for raw UTF8 input
2019-05-13 01:23:39 +02:00
Jörg Breitbart 6fd5cdd8f1 apply attach changes to demo 2019-05-13 00:58:14 +02:00
Jörg Breitbart c0e9bbe87f Revert "change demo to utf8 input"
This reverts commit e6e5ecc0f2.
2019-05-12 22:17:06 +02:00
Jörg Breitbart 06c292c11d Merge branch 'master' into utf8_input 2019-05-12 22:16:59 +02:00
Jörg Breitbart bda068c5f0 docs 2019-05-12 22:07:14 +02:00
Daniel Imms 031a30b007 Merge pull request #2065 from Tyriar/1128_addons
New addon API
2019-05-12 12:54:45 -07:00
Daniel Imms 3475764946 Types/doc polish 2019-05-12 10:59:26 -07:00
Daniel Imms f90239377b Fix possible infinite loop if addon disposes terminal 2019-05-12 10:47:35 -07:00
Daniel Imms 1502fea431 Remove unused fullscreen addon from demo 2019-05-12 10:41:01 -07:00
Daniel Imms caf8f9d35e Update search addon 2019-05-12 10:39:39 -07:00
Daniel Imms d230f93bde Remove old search addon from demo 2019-05-12 10:25:41 -07:00
Daniel Imms bae125b789 Merge branch 'master' into utf8_input 2019-05-12 10:24:39 -07:00
Daniel Imms eda04bcb23 Add new search addon, move AddonManager to public
Because addons build on top of the API it needs to live in public, the main
reason for this is because the implementation of buffer differs on
public/Terminal and src/Terminal.
2019-05-12 10:22:29 -07:00
Jörg Breitbart 523d562f73 fix missing types 2019-05-12 18:49:23 +02:00
Daniel Imms 0c588a7333 Fix missed merge conflict 2019-05-12 09:45:09 -07:00
Daniel Imms f7612a49d2 Merge remote-tracking branch 'ups/master' into 1128_addons 2019-05-12 09:44:09 -07:00
Daniel Imms 34244248bf Merge pull request #2078 from Tyriar/1443_selection_api
select and getSelectionPosition APIs
2019-05-12 09:40:03 -07:00
Daniel Imms f654044e5e Fix search addon unit tests 2019-05-12 00:17:59 -07:00
Daniel Imms a7fa58cc60 Add API test for getSelectionPosition 2019-05-11 23:59:51 -07:00
Daniel Imms 9ca9f7296e Use new APIs in selection addon 2019-05-11 23:56:34 -07:00
Daniel Imms 5bbbbf7348 Expose getSelectionPosition and select APIs instead 2019-05-11 23:52:38 -07:00
Daniel Imms da7c39e526 Add API test 2019-05-11 23:37:42 -07:00
Daniel Imms 6674f05cc8 Implement setSelection API
Fixes #1443
2019-05-11 23:35:31 -07:00
Daniel Imms 161c7f9339 Use API clearSelection in search addon 2019-05-11 23:22:46 -07:00
Daniel Imms 780e924b21 Use stable API for buffer in search addon 2019-05-11 23:15:04 -07:00
Daniel Imms 1f000054c2 Merge remote-tracking branch 'ups/master' into 1128_addons 2019-05-11 22:48:49 -07:00
Daniel Imms c13d6e5eeb Make write and writeln consistent with writeUtf8 test 2019-05-11 22:29:01 -07:00
Daniel Imms e5dfc56030 Add api test for writeUtf8 2019-05-11 22:24:33 -07:00
Daniel Imms 00423407c1 Clean up 2019-05-11 22:18:18 -07:00
Daniel Imms 2340fcd071 Fix compile and update yarn.lock with utf8 2019-05-11 21:21:36 -07:00
Daniel Imms 59a1749d44 Merge branch 'master' into utf8_input 2019-05-11 21:16:05 -07:00
Daniel Imms 0fae9bb5a8 Merge pull request #2074 from Tyriar/1994_buffer_api
Buffer API
2019-05-11 21:15:55 -07:00
Daniel Imms 70ba349a85 Fix invalid index check, add api tests 2019-05-11 20:58:51 -07:00
Daniel Imms 49574be510 Add warnings to getCell and getLine 2019-05-11 20:49:48 -07:00
Daniel Imms f41e00ed97 Return undefined if cell or line doesn't exist 2019-05-11 20:46:55 -07:00
Jörg Breitbart ce079f399c fix docstring 2019-05-12 00:07:07 +02:00
Jörg Breitbart 7a567d2717 apply time-based limit 2019-05-11 23:10:18 +02:00
Daniel Imms cd3f2609d6 Make tests use buffer API over _core 2019-05-11 12:12:53 -07:00
Daniel Imms 8a929ed142 Add API tests for loadAddon 2019-05-11 11:02:15 -07:00
Daniel Imms 46995fdbc1 Add tests for buffer.getLine 2019-05-11 10:46:00 -07:00
Daniel Imms d694eae6b5 Add some buffer tests 2019-05-11 10:32:53 -07:00
Daniel Imms bce2eae66f Update yarn.lock 2019-05-11 10:15:29 -07:00
Daniel Imms 3554d3e075 Merge branch 'master' into 1128_addons 2019-05-11 10:14:48 -07:00
Daniel Imms eb6deb67f9 Fix build issues 2019-05-11 10:10:31 -07:00
Daniel Imms 7c55e1be9e Merge remote-tracking branch 'ups/master' into 1994_buffer_api 2019-05-11 10:05:31 -07:00
Daniel Imms 7549ca59be Merge branch 'master' into utf8_input 2019-05-11 10:02:14 -07:00
Daniel Imms af81acc50e Merge pull request #2068 from Tyriar/api_tests
API integration tests
2019-05-11 10:00:36 -07:00
Jörg Breitbart f033800554 fix imports 2019-05-11 17:56:26 +02:00
Daniel Imms 623dd56190 Merge pull request #2073 from jerch/2072_remove_instanceof
remove instanceof check
2019-05-11 08:46:22 -07:00
Jörg Breitbart 740604f035 remove instanceof check 2019-05-11 17:21:16 +02:00
Daniel Imms 3f68a60e73 Merge pull request #2067 from starpit/floor
fix: don't use Math.floor in DomRenderer charWidth computation
2019-05-11 00:50:20 -07:00
Daniel Imms 556c56ff94 Merge branch 'master' into api_tests 2019-05-11 00:10:33 -07:00
Daniel Imms dfb5d8e663 Add focus, blur test 2019-05-11 00:00:57 -07:00
Daniel Imms 7562948259 Add tests for all API events 2019-05-10 23:47:28 -07:00
Daniel Imms 34ac1bc502 Fix clearSelection not firing onSelectionChange
Fixes #2070
2019-05-10 23:38:45 -07:00
Daniel Imms 97b176e701 Add selection tests 2019-05-10 23:14:16 -07:00
Daniel Imms 8a5b6b0356 Move puppeteer to devDependencies 2019-05-10 22:58:23 -07:00
Daniel Imms 55d590348c API integration tests
Part of #1247
2019-05-10 22:57:27 -07:00
Nick Mitchell 23bdb2a6c2 fix: don't use Math.floor in DomRenderer charWidth computation
Fixes #2063
2019-05-11 00:59:59 -04:00
Daniel Imms 16aaf6c58c Fix build 2019-05-10 21:08:06 -07:00
Daniel Imms 22c9ad7145 Merge remote-tracking branch 'origin/master' into 1994_buffer_api 2019-05-10 21:04:26 -07:00
Daniel Imms 41a7cabbc2 Merge branch 'master' into 1128_addons 2019-05-10 21:02:55 -07:00
Daniel Imms 724baf22f9 Merge pull request #2066 from Tyriar/lib_import
Fix bad import from lib
2019-05-10 20:52:20 -07:00
Daniel Imms c04ebe974f Fix bad import from lib
Related #1996
2019-05-10 20:51:18 -07:00
Daniel Imms fcee890819 Merge branch 'master' into 1128_addons 2019-05-10 20:47:17 -07:00
Daniel Imms d696046921 Simplify and mark new addon API as experimental 2019-05-10 20:38:08 -07:00
Daniel Imms 518e2734ba Re-introduce original attach and webLinks addons back
We could release this in v3 if we don't break addons like this
2019-05-10 20:30:47 -07:00
Daniel Imms eedcbccb15 Merge remote-tracking branch 'origin/master' into 1128_addons 2019-05-10 20:24:43 -07:00
Daniel Imms d7e6cb17a5 Merge pull request #2062 from Tyriar/windowsMode_typings
Add typings for windowsMode
2019-05-10 19:41:49 -07:00
Daniel Imms b658baf921 Add typings for windowsMode 2019-05-10 16:26:53 -07:00
Daniel Imms 10c6e900ad Merge pull request #2059 from Tyriar/buffer_core
Move BufferLine into core
2019-05-10 15:17:14 -07:00
Daniel Imms b608c9d0ef Merge branch 'master' into buffer_core 2019-05-10 14:57:32 -07:00
Daniel Imms 0e0bcde957 Merge pull request #2061 from Tyriar/fix_beta_off_patch
Make sure beta builds are always on patch version 0
2019-05-10 07:57:33 -07:00
Daniel Imms d735196a30 Make sure beta builds are always on patch version 0 2019-05-10 07:39:42 -07:00
Daniel Imms 59aec69379 Add BufferLine into core and strict null check 2019-05-09 22:19:33 -07:00
Daniel Imms 228ec7b818 Move BufferLine into core 2019-05-09 22:15:32 -07:00
Daniel Imms 7b7fc53157 Move more BufferLine dependencies into core 2019-05-09 22:10:07 -07:00
Daniel Imms f381cdfc33 Move a bunch of types to core 2019-05-09 21:57:33 -07:00
Daniel Imms ac6bced6e7 Merge pull request #2056 from xtermjs/Tyriar-patch-1
Add missing space to typings
2019-05-09 10:12:29 -07:00
Daniel Imms 1a61401cbe Merge pull request #2057 from Tyriar/fix_cd_after_release
Fix beta CD for new major/minor beta versions
2019-05-09 10:12:11 -07:00
Daniel Imms 6d55ab23fd Fix beta CD for new major/minor beta versions 2019-05-09 10:11:25 -07:00
Daniel Imms 3abc090412 Add missing space to typings 2019-05-09 10:02:42 -07:00
Daniel Imms 21f1498977 Merge pull request #2053 from xtermjs/Tyriar-patch-1
Update year in README
2019-05-09 10:00:09 -07:00
Daniel Imms 16c0550d7c Merge pull request #2051 from Tyriar/2019_prepublish
Replace prepublish
2019-05-09 09:59:58 -07:00
Daniel Imms 517d5cfd0e Merge pull request #2050 from Tyriar/2048_demo_line_height
Update terminal dimensions after line height changes
2019-05-09 09:59:49 -07:00
Daniel Imms d363416fb4 Merge pull request #2046 from NizamLZ/fix/2045
Allow + char in URI path
2019-05-09 09:59:36 -07:00
Daniel Imms ffc868a4b8 Merge pull request #2055 from xtermjs/Tyriar-patch-2
v3.13.0
2019-05-09 09:42:56 -07:00
Daniel Imms e40f924913 v3.13.0 2019-05-09 09:37:07 -07:00
Daniel Imms ca1c647442 Merge pull request #2054 from Tyriar/fix_beta_cd
Actually fix beta CD
2019-05-09 08:20:58 -07:00
Daniel Imms 79e182d63f Actually fix beta CD
Part of #2044
2019-05-09 08:20:19 -07:00
Daniel Imms c1b56722d3 Merge pull request #2052 from jflatow/unit-separator
Send the unit separator for C-_, like some other keyboards
2019-05-09 07:56:30 -07:00
Daniel Imms b959fc8d6a Update year in README 2019-05-09 07:49:50 -07:00
Khaja Nizamuddin 48753625f3 Merge branch 'master' into fix/2045 2019-05-09 12:43:25 +05:30
Jared Flatow dc236aeb20 Send the unit separator for C-_, like some other keyboards 2019-05-09 00:06:32 -07:00
Daniel Imms 71886167be Replace prepublish
On prepublishOnly we want to do a full build, on prepare we want
to only build the ts projects so the .d.ts files are avilable.

Fixes #2019
2019-05-08 23:08:39 -07:00
Daniel Imms 4b1c54d634 Update terminal dimensions after line height changes
Fixes #2048
2019-05-08 20:53:24 -07:00
Daniel Imms 2d0937ac1d Merge pull request #2047 from Tyriar/2044_cd_fix
Base the next beta version on the correct current beta
2019-05-08 18:08:18 -07:00
Daniel Imms 0d5cd9582f Base the next beta version on the correct current beta
Fixes #2044
2019-05-08 18:03:06 -07:00
Khaja Nizamuddin e831bdf1ef Allow + char in URI path 2019-05-08 21:06:22 +05:30
Daniel Imms 4729bfaa2d Merge pull request #2043 from cubiclesoft/add_php_app_server
Added PHP App Server to Real-world uses section.
2019-05-07 18:30:04 -07:00
cubiclesoft a88469aac6 Added PHP App Server to Real-world uses section. 2019-05-07 12:07:00 -07:00
jerch d6da010c7e Merge pull request #2035 from jerch/2028_handle_joined_cells
cell representation for joined cells
2019-05-06 22:42:05 +02:00
Daniel Imms c6138edec2 Merge branch 'master' into 2028_handle_joined_cells 2019-05-05 18:55:53 -07:00
Daniel Imms 15a6c9846d Merge pull request #2040 from Tyriar/devcontainer
Add a dev container
2019-05-05 16:06:55 -07:00
Jörg Breitbart ca193ed00d Merge branch 'master' into 2028_handle_joined_cells 2019-05-05 21:54:16 +02:00
Jörg Breitbart ffcdba8d5b simplify JoinedCellData 2019-05-05 21:48:35 +02:00
Daniel Imms d68c441b86 Merge pull request #2038 from roottool/fix-that-webLinks-not-interpreted#1954
Fix that webLinks not interpreted
2019-05-03 21:13:00 -07:00
Daniel Imms 613f877954 Add a dev container
This lets users using VS Code/Docker avoid installing node and the C++
dependencies necessary for running xterm.js.
2019-05-03 21:08:25 -07:00
Daniel Imms a1353a8fb4 Merge pull request #2039 from roottool/refacter-the-css-code-of-cursor-blink
Refactored the CSS code of cursor blink
2019-05-03 12:59:04 -07:00
roottool 4269777f1c Fix: Refactored the css code of keyframes blink 2019-05-04 02:54:38 +09:00
roottool 23eed1b3ea Fix: Changed pathClause 2019-05-04 02:02:26 +09:00
Daniel Imms ebc0083531 Merge pull request #2036 from Tyriar/protect_markers
Make Terminal.markers readonly
2019-05-02 09:45:15 -07:00
Daniel Imms 7d3e2d7da4 Merge branch 'master' into protect_markers 2019-05-02 09:33:24 -07:00
Daniel Imms ea09c6af09 Fix build 2019-05-02 09:23:13 -07:00
Daniel Imms 267357c4de Merge pull request #2032 from Tyriar/task
Add build and test task
2019-05-02 07:54:42 -07:00
Daniel Imms f416bd155a Make compound task the default 2019-05-02 07:53:28 -07:00
Daniel Imms c6a3fb3b42 Merge branch 'master' into task 2019-05-02 07:47:29 -07:00
Daniel Imms cb33c897d2 Merge branch 'master' into protect_markers 2019-04-30 12:20:30 -07:00
Daniel Imms 469d5158a0 Make Terminal.markers readonly 2019-04-30 19:19:41 +00:00
Daniel Imms 766b1745d3 Merge pull request #2027 from Tyriar/auto_release
Automatically release stable builds
2019-04-29 22:50:16 -07:00
Daniel Imms 68182ed162 Merge branch 'master' into auto_release 2019-04-29 22:42:20 -07:00
Daniel Imms d261862ccb Merge pull request #2026 from Tyriar/ui_project
Create UI project, strict null check some more files
2019-04-29 22:41:54 -07:00
Daniel Imms 8d6682a2bc Merge branch 'master' into ui_project 2019-04-29 22:26:28 -07:00
Daniel Imms 63833b59ed Fix lint 2019-04-29 22:24:44 -07:00
Jörg Breitbart 4fd9b3f249 jix joined cell representation as overloaded CellData type 2019-04-30 00:58:18 +02:00
jerch 3f145b8a0c Merge pull request #2034 from jerch/2031_defaultcolor_handling
apply default fg color for uncached chars and underline in canvas renderer
2019-04-29 23:40:18 +02:00
Jörg Breitbart 1f42e7c06a fix fg color for underline 2019-04-29 23:19:16 +02:00
Jörg Breitbart 42b1dca7db add handling for default fg color 2019-04-29 22:33:01 +02:00
Daniel Imms f0c3bab156 Add build and test task 2019-04-29 11:35:42 -07:00
Daniel Imms 4453a1cbf7 Automatically release stable builds
Part of #1921
2019-04-28 03:52:43 +00:00
Daniel Imms 362152004b Move files not in ui project back to root 2019-04-28 02:28:20 +00:00
Daniel Imms 88d5cf46f8 Strict null check ScreenDprMonitor 2019-04-28 02:16:28 +00:00
Daniel Imms ebfa57b71c Strict null check RenderDebouncer 2019-04-28 02:03:41 +00:00
Daniel Imms 4c3082c924 Remove ITerminal dependency in RenderDebouncer 2019-04-28 01:59:40 +00:00
Daniel Imms 672db9437f Create ui project, add Lifecycle 2019-04-28 01:55:56 +00:00
Daniel Imms eb10652e46 Merge branch 'master' into utf8_input 2019-04-27 18:49:46 -07:00
Daniel Imms f4bbfc30f3 Merge pull request #1872 from Tyriar/cd
Setup continuous deployment beta builds
2019-04-27 18:33:46 -07:00
Daniel Imms 65eaea39d3 Base the beta build off of the next minor version 2019-04-28 00:45:51 +00:00
Daniel Imms 70db48b533 Add notice about beta builds in readme 2019-04-28 00:34:44 +00:00
Daniel Imms 779ebe87e5 Merge branch 'master' into cd 2019-04-27 16:52:09 -07:00
Daniel Imms 6237eaa86f Merge pull request #2025 from thebradbain/fix-terminal-resize
Clear line cache on terminal resize
2019-04-27 16:42:30 -07:00
Bradley Bain 736bd53e49 Clear line cache on terminal resize 2019-04-25 21:24:07 -07:00
Daniel Imms 69d43d4a40 Merge branch 'master' into cd 2019-04-14 16:04:49 -07:00
Daniel Imms 017a5b1218 Merge branch 'master' into utf8_input 2019-04-14 12:54:26 -07:00
Daniel Imms c6f785f51a Merge pull request #2014 from starpit/underline
feat: add underline support to DOM renderer
2019-04-14 11:24:25 -07:00
Nick Mitchell 8718d3a4ca feat: add underline support to DOM renderer
part of #1896
2019-04-14 13:47:58 -04:00
Daniel Imms 7aaa1ad0bb Merge pull request #2009 from Tyriar/single_quote
Add vscode setting for single quote style
2019-04-12 09:36:35 -07:00
Daniel Imms fa70aa0983 Merge pull request #2008 from Tyriar/event_emitter_2
Explicit event API
2019-04-11 09:08:15 -07:00
Daniel Imms 89a3931a68 Merge branch 'master' into event_emitter_2 2019-04-11 08:15:19 -07:00
Daniel Imms a0ee09a7bc Add vscode setting for single quote style
This will alwayts use single quotes when TS server does auto imports,
implement interface, etc.
2019-04-11 08:14:18 -07:00
Daniel Imms 94415a227d Merge pull request #1866 from ntchjb/master
Fix search addons: Fix problem of skipping some results and incorrect text selection after resize window
2019-04-10 03:45:58 -04:00
Daniel Imms 0b4ff4bb6b Merge branch 'master' into event_emitter_2 2019-04-10 03:34:37 -04:00
Daniel Imms 4be376d397 Merge branch 'master' into master 2019-04-10 03:31:40 -04:00
Daniel Imms 5362ea195c Add first API test 2019-04-10 00:24:50 -07:00
Daniel Imms b55bedc6af Add terminal API interface to Types.ts
This is needed since the API/public buffer now differs from the TerminalCore's
2019-04-09 21:29:08 -07:00
Daniel Imms cf4b59567b Add tests for new events 2019-04-09 21:01:55 -07:00
Daniel Imms b9bc219ecc Make events in d.ts alphabetical 2019-04-09 20:52:18 -07:00
Daniel Imms f4c7e3fd7d Remove extends EventEmitter from Linkifier 2019-04-09 20:43:42 -07:00
Daniel Imms 36567e60df Remove extends EventEmitter from more classes 2019-04-09 20:36:08 -07:00
Daniel Imms 2e0e24c382 Remove extends EventEmitter from SelectinoManager 2019-04-09 20:26:18 -07:00
Daniel Imms 290bde6163 Convert refresh to EventEmitter2 2019-04-09 20:16:26 -07:00
Daniel Imms db78b75e8b Convert selection to EventEmitter2 2019-04-09 20:05:13 -07:00
Daniel Imms 87328fe293 Convert data to EventEmitter2 2019-04-09 19:53:02 -07:00
Daniel Imms 2c96c262f4 Convert scroll to EventEmitter2 2019-04-09 19:42:53 -07:00
Daniel Imms f111aa27dc Convert linefeed to EventEmitter2 2019-04-09 19:35:41 -07:00
Daniel Imms 8e5d372b81 Convert cursormove to EventEmitter2 2019-04-09 19:31:59 -07:00
Daniel Imms 8b5b64605e Start find previous from the current viewport 2019-04-09 19:53:22 -04:00
Daniel Imms 0c388c69bc Merge branch 'master' into pr/jerch/1904 2019-04-09 19:38:39 -04:00
Daniel Imms 660466d244 Merge pull request #1923 from jerch/fix_1879
signal sequence was finally handled
2019-04-09 11:15:02 -04:00
Daniel Imms dee4429151 Remove unneeded interfaces 2019-04-09 11:11:16 -04:00
Daniel Imms c3d1b0703c Merge branch 'master' into fix_1879 2019-04-09 11:10:17 -04:00
Daniel Imms 71827f7981 Merge branch 'master' into master 2019-04-09 11:01:02 -04:00
Daniel Imms 2d80abe801 Merge branch 'master' into 1128_addons 2019-04-09 10:57:32 -04:00
Daniel Imms 6b0f2170ea Merge branch 'master' into 1994_buffer_api 2019-04-09 10:57:22 -04:00
Daniel Imms a86c2943b8 Merge branch 'master' into event_emitter_2 2019-04-09 10:57:11 -04:00
Daniel Imms cb591f212a Merge pull request #2006 from skavanagh/patch-1
Added Bastillion to Real-world uses
2019-04-09 10:53:08 -04:00
Sean Kavanagh e5f94391ae Update README.md 2019-04-09 09:10:29 -04:00
Daniel Imms 5476f4cb93 Merge pull request #2002 from Tyriar/1932_broken_reflow
Fix reflow case where wrapped line portions ended in \t
2019-04-08 18:59:21 -04:00
Daniel Imms aaf8b80292 Merge branch 'master' into 1932_broken_reflow 2019-04-08 18:51:02 -04:00
Daniel Imms 9ab3d319d1 Merge pull request #2004 from Tyriar/dim_dom_renderer_test
Add a test for dim flag in dom renderer
2019-04-08 10:56:15 -04:00
Daniel Imms efeca49705 Mostly implemented buffer API
Part of #1994
2019-04-07 15:29:37 -04:00
Daniel Imms 267071ead6 Add deprecation message to applyAddon 2019-04-07 15:00:27 -04:00
Daniel Imms 26a80d0d35 Convert to much simpler model 2019-04-07 14:53:09 -04:00
Daniel Imms 49f58f5d25 Merge branch 'master' into 1128_addons 2019-04-07 14:24:29 -04:00
Daniel Imms a0b4ee56f6 Add a test for dim flag in dom renderer 2019-04-07 14:17:38 -04:00
Daniel Imms 6ff81c43f6 Convert marker dispose, selection manager newselection 2019-04-07 14:09:31 -04:00
Daniel Imms 625e168e1b Convert title and resize events 2019-04-07 14:02:11 -04:00
Daniel Imms b2ab89ddaa Merge branch 'master' into event_emitter_2 2019-04-07 13:56:50 -04:00
Daniel Imms 4ace81d994 Merge branch 'master' into 1932_broken_reflow 2019-04-07 13:53:23 -04:00
Daniel Imms 25745777c6 Merge pull request #2003 from Tyriar/fix_merge_problem
Fix compile error from conflicting PRs
2019-04-07 13:53:09 -04:00
Daniel Imms 74b68ac1c7 Fix compile error from conflicting PRs 2019-04-07 13:49:56 -04:00
Daniel Imms 2a4208cf3e Merge branch 'master' into 1932_broken_reflow 2019-04-07 13:48:31 -04:00
Daniel Imms e58033bbac Merge pull request #1895 from jerch/true_color
True color support
2019-04-07 13:45:08 -04:00
Daniel Imms bd92aaf4dc Merge branch 'master' into 1932_broken_reflow 2019-04-07 13:44:29 -04:00
Daniel Imms 3ac313f8e1 Fix reflow larger case
Fixes #1932
2019-04-07 13:18:05 -04:00
Daniel Imms ab44650d87 Fix reflow smaller case related to ended \t chars
Part of #1932
2019-04-07 13:16:20 -04:00
Daniel Imms 11ab4dbd5b Merge pull request #2000 from starpit/dim
feat: add DIM support to DomRenderer
2019-04-07 09:47:51 -04:00
Daniel Imms 92c435a16d Use same dim opacity as canvas renderer 2019-04-07 09:45:54 -04:00
Nick Mitchell ddd02b4968 feat: add DIM support to DomRenderer
part of #1896
2019-04-06 16:04:50 -04:00
Daniel Imms 7e36bf47c6 Have undefined | true mean success 2019-04-06 15:21:20 -04:00
Daniel Imms d6daf40250 Merge branch 'master' into fix_1879 2019-04-06 15:08:58 -04:00
Daniel Imms 09a5fd4e61 Fix capitalization in color mode 2019-04-06 15:06:42 -04:00
Daniel Imms 171b9337cb Make BufferLine enums const 2019-04-06 14:56:15 -04:00
Daniel Imms bb324ba9c1 Move width shift back into enum 2019-04-06 14:55:43 -04:00
Daniel Imms 27283e45e9 Merge branch 'master' into true_color 2019-04-06 14:13:14 -04:00
Daniel Imms 23ce6ce19e Merge pull request #1999 from asadm/master
add CodeInterview.io in README
2019-04-05 11:12:03 -04:00
Asad Memon e8a9994583 add CodeInterview.io in README 2019-04-04 11:58:19 -07:00
Daniel Imms 46f3b3fa62 Merge branch 'master' into true_color 2019-04-04 01:06:26 -04:00
Daniel Imms 2f8d49c74d Convert internal key event usages 2019-04-04 00:45:57 -04:00
Daniel Imms 629238ae70 Use onResize in demo 2019-04-04 00:25:03 -04:00
Daniel Imms 3f9d90ecf6 Remove unnecessary paste listener from demo 2019-04-04 00:23:12 -04:00
Daniel Imms f35dfb496a Use onKey in demo 2019-04-04 00:22:34 -04:00
Daniel Imms 4e6f4be6cc Convert Listener to an interface 2019-04-04 00:14:04 -04:00
Daniel Imms 798cf8abc3 Merge branch 'master' into event_emitter_2 2019-04-04 00:12:07 -04:00
Daniel Imms b591db8c02 Merge pull request #1997 from Tyriar/1989_backspace_demo
Fix backspace on demo
2019-04-04 00:06:09 -04:00
Daniel Imms b18829963c Fix backspace on demo
buffer.x will probably be public API soon (#1994)

Fixes #1989
2019-04-04 00:01:43 -04:00
Daniel Imms e402dba635 Merge pull request #1995 from termius/fix_csi_scroll_down
Fix CSI scroll down handler
2019-04-03 23:57:01 -04:00
Daniel Imms 2023b5b677 Merge pull request #1992 from Tyriar/1990_layering_libs
Ensure DOM APIs cannot be used in common and core
2019-04-03 18:28:53 -04:00
Vadim Zakondyrin 68e3d7fa16 Fix CSI scroll down handler
The issue has been introduced in cd8477a942
2019-04-03 12:10:32 +06:00
Daniel Imms 3f993d675f Fix conflicts with new stuff 2019-04-02 20:17:33 -04:00
Daniel Imms 7ddcf1a2a2 Merge branch 'master' into 1128_addons 2019-04-02 20:16:09 -04:00
Daniel Imms e6333bde2d Merge branch 'master' into true_color 2019-04-02 17:13:21 -07:00
Daniel Imms 51c7337099 Merge branch 'master' into 1990_layering_libs 2019-04-02 17:10:49 -07:00
Daniel Imms 6476429077 Merge pull request #1993 from Tyriar/windows_mode
Replace winptyCompat addon with windowsMode option
2019-04-02 17:08:31 -07:00
Daniel Imms 7b9a718af0 Fix some imports to point at ts files, not lib/ 2019-04-02 16:45:43 -07:00
Daniel Imms 60113fa155 Replace EventEmitter usage in CharMeasure 2019-04-02 11:38:55 -07:00
Daniel Imms 60c2b20d68 Replace EventEmitter usage in BufferSet 2019-04-02 11:35:20 -07:00
Daniel Imms f8fb4da9f4 Replace EventEmitter with EventEmitter2 in CircularList 2019-04-02 11:30:47 -07:00
Daniel Imms 5f014be057 Add onCursorMove, replace .on usage in addons 2019-04-02 11:12:57 -07:00
Daniel Imms b12d2c218e Remove reference to winptyCompat tsconfig 2019-04-02 11:03:24 -07:00
Daniel Imms ba4662ac14 Introduce new onEvent APIs and deprecate on/off/etc.
Part of #1505
2019-04-02 11:01:16 -07:00
Daniel Imms ca1f7f1392 Add EventEmitter2 2019-04-02 10:11:59 -07:00
Daniel Imms fa505111a2 Replace winptyCompat addon with windowsMode option 2019-04-02 08:51:23 -07:00
Daniel Imms 2e10c8c25e Clean up 2019-04-02 08:04:39 -07:00
Daniel Imms 8d4da3c2ac Merge branch 'master' into pr/jerch/1895 2019-04-02 07:53:22 -07:00
Daniel Imms 542c109b99 Merge branch 'master' into webgl2 2019-04-02 06:39:25 -07:00
Daniel Imms 81dda13218 Merge branch 'master' into 1990_layering_libs 2019-04-02 06:35:59 -07:00
Daniel Imms 0a8d57ce74 Merge pull request #1878 from jerch/utf32_buffer
Utf32 buffer
2019-04-01 17:50:09 -07:00
Daniel Imms 5c8c680dac Fix feedback 2019-04-01 00:01:41 -07:00
Daniel Imms 69f8700557 Merge branch 'master' into pr/jerch/1878 2019-03-31 23:34:46 -07:00
Daniel Imms 4a3609f805 Move platform to common and remove dom dependence in common
Because common/ imports 'xterm', it also imported dom accidentally.

Fixes #1990
2019-03-31 23:24:29 -07:00
Daniel Imms fa2cbb0aca Merge branch 'master' into fix_1879 2019-03-30 15:38:53 -07:00
Daniel Imms b05c66b132 Merge pull request #1987 from Tyriar/1986_localhost
Recommend 127.0.0.1:3000 on mac and linux too
2019-03-30 15:36:42 -07:00
Daniel Imms 75046235af Merge pull request #1984 from Tyriar/project_references
Build using TypeScript project references
2019-03-30 15:09:11 -07:00
Daniel Imms bab94ebbdc Merge pull request #1958 from nikonso/1947-weblinks-with-selection
WebLinks plugin don't follow link on selection
2019-03-30 15:07:34 -07:00
Daniel Imms 4d008c66f1 Recommend 127.0.0.1:3000 on mac and linux too
Fixes #1986
2019-03-30 15:06:25 -07:00
Daniel Imms bf9d879efa Fix typo 2019-03-30 14:59:31 -07:00
Daniel Imms 636afa11d6 Merge branch 'master' into 1947-weblinks-with-selection 2019-03-30 14:57:24 -07:00
Daniel Imms 1283123d4d Merge pull request #1985 from Tyriar/fix_demo_non_win
Fix demo on non-Windows
2019-03-30 14:55:00 -07:00
Daniel Imms e182e3d4e4 Fix demo on non-Windows
Broke in #1978
2019-03-30 14:52:48 -07:00
Daniel Imms 51033596ef Merge branch 'master' into 1947-weblinks-with-selection 2019-03-30 14:47:46 -07:00
Daniel Imms 0960a7ae14 Merge branch 'master' into project_references 2019-03-30 14:43:11 -07:00
Daniel Imms 84d5963e7e Merge pull request #1976 from Tyriar/1975_renderer_pause_fix
Fix renderer pausing to not full refresh every time
2019-03-30 14:42:38 -07:00
Daniel Imms 10b7b467b4 Merge pull request #1978 from Tyriar/move_windows_check
Let consumers decide whether winptyCompat should be active
2019-03-30 14:41:58 -07:00
Daniel Imms 2317a319d0 Merge pull request #1982 from Tyriar/1981_prevent_scroll_on_focus
Prevent scroll on focus
2019-03-30 14:40:26 -07:00
Daniel Imms f80924fb8d Remove zmodem demo 2019-03-30 14:12:15 -07:00
Daniel Imms 18f4dc6b3e Remove concurrently 2019-03-30 14:09:51 -07:00
Daniel Imms b400f9ca3b Don't clear terminal on yarn watch 2019-03-30 14:08:57 -07:00
Daniel Imms 0b78011fa3 Adopt project references
Recent versions of TypeScript has improved the performance of project
references so they are now viable to switch over to.
2019-03-30 14:05:24 -07:00
Daniel Imms 2be0a5819b Merge branch 'master' into 1981_prevent_scroll_on_focus 2019-03-29 19:57:33 -07:00
Daniel Imms e346f8bba3 Prevent scroll on focus
Fixes #1981
2019-03-29 19:46:24 -07:00
Daniel Imms 1451bcb6ae Merge pull request #1961 from nikonso:1773-take-drawBoldTextInBrightColors-into-account
Fix #1773 - drawBoldTextInBrightColors is not taken into account with DOM renderer
2019-03-29 12:59:20 -07:00
Daniel Imms f1ef9abc77 Merge pull request #1979 from JesseStolwijk:master
#1977 Add blinking cursor to DomRenderer
2019-03-29 12:51:49 -07:00
Jesse Stolwijk f9df863ee0 Add blinking cursor to DomRenderer 2019-03-25 22:17:16 +01:00
Daniel Imms e6ac5634bb Merge branch 'master' into move_windows_check 2019-03-23 11:38:19 -07:00
Daniel Imms 4dbe8ec1db Let consumers decide whether winptyCompat should be active 2019-03-23 10:58:26 -07:00
Daniel Imms 8b6d564598 Merge pull request #1968 from nikonso/new-feature
Use new vscode serverReadyAction
2019-03-23 09:37:15 -07:00
Daniel Imms 131e4f78bd Fix renderer pausing to not full refresh every time
Fixes #1975
2019-03-23 09:08:55 -07:00
Daniel Imms 99beeb2270 Merge pull request #1973 from zhaojh329/master
Modify uses
2019-03-19 10:46:23 -07:00
Jianhui Zhao 0d63cecc6b Modify uses
Signed-off-by: Jianhui Zhao <jianhuizhao329@gmail.com>
2019-03-19 14:04:16 +08:00
ntchjb 3c444ca39a Fixed coding format 2019-03-15 19:20:23 +07:00
ntchjb 03e648a0fb Fixed the case that, if findPrevious is run without any selection, then start scan at the last row 2019-03-15 19:15:41 +07:00
Max 48a98fa29f Merge pull request #1 from xtermjs/master
update branch
2019-03-15 17:26:55 +07:00
Bruno Ribeito 27ebe8c353 Use new vscode serverReadyAction 2019-03-11 20:58:42 +00:00
Bruno Ribeito 62cfa642cb Better aproach, check i a selection is being performed 2019-03-11 20:54:17 +00:00
Bruno Ribeito c16e3e54e8 Merge branch 'master' of https://github.com/xtermjs/xterm.js into 1947-weblinks-with-selection 2019-03-11 20:41:23 +00:00
Daniel Imms bc86a61a0c Merge pull request #1966 from turtle0x1/master
Add LxdMosaic to list of applications that use xterm.js
2019-03-11 10:29:22 -07:00
turtle0x1 19d36f9228 Update readme with link for lxdmosaic 2019-03-11 13:47:25 +00:00
Bruno Ribeito b4bef0986c Remove circular dependency 2019-03-10 22:03:38 +00: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 f63bd3d218 Merge branch 'master' into master 2019-03-08 11:47:41 -08:00
Daniel Imms 5cf2a21ddd Merge branch 'master' into cd 2019-03-08 11:44:55 -08:00
Daniel Imms 7e1b5cc7e9 Merge pull request #1952 from NickShaffner/master
Fix for issue #812: Xterm.js's encoding of mouse coordinate
2019-03-08 09:50:24 -08:00
Daniel Imms 4046d682c9 v3.12.0 2019-03-08 09:21:01 -08:00
jerch 127a2ca27a Merge branch 'master' into master 2019-03-07 23:28:26 +01:00
Bruno Ribeito 525af9c36a Fix #1773 2019-03-07 21:30:32 +00:00
Bruno Ribeito 5878aa099d Cleaner aproach 2019-03-07 21:00:07 +00:00
Daniel Imms 9597ad20d3 Merge pull request #1950 from Tyriar/1943_winpty_compat_reflow
Disable reflow when winptyCompat is on
2019-03-07 12:38:30 -08:00
Daniel Imms 6deb3e13d2 Merge pull request #1938 from Tyriar/1937_uncached_char_top_fix
Align y draw coord with how cache draws it
2019-03-07 12:38:00 -08:00
Daniel Imms ecb7f429bc Merge branch 'master' into 1937_uncached_char_top_fix 2019-03-07 12:34:57 -08:00
Daniel Imms ce09ae4ff8 Merge pull request #1959 from nikonso/1908-leave-callback
Fix #1908 - leaveCallback does not fire when links are on the edge of the terminal
2019-03-07 11:17:49 -08:00
Bruno Ribeito bc41cc7d27 Fix #1908 2019-03-07 00:15:03 +00:00
Bruno Ribeito 51e2cdfafb WIP: First draft 2019-03-06 21:45:53 +00:00
Daniel Imms f41146fb40 Merge pull request #1934 from ahtshamraziq/fix-docker-compose-variable-substitution
Compose file: fix variable substitution
2019-03-05 08:31:59 -08:00
Daniel Imms 8fa7f177a6 Merge pull request #1956 from JesseStolwijk/master
Replace array shift with offset
2019-03-05 08:18:06 -08:00
Jesse Stolwijk 07430a4892 Replace array shift with offset (#1955) 2019-03-05 00:00:54 +01:00
Daniel Imms ce1c45fb18 Merge pull request #1818 from juancampa/perf3
Use a time-based limit in Terminal._innerWrite
2019-03-04 10:50:27 -08:00
Daniel Imms 55f3aeeff5 Merge branch 'master' into perf3 2019-03-04 10:39:00 -08:00
Daniel Imms 1ecc9dc832 Merge branch 'master' into webgl2 2019-03-04 10:38:20 -08:00
Daniel Imms a99364eae9 Merge branch 'master' into fix_1879 2019-03-04 10:37:51 -08:00
Daniel Imms 7b41b002c6 Merge branch 'master' into master 2019-03-04 10:05:18 -08:00
Daniel Imms 32e157bfaa Remove unnecessary else 2019-03-04 10:04:52 -08:00
Daniel Imms 655c595011 Merge pull request #1927 from pfitzseb/sp/mousehandlerfix
*actually* fix mouse handler before term attached
2019-03-04 10:01:42 -08:00
Daniel Imms 064a372c71 Merge branch 'master' into sp/mousehandlerfix 2019-03-04 10:00:38 -08:00
Daniel Imms c63f15a9b2 Fix lint 2019-03-04 10:00:04 -08:00
Daniel Imms 1aa40eb58b Merge branch 'master' into fix-docker-compose-variable-substitution 2019-03-04 09:57:33 -08:00
Daniel Imms d8b973b126 Merge pull request #1929 from coderaiser/patch-1
fix: Renderer: IntersectionObserver can produce more then 1 entry
2019-03-04 09:54:53 -08:00
Daniel Imms 05b162eefd Merge branch 'master' into patch-1 2019-03-04 09:53:12 -08:00
Daniel Imms 46aa6a40f9 Merge branch 'master' into fix-docker-compose-variable-substitution 2019-03-04 09:49:12 -08:00
Daniel Imms 9f2aec1944 Merge branch 'master' into 1937_uncached_char_top_fix 2019-03-04 09:47:33 -08:00
Daniel Imms 42b66d98b2 Merge branch 'master' into 1943_winpty_compat_reflow 2019-03-04 09:46:15 -08:00
Daniel Imms 1eee182860 Merge pull request #1930 from Tyriar/1926_reflow_larger_fix
Make sure the viewport is filled when reflowing a row change
2019-03-04 09:45:43 -08:00
Daniel Imms bd602fb078 Merge branch 'master' into 1926_reflow_larger_fix 2019-03-04 07:23:06 -08:00
Daniel Imms 8ea254bdc7 Merge pull request #1953 from cherouvim/patch-1
docs: style improvements
2019-03-01 11:26:06 -08:00
Ioannis Cherouvim 09754fddf8 xterm.js references to the library should not be backticked 2019-03-01 21:15:20 +02:00
Ioannis Cherouvim a8a0344d1a docs: style improvements
- Added a trailing dot at the end of each list line.
- Consistent usage of `xterm.js` in "Real-world uses".
2019-03-01 14:51:19 +02:00
Ioannis Cherouvim 4e479b455a docs: Consistent style on lists.
Added some missing dots, capitalized a couple of lines.
2019-03-01 14:40:21 +02:00
Nick Shaffner e178139907 Fix for issue #812: Xterm.js's encoding of mouse coordinate
See: https://github.com/xtermjs/xterm.js/issues/812
Changed the utf-8 mouse encoding to match iTerm
2019-02-27 22:37:22 -08:00
Sebastian Pfitzner 0854f84653 actually fix mouse handler before term attached 2019-02-26 11:31:22 +01:00
Daniel Imms a35cd43395 Merge branch 'master' into 1943_winpty_compat_reflow 2019-02-20 10:02:54 -08:00
Daniel Imms 3285374618 Disable reflow when winptyCompat is on
Fixes #1943
2019-02-20 07:03:40 -08:00
Daniel Imms 6ad6a01c3f Merge pull request #1949 from liuzheng/master
Update README.md
2019-02-20 06:21:08 -08:00
夏虫 e1c1c7a4f2 Update README.md
move it to the bottom
2019-02-20 14:57:16 +08:00
Daniel Imms 437a59d4cd Merge branch 'master' into 1937_uncached_char_top_fix 2019-02-19 07:19:33 -08:00
夏虫 9f29eeed23 Update README.md
(Jumpserver)[https://github.com/jumpserver/] use xterm.js
2019-02-19 17:19:19 +08:00
coderaiser b0f01beb0f Merge branch 'master' into patch-1 2019-02-15 16:57:58 +02:00
Daniel Imms 857ae4b702 Merge pull request #1936 from Tyriar/1935_remove_font_family
Remove font-family from .css file
2019-02-11 07:24:11 -08:00
Daniel Imms c934200c86 Also set font size 2019-02-11 06:07:31 -08:00
Daniel Imms 78426d8a12 Make the composition view use the same font as the terminal 2019-02-11 06:05:14 -08:00
Daniel Imms 817401bbcd Align y draw coord with how cache draws it
Fixes #1937
2019-02-11 05:32:47 -08:00
Daniel Imms 84d7bfeacc Remove font-family from .css file
Fixes #1935
2019-02-11 05:14:55 -08:00
Ahtsham Raziq 92be01dd81 Compose file: fix variable substitution 2019-02-09 23:24:32 +05:00
Daniel Imms d17dfbc73f Cover a case when resizing smaller making y go out of bounds 2019-02-08 12:13:00 -08:00
Daniel Imms ba9ed43acd Merge branch 'master' into utf32_buffer 2019-02-05 11:39:08 -08:00
Daniel Imms b88230db8b Make sure the viewport is filled when reflowing a row change
Fixes #1926
2019-02-05 08:20:16 -08:00
coderaiser 69d3a4667f fix: Renderer: IntersectionObserver can produce more then 1 entry 2019-02-04 13:28:14 +02:00
Daniel Imms abf6a9fa58 Merge pull request #1925 from xtermjs/Tyriar-patch-1
Add roadmap wiki link to README
2019-02-03 15:37:50 -08:00
Daniel Imms ea9d1d7ef0 Merge pull request #1928 from xtermjs/Tyriar-patch-2
Update license year
2019-02-03 15:37:40 -08:00
Daniel Imms f3aac10bbd Update license year 2019-02-03 10:46:20 -08:00
Daniel Imms f30012b985 Merge branch 'master' into fix_1879 2019-02-01 20:03:40 -08:00
Daniel Imms db9aa5c88b Merge pull request #1916 from skyway777:master
Clear selection state if selection doesn't exists
2019-02-01 19:39:25 -08:00
Daniel Imms 1829cb7609 Add roadmap wiki link to README 2019-02-01 19:28:07 -08:00
Daniel Imms 6d6be9bed8 Merge pull request #1924 from xtermjs/Tyriar-patch-1
v3.11.0
2019-02-01 18:29:09 -08:00
Daniel Imms 54a1319f57 v3.11.0 2019-02-01 18:23:10 -08:00
Jörg Breitbart 65dbf88460 apply bright shift for uncached draws 2019-02-01 21:44:51 +01:00
Jörg Breitbart 0c54b1a29e Merge branch 'master' into true_color 2019-02-01 20:59:31 +01:00
Jörg Breitbart 179e5d5892 Merge branch 'master' into utf32_buffer 2019-02-01 20:59:02 +01:00
Jörg Breitbart 6993daef15 Merge branch 'master' into fix_1879 2019-02-01 20:38:45 +01:00
Jörg Breitbart 801db3831d type add methods 2019-02-01 20:32:07 +01:00
Jörg Breitbart e813ae02fc return true from inputhandler methods to signal sequence was handled 2019-02-01 20:28:45 +01:00
Daniel Imms 73ec8a89a0 Merge pull request #1912 from mofux/contextmenu_fix
Make textarea positioning work with css transformations
2019-02-01 09:53:16 -08:00
Jörg Breitbart c2446df966 Merge branch 'utf32_buffer' into true_color 2019-02-01 01:30:29 +01:00
Jörg Breitbart 2de39024be Merge branch 'utf32_buffer' into utf8_input 2019-02-01 01:11:58 +01:00
Jörg Breitbart 079729f1b4 change property getter into methods 2019-02-01 01:10:20 +01:00
Jörg Breitbart ec3a95f727 Merge branch 'utf32_buffer' into utf8_input 2019-01-31 23:32:48 +01:00
Jörg Breitbart c4a5e0862c Merge branch 'utf32_buffer' into true_color 2019-01-31 23:16:23 +01:00
Jörg Breitbart 594797e05b Merge branch 'master' into utf32_buffer 2019-01-31 23:15:50 +01:00
Daniel Imms f5d901944d Merge branch 'master' into webgl2 2019-01-31 14:10:35 -08:00
jerch 682efc7206 Merge pull request #1887 from jerch/fix_linkifier_offset
account empty cells in stringIndexToBufferIndex
2019-01-31 23:07:24 +01:00
jerch 9791d8ab49 Merge branch 'master' into fix_linkifier_offset 2019-01-31 23:02:53 +01:00
Daniel Imms 8e88ce8da5 Merge pull request #1919 from xtermjs/Tyriar-patch-1
Improve docs on Terminal.resize
2019-01-31 14:02:12 -08:00
Daniel Imms 828f14f2ab Improve docs on Terminal.resize 2019-01-31 14:00:39 -08:00
Jörg Breitbart 7b7f85e3cf add test for correct tab handling, docs 2019-01-31 22:56:55 +01:00
Jörg Breitbart 7da40b9d56 Merge branch 'utf32_buffer' into true_color 2019-01-31 22:13:33 +01:00
Jörg Breitbart a1b61e05f9 Merge branch 'master' into utf32_buffer 2019-01-31 21:51:58 +01:00
jerch 21cb9872f3 Merge branch 'master' into fix_linkifier_offset 2019-01-31 20:33:26 +01:00
Daniel Imms 93d3842156 Merge pull request #1917 from Tyriar/vscode67364
Fix various problems with reflow
2019-01-31 09:07:51 -08:00
Daniel Imms db31a44da3 Fix tests 2019-01-30 22:14:47 -08:00
Daniel Imms 33e46682b1 Fix various problems with reflow
- No longer reflow lines where the full unwrapped line contains the cursor
- Add guards to prevent y and ybase becoming invalid values

Part of Microsoft/vscode#67364
Fixes #1910
2019-01-30 21:47:39 -08:00
Nikita Chuklinov fc1692b3eb clear state if selection doesn't exists 2019-01-30 20:34:16 +03:00
Daniel Imms d48982b60e Merge branch 'master' into cd 2019-01-28 07:25:55 -08:00
Daniel Imms 9c72254d3a Bump to 3.11.0 2019-01-28 07:23:58 -08:00
Daniel Imms af6544d6d9 Improve package.json modifications 2019-01-28 07:23:46 -08:00
Jörg Breitbart 39fd6c427d name polishing, docs 2019-01-28 10:42:44 +01:00
Jörg Breitbart ef3c0c0e72 Merge branch 'fix_linkifier_offset' of git+ssh://github.com/jerch/xterm.js into fix_linkifier_offset 2019-01-27 22:23:08 +01:00
Jörg Breitbart 13f0fd0503 Merge branch 'master' into fix_linkifier_offset 2019-01-27 22:22:52 +01:00
Jörg Breitbart c60f9b1468 code formatting 2019-01-27 20:06:58 +01:00
Jörg Breitbart e77e36cbb7 fix typo in HAS_CONTENT 2019-01-27 19:59:13 +01:00
Jörg Breitbart b20730ee4d add more docs 2019-01-27 19:40:28 +01:00
Jörg Breitbart acea73c8ac Merge branch 'master' into utf32_buffer 2019-01-27 19:02:09 +01:00
jerch cc531f1933 Merge pull request #1796 from jerch/typedarray_parser
support typed array in parser
2019-01-27 18:22:08 +01:00
Daniel Imms c1b0c9bbf1 Merge branch 'master' into fix_linkifier_offset 2019-01-27 08:45:57 -08:00
Jörg Breitbart 358d70d721 cleanup gitignore 2019-01-27 17:34:58 +01:00
Jörg Breitbart 975dfc4a5e Merge branch 'typedarray_parser' of git+ssh://github.com/jerch/xterm.js into typedarray_parser 2019-01-27 17:29:41 +01:00
Jörg Breitbart fdf784ea96 Merge branch 'master' into typedarray_parser 2019-01-27 17:29:12 +01:00
Jörg Breitbart e67bef69f4 cleanup types 2019-01-27 17:28:15 +01:00
Daniel Imms 8b6327b563 Merge branch 'master' into master 2019-01-27 08:18:40 -08:00
Daniel Imms 8e37883b90 Merge branch 'master' into typedarray_parser 2019-01-27 08:11:37 -08:00
Daniel Imms ace855d0fe Merge branch 'master' into contextmenu_fix 2019-01-27 07:49:03 -08:00
Daniel Imms 007cac22d2 Merge branch 'master' into cd 2019-01-27 07:29:34 -08:00
Daniel Imms b047045949 Replace hardcoded version 2019-01-27 07:28:04 -08:00
Daniel Imms c7cfca395c Merge pull request #1871 from Tyriar/1867_readonly_api_props
Make Terminal API properties readonly
2019-01-27 07:25:15 -08:00
Daniel Imms a7f2348c63 Merge branch 'master' into 1867_readonly_api_props 2019-01-27 07:17:07 -08:00
Daniel Imms 51a148508e Merge pull request #1900 from Tyriar/cleanup
Remove unused var and unneeded defensive check
2019-01-27 07:16:53 -08:00
Jörg Breitbart 90a41a113a review changes 2019-01-27 13:22:34 +01:00
Thomas Zilz 2a1f25e7dc Make textarea positioning work with css transformations on parent elements 2019-01-27 13:15:37 +01:00
Daniel Imms 7e3b315d91 Merge branch 'master' into perf3 2019-01-26 13:20:32 -08:00
Daniel Imms 3a32a5714c Merge branch 'master' into cleanup 2019-01-26 13:17:32 -08:00
Daniel Imms 273cc45357 Merge branch 'master' into cd 2019-01-26 13:12:40 -08:00
Daniel Imms 4dab31dbe0 Merge branch 'master' into 1867_readonly_api_props 2019-01-26 12:58:13 -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
Jörg Breitbart 87e9789748 more explicit docs for DCS parsers 2019-01-25 18:16:01 +01:00
Jörg Breitbart 4855b60ffe move utf32ToString to TextDecoder.ts 2019-01-25 17:35:12 +01:00
Jörg Breitbart 21165a4286 Merge branch 'master' into typedarray_parser 2019-01-25 16:53:06 +01:00
Daniel Imms c908da351b Merge pull request #1864 from Tyriar/622_reflow3
Reflow text on resize
2019-01-24 20:04:33 -08:00
Daniel Imms 52a429f584 Merge branch 'master' into 622_reflow3 2019-01-24 19:01:21 -08:00
Jörg Breitbart e6447bc91f Merge branch 'master' into true_color 2019-01-25 02:43:52 +01:00
Jörg Breitbart b587c2f30f Merge branch 'master' into utf8_input 2019-01-25 02:43:07 +01:00
Jörg Breitbart 4f531f8490 Merge branch 'master' into utf32_buffer 2019-01-25 02:42:40 +01:00
Jörg Breitbart 19931e75c0 Merge branch 'master' into typedarray_parser 2019-01-25 02:41:56 +01:00
Daniel Imms 2edf02e468 Merge pull request #1905 from pfitzseb/sp/mousehandler
fix mouse event listener change before term attached
2019-01-24 11:49:09 -08:00
Daniel Imms e1363e9fe7 Replace if/add/remove with a toggle 2019-01-24 11:32:09 -08:00
Daniel Imms 109e3a50e8 jsdoc 2019-01-24 10:20:18 -08:00
Daniel Imms 99ac78031c Remove out param from reflow large method 2019-01-24 09:11:16 -08:00
Daniel Imms d4bd8ae2be Pull more parts out of reflow larger 2019-01-23 23:58:38 -08:00
Daniel Imms dfff04cf3d Pull toRemove step into BufferReflow 2019-01-23 23:51:28 -08:00
Daniel Imms deb04ca162 Merge branch 'master' into 622_reflow3 2019-01-23 22:48:53 -08:00
Daniel Imms 178c513407 Clean up 2019-01-23 22:48:32 -08:00
Daniel Imms df7cd9c319 Get reflow smaller working for wide chars 2019-01-23 22:40:40 -08:00
Daniel Imms ce69dceee7 Progress on reflow smaller with wide chars 2019-01-23 21:46:35 -08:00
Juan Campa 3077ae5311 Only apply the selection hack for the WebGL renderer 2019-01-21 18:56:54 -05:00
Daniel Imms 4843ca5bb8 Fix reflow larger with wide chars 2019-01-21 09:08:33 -08:00
Sebastian Pfitzner 8bdb606fd1 fix mouse event listener change before term attached 2019-01-21 11:09:00 +01:00
Jörg Breitbart e6e5ecc0f2 change demo to utf8 input 2019-01-20 23:06:51 +01:00
Jörg Breitbart 3a2076805c Merge branch 'master' into utf8_input 2019-01-20 22:44:15 +01:00
Jörg Breitbart d7ea0edfcf add utf8 input to terminal 2019-01-20 22:19:50 +01:00
Daniel Imms 50abb43e9c Remove request term info handler
We're not supporting it anyway, no point having it.
2019-01-20 12:56:49 -08:00
Jörg Breitbart 6bdd380890 add utf8 decoder 2019-01-20 21:54:58 +01: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 07d3407892 Remove unused var and unneeded defensive check
...items as an arg will always be an array
2019-01-17 09:48:18 -08:00
Daniel Imms 68197ed47b Merge branch 'master' into 622_reflow3 2019-01-16 19:41:46 -08:00
Jörg Breitbart b13b737a07 Merge branch 'master' into true_color 2019-01-17 02:09:44 +01:00
Jörg Breitbart 200f7bf33d Merge branch 'master' into utf32_buffer 2019-01-17 02:09:19 +01:00
Jörg Breitbart 9549896ea5 Merge branch 'master' into typedarray_parser 2019-01-17 02:08:58 +01:00
Jörg Breitbart 2370038523 always draw RGB uncached 2019-01-17 01:41:48 +01:00
Jörg Breitbart df739ab814 remove old color and flag shims 2019-01-17 01:31:59 +01:00
Jörg Breitbart 8d850d6c8b apply CellData to canvas renderer 2019-01-17 01:25:16 +01:00
Jörg Breitbart ae50d84c5a fix characterjoiner to support AttrData 2019-01-17 00:07:25 +01:00
Daniel Imms daaed5ac8f Merge pull request #1897 from juancampa/char-measure-fix
Prevent charsizechanged from firing unnecessarily
2019-01-16 13:07:54 -08: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 e02a9ff09e Prevent charsizechanged from firing unnecessarily 2019-01-15 11:00:34 -05:00
Jörg Breitbart 1536e79542 remove printf remnant 2019-01-15 03:24:47 +01:00
Jörg Breitbart 94c19fb92a preliminarly RGB support in canvas renderer 2019-01-15 03:13:44 +01:00
Jörg Breitbart 9cf479bcfa cleanup rgb channel conversion 2019-01-14 08:51:18 +01:00
Jörg Breitbart 0802582c9b test cases for DOM renderer style changes 2019-01-14 01:00:07 +01:00
Jörg Breitbart 3515c0b220 DOM renderer with RGB support 2019-01-14 00:46:44 +01:00
Jörg Breitbart 70ded42bee follow naming scheme 2019-01-13 23:50:58 +01:00
Jörg Breitbart c444eebd89 RGB support in buffer and attributes 2019-01-13 23:19:56 +01:00
Jörg Breitbart 7c6dad5805 test cases 2019-01-12 19:06:09 +01:00
Jörg Breitbart 40b231edd1 tests for CellData 2019-01-12 18:44:10 +01:00
Jörg Breitbart 35a6aa8326 some docs 2019-01-12 18:04:52 +01:00
Jörg Breitbart 711ae65947 remove get CharData from codebase and deprecate method 2019-01-12 17:50:19 +01:00
Jörg Breitbart ece7192db7 remove set with CharData from codebase and deprecate method 2019-01-12 16:15:24 +01:00
Jörg Breitbart 3e456971b1 change buffer line ctor to new interface 2019-01-12 15:47:50 +01:00
Jörg Breitbart 60a591e8c8 use getNullChar in InputHandler.print 2019-01-12 15:37:20 +01:00
Jörg Breitbart 56dec2849f change resize, fill to new interface, remove _cell on buffer line 2019-01-12 15:21:55 +01:00
Jörg Breitbart fe6919b52a change replaceCells to new interface 2019-01-12 15:05:52 +01:00
Jörg Breitbart 4bf7f3eb89 change deleteCells to new interface 2019-01-12 14:58:30 +01:00
Jörg Breitbart 523ff6e5fc add null and whitespace placeholder cells to buffer 2019-01-12 14:54:54 +01:00
Jörg Breitbart 88a037b309 change insertCells to new interface 2019-01-12 14:34:29 +01:00
Jörg Breitbart ad67f47acb Merge branch 'typedarray_parser' into utf32_buffer 2019-01-12 14:08:53 +01:00
Jörg Breitbart 329d40ab14 cleanup DCS handler 2019-01-12 13:53:43 +01:00
Jörg Breitbart a1f8749411 Merge branch 'typedarray_parser' of git+ssh://github.com/jerch/xterm.js into typedarray_parser 2019-01-12 13:43:55 +01:00
Jörg Breitbart e7e0f67ea8 Merge branch 'master' into typedarray_parser 2019-01-12 13:43:40 +01:00
Jörg Breitbart 907a6b9732 Merge branch 'master' into utf32_buffer 2019-01-12 13:43:11 +01:00
Daniel Imms 7fe3f0a4e3 Improve BufferLine test
Ensure combined is cleared when shrinking and enlarging
2019-01-11 12:58:41 -08:00
ntchjb 9236934586 _findInLine() function should not run multiple times on the same row 2019-01-09 07:01:34 +07:00
Juan Campa 98706aa7d2 Use bg luminance to determine background color 2019-01-08 16:44:57 -05:00
Daniel Imms 932d5c7c21 Merge branch 'master' into master 2019-01-08 10:19:38 -08:00
Daniel Imms 509ce5fa3a Merge pull request #1881 from Tyriar/1880_key_repeat
Don't print keys that print more than a single char
2019-01-07 14:43:20 -08:00
Jörg Breitbart fed430b78c Merge branch 'master' into fix_linkifier_offset 2019-01-07 11:39:52 +01:00
Jörg Breitbart 883ad01bd5 make linter happy 2019-01-07 11:39:16 +01:00
Jörg Breitbart 249f8800af account empty cells in stringIndexToBufferIndex 2019-01-07 11:30:26 +01:00
Daniel Imms 0b8c320579 Merge pull request #1886 from epicfaace/typos
Fix typos
2019-01-06 19:01:35 -08:00
Ashwin Ramaswami f04f2efc52 doc: fix more typos 2019-01-06 15:09:57 -08:00
Ashwin Ramaswami f090fa822d doc: fix typos 2019-01-06 15:07:36 -08:00
jerch 9bcf06f658 Merge branch 'master' into typedarray_parser 2019-01-05 05:04:42 +01:00
jerch 6581eb7d88 fix leftover BufferLineConstructor 2019-01-05 01:47:44 +01:00
jerch 90950e2b00 Merge branch 'master' into 622_reflow3 2019-01-05 01:24:28 +01:00
Jörg Breitbart 62dfa84d5d remove get CharData calls from codebase (beside tests) 2019-01-05 01:01:10 +01:00
Jörg Breitbart b93b774971 direct cell attrs getter 2019-01-04 19:14:56 +01:00
Jörg Breitbart 6552a023c1 remove get from linkifier 2019-01-04 18:46:45 +01:00
Jörg Breitbart 13ffed392d remove get calls from renderer 2019-01-04 18:36:07 +01:00
Jörg Breitbart d7e5977d9a remove leftover 2019-01-04 16:19:01 +01:00
Daniel Imms 7a416aa18f Don't print keys that print more than a single char
Fixes #1880
2019-01-03 22:49:03 -08:00
Daniel Imms 7ba17ca770 Convert web links and attach to modules 2019-01-03 22:19:30 -08:00
Daniel Imms 290394b401 New addon prototype
Part of #1128
2019-01-03 20:22:53 -08:00
Jörg Breitbart 802543f7cf replace set(CharData) with setCell 2019-01-04 02:58:15 +01:00
Jörg Breitbart f3619ab61c fix linter error 2019-01-04 01:33:49 +01:00
Jörg Breitbart 2f66efa49a first try to optimize read access 2019-01-04 01:32:56 +01:00
Jörg Breitbart 75fbda1fe6 further opt for InputHandler.print 2019-01-04 01:32:20 +01:00
Jörg Breitbart b0eecea45a partially apply fast data access in InputHandler.print 2019-01-03 21:40:34 +01:00
Jörg Breitbart f63223f8d8 Merge branch 'master' into utf32_buffer 2019-01-03 21:10:40 +01:00
Jörg Breitbart a2a8c3d47f extend buffer line with more direct access methods 2019-01-03 21:08:18 +01:00
jerch f98572cf71 Merge pull request #1877 from jerch/remove_jsarray_buffer
remove js array based buffer line
2019-01-03 20:55:09 +01:00
Jörg Breitbart ba1582cf3c apply utf32 buffer layout 2019-01-03 19:01:43 +01:00
Jörg Breitbart c668bb1243 remove js array based buffer line 2019-01-03 16:08:40 +01:00
Max b4b6bab000 Merge branch 'master' into master 2019-01-03 16:12:19 +07:00
ntchjb c784a012c7 Fix: update findingRow and cumulativeCols before running _findInLine
to be able to scan unwrapped line at the last row
2019-01-03 15:55:27 +07:00
ntchjb efe22d8cf3 Revert "Support wide characters and combined characters"
This reverts commit f961f90bc8.
2019-01-03 15:32:25 +07:00
Jörg Breitbart 27b91f6b00 speedup utf32ToString conversion 2019-01-03 02:55:11 +01:00
Jörg Breitbart 1fb1f556b1 Merge branch 'master' into typedarray_parser 2019-01-03 00:54:12 +01:00
Jörg Breitbart 8fc66a39e3 switch parse buffer to UTF32 2019-01-03 00:48:00 +01: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
Jörg Breitbart 2918a6763f fix wrongly changed test case 2019-01-02 22:55:50 +01:00
Jörg Breitbart dfc853aef4 add TextDecoder for string to UTF32 2019-01-02 22:50:15 +01:00
Daniel Imms 4db95f253e Build to dist dir in release build 2019-01-02 13:40:06 -08:00
Daniel Imms 805c02fb18 Merge branch 'master' into cd 2019-01-02 12:56:07 -08:00
Daniel Imms d120ef5301 Re-enable condition and dependsOn 2019-01-02 12:55:44 -08:00
Daniel Imms 68fbb2f8c9 Tweak more 2019-01-02 11:53:51 -08:00
Daniel Imms 515cf7878e Tweak var 2019-01-02 11:49:20 -08:00
Daniel Imms a35ad6aa81 Inherit exit code from publish call 2019-01-02 11:39:44 -08:00
Daniel Imms aa2d28e619 Disable dependsOn 2019-01-02 11:37:34 -08:00
Daniel Imms a6c3f94860 Publish to npm as beta 2019-01-02 11:24:06 -08:00
Daniel Imms ff81ce078b Add a release pipelines job 2019-01-02 09:38:40 -08:00
Jörg Breitbart 5fd764a89d dont pullin everything from .vscode folder 2019-01-02 18:10:51 +01:00
Jörg Breitbart 83c734eae3 Merge branch 'typedarray_parser' of git+ssh://github.com/jerch/xterm.js into typedarray_parser 2019-01-02 18:00:31 +01:00
Jörg Breitbart 570cd786cb Merge branch 'master' into typedarray_parser 2019-01-02 18:00:05 +01:00
ntchjb f961f90bc8 Support wide characters and combined characters
- Convert buffer index to string index before searching
- Convert string index to buffer index after searching
- Fix bug when search selection skipped some result
2019-01-01 16:39:23 +07:00
Daniel Imms 338558d86c Make Terminal API properties readonly
Fixes #1867
2018-12-31 20:09:48 -08:00
Daniel Imms 408388130d Merge branch 'master' into webgl2 2018-12-31 19:46:36 -08:00
Daniel Imms 2ce67b89bc Remove unneeded MockTerminal member 2018-12-31 14:43:50 -08:00
Daniel Imms 6559931f34 Add lots of tests 2018-12-31 14:28:52 -08:00
Daniel Imms 840970eac7 Update markers after a reflow 2018-12-31 13:15:23 -08:00
Daniel Imms 40e8618cf5 Discard cut off combined data when resizing BufferLines 2018-12-31 10:26:10 -08:00
Daniel Imms db488ebcc9 Reflow combined chars 2018-12-31 10:18:38 -08:00
Daniel Imms 1612cec3e0 Fix reflow larger bug, add regression test 2018-12-31 09:54:24 -08:00
Daniel Imms 135e31f2ca Speed up reflow larger by batching removals 2018-12-31 08:58:04 -08:00
Daniel Imms b7081abfce Move loop into reflowLarger (adjust indent) 2018-12-31 07:54:16 -08:00
Daniel Imms c9f4a650c6 Clean up comments and todos 2018-12-31 07:26:08 -08:00
Daniel Imms 478742a22e Make reflow small crazy fast
This messy but this drops 100000 scrollback reflow from 87 cols to 40 cols
go from ~18 seconds to < 1 second, 10000 takes around 70ms
2018-12-30 12:14:48 -08:00
ntchjb d94c897754 Fix search addons: be able to search wrapped lines from unwrapped line
by managing column range that is needed to be scanned.
2018-12-29 13:55:14 +07:00
Daniel Imms dde96187fa Keep track of cols/rows inside Buffer 2018-12-28 19:27:38 -08:00
Daniel Imms 4a9f10d062 Remove some of Buffer's dependency on Terminal 2018-12-28 19:22:05 -08:00
Daniel Imms 7435971c32 Merge remote-tracking branch 'origin/master' into 622_reflow3 2018-12-28 19:13:12 -08:00
Max 1b68682b79 Merge branch 'master' into master 2018-12-29 10:12:17 +07:00
ntchjb 565cba9c1a Fix search addons:
- Changed to use `this._terminal.cols` for buffer line length instead.
- Let `_findInLine` check on wrapped line
- Added conditions in `_findInLine`
  - For reverse search, if there is no  selection at given row, then start scan at the end of the string
2018-12-29 09:38:17 +07:00
Daniel Imms 72369e060e Only enable reflow on the normal buffer 2018-12-28 14:55:58 -08:00
Daniel Imms 2a0da173f2 Add a bunch of reflow tests 2018-12-28 14:55:15 -08:00
Daniel Imms a33e8a6af7 Properly shrink rows to cols every time 2018-12-28 12:57:10 -08:00
Daniel Imms 358898daf9 Fix some tests 2018-12-28 11:02:08 -08:00
Daniel Imms 7684f93773 Fix ydisp/ybase after trimming buffer 2018-12-28 01:32:19 -08:00
Daniel Imms ae29dbb133 Fix scrollbar when wrapping beyond single viewport of data 2018-12-28 01:26:49 -08:00
Daniel Imms 3311ed509a Do shrink in reverse, fix up row remove count again 2018-12-28 00:40:30 -08:00
Daniel Imms 8bc04c2fa7 Tidy up 2018-12-27 23:58:57 -08:00
Daniel Imms fa47036982 Fix row removal in reflowLarger 2018-12-27 23:49:59 -08:00
Daniel Imms 314f98f2a6 Mostly working for reflowing to smaller 2018-12-27 23:35:52 -08:00
Daniel Imms 8a50729a98 Reflow wider 2018-12-27 21:58:54 -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 60bc1bb873 Merge branch 'master' into perf3 2018-12-27 13:53:01 -08:00
Daniel Imms d5bffb5395 Merge branch 'master' into typedarray_parser 2018-12-27 13:20:48 -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
Jörg Breitbart ef171bf29f Merge branch 'master' into typedarray_parser 2018-12-15 23:42:08 +01:00
Daniel Imms dc5c2381a8 Merge branch 'master' into perf3 2018-12-12 11:24:34 -08:00
Juan Campa 3d2ae2b01e Removing redundant condition. Clearer variable name 2018-12-09 17:58:44 -05: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
Juan Campa fd34caee23 Use a time-based limit to Terminal._innerWrite
The idea is that it should run for a bit and then let the renderer draw
a frame so that the terminal look responsive. The existing approach
limits the work done using a fixed number elements from the write
buffer so the duration of a frame can vary widely.

This approach looks at the clock to determine when to stop, we basically
allocate an amount of time each frame to write, while the rest can be
used for rendering.

From my tests this change makes the terminal feel a lot smoother.
2018-12-08 00:44:05 -05:00
Jörg Breitbart 2483a98f63 use faster string conversion 2018-11-29 21:13:18 +01:00
Jörg Breitbart 5d3ef759b4 Merge branch 'master' into typedarray_parser 2018-11-29 21:11:07 +01:00
Daniel Imms 6bc9b9b14d Improve constructor use in sliceFallback 2018-11-29 10:26:04 -08:00
Jörg Breitbart a6ef64dcb6 always clear DCS buffer on HOOK 2018-11-29 16:39:17 +01:00
Jörg Breitbart a4e3646640 Merge branch 'master' into typedarray_parser 2018-11-29 16:35:12 +01:00
Jörg Breitbart 591dfd506d fix DCS handler 2018-11-29 16:33:56 +01: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
Jörg Breitbart 14d6960873 Merge remote-tracking branch 'upstream/master' into typedarray_parser 2018-11-23 23:33:56 +01:00
Jörg Breitbart 06e89549a8 typed array support for parser 2018-11-23 23:30:37 +01: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
314 changed files with 29137 additions and 17217 deletions
+22
View File
@@ -0,0 +1,22 @@
FROM node:10
# Configure apt
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get -y install --no-install-recommends apt-utils 2>&1
# Verify git and process tools are installed
RUN apt-get install -y git procps
# Install yarn
RUN apt-get install -y curl apt-transport-https lsb-release \
&& curl -sS https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/pubkey.gpg | apt-key add - 2>/dev/null \
&& echo "deb https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
&& apt-get update \
&& apt-get -y install --no-install-recommends yarn
# Clean up
RUN apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
ENV DEBIAN_FRONTEND=dialog
+9
View File
@@ -0,0 +1,9 @@
{
"name": "xterm.js",
"dockerFile": "Dockerfile",
"appPort": 3000,
"extensions": [
"editorconfig.editorconfig",
"ms-vscode.vscode-typescript-tslint-plugin"
]
}
+6 -5
View File
@@ -2,6 +2,8 @@ node_modules/
*.swp
.lock-wscript
lib/
out/
out-test/
Makefile.gyp
*.Makefile
*.target.gyp.mk
@@ -13,13 +15,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/
+10 -1
View File
@@ -6,6 +6,9 @@
!*.js
!*.json
# Whitelist - css/
!css/**/*.css
# Whitelist - dist/
!dist/**/*.js
!dist/**/*.js.map
@@ -33,16 +36,22 @@
!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/
tslint.json
webpack.config.js
docs/
/.idea/
.vscode/
bin/
build/
fixtures/
coverage/
demo/
.devcontainer/
out/
addons/
+28 -6
View File
@@ -13,7 +13,28 @@
"runtimeArgs": [
"--colors",
"--recursive",
"${workspaceRoot}/lib"
"${workspaceRoot}/out/**/*.test.js"
],
"env": {
"NODE_PATH": "${workspaceRoot}/out"
},
"sourceMaps": true,
"outFiles": [ "${workspaceRoot}/out/**/*.js" ],
"internalConsoleOptions": "openOnSessionStart"
},
{
"type": "node",
"request": "launch",
"name": "Integration Tests",
"cwd": "${workspaceRoot}",
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/mocha",
"windows": {
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/mocha.cmd"
},
"runtimeArgs": [
"--colors",
"--recursive",
"${workspaceRoot}/out/**/*.api.js"
],
"sourceMaps": true,
"outFiles": [ "${workspaceRoot}/lib/**/*.js" ],
@@ -23,10 +44,7 @@
"type": "chrome",
"request": "launch",
"name": "Demo Client",
"url": "http://0.0.0.0:3000",
"windows": {
"url": "http://127.0.0.1:3000"
},
"url": "http://127.0.0.1:3000",
"webRoot": "${workspaceFolder}/"
},
{
@@ -38,7 +56,11 @@
"run",
"start-debug"
],
"port": 9229
"port": 9229,
"serverReadyAction": {
"action": "openExternally",
"pattern": "App listening to (http://.*?:[0-9]+)"
}
}
]
}
+3
View File
@@ -0,0 +1,3 @@
{
"typescript.preferences.quoteStyle": "single"
}
+51
View File
@@ -0,0 +1,51 @@
{
"version": "2.0.0",
"presentation": {
"echo": false,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": true
},
"tasks": [
{
"type": "npm",
"script": "test",
"group": "test",
"problemMatcher": []
},
{
"type": "npm",
"script": "watch",
"group": "build",
"isBackground": true,
"problemMatcher": [],
"presentation": {
"group": "vscode"
}
},
{
"type": "npm",
"script": "start",
"group": "build",
"isBackground": true,
"problemMatcher": [],
"presentation": {
"group": "vscode"
}
},
{
"label": "Start demo",
"dependsOn": ["npm: watch", "npm: start"],
"group": {
"kind": "build",
"isDefault": true
},
"isBackground": true,
"problemMatcher": [],
"presentation": {
"group": "vscode"
}
}
]
}
+6 -6
View File
@@ -33,21 +33,21 @@ opening an issue, read these pointers.
You can find issues to work on by looking at the [help wanted](https://github.com/xtermjs/xterm.js/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) or [good first issue](https://github.com/xtermjs/xterm.js/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) issues. It's a good idea to comment on the issue saying that you're taking it, just in case someone else comes along and you duplicate work. Once you have your issue, here are the steps to contribute:
- Fork [xterm.js](https://github.com/sourcelair/xterm.js/)
([how to fork a repo](https://help.github.com/articles/fork-a-repo))
- Get the [xterm.js demo](https://github.com/xtermjs/xterm.js/wiki/Contributing#running-the-demo) running
- Make your changes
([how to fork a repo](https://help.github.com/articles/fork-a-repo)).
- Get the [xterm.js demo](https://github.com/xtermjs/xterm.js/wiki/Contributing#running-the-demo) running.
- Make your changes.
- If your changes are easy to test or likely to regress, add tests. Tests go into `test`, directory.
- Follow the general code style of the rest of the project (see below).
- Submit a pull request
([how to create a pull request](https://help.github.com/articles/fork-a-repo)).
Don't put more than one feature/fix in a single pull request.
By contributing code to xterm.js you
By contributing code to xterm.js you:
- agree to license the contributed code under xterm.js' [MIT
- Agree to license the contributed code under xterm.js' [MIT
license](LICENSE).
- confirm that you have the right to contribute and license the code
- Confirm that you have the right to contribute and license the code
in question. (Either you hold all rights on the code, or the rights
holder has explicitly granted the right to use it like this,
through a compatible open source license or through a direct
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2017-2018, The xterm.js authors (https://github.com/xtermjs/xterm.js)
Copyright (c) 2017-2019, The xterm.js authors (https://github.com/xtermjs/xterm.js)
Copyright (c) 2014-2016, SourceLair Private Company (https://www.sourcelair.com)
Copyright (c) 2012-2013, Christopher Jeffrey (https://github.com/chjj/)
+63 -53
View File
@@ -1,23 +1,22 @@
# [![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
- **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
- **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.
- **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.
- **And much more**: Links, theming, addons, well documented API, etc.
## What xterm.js is not
- Xterm.js is not a terminal application that you can download and use on your computer
- Xterm.js is not `bash`. Xterm.js can be connected to processes like `bash` and let you interact with them (provide input, receive output)
- Xterm.js is not a terminal application that you can download and use on your computer.
- Xterm.js is not `bash`. Xterm.js can be connected to processes like `bash` and let you interact with them (provide input, receive output).
## Getting Started
@@ -33,15 +32,15 @@ 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>
<script>
var term = new Terminal();
term.open(document.getElementById('terminal'));
      term.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ ')
term.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ ')
</script>
</body>
</html>
@@ -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.
@@ -106,17 +100,17 @@ Note that some APIs are marked *experimental*, these are added to enable experim
## Real-world uses
Xterm.js is used in several world-class applications to provide great terminal experiences.
- [**SourceLair**](https://www.sourcelair.com/): In-browser IDE that provides its users with fully-featured Linux terminals based on xterm.js
- [**Microsoft Visual Studio Code**](http://code.visualstudio.com/): Modern, versatile and powerful open source code editor that provides an integrated terminal based on xterm.js
- [**ttyd**](https://github.com/tsl0922/ttyd): A command-line tool for sharing terminal over the web, with fully-featured terminal emulation based on xterm.js
- [**SourceLair**](https://www.sourcelair.com/): In-browser IDE that provides its users with fully-featured Linux terminals based on xterm.js.
- [**Microsoft Visual Studio Code**](http://code.visualstudio.com/): Modern, versatile and powerful open source code editor that provides an integrated terminal based on xterm.js.
- [**ttyd**](https://github.com/tsl0922/ttyd): A command-line tool for sharing terminal over the web, with fully-featured terminal emulation based on xterm.js.
- [**Katacoda**](https://www.katacoda.com/): Katacoda is an Interactive Learning Platform for software developers, covering the latest Cloud Native technologies.
- [**Eclipse Che**](http://www.eclipse.org/che): Developer workspace server, cloud IDE, and Eclipse next-generation IDE.
- [**Codenvy**](http://www.codenvy.com): Cloud workspaces for development teams.
- [**CoderPad**](https://coderpad.io): Online interviewing platform for programmers. Run code in many programming languages, with results displayed by `xterm.js`.
- [**WebSSH2**](https://github.com/billchurch/WebSSH2): A web based SSH2 client using `xterm.js`, socket.io, and ssh2.
- [**CoderPad**](https://coderpad.io): Online interviewing platform for programmers. Run code in many programming languages, with results displayed by xterm.js.
- [**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`.
- [**Codevolve**](https://www.codevolve.com "Codevolve"): 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.
@@ -124,9 +118,8 @@ Xterm.js is used in several world-class applications to provide great terminal e
- [**Hexlet**](https://en.hexlet.io): Practical programming courses (JavaScript, PHP, Unix, databases, functional programming). A steady path from the first line of code to the first job.
- [**Selenoid UI**](https://github.com/aerokube/selenoid-ui): Simple UI for the scallable golang implementation of Selenium Hub named Selenoid. We use XTerm for streaming logs over websockets from docker containers.
- [**Portainer**](https://portainer.io): Simple management UI for Docker.
- [**SSHy**](https://github.com/stuicey/SSHy): HTML5 Based SSHv2 Web Client with E2E encryption utilising `xterm.js`, SJCL & websockets.
- [**JupyterLab**](https://github.com/jupyterlab/jupyterlab): An extensible
computational environment for Jupyter, supporting interactive data science and scientific computing across all programming languages.
- [**SSHy**](https://github.com/stuicey/SSHy): HTML5 Based SSHv2 Web Client with E2E encryption utilising xterm.js, SJCL & websockets.
- [**JupyterLab**](https://github.com/jupyterlab/jupyterlab): An extensible computational environment for Jupyter, supporting interactive data science and scientific computing across all programming languages.
- [**Theia**](https://github.com/theia-ide/theia): Theia is a cloud & desktop IDE framework implemented in TypeScript.
- [**Opshell**](https://github.com/ricktbaker/opshell) Ops Helper tool to make life easier working with AWS instances across multiple organizations.
- [**Proxmox VE**](https://www.proxmox.com/en/proxmox-ve): Proxmox VE is a complete open-source platform for enterprise virtualization. It uses xterm.js for container terminals and the host shell.
@@ -137,23 +130,30 @@ computational environment for Jupyter, supporting interactive data science and s
- [**Kubebox**](https://github.com/astefanutti/kubebox): Terminal console for Kubernetes clusters.
- [**Azure Cloud Shell**](https://shell.azure.com): Azure Cloud Shell is a Microsoft-managed admin machine built on Azure, for Azure.
- [**atom-xterm**](https://atom.io/packages/atom-xterm): Atom plugin for providing terminals inside your Atom workspace.
- [**rtty**](https://github.com/zhaojh329/rtty): A reverse proxy WebTTY. It is composed of the client and the server.
- [**Pisth**](https://github.com/ColdGrub1384/Pisth): An SFTP and SSH client for iOS
- [**rtty**](https://github.com/zhaojh329/rtty): Access your terminals from anywhere via the web.
- [**Pisth**](https://github.com/ColdGrub1384/Pisth): An SFTP and SSH client for iOS.
- [**abstruse**](https://github.com/bleenco/abstruse): Abstruse CI is a continuous integration platform based on Node.JS and Docker.
- [**Azure Data Studio**](https://github.com/Microsoft/azuredatastudio): A data management tool that enables working with SQL Server, Azure SQL DB and SQL DW from Windows, macOS and Linux.
- [**FreeMAN**](https://github.com/matthew-matvei/freeman): A free, cross-platform file manager for power users
- [**FreeMAN**](https://github.com/matthew-matvei/freeman): A free, cross-platform file manager for power users.
- [**Fluent Terminal**](https://github.com/felixse/FluentTerminal): A terminal emulator based on UWP and web technologies.
- [**Hyper**](https://hyper.is): A terminal built on web technologies
- [**Hyper**](https://hyper.is): A terminal built on web technologies.
- [**Diag**](https://diag.ai): A better way to troubleshoot problems faster. Capture, share and reapply troubleshooting knowledge so you can focus on solving problems that matter.
- [**GoTTY**](https://github.com/yudai/gotty): A simple command line tool that shares your terminal as a web application based on xterm.js.
- [**genact**](https://github.com/svenstaro/genact): A nonsense activity generator.
- [**cPanel & WHM**](https://cpanel.com): The hosting platform of choice.
- [**Nutanix**](https://github.com/nutanix): Nutanix Enterprise Cloud uses xterm in the webssh functionality within Nutanix Calm, and is also looking to move our old noserial (termjs) functionality to xterm.js
- [**Nutanix**](https://github.com/nutanix): Nutanix Enterprise Cloud uses xterm in the webssh functionality within Nutanix Calm, and is also looking to move our old noserial (termjs) functionality to xterm.js.
- [**SSH Web Client**](https://github.com/roke22/PHP-SSH2-Web-Client): SSH Web Client with PHP.
- [**Shellvault**](https://www.shellvault.io): The cloud-based SSH terminal you can access from anywhere.
- [**Juno**](http://junolab.org/): A flexible Julia IDE, based on Atom.
- [**webssh**](https://github.com/huashengdun/webssh): Web based ssh client.
- [**info-beamer hosted**](https://info-beamer.com): Uses Xterm.js to manage digital signage devices from the web dashboard.
- [**info-beamer hosted**](https://info-beamer.com): Uses xterm.js to manage digital signage devices from the web dashboard.
- [**Jumpserver**](https://github.com/jumpserver/luna): Jumpserver Luna project, Jumpserver is a bastion server project, Luna use xterm.js for web terminal emulation.
- [**LxdMosaic**](https://github.com/turtle0x1/LxdMosaic): Uses xterm.js to give terminal access to containers through LXD
- [**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.
[And much more...](https://github.com/xtermjs/xterm.js/network/dependents)
@@ -163,7 +163,17 @@ Do you use xterm.js in your application as well? Please [open a Pull Request](ht
Xterm.js follows a monthly release cycle roughly.
All current and past releases are available on this repo's [Releases page](https://github.com/sourcelair/xterm.js/releases), while a rough roadmap is available by looking through [Milestones](https://github.com/sourcelair/xterm.js/milestones).
All current and past releases are available on this repo's [Releases page](https://github.com/sourcelair/xterm.js/releases), you can view the [high-level roadmap on the wiki](https://github.com/xtermjs/xterm.js/wiki/Roadmap) and see what we're working on now by looking through [Milestones](https://github.com/sourcelair/xterm.js/milestones).
### Beta builds
Our CI releases beta builds to npm for every change that goes into master, install the latest beta build with:
```
npm install -S xterm@beta
```
These should generally be stable but some bugs may slip in, we recommend using the beta build primarily to test out new features and for verifying bug fixes.
## Contributing
@@ -173,6 +183,6 @@ You can read the [guide on the wiki](https://github.com/xtermjs/xterm.js/wiki/Co
If you contribute code to this project, you are implicitly allowing your code to be distributed under the MIT license. You are also implicitly verifying that all code is your original work.
Copyright (c) 2017-2018, [The xterm.js authors](https://github.com/xtermjs/xterm.js/graphs/contributors) (MIT License)<br>
Copyright (c) 2017-2019, [The xterm.js authors](https://github.com/xtermjs/xterm.js/graphs/contributors) (MIT License)<br>
Copyright (c) 2014-2017, SourceLair, Private Company ([www.sourcelair.com](https://www.sourcelair.com/home)) (MIT License)<br>
Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
+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 { FitAddon } 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.2.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": "^3.14.0"
}
}
@@ -0,0 +1,71 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import * as puppeteer from 'puppeteer';
import { assert } from 'chai';
import { ITerminalOptions } from 'xterm';
import WebSocket = require('ws');
const APP = 'http://127.0.0.1:3000/test';
let browser: puppeteer.Browser;
let page: puppeteer.Page;
const width = 800;
const height = 600;
describe('AttachAddon', () => {
before(async function(): Promise<any> {
this.timeout(20000);
browser = await puppeteer.launch({
headless: process.argv.indexOf('--headless') !== -1,
slowMo: 80,
args: [`--window-size=${width},${height}`]
});
page = (await browser.pages())[0];
await page.setViewport({ width, height });
});
after(async () => {
await browser.close();
});
beforeEach(async function(): Promise<any> {
this.timeout(20000);
await page.goto(APP);
});
it('string', async function(): Promise<any> {
this.timeout(20000);
await openTerminal({ 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}')))`);
assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString(true)`), 'foo');
server.close();
});
it('utf8', async function(): Promise<any> {
this.timeout(20000);
await openTerminal({ 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}'), { inputUtf8: true }))`);
assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString(true)`), 'foo');
server.close();
});
});
async function openTerminal(options: ITerminalOptions = {}): Promise<void> {
await page.evaluate(`window.term = new Terminal(${JSON.stringify(options)})`);
await page.evaluate(`window.term.open(document.querySelector('#terminal-container'))`);
if (options.rendererType === 'dom') {
await page.waitForSelector('.xterm-rows');
} else {
await page.waitForSelector('.xterm-text-layer');
}
}
@@ -0,0 +1,71 @@
/**
* 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;
inputUtf8?: boolean;
}
export class AttachAddon implements ITerminalAddon {
private _socket: WebSocket;
private _bidirectional: boolean;
private _utf8: 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;
this._utf8 = !!(options && options.inputUtf8);
}
public activate(terminal: Terminal): void {
if (this._utf8) {
this._disposables.push(addSocketListener(this._socket, 'message',
(ev: MessageEvent | Event | CloseEvent) => terminal.writeUtf8(new Uint8Array((ev as any).data as ArrayBuffer))));
} else {
this._disposables.push(addSocketListener(this._socket, 'message',
(ev: MessageEvent | Event | CloseEvent) => terminal.write((ev as any).data as string)));
}
if (this._bidirectional) {
this._disposables.push(terminal.onData(data => this._sendData(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);
}
}
function addSocketListener(socket: WebSocket, type: string, handler: (this: WebSocket, ev: MessageEvent | Event | CloseEvent) => any): IDisposable {
socket.addEventListener(type, handler);
return {
dispose: () => {
if (!handler) {
// Already disposed
return;
}
socket.removeEventListener(type, handler);
}
};
}
@@ -1,23 +1,19 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"target": "es2015",
"lib": [
"dom",
"es5",
"es2015"
],
"rootDir": ".",
"outDir": "../../../lib/addons/webLinks/",
"outDir": "../out",
"sourceMap": true,
"removeComments": true,
"declaration": true,
"preserveWatchOutput": true,
"types": [
"../../node_modules/@types/mocha"
]
"strict": true
},
"include": [
"**/*.ts",
"./**/*",
"../../../typings/xterm.d.ts"
]
}
@@ -0,0 +1,29 @@
/**
* 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;
/**
* Whether to use UTF8 binary transport for incoming messages. Defaults to `false`.
* Note: This must be in line with the server side of the websocket.
* Always send string messages from the backend if this options is false,
* otherwise always binary UTF8 data.
*/
inputUtf8?: 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.2.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": "^3.14.0"
}
}
+79
View File
@@ -0,0 +1,79 @@
/**
* 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;
}
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 = (<any>this._terminal)._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.parentElement) {
return undefined;
}
// TODO: Remove reliance on private API
const core = (<any>this._terminal)._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.floor(availableWidth / core._renderService.dimensions.actualCellWidth),
rows: Math.floor(availableHeight / core._renderService.dimensions.actualCellHeight)
};
return geometry;
}
}
@@ -4,20 +4,16 @@
"target": "es5",
"lib": [
"dom",
"es5"
"es2015"
],
"rootDir": ".",
"outDir": "../../../lib/addons/fit/",
"outDir": "../out",
"sourceMap": true,
"removeComments": true,
"declaration": true,
"preserveWatchOutput": true,
"types": [
"../../node_modules/@types/mocha"
]
"strict": true
},
"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.
+21
View File
@@ -0,0 +1,21 @@
{
"name": "xterm-addon-search",
"version": "0.2.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": "^3.14.0"
}
}
@@ -0,0 +1,129 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import * as puppeteer from 'puppeteer';
import { assert } from 'chai';
import { ITerminalOptions } from 'xterm';
const APP = 'http://127.0.0.1:3000/test';
let browser: puppeteer.Browser;
let page: puppeteer.Page;
const width = 800;
const height = 600;
describe('Search Tests', function (): void {
this.timeout(200000);
before(async function (): Promise<any> {
browser = await puppeteer.launch({
headless: process.argv.indexOf('--headless') !== -1,
slowMo: 80,
args: [`--window-size=${width},${height}`]
});
page = (await browser.pages())[0];
await page.setViewport({ width, height });
await page.goto(APP);
await openTerminal();
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('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(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('package.json pack package.lock');
await page.evaluate(`window.search.findPrevious('pack', {incremental: true})`);
let line: string = await page.evaluate(`window.term.buffer.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.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('package.jsonc');
await page.evaluate(`window.search.findNext('pack', {incremental: true})`);
let line: string = await page.evaluate(`window.term.buffer.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.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('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');
});
});
async function openTerminal(options: ITerminalOptions = {}): Promise<void> {
await page.evaluate(`window.term = new Terminal(${JSON.stringify(options)})`);
await page.evaluate(`window.term.open(document.querySelector('#terminal-container'))`);
if (options.rendererType === 'dom') {
await page.waitForSelector('.xterm-rows');
} else {
await page.waitForSelector('.xterm-text-layer');
}
}
async function writeSync(data: string): Promise<void> {
await page.evaluate(`window.term.write('${data}');`);
while (true) {
if (await page.evaluate(`window.term._core.writeBuffer.length === 0`)) {
break;
}
}
}
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,27 +3,43 @@
* @license MIT
*/
import { ISearchHelper, ISearchAddonTerminal, ISearchOptions, ISearchResult } from './Interfaces';
import { Terminal, IDisposable, ITerminalAddon } from 'xterm';
export interface ISearchOptions {
regex?: boolean;
wholeWord?: boolean;
caseSensitive?: boolean;
incremental?: boolean;
}
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.
@@ -32,46 +48,48 @@ export class SearchHelper implements ISearchHelper {
* @return Whether a result was found.
*/
public findNext(term: string, searchOptions?: ISearchOptions): boolean {
const selectionManager = this._terminal._core.selectionManager;
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) {
selectionManager.clearSelection();
this._terminal.clearSelection();
return false;
}
let startCol: number = 0;
let startRow = this._terminal._core.buffer.ydisp;
let startCol = 0;
let startRow = 0;
if (selectionManager.selectionEnd) {
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
if (this._terminal.getSelection().length !== 0) {
startRow = incremental ? selectionManager.selectionStart[1] : selectionManager.selectionEnd[1];
startCol = incremental ? selectionManager.selectionStart[0] : selectionManager.selectionEnd[0];
}
const currentSelection = this._terminal.getSelectionPosition()!;
startRow = incremental ? currentSelection.startRow : currentSelection.endRow;
startCol = incremental ? currentSelection.startColumn : currentSelection.endColumn;
}
this._initLinesCache();
// Search startRow
result = this._findInLine(term, startRow, startCol, searchOptions);
let result = this._findInLine(term, startRow, startCol, searchOptions);
// Search from startRow + 1 to end
if (!result) {
for (let y = startRow + 1; y < this._terminal._core.buffer.ybase + this._terminal.rows; y++) {
for (let y = startRow + 1; y < this._terminal.buffer.baseY + this._terminal.rows; y++) {
// 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);
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 <= startRow; y++) {
// 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++) {
result = this._findInLine(term, y, 0, searchOptions);
if (result) {
break;
@@ -91,47 +109,52 @@ export class SearchHelper implements ISearchHelper {
* @return Whether a result was found.
*/
public findPrevious(term: string, searchOptions?: ISearchOptions): boolean {
const selectionManager = this._terminal._core.selectionManager;
let result: ISearchResult;
if (!this._terminal) {
throw new Error('Cannot use addon until it has been loaded');
}
if (!term || term.length === 0) {
selectionManager.clearSelection();
this._terminal.clearSelection();
return false;
}
const isReverseSearch = true;
let startRow = this._terminal._core.buffer.ydisp;
let startCol: number = this._terminal._core.buffer.lines.get(startRow).length;
if (selectionManager.selectionStart) {
// Start from the selection start if there is a selection
if (this._terminal.getSelection().length !== 0) {
startRow = selectionManager.selectionStart[1];
startCol = selectionManager.selectionStart[0];
}
let startRow = this._terminal.buffer.baseY + this._terminal.rows;
let startCol = this._terminal.cols;
let result: ISearchResult | undefined = undefined;
const incremental = searchOptions ? searchOptions.incremental : false;
if (this._terminal.hasSelection()) {
const currentSelection = this._terminal.getSelectionPosition()!;
// Start from selection start if there is a selection
startRow = currentSelection.startRow;
startCol = currentSelection.startColumn;
}
this._initLinesCache();
// Search startRow
result = this._findInLine(term, startRow, startCol, searchOptions, isReverseSearch);
if (incremental) {
result = this._findInLine(term, startRow, startCol, searchOptions, false);
if (!(result && result.row === startRow && result.col === startCol)) {
result = this._findInLine(term, startRow, startCol, searchOptions, true);
}
} else {
result = this._findInLine(term, startRow, startCol, searchOptions, isReverseSearch);
}
// Search from startRow - 1 to top
if (!result) {
startCol = this._terminal.cols;
for (let y = startRow - 1; y >= 0; y--) {
result = this._findInLine(term, y, this._terminal._core.buffer.lines.get(y).length, searchOptions, isReverseSearch);
result = this._findInLine(term, y, startCol, 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._core.buffer.ybase + this._terminal.rows - 1;
for (let y = searchFrom; y >= startRow; y--) {
result = this._findInLine(term, y, this._terminal._core.buffer.lines.get(y).length, searchOptions, isReverseSearch);
// If we hit the top and didn't search from the very bottom wrap back down
if (!result && startRow !== (this._terminal.buffer.baseY + this._terminal.rows)) {
for (let y = (this._terminal.buffer.baseY + this._terminal.rows); y > startRow; y--) {
result = this._findInLine(term, y, startCol, searchOptions, isReverseSearch);
if (result) {
break;
}
@@ -146,9 +169,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._core.buffer.length);
this._terminal.on('cursormove', this._destroyLinesCache);
this._linesCache = new Array(terminal.buffer.length);
this._cursorMoveListener = terminal.onCursorMove(() => this._destroyLinesCache());
this._resizeListener = terminal.onResize(() => this._destroyLinesCache());
}
window.clearTimeout(this._linesCacheTimeoutId);
@@ -156,8 +181,15 @@ export class SearchHelper implements ISearchHelper {
}
private _destroyLinesCache(): void {
this._linesCache = null;
this._terminal.off('cursormove', this._destroyLinesCache);
this._linesCache = undefined;
if (this._cursorMoveListener) {
this._cursorMoveListener.dispose();
this._cursorMoveListener = undefined;
}
if (this._resizeListener) {
this._resizeListener.dispose();
this._resizeListener = undefined;
}
if (this._linesCacheTimeoutId) {
window.clearTimeout(this._linesCacheTimeoutId);
this._linesCacheTimeoutId = 0;
@@ -172,7 +204,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)));
}
/**
@@ -186,14 +218,17 @@ export class SearchHelper implements ISearchHelper {
* @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 {
if (this._terminal._core.buffer.lines.get(row).isWrapped) {
protected _findInLine(term: string, row: number, col: number, searchOptions: ISearchOptions = {}, isReverseSearch: boolean = false): ISearchResult | undefined {
const terminal = this._terminal!;
// Ignore wrapped lines, only consider on unwrapped line (first row of command string).
const firstLine = terminal.buffer.getLine(row);
if (firstLine && firstLine.isWrapped) {
return;
}
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;
}
@@ -205,7 +240,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))) {
@@ -232,28 +267,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._core.buffer.lines.get(row);
const line = terminal.buffer.getLine(row);
for (let i = 0; i < resultIndex; i++) {
const charData = line.get(i);
// Adjust the searchIndex to normalize emoji into single chars
const char = charData[1/*CHAR_DATA_CHAR_INDEX*/];
if (char.length > 1) {
resultIndex -= char.length - 1;
}
// Adjust the searchIndex for empty characters following wide unicode
// chars (eg. CJK)
const charWidth = charData[2/*CHAR_DATA_WIDTH_INDEX*/];
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.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++;
}
}
}
return {
@@ -263,6 +303,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
@@ -271,14 +312,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._core.buffer.lines.get(lineIndex + 1);
const nextLine = terminal.buffer.getLine(lineIndex + 1);
lineWrapsToNext = nextLine ? nextLine.isWrapped : false;
lineString += this._terminal._core.buffer.translateBufferLineToString(lineIndex, !lineWrapsToNext && trimRight).substring(0, this._terminal.cols);
const line = terminal.buffer.getLine(lineIndex);
if (!line) {
break;
}
lineString += line.translateToString(!lineWrapsToNext && trimRight).substring(0, terminal.cols);
lineIndex++;
} while (lineWrapsToNext);
@@ -290,13 +336,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._core.selectionManager.setSelection(result.col, result.row, result.term.length);
this._terminal.scrollLines(result.row - this._terminal._core.buffer.ydisp);
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.viewportY + terminal.rows) || result.row < terminal.buffer.viewportY) {
let scroll = result.row - terminal.buffer.viewportY;
scroll = scroll - Math.floor(terminal.rows / 2);
terminal.scrollLines(scroll);
}
return true;
}
}
@@ -7,14 +7,13 @@
"es6",
],
"rootDir": ".",
"outDir": "../../../lib/addons/attach/",
"outDir": "../out",
"sourceMap": true,
"removeComments": true,
"declaration": true,
"preserveWatchOutput": true
"strict": true
},
"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
* suppounded in "non-word" characters such as `_`, `(`, `)` or space.
*/
wholeWord?: boolean;
/**
* Whether the search is case sensitive.
*/
caseSensitive?: boolean;
/**
* Whether to do an indcremental 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'
};
+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.2.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": "^3.14.0"
}
}
@@ -0,0 +1,89 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import * as puppeteer from 'puppeteer';
import { assert } from 'chai';
import { ITerminalOptions } from 'xterm';
const APP = 'http://127.0.0.1:3000/test';
let browser: puppeteer.Browser;
let page: puppeteer.Page;
const width = 800;
const height = 600;
describe('WebLinksAddon', () => {
before(async function(): Promise<any> {
this.timeout(10000);
browser = await puppeteer.launch({
headless: process.argv.indexOf('--headless') !== -1,
slowMo: 80,
args: [`--window-size=${width},${height}`]
});
page = (await browser.pages())[0];
await page.setViewport({ width, height });
});
after(async () => {
await browser.close();
});
beforeEach(async function(): Promise<any> {
this.timeout(5000);
await page.goto(APP);
});
it('.com', async function(): Promise<any> {
this.timeout(20000);
await testHostName('foo.com');
});
it('.com.au', async function(): Promise<any> {
this.timeout(20000);
await testHostName('foo.com.au');
});
it('.io', async function(): Promise<any> {
this.timeout(20000);
await testHostName('foo.io');
});
});
async function testHostName(hostname: string): Promise<void> {
await openTerminal({ rendererType: 'dom' });
await page.evaluate(`window.term.loadAddon(new window.WebLinksAddon())`);
await page.evaluate(`
window.term.writeln(' http://${hostname} ');
window.term.writeln(' http://${hostname}/a~b#c~d?e~f ');
window.term.writeln(' http://${hostname}/colon:test ');
window.term.writeln(' http://${hostname}/colon:test: ');
window.term.writeln('"http://${hostname}/"');
window.term.writeln('\\'http://${hostname}/\\'');
window.term.writeln('http://${hostname}/subpath/+/id');
`);
assert.equal(await getLinkAtCell(3, 1), `http://${hostname}`);
assert.equal(await getLinkAtCell(3, 2), `http://${hostname}/a~b#c~d?e~f`);
assert.equal(await getLinkAtCell(3, 3), `http://${hostname}/colon:test`);
assert.equal(await getLinkAtCell(3, 4), `http://${hostname}/colon:test`);
assert.equal(await getLinkAtCell(2, 5), `http://${hostname}/`);
assert.equal(await getLinkAtCell(2, 6), `http://${hostname}/`);
assert.equal(await getLinkAtCell(1, 7), `http://${hostname}/subpath/+/id`);
}
async function openTerminal(options: ITerminalOptions = {}): Promise<void> {
await page.evaluate(`window.term = new Terminal(${JSON.stringify(options)})`);
await page.evaluate(`window.term.open(document.querySelector('#terminal-container'))`);
if (options.rendererType === 'dom') {
await page.waitForSelector('.xterm-rows');
} else {
await page.waitForSelector('.xterm-text-layer');
}
}
async function getLinkAtCell(col: number, row: number): Promise<string> {
const rowSelector = `.xterm-rows > :nth-child(${row})`;
await page.hover(`${rowSelector} > :nth-child(${col})`);
return await page.evaluate(`Array.prototype.reduce.call(document.querySelectorAll('${rowSelector} > span[style]'), (a, b) => a + b.textContent, '');`);
}
@@ -3,7 +3,7 @@
* @license MIT
*/
import { Terminal, ILinkMatcherOptions } from 'xterm';
import { Terminal, ILinkMatcherOptions, ITerminalAddon } from 'xterm';
const protocolClause = '(https?:\\/\\/)';
const domainCharacterSet = '[\\da-z\\.-]+';
@@ -14,7 +14,8 @@ 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 pathClause = '(\\/[\\/\\w\\.\\-%~:]*)*([^:"\'\\s])';
const pathCharacterSet = '(\\/[\\/\\w\\.\\-%~:+]*)*([^:"\'\\s])';
const pathClause = '(' + pathCharacterSet + ')?';
const queryStringHashFragmentCharacterSet = '[0-9\\w\\[\\]\\(\\)\\/\\?\\!#@$%&\'*+,:;~\\=\\.\\-]*';
const queryStringClause = '(\\?' + queryStringHashFragmentCharacterSet + ')?';
const hashFragmentClause = '(#' + queryStringHashFragmentCharacterSet + ')?';
@@ -28,19 +29,25 @@ function handleLink(event: MouseEvent, uri: string): void {
window.open(uri, '_blank');
}
/**
* Initialize the web links addon, registering the link matcher.
* @param term The terminal to use web links within.
* @param handler A custom handler to use.
* @param options Custom options to use, matchIndex will always be ignored.
*/
export function webLinksInit(term: Terminal, handler: (event: MouseEvent, uri: string) => void = handleLink, options: ILinkMatcherOptions = {}): void {
options.matchIndex = 1;
term.registerLinkMatcher(strictUrlRegex, handler, options);
}
export class WebLinksAddon implements ITerminalAddon {
private _linkMatcherId: number | undefined;
private _terminal: Terminal | undefined;
export function apply(terminalConstructor: typeof Terminal): void {
(<any>terminalConstructor.prototype).webLinksInit = function (handler?: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions): void {
webLinksInit(this, handler, options);
};
constructor(
private _handler: (event: MouseEvent, uri: string) => void = handleLink,
private _options: ILinkMatcherOptions = {}
) {
this._options.matchIndex = 1;
}
public activate(terminal: Terminal): void {
this._terminal = terminal;
this._linkMatcherId = this._terminal.registerLinkMatcher(strictUrlRegex, this._handler, this._options);
}
public dispose(): void {
if (this._linkMatcherId !== undefined && this._terminal !== undefined) {
this._terminal.deregisterLinkMatcher(this._linkMatcherId);
}
}
}
@@ -4,20 +4,16 @@
"target": "es5",
"lib": [
"dom",
"es5"
"es2015"
],
"rootDir": ".",
"outDir": "../../../lib/addons/search/",
"outDir": "../out",
"sourceMap": true,
"removeComments": true,
"declaration": true,
"preserveWatchOutput": true,
"types": [
"../../node_modules/@types/mocha"
]
"strict": true
},
"include": [
"**/*.ts",
"./**/*",
"../../../typings/xterm.d.ts"
]
}
@@ -0,0 +1,32 @@
/**
* 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.
*/
constructor(handler?: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions);
/**
* 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.2.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": "^3.14.0"
}
}
@@ -0,0 +1,28 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { CellData } from 'common/buffer/CellData';
import { FLAGS } from './Constants';
import { IBufferLine } from 'common/Types';
export function getCompatAttr(bufferLine: IBufferLine, index: number): number {
// TODO: Need to move WebGL over to the new system and remove this block
const cell = new CellData();
bufferLine.loadCell(index, cell);
const oldBg = cell.getBgColor() === -1 ? 256 : cell.getBgColor();
const oldFg = cell.getFgColor() === -1 ? 256 : cell.getFgColor();
const oldAttr =
(cell.isBold() ? FLAGS.BOLD : 0) |
(cell.isUnderline() ? FLAGS.UNDERLINE : 0) |
(cell.isBlink() ? FLAGS.BLINK : 0) |
(cell.isInverse() ? FLAGS.INVERSE : 0) |
(cell.isDim() ? FLAGS.DIM : 0) |
(cell.isItalic() ? FLAGS.ITALIC : 0);
const attrCompat =
oldBg |
(oldFg << 9) |
(oldAttr << 18);
return attrCompat;
}
@@ -0,0 +1,14 @@
/**
* @license MIT
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
*/
import { IColor } from 'browser/Types';
export function getLuminance(color: IColor): number {
// Coefficients taken from: https://www.w3.org/TR/AERT/#color-contrast
const r = color.rgba >> 24 & 0xff;
const g = color.rgba >> 16 & 0xff;
const b = color.rgba >> 8 & 0xff;
return (0.299 * r + 0.587 * g + 0.114 * b) / 255;
}
+15
View File
@@ -0,0 +1,15 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
// TODO: Should be removed after chardata workaround is fixed
export const enum FLAGS {
BOLD = 1,
UNDERLINE = 2,
BLINK = 4,
INVERSE = 8,
INVISIBLE = 16,
DIM = 32,
ITALIC = 64
}
@@ -0,0 +1,374 @@
/**
* 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 { INDICIES_PER_CELL } from './WebglRenderer';
import { COMBINED_CHAR_BIT_MASK } from './RenderModel';
import { fill } from 'common/TypedArrayUtils';
import { slice } from './TypedArray';
import { NULL_CELL_CODE, WHITESPACE_CELL_CODE } from 'common/buffer/Constants';
import { getLuminance } from './ColorUtils';
import { Terminal, IBufferLine } from 'xterm';
import { IColorSet } from 'browser/Types';
import { IRenderDimensions } from 'browser/renderer/Types';
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));
if (program === undefined) {
throw new Error('Could not create WebGL program');
}
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, attr: number, bg: number, fg: number, chars: string): void {
this._updateCell(this._vertices.attributes, x, y, code, attr, bg, fg, chars);
}
private _updateCell(array: Float32Array, x: number, y: number, code: number | undefined, attr: number, 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) {
throw new Error('atlas must be set before updating cell');
}
if (chars && chars.length > 1) {
rasterizedGlyph = this._atlas.getRasterizedGlyphCombinedChar(chars, attr, bg, fg);
} else {
rasterizedGlyph = this._atlas.getRasterizedGlyph(code, attr, 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);
// TODO: Make fg and bg configurable, currently since the buffer doesn't
// support truecolor the char atlas cannot store it.
const lumi = getLuminance(this._colors.background);
const fg = lumi > 0.5 ? 7 : 0;
const bg = lumi > 0.5 ? 0 : 7;
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, fg);
}
} 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, fg);
// 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, fg);
}
// 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, fg);
}
}
}
private _updateSelectionRange(startCol: number, endCol: number, y: number, model: IRenderModel, bg: number, fg: number): void {
const terminal = this._terminal;
const row = y + terminal.buffer.viewportY;
let line: IBufferLine | undefined;
for (let x = startCol; x < endCol; x++) {
const offset = (y * this._terminal.cols + x) * INDICIES_PER_CELL;
// Because the cache uses attr as a lookup key it needs to contain the selection colors as well
let attr = model.cells[offset + 1];
attr = attr & ~0x3ffff | bg << 9 | fg;
const code = model.cells[offset];
if (code & COMBINED_CHAR_BIT_MASK) {
if (!line) {
line = terminal.buffer.getLine(row);
}
const chars = line!.getCell(x)!.char;
this._updateCell(this._vertices.selectionAttributes, x, y, model.cells[offset], attr, bg, fg, chars);
} else {
this._updateCell(this._vertices.selectionAttributes, x, y, model.cells[offset], attr, bg, fg);
}
}
}
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,325 @@
/**
* 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 { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
import { is256Color } from './atlas/CharAtlasUtils';
import { DEFAULT_COLOR } from 'common/buffer/Constants';
import { Terminal } from 'xterm';
import { IColorSet, IColor } from 'browser/Types';
import { IRenderDimensions } from 'browser/renderer/Types';
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 vec3 a_color;
layout (location = ${VertexAttribLocations.UNIT_QUAD}) in vec2 a_unitquad;
uniform mat4 u_projection;
uniform vec2 u_resolution;
out vec3 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 vec3 v_color;
out vec4 outColor;
void main() {
outColor = vec4(v_color, 1);
}`;
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.selection);
}
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 = DEFAULT_COLOR;
for (let x = 0; x < terminal.cols; x++) {
const modelIndex = ((y * terminal.cols) + x) * 4;
const bg = model.cells[modelIndex + 2];
if (bg !== currentBg) {
// A rectangle needs to be drawn if going from non-default to another color
if (currentBg !== DEFAULT_COLOR) {
const offset = rectangleCount++ * INDICES_PER_RECTANGLE;
this._updateRectangle(vertices, offset, currentBg, currentStartX, x, y);
}
currentStartX = x;
currentBg = bg;
}
}
// Finish rectangle if it's still going
if (currentBg !== DEFAULT_COLOR) {
const offset = rectangleCount++ * INDICES_PER_RECTANGLE;
this._updateRectangle(vertices, offset, currentBg, currentStartX, terminal.cols, y);
}
}
vertices.count = rectangleCount;
}
private _updateRectangle(vertices: IVertices, offset: number, bg: number, startX: number, endX: number, y: number): void {
let color: IColor | null = null;
if (bg === INVERTED_DEFAULT_COLOR) {
color = this._colors.foreground;
} else if (is256Color(bg)) {
color = this._colors.ansi[bg];
} else {
// TODO: Add support for true color
color = this._colors.foreground;
}
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 = ((color.rgba >> 24) & 0xFF) / 255;
const g = ((color.rgba >> 16) & 0xFF) / 255;
const b = ((color.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,55 @@
/**
* 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 = 4;
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,122 @@
/**
* 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,34 @@
/**
* 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 {
[flags: number]: IRasterizedGlyph;
}
/**
* 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,28 @@
/**
* 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 {
constructor(
private _preserveDrawingBuffer?: boolean
) {}
public activate(terminal: Terminal): void {
if (!terminal.element) {
throw new Error('Cannot activate WebglRendererAddon before Terminal.open');
}
const renderService: IRenderService = (<any>terminal)._core._renderService;
const colors: IColorSet = (<any>terminal)._core._colorManager.colors;
renderService.setRenderer(new WebglRenderer(terminal, colors, this._preserveDrawingBuffer));
}
public dispose(): void {
throw new Error('WebglRendererAddon.dispose Not yet implemented');
}
}
@@ -0,0 +1,168 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import * as puppeteer from 'puppeteer';
import { assert } from 'chai';
import { ITerminalOptions } from '../../../src/Types';
import { ITheme } from 'xterm';
const APP = 'http://127.0.0.1:3000/test';
let browser: puppeteer.Browser;
let page: puppeteer.Page;
const width = 800;
const height = 600;
describe('WebGL Renderer Integration Tests', function(): void {
this.timeout(20000);
before(async function(): Promise<any> {
browser = await puppeteer.launch({
headless: process.argv.indexOf('--headless') !== -1,
slowMo: 80,
args: [`--window-size=${width},${height}`]
});
page = (await browser.pages())[0];
await page.setViewport({ width, height });
await page.goto(APP);
await openTerminal();
await page.evaluate(`window.term.loadAddon(new WebglAddon(true));`);
});
after(() => {
browser.close();
});
beforeEach(async () => {
await page.evaluate(`window.term.reset()`);
});
describe('WebGL Renderer', () => {
it('foreground colors normal', async function(): Promise<any> {
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(`\\x1b[30m█\\x1b[31m█\\x1b[32m█\\x1b[33m█\\x1b[34m█\\x1b[35m█\\x1b[36m█\\x1b[37m█`);
assert.deepEqual(await getCellColor(1, 1), [1, 2, 3, 255]);
assert.deepEqual(await getCellColor(2, 1), [4, 5, 6, 255]);
assert.deepEqual(await getCellColor(3, 1), [7, 8, 9, 255]);
assert.deepEqual(await getCellColor(4, 1), [10, 11, 12, 255]);
assert.deepEqual(await getCellColor(5, 1), [13, 14, 15, 255]);
assert.deepEqual(await getCellColor(6, 1), [16, 17, 18, 255]);
assert.deepEqual(await getCellColor(7, 1), [19, 20, 21, 255]);
assert.deepEqual(await getCellColor(8, 1), [22, 23, 24, 255]);
});
it('foreground colors bright', async function(): Promise<any> {
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(`\\x1b[90m█\\x1b[91m█\\x1b[92m█\\x1b[93m█\\x1b[94m█\\x1b[95m█\\x1b[96m█\\x1b[97m█`);
assert.deepEqual(await getCellColor(1, 1), [1, 2, 3, 255]);
assert.deepEqual(await getCellColor(2, 1), [4, 5, 6, 255]);
assert.deepEqual(await getCellColor(3, 1), [7, 8, 9, 255]);
assert.deepEqual(await getCellColor(4, 1), [10, 11, 12, 255]);
assert.deepEqual(await getCellColor(5, 1), [13, 14, 15, 255]);
assert.deepEqual(await getCellColor(6, 1), [16, 17, 18, 255]);
assert.deepEqual(await getCellColor(7, 1), [19, 20, 21, 255]);
assert.deepEqual(await getCellColor(8, 1), [22, 23, 24, 255]);
});
it('background colors normal', async function(): Promise<any> {
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(`\\x1b[40m \\x1b[41m \\x1b[42m \\x1b[43m \\x1b[44m \\x1b[45m \\x1b[46m \\x1b[47m `);
assert.deepEqual(await getCellColor(1, 1), [1, 2, 3, 255]);
assert.deepEqual(await getCellColor(2, 1), [4, 5, 6, 255]);
assert.deepEqual(await getCellColor(3, 1), [7, 8, 9, 255]);
assert.deepEqual(await getCellColor(4, 1), [10, 11, 12, 255]);
assert.deepEqual(await getCellColor(5, 1), [13, 14, 15, 255]);
assert.deepEqual(await getCellColor(6, 1), [16, 17, 18, 255]);
assert.deepEqual(await getCellColor(7, 1), [19, 20, 21, 255]);
assert.deepEqual(await getCellColor(8, 1), [22, 23, 24, 255]);
});
it('background colors bright', async function(): Promise<any> {
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(`\\x1b[100m \\x1b[101m \\x1b[102m \\x1b[103m \\x1b[104m \\x1b[105m \\x1b[106m \\x1b[107m `);
assert.deepEqual(await getCellColor(1, 1), [1, 2, 3, 255]);
assert.deepEqual(await getCellColor(2, 1), [4, 5, 6, 255]);
assert.deepEqual(await getCellColor(3, 1), [7, 8, 9, 255]);
assert.deepEqual(await getCellColor(4, 1), [10, 11, 12, 255]);
assert.deepEqual(await getCellColor(5, 1), [13, 14, 15, 255]);
assert.deepEqual(await getCellColor(6, 1), [16, 17, 18, 255]);
assert.deepEqual(await getCellColor(7, 1), [19, 20, 21, 255]);
assert.deepEqual(await getCellColor(8, 1), [22, 23, 24, 255]);
});
});
});
async function openTerminal(options: ITerminalOptions = {}): Promise<void> {
await page.evaluate(`window.term = new Terminal(${JSON.stringify(options)})`);
await page.evaluate(`window.term.open(document.querySelector('#terminal-container'))`);
if (options.rendererType === 'dom') {
await page.waitForSelector('.xterm-rows');
} else {
await page.waitForSelector('.xterm-text-layer');
}
}
async function writeSync(data: string): Promise<void> {
await page.evaluate(`window.term.write('${data}');`);
while (true) {
if (await page.evaluate(`window.term._core.writeBuffer.length === 0`)) {
break;
}
}
}
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)`);
}
@@ -0,0 +1,410 @@
/**
* 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 { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
import { RenderModel, COMBINED_CHAR_BIT_MASK } from './RenderModel';
import { Disposable } from 'common/Lifecycle';
import { DEFAULT_COLOR, CHAR_DATA_CHAR_INDEX, CHAR_DATA_CODE_INDEX, CHAR_DATA_ATTR_INDEX, NULL_CELL_CODE } from 'common/buffer/Constants';
import { Terminal } from 'xterm';
import { getLuminance } from './ColorUtils';
import { IRenderLayer } from './renderLayer/Types';
import { IRenderDimensions, IRenderer } from 'browser/renderer/Types';
import { IColorSet } from 'browser/Types';
import { FLAGS } from './Constants';
import { getCompatAttr } from './CharDataCompat';
export const INDICIES_PER_CELL = 4;
export class WebglRenderer extends Disposable implements IRenderer {
private _renderLayers: IRenderLayer[];
private _charAtlas: WebglCharAtlas | undefined;
private _devicePixelRatio: number;
private _model: RenderModel = new RenderModel();
private _canvas: HTMLCanvasElement;
private _gl: IWebGL2RenderingContext;
private _rectangleRenderer: RectangleRenderer;
private _glyphRenderer: GlyphRenderer;
public dimensions: IRenderDimensions;
private _core: ITerminal;
constructor(
private _terminal: Terminal,
private _colors: IColorSet,
preserveDrawingBuffer?: boolean
) {
super();
this._core = (<any>this._terminal)._core;
this._applyBgLuminanceBasedSelection();
this._renderLayers = [
new LinkRenderLayer(this._core.screenElement, 2, this._colors, this._core),
new CursorRenderLayer(this._core.screenElement, 3, this._colors)
];
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._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();
}
public dispose(): void {
this._renderLayers.forEach(l => l.dispose());
this._core.screenElement.removeChild(this._canvas);
super.dispose();
}
private _applyBgLuminanceBasedSelection(): void {
// HACK: This is needed until webgl renderer adds support for selection colors
if (getLuminance(this._colors.background) > 0.5) {
this._colors.selection = { css: '#000', rgba: 255 };
} else {
this._colors.selection = { css: '#fff', rgba: 4294967295 };
}
}
public setColors(colors: IColorSet): void {
this._colors = colors;
this._applyBgLuminanceBasedSelection();
// 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);
// TODO: #2102 Should this move to RenderCoordinator?
this._core.refresh(0, 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) {
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 {
// 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++) {
const charData = line.get(x);
const chars = charData[CHAR_DATA_CHAR_INDEX];
let code = charData[CHAR_DATA_CODE_INDEX];
const attr = getCompatAttr(line, x); // charData[CHAR_DATA_ATTR_INDEX];
const i = ((y * terminal.cols) + x) * 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 + 1] === attr) {
continue;
}
// Resolve bg and fg and cache in the model
const flags = attr >> 18;
let bg = attr & 0x1ff;
let fg = (attr >> 9) & 0x1ff;
// If inverse flag is on, the foreground should become the background.
if (flags & FLAGS.INVERSE) {
const temp = bg;
bg = fg;
fg = temp;
if (fg === DEFAULT_COLOR) {
fg = INVERTED_DEFAULT_COLOR;
}
if (bg === DEFAULT_COLOR) {
bg = INVERTED_DEFAULT_COLOR;
}
}
const drawInBrightColor = terminal.options.drawBoldTextInBrightColors && !!(flags & FLAGS.BOLD) && fg < 8 && fg !== INVERTED_DEFAULT_COLOR;
fg += drawInBrightColor ? 8 : 0;
// Flag combined chars with a bit mask so they're easily identifiable
if (chars.length > 1) {
code = code | COMBINED_CHAR_BIT_MASK;
}
this._model.cells[i ] = code;
this._model.cells[i + 1] = attr;
this._model.cells[i + 2] = bg;
this._model.cells[i + 3] = fg;
this._glyphRenderer.updateCell(x, y, code, attr, bg, 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.viewportY;
const viewportEndRow = end[1] - terminal.buffer.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 (!(<any>this._core)._charSizeService.width || !(<any>this._core)._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((<any>this._core)._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((<any>this._core)._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 { IColorSet } 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';
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,61 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { ICharAtlasConfig } from './Types';
import { DEFAULT_COLOR } 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,
// 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()
};
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'),
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.colors.foreground === b.colors.foreground &&
a.colors.background === b.colors.background;
}
export function is256Color(colorCode: number): boolean {
return colorCode < DEFAULT_COLOR;
}
@@ -4,13 +4,7 @@
*/
import { FontWeight } from 'xterm';
import { IColorSet } from '../Types';
export const DEFAULT_COLOR = 256;
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;
@@ -23,7 +17,6 @@ export interface IGlyphIdentifier {
}
export interface ICharAtlasConfig {
type: 'none' | 'static' | 'dynamic';
devicePixelRatio: number;
fontSize: number;
fontFamily: string;
@@ -0,0 +1,400 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { ICharAtlasConfig } from './Types';
import { DIM_OPACITY, INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
import { IRasterizedGlyph, IBoundingBox, IRasterizedGlyphSet } from '../Types';
import { DEFAULT_COLOR, DEFAULT_ATTR } from 'common/buffer/Constants';
import { is256Color } from './CharAtlasUtils';
import { throwIfFalsy } from '../WebglUtils';
import { IColor } from 'browser/Types';
import { FLAGS } from '../Constants';
import { IDisposable } from 'xterm';
// 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 };
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}));
// This is useful for debugging
document.body.appendChild(this.cacheCanvas);
}
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_ATTR, DEFAULT_COLOR, DEFAULT_COLOR);
this._cacheMap[i] = {
[DEFAULT_ATTR]: 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, attr: number, bg: number, fg: number): IRasterizedGlyph {
let rasterizedGlyphSet = this._cacheMapCombined[chars];
if (!rasterizedGlyphSet) {
rasterizedGlyphSet = {};
this._cacheMapCombined[chars] = rasterizedGlyphSet;
}
let rasterizedGlyph = rasterizedGlyphSet[attr];
if (!rasterizedGlyph) {
rasterizedGlyph = this._drawToCache(chars, attr, bg, fg);
rasterizedGlyphSet[attr] = rasterizedGlyph;
}
return rasterizedGlyph;
}
/**
* Gets the glyphs texture coords, drawing the texture if it's not already
*/
public getRasterizedGlyph(code: number, attr: number, bg: number, fg: number): IRasterizedGlyph {
let rasterizedGlyphSet = this._cacheMap[code];
if (!rasterizedGlyphSet) {
rasterizedGlyphSet = {};
this._cacheMap[code] = rasterizedGlyphSet;
}
let rasterizedGlyph = rasterizedGlyphSet[attr];
if (!rasterizedGlyph) {
rasterizedGlyph = this._drawToCache(code, attr, bg, fg);
rasterizedGlyphSet[attr] = 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(bg: number): 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;
} else if (bg === INVERTED_DEFAULT_COLOR) {
return this._config.colors.foreground;
} else if (is256Color(bg)) {
return this._getColorFromAnsiIndex(bg);
}
// TODO: Support true color
return this._config.colors.background;
}
private _getForegroundColor(fg: number): IColor {
if (fg === INVERTED_DEFAULT_COLOR) {
return this._config.colors.background;
} else if (is256Color(fg)) {
return this._getColorFromAnsiIndex(fg);
}
// TODO: Support true color
return this._config.colors.foreground;
}
private _drawToCache(code: number, attr: number, bg: number, fg: number): IRasterizedGlyph;
private _drawToCache(chars: string, attr: number, bg: number, fg: number): IRasterizedGlyph;
private _drawToCache(codeOrChars: number | string, attr: number, bg: number, fg: number): IRasterizedGlyph {
const chars = typeof codeOrChars === 'number' ? String.fromCharCode(codeOrChars) : codeOrChars;
this.hasCanvasChanged = true;
const flags = attr >> 18;
const bold = !!(flags & FLAGS.BOLD);
const dim = !!(flags & FLAGS.DIM);
const italic = !!(flags & FLAGS.ITALIC);
this._tmpCtx.save();
// draw the background
const backgroundColor = this._getBackgroundColor(bg);
// 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._getForegroundColor(fg).css;
// 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;
}
@@ -0,0 +1,276 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { IRenderLayer } from './Types';
import { IGlyphIdentifier } from '../atlas/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;
/**
* An object that's reused when drawing glyphs in order to reduce GC.
*/
private _currentGlyphIdentifier: IGlyphIdentifier = {
chars: '',
code: 0,
bg: 0,
fg: 0,
bold: false,
dim: false,
italic: false
};
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 = <HTMLCanvasElement>this._canvas.cloneNode();
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): void {
this._ctx.fillRect(
x * this._scaledCellWidth,
y * this._scaledCellHeight,
window.devicePixelRatio,
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')}`;
}
}
@@ -0,0 +1,358 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { Terminal } from 'xterm';
import { BaseRenderLayer } from './BaseRenderLayer';
import { ICellData } from 'common/Types';
import { CellData } from 'common/buffer/CellData';
import { IColorSet } from 'browser/Types';
import { IRenderDimensions } from 'browser/renderer/Types';
interface ICursorState {
x: number;
y: number;
isFocused: boolean;
style: string;
width: number;
}
/**
* The time between cursor blinks.
*/
const BLINK_INTERVAL = 600;
export class CursorRenderLayer extends BaseRenderLayer {
private _state: ICursorState;
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) {
super(container, 'cursor', zIndex, true, colors);
this._state = {
x: 0,
y: 0,
isFocused: false,
style: '',
width: 0
};
this._cursorRenderers = {
'bar': this._renderBarCursor.bind(this),
'block': this._renderBlockCursor.bind(this),
'underline': this._renderUnderlineCursor.bind(this)
};
// TODO: Consider initial options? Maybe onOptionsChanged should be called at the end of open?
}
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: 0,
y: 0,
isFocused: false,
style: '',
width: 0
};
}
public reset(terminal: Terminal): void {
this._clearCursor();
if (this._cursorBlinkStateManager) {
this._cursorBlinkStateManager.dispose();
this.onOptionsChanged(terminal);
}
}
public onBlur(terminal: Terminal): void {
if (this._cursorBlinkStateManager) {
this._cursorBlinkStateManager.pause();
}
terminal.refresh(terminal.buffer.cursorY, terminal.buffer.cursorY);
}
public onFocus(terminal: Terminal): void {
if (this._cursorBlinkStateManager) {
this._cursorBlinkStateManager.resume(terminal);
} else {
terminal.refresh(terminal.buffer.cursorY, terminal.buffer.cursorY);
}
}
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();
}
// Request a refresh from the terminal as management of rendering is being
// moved back to the terminal
terminal.refresh(terminal.buffer.cursorY, terminal.buffer.cursorY);
}
}
public onCursorMove(terminal: Terminal): void {
if (this._cursorBlinkStateManager) {
this._cursorBlinkStateManager.restartBlinkAnimation(terminal);
}
}
public onGridChanged(terminal: Terminal, startRow: number, endRow: number): void {
if (!this._cursorBlinkStateManager || this._cursorBlinkStateManager.isPaused) {
this._render(terminal, false);
} else {
this._cursorBlinkStateManager.restartBlinkAnimation(terminal);
}
}
private _render(terminal: Terminal, triggeredByAnimationFrame: boolean): void {
// Don't draw the cursor if it's hidden
// TODO: Need to expose API for this
if (!(terminal as any)._core.cursorState || (terminal as any)._core.cursorHidden) {
this._clearCursor();
return;
}
const cursorY = terminal.buffer.baseY + terminal.buffer.cursorY;
const viewportRelativeCursorY = cursorY - terminal.buffer.viewportY;
// Don't draw the cursor if it's off-screen
if (viewportRelativeCursorY < 0 || viewportRelativeCursorY >= terminal.rows) {
this._clearCursor();
return;
}
// TODO: Need fast buffer API for loading cell
(terminal as any)._core.buffer.lines.get(cursorY).loadCell(terminal.buffer.cursorX, this._cell);
if (this._cell.content === undefined) {
return;
}
if (!isTerminalFocused(terminal)) {
this._clearCursor();
this._ctx.save();
this._ctx.fillStyle = this._colors.cursor.css;
this._renderBlurCursor(terminal, terminal.buffer.cursorX, viewportRelativeCursorY, this._cell);
this._ctx.restore();
this._state.x = terminal.buffer.cursorX;
this._state.y = viewportRelativeCursorY;
this._state.isFocused = false;
this._state.style = terminal.getOption('cursorStyle');
this._state.width = this._cell.getWidth();
return;
}
// Don't draw the cursor if it's blinking
if (this._cursorBlinkStateManager && !this._cursorBlinkStateManager.isCursorVisible) {
this._clearCursor();
return;
}
if (this._state) {
// The cursor is already in the correct spot, don't redraw
if (this._state.x === terminal.buffer.cursorX &&
this._state.y === viewportRelativeCursorY &&
this._state.isFocused === isTerminalFocused(terminal) &&
this._state.style === terminal.getOption('cursorStyle') &&
this._state.width === this._cell.getWidth()) {
return;
}
this._clearCursor();
}
this._ctx.save();
this._cursorRenderers[terminal.getOption('cursorStyle') || 'block'](terminal, terminal.buffer.cursorX, viewportRelativeCursorY, this._cell);
this._ctx.restore();
this._state.x = terminal.buffer.cursorX;
this._state.y = viewportRelativeCursorY;
this._state.isFocused = false;
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._state = {
x: 0,
y: 0,
isFocused: false,
style: '',
width: 0
};
}
}
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._ctx.restore();
}
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._ctx.fillStyle = this._colors.cursorAccent.css;
this._fillCharTrueColor(terminal, cell, x, y);
this._ctx.restore();
}
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._ctx.restore();
}
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._ctx.restore();
}
}
class CursorBlinkStateManager {
public isCursorVisible: boolean;
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 | undefined;
constructor(
terminal: Terminal,
private _renderCallback: () => void
) {
this.isCursorVisible = true;
if (isTerminalFocused(terminal)) {
this._restartInterval();
}
}
public get isPaused(): boolean { return !(this._blinkStartTimeout || this._blinkInterval); }
public dispose(): void {
if (this._blinkInterval) {
window.clearInterval(this._blinkInterval);
this._blinkInterval = undefined;
}
if (this._blinkStartTimeout) {
window.clearTimeout(this._blinkStartTimeout);
this._blinkStartTimeout = undefined;
}
if (this._animationFrame) {
window.cancelAnimationFrame(this._animationFrame);
this._animationFrame = undefined;
}
}
public restartBlinkAnimation(terminal: Terminal): void {
if (this.isPaused) {
return;
}
// Save a timestamp so that the restart can be done on the next interval
this._animationTimeRestarted = Date.now();
// Force a cursor render to ensure it's visible and in the correct position
this.isCursorVisible = true;
if (!this._animationFrame) {
this._animationFrame = window.requestAnimationFrame(() => {
this._renderCallback();
this._animationFrame = undefined;
});
}
}
private _restartInterval(timeToStart: number = BLINK_INTERVAL): void {
// Clear any existing interval
if (this._blinkInterval) {
window.clearInterval(this._blinkInterval);
}
// Setup the initial timeout which will hide the cursor, this is done before
// 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(() => {
// 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 = undefined;
if (time > 0) {
this._restartInterval(time);
return;
}
}
// Hide the cursor
this.isCursorVisible = false;
this._animationFrame = window.requestAnimationFrame(() => {
this._renderCallback();
this._animationFrame = undefined;
});
// Setup the blink interval
this._blinkInterval = <number><any>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 = undefined;
this._restartInterval(time);
return;
}
// Invert visibility and render
this.isCursorVisible = !this.isCursorVisible;
this._animationFrame = window.requestAnimationFrame(() => {
this._renderCallback();
this._animationFrame = undefined;
});
}, BLINK_INTERVAL);
}, timeToStart);
}
public pause(): void {
this.isCursorVisible = true;
if (this._blinkInterval) {
window.clearInterval(this._blinkInterval);
this._blinkInterval = undefined;
}
if (this._blinkStartTimeout) {
window.clearTimeout(this._blinkStartTimeout);
this._blinkStartTimeout = undefined;
}
if (this._animationFrame) {
window.cancelAnimationFrame(this._animationFrame);
this._animationFrame = undefined;
}
}
public resume(terminal: Terminal): void {
this._animationTimeRestarted = undefined;
this._restartInterval();
this.restartBlinkAnimation(terminal);
}
}
function isTerminalFocused(terminal: Terminal): boolean {
return document.activeElement === terminal.textarea && document.hasFocus();
}
@@ -0,0 +1,72 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { ILinkifierAccessor } from '../../../../src/Types';
import { Terminal } from 'xterm';
import { BaseRenderLayer } from './BaseRenderLayer';
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 | 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));
}
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 = undefined;
}
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);
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.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 (e.fg !== undefined && is256Color(e.fg)) {
// 256 color support
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);
} else {
// Multi-line link
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, e.y2, e.x2);
}
this._state = e;
}
private _onLinkLeave(e: ILinkifierEvent): void {
this._clearCurrentLink();
}
}
@@ -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,28 @@
{
"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
},
"include": [
"./**/*",
"../../../typings/xterm.d.ts"
],
"references": [
{ "path": "../../../src/common" },
{ "path": "../../../src/browser" }
]
}
+26
View File
@@ -0,0 +1,26 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { Terminal, IDisposable, ITerminalAddon } from 'xterm';
declare module 'xterm-addon-webgl' {
/**
* An xterm.js addon that provides search functionality.
*/
export class WebglAddon implements ITerminalAddon {
constructor(preserveDrawingBuffer?: 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,39 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
const path = require('path');
const addonName = 'WebglAddon';
const mainFile = 'xterm-addon-webgl.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'),
browser: path.resolve('../../out/browser')
}
},
output: {
filename: mainFile,
path: path.resolve('./lib'),
library: addonName,
libraryTarget: 'umd'
},
mode: 'production'
};
+71 -11
View File
@@ -20,8 +20,8 @@ jobs:
yarn
displayName: 'Install dependencies and build'
- script: |
yarn mocha
displayName: 'Test'
yarn test-unit
displayName: 'Unit tests'
- script: |
yarn lint
displayName: 'Lint'
@@ -38,16 +38,11 @@ jobs:
yarn
displayName: 'Install dependencies and build'
- script: |
yarn mocha
displayName: 'Test'
yarn test-unit
displayName: 'Unit tests'
- script: |
yarn lint
displayName: 'Lint'
- script: |
yarn test-coverage
export COVERALLS_GIT_BRANCH=$BUILD_SOURCEBRANCH
yarn coveralls
displayName: 'Generate and publish coverage'
- job: Windows
pool:
@@ -61,8 +56,73 @@ jobs:
yarn
displayName: 'Install dependencies and build'
- script: |
yarn mocha
displayName: 'Test'
yarn test-unit
displayName: 'Unit tests'
- script: |
yarn lint
displayName: 'Lint'
- job: Linux_IntegrationTests
pool:
vmImage: 'ubuntu-16.04'
steps:
- task: NodeTool@0
inputs:
versionSpec: '8.x'
displayName: 'Install Node.js'
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.9.4"
displayName: 'Install Yarn'
- script: |
yarn
displayName: 'Install dependencies and build'
- script: |
yarn start &
sleep 10
yarn test-api --headless
displayName: 'Linux Integration tests'
- job: macOS_IntegrationTests
pool:
vmImage: 'xcode9-macos10.13'
steps:
- task: NodeTool@0
inputs:
versionSpec: '8.x'
displayName: 'Install Node.js'
- script: |
yarn
displayName: 'Install dependencies and build'
- script: |
yarn start &
sleep 10
yarn test-api --headless
displayName: 'MacOS Integration tests'
- job: Release
dependsOn:
- Linux
- macOS
- Windows
- Linux_IntegrationTests
- macOS_IntegrationTests
condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq(variables['Build.SourceBranch'], 'refs/heads/release/*')))
pool:
vmImage: 'ubuntu-16.04'
steps:
- task: NodeTool@0
inputs:
versionSpec: '8.x'
displayName: 'Install Node.js'
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.9.4"
displayName: 'Install Yarn'
- script: |
yarn
BUILD_DIR=dist npm run build
displayName: 'Install dependencies and build'
- script: |
NPM_AUTH_TOKEN="$(NPM_AUTH_TOKEN)" node ./bin/publish.js
displayName: 'Publish to npm'
-24
View File
@@ -1,24 +0,0 @@
#! /usr/bin/env sh
# Usage: ./bin/prepare-release x.y.z
# x.y.z should be semver (e.g. 1.0.0)
set -e
NEW_VERSION=$1
CURRENT_PACKAGE_JSON_VERSION=$(cat package.json \
| grep version \
| head -1 \
| awk -F: '{ print $2 }' \
| sed 's/[",]//g' \
| tr -d '[[:space:]]')
# Build xterm.js into `dist`
export BUILD_DIR=dist
npm run build
# Update version in package.json
sed -i "s/\"version\": \"$CURRENT_PACKAGE_JSON_VERSION\"/\"version\": \"$NEW_VERSION\"/g" package.json
git commit -S -s -a -m "Bump version to $NEW_VERSION"
git tag $NEW_VERSION
+117
View File
@@ -0,0 +1,117 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
const cp = require('child_process');
const fs = require('fs');
const path = require('path');
// Setup auth
fs.writeFileSync(`${process.env['HOME']}/.npmrc`, `//registry.npmjs.org/:_authToken=${process.env['NPM_AUTH_TOKEN']}`);
const isDryRun = process.argv.indexOf('--dry') !== -1;
if (isDryRun) {
console.log('Publish dry run');
}
const changedFiles = getChangedFilesInCommit('HEAD');
// Publish xterm if any files were changed outside of the addons directory
if (changedFiles.some(e => e.search(/^addons\//) === -1)) {
checkAndPublishPackage(path.resolve(__dirname, '..'));
}
// Publish addons if any files were changed inside of the addon
const addonPackageDirs = [
path.resolve(__dirname, '../addons/xterm-addon-attach'),
path.resolve(__dirname, '../addons/xterm-addon-fit'),
path.resolve(__dirname, '../addons/xterm-addon-search'),
path.resolve(__dirname, '../addons/xterm-addon-web-links'),
path.resolve(__dirname, '../addons/xterm-addon-webgl')
];
console.log(`Checking if addons need to be published`);
addonPackageDirs.forEach(p => {
const addon = path.basename(p);
if (changedFiles.some(e => e.indexOf(addon) !== -1)) {
console.log(`Try publish ${addon}`);
checkAndPublishPackage(p);
}
});
function checkAndPublishPackage(packageDir) {
const packageJson = require(path.join(packageDir, 'package.json'));
// Determine if this is a stable or beta release
const publishedVersions = getPublishedVersions(packageJson);
const isStableRelease = publishedVersions.indexOf(packageJson.version) === -1;
// Get the next version
let nextVersion = isStableRelease ? packageJson.version : getNextBetaVersion(packageJson);
console.log(`Publishing version: ${nextVersion}`);
// Set the version in package.json
const packageJsonFile = path.join(packageDir, 'package.json');
packageJson.version = nextVersion;
console.log(`Set version of ${packageJsonFile} to ${nextVersion}`);
if (!isDryRun) {
fs.writeFileSync(packageJsonFile, JSON.stringify(packageJson, null, 2));
}
// Publish
const args = ['publish'];
if (!isStableRelease) {
args.push('--tag', 'beta');
}
console.log(`Spawn: npm ${args.join(' ')}`);
if (!isDryRun) {
const result = cp.spawnSync('npm', args, {
cwd: packageDir,
stdio: 'inherit'
});
if (result.status) {
console.error(`Spawn exited with code ${result.status}`);
process.exit(result.status);
}
}
console.groupEnd();
}
function getNextBetaVersion(packageJson) {
if (!/^[0-9]+\.[0-9]+\.[0-9]+$/.exec(packageJson.version)) {
console.error('The package.json version must be of the form x.y.z');
process.exit(1);
}
const tag = 'beta';
const stableVersion = packageJson.version.split('.');
const nextStableVersion = `${stableVersion[0]}.${parseInt(stableVersion[1]) + 1}.0`;
const publishedVersions = getPublishedVersions(packageJson, nextStableVersion, tag);
if (publishedVersions.length === 0) {
return `${nextStableVersion}-${tag}1`;
}
const latestPublishedVersion = publishedVersions.sort((a, b) => {
const aVersion = parseInt(a.substr(a.search(/[0-9]+$/)));
const bVersion = parseInt(b.substr(b.search(/[0-9]+$/)));
return aVersion > bVersion ? -1 : 1;
})[0];
const latestTagVersion = parseInt(latestPublishedVersion.substr(latestPublishedVersion.search(/[0-9]+$/)), 10);
return `${nextStableVersion}-${tag}${latestTagVersion + 1}`;
}
function getPublishedVersions(packageJson, version, tag) {
const versionsProcess = cp.spawnSync('npm', ['view', packageJson.name, 'versions', '--json']);
const versionsJson = JSON.parse(versionsProcess.stdout);
if (tag) {
return versionsJson.filter(v => !v.search(new RegExp(`${version}-${tag}[0-9]+`)));
}
return versionsJson;
}
function getChangedFilesInCommit(commit) {
const args = ['log', '-m', '-1', '--name-only', `--pretty=format:`, commit];
const result = cp.spawnSync('git', args);
const output = result.stdout.toString();
const changedFiles = output.split('\n').filter(e => e.length > 0);
return changedFiles;
}
-22
View File
@@ -1,22 +0,0 @@
#! /usr/bin/env sh
# Usage: ./bin/release x.y.z
# x.y.z should be semver (e.g. 1.0.0)
set -e
if [ -z "$1" ];
then
echo "No version supplied. Please a version argument\n"
echo "Usage: $0 VERSION\n"
echo "Example: $0 1.0.0"
exit
fi
NEW_VERSION=$1
./bin/prepare-release $NEW_VERSION
git push && \
git push --tags && \
npm publish
+34
View File
@@ -0,0 +1,34 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
const cp = require('child_process');
const path = require('path');
// Add `out` to the NODE_PATH so absolute paths can be resolved.
const env = { ...process.env };
env.NODE_PATH = path.resolve(__dirname, '../out');
let testFiles = [
'./out/*test.js',
'./out/**/*test.js'
];
// ability to inject particular test files via
// yarn test [testFileA testFileB ...]
if (process.argv.length > 2) {
testFiles = process.argv.slice(2);
}
const run = cp.spawnSync(
path.resolve(__dirname, '../node_modules/.bin/mocha'),
testFiles,
{
cwd: path.resolve(__dirname, '..'),
env,
stdio: 'inherit'
}
);
process.exit(run.status);
+212
View File
@@ -0,0 +1,212 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*
* Script to test different mouse modes in terminal emulators.
* Tests for protocols DECSET 9, 1000, 1002, 1003 with different
* report encodings (default, UTF8, SGR, URXVT).
*
* VT200 Highlight mode (DECSET 1001) is not implemented.
*
* The test basically applies the report data to the cursor, thus
* a mouse report should move the cursor to the cell under the mouse.
* Furthermore the reports are printed in the left lower corner as
* raw data and their meaning.
*
* A failing test might show:
* - wrong coords: the cursor will jump to some other place
* - wrong buttons: see meaning output and check whether it makes sense
* - faulty reports: inspect the raw data and compare with other emulators
* - missing events: compare with spec / other emulators
*/
let activeProtocol = 0;
let activeEnc = 0;
const stdin = process.openStdin();
process.stdin.setRawMode(true);
// close handler - reset terminal on exit
stdin.addListener('data', function(data) {
if (data[0] === 0x03) {
process.stdin.setRawMode(false);
process.stdout.write('\x1bc');
process.exit();
}
if (data[0] === 0x01) {
switchActiveProtocol();
printMenu();
}
if (data[0] === 0x02) {
switchActiveEnc();
printMenu();
}
console.log('\x1b[100;H\x1b[2A\x1b[2KReport:', data, [data.toString('binary')]);
// filter mouse reports
if (data[0] === 0x1b && data[1] === '['.charCodeAt(0)) {
applyReportData(data);
}
});
// button definitions
const buttons = {
'<none>': -1,
left: 0,
middle: 1,
right: 2,
released: 3,
wheelUp: 4,
wheelDown: 5,
wheelLeft: 6,
wheelRight: 7,
aux1: 8,
aux2: 9,
aux3: 10,
aux4: 11,
aux5: 12,
aux6: 13,
aux7: 14,
aux8: 15
};
const reverseButtons = {};
for (const el in buttons) {
reverseButtons[buttons[el]] = el;
}
// extract button data from buttonCode
function evalButtonCode(code) {
// more than 15 buttons are not supported
if (code > 255) {
return {button: 'invalid', action: 'invalid', modifier: {}};
}
const modifier = {shift: !!(code & 4), meta: !!(code & 8), control: !!(code & 16)};
const move = code & 32;
let button = code & 3;
if (code & 128) {
button |= 8;
}
if (code & 64) {
button |= 4
}
let actionS = 'press';
let buttonS = reverseButtons[button];
if (button === 3) {
buttonS = '<none>';
actionS = 'release';
}
if (move) {
actionS = 'move';
} else if (4 <= button && button <= 7) {
buttonS = 'wheel';
actionS = button === 4 ? 'up' : button === 5 ? 'down' : button === 6 ? 'left' : 'right';
}
return {button: buttonS, action: actionS, modifier};
}
// protocols
const PROTOCOLS = {
'9 (X10: press only)': '\x1b[?9h',
'1000 (VT200: press, release, wheel)': '\x1b[?1000h',
// '1001 (VT200 highlight)': '\x1b[?1001h', // handle of backreport - not implemented
'1002 (press, release, move on pressed, wheel)': '\x1b[?1002h',
'1003 (press, relase, move, wheel)': '\x1b[?1003h'
}
// encodings: ENCODING_NAME => [sequence, parse_report]
const ENC = {
'DEFAULT' : [
'',
// format: CSI M <button + 32> <row + 32> <col + 32>
report => ({
state: evalButtonCode(report[3] - 32),
col: report[4] - 32,
row: report[5] - 32
})
],
'UTF8' : [
'\x1b[?1005h',
// format: CSI M <button + 32> <row + 32> <col + 32>
// + utf8 encoding on row/col
report => {
const sReport = report.toString(); // decode with utf8
return {
state: evalButtonCode(sReport.charCodeAt(3) - 32),
col: sReport.charCodeAt(4) - 32,
row: sReport.charCodeAt(5) - 32
};
}
],
'SGR' : [
'\x1b[?1006h',
// format: CSI < Pbutton ; Prow ; Pcol M
report => {
// strip off introducer + M
const sReport = report.toString().slice(3, -1);
const [buttonCode, col, row] = sReport.split(';');
const state = evalButtonCode(buttonCode);
if (report[report.length - 1] === 'm'.charCodeAt(0)) {
state.action = 'release';
}
return {state, row, col};
}
],
'URXVT': [
'\x1b[?1015h',
// format: CSI <button + 32> ; Prow ; Pcol M
report => {
// strip off introducer + M
const sReport = report.toString().slice(2, -1);
const [button, col, row] = sReport.split(';');
return {state: evalButtonCode(button - 32), row, col};
}
]
}
function printMenu() {
console.log('\x1b[2J\x1b\[HTest mouse reports [Ctrl-C to exit]');
console.log();
console.log(' Selected protocol [Ctrl-A to switch]');
const protocols = Object.keys(PROTOCOLS);
for (let i = 0; i < protocols.length; ++i) {
console.log(` ${activeProtocol === i ? '->' : ' '} ${protocols[i]}`);
}
console.log();
console.log(' Selected encoding [Ctrl-B to switch]');
const encs = Object.keys(ENC);
for (let i = 0; i < encs.length; ++i) {
console.log(` ${activeEnc === i ? '->' : ' '} ${encs[i]}`);
}
process.stdout.write('\x1b[100;H');
}
function switchActiveProtocol() {
activeProtocol++;
activeProtocol %= Object.keys(PROTOCOLS).length;
activate();
}
function switchActiveEnc() {
activeEnc++;
activeEnc %= Object.keys(ENC).length;
activate();
}
function activate() {
// clear all protocols and encodings
process.stdout.write('\x1b[?9l\x1b[?1000l\x1b[?1001l\x1b[?1002l\x1b[?1003l');
process.stdout.write('\x1b[?1005l\x1b[?1006l\x1b[?1015l');
// apply new protocol and encoding
process.stdout.write(PROTOCOLS[Object.keys(PROTOCOLS)[activeProtocol]]);
process.stdout.write(ENC[Object.keys(ENC)[activeEnc]][0]);
console.log('\x1b[100;H\x1b[2A\x1b[2KReport:');
}
function applyReportData(data) {
let {state, row, col} = ENC[Object.keys(ENC)[activeEnc]][1](data);
console.log('\x1b[2KButton:', state.button, 'Action:', state.action, 'Modifier:', state.modifier, 'row:', row, 'col:', col);
// apply to cursor position
process.stdout.write(`\x1b[${row};${col}H`);
}
printMenu();
activate();
+11 -4
View File
@@ -36,7 +36,6 @@
*/
.xterm {
font-family: courier-new, courier, monospace;
font-feature-settings: "liga" 0;
position: relative;
user-select: none;
@@ -56,7 +55,7 @@
* The z-index of the helpers must be higher than the canvases in order for
* IMEs to appear on top.
*/
z-index: 10;
z-index: 5;
}
.xterm .xterm-helper-textarea {
@@ -70,7 +69,7 @@
top: 0;
width: 0;
height: 0;
z-index: -10;
z-index: -5;
/** Prevent wrapping so the IME appears against the textarea at the correct position */
white-space: nowrap;
overflow: hidden;
@@ -151,7 +150,7 @@
top: 0;
bottom: 0;
right: 0;
z-index: 100;
z-index: 10;
color: transparent;
}
@@ -162,3 +161,11 @@
height: 1px;
overflow: hidden;
}
.xterm-dim {
opacity: 0.5;
}
.xterm-underline {
text-decoration: underline;
}
+80 -50
View File
@@ -7,33 +7,40 @@
/// <reference path="../typings/xterm.d.ts"/>
import { Terminal } from '../lib/public/Terminal';
import * as attach from '../lib/addons/attach/attach';
import * as fit from '../lib/addons/fit/fit';
import * as fullscreen from '../lib/addons/fullscreen/fullscreen';
import * as search from '../lib/addons/search/search';
import * as webLinks from '../lib/addons/webLinks/webLinks';
import * as winptyCompat from '../lib/addons/winptyCompat/winptyCompat';
import { ISearchOptions } from '../lib/addons/search/Interfaces';
// Use tsc version (yarn watch)
import { Terminal } from '../out/public/Terminal';
import { AttachAddon } from '../addons/xterm-addon-attach/out/AttachAddon';
import { FitAddon } from '../addons/xterm-addon-fit/out/FitAddon';
import { SearchAddon, ISearchOptions } from '../addons/xterm-addon-search/out/SearchAddon';
import { WebLinksAddon } from '../addons/xterm-addon-web-links/out/WebLinksAddon';
import { WebglAddon } from '../addons/xterm-addon-webgl/out/WebglAddon';
// Use webpacked version (yarn package)
// import { Terminal } from '../lib/xterm';
// import { AttachAddon } from 'xterm-addon-attach';
// import { FitAddon } from 'xterm-addon-fit';
// import { SearchAddon, ISearchOptions } from 'xterm-addon-search';
// import { WebLinksAddon } from 'xterm-addon-web-links';
// import { WebglAddon } from 'xterm-addon-webgl';
// Pulling in the module's types relies on the <reference> above, it's looks a
// little weird here as we're importing "this" module
import { Terminal as TerminalType } from 'xterm';
import { Terminal as TerminalType, ITerminalOptions } from 'xterm';
export interface IWindowWithTerminal extends Window {
term: TerminalType;
Terminal?: typeof TerminalType;
AttachAddon?: typeof AttachAddon;
FitAddon?: typeof FitAddon;
SearchAddon?: typeof SearchAddon;
WebLinksAddon?: typeof WebLinksAddon;
WebglAddon?: typeof WebglAddon;
}
declare let window: IWindowWithTerminal;
Terminal.applyAddon(attach);
Terminal.applyAddon(fit);
Terminal.applyAddon(fullscreen);
Terminal.applyAddon(search);
Terminal.applyAddon(webLinks);
Terminal.applyAddon(winptyCompat);
let term;
let fitAddon: FitAddon;
let searchAddon: SearchAddon;
let protocol;
let socketURL;
let socket;
@@ -51,16 +58,15 @@ function setPadding(): void {
term.fit();
}
function getSearchOptions(): ISearchOptions {
function getSearchOptions(e: KeyboardEvent): ISearchOptions {
return {
regex: (document.getElementById('regex') as HTMLInputElement).checked,
wholeWord: (document.getElementById('whole-word') as HTMLInputElement).checked,
caseSensitive: (document.getElementById('case-sensitive') as HTMLInputElement).checked
caseSensitive: (document.getElementById('case-sensitive') as HTMLInputElement).checked,
incremental: e.key !== `Enter`
};
}
createTerminal();
const disposeRecreateButtonHandler = () => {
// If the terminal exists dispose of it, otherwise recreate it
if (term) {
@@ -76,16 +82,40 @@ const disposeRecreateButtonHandler = () => {
}
};
document.getElementById('dispose').addEventListener('click', disposeRecreateButtonHandler);
if (document.location.pathname === '/test') {
window.Terminal = Terminal;
window.AttachAddon = AttachAddon;
window.FitAddon = FitAddon;
window.SearchAddon = SearchAddon;
window.WebLinksAddon = WebLinksAddon;
window.WebglAddon = WebglAddon;
} else {
createTerminal();
document.getElementById('dispose').addEventListener('click', disposeRecreateButtonHandler);
document.getElementById('webgl').addEventListener('click', () => term.loadAddon(new WebglAddon()));
}
function createTerminal(): void {
// Clean terminal
while (terminalContainer.children.length) {
terminalContainer.removeChild(terminalContainer.children[0]);
}
term = new Terminal({});
const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].indexOf(navigator.platform) >= 0;
term = new Terminal({
windowsMode: isWindows
} as ITerminalOptions);
// Load addons
const typedTerm = term as TerminalType;
typedTerm.loadAddon(new WebLinksAddon());
searchAddon = new SearchAddon();
typedTerm.loadAddon(searchAddon);
fitAddon = new FitAddon();
typedTerm.loadAddon(fitAddon);
window.term = term; // Expose `term` to window for debugging purposes
term.on('resize', (size: { cols: number, rows: number }) => {
term.onResize((size: { cols: number, rows: number }) => {
if (!pid) {
return;
}
@@ -99,23 +129,17 @@ function createTerminal(): void {
socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + '/terminals/';
term.open(terminalContainer);
term.winptyCompatInit();
term.webLinksInit();
term.fit();
fitAddon.fit();
term.focus();
addDomListener(paddingElement, 'change', setPadding);
addDomListener(actionElements.findNext, 'keyup', (e) => {
const searchOptions = getSearchOptions();
searchOptions.incremental = e.key !== `Enter`;
term.findNext(actionElements.findNext.value, searchOptions);
searchAddon.findNext(actionElements.findNext.value, getSearchOptions(e));
});
addDomListener(actionElements.findPrevious, 'keyup', (e) => {
if (e.key === `Enter`) {
term.findPrevious(actionElements.findPrevious.value, getSearchOptions());
}
searchAddon.findPrevious(actionElements.findPrevious.value, getSearchOptions(e));
});
// fit is called within a setTimeout, cols and rows need this.
@@ -143,7 +167,14 @@ function createTerminal(): void {
}
function runRealTerminal(): void {
term.attach(socket);
/**
* The demo defaults to string transport by default.
* To run it with UTF8 binary transport, swap comment on
* the lines below. (Must also be switched in server.js)
*/
term.loadAddon(new AttachAddon(socket));
// term.loadAddon(new AttachAddon(socket, {inputUtf8: true}));
term._initialized = true;
}
@@ -164,24 +195,21 @@ function runFakeTerminal(): void {
term.writeln('');
term.prompt();
term._core.register(term.addDisposableListener('key', (key, ev) => {
const printable = !ev.altKey && !ev.altGraphKey && !ev.ctrlKey && !ev.metaKey;
term.onKey((e: { key: string, domEvent: KeyboardEvent }) => {
const ev = e.domEvent;
const printable = !ev.altKey && !ev.ctrlKey && !ev.metaKey;
if (ev.keyCode === 13) {
term.prompt();
} else if (ev.keyCode === 8) {
// Do not delete the prompt
if (term.x > 2) {
if (term._core.buffer.x > 2) {
term.write('\b \b');
}
} else if (printable) {
term.write(key);
term.write(e.key);
}
}));
term._core.register(term.addDisposableListener('paste', (data, ev) => {
term.write(data);
}));
});
}
function initOptions(term: TerminalType): void {
@@ -189,7 +217,6 @@ function initOptions(term: TerminalType): void {
// Internal only options
'cancelEvents',
'convertEol',
'debug',
'handler',
'screenKeys',
'termName',
@@ -201,12 +228,12 @@ function initOptions(term: TerminalType): void {
bellSound: null,
bellStyle: ['none', 'sound'],
cursorStyle: ['block', 'underline', 'bar'],
experimentalCharAtlas: ['none', 'static', 'dynamic'],
fontFamily: null,
fontWeight: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'],
fontWeightBold: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'],
logLevel: ['debug', 'info', 'warn', 'error', 'off'],
rendererType: ['dom', 'canvas'],
experimentalBufferLineImpl: ['JsArray', 'TypedArray']
wordSeparator: null
};
const options = Object.keys((<any>term)._core.options);
const booleanOptions = [];
@@ -262,8 +289,11 @@ function initOptions(term: TerminalType): void {
console.log('change', o, input.value);
if (o === 'cols' || o === 'rows') {
updateTerminalSize();
} else if (o === 'lineHeight') {
term.setOption(o, parseFloat(input.value));
updateTerminalSize();
} else {
term.setOption(o, o === 'lineHeight' ? parseFloat(input.value) : parseInt(input.value, 10));
term.setOption(o, parseInt(input.value));
}
});
});
@@ -284,9 +314,9 @@ function addDomListener(element: HTMLElement, type: string, handler: (...args: a
function updateTerminalSize(): void {
const cols = parseInt((<HTMLInputElement>document.getElementById(`opt-cols`)).value, 10);
const rows = parseInt((<HTMLInputElement>document.getElementById(`opt-rows`)).value, 10);
const width = (cols * term._core.renderer.dimensions.actualCellWidth + term._core.viewport.scrollBarWidth).toString() + 'px';
const height = (rows * term._core.renderer.dimensions.actualCellHeight).toString() + 'px';
const width = (cols * term._core._renderService.dimensions.actualCellWidth + term._core.viewport.scrollBarWidth).toString() + 'px';
const height = (rows * term._core._renderService.dimensions.actualCellHeight).toString() + 'px';
terminalContainer.style.width = width;
terminalContainer.style.height = height;
term.fit();
fitAddon.fit();
}
+5 -4
View File
@@ -2,9 +2,9 @@
<html>
<head>
<title>xterm.js demo</title>
<link rel="stylesheet" href="/build/xterm.css" />
<link rel="stylesheet" href="/build/addons/fullscreen/fullscreen.css" />
<link rel="stylesheet" href="style.css" />
<link rel="shortcut icon" type="image/png" href="/logo.png">
<link rel="stylesheet" href="/xterm.css" />
<link rel="stylesheet" href="/style.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.auto.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/1.0.0/fetch.min.js"></script>
</head>
@@ -16,7 +16,7 @@
<p>
<label>Find next <input id="find-next"/></label>
<label>Find previous <input id="find-previous"/></label>
<label>Use regex<input type="checkbox" id="regex"/></label>
<label>Use regex<input type="checkbox" id="regex"/></label>
<label>Case sensitive<input type="checkbox" id="case-sensitive"/></label>
<label>Whole word<input type="checkbox" id="whole-word"/></label>
</p>
@@ -36,6 +36,7 @@
<hr/>
<p><strong>Attention:</strong> The demo is a barebones implementation and is designed for the development and evaluation of xterm.js only. Exposing the demo to the public as is would introduce security risks for the host.</p>
<button id="dispose" title="This is used to testing memory leaks">Dispose terminal</button>
<button id="webgl">Enable WebGL Renderer</button>
<script src="dist/client-bundle.js" defer ></script>
</body>
</html>
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

+42 -9
View File
@@ -3,6 +3,13 @@ var expressWs = require('express-ws');
var os = require('os');
var pty = require('node-pty');
/**
* Whether to use UTF8 binary transport.
* (Must also be switched in client.ts)
*/
const USE_BINARY_UTF8 = false;
function startServer() {
var app = express();
expressWs(app);
@@ -10,29 +17,36 @@ function startServer() {
var terminals = {},
logs = {};
app.use('/build', express.static(__dirname + '/../build'));
app.use('/xterm.css', express.static(__dirname + '/../css/xterm.css'));
app.get('/logo.png', (req, res) => res.sendFile(__dirname + '/logo.png'));
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
app.get('/test', function(req, res){
res.sendFile(__dirname + '/test.html');
});
app.get('/style.css', function(req, res){
res.sendFile(__dirname + '/style.css');
});
app.get('/dist/client-bundle.js', function(req, res){
res.sendFile(__dirname + '/dist/client-bundle.js');
});
app.use('/dist', express.static(__dirname + '/dist'));
app.use('/src', express.static(__dirname + '/src'));
app.post('/terminals', function (req, res) {
const env = Object.assign({}, process.env);
env['COLORTERM'] = 'truecolor';
var cols = parseInt(req.query.cols),
rows = parseInt(req.query.rows),
term = pty.spawn(process.platform === 'win32' ? 'cmd.exe' : 'bash', [], {
name: 'xterm-color',
name: 'xterm-256color',
cols: cols || 80,
rows: rows || 24,
cwd: process.env.PWD,
env: process.env
cwd: env.PWD,
env: env,
encoding: USE_BINARY_UTF8 ? null : 'utf8'
});
console.log('Created terminal with PID: ' + term.pid);
@@ -61,6 +75,7 @@ function startServer() {
console.log('Connected to terminal ' + term.pid);
ws.send(logs[term.pid]);
// string message buffering
function buffer(socket, timeout) {
let s = '';
let sender = null;
@@ -75,7 +90,25 @@ function startServer() {
}
};
}
const send = buffer(ws, 5);
// binary message buffering
function bufferUtf8(socket, timeout) {
let buffer = [];
let sender = null;
let length = 0;
return (data) => {
buffer.push(data);
length += data.length;
if (!sender) {
sender = setTimeout(() => {
socket.send(Buffer.concat(buffer, length));
buffer = [];
sender = null;
length = 0;
}, timeout);
}
};
}
const send = USE_BINARY_UTF8 ? bufferUtf8(ws, 5) : buffer(ws, 5);
term.on('data', function(data) {
try {
@@ -99,7 +132,7 @@ function startServer() {
var port = process.env.PORT || 3000,
host = os.platform() === 'win32' ? '127.0.0.1' : '0.0.0.0';
console.log('App listening to http://' + host + ':' + port);
console.log('App listening to http://127.0.0.1:' + port);
app.listen(port, host);
}
+22 -4
View File
@@ -5,14 +5,22 @@
* This file is the entry point for browserify.
*/
const cp = require('child_process');
const path = require('path');
const webpack = require('webpack');
const startServer = require('./server.js');
startServer();
// Build/watch client source
/**
* This webpack config builds and watches the demo project. It works by taking the output from tsc
* (via `yarn watch`) which is put into `out/` and then webpacks it into `demo/dist/`. The aliases
* are used fix up the absolute paths output by tsc (because of `baseUrl` and `paths` in
* `tsconfig.json`.
*
* For production builds see `webpack.config.js` in the root directory. If that is built the demo
* can use that by switching out which `Terminal` is imported in `client.ts`, this is useful for
* validating that the packaged version works correctly.
*/
const clientConfig = {
entry: path.resolve(__dirname, 'client.ts'),
devtool: 'inline-source-map',
@@ -26,12 +34,22 @@ const clientConfig = {
{
test: /\.js$/,
use: ["source-map-loader"],
enforce: "pre"
enforce: "pre",
exclude: /node_modules/
}
]
},
resolve: {
extensions: [ '.tsx', '.ts', '.js' ]
modules: [
'node_modules',
path.resolve(__dirname, '..'),
path.resolve(__dirname, '../addons')
],
extensions: [ '.tsx', '.ts', '.js' ],
alias: {
common: path.resolve('./out/common'),
browser: path.resolve('./out/browser')
}
},
output: {
filename: 'client-bundle.js',
+12
View File
@@ -0,0 +1,12 @@
<!doctype html>
<html>
<head>
<title>xterm.js integration test fixture</title>
<link rel="stylesheet" href="/xterm.css" />
<link rel="stylesheet" href="/style.css" />
</head>
<body>
<div id="terminal-container"></div>
<script src="dist/client-bundle.js" defer ></script>
</body>
</html>
+10 -2
View File
@@ -1,9 +1,17 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"target": "es2015",
"rootDir": ".",
"sourceMap": true
"sourceMap": true,
"baseUrl": ".",
"paths": {
"xterm-addon-attach": ["../addons/xterm-addon-attach"],
"xterm-addon-fit": ["../addons/xterm-addon-fit"],
"xterm-addon-search": ["../addons/xterm-addon-search"],
"xterm-addon-web-links": ["../addons/xterm-addon-web-links"],
"xterm-addon-webgl": ["../addons/xterm-addon-webgl"]
}
},
"include": [
"client.ts",
-87
View File
@@ -1,87 +0,0 @@
var express = require('express');
var app = express();
var expressWs = require('express-ws')(app);
var os = require('os');
var pty = require('node-pty');
var terminals = {},
logs = {};
app.use('/build', express.static(__dirname + '/../../build'));
app.use('/demo', express.static(__dirname + '/../../demo'));
app.use('/zmodemjs', express.static(__dirname + '/../../node_modules/zmodem.js/dist'));
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
app.get('/style.css', function(req, res){
res.sendFile(__dirname + '../style.css');
});
app.get('/main.js', function(req, res){
res.sendFile(__dirname + '/main.js');
});
app.post('/terminals', function (req, res) {
var cols = parseInt(req.query.cols),
rows = parseInt(req.query.rows),
term = pty.spawn(process.platform === 'win32' ? 'cmd.exe' : 'bash', [], {
encoding: null,
name: 'xterm-color',
cols: cols || 80,
rows: rows || 24,
cwd: process.env.PWD,
env: process.env
});
console.log('Created terminal with PID: ' + term.pid);
terminals[term.pid] = term;
logs[term.pid] = '';
term.on('data', function(data) {
logs[term.pid] += data;
});
res.send(term.pid.toString());
res.end();
});
app.post('/terminals/:pid/size', function (req, res) {
var pid = parseInt(req.params.pid),
cols = parseInt(req.query.cols),
rows = parseInt(req.query.rows),
term = terminals[pid];
term.resize(cols, rows);
console.log('Resized terminal ' + pid + ' to ' + cols + ' cols and ' + rows + ' rows.');
res.end();
});
app.ws('/terminals/:pid', function (ws, req) {
var term = terminals[parseInt(req.params.pid)];
console.log('Connected to terminal ' + term.pid);
ws.send(logs[term.pid]);
term.on('data', function(data) {
try {
ws.send(data);
} catch (ex) {
// The WebSocket is not open, ignore
}
});
ws.on('message', function(msg) {
term.write(msg);
});
ws.on('close', function () {
term.kill();
console.log('Closed terminal ' + term.pid);
// Clean things up
delete terminals[term.pid];
delete logs[term.pid];
});
});
var port = process.env.PORT || 3000,
host = os.platform() === 'win32' ? '127.0.0.1' : '0.0.0.0';
console.log('App listening to http://' + host + ':' + port);
app.listen(port, host);
-128
View File
@@ -1,128 +0,0 @@
<!doctype html>
<html>
<head>
<title>xterm.js demo</title>
<link rel="stylesheet" href="/build/xterm.css" />
<link rel="stylesheet" href="/build/addons/fullscreen/fullscreen.css" />
<link rel="stylesheet" href="/demo/style.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.auto.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/1.0.0/fetch.min.js"></script>
<script src="/build/xterm.js" ></script>
<script src="/build/addons/attach/attach.js" ></script>
<script src="/zmodemjs/zmodem.js"></script>
<script src="/build/addons/zmodem/zmodem.js" ></script>
<script src="/build/addons/fit/fit.js" ></script>
<script src="/build/addons/fullscreen/fullscreen.js" ></script>
<script src="/build/addons/search/search.js" ></script>
</head>
<body>
<h1>xterm.js: xterm, in the browser</h1>
<div id="terminal-container"></div>
<div id="zmodem_controls">
<form id="zm_start" style="display: none" action="javascript:void(0)">
ZMODEM detected: Start ZMODEM session?
<label><input id="zmstart_yes" name="zmstart" type=radio checked value="1"> Yes</label>
&nbsp;
<label><input name="zmstart" type=radio value=""> No</label>
<button type="submit">Submit</button>
</form>
<form id="zm_offer" style="display: none" action="javascript:void(0)">
<p>ZMODEM File offered!</p>
<label><input id="zmaccept_yes" name="zmaccept" type=radio checked value="1"> Accept</label>
&nbsp;
<label><input name="zmaccept" type=radio value=""> Skip</label>
<button type="submit">Submit</button>
</form>
<div id="zm_file" style="display: none">
<div>Name: <span id="name"></span></div>
<div>Size: <span id="size"></span></div>
<div>Last modified: <span id="mtime"></span></div>
<div>Mode: <span id="mode"></span></div>
<br>
<div>Conversion: <span id="zfile_conversion"></span></div>
<div>Management: <span id="zfile_management"></span></div>
<div>Transport: <span id="zfile_transport"></span></div>
<div>Sparse? <span id="zfile_sparse"></span></div>
<br>
<div>Files remaining in batch: <span id="files_remaining"></span></div>
<div>Bytes remaining in batch: <span id="bytes_remaining"></span></div>
</div>
<form id="zm_progress" style="display: none" action="javascript:void(0)">
<div><span id="percent_received"></span>% (<span id="bytes_received"></span> bytes) received</div>
<button id="zm_progress_skipper" type="button" onclick="skip_current_file();">Skip File</button>
</form>
<form id="zm_choose" style="display: none" action="javascript:void(0)">
<label>Choose file(s): <input id="zm_files" type="file" multiple></label>
</form>
</div>
<div>
<h2>Actions</h2>
<p>
<label>Find next <input id="find-next"/></label>
<label>Find previous <input id="find-previous"/></label>
</p>
</div>
<div>
<h2>Options</h2>
<p>
<label><input type="checkbox" id="option-cursor-blink"> cursorBlink</label>
</p>
<p>
<label><input type="checkbox" checked id="zmodem-auto"> Accept all ZMODEM prompts<sup>*</sup></label>
</p>
<p>
<label>
cursorStyle
<select id="option-cursor-style">
<option value="block">block</option>
<option value="underline">underline</option>
<option value="bar">bar</option>
</select>
</label>
</p>
<p>
<label>
bellStyle
<select id="option-bell-style">
<option value="">none</option>
<option value="sound">sound</option>
<option value="visual">visual</option>
<option value="both">both</option>
</select>
</label>
</p>
<p>
<label>scrollback <input type="number" id="option-scrollback" value="1000" /></label>
</p>
<p>
<label>tabStopWidth <input type="number" id="option-tabstopwidth" value="8" /></label>
</p>
<div>
<h3>Size</h3>
<div>
<div style="display: inline-block; margin-right: 16px;">
<label for="cols">Columns</label>
<input type="number" id="cols" />
</div>
<div style="display: inline-block; margin-right: 16px;">
<label for="rows">Rows</label>
<input type="number" id="rows" />
</div>
</div>
</div>
</div>
<p><strong>Attention:</strong> The demo is a barebones implementation and is designed for xterm.js evaluation purposes only. Exposing the demo to the public as is would introduce security risks for the host.</p>
<p><sup>*</sup> ZMODEM file transfers are supported via an addon. To try it out, install <a href="https://ohse.de/uwe/software/lrzsz.html"><code>lrzsz</code></a> onto the remote peer, then run <code>rz</code> to send from your browser or <code>sz &lt;file&gt;</code> to send from the remote peer.</p>
<script src="main.js" defer ></script>
</body>
</html>
-388
View File
@@ -1,388 +0,0 @@
"use strict";
var term,
protocol,
socketURL,
socket,
pid;
Terminal.applyAddon(fit);
Terminal.applyAddon(attach);
Terminal.applyAddon(zmodem);
Terminal.applyAddon(search);
var terminalContainer = document.getElementById('terminal-container'),
actionElements = {
findNext: document.querySelector('#find-next'),
findPrevious: document.querySelector('#find-previous')
},
optionElements = {
cursorBlink: document.querySelector('#option-cursor-blink'),
cursorStyle: document.querySelector('#option-cursor-style'),
scrollback: document.querySelector('#option-scrollback'),
tabstopwidth: document.querySelector('#option-tabstopwidth'),
bellStyle: document.querySelector('#option-bell-style')
},
colsElement = document.getElementById('cols'),
rowsElement = document.getElementById('rows');
function setTerminalSize() {
var cols = parseInt(colsElement.value, 10);
var rows = parseInt(rowsElement.value, 10);
var viewportElement = document.querySelector('.xterm-viewport');
var scrollBarWidth = viewportElement.offsetWidth - viewportElement.clientWidth;
var width = (cols * term.charMeasure.width + 20 /*room for scrollbar*/).toString() + 'px';
var height = (rows * term.charMeasure.height).toString() + 'px';
terminalContainer.style.width = width;
terminalContainer.style.height = height;
term.resize(cols, rows);
}
colsElement.addEventListener('change', setTerminalSize);
rowsElement.addEventListener('change', setTerminalSize);
actionElements.findNext.addEventListener('keypress', function (e) {
if (e.key === "Enter") {
e.preventDefault();
term.findNext(actionElements.findNext.value);
}
});
actionElements.findPrevious.addEventListener('keypress', function (e) {
if (e.key === "Enter") {
e.preventDefault();
term.findPrevious(actionElements.findPrevious.value);
}
});
optionElements.cursorBlink.addEventListener('change', function () {
term.setOption('cursorBlink', optionElements.cursorBlink.checked);
});
optionElements.cursorStyle.addEventListener('change', function () {
term.setOption('cursorStyle', optionElements.cursorStyle.value);
});
optionElements.bellStyle.addEventListener('change', function () {
term.setOption('bellStyle', optionElements.bellStyle.value);
});
optionElements.scrollback.addEventListener('change', function () {
term.setOption('scrollback', parseInt(optionElements.scrollback.value, 10));
});
optionElements.tabstopwidth.addEventListener('change', function () {
term.setOption('tabStopWidth', parseInt(optionElements.tabstopwidth.value, 10));
});
createTerminal();
function createTerminal() {
// Clean terminal
while (terminalContainer.children.length) {
terminalContainer.removeChild(terminalContainer.children[0]);
}
term = new Terminal({
cursorBlink: optionElements.cursorBlink.checked,
scrollback: parseInt(optionElements.scrollback.value, 10),
tabStopWidth: parseInt(optionElements.tabstopwidth.value, 10)
});
term.on('resize', function (size) {
if (!pid) {
return;
}
var cols = size.cols,
rows = size.rows,
url = '/terminals/' + pid + '/size?cols=' + cols + '&rows=' + rows;
fetch(url, {method: 'POST'});
});
protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://';
socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + '/terminals/';
term.open(terminalContainer);
term.fit();
// fit is called within a setTimeout, cols and rows need this.
setTimeout(function () {
colsElement.value = term.cols;
rowsElement.value = term.rows;
// Set terminal size again to set the specific dimensions on the demo
setTerminalSize();
fetch('/terminals?cols=' + term.cols + '&rows=' + term.rows, {method: 'POST'}).then(function (res) {
res.text().then(function (pid) {
window.pid = pid;
socketURL += pid;
socket = new WebSocket(socketURL);
socket.onopen = runRealTerminal;
socket.onclose = runFakeTerminal;
socket.onerror = runFakeTerminal;
term.zmodemAttach(socket, {
noTerminalWriteOutsideSession: true,
} );
term.on("zmodemRetract", () => {
start_form.style.display = "none";
start_form.onsubmit = null;
});
term.on("zmodemDetect", (detection) => {
function do_zmodem() {
term.detach();
let zsession = detection.confirm();
var promise;
if (zsession.type === "receive") {
promise = _handle_receive_session(zsession);
}
else {
promise = _handle_send_session(zsession);
}
promise.catch( console.error.bind(console) ).then( () => {
term.attach(socket);
} );
}
if (_auto_zmodem()) {
do_zmodem();
}
else {
start_form.style.display = "";
start_form.onsubmit = function(e) {
start_form.style.display = "none";
if (document.getElementById("zmstart_yes").checked) {
do_zmodem();
}
else {
detection.deny();
}
};
}
});
});
});
}, 0);
}
//----------------------------------------------------------------------
// UI STUFF
function _show_file_info(xfer) {
var file_info = xfer.get_details();
document.getElementById("name").textContent = file_info.name;
document.getElementById("size").textContent = file_info.size;
document.getElementById("mtime").textContent = file_info.mtime;
document.getElementById("files_remaining").textContent = file_info.files_remaining;
document.getElementById("bytes_remaining").textContent = file_info.bytes_remaining;
document.getElementById("mode").textContent = "0" + file_info.mode.toString(8);
var xfer_opts = xfer.get_options();
["conversion", "management", "transport", "sparse"].forEach( (lbl) => {
document.getElementById(`zfile_${lbl}`).textContent = xfer_opts[lbl];
} );
document.getElementById("zm_file").style.display = "";
}
function _hide_file_info() {
document.getElementById("zm_file").style.display = "none";
}
function _save_to_disk(xfer, buffer) {
return Zmodem.Browser.save_to_disk(buffer, xfer.get_details().name);
}
var skipper_button = document.getElementById("zm_progress_skipper");
var skipper_button_orig_text = skipper_button.textContent;
function _show_progress() {
skipper_button.disabled = false;
skipper_button.textContent = skipper_button_orig_text;
document.getElementById("bytes_received").textContent = 0;
document.getElementById("percent_received").textContent = 0;
document.getElementById("zm_progress").style.display = "";
}
function _update_progress(xfer) {
var total_in = xfer.get_offset();
document.getElementById("bytes_received").textContent = total_in;
var percent_received = 100 * total_in / xfer.get_details().size;
document.getElementById("percent_received").textContent = percent_received.toFixed(2);
}
function _hide_progress() {
document.getElementById("zm_progress").style.display = "none";
}
var start_form = document.getElementById("zm_start");
function _auto_zmodem() {
return document.getElementById("zmodem-auto").checked;
}
// END UI STUFF
//----------------------------------------------------------------------
function _handle_receive_session(zsession) {
zsession.on("offer", function(xfer) {
current_receive_xfer = xfer;
_show_file_info(xfer);
var offer_form = document.getElementById("zm_offer");
function on_form_submit() {
offer_form.style.display = "none";
//START
//if (offer_form.zmaccept.value) {
if (_auto_zmodem() || document.getElementById("zmaccept_yes").checked) {
_show_progress();
var FILE_BUFFER = [];
xfer.on("input", (payload) => {
_update_progress(xfer);
FILE_BUFFER.push( new Uint8Array(payload) );
});
xfer.accept().then(
() => {
_save_to_disk(xfer, FILE_BUFFER);
},
console.error.bind(console)
);
}
else {
xfer.skip();
}
//END
}
if (_auto_zmodem()) {
on_form_submit();
}
else {
offer_form.onsubmit = on_form_submit;
offer_form.style.display = "";
}
} );
var promise = new Promise( (res) => {
zsession.on("session_end", () => {
_hide_file_info();
_hide_progress();
res();
} );
} );
zsession.start();
return promise;
}
function _handle_send_session(zsession) {
var choose_form = document.getElementById("zm_choose");
choose_form.style.display = "";
var file_el = document.getElementById("zm_files");
var promise = new Promise( (res) => {
file_el.onchange = function(e) {
choose_form.style.display = "none";
var files_obj = file_el.files;
Zmodem.Browser.send_files(
zsession,
files_obj,
{
on_offer_response(obj, xfer) {
if (xfer) _show_progress();
//console.log("offer", xfer ? "accepted" : "skipped");
},
on_progress(obj, xfer) {
_update_progress(xfer);
},
on_file_complete(obj) {
//console.log("COMPLETE", obj);
_hide_progress();
},
}
).then(_hide_progress).then(
zsession.close.bind(zsession),
console.error.bind(console)
).then( () => {
_hide_file_info();
_hide_progress();
res();
} );
};
} );
return promise;
}
//This is here to allow canceling of an in-progress ZMODEM transfer.
var current_receive_xfer;
//Called from HTML directly.
function skip_current_file() {
current_receive_xfer.skip();
skipper_button.disabled = true;
skipper_button.textContent = "Waiting for server to acknowledge skip …";
}
function runRealTerminal() {
term.attach(socket);
term._initialized = true;
}
function runFakeTerminal() {
if (term._initialized) {
return;
}
term._initialized = true;
var shellprompt = '$ ';
term.prompt = function () {
term.write('\r\n' + shellprompt);
};
term.writeln('Welcome to xterm.js');
term.writeln('This is a local terminal emulation, without a real terminal in the back-end.');
term.writeln('Type some keys and commands to play around.');
term.writeln('');
term.prompt();
term.on('key', function (key, ev) {
var printable = (
!ev.altKey && !ev.altGraphKey && !ev.ctrlKey && !ev.metaKey
);
if (ev.keyCode == 13) {
term.prompt();
} else if (ev.keyCode == 8) {
// Do not delete the prompt
if (term.x > 2) {
term.write('\b \b');
}
} else if (printable) {
term.write(key);
}
});
term.on('paste', function (data, ev) {
term.write(data);
});
}
+1 -1
View File
@@ -7,7 +7,7 @@ services:
volumes:
- ./:/usr/src/app
ports:
- ${XTERMJS_PORT:3000}:3000
- ${XTERMJS_PORT:-3000}:3000
command: ["npm", "start"]
watch:
@@ -0,0 +1,73 @@
from glob import glob
import os
import sys
import termios
import atexit
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
def enable_echo(fd, enabled):
(iflag, oflag, cflag, lflag, ispeed, ospeed, cc) = termios.tcgetattr(fd)
if enabled:
lflag |= termios.ECHO
else:
lflag &= ~termios.ECHO
new_attr = [iflag, oflag, cflag, lflag, ispeed, ospeed, cc]
termios.tcsetattr(fd, termios.TCSANOW, new_attr)
atexit.register(enable_echo, sys.stdin.fileno(), True)
output = []
def log(append=False, *s):
if append:
output[-1] += ' ' + ' '.join(str(part) for part in s)
else:
output.append(' '.join(str(part) for part in s))
def reset_terminal():
sys.stdout.write('\x1bc\x1b[H')
sys.stdout.flush()
def test():
count = 0
passed = 0
for i, testfile in enumerate(sorted(glob(os.path.join(BASE_DIR, '*.in')))):
count += 1
log(False, os.path.basename(testfile))
reset_terminal()
with open(testfile) as test:
sys.stdout.write('\x1b]0;%s\x07' % os.path.basename(testfile))
sys.stdout.write(test.read()+'\x1bt')
sys.stdout.flush()
with open(os.path.join(os.path.dirname(testfile),
os.path.basename(testfile).split('.')[0]+'.text')) as expected:
terminal_output = sys.stdin.read()
if not terminal_output:
# we are in xterm
continue
if terminal_output != expected.read():
log(True, '\x1b[31merror\x1b[0m')
with open(os.path.join(os.path.dirname(testfile), 'output',
os.path.basename(testfile)), 'w') as t_out:
t_out.write(terminal_output)
else:
passed += 1
log(True, '\x1b[32mpass\x1b[0m')
return count, passed
if __name__ == '__main__':
enable_echo(sys.stdin.fileno(), False)
count, passed = test()
enable_echo(sys.stdin.fileno(), True)
reset_terminal()
for i in range(len(output)/2+1):
if not (i+1) % 25:
sys.stdin.read()
print ''.join(i.ljust(40) for i in output[i*2:i*2+2])
print '\x1b[33mcoverage: %s/%s (%d%%) tests passed.\x1b[0m' % (passed, count, passed*100/count)
@@ -27,5 +27,5 @@ r
s
t
uvwxyz


The end.
@@ -1,25 +1,25 @@
1
2
6
7
8
9 ABC
6
7
8
9 ABC
DEF
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
yz qrstu vwx
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
yz vwx
The end.
@@ -1,3 +1,3 @@
1D2D3D4D5D6D7D8D9ABCDEFaDbDcDdDeDfDgDhDiDjDkDlDmDnDoDpDqDrDsDtDuvwxyz


The end.

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