aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/ex_getln.c2
-rw-r--r--src/nvim/getchar.c5
-rw-r--r--src/nvim/main.c54
-rw-r--r--src/nvim/misc1.c1
-rw-r--r--src/nvim/os/event.h9
-rw-r--r--src/nvim/os/input.c6
-rw-r--r--src/nvim/os/shell.c1
-rw-r--r--src/nvim/tui/tui.c40
-rw-r--r--src/nvim/ui.c5
-rw-r--r--test/functional/ui/screen.lua2
10 files changed, 63 insertions, 62 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/main.c b/src/nvim/main.c
index 9479d80f31..2f1e6e6d3b 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -268,16 +268,26 @@ int main(int argc, char **argv)
/* Set the break level after the terminal is initialized. */
debug_break_level = params.use_debug_break_level;
+ bool reading_input = !params.headless && (params.input_isatty
+ || params.output_isatty || params.err_isatty);
+
+ if (reading_input) {
+ // Its possible that one of the startup commands(arguments, sourced scripts
+ // or plugins) will prompt the user, so start reading from a tty stream
+ // now.
+ int fd = fileno(stdin);
+ if (!params.input_isatty || params.edit_type == EDIT_STDIN) {
+ // use stderr or stdout since stdin is not a tty and/or could be used to
+ // read the file we'll edit when the "-" argument is given(eg: cat file |
+ // nvim -)
+ fd = params.err_isatty ? fileno(stderr) : fileno(stdout);
+ }
+ input_start_stdin(fd);
+ }
+
/* Execute --cmd arguments. */
exe_pre_commands(&params);
- if (!params.headless && params.input_isatty) {
- // Its possible that one of the scripts sourced at startup will prompt the
- // user, so start stdin now. TODO(tarruda): This is only for compatibility.
- // Startup user prompting should be done in the VimEnter autocmd
- input_start_stdin();
- }
-
/* Source startup scripts. */
source_startup_scripts(&params);
@@ -358,22 +368,19 @@ int main(int argc, char **argv)
if (params.edit_type == EDIT_STDIN && !recoverymode)
read_stdin();
- if (!params.headless) {
- if ((params.output_isatty || params.err_isatty)
- && (need_wait_return || msg_didany)) {
- // Since at this point there's no UI instance running yet, error messages
- // would have been printed to stdout. Before starting (which can result in
- // a alternate screen buffer being shown) we need confirmation that the
- // user has seen the messages and that is done with a call to wait_return.
- TIME_MSG("waiting for return");
- wait_return(TRUE);
- }
- if (params.input_isatty) {
- // Stop reading from stdin, the UI module will take over now.
- input_stop_stdin();
- }
+ if (reading_input && (need_wait_return || msg_didany)) {
+ // Since at this point there's no UI instance running yet, error messages
+ // would have been printed to stdout. Before starting (which can result in
+ // a alternate screen buffer being shown) we need confirmation that the
+ // user has seen the messages and that is done with a call to wait_return.
+ TIME_MSG("waiting for return");
+ wait_return(TRUE);
+ }
+ if (!params.headless) {
+ // Stop reading from stdin, the UI layer will take over now
+ input_stop_stdin();
ui_builtin_start();
}
@@ -1465,11 +1472,6 @@ static void check_tty(mparm_T *parmp)
TIME_MSG("Warning delay");
}
-
- if (parmp->edit_type != EDIT_STDIN && !parmp->input_isatty) {
- // read commands from directly from stdin
- input_start_stdin();
- }
}
/*
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/input.c b/src/nvim/os/input.c
index 00efa28161..a409a9ed13 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -46,7 +46,7 @@ void input_init(void)
input_buffer = rbuffer_new(INPUT_BUFFER_SIZE + MAX_KEY_CODE_LEN);
}
-void input_start_stdin(void)
+void input_start_stdin(int fd)
{
if (read_stream) {
return;
@@ -54,7 +54,7 @@ void input_start_stdin(void)
read_buffer = rbuffer_new(READ_BUFFER_SIZE);
read_stream = rstream_new(read_cb, read_buffer, NULL);
- rstream_set_file(read_stream, fileno(stdin));
+ rstream_set_file(read_stream, fd);
rstream_start(read_stream);
}
@@ -69,7 +69,7 @@ void input_stop_stdin(void)
read_stream = NULL;
}
-// Low level input function.
+// Low level input function
int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt)
{
if (rbuffer_pending(input_buffer)) {
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