diff options
-rw-r--r-- | runtime/doc/options.txt | 54 | ||||
-rw-r--r-- | src/nvim/tui/term_input.inl | 27 | ||||
-rw-r--r-- | src/nvim/tui/tui.c | 45 |
3 files changed, 58 insertions, 68 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 790903a847..5d6fedcac4 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -6988,59 +6988,35 @@ A jump table for the options with a short description can be found at |Q_op|. *'timeout'* *'to'* *'notimeout'* *'noto'* 'timeout' 'to' boolean (default on) global + This option and 'timeoutlen' determine the behavior when part of a + mapped key sequence has been received. For example, if <c-f> is + pressed and 'timeout' is set, Nvim will wait 'timeoutlen' milliseconds + for any key that can follow <c-f> in a mapping. + *'ttimeout'* *'nottimeout'* 'ttimeout' boolean (default off) global {not in Vi} - These two options together determine the behavior when part of a - mapped key sequence or keyboard code has been received: - - 'timeout' 'ttimeout' action ~ - off off do not time out - on on or off time out on :mappings and key codes - off on time out on key codes - - If both options are off, Vim will wait until either the complete - mapping or key sequence has been received, or it is clear that there - is no mapping or key sequence for the received characters. For - example: if you have mapped "vl" and Vim has received 'v', the next - character is needed to see if the 'v' is followed by an 'l'. - When one of the options is on, Vim will wait for about 1 second for - the next character to arrive. After that the already received - characters are interpreted as single characters. The waiting time can - be changed with the 'timeoutlen' option. - On slow terminals or very busy systems timing out may cause - malfunctioning cursor keys. If both options are off, Vim waits - forever after an entered <Esc> if there are key codes that start - with <Esc>. You will have to type <Esc> twice. If you do not have - problems with key codes, but would like to have :mapped key - sequences not timing out in 1 second, set the 'ttimeout' option and - reset the 'timeout' option. + This option and 'ttimeoutlen' determine the behavior when part of a + key code sequence has been received by the terminal UI. For example, + if the \x1b byte is received and 'ttimeout' is set, Nvim will wait + 'ttimeoutlen' milliseconds for the terminal to complete a byte + sequence that represents a key that starts with \x1b. *'timeoutlen'* *'tm'* 'timeoutlen' 'tm' number (default 1000) global + The time in milliseconds that is waited for a mapped sequence to + complete. {not in all versions of Vi} + *'ttimeoutlen'* *'ttm'* 'ttimeoutlen' 'ttm' number (default -1) global {not in Vi} - The time in milliseconds that is waited for a key code or mapped key - sequence to complete. Also used for CTRL-\ CTRL-N and CTRL-\ CTRL-G + The time in milliseconds that is waited for a key code + sequence to complete. Also used for CTRL-\ CTRL-N and CTRL-\ CTRL-G when part of a command has been typed. - Normally only 'timeoutlen' is used and 'ttimeoutlen' is -1. When a - different timeout value for key codes is desired set 'ttimeoutlen' to - a non-negative number. - - ttimeoutlen mapping delay key code delay ~ - < 0 'timeoutlen' 'timeoutlen' - >= 0 'timeoutlen' 'ttimeoutlen' - - The timeout only happens when the 'timeout' and 'ttimeout' options - tell so. A useful setting would be > - :set timeout timeoutlen=3000 ttimeoutlen=100 -< (time out on mapping after three seconds, time out on key codes after - a tenth of a second). *'title'* *'notitle'* 'title' boolean (default off, on when title can be restored) diff --git a/src/nvim/tui/term_input.inl b/src/nvim/tui/term_input.inl index dba970e8f2..9a40a64ed9 100644 --- a/src/nvim/tui/term_input.inl +++ b/src/nvim/tui/term_input.inl @@ -10,8 +10,9 @@ struct term_input { int in_fd; + bool paste_enabled; TermKey *tk; - uv_tty_t input_handle; + uv_pipe_t input_handle; uv_timer_t timer_handle; RBuffer *read_buffer; RStream *read_stream; @@ -111,17 +112,11 @@ static void timer_cb(uv_timer_t *handle); static int get_key_code_timeout(void) { - Integer ms = 0; - bool timeout = false; - // Check 'timeout' and 'ttimeout' to determine if we should send ESC - // after 'ttimeoutlen'. See :help 'ttimeout' for more information + Integer ms = -1; + // Check 'ttimeout' to determine if we should send ESC after 'ttimeoutlen'. + // See :help 'ttimeout' for more information Error err = ERROR_INIT; - timeout = vim_get_option(cstr_as_string("timeout"), &err).data.boolean; - if (!timeout) { - timeout = vim_get_option(cstr_as_string("ttimeout"), &err).data.boolean; - } - - if (timeout) { + if (vim_get_option(cstr_as_string("ttimeout"), &err).data.boolean) { ms = vim_get_option(cstr_as_string("ttimeoutlen"), &err).data.integer; } @@ -175,6 +170,9 @@ static bool handle_bracketed_paste(TermInput *input) bool enable = ptr[4] == '0'; // Advance past the sequence rbuffer_consumed(input->read_buffer, 6); + if (input->paste_enabled == enable) { + return true; + } if (enable) { // Get the current mode int state = get_real_state(); @@ -190,6 +188,7 @@ static bool handle_bracketed_paste(TermInput *input) } } input_enqueue(cstr_as_string(PASTETOGGLE_KEY)); + input->paste_enabled = enable; return true; } return false; @@ -240,6 +239,7 @@ static void read_cb(RStream *rstream, void *rstream_data, bool eof) static TermInput *term_input_new(void) { TermInput *rv = xmalloc(sizeof(TermInput)); + rv->paste_enabled = false; // read input from stderr if stdin is not a tty rv->in_fd = os_isatty(0) ? 0 : (os_isatty(2) ? 2 : 0); @@ -259,8 +259,8 @@ static TermInput *term_input_new(void) int curflags = termkey_get_canonflags(rv->tk); termkey_set_canonflags(rv->tk, curflags | TERMKEY_CANON_DELBS); // setup input handle - uv_tty_init(uv_default_loop(), &rv->input_handle, rv->in_fd, 1); - uv_tty_set_mode(&rv->input_handle, UV_TTY_MODE_RAW); + uv_pipe_init(uv_default_loop(), &rv->input_handle, 0); + uv_pipe_open(&rv->input_handle, rv->in_fd); rv->input_handle.data = NULL; rv->read_buffer = rbuffer_new(0xfff); rv->read_stream = rstream_new(read_cb, rv->read_buffer, rv); @@ -279,7 +279,6 @@ static TermInput *term_input_new(void) static void term_input_destroy(TermInput *input) { - uv_tty_reset_mode(); uv_timer_stop(&input->timer_handle); rstream_stop(input->read_stream); rstream_free(input->read_stream); diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 57119b9030..5951408c42 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -49,9 +49,9 @@ typedef struct { HlAttrs attrs, print_attrs; Cell **screen; struct { - size_t enable_mouse, disable_mouse; - size_t enable_bracketed_paste, disable_bracketed_paste; - size_t enter_insert_mode, exit_insert_mode; + int enable_mouse, disable_mouse; + int enable_bracketed_paste, disable_bracketed_paste; + int enter_insert_mode, exit_insert_mode; } unibi_ext; } TUIData; @@ -88,6 +88,12 @@ void tui_start(void) data->can_use_terminal_scroll = true; data->bufpos = 0; data->option_cache = pmap_new(cstr_t)(); + data->unibi_ext.enable_mouse = -1; + data->unibi_ext.disable_mouse = -1; + data->unibi_ext.enable_bracketed_paste = -1; + data->unibi_ext.disable_bracketed_paste = -1; + data->unibi_ext.enter_insert_mode = -1; + data->unibi_ext.exit_insert_mode = -1; // write output to stderr if stdout is not a tty data->out_fd = os_isatty(1) ? 1 : (os_isatty(2) ? 2 : 1); @@ -113,6 +119,7 @@ void tui_start(void) data->write_loop = xmalloc(sizeof(uv_loop_t)); uv_loop_init(data->write_loop); uv_tty_init(data->write_loop, &data->output_handle, data->out_fd, 0); + uv_tty_set_mode(&data->output_handle, UV_TTY_MODE_RAW); // Obtain screen dimensions update_size(ui); @@ -169,6 +176,7 @@ static void tui_stop(UI *ui) // Disable bracketed paste unibi_out(ui, (int)data->unibi_ext.disable_bracketed_paste); flush_buf(ui); + uv_tty_reset_mode(); uv_close((uv_handle_t *)&data->output_handle, NULL); uv_run(data->write_loop, UV_RUN_DEFAULT); if (uv_loop_close(data->write_loop)) { @@ -404,6 +412,11 @@ static void tui_scroll(UI *ui, int count) data->params[1].i = bot; unibi_out(ui, unibi_change_scroll_region); unibi_goto(ui, top, left); + // also set default color attributes or some terminals can become funny + HlAttrs clear_attrs = EMPTY_ATTRS; + clear_attrs.foreground = data->fg; + clear_attrs.background = data->bg; + update_attrs(ui, clear_attrs); } // Compute start/stop/step for the loop below, also use terminal scroll @@ -633,10 +646,12 @@ static void unibi_out(UI *ui, int unibi_index) const char *str = NULL; - if (unibi_index < unibi_string_begin_) { - str = unibi_get_ext_str(data->ut, (unsigned)unibi_index); - } else { - str = unibi_get_str(data->ut, (unsigned)unibi_index); + if (unibi_index >= 0) { + if (unibi_index < unibi_string_begin_) { + str = unibi_get_ext_str(data->ut, (unsigned)unibi_index); + } else { + str = unibi_get_str(data->ut, (unsigned)unibi_index); + } } if (str) { @@ -696,9 +711,9 @@ static void fix_terminfo(TUIData *data) } if (STARTS_WITH(term, "xterm") || STARTS_WITH(term, "rxvt") || inside_tmux) { - data->unibi_ext.enable_bracketed_paste = unibi_add_ext_str(ut, NULL, + data->unibi_ext.enable_bracketed_paste = (int)unibi_add_ext_str(ut, NULL, "\x1b[?2004h"); - data->unibi_ext.disable_bracketed_paste = unibi_add_ext_str(ut, NULL, + data->unibi_ext.disable_bracketed_paste = (int)unibi_add_ext_str(ut, NULL, "\x1b[?2004l"); } @@ -713,23 +728,23 @@ static void fix_terminfo(TUIData *data) if ((term_prog && !strcmp(term_prog, "iTerm.app")) || os_getenv("ITERM_SESSION_ID") != NULL) { // iterm - data->unibi_ext.enter_insert_mode = unibi_add_ext_str(ut, NULL, + data->unibi_ext.enter_insert_mode = (int)unibi_add_ext_str(ut, NULL, TMUX_WRAP("\x1b]50;CursorShape=1;BlinkingCursorEnabled=1\x07")); - data->unibi_ext.exit_insert_mode = unibi_add_ext_str(ut, NULL, + data->unibi_ext.exit_insert_mode = (int)unibi_add_ext_str(ut, NULL, TMUX_WRAP("\x1b]50;CursorShape=0;BlinkingCursorEnabled=0\x07")); } else { // xterm-like sequences for blinking bar and solid block - data->unibi_ext.enter_insert_mode = unibi_add_ext_str(ut, NULL, + data->unibi_ext.enter_insert_mode = (int)unibi_add_ext_str(ut, NULL, TMUX_WRAP("\x1b[5 q")); - data->unibi_ext.exit_insert_mode = unibi_add_ext_str(ut, NULL, + data->unibi_ext.exit_insert_mode = (int)unibi_add_ext_str(ut, NULL, TMUX_WRAP("\x1b[2 q")); } end: // Fill some empty slots with common terminal strings - data->unibi_ext.enable_mouse = unibi_add_ext_str(ut, NULL, + data->unibi_ext.enable_mouse = (int)unibi_add_ext_str(ut, NULL, "\x1b[?1002h\x1b[?1006h"); - data->unibi_ext.disable_mouse = unibi_add_ext_str(ut, NULL, + data->unibi_ext.disable_mouse = (int)unibi_add_ext_str(ut, NULL, "\x1b[?1002l\x1b[?1006l"); unibi_set_if_empty(ut, unibi_cursor_address, "\x1b[%i%p1%d;%p2%dH"); unibi_set_if_empty(ut, unibi_exit_attribute_mode, "\x1b[0;10m"); |