From cdedd89d228a016a4e433968702e9e3ce5165e7d Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Sun, 8 Mar 2015 08:58:31 -0300 Subject: terminal: New module that implements a terminal emulator 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. --- src/nvim/window.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 7b5848c124..9f07f2bddc 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -52,6 +52,7 @@ #include "nvim/search.h" #include "nvim/strings.h" #include "nvim/syntax.h" +#include "nvim/terminal.h" #include "nvim/undo.h" #include "nvim/os/os.h" @@ -1765,6 +1766,12 @@ static int close_last_window_tabpage(win_T *win, int free_buf, tabpage_T *prev_c } buf_T *old_curbuf = curbuf; + Terminal *term = win->w_buffer->terminal; + if (term) { + // Don't free terminal buffers + free_buf = false; + } + /* * Closing the last window in a tab page. First go to another tab * page and then close the window and the tab page. This avoids that @@ -1789,6 +1796,13 @@ static int close_last_window_tabpage(win_T *win, int free_buf, tabpage_T *prev_c if (h != tabline_height()) shell_new_rows(); } + + if (term) { + // When a window containing a terminal buffer is closed, recalculate its + // size + terminal_resize(term, 0, 0); + } + /* Since goto_tabpage_tp above did not trigger *Enter autocommands, do * that now. */ apply_autocmds(EVENT_TABCLOSED, prev_idx, prev_idx, FALSE, curbuf); @@ -1907,6 +1921,8 @@ int win_close(win_T *win, int free_buf) || close_last_window_tabpage(win, free_buf, prev_curtab)) return FAIL; + // let terminal buffers know that this window dimensions may be ignored + win->w_closing = true; /* Free the memory used for the window and get the window that received * the screen space. */ wp = win_free_mem(win, &dir, NULL); @@ -1963,7 +1979,6 @@ int win_close(win_T *win, int free_buf) if (help_window) restore_snapshot(SNAP_HELP_IDX, close_curwin); - redraw_all_later(NOT_VALID); return OK; } @@ -4689,6 +4704,11 @@ void win_new_height(win_T *wp, int height) redraw_win_later(wp, SOME_VALID); wp->w_redr_status = TRUE; invalidate_botline_win(wp); + + if (wp->w_buffer->terminal) { + terminal_resize(wp->w_buffer->terminal, 0, wp->w_height); + redraw_win_later(wp, CLEAR); + } } /* @@ -4706,6 +4726,11 @@ void win_new_width(win_T *wp, int width) } redraw_win_later(wp, NOT_VALID); wp->w_redr_status = TRUE; + + if (wp->w_buffer->terminal) { + terminal_resize(wp->w_buffer->terminal, wp->w_width, 0); + redraw_win_later(wp, CLEAR); + } } void win_comp_scroll(win_T *wp) @@ -5570,4 +5595,3 @@ static int frame_check_width(frame_T *topfrp, int width) return TRUE; } - -- cgit