aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2019-06-04 09:14:45 +0200
committerJustin M. Keyes <justinkz@gmail.com>2019-06-04 09:14:45 +0200
commit58f505dc7432cad76269ee447029eb1ad94b5aeb (patch)
tree2f4e2176d828c8caeacef2b3bb5db187564a8bf5
parent16b1e8f9c070ad853c6c63b43591e297bf512662 (diff)
parent4719fdb3a44677cc1127624478f67a5316452aa0 (diff)
downloadrneovim-58f505dc7432cad76269ee447029eb1ad94b5aeb.tar.gz
rneovim-58f505dc7432cad76269ee447029eb1ad94b5aeb.tar.bz2
rneovim-58f505dc7432cad76269ee447029eb1ad94b5aeb.zip
Merge #9829 'startup: remove TUI init special-case'
fixes #7967 fixes #9959 Historically Vim/Nvim does backflips to handle input and show messages before a UI is available. This logical contradiction was already fixed for remote UIs (#9024 c236e80cf3df). Fixing it also for the TUI avoids problems on Windows, simplifies the logic, and avoids races like #9959. - Move ui_builtin_start() to the same position as embedded_mode remote_ui_wait_for_attach(). - If stdin is redirected, save the original `stdin` and replace fd 0 with tty before calling `ui_builtin_start()`.
-rw-r--r--src/nvim/main.c58
-rw-r--r--src/nvim/tui/input.c46
-rw-r--r--test/functional/core/startup_spec.lua6
3 files changed, 41 insertions, 69 deletions
diff --git a/src/nvim/main.c b/src/nvim/main.c
index ed8788af60..8ff873e127 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -316,28 +316,9 @@ int main(int argc, char **argv)
// Set the break level after the terminal is initialized.
debug_break_level = params.use_debug_break_level;
- //
- // Read user-input if any TTY is connected.
// Read ex-commands if invoked with "-es".
- //
- bool reading_tty = !headless_mode
- && !embedded_mode
- && !silent_mode
- && (params.input_isatty || params.output_isatty
- || params.err_isatty);
- bool reading_excmds = !params.input_isatty
- && silent_mode
- && exmode_active == EXMODE_NORMAL;
- if (reading_tty || reading_excmds) {
- // One of the startup commands (arguments, sourced scripts or plugins) may
- // prompt the user, so start reading from a tty now.
- int fd = STDIN_FILENO;
- if (!silent_mode
- && (!params.input_isatty || params.edit_type == EDIT_STDIN)) {
- // Use stderr or stdout since stdin is being used to read commands.
- fd = params.err_isatty ? fileno(stderr) : fileno(stdout);
- }
- input_start(fd);
+ if (!params.input_isatty && silent_mode && exmode_active == EXMODE_NORMAL) {
+ input_start(STDIN_FILENO);
}
// open terminals when opening files that start with term://
@@ -366,16 +347,22 @@ int main(int argc, char **argv)
// startup. This allows an external UI to show messages and prompts from
// --cmd and buffer loading (e.g. swap files)
bool early_ui = false;
- if (embedded_mode && !headless_mode) {
- TIME_MSG("waiting for embedder to make request");
- remote_ui_wait_for_attach();
- TIME_MSG("done waiting for embedder");
+ bool use_remote_ui = (embedded_mode && !headless_mode);
+ bool use_builtin_ui = (!headless_mode && !embedded_mode && !silent_mode);
+ if (use_remote_ui || use_builtin_ui) {
+ TIME_MSG("waiting for UI to make request");
+ if (use_remote_ui) {
+ remote_ui_wait_for_attach();
+ } else {
+ ui_builtin_start();
+ }
+ TIME_MSG("done waiting for UI");
// prepare screen now, so external UIs can display messages
starting = NO_BUFFERS;
screenclear();
early_ui = true;
- TIME_MSG("initialized screen early for embedder");
+ TIME_MSG("initialized screen early for UI");
}
// Execute --cmd arguments.
@@ -469,25 +456,12 @@ int main(int argc, char **argv)
read_stdin();
}
- if (reading_tty && (need_wait_return || msg_didany)) {
- // Because there's no UI yet, error messages would have been printed to
- // stdout. Before starting 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 (!headless_mode && !embedded_mode && !silent_mode) {
- input_stop(); // Stop reading input, let the UI take over.
- ui_builtin_start();
- }
-
setmouse(); // may start using the mouse
if (exmode_active || early_ui) {
- // Don't clear the screen when starting in Ex mode, or when an
- // embedding UI might have displayed messages
- must_redraw = CLEAR;
+ // Don't clear the screen when starting in Ex mode, or when a UI might have
+ // displayed messages.
+ redraw_later(VALID);
} else {
screenclear(); // clear screen
TIME_MSG("clearing screen");
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 6d9023bd79..7a725df0a1 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -48,6 +48,26 @@ void tinput_init(TermInput *input, Loop *loop)
int curflags = termkey_get_canonflags(input->tk);
termkey_set_canonflags(input->tk, curflags | TERMKEY_CANON_DELBS);
+
+ // If stdin is not a pty, switch to stderr. For cases like:
+ // echo q | nvim -es
+ // ls *.md | xargs nvim
+#ifdef WIN32
+ if (!os_isatty(0)) {
+ const HANDLE conin_handle = CreateFile("CONIN$",
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ (LPSECURITY_ATTRIBUTES)NULL,
+ OPEN_EXISTING, 0, (HANDLE)NULL);
+ input->in_fd = _open_osfhandle(conin_handle, _O_RDONLY);
+ assert(input->in_fd != -1);
+ }
+#else
+ if (!os_isatty(0) && os_isatty(2)) {
+ input->in_fd = 2;
+ }
+#endif
+
// setup input handle
rstream_init_fd(loop, &input->read_stream, input->in_fd, 0xfff);
// initialize a timer handle for handling ESC with libtermkey
@@ -435,24 +455,7 @@ static void tinput_read_cb(Stream *stream, RBuffer *buf, size_t count_,
TermInput *input = data;
if (eof) {
- if (input->in_fd == 0 && !os_isatty(0) && os_isatty(2)) {
- // Started reading from stdin which is not a pty but failed. Switch to
- // stderr since it is a pty.
- //
- // This is how we support commands like:
- //
- // echo q | nvim -es
- //
- // and
- //
- // ls *.md | xargs nvim
- input->in_fd = 2;
- stream_close(&input->read_stream, NULL, NULL);
- multiqueue_put(input->loop->fast_events, tinput_restart_reading, 1,
- input);
- } else {
- loop_schedule(&main_loop, event_create(tinput_done_event, 0));
- }
+ loop_schedule(&main_loop, event_create(tinput_done_event, 0));
return;
}
@@ -496,10 +499,3 @@ static void tinput_read_cb(Stream *stream, RBuffer *buf, size_t count_,
// without wrap around, otherwise it could be misinterpreted.
rbuffer_reset(input->read_stream.buffer);
}
-
-static void tinput_restart_reading(void **argv)
-{
- TermInput *input = argv[0];
- rstream_init_fd(input->loop, &input->read_stream, input->in_fd, 0xfff);
- rstream_start(&input->read_stream, tinput_read_cb, input);
-}
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index f77af836a6..45bfa93b56 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -46,7 +46,7 @@ describe('startup', function()
]])
end)
it('in a TTY: has("ttyin")==1 has("ttyout")==1', function()
- local screen = Screen.new(25, 3)
+ local screen = Screen.new(25, 4)
screen:attach()
if iswin() then
command([[set shellcmdflag=/s\ /c shellxquote=\"]])
@@ -58,6 +58,7 @@ describe('startup', function()
..[[, shellescape(v:progpath))]])
screen:expect([[
^ |
+ ~ |
1 1 |
|
]])
@@ -96,7 +97,7 @@ describe('startup', function()
end)
end)
it('input from pipe (implicit) #7679', function()
- local screen = Screen.new(25, 3)
+ local screen = Screen.new(25, 4)
screen:attach()
if iswin() then
command([[set shellcmdflag=/s\ /c shellxquote=\"]])
@@ -109,6 +110,7 @@ describe('startup', function()
..[[, shellescape(v:progpath))]])
screen:expect([[
^foo |
+ ~ |
0 1 |
|
]])