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.
This commit is contained in:
Thiago de Arruda
2015-03-08 08:58:31 -03:00
parent 6f471fa4fc
commit cdedd89d22
25 changed files with 1578 additions and 93 deletions

View File

@@ -131,6 +131,7 @@
#include "nvim/spell.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/terminal.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/version.h"
@@ -2210,7 +2211,7 @@ win_line (
}
/* Check for columns to display for 'colorcolumn'. */
color_cols = wp->w_p_cc_cols;
color_cols = wp->w_buffer->terminal ? NULL : wp->w_p_cc_cols;
if (color_cols != NULL)
draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
@@ -2592,6 +2593,13 @@ win_line (
off += col;
}
// wont highlight after 1024 columns
int term_attrs[1024] = {0};
if (wp->w_buffer->terminal) {
terminal_get_line_attributes(wp->w_buffer->terminal, wp, lnum, term_attrs);
extra_check = true;
}
/*
* Repeat for the whole displayed line.
*/
@@ -3213,6 +3221,8 @@ win_line (
syntax_flags = 0;
else
syntax_flags = get_syntax_info(&syntax_seqnr);
} else if (!attr_pri) {
char_attr = 0;
}
/* Check spelling (unless at the end of the line).
@@ -3290,6 +3300,11 @@ win_line (
else
char_attr = hl_combine_attr(spell_attr, char_attr);
}
if (wp->w_buffer->terminal) {
char_attr = hl_combine_attr(char_attr, term_attrs[vcol]);
}
/*
* Found last space before word: check for line break.
*/
@@ -3787,6 +3802,18 @@ win_line (
}
}
if (wp->w_buffer->terminal) {
// terminal buffers may need to highlight beyond the end of the
// logical line
while (col < wp->w_width) {
ScreenLines[off] = ' ';
if (enc_utf8) {
ScreenLinesUC[off] = 0;
}
ScreenAttrs[off++] = term_attrs[vcol++];
col++;
}
}
SCREEN_LINE(screen_row, wp->w_wincol, col, wp->w_width, wp->w_p_rl);
row++;
@@ -6536,7 +6563,8 @@ int showmode(void)
int sub_attr;
do_mode = ((p_smd && msg_silent == 0)
&& ((State & INSERT)
&& ((State & TERM_FOCUS)
|| (State & INSERT)
|| restart_edit
|| VIsual_active
));
@@ -6591,7 +6619,9 @@ int showmode(void)
}
}
} else {
if (State & VREPLACE_FLAG)
if (State & TERM_FOCUS) {
MSG_PUTS_ATTR(_(" TERMINAL"), attr);
} else if (State & VREPLACE_FLAG)
MSG_PUTS_ATTR(_(" VREPLACE"), attr);
else if (State & REPLACE_FLAG)
MSG_PUTS_ATTR(_(" REPLACE"), attr);