From bd8d43c6fef868ad5ed50a79deb0f7adc1f5e53a Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Wed, 18 Jul 2018 13:31:23 +0200 Subject: startup: wait for embedder before executing startup commands and files Give embeders a chance to set up nvim, by processing a request before startup. This allows an external UI to show messages and prompts from --cmd and buffer loading (e.g. swap files) --- src/nvim/main.c | 24 ++++++++++++++++++++++-- src/nvim/msgpack_rpc/channel.c | 26 ++++++++++++++++++++++++++ src/nvim/syntax.c | 3 +-- 3 files changed, 49 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/main.c b/src/nvim/main.c index 771074f189..b00f7947bd 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -344,6 +344,24 @@ int main(int argc, char **argv) p_lpl = false; } + // give embedders a chance to set up nvim, by processing a request before + // 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) { + TIME_MSG("waiting for embedder to make request"); + rpc_wait_for_request(); + TIME_MSG("done waiting for embedder"); + + if (ui_active()) { + // prepare screen now, so external UIs can display messages + starting = NO_BUFFERS; + screenclear(); + early_ui = true; + TIME_MSG("initialized screen early for embedder"); + } + } + // Execute --cmd arguments. exe_pre_commands(¶ms); @@ -456,8 +474,10 @@ int main(int argc, char **argv) setmouse(); // may start using the mouse - if (exmode_active) { - must_redraw = CLEAR; // Don't clear the screen when starting in Ex mode. + 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; } else { screenclear(); // clear screen TIME_MSG("clearing screen"); diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index bb4aea0986..c37dde341f 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -40,6 +40,8 @@ static PMap(cstr_t) *event_strings = NULL; static msgpack_sbuffer out_buffer; +static bool got_stdio_request = false; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "msgpack_rpc/channel.c.generated.h" #endif @@ -329,6 +331,9 @@ static void handle_request(Channel *channel, msgpack_object *request) send_error(channel, request_id, error.msg); api_clear_error(&error); api_free_array(args); + if (channel->id == CHAN_STDIO) { + got_stdio_request = true; + } return; } @@ -344,6 +349,9 @@ static void handle_request(Channel *channel, msgpack_object *request) if (is_get_mode && !input_blocking()) { // Defer the event to a special queue used by os/input.c. #6247 multiqueue_put(ch_before_blocking_events, on_request_event, 1, evdata); + if (channel->id == CHAN_STDIO) { + got_stdio_request = true; + } } else { // Invoke immediately. on_request_event((void **)&evdata); @@ -378,6 +386,11 @@ static void on_request_event(void **argv) channel_decref(channel); xfree(e); api_clear_error(&error); + bool is_api_info = handler.fn == handle_nvim_get_api_info; + // api info is used to initiate client library, ignore it + if (channel->id == CHAN_STDIO && !is_api_info) { + got_stdio_request = true; + } } static bool channel_write(Channel *channel, WBuffer *buffer) @@ -744,3 +757,16 @@ static void log_msg_close(FILE *f, msgpack_object msg) } #endif +/// Wait until embedder has done a request +void rpc_wait_for_request(void) +{ + Channel *channel = find_rpc_channel(CHAN_STDIO); + if (!channel) { + // this function should only be called in --embed mode, stdio channel + // can be assumed. + abort(); + } + + LOOP_PROCESS_EVENTS_UNTIL(&main_loop, channel->events, -1, got_stdio_request); +} + diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 332c50129e..05f06d64c3 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -6332,7 +6332,6 @@ int load_colors(char_u *name) apply_autocmds(EVENT_COLORSCHEME, name, curbuf->b_fname, FALSE, curbuf); recursive = false; - ui_refresh(); return retval; } @@ -6885,7 +6884,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) // "fg", which have been changed now. highlight_attr_set_all(); - if (!ui_is_external(kUINewgrid)) { + if (!ui_is_external(kUINewgrid) && starting != NO_SCREEN) { // Older UIs assume that we clear the screen after normal group is // changed ui_refresh(); -- cgit