mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge PR #2025 'More fixes to the new TUI'
This commit is contained in:
commit
2f04fd4e72
@ -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'* *'notimeout'* *'noto'*
|
||||||
'timeout' 'to' boolean (default on)
|
'timeout' 'to' boolean (default on)
|
||||||
global
|
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'* *'nottimeout'*
|
||||||
'ttimeout' boolean (default off)
|
'ttimeout' boolean (default off)
|
||||||
global
|
global
|
||||||
{not in Vi}
|
{not in Vi}
|
||||||
These two options together determine the behavior when part of a
|
This option and 'ttimeoutlen' determine the behavior when part of a
|
||||||
mapped key sequence or keyboard code has been received:
|
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
|
||||||
'timeout' 'ttimeout' action ~
|
'ttimeoutlen' milliseconds for the terminal to complete a byte
|
||||||
off off do not time out
|
sequence that represents a key that starts with \x1b.
|
||||||
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.
|
|
||||||
|
|
||||||
*'timeoutlen'* *'tm'*
|
*'timeoutlen'* *'tm'*
|
||||||
'timeoutlen' 'tm' number (default 1000)
|
'timeoutlen' 'tm' number (default 1000)
|
||||||
global
|
global
|
||||||
|
The time in milliseconds that is waited for a mapped sequence to
|
||||||
|
complete.
|
||||||
{not in all versions of Vi}
|
{not in all versions of Vi}
|
||||||
|
|
||||||
*'ttimeoutlen'* *'ttm'*
|
*'ttimeoutlen'* *'ttm'*
|
||||||
'ttimeoutlen' 'ttm' number (default -1)
|
'ttimeoutlen' 'ttm' number (default -1)
|
||||||
global
|
global
|
||||||
{not in Vi}
|
{not in Vi}
|
||||||
The time in milliseconds that is waited for a key code or mapped key
|
The time in milliseconds that is waited for a key code
|
||||||
sequence to complete. Also used for CTRL-\ CTRL-N and CTRL-\ CTRL-G
|
sequence to complete. Also used for CTRL-\ CTRL-N and CTRL-\ CTRL-G
|
||||||
when part of a command has been typed.
|
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'* *'notitle'*
|
||||||
'title' boolean (default off, on when title can be restored)
|
'title' boolean (default off, on when title can be restored)
|
||||||
|
@ -10,8 +10,9 @@
|
|||||||
|
|
||||||
struct term_input {
|
struct term_input {
|
||||||
int in_fd;
|
int in_fd;
|
||||||
|
bool paste_enabled;
|
||||||
TermKey *tk;
|
TermKey *tk;
|
||||||
uv_tty_t input_handle;
|
uv_pipe_t input_handle;
|
||||||
uv_timer_t timer_handle;
|
uv_timer_t timer_handle;
|
||||||
RBuffer *read_buffer;
|
RBuffer *read_buffer;
|
||||||
RStream *read_stream;
|
RStream *read_stream;
|
||||||
@ -111,17 +112,11 @@ static void timer_cb(uv_timer_t *handle);
|
|||||||
|
|
||||||
static int get_key_code_timeout(void)
|
static int get_key_code_timeout(void)
|
||||||
{
|
{
|
||||||
Integer ms = 0;
|
Integer ms = -1;
|
||||||
bool timeout = false;
|
// Check 'ttimeout' to determine if we should send ESC after 'ttimeoutlen'.
|
||||||
// Check 'timeout' and 'ttimeout' to determine if we should send ESC
|
// See :help 'ttimeout' for more information
|
||||||
// after 'ttimeoutlen'. See :help 'ttimeout' for more information
|
|
||||||
Error err = ERROR_INIT;
|
Error err = ERROR_INIT;
|
||||||
timeout = vim_get_option(cstr_as_string("timeout"), &err).data.boolean;
|
if (vim_get_option(cstr_as_string("ttimeout"), &err).data.boolean) {
|
||||||
if (!timeout) {
|
|
||||||
timeout = vim_get_option(cstr_as_string("ttimeout"), &err).data.boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
ms = vim_get_option(cstr_as_string("ttimeoutlen"), &err).data.integer;
|
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';
|
bool enable = ptr[4] == '0';
|
||||||
// Advance past the sequence
|
// Advance past the sequence
|
||||||
rbuffer_consumed(input->read_buffer, 6);
|
rbuffer_consumed(input->read_buffer, 6);
|
||||||
|
if (input->paste_enabled == enable) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (enable) {
|
if (enable) {
|
||||||
// Get the current mode
|
// Get the current mode
|
||||||
int state = get_real_state();
|
int state = get_real_state();
|
||||||
@ -190,6 +188,7 @@ static bool handle_bracketed_paste(TermInput *input)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
input_enqueue(cstr_as_string(PASTETOGGLE_KEY));
|
input_enqueue(cstr_as_string(PASTETOGGLE_KEY));
|
||||||
|
input->paste_enabled = enable;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -240,6 +239,7 @@ static void read_cb(RStream *rstream, void *rstream_data, bool eof)
|
|||||||
static TermInput *term_input_new(void)
|
static TermInput *term_input_new(void)
|
||||||
{
|
{
|
||||||
TermInput *rv = xmalloc(sizeof(TermInput));
|
TermInput *rv = xmalloc(sizeof(TermInput));
|
||||||
|
rv->paste_enabled = false;
|
||||||
// read input from stderr if stdin is not a tty
|
// read input from stderr if stdin is not a tty
|
||||||
rv->in_fd = os_isatty(0) ? 0 : (os_isatty(2) ? 2 : 0);
|
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);
|
int curflags = termkey_get_canonflags(rv->tk);
|
||||||
termkey_set_canonflags(rv->tk, curflags | TERMKEY_CANON_DELBS);
|
termkey_set_canonflags(rv->tk, curflags | TERMKEY_CANON_DELBS);
|
||||||
// setup input handle
|
// setup input handle
|
||||||
uv_tty_init(uv_default_loop(), &rv->input_handle, rv->in_fd, 1);
|
uv_pipe_init(uv_default_loop(), &rv->input_handle, 0);
|
||||||
uv_tty_set_mode(&rv->input_handle, UV_TTY_MODE_RAW);
|
uv_pipe_open(&rv->input_handle, rv->in_fd);
|
||||||
rv->input_handle.data = NULL;
|
rv->input_handle.data = NULL;
|
||||||
rv->read_buffer = rbuffer_new(0xfff);
|
rv->read_buffer = rbuffer_new(0xfff);
|
||||||
rv->read_stream = rstream_new(read_cb, rv->read_buffer, rv);
|
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)
|
static void term_input_destroy(TermInput *input)
|
||||||
{
|
{
|
||||||
uv_tty_reset_mode();
|
|
||||||
uv_timer_stop(&input->timer_handle);
|
uv_timer_stop(&input->timer_handle);
|
||||||
rstream_stop(input->read_stream);
|
rstream_stop(input->read_stream);
|
||||||
rstream_free(input->read_stream);
|
rstream_free(input->read_stream);
|
||||||
|
@ -49,9 +49,9 @@ typedef struct {
|
|||||||
HlAttrs attrs, print_attrs;
|
HlAttrs attrs, print_attrs;
|
||||||
Cell **screen;
|
Cell **screen;
|
||||||
struct {
|
struct {
|
||||||
size_t enable_mouse, disable_mouse;
|
int enable_mouse, disable_mouse;
|
||||||
size_t enable_bracketed_paste, disable_bracketed_paste;
|
int enable_bracketed_paste, disable_bracketed_paste;
|
||||||
size_t enter_insert_mode, exit_insert_mode;
|
int enter_insert_mode, exit_insert_mode;
|
||||||
} unibi_ext;
|
} unibi_ext;
|
||||||
} TUIData;
|
} TUIData;
|
||||||
|
|
||||||
@ -88,6 +88,12 @@ void tui_start(void)
|
|||||||
data->can_use_terminal_scroll = true;
|
data->can_use_terminal_scroll = true;
|
||||||
data->bufpos = 0;
|
data->bufpos = 0;
|
||||||
data->option_cache = pmap_new(cstr_t)();
|
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
|
// write output to stderr if stdout is not a tty
|
||||||
data->out_fd = os_isatty(1) ? 1 : (os_isatty(2) ? 2 : 1);
|
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));
|
data->write_loop = xmalloc(sizeof(uv_loop_t));
|
||||||
uv_loop_init(data->write_loop);
|
uv_loop_init(data->write_loop);
|
||||||
uv_tty_init(data->write_loop, &data->output_handle, data->out_fd, 0);
|
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
|
// Obtain screen dimensions
|
||||||
update_size(ui);
|
update_size(ui);
|
||||||
@ -169,6 +176,7 @@ static void tui_stop(UI *ui)
|
|||||||
// Disable bracketed paste
|
// Disable bracketed paste
|
||||||
unibi_out(ui, (int)data->unibi_ext.disable_bracketed_paste);
|
unibi_out(ui, (int)data->unibi_ext.disable_bracketed_paste);
|
||||||
flush_buf(ui);
|
flush_buf(ui);
|
||||||
|
uv_tty_reset_mode();
|
||||||
uv_close((uv_handle_t *)&data->output_handle, NULL);
|
uv_close((uv_handle_t *)&data->output_handle, NULL);
|
||||||
uv_run(data->write_loop, UV_RUN_DEFAULT);
|
uv_run(data->write_loop, UV_RUN_DEFAULT);
|
||||||
if (uv_loop_close(data->write_loop)) {
|
if (uv_loop_close(data->write_loop)) {
|
||||||
@ -404,6 +412,11 @@ static void tui_scroll(UI *ui, int count)
|
|||||||
data->params[1].i = bot;
|
data->params[1].i = bot;
|
||||||
unibi_out(ui, unibi_change_scroll_region);
|
unibi_out(ui, unibi_change_scroll_region);
|
||||||
unibi_goto(ui, top, left);
|
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
|
// 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;
|
const char *str = NULL;
|
||||||
|
|
||||||
if (unibi_index < unibi_string_begin_) {
|
if (unibi_index >= 0) {
|
||||||
str = unibi_get_ext_str(data->ut, (unsigned)unibi_index);
|
if (unibi_index < unibi_string_begin_) {
|
||||||
} else {
|
str = unibi_get_ext_str(data->ut, (unsigned)unibi_index);
|
||||||
str = unibi_get_str(data->ut, (unsigned)unibi_index);
|
} else {
|
||||||
|
str = unibi_get_str(data->ut, (unsigned)unibi_index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str) {
|
if (str) {
|
||||||
@ -696,9 +711,9 @@ static void fix_terminfo(TUIData *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (STARTS_WITH(term, "xterm") || STARTS_WITH(term, "rxvt") || inside_tmux) {
|
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");
|
"\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");
|
"\x1b[?2004l");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -713,23 +728,23 @@ static void fix_terminfo(TUIData *data)
|
|||||||
if ((term_prog && !strcmp(term_prog, "iTerm.app"))
|
if ((term_prog && !strcmp(term_prog, "iTerm.app"))
|
||||||
|| os_getenv("ITERM_SESSION_ID") != NULL) {
|
|| os_getenv("ITERM_SESSION_ID") != NULL) {
|
||||||
// iterm
|
// 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"));
|
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"));
|
TMUX_WRAP("\x1b]50;CursorShape=0;BlinkingCursorEnabled=0\x07"));
|
||||||
} else {
|
} else {
|
||||||
// xterm-like sequences for blinking bar and solid block
|
// 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"));
|
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"));
|
TMUX_WRAP("\x1b[2 q"));
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
// Fill some empty slots with common terminal strings
|
// 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");
|
"\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");
|
"\x1b[?1002l\x1b[?1006l");
|
||||||
unibi_set_if_empty(ut, unibi_cursor_address, "\x1b[%i%p1%d;%p2%dH");
|
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");
|
unibi_set_if_empty(ut, unibi_exit_attribute_mode, "\x1b[0;10m");
|
||||||
|
Loading…
Reference in New Issue
Block a user