mirror of
https://github.com/neovim/neovim
synced 2025-07-16 09:11:51 +00:00
feat(server): allow embed with listen (#25709)
connection from any channel or stdio will unblock remote_ui_wait_for_attach. Wait on stdio only if only —embed specified, if both —embed and —listen then wait on any channel.
This commit is contained in:
@ -390,6 +390,10 @@ argument.
|
|||||||
< Then startup will continue without waiting for `nvim_ui_attach`.
|
< Then startup will continue without waiting for `nvim_ui_attach`.
|
||||||
This is equivalent to: >
|
This is equivalent to: >
|
||||||
nvim --headless --cmd "call stdioopen({'rpc': v:true})"
|
nvim --headless --cmd "call stdioopen({'rpc': v:true})"
|
||||||
|
<
|
||||||
|
Embedders that use the UI protocol on a socket connection must
|
||||||
|
pass |--listen| as well as |--embed|: >
|
||||||
|
nvim --embed --listen addr
|
||||||
|
|
||||||
< See also: |ui-startup| |channel-stdio|
|
< See also: |ui-startup| |channel-stdio|
|
||||||
|
|
||||||
|
@ -126,18 +126,24 @@ void remote_ui_disconnect(uint64_t channel_id)
|
|||||||
xfree(ui);
|
xfree(ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait until ui has connected on stdio channel.
|
/// Wait until ui has connected on stdio channel if only_stdio
|
||||||
void remote_ui_wait_for_attach(void)
|
/// is true, otherwise any channel.
|
||||||
|
void remote_ui_wait_for_attach(bool only_stdio)
|
||||||
{
|
{
|
||||||
Channel *channel = find_channel(CHAN_STDIO);
|
if (only_stdio) {
|
||||||
if (!channel) {
|
Channel *channel = find_channel(CHAN_STDIO);
|
||||||
// this function should only be called in --embed mode, stdio channel
|
if (!channel) {
|
||||||
// can be assumed.
|
// this function should only be called in --embed mode, stdio channel
|
||||||
abort();
|
// can be assumed.
|
||||||
}
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, channel->events, -1,
|
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, channel->events, -1,
|
||||||
map_has(uint64_t, &connected_uis, CHAN_STDIO));
|
map_has(uint64_t, &connected_uis, CHAN_STDIO));
|
||||||
|
} else {
|
||||||
|
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, main_loop.events, -1,
|
||||||
|
ui_active());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Activates UI events on the channel.
|
/// Activates UI events on the channel.
|
||||||
|
@ -392,9 +392,10 @@ int main(int argc, char **argv)
|
|||||||
// Wait for UIs to set up Nvim or show early messages
|
// Wait for UIs to set up Nvim or show early messages
|
||||||
// and prompts (--cmd, swapfile dialog, …).
|
// and prompts (--cmd, swapfile dialog, …).
|
||||||
bool use_remote_ui = (embedded_mode && !headless_mode);
|
bool use_remote_ui = (embedded_mode && !headless_mode);
|
||||||
|
bool listen_and_embed = params.listen_addr != NULL;
|
||||||
if (use_remote_ui) {
|
if (use_remote_ui) {
|
||||||
TIME_MSG("waiting for UI");
|
TIME_MSG("waiting for UI");
|
||||||
remote_ui_wait_for_attach();
|
remote_ui_wait_for_attach(!listen_and_embed);
|
||||||
TIME_MSG("done waiting for UI");
|
TIME_MSG("done waiting for UI");
|
||||||
firstwin->w_prev_height = firstwin->w_height; // may have changed
|
firstwin->w_prev_height = firstwin->w_height; // may have changed
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,13 @@ local uv = require'luv'
|
|||||||
|
|
||||||
local helpers = require('test.functional.helpers')(after_each)
|
local helpers = require('test.functional.helpers')(after_each)
|
||||||
local Screen = require('test.functional.ui.screen')
|
local Screen = require('test.functional.ui.screen')
|
||||||
|
local thelpers = require('test.functional.terminal.helpers')
|
||||||
|
|
||||||
local feed = helpers.feed
|
local feed = helpers.feed
|
||||||
local eq = helpers.eq
|
local eq = helpers.eq
|
||||||
local clear = helpers.clear
|
local clear = helpers.clear
|
||||||
|
local ok = helpers.ok
|
||||||
|
|
||||||
|
|
||||||
local function test_embed(ext_linegrid)
|
local function test_embed(ext_linegrid)
|
||||||
local screen
|
local screen
|
||||||
@ -133,3 +136,60 @@ describe('--embed UI', function()
|
|||||||
]]}
|
]]}
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
describe('--embed --listen UI', function()
|
||||||
|
it('waits for connection on listening address', function()
|
||||||
|
helpers.skip(helpers.is_os('win'))
|
||||||
|
clear()
|
||||||
|
local child_server = assert(helpers.new_pipename())
|
||||||
|
|
||||||
|
local screen = thelpers.screen_setup(0,
|
||||||
|
string.format(
|
||||||
|
[=[["%s", "--embed", "--listen", "%s", "-u", "NONE", "-i", "NONE", "--cmd", "%s"]]=],
|
||||||
|
helpers.nvim_prog, child_server, helpers.nvim_set))
|
||||||
|
screen:expect{grid=[[
|
||||||
|
{1: } |
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
{3:-- TERMINAL --} |
|
||||||
|
]]}
|
||||||
|
|
||||||
|
local child_session = helpers.connect(child_server)
|
||||||
|
|
||||||
|
local info_ok, apiinfo = child_session:request('nvim_get_api_info')
|
||||||
|
assert(info_ok)
|
||||||
|
assert(#apiinfo == 2)
|
||||||
|
|
||||||
|
child_session:request('nvim_exec2', [[
|
||||||
|
let g:vim_entered=0
|
||||||
|
autocmd VimEnter * call execute("let g:vim_entered=1")
|
||||||
|
]], {})
|
||||||
|
|
||||||
|
-- g:vim_entered shouldn't be set to 1 until after attach
|
||||||
|
local var_ok, var = child_session:request('nvim_get_var', 'vim_entered')
|
||||||
|
assert(var_ok)
|
||||||
|
ok(var == 0)
|
||||||
|
|
||||||
|
local child_screen = Screen.new(40, 6)
|
||||||
|
child_screen:attach(nil, child_session)
|
||||||
|
child_screen:expect{grid=[[
|
||||||
|
^ |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
|
|
||||||
|
]], attr_ids={
|
||||||
|
[1] = {foreground = Screen.colors.Blue, bold = true};
|
||||||
|
}}
|
||||||
|
|
||||||
|
-- g:vim_entered should now be set to 1
|
||||||
|
var_ok, var = child_session:request('nvim_get_var', 'vim_entered')
|
||||||
|
assert(var_ok)
|
||||||
|
ok(var == 1)
|
||||||
|
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
Reference in New Issue
Block a user