aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2018-09-20 19:19:38 +0200
committerBjörn Linse <bjorn.linse@gmail.com>2018-09-22 10:18:28 +0200
commit4da5cb38d396d76d8072815d150725f7c9a85078 (patch)
tree426eb0f7525621d9760bb2cbf394d5c42b691775
parent7f990741f7018b5e52833f2da6913b97c6d2d5ee (diff)
downloadrneovim-4da5cb38d396d76d8072815d150725f7c9a85078.tar.gz
rneovim-4da5cb38d396d76d8072815d150725f7c9a85078.tar.bz2
rneovim-4da5cb38d396d76d8072815d150725f7c9a85078.zip
startup: always wait for UI with --embed, unless --headless also is supplied
-rw-r--r--runtime/doc/starting.txt33
-rw-r--r--src/nvim/api/ui.c15
-rw-r--r--src/nvim/channel.c2
-rw-r--r--src/nvim/main.c21
-rw-r--r--src/nvim/msgpack_rpc/channel.c27
-rw-r--r--test/functional/api/server_requests_spec.lua7
-rw-r--r--test/functional/ex_cmds/oldfiles_spec.lua2
-rw-r--r--test/functional/helpers.lua9
-rw-r--r--test/functional/plugin/helpers.lua4
-rw-r--r--test/functional/shada/helpers.lua5
-rw-r--r--test/functional/shada/marks_spec.lua4
-rw-r--r--test/functional/shada/shada_spec.lua6
-rw-r--r--test/functional/ui/embed_spec.lua16
13 files changed, 70 insertions, 81 deletions
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
index 275b08b5dd..dd9f9ad0f3 100644
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -348,30 +348,35 @@ argument.
*--embed*
--embed Use stdin/stdout as a msgpack-RPC channel, so applications can
- embed and control Nvim via the |rpc-api|. Implies |--headless|.
-
- Nvim will wait for a single request before sourcing startup
- files and reading buffers. This is mainly so that UIs can call
- `nvim_ui_attach` so that the UI can show startup messages
- and possible swap file dialog for the first loaded file. In
- addition, a `nvim_get_api_info` call before the `nvim_ui_attach`
- call is also allowed, so that UI features can be safely
- detected by the UI.
-
- To avoid this behavior, this alterative could be used instead: >
+ embed and control Nvim via the |rpc-api|.
+
+ By default nvim will wait for the embedding process to call
+ `nvim_ui_attach` before sourcing startup files and reading
+ buffers. This is so that UI can show startup messages and
+ possible swap file dialog for the first loaded file. The
+ process can do requests before the `nvim_ui_attach`, for
+ instance a `nvim_get_api_info` call so that UI features can be
+ safely detected by the UI before attaching.
+
+ To embed nvim without using the UI protocol, `--headless` should
+ be supplied together with `--embed`. Then initialization is
+ performed without waiting for an UI. This is also equivalent
+ to the following alternative: >
nvim --headless --cmd "call stdioopen({'rpc': v:true})"
<
See also |channel-stdio|.
*--headless*
---headless Do not start the default UI, so stdio can be used as an
- arbitrary communication channel. |channel-stdio|
+--headless Start nvim without an UI. The TUI is not used, so stdio
+ can be used as an arbitrary communication channel.
+ |channel-stdio| When used together with `--embed`, do not wait
+ for the embedder to attach an UI.
Also useful for scripting (tests) to see messages that would
not be printed by |-es|.
To detect if a UI is available, check if |nvim_list_uis()| is
- empty after |VimEnter|.
+ empty in or after |VimEnter|.
To read stdin as text, "-" must be given explicitly:
--headless cannot assume that stdin is just text. >
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 509032892b..4971753854 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -58,6 +58,21 @@ void remote_ui_disconnect(uint64_t channel_id)
xfree(ui);
}
+/// Wait until ui has connected on stdio channel.
+void remote_ui_wait_for_attach(void)
+ FUNC_API_NOEXPORT
+{
+ Channel *channel = find_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,
+ pmap_has(uint64_t)(connected_uis, CHAN_STDIO));
+}
+
void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
Dictionary options, Error *err)
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
diff --git a/src/nvim/channel.c b/src/nvim/channel.c
index 36423d0aa1..259f1cc600 100644
--- a/src/nvim/channel.c
+++ b/src/nvim/channel.c
@@ -432,7 +432,7 @@ uint64_t channel_from_stdio(bool rpc, CallbackReader on_output,
const char **error)
FUNC_ATTR_NONNULL_ALL
{
- if (!headless_mode) {
+ if (!headless_mode && !embedded_mode) {
*error = _("can only be opened in headless mode");
return 0;
}
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 192e7d2907..4b838a837c 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -65,6 +65,7 @@
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/msgpack_rpc/server.h"
#include "nvim/msgpack_rpc/channel.h"
+#include "nvim/api/ui.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/handle.h"
@@ -304,6 +305,7 @@ int main(int argc, char **argv)
// 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);
@@ -348,18 +350,16 @@ 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) {
+ if (embedded_mode && !headless_mode) {
TIME_MSG("waiting for embedder to make request");
- rpc_wait_for_request();
+ remote_ui_wait_for_attach();
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");
- }
+ // 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.
@@ -467,7 +467,7 @@ int main(int argc, char **argv)
wait_return(true);
}
- if (!headless_mode && !silent_mode) {
+ if (!headless_mode && !embedded_mode && !silent_mode) {
input_stop(); // Stop reading input, let the UI take over.
ui_builtin_start();
}
@@ -848,7 +848,6 @@ static void command_line_scan(mparm_T *parmp)
headless_mode = true;
} else if (STRICMP(argv[0] + argv_idx, "embed") == 0) {
embedded_mode = true;
- headless_mode = true;
const char *err;
if (!channel_from_stdio(true, CALLBACK_READER_INIT, &err)) {
abort();
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index c6cfb1a9ce..3356cdc61e 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -40,8 +40,6 @@
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
@@ -331,9 +329,6 @@ 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;
}
@@ -349,9 +344,6 @@ 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);
@@ -387,11 +379,6 @@ 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)
@@ -757,17 +744,3 @@ static void log_msg_close(FILE *f, msgpack_object msg)
log_unlock();
}
#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/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua
index 856e5ca4d2..4d25ba0819 100644
--- a/test/functional/api/server_requests_spec.lua
+++ b/test/functional/api/server_requests_spec.lua
@@ -9,7 +9,7 @@ local nvim_prog, command, funcs = helpers.nvim_prog, helpers.command, helpers.fu
local source, next_msg = helpers.source, helpers.next_msg
local ok = helpers.ok
local meths = helpers.meths
-local spawn, nvim_argv = helpers.spawn, helpers.nvim_argv
+local spawn, merge_args = helpers.spawn, helpers.merge_args
local set_session = helpers.set_session
local expect_err = helpers.expect_err
@@ -23,7 +23,7 @@ describe('server -> client', function()
it('handles unexpected closed stream while preparing RPC response', function()
source([[
- let g:_nvim_args = [v:progpath, '--embed', '-n', '-u', 'NONE', '-i', 'NONE', ]
+ let g:_nvim_args = [v:progpath, '--embed', '--headless', '-n', '-u', 'NONE', '-i', 'NONE', ]
let ch1 = jobstart(g:_nvim_args, {'rpc': v:true})
let child1_ch = rpcrequest(ch1, "nvim_get_api_info")[0]
call rpcnotify(ch1, 'nvim_eval', 'rpcrequest('.child1_ch.', "nvim_get_api_info")')
@@ -189,7 +189,7 @@ describe('server -> client', function()
end
before_each(function()
- command("let vim = rpcstart('"..nvim_prog.."', ['-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--embed'])")
+ command("let vim = rpcstart('"..nvim_prog.."', ['-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--embed', '--headless'])")
neq(0, eval('vim'))
end)
@@ -268,6 +268,7 @@ describe('server -> client', function()
end)
describe('connecting to another (peer) nvim', function()
+ local nvim_argv = merge_args(helpers.nvim_argv, {'--headless'})
local function connect_test(server, mode, address)
local serverpid = funcs.getpid()
local client = spawn(nvim_argv)
diff --git a/test/functional/ex_cmds/oldfiles_spec.lua b/test/functional/ex_cmds/oldfiles_spec.lua
index 448326cdfb..e2958c2924 100644
--- a/test/functional/ex_cmds/oldfiles_spec.lua
+++ b/test/functional/ex_cmds/oldfiles_spec.lua
@@ -9,7 +9,7 @@ local eval = helpers.eval
local shada_file = 'Xtest.shada'
local function _clear()
- set_session(spawn({nvim_prog, '--embed', '-u', 'NONE',
+ set_session(spawn({nvim_prog, '--embed', '--headless', '-u', 'NONE',
-- Need shada for these tests.
'-i', shada_file,
'--cmd', 'set noswapfile undodir=. directory=. viewdir=. backupdir=. belloff= noshowcmd noruler'}))
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 8823a6e003..a51eca7fdc 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -330,6 +330,7 @@ local function clear(...)
local new_args
local env = nil
local opts = select(1, ...)
+ local headless = true
if type(opts) == 'table' then
if opts.env then
local env_tbl = {}
@@ -355,15 +356,19 @@ local function clear(...)
end
end
new_args = opts.args or {}
+ if opts.headless == false then
+ headless = false
+ end
else
new_args = {...}
end
+ if headless then
+ table.insert(args, '--headless')
+ end
for _, arg in ipairs(new_args) do
table.insert(args, arg)
end
set_session(spawn(args, nil, env))
- -- Dummy request so that --embed continues past UI initialization
- session:request('nvim_eval', "0")
end
local function insert(...)
diff --git a/test/functional/plugin/helpers.lua b/test/functional/plugin/helpers.lua
index bd482d2db7..4359380bd7 100644
--- a/test/functional/plugin/helpers.lua
+++ b/test/functional/plugin/helpers.lua
@@ -3,7 +3,6 @@ local paths = require('test.config.paths')
local helpers = require('test.functional.helpers')(nil)
local spawn, set_session, nvim_prog, merge_args =
helpers.spawn, helpers.set_session, helpers.nvim_prog, helpers.merge_args
-local request = helpers.request
local additional_cmd = ''
@@ -14,7 +13,7 @@ local function nvim_argv(shada_file)
'--cmd', 'set shortmess+=I background=light noswapfile belloff= noshowcmd noruler',
'--cmd', 'let &runtimepath=' .. rtp_value,
'--cmd', additional_cmd,
- '--embed'}
+ '--embed', '--headless'}
if helpers.prepend_argv then
return merge_args(helpers.prepend_argv, nvim_args)
else
@@ -30,7 +29,6 @@ local function reset(...)
end
session = spawn(nvim_argv(...))
set_session(session)
- request('nvim_eval', "0")
end
local function set_additional_cmd(s)
diff --git a/test/functional/shada/helpers.lua b/test/functional/shada/helpers.lua
index 1312d762d8..d5e061bb50 100644
--- a/test/functional/shada/helpers.lua
+++ b/test/functional/shada/helpers.lua
@@ -9,9 +9,12 @@ local tmpname = helpers.tmpname()
local append_argv = nil
local function nvim_argv(shada_file, embed)
+ if embed == nil then
+ embed = true
+ end
local argv = {nvim_prog, '-u', 'NONE', '-i', shada_file or tmpname, '-N',
'--cmd', 'set shortmess+=I background=light noswapfile',
- embed or '--embed'}
+ '--headless', embed and '--embed' or nil}
if helpers.prepend_argv or append_argv then
return merge_args(helpers.prepend_argv, argv, append_argv)
else
diff --git a/test/functional/shada/marks_spec.lua b/test/functional/shada/marks_spec.lua
index 4cceae1aa3..c2f6351e00 100644
--- a/test/functional/shada/marks_spec.lua
+++ b/test/functional/shada/marks_spec.lua
@@ -224,7 +224,7 @@ describe('ShaDa support code', function()
it('does not create incorrect file for non-existent buffers when writing from -c',
function()
add_argv('--cmd', 'silent edit ' .. non_existent_testfilename, '-c', 'qall')
- local argv = nvim_argv(nil, '--headless')
+ local argv = nvim_argv(nil, false) -- no --embed
eq('', funcs.system(argv))
eq(0, exc_exec('rshada'))
end)
@@ -233,7 +233,7 @@ describe('ShaDa support code', function()
function()
add_argv('-c', 'silent edit ' .. non_existent_testfilename,
'-c', 'autocmd VimEnter * qall')
- local argv = nvim_argv(nil, '--headless')
+ local argv = nvim_argv(nil, false) -- no --embed
eq('', funcs.system(argv))
eq(0, exc_exec('rshada'))
end)
diff --git a/test/functional/shada/shada_spec.lua b/test/functional/shada/shada_spec.lua
index 720855860a..5f7daf73e5 100644
--- a/test/functional/shada/shada_spec.lua
+++ b/test/functional/shada/shada_spec.lua
@@ -137,7 +137,7 @@ describe('ShaDa support code', function()
it('does not write NONE file', function()
local session = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed',
- '--cmd', 'qall'}, true)
+ '--headless', '--cmd', 'qall'}, true)
session:close()
eq(nil, lfs.attributes('NONE'))
eq(nil, lfs.attributes('NONE.tmp.a'))
@@ -145,8 +145,8 @@ describe('ShaDa support code', function()
it('does not read NONE file', function()
write_file('NONE', '\005\001\015\131\161na\162rX\194\162rc\145\196\001-')
- local session = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed'},
- true)
+ local session = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed',
+ '--headless'}, true)
set_session(session)
eq('', funcs.getreg('a'))
session:close()
diff --git a/test/functional/ui/embed_spec.lua b/test/functional/ui/embed_spec.lua
index afe4db66b3..6a5227803d 100644
--- a/test/functional/ui/embed_spec.lua
+++ b/test/functional/ui/embed_spec.lua
@@ -3,18 +3,12 @@ local Screen = require('test.functional.ui.screen')
local feed = helpers.feed
local eq = helpers.eq
-local spawn, set_session = helpers.spawn, helpers.set_session
-local nvim_prog, nvim_set = helpers.nvim_prog, helpers.nvim_set
-local merge_args, prepend_argv = helpers.merge_args, helpers.prepend_argv
+local clear = helpers.clear
local function test_embed(ext_newgrid)
- local session, screen
+ local screen
local function startup(...)
- local nvim_argv = {nvim_prog, '-u', 'NONE', '-i', 'NONE',
- '--cmd', nvim_set, '--embed'}
- nvim_argv = merge_args(prepend_argv, nvim_argv, {...})
- session = spawn(nvim_argv)
- set_session(session)
+ clear{headless=false, args={...}}
-- attach immediately after startup, for early UI
screen = Screen.new(60, 8)
@@ -26,10 +20,6 @@ local function test_embed(ext_newgrid)
})
end
- after_each(function()
- session:close()
- end)
-
it('can display errors', function()
startup('--cmd', 'echoerr invalid+')
screen:expect([[