Merge PR #2025 'More fixes to the new TUI'

This commit is contained in:
Thiago de Arruda 2015-02-20 10:16:19 -03:00
commit 2f04fd4e72
3 changed files with 58 additions and 68 deletions

View File

@ -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
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)

View File

@ -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);

View File

@ -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,11 +646,13 @@ static void unibi_out(UI *ui, int unibi_index)
const char *str = NULL;
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) {
data->bufpos += unibi_run(str, data->params, data->buf + data->bufpos,
@ -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");