Hyper: Change to xterm.js

Created on 19 Dec 2016  Β·  68Comments  Β·  Source: vercel/hyper

Hi, after evaluating several JS libs for terminal emulation to improve the performance of hyper, I found that https://github.com/sourcelair/xterm.js would probably better suite this project.

  • πŸ‘ It is actively maintained.
  • πŸ‘ Used by Visual Studio Code and maintained by @Tyriar , who would probably welcome some combined efforts on fixing bugs and improving xterm.js
  • πŸ‘ It doesn't require to sign an NDA to contribute
  • πŸ‘ It doesn't isolate the terminal DOM inside an iframe, which makes it much easier to hack and style
  • πŸ‘ It has solved some of the problems we are having with hterm currently, e.g. IME and CJK character support
  • πŸ‘Ž It is currently being migrated to typescript, which might not be everyone's favourite flavour
  • πŸ‘Ž It feels slightly less responsive at the moment, I think this is caused by the queue mechanism that tries to schedule big ui updates and introduces some ms lag - but it can be optimized

I did some quick tests replacing hterm with xterm.js and the performance seems level. I was also able to quick and dirty put in some of the features we get from hterm, e.g. changing the cursor color on bell.

If you like I can start working on pull request that replaces the current implementation with xterm.js, but I'd like to see some thumbs up for that first :neckbeard:

Enhancement πŸ’¬ Feedback Wanted

Most helpful comment

I'm very happy with the state of xterm.js right now. Wanted to give everyone heads-up on this thread that we are currently migrating to it.

All 68 comments

When I first tested it it had some serious problems in terms of support of terminal features and slower performance. Would be useful to revisit this now, though

Agree, would actually be good to have some reproducible test cases to compare both against each other. Like the vtop or emoji test for non standard-width characters (which is broken in xterm and hterm) and locale specific tests, as well as tests for unicode, performance (seq 1000000) etc... I will try to create a couple of test files and run them to compare the output.

It also may fix #270.

Actually it won't, it has no support for cursor shapes at all. It would be a lot easier to fix #270 though.

@mofux I recently generated the stats at https://github.com/zeit/hyper/issues/687#issuecomment-268141860. It's a really somewhat terrible ruby script but I could put it in a gist if you're interested.

It's actually a bit involved to measure output lag (from the outside) because the actual commands finish long before the output arrives.

https://github.com/zeit/hyper/pull/1286#issuecomment-268610797

There are a number of other styling things I'd like to fix, such as underline/i-beam cursors not blinking, but the root cause is hterm. SO CAN WE PLEASE FOR THE LOVE OF GOD USE A JAVASCRIPT TERMINAL LIBRARY THAT DOES NOT REQUIRE SIGNING AN NDA TO CONTRIBUTE TO!!!!!!11!!1 #1275

FYI, the main issues on xterm.js to watch regarding perf are:

It might be worth holding out on migrating until these 2 are tackled if the laggy input is too much of a regression (likely some time in January of February).

I say we wait then. We finally have a good looking terminal on Windows, I'd be sad if it turns laggy :(

I agree. Thanks @Tyriar for giving us a rough roadmap. I'll follow the issues closely and catch up again once they have been resolved.

+1 for switching to xterm.js. As an Asian user, I would be very happy to see correctly rendered CJK characters and support for IME, as for now they mess up any other output in hyper.

@dionisokan can you describe the issues you have with the IME support in 1.0? cc @matheuss

@rauchg I have uploaded two GIFs (iTerm 2 & Hyper 1.0) depicting Chinese IME usage under iTerm 2 and Hyper 1.0, with the same font configuration in both terminal emulators.
I typed zhongwenceshi in order to get δΈ­ζ–‡ζ΅‹θ―•. As the GIFs show, the iTerm one is normal, and what it should be, while the Hyper one is unacceptable.
Thanks in advance for looking into this problem. Also, this is likely the same issue as #149.

So helpful @dionisokan, thank you

I made another test. Using Chinese locales, so GNU softwares on my Mac shows in Chinese if possible. My nano is in Chinese, and here goes the result of a random nano somethingnew.text:

  • under iTerm 2, which is normal:
    image

  • under Hyper 1.0, which is abnormal:
    image

Would like to help if further testing is requested.

The xterm.js performance issues should be fixed in the next release, see https://github.com/Microsoft/vscode/issues/17875 for what's done and what's left. We're targeting Feb 6 for v2.3.0.

An interesting benchmark would be to see how it handles yes.

Currently, hyper becomes totally unusable for 10-20 seconds after running yes

With the https://github.com/sourcelair/xterm.js/pull/438 branch which is pending review, yes is silky smooth after the initial ~2 seconds of filling of the buffer (created https://github.com/sourcelair/xterm.js/issues/444 to look into this). We don't currently sync with the backing program though which could cause issues if the app is sending too much text to process (tracked in https://github.com/sourcelair/xterm.js/issues/425).

@avindra the question is whether that's a problem with the current RPC / redux dance, rather than hterm itself.

We have some improvements coming in that front regardless, which will be good for hterm, xterm, or whatever we use in the future

Update on xterm.js: The big performance issues have landed (excluding https://github.com/sourcelair/xterm.js/pull/447) and I've started rewriting the parser to be more performant and better organized (https://github.com/sourcelair/xterm.js/pull/462). After these changes xterm.js will no longer lock up when a program gives a large amount of output, and it will finish the command a lot faster (typically 300-500% faster depending on situation):

Old (within vscode) ~11s:

out

New ~2.5s:

out-2

Note that the above does not have all the fixes included and it is also being hosted within VS Code which is quite heavy when compared to Hyper. Hyper currently acts similar (but worse) than the old xterm.js (see https://github.com/zeit/hyper/issues/94).

These changes and the larger move towards TypeScript are also bringing us closer to separating rendering logic completely (necessary for https://github.com/zeit/hyper/issues/781 and https://github.com/Microsoft/vscode/issues/12000).

@Tyriar we're working on debouncing the pty calls, I don't think the choking up is hterm's fault?

@rauchg if by debouncing you're talking about sending XOFF and XON to the pty then fixing that would fix the lock up issue, it won't fix processing or rendering times though. The above doesn't actually include the XOFF/XON catch up support just yet (https://github.com/sourcelair/xterm.js/pull/447), it's just that rendering isn't as taxing anymore.

If you did add catch up via XOFF/XON, but did not improve rendering or parsing performance the commands will be smooth but take a very long time (because you're still doing all the same stuff, it's just spaced out more). Hope that made sense, I've been digging into this stuff a lot in the last 2 weeks :smile:

I see @Tyriar, thanks for the info re: XOFF. That said, with the spacing out, the terminal _feels_ much better with long output streams. @hharnisc you might be interested in this ^

Seems like they're not implemented in hterm:

/**
 * Transmit On (XON).
 *
 * Not currently implemented.
 *
 * TODO(rginda): Implement?
 */
hterm.VT.CC1['\x11'] = hterm.VT.ignore;

/**
 * Transmit Off (XOFF).
 *
 * Not currently implemented.
 *
 * TODO(rginda): Implement?
 */
hterm.VT.CC1['\x13'] = hterm.VT.ignore;

@Tyriar I took another look at xterm.js the other day, but it'd be a regression for us in two fronts:

  • special characters like the ones that vtop use didn't render correctly for me (maybe you've addressed this)
  • composition / emojis dialog was not working for me.

I tried those two with master and latest stable vs code.

I checked out https://github.com/hharnisc/hyper/commit/de2e3db380da4994ed1b0859ecab41abe2201af0, that's just adding a write queue, meaning the process continues to send craploads of data and you can only SIGINT (ctrl+c) for example once it has been processed up to this point. So an ls -lR ~ could take 5-10 seconds to actually run, but sending a SIGINT to interrupt the process of you're 10 seconds into the, say 50 seconds it takes to run, would do nothing as the process has already finished. The SIGINT would be send to the shell (eg. bash), instead of the ls process in this case.

Right, but we need to do both things right? Or would you take out the debouncing if you added the backoff commands?

It shouldn't be too difficult to add the special characters if hterm supports them, I know hterm's has some additional (non-CJK) character support beyond xterm.js (created https://github.com/sourcelair/xterm.js/issues/467). @rauchg if you get a chance could you file an issue on the composition one? I'm not familiar with that particular IME.

@rauchg yes having a processing queue is definitely one of the improvements you will want.

Little confused by what you're saying @Tyriar

Let's say an ls takes 10 seconds to run and takes 50 seconds for Hyper to display all output. I think what I you said was that if send a SIGINT at 20 seconds then the SIGINT will go to the shell.

But if I send the SIGINT at 5 seconds would that still go to the ls command?

@hharnisc sending it 5 seconds in it would be sent to the pty process at that point, meaning you still have 20 more seconds output to process where the terminal is seemingly unresponsive.

@Tyriar it's honestly pretty difficult, and we haven't gotten it perfect yet. We basically _added_ it to hterm (it was pretty convoluted, you might want to look at our hterm.js extensions if you want to take ideas for xterm.js).

In particular, I'm talking about the emoji dialog on macOS and compositions like japanese characters.

@rauchg are you referring to the emoji IME support in hterm.js?

Yes, command+control+space didn't work for me on xterm. Was it supposed to work?

With regards to the vtop characters, I believe we added those as well :D Lots of patching Β―_(ツ)_/Β―

@rauchg well CJK IMEs work in general, the is a lingering issue with the position though. I would expect emoji ones to work the same but I never added support for that explicitly.

RE vtop: Thanks I'll check it out :smiley:

Sounds like then we're pretty close! Do you do the debouncing within xterm? If we were to migrate, do you recommend we still try to aggregate our redux actions like @hharnisc is doing?

@matheuss can probably look into into emoji dialog for xterm.js ;)

@rauchg yes pty data is processed in an async queue. Keep in mind all these recent changes are going into 2.3 so they're only available in master right now.

xterm.js is improving quickly and most of the critical bugs have been solved or have PRs that will solve them soon. Of course, there are likely things that are still missing, or that were already implemented by the hypers hterm implementation.

@rauchg what do you think would be the best approach to change over to xterm.js? This change will probably make lots of plugins and themes unusable.

I could start to implement xterm.js, but I feel it needs a combined effort to make this change happen.

@Tyriar How would you suggest implementing the pty data using xterm.

What do you mean by implementing the pty data?

Will xterm take care of the async queue when the write is send to the terminal?

Yes it will

You would definitely need to draw a line for compatibility with the current hterm implementation.

Breaking plugins is a big deal: including some of the more popular ones by default may need to be included in the scope. Similarly, hterm's tmux support and performance is much better than xterm.js.

(Create a milestone that details the baseline features?)

@elithrar The current master branch of xterm.js has quite improved in terms of performance (at least when enabling the control flow mechanism that is disabled by default because it breaks oh-my-zsh that interprets the XON / XOFF control sequences as keystokes). For example, commands like seq 1000000 or yes will not freeze xterm when control flow is enabled. What issues do you see with the tmux support in xterm?

@mofux https://github.com/sourcelair/xterm.js/issues/456 -> xterm's handling of tmux splits & selection feels very 'early days' - Hyper doesn't have those issues, but does have some less obvious ones: https://github.com/zeit/hyper/issues/1358 & https://github.com/zeit/hyper/issues/1140

(The selection/splits is breaking, the others are bugs)

@mofux If you have a good way to implement the control flow in xterm. Go to inside #1497

I'm very happy with the state of xterm.js right now. Wanted to give everyone heads-up on this thread that we are currently migrating to it.

@rauchg is there a current PR we can follow for the migration?

Looking forward to it, thank you!

Is there a timeline for this issue?

You can already use it.
Available on canary update channel.

@chabou when on the canary channel how do you flip hyper over to xterm?

@isseiler the canary update channel sets xterm as the default

Update your .hyper.js config file:

image

Close me, I'm done :sparkles:

A long journey finally comes to an end β™₯️ -- but a new journey has just started! Now that we are on xterm.js it's in our hands to improve Hyper and xterm to build the most awesome terminal in the block πŸŽ‰ Big thanks to everybody involved making this happen πŸ’ͺ

@mofux Let's do this!

@mofux So Hyper v2.0 use xterm.js? Also, what _did_ it use before xterm.js? Did Zeit develop the terminal ui before xterm.js?

@DRSDavidSoft before that we used hterm (Chromium embedded terminal), in a iframe, with a lot of monkey patches. Without any power to enhance it. It was backed by DOM. More pluggable but less perfmonant/robust/healthy than xtermjs, backed by a canvas render engine and an amazing community.

@DRSDavidSoft Indeed the UI is developed since the start. We where using hterm but xterm is more promising and useful since we are in contact with actives maintainers and we can reduce bugs or isolate them more easily.

@Tyriar does this mean it should be possible to use within VS Code ?

No @cgatian, we now use the same library as in vs code do render the terminal, VS Code already have a built in terminal πŸ‘

how we can integrate hype with internal vs code terminal.
as I can see in the issues it was not possible because it was not using the xterm.js but now we are on 2.0 so how can we do it?

Hyper and vscode both use xterm.js to render the terminal, but apart from that they are two completely separate applications with different architectural designs. Both cannot be integrated into each other. But the good news is: contributing enhancements and addons to xterm.js will allow both to use them! The xterm.js crew is currently working on a plugin architecture that once landed will make it much easier for vscode and hyper to use addons written for xterm.js.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

laur1s picture laur1s  Β·  3Comments

hxnt picture hxnt  Β·  3Comments

ConstantinChirila picture ConstantinChirila  Β·  3Comments

ghost picture ghost  Β·  3Comments

yvan-sraka picture yvan-sraka  Β·  3Comments