[RDY] Builtin terminal emulation#2076
Conversation
|
Wondering how it deals with https://bugs.launchpad.net/libvterm/+bug/1412093. Also what is the $TERM value (see https://bugs.launchpad.net/libvterm/+bug/1412091 for why this is relevant)? |
|
@ZyX-I I've directed the URL to a fork that fixes these messages: https://github.com/neovim/libvterm/commits/cflags-override( @leonerd will probably merge them once he gets back from holidays) As for https://bugs.launchpad.net/libvterm/+bug/1412091 , libvterm aims have xterm compliance but its not there yet. |
|
Very nice! Is it possible to somehow paste/send stdin data to the vte ? (perhaps |
|
Shouldn't the "real" terminal cursor follow the vte cursor when in "insert" mode ? Otherwise it looks weird when e.g. using input methods |
|
@bfredl I plan to fully integrate this with vimscript job control API(it will be possible to control debuggers, paste data, etc) Im still not sure about the cursor behavior(perhaps it should simply become invisible when in normal mode?) |
|
Invisible cursor looks like neovim doing something. Always invisible cursor looks like neovim hang forever. |
|
@ZyX-I I meant that the vterm cursor should be invisible when in normal mode and also the other way around, so there will only be one visible cursor at a time |
|
@tarruda yes, and when in vterm mode the vterm cursor should be forwarded as ui cursor events. This is required to make the preview buffer of input methods to show up at the right place (that is, at the cursor) |
@tarruda Is this in reference to #1802? I'm not attached to that PR, but the purpose of that PR is to give plugins (and core) the option to emit non-blocking messages, not to eliminate them entirely. The next (future) step I was envisioning was for We could offer an option to eliminate all "Press ENTER" messages, but I'm not sure this would actually be a good thing for users to do. The "pager" that Vim emulates for messages is quite handy for messages that the user wants to briefly check, and the fact that it can be dismissed by pressing any normal-mode key (which is then executed) is a feature that would be missed. So, #1802 has a small imperfection that I still need to fix, but perhaps we should discuss whether it is worth continuing. I would really like to wrap it up this weekend one way or other. |
|
Btw, the obligatory nvim-within-nvim test already works (probably not practically useful, but reckon it is a good "stress test" ) 👍 |
|
@bfredl Really cool :) Going to try this PR now |
I agree @justinmk. I don't think it's wise to remove them all, they do serve a purpose and sometimes you really do want to call attention to the user. |
|
This is awesome :) |
|
Awesome! I really don't know how I would use this feature but it's impressive how well it works. Some things I noticed:
|
|
This is SUPER AWESOME :) |
|
👍 awesome feature from Neovim. |
|
Just one thing, when I type Fucking awesome feature. |
|
@rainerborene on my system I don't see either of the bugs you describe with |
Whats the value of your |
There was a problem hiding this comment.
We need a free(line); here. ml_append seems to copy line.
|
@justinmk / @jszakmeister The states where user feedback is required can be easily emulated with the new terminal module. For example, here's how I plan to enhance bang commands with this new feature while still maintaining vimscript compatibility:
Note that the keypress sequence is still the same, the differences are:
A similar concept can be applied to message output:
The advantage of using this approach may not be obvious but here are some:
|
👍 |
With time, the numerous use cases for this feature will be clear, but here's one idea: This allows another level of integration between text mode programs and Neovim. For example, we'll be able to make gdb respond to nvim mappings and change file/line numbers when a breakpoint is hit(Technically this might be possible with tmux but not without numerous hacks)
👍 needs to be fixed
Not sure what you mean, but when you leave terminal focus(Ctrl+w, esc) you can move around the scrollback just like any other buffer)
Thats expected, the terminal buffer cannot receive direct modifications from the user: The key presses are forwarded to the underlying program which outputs redraw instructions. This is how any terminal behaves(you cannot delete lines from tmux panes for example)
👍 Its just a redraw glitch, should be easy to fix. |
I know, this was one of the first things I tried with 5 levels of nesting 😄 |
|
On Wed, Mar 25, 2015 at 10:14 AM, Ian Ker-Seymer
I assume that nvim will but the GUI-versions of it won't. Either case, The advantage of not having a terminal emulator in nvim would be
Which functionality of a REPL would not be available in a stand-alone @jochen Goertler |
|
@Shugyousha If you want to see how more sophisticated REPL integration could be like, take a look at the idris mode for emacs. @tarruda also wrote a nice little script to integrate |
|
First I thought that a terminal emulator would be more elegant if implemented as a plugin(possibly working better than Conque because of Neovim async capabilities), but it would never be as good or efficient as a native implementation due to the way buffers/windows currently work in Neovim. Implementing it in the core also gives more flexibility and power to plugins, because a terminal emulator is by itself a very nice extension point for a editor(as you will see below)
This is only an advantage for developers, not for users. In any case, I did my best to ensure the code is documented and simple. Most of the line count introduced by this PR is for functional tests. This is the function that vim uses for calling the shell in unix systems, its has as many lines as the terminal module introduced by this PR. Would you say vim code for calling external programs is less complex because they don't implement a terminal emulator? FWIW, somewhere in that function there's code to spawn a pty and emulate a (very poor) terminal in gvim(Even though that is a bit contradictory with the information in
Less dependencies is nice, but its infinitely worse implementing the code yourself.
That would be an advantage for embedded systems, but Neovim is supposed to run in a developer workstation, which is where its extra features makes a difference.
With a standard terminal emulator its much harder to have automatic two-way integration with the editor. This script integrates neovim with gdb and it has the following features:
The script is very basic and I plan to extract most of the logic into a common debugging interface, one that will make integrate debuggers into Neovim as simple as writing regular expressions to match debugger states. The same concept can be used to provide automatic integration with REPLs(send lines, automatically evaluate expressions, etc) |
|
On Wed, Mar 25, 2015 at 03:50:00AM -0700, Thiago de Arruda wrote:
I would argue that keeping the code lines /complexity low is an
Hehe, it's true that this code is very ugly but, to be fair, a lot of As far as I can tell this function is around 1100 lines of code while
Sure, but that's not what I am suggesting. I think this functionality
Not if you don't use them... then the added lines of code and
I am not sure why you would need an integrated terminal emulator for In any case, this feature seems to be wanted by a lot of people so I will |
Yes, simply ignore the |
|
I would definitely agree that it should be optional at compile time (because it introduces a dependency, and seems well isolated), but I'm not sure that's viable if is_call_shell() is eventually reworked to use libvterm. And as @tarruda said, it can just be ignored anyways. |
|
I'm 100% for this feature being compiled into neovim while having a (completely feasible) compile-time option to skip it entirely for those who aren't. Neovim plugins would need to check for the feature: I absolutely love this feature. I feel more productive with the convenience of all the functionality i have outside of TERMINAL mode (yanking, pasting, commands, searching, etc, etc, etc) without emulation like would be needed in tmux. I've left tmux and haven't even thought of looking back. And soon I'll be able to do this in a kickass GUI neovim? Fck yeah. Plus all the possibilities Thiago just mentioned which are now much easier to implement direvtly with neovim's architecture, not relying on (multiple) ugly hacks to get these things working with (multiple) other emulators outside of neovim? Fck yeaaaaaaah. Another fck yeah example: with syntax highlighting, things like can very easily become //trusktr@starlancer//path/to/cwd❯ cat helloWorld.js
if (true) {
console.log('hello world!')
}using just the current features of neovim plus the new terminal mode (imagine the command line also colored). |
Command-line can easily be colored using the other means: check out zsh-syntax-highlighting or zsh-pygments-highlighting (first is slow and in many cases incorrect, second is fast, but is a technical preview, requires zsh syntax support in pygments (currently only highlights bash-compatible input) and zpython module installed). I know you theoretically can highlight the output of |
|
@tarruda do you plan on documenting this soonish? I assume you have a lot to do already, but I can't think of a better person to document this than the person who wrote it. If I can help in any way just ask. |
Definitely. I didnt do it yet because I will create another PR after this one that will contain changes to the job API, so I'd rather document everything in one step. |
👍 Thanks for clarifying. |
This is required to avoid event loop recursion due to indirect calls to os_breakcheck by screenalloc
This ifndef causes problems when including fileio headers.
Most internal functions to modify buffers operate on the current buffer and require temporary switchs. This macro is a temporary workaround until a cleaner refactoring of the internal API is performed.
This commit integrates libvterm with Neovim and implements a terminal emulator
with nvim buffers as the display mechanism. Terminal buffers can be created
using any of the following methods:
- Opening a file with name following the "term://[${cwd}//[${pid}:]]${cmd}"
URI pattern where:
- cwd is the working directory of the process
- pid is the process id. This is just for use in session files where a pid
would have been assigned to the saved buffer title.
- cmd is the command to run
- Invoking the `:terminal` ex command
- Invoking the `termopen` function which returns a job id for automating the
terminal window.
Some extra changes were also implemented to adapt with terminal buffers. Here's
an overview:
- The `main` function now sets a BufReadCmd autocmd to intercept the term:// URI
and spawn the terminal buffer instead of reading the file.
- terminal buffers behave as if the following local buffer options were set:
- `nomodifiable`
- `swapfile`
- `undolevels=-1`
- `bufhidden=hide`
- All commands that delete buffers(`:bun`, `:bd` and `:bw`) behave the same for
terminal buffers, but only work when bang is passed(eg: `:bwipeout!`)
- A new "terminal" mode was added. A consequence is that a new set of mapping
commands were implemented with the "t" prefix(tmap, tunmap, tnoremap...)
- The `edit` function(which enters insert mode) will actually enter terminal
mode if the current buffer is a terminal
- The `put` operator was adapted to send data to the terminal instead of
modifying the buffer directly.
- A window being resized will also trigger a terminal resize if the window
displays the terminal.
- Free memory allocated for job data when the job table is full.
Since all reads are queued by the event loop, we must also queue the exit event, or else the process_close function can close the job streams before received data is processed.
- Modify tty-test to allow easier control over the terminal - Add a new directory with various terminal tests/specifications - Remove a pending job/pty test. - Flush stdout in Screen:snapshot_util() (avoid waiting for the test to finish) - Replace libuv sigwinch watcher by a sigaction handler. libuv randomly fails to deliver signals on OSX. Might be related to the problem fixed by @bbcddc55ee1e5605657592644be0102ed3a5f104 (under the hoods, libuv uses a pipe to deliver signals to the main thread, which might be blocking in some situations)
I wouldn't want to use all those other means because those means are already part of Neovim, and we can use them on the terminal buffer. It's so convenient. |
This PR uses libvterm(big thanks to @leonerd for that project) to implement a full VT220 terminal emulator using Neovim buffers and windows. ~~It will also refactor the calling of shell commands to use this facility, fixing #1044 #1386 #1496 #1716 (all caused by an issue introduced in #1365)~~~(I've decided to not touch the generic
os_call_shellfor now)Still a WIP but the
:terminalex command can already be used, here's a quick rundown::term [prog/args]will open a new special buffer "connected" to a pseudo terminal running prog/args<c-\><c-n>combination will return to normal mode.tnoremap <c-a> <c-\><c-n>exit terminal focus using ctrl+a)@justinmk An observation about the new
Terminalclass: It is not coupled to job control so we can use it for implementing #901 and eventually remove all blocking messages(press enter to continue) from nvim(We could have a Terminal instance created at startup and feed all messages to it, for example)