aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/terminal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/terminal.c')
-rw-r--r--src/nvim/terminal.c153
1 files changed, 67 insertions, 86 deletions
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index ffe650f416..d8d529d0f6 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -374,6 +374,7 @@ void terminal_enter(void)
TerminalState state, *s = &state;
memset(s, 0, sizeof(TerminalState));
s->term = buf->terminal;
+ stop_insert_mode = false;
// Ensure the terminal is properly sized. Ideally window size management
// code should always have resized the terminal already, but check here to
@@ -400,9 +401,9 @@ void terminal_enter(void)
showmode();
curwin->w_redr_status = true; // For mode() in statusline. #8323
ui_busy_start();
- redraw(false);
s->state.execute = terminal_execute;
+ s->state.check = terminal_check;
state_enter(&s->state);
restart_edit = 0;
@@ -415,8 +416,10 @@ void terminal_enter(void)
// draw the unfocused cursor
invalidate_terminal(s->term, s->term->cursor.row, s->term->cursor.row + 1);
+ if (curbuf->terminal == s->term && !s->close) {
+ terminal_check_cursor();
+ }
unshowmode(true);
- redraw(curbuf->handle != s->term->buf_handle);
ui_busy_stop();
if (s->close) {
bool wipe = s->term->buf_handle != 0;
@@ -427,6 +430,45 @@ void terminal_enter(void)
}
}
+static void terminal_check_cursor(void)
+{
+ Terminal *term = curbuf->terminal;
+ curwin->w_wrow = term->cursor.row;
+ curwin->w_wcol = term->cursor.col + win_col_off(curwin);
+ curwin->w_cursor.lnum = MIN(curbuf->b_ml.ml_line_count,
+ row_to_linenr(term, term->cursor.row));
+ // Nudge cursor when returning to normal-mode.
+ int off = is_focused(term) ? 0 : (curwin->w_p_rl ? 1 : -1);
+ curwin->w_cursor.col = MAX(0, term->cursor.col + win_col_off(curwin) + off);
+ curwin->w_cursor.coladd = 0;
+ mb_check_adjust_col(curwin);
+}
+
+// Function executed before each iteration of terminal mode.
+// Return:
+// 1 if the iteration should continue normally
+// 0 if the main loop must exit
+static int terminal_check(VimState *state)
+{
+ if (stop_insert_mode) {
+ return 0;
+ }
+
+ terminal_check_cursor();
+
+ if (must_redraw) {
+ update_screen(0);
+ }
+
+ if (need_maketitle) { // Update title in terminal-mode. #7248
+ maketitle();
+ }
+
+ setcursor();
+ ui_flush();
+ return 1;
+}
+
static int terminal_execute(VimState *state, int key)
{
TerminalState *s = (TerminalState *)state;
@@ -878,15 +920,20 @@ static VTermKey convert_key(int key, VTermModifier *statep)
case K_KINS: return VTERM_KEY_KP_0;
case K_K1: FALLTHROUGH;
case K_KEND: return VTERM_KEY_KP_1;
- case K_K2: return VTERM_KEY_KP_2;
+ case K_K2: FALLTHROUGH;
+ case K_KDOWN: return VTERM_KEY_KP_2;
case K_K3: FALLTHROUGH;
case K_KPAGEDOWN: return VTERM_KEY_KP_3;
- case K_K4: return VTERM_KEY_KP_4;
- case K_K5: return VTERM_KEY_KP_5;
- case K_K6: return VTERM_KEY_KP_6;
+ case K_K4: FALLTHROUGH;
+ case K_KLEFT: return VTERM_KEY_KP_4;
+ case K_K5: FALLTHROUGH;
+ case K_KORIGIN: return VTERM_KEY_KP_5;
+ case K_K6: FALLTHROUGH;
+ case K_KRIGHT: return VTERM_KEY_KP_6;
case K_K7: FALLTHROUGH;
case K_KHOME: return VTERM_KEY_KP_7;
- case K_K8: return VTERM_KEY_KP_8;
+ case K_K8: FALLTHROUGH;
+ case K_KUP: return VTERM_KEY_KP_8;
case K_K9: FALLTHROUGH;
case K_KPAGEUP: return VTERM_KEY_KP_9;
case K_KDEL: FALLTHROUGH;
@@ -977,6 +1024,9 @@ static bool send_mouse_event(Terminal *term, int c)
{
int row = mouse_row, col = mouse_col, grid = mouse_grid;
win_T *mouse_win = mouse_find_win(&grid, &row, &col);
+ if (mouse_win == NULL) {
+ goto end;
+ }
if (term->forward_mouse && mouse_win->w_buffer->terminal == term) {
// event in the terminal window and mouse events was enabled by the
@@ -1024,6 +1074,7 @@ static bool send_mouse_event(Terminal *term, int c)
return mouse_win == curwin;
}
+end:
ins_char_typebuf(c);
return true;
}
@@ -1128,11 +1179,7 @@ static void refresh_terminal(Terminal *term)
static void refresh_timer_cb(TimeWatcher *watcher, void *data)
{
refresh_pending = false;
- if (exiting // Cannot redraw (requires event loop) during teardown/exit.
- || (State & CMDPREVIEW)
- // WM_LIST (^D) is not redrawn, unlike the normal wildmenu. So we must
- // skip redraws to keep it visible.
- || wild_menu_showing == WM_LIST) {
+ if (exiting) { // Cannot redraw (requires event loop) during teardown/exit.
return;
}
Terminal *term;
@@ -1142,12 +1189,8 @@ static void refresh_timer_cb(TimeWatcher *watcher, void *data)
map_foreach(invalidated_terminals, term, stub, {
refresh_terminal(term);
});
- bool any_visible = is_term_visible();
pmap_clear(ptr_t)(invalidated_terminals);
unblock_autocmds();
- if (any_visible) {
- redraw(true);
- }
}
static void refresh_size(Terminal *term, buf_T *buf)
@@ -1261,61 +1304,6 @@ static void refresh_screen(Terminal *term, buf_T *buf)
term->invalid_end = -1;
}
-/// @return true if any invalidated terminal buffer is visible to the user
-static bool is_term_visible(void)
-{
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_buffer->terminal
- && pmap_has(ptr_t)(invalidated_terminals, wp->w_buffer->terminal)) {
- return true;
- }
- }
- return false;
-}
-
-static void redraw(bool restore_cursor)
-{
- Terminal *term = curbuf->terminal;
- if (!term) {
- restore_cursor = true;
- }
-
- int save_row = 0;
- int save_col = 0;
- if (restore_cursor) {
- // save the current row/col to restore after updating screen when not
- // focused
- save_row = ui_current_row();
- save_col = ui_current_col();
- }
- block_autocmds();
-
- if (must_redraw) {
- update_screen(0);
- }
-
- if (need_maketitle) { // Update title in terminal-mode. #7248
- maketitle();
- }
-
- if (restore_cursor) {
- ui_cursor_goto(save_row, save_col);
- } else if (term) {
- curwin->w_wrow = term->cursor.row;
- curwin->w_wcol = term->cursor.col + win_col_off(curwin);
- curwin->w_cursor.lnum = MIN(curbuf->b_ml.ml_line_count,
- row_to_linenr(term, term->cursor.row));
- // Nudge cursor when returning to normal-mode.
- int off = is_focused(term) ? 0 : (curwin->w_p_rl ? 1 : -1);
- curwin->w_cursor.col = MAX(0, term->cursor.col + win_col_off(curwin) + off);
- curwin->w_cursor.coladd = 0;
- mb_check_adjust_col(curwin);
- }
-
- unblock_autocmds();
- ui_flush();
-}
-
static void adjust_topline(Terminal *term, buf_T *buf, long added)
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
@@ -1351,23 +1339,16 @@ static bool is_focused(Terminal *term)
return State & TERM_FOCUS && curbuf->terminal == term;
}
-#define GET_CONFIG_VALUE(k, o) \
- do { \
- Error err = ERROR_INIT; \
- /* Only called from terminal_open where curbuf->terminal is the */ \
- /* context */ \
- o = dict_get_value(curbuf->b_vars, cstr_as_string(k), &err); \
- api_clear_error(&err); \
- if (o.type == kObjectTypeNil) { \
- o = dict_get_value(&globvardict, cstr_as_string(k), &err); \
- api_clear_error(&err); \
- } \
- } while (0)
-
static char *get_config_string(char *key)
{
- Object obj;
- GET_CONFIG_VALUE(key, obj);
+ Error err = ERROR_INIT;
+ // Only called from terminal_open where curbuf->terminal is the context.
+ Object obj = dict_get_value(curbuf->b_vars, cstr_as_string(key), &err);
+ api_clear_error(&err);
+ if (obj.type == kObjectTypeNil) {
+ obj = dict_get_value(&globvardict, cstr_as_string(key), &err);
+ api_clear_error(&err);
+ }
if (obj.type == kObjectTypeString) {
return obj.data.string.data;
}