Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

integrated terminal #372

Open
tcoopman opened this issue Jul 2, 2019 · 5 comments

Comments

Projects
None yet
4 participants
@tcoopman
Copy link

commented Jul 2, 2019

This is a feature request/discussion.

I'm wondering what the opinion is on an integrated terminal in Oni? I'm using neovim at the moment and the : terminal command has replaced almost all my usage of tmux. I browsed for a bit and saw that vim also supports terminal but I'm not sure how well it works.

Are you planning on supporting terminal integration, and if so, how do you plan on integrating this? I'm not sure how the terminal on windows works for example.

@CrossR

This comment has been minimized.

Copy link
Member

commented Jul 2, 2019

To my knowledge, it works almost the same as neovim, though I've found it a little difficult compared to the neovim one (though I've been using that one for years, so any change is noticeable).

On Windows, :terminal will launch cmd, the same as neovim. You can then change that either with a shell variable, to change the default, or just call longer commands: :terminal powershell loads powershell, or :terminal cmd /K F:\ProgramData\Anaconda3\Scripts\activate.bat F:\ProgramData\Anaconda3 to launch Anaconda.

The only real difference in launch is that for whatever reason, :terminal bash doesn't work for me, whereas in neovim it would launch the WSL bash. From a quick google its because gvim is 32bit, whereas WSL is 64 bit? There is a workaround to set a few variables (below) which works for me though.

if has("windows") && ! has('nvim')
    set shell=C:\Windows\Sysnative\wsl.exe
    set shellpipe=|
    set shellredir=>
    set shellcmdflag=
endif
@yunti

This comment has been minimized.

Copy link

commented Jul 3, 2019

Will the vscode api mean we can use the vscode integrated terminal or is that too integreated to vscode?

@bryphe

This comment has been minimized.

Copy link
Member

commented Jul 4, 2019

Thanks for starting this discussion here, @tcoopman ! Had some thoughts on this - it's a good time to share them out and get some feedback.

I'm wondering what the opinion is on an integrated terminal in Oni? I'm using neovim at the moment and the : terminal command has replaced almost all my usage of tmux.

I agree, it's a useful and critical feature to have!

There were three high-level pieces I was thinking about in relation to this:

  • User Experience
  • Technical Implementation
  • VSCode API integration

User Experience

VSCode and Vim/Neovim have different user experiences when it comes to managing terminals.

In Vim/Neovim, the terminal is essentially a buffer in a window split - and can be arranged in relation to other splits. This is part of why it can be a replacement for tmux.

A nice property of this is that you can keep multiple terminals running in parallel on your screen:
image

In VSCode, the terminal is limited to the bottom pane, and although there can be multiple terminals at a time, only one is visible at a time:
image

My preference for the user experience would be to keep the Vim/Neovim model of terminals-in-splits, because I believe this is more flexible and allows the same metaphors for navigating between. But open to ideas.

Technical Implementation

Implementing a terminal emulator is tricky! There are so many termcodes that you need to recognize and handle. Both neovim and Vim use a library called libvterm to handle this heavy lifting (Vim forked + modified it slightly).

Having an abstraction where you can send the raw terminal output to a library like libvterm, and have it tell you what characters should be at what grid location on the screen absolutely makes sense.

VSCode, on the other hand, uses Xterm.js last I checked - a TypeScript terminal helper.

For our implementation, we'd want to use a native library like libvterm for performance - there'd be no benefit to sending this across to a node process and leveraging Xterm.js - it would likely both be more complicated and less-performant.

However, an open question at the moment is how much can we leverage the terminal.c code in vim/libvim. The challenge is that, rendering a terminal surface is coupled to rendering - and Onivim 2 owns the rendering layer. There's a nice description of the flow here: https://github.com/onivim/libvim/blob/7b10e4c7011388e7db1bddffc128f52bb47a21a6/src/terminal.c#L13

The question that remains to be figured out is - what is the right layer to hook in?

At one extreme - we could use as much of Vim's architecture for :terminal as possible, and hook in some callbacks / events to help us with rendering (ie, forwarding the libvterm drawing events). On the other extreme - we could take over the management of the terminal (ie, we'd handle the pty, sending output to libterm, and drawing events) - and then handle pushing the terminal data to Vim - this would give us control over the flow. We could still allow Vim to handle the buffer as a special terminal buffer (so keys, etc worked as expected).

Still some time needed to investigate the best strategy for hooking this feature up. It'd be nice to reuse as much as possible from terminal.c - we'd just have to find the right API to bubble up the drawing. In other words, what hooks would we need in libvim to communicate the terminal redraws from Vim -> Onivim 2? What could the interface look like in libvim.h?

As a tangent - one project I would be interested to see - and would be a great fit for Revery today - would be a stand-alone terminal (like Hyper, but built with Reason/Revery) - could have a fast, cross-platform terminal on this stack IMO. Might help answer some of these questions!

  • VSCode API integration

Lastly, even though my plan would be to use libvterm and not use VSCode's integrated terminal - it still has a protocol via its extension API for extensions to ask things about terminals / create terminals.

This API is documented here:

The API basically lets the extensions listen to events about the terminal (when a terminal is opened, closed, resized, takes input, etc), and also allows the extensions to spawn processes against a terminal. I believe this API would map to our implementation - even if we put the terminals in splits vs VSCode's model of terminals-in-the-bottom-pane.

@tcoopman

This comment has been minimized.

Copy link
Author

commented Jul 5, 2019

It's very nice to see you have thought this through in detail already. I don't have that much feedback at the moment about the technical parts, but here is what I think about this:

My preference for the user experience would be to keep the Vim/Neovim model of terminals-in-splits, because I believe this is more flexible and allows the same metaphors for navigating between. But open to ideas.

I agree 100%. The terminal placement in vscode is very limited. Having them as buffers in whatever place you like is really powerful.

VSCode API integration

Well, seeing that it's a goal to be compatible with VSCode plugins this will be important indeed. Looking at the API it doesn't seem that hard though to support most/all of those things.
Having vim compatibility would also be nice to be able to support things that neoterm does. The integration with vim-test is something that is very powerful as well.

@yunti

This comment has been minimized.

Copy link

commented Jul 5, 2019

A feature of the vscode integrated terminal that is very good is the problems summary (perhaps not strictly part of the terminal but part of that tool window) it would be great to have a similar feature in onivim and something to bear in mind when working out a solution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.