diff options
author | Thiago de Arruda <tpadilha84@gmail.com> | 2015-03-18 12:34:36 -0300 |
---|---|---|
committer | Thiago de Arruda <tpadilha84@gmail.com> | 2015-03-18 14:16:23 -0300 |
commit | 8b7b71f4742d94cf7a2e5a08e7b2f5a725619476 (patch) | |
tree | 05ec646ae8f0bfb6080d160456e4de3038ea9560 | |
parent | a0f2961b4fc2beabf1266faef0f543afdffd45f8 (diff) | |
download | rneovim-8b7b71f4742d94cf7a2e5a08e7b2f5a725619476.tar.gz rneovim-8b7b71f4742d94cf7a2e5a08e7b2f5a725619476.tar.bz2 rneovim-8b7b71f4742d94cf7a2e5a08e7b2f5a725619476.zip |
ui: Refactor so that busy state won't be the default
Even though assuming nvim is busy most times is simpler, it has a problem: A lot
of unnecessary busy_start/busy_stop notifications are sent to the UI. That's
because in the majority of scenarios almost no time is spent between
`event_poll` calls.
This restores the normal behavior which is to call busy_start only when nvim is
going to perform some task that can take a significant amount of time. Also
improve the usage of buffering in the TUI when changing the cursor state.
-rw-r--r-- | src/nvim/ex_getln.c | 2 | ||||
-rw-r--r-- | src/nvim/getchar.c | 5 | ||||
-rw-r--r-- | src/nvim/misc1.c | 1 | ||||
-rw-r--r-- | src/nvim/os/event.h | 9 | ||||
-rw-r--r-- | src/nvim/os/shell.c | 1 | ||||
-rw-r--r-- | src/nvim/tui/tui.c | 40 | ||||
-rw-r--r-- | src/nvim/ui.c | 5 | ||||
-rw-r--r-- | test/functional/ui/screen.lua | 2 |
8 files changed, 32 insertions, 33 deletions
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index c9e990b713..d5f7a218f4 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1364,6 +1364,7 @@ cmdline_changed: if (ccline.cmdlen == 0) i = 0; else { + ui_busy_start(); ui_flush(); ++emsg_off; /* So it doesn't beep if bad expr */ /* Set the time limit to half a second. */ @@ -1381,6 +1382,7 @@ cmdline_changed: } else if (char_avail()) /* cancelled searching because a char was typed */ incsearch_postponed = TRUE; + ui_busy_stop(); } if (i != 0) highlight_match = TRUE; /* highlight position */ diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 41b3d9dda8..96ce586a9e 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -2379,6 +2379,11 @@ inchar ( int retesc = FALSE; /* return ESC with gotint */ int script_char; + if (wait_time == -1L || wait_time > 100L) { + // flush output before waiting + ui_flush(); + } + /* * Don't reset these when at the hit-return prompt, otherwise an endless * recursive loop may result (write error in swapfile, hit-return, timeout diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index 07cbc0f7c4..c9f3fbd511 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -2364,6 +2364,7 @@ int get_keystroke(void) mapped_ctrl_c = FALSE; /* mappings are not used here */ for (;; ) { + // flush output before waiting ui_flush(); /* Leave some room for check_termcode() to insert a key code into (max * 5 chars plus NUL). And fix_input_buffer() can triple the number of diff --git a/src/nvim/os/event.h b/src/nvim/os/event.h index 986db51431..db02b38c7f 100644 --- a/src/nvim/os/event.h +++ b/src/nvim/os/event.h @@ -8,15 +8,9 @@ #include "nvim/os/job_defs.h" #include "nvim/os/time.h" -void ui_busy_start(void); -void ui_busy_stop(void); - // Poll for events until a condition or timeout #define event_poll_until(timeout, condition) \ do { \ - if (timeout < 0 || timeout > 100) { \ - ui_busy_stop(); \ - } \ int remaining = timeout; \ uint64_t before = (remaining > 0) ? os_hrtime() : 0; \ while (!(condition)) { \ @@ -32,9 +26,6 @@ void ui_busy_stop(void); } \ } \ } \ - if (timeout < 0 || timeout > 100) { \ - ui_busy_start(); \ - } \ } while (0) #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index 290d6a9ec9..6fcb62a5f3 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -241,6 +241,7 @@ static int shell(const char *cmd, // invoke busy_start here so event_poll_until wont change the busy state for // the UI ui_busy_start(); + ui_flush(); status = job_wait(job, -1); ui_busy_stop(); diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 4f858456f9..4736e7a8ba 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -16,6 +16,11 @@ #include "nvim/os/event.h" #include "nvim/tui/tui.h" +// Space reserved in the output buffer to restore the cursor to normal when +// flushing. No existing terminal will require 32 bytes to do that. +#define CNORM_COMMAND_MAX_SIZE 32 +#define OUTBUF_SIZE 0xffff + typedef struct term_input TermInput; #include "term_input.inl" @@ -31,8 +36,8 @@ typedef struct { typedef struct { unibi_var_t params[9]; - char buf[0xffff]; - size_t bufpos; + char buf[OUTBUF_SIZE]; + size_t bufpos, bufsize; TermInput *input; uv_loop_t *write_loop; unibi_term *ut; @@ -81,13 +86,13 @@ typedef struct { void tui_start(void) { TUIData *data = xcalloc(1, sizeof(TUIData)); - data->busy = true; UI *ui = xcalloc(1, sizeof(UI)); ui->data = data; data->attrs = data->print_attrs = EMPTY_ATTRS; data->fg = data->bg = -1; data->can_use_terminal_scroll = true; data->bufpos = 0; + data->bufsize = sizeof(data->buf) - CNORM_COMMAND_MAX_SIZE; data->unibi_ext.enable_mouse = -1; data->unibi_ext.disable_mouse = -1; data->unibi_ext.enable_bracketed_paste = -1; @@ -108,7 +113,6 @@ void tui_start(void) data->ut = unibi_dummy(); } fix_terminfo(data); - unibi_out(ui, unibi_cursor_invisible); // Enter alternate screen and clear unibi_out(ui, unibi_enter_ca_mode); unibi_out(ui, unibi_clear_screen); @@ -172,6 +176,7 @@ static void tui_stop(UI *ui) tui_normal_mode(ui); tui_mouse_off(ui); unibi_out(ui, unibi_exit_attribute_mode); + // cursor should be set to normal before exiting alternate screen unibi_out(ui, unibi_cursor_normal); unibi_out(ui, unibi_exit_ca_mode); // Disable bracketed paste @@ -661,7 +666,7 @@ static void out(void *ctx, const char *str, size_t len) { UI *ui = ctx; TUIData *data = ui->data; - size_t available = sizeof(data->buf) - data->bufpos; + size_t available = data->bufsize - data->bufpos; if (len > available) { flush_buf(ui); @@ -786,29 +791,26 @@ end: static void flush_buf(UI *ui) { uv_write_t req; - uv_buf_t buf[2]; - unsigned int buf_count = 1; - + uv_buf_t buf; TUIData *data = ui->data; - buf[0].base = data->buf; - buf[0].len = data->bufpos; - - char normal_buf[64]; if (!data->busy) { - // Cannot use unibi_out(ui, unibi_cursor_normal), in case there is not - // enough remaining space in data->buf. - const char *str = unibi_get_str(data->ut, unibi_cursor_normal); - buf[1].base = normal_buf; - buf[1].len = unibi_run(str, data->params, normal_buf, sizeof(normal_buf)); - buf_count++; + // not busy and the cursor is invisible(see below). Append a "cursor + // normal" command to the end of the buffer. + data->bufsize += CNORM_COMMAND_MAX_SIZE; + unibi_out(ui, unibi_cursor_normal); + data->bufsize -= CNORM_COMMAND_MAX_SIZE; } - uv_write(&req, (uv_stream_t *)&data->output_handle, buf, buf_count, NULL); + buf.base = data->buf; + buf.len = data->bufpos; + uv_write(&req, (uv_stream_t *)&data->output_handle, &buf, 1, NULL); uv_run(data->write_loop, UV_RUN_DEFAULT); data->bufpos = 0; if (!data->busy) { + // not busy and cursor is visible(see above), append a "cursor invisible" + // command to the beginning of the buffer for the next flush unibi_out(ui, unibi_cursor_invisible); } } diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 2189021d22..443b50da87 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -45,7 +45,7 @@ static struct { } sr; static int current_attr_code = 0; static bool pending_cursor_update = false; -static int busy = 1; +static int busy = 0; static int height, width; // This set of macros allow us to use UI_CALL to invoke any function on @@ -155,7 +155,6 @@ void ui_busy_start(void) { if (!(busy++)) { UI_CALL(busy_start); - ui_flush(); } } @@ -163,11 +162,9 @@ void ui_busy_stop(void) { if (!(--busy)) { UI_CALL(busy_stop); - ui_flush(); } } - void ui_mouse_on(void) { UI_CALL(mouse_on); diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 2cebaf048c..f79d634536 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -166,7 +166,7 @@ function Screen.new(width, height) _cursor = { row = 1, col = 1 }, - _busy = true + _busy = false }, Screen) self:_handle_resize(width, height) return self |