mirror of
https://github.com/neovim/neovim.git
synced 2026-07-21 00:21:38 +00:00
terminal: Refactor to use state_enter
- Create `TerminalState` structure containing data used in terminal mode - Extract `terminal_execute` from `terminal_enter` and use it with `state_enter`.
This commit is contained in:
@@ -63,6 +63,7 @@
|
||||
#include "nvim/map.h"
|
||||
#include "nvim/misc1.h"
|
||||
#include "nvim/move.h"
|
||||
#include "nvim/state.h"
|
||||
#include "nvim/ex_docmd.h"
|
||||
#include "nvim/ex_cmds.h"
|
||||
#include "nvim/window.h"
|
||||
@@ -73,6 +74,16 @@
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/api/private/handle.h"
|
||||
|
||||
typedef struct terminal_state {
|
||||
VimState state;
|
||||
Terminal *term;
|
||||
int save_state; // saved value of State
|
||||
int save_rd; // saved value of RedrawingDisabled
|
||||
bool save_mapped_ctrl_c; // saved value of mapped_ctrl_c;
|
||||
bool close;
|
||||
bool got_bs; // if the last input was <C-\>
|
||||
} TerminalState;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "terminal.c.generated.h"
|
||||
#endif
|
||||
@@ -341,105 +352,106 @@ void terminal_resize(Terminal *term, uint16_t width, uint16_t height)
|
||||
void terminal_enter(void)
|
||||
{
|
||||
buf_T *buf = curbuf;
|
||||
Terminal *term = buf->terminal;
|
||||
assert(term && "should only be called when curbuf has a terminal");
|
||||
TerminalState state, *s = &state;
|
||||
memset(s, 0, sizeof(TerminalState));
|
||||
s->term = buf->terminal;
|
||||
assert(s->term && "should only be called when curbuf has a terminal");
|
||||
|
||||
// Ensure the terminal is properly sized.
|
||||
terminal_resize(term, 0, 0);
|
||||
terminal_resize(s->term, 0, 0);
|
||||
|
||||
checkpcmark();
|
||||
setpcmark();
|
||||
int save_state = State;
|
||||
int save_rd = RedrawingDisabled;
|
||||
s->save_state = State;
|
||||
s->save_rd = RedrawingDisabled;
|
||||
State = TERM_FOCUS;
|
||||
RedrawingDisabled = false;
|
||||
bool save_mapped_ctrl_c = mapped_ctrl_c;
|
||||
s->save_mapped_ctrl_c = mapped_ctrl_c;
|
||||
mapped_ctrl_c = true;
|
||||
// go to the bottom when the terminal is focused
|
||||
adjust_topline(term, buf, false);
|
||||
adjust_topline(s->term, buf, false);
|
||||
// erase the unfocused cursor
|
||||
invalidate_terminal(term, term->cursor.row, term->cursor.row + 1);
|
||||
invalidate_terminal(s->term, s->term->cursor.row, s->term->cursor.row + 1);
|
||||
showmode();
|
||||
ui_busy_start();
|
||||
redraw(false);
|
||||
int c;
|
||||
bool close = false;
|
||||
|
||||
bool got_bs = false; // True if the last input was <C-\>
|
||||
s->state.execute = terminal_execute;
|
||||
state_enter(&s->state);
|
||||
|
||||
while (curbuf->handle == term->buf_handle) {
|
||||
input_enable_events();
|
||||
c = safe_vgetc();
|
||||
input_disable_events();
|
||||
|
||||
switch (c) {
|
||||
case K_LEFTMOUSE:
|
||||
case K_LEFTDRAG:
|
||||
case K_LEFTRELEASE:
|
||||
case K_MIDDLEMOUSE:
|
||||
case K_MIDDLEDRAG:
|
||||
case K_MIDDLERELEASE:
|
||||
case K_RIGHTMOUSE:
|
||||
case K_RIGHTDRAG:
|
||||
case K_RIGHTRELEASE:
|
||||
case K_MOUSEDOWN:
|
||||
case K_MOUSEUP:
|
||||
if (send_mouse_event(term, c)) {
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
|
||||
case K_EVENT:
|
||||
// We cannot let an event free the terminal yet. It is still needed.
|
||||
term->refcount++;
|
||||
queue_process_events(loop.events);
|
||||
term->refcount--;
|
||||
if (term->buf_handle == 0) {
|
||||
close = true;
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
|
||||
case Ctrl_N:
|
||||
if (got_bs) {
|
||||
goto end;
|
||||
}
|
||||
// FALLTHROUGH
|
||||
|
||||
default:
|
||||
if (c == Ctrl_BSL && !got_bs) {
|
||||
got_bs = true;
|
||||
break;
|
||||
}
|
||||
if (term->closed) {
|
||||
close = true;
|
||||
goto end;
|
||||
}
|
||||
|
||||
got_bs = false;
|
||||
terminal_send_key(term, c);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
restart_edit = 0;
|
||||
State = save_state;
|
||||
RedrawingDisabled = save_rd;
|
||||
State = s->save_state;
|
||||
RedrawingDisabled = s->save_rd;
|
||||
// draw the unfocused cursor
|
||||
invalidate_terminal(term, term->cursor.row, term->cursor.row + 1);
|
||||
mapped_ctrl_c = save_mapped_ctrl_c;
|
||||
invalidate_terminal(s->term, s->term->cursor.row, s->term->cursor.row + 1);
|
||||
mapped_ctrl_c = s->save_mapped_ctrl_c;
|
||||
unshowmode(true);
|
||||
redraw(buf != curbuf);
|
||||
redraw(curbuf->handle != s->term->buf_handle);
|
||||
ui_busy_stop();
|
||||
if (close) {
|
||||
bool wipe = term->buf_handle != 0;
|
||||
term->opts.close_cb(term->opts.data);
|
||||
if (s->close) {
|
||||
bool wipe = s->term->buf_handle != 0;
|
||||
s->term->opts.close_cb(s->term->opts.data);
|
||||
if (wipe) {
|
||||
do_cmdline_cmd("bwipeout!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int terminal_execute(VimState *state, int key)
|
||||
{
|
||||
TerminalState *s = (TerminalState *)state;
|
||||
|
||||
switch (key) {
|
||||
case K_LEFTMOUSE:
|
||||
case K_LEFTDRAG:
|
||||
case K_LEFTRELEASE:
|
||||
case K_MIDDLEMOUSE:
|
||||
case K_MIDDLEDRAG:
|
||||
case K_MIDDLERELEASE:
|
||||
case K_RIGHTMOUSE:
|
||||
case K_RIGHTDRAG:
|
||||
case K_RIGHTRELEASE:
|
||||
case K_MOUSEDOWN:
|
||||
case K_MOUSEUP:
|
||||
if (send_mouse_event(s->term, key)) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case K_EVENT:
|
||||
// We cannot let an event free the terminal yet. It is still needed.
|
||||
s->term->refcount++;
|
||||
queue_process_events(loop.events);
|
||||
s->term->refcount--;
|
||||
if (s->term->buf_handle == 0) {
|
||||
s->close = true;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case Ctrl_N:
|
||||
if (s->got_bs) {
|
||||
return 0;
|
||||
}
|
||||
// FALLTHROUGH
|
||||
|
||||
default:
|
||||
if (key == Ctrl_BSL && !s->got_bs) {
|
||||
s->got_bs = true;
|
||||
break;
|
||||
}
|
||||
if (s->term->closed) {
|
||||
s->close = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->got_bs = false;
|
||||
terminal_send_key(s->term, key);
|
||||
}
|
||||
|
||||
return curbuf->handle == s->term->buf_handle;
|
||||
}
|
||||
|
||||
void terminal_destroy(Terminal *term)
|
||||
{
|
||||
buf_T *buf = handle_get_buffer(term->buf_handle);
|
||||
|
||||
Reference in New Issue
Block a user