diff options
-rw-r--r-- | .github/workflows/optional.yml | 34 | ||||
-rw-r--r-- | .github/workflows/test.yml | 2 | ||||
-rw-r--r-- | runtime/doc/starting.txt | 4 | ||||
-rw-r--r-- | src/nvim/CMakeLists.txt | 8 | ||||
-rw-r--r-- | src/nvim/api/ui.c | 26 | ||||
-rw-r--r-- | src/nvim/autocmd.c | 3 | ||||
-rw-r--r-- | src/nvim/main.c | 5 | ||||
-rw-r--r-- | src/nvim/ui.c | 10 | ||||
-rw-r--r-- | test/functional/api/ui_spec.lua | 15 | ||||
-rw-r--r-- | test/functional/ui/embed_spec.lua | 61 |
10 files changed, 141 insertions, 27 deletions
diff --git a/.github/workflows/optional.yml b/.github/workflows/optional.yml new file mode 100644 index 0000000000..f512bb0d2a --- /dev/null +++ b/.github/workflows/optional.yml @@ -0,0 +1,34 @@ +name: optional +on: + pull_request: + types: [labeled, opened, synchronize, reopened] + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} + cancel-in-progress: true + +jobs: + s390x: + if: ${{ github.event.label.name == 'ci-s390x' }} + strategy: + fail-fast: false + matrix: + test: [functionaltest, oldtest] + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - run: docker run --rm --privileged multiarch/qemu-user-static:register --reset + - uses: docker://multiarch/ubuntu-core:s390x-focal + with: + args: > + bash -c + " + apt-get -y update && + DEBIAN_FRONTEND=noninteractive apt-get -y install attr build-essential cmake curl gettext libattr1-dev ninja-build unzip locales-all cpanminus git && + git clone --depth=1 https://github.com/neovim/neovim.git && + cd neovim && + cmake -S cmake.deps -B .deps -G Ninja -D USE_BUNDLED_LUAJIT=OFF -D USE_BUNDLED_LUA=ON && + cmake --build .deps && + cmake -B build -G Ninja -D PREFER_LUA=ON && + make ${{ matrix.test }} + " diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a9fbf4330a..1ff6b31a2d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -110,7 +110,7 @@ jobs: [ { runner: ubuntu-22.04, flavor: asan, cc: clang, flags: -D ENABLE_ASAN_UBSAN=ON }, { runner: ubuntu-22.04, flavor: tsan, cc: clang, flags: -D ENABLE_TSAN=ON }, - { runner: ubuntu-22.04, flavor: uchar, cc: gcc, flags: -D UNSIGNED_CHAR=ON }, + { runner: ubuntu-22.04, cc: gcc }, { runner: macos-12, cc: clang, flags: -D CMAKE_FIND_FRAMEWORK=NEVER, deps_flags: -D CMAKE_FIND_FRAMEWORK=NEVER }, { runner: ubuntu-22.04, flavor: functionaltest-lua, cc: gcc, deps_flags: -D USE_BUNDLED_LUAJIT=OFF -D USE_BUNDLED_LUA=ON, flags: -D PREFER_LUA=ON }, ] diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index af175ed2b9..9f7a729575 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -390,6 +390,10 @@ argument. < Then startup will continue without waiting for `nvim_ui_attach`. This is equivalent to: > 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| diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 9cad80db23..49402a36a8 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -100,7 +100,8 @@ else() -Wdouble-promotion -Wmissing-noreturn -Wmissing-format-attribute - -Wmissing-prototypes) + -Wmissing-prototypes + -fsigned-char) if(CMAKE_C_COMPILER_ID STREQUAL "GNU") target_compile_options(main_lib INTERFACE -fno-common @@ -172,11 +173,6 @@ if(CI_BUILD) endif() endif() -option(UNSIGNED_CHAR "Set char to be unsigned" OFF) -if(UNSIGNED_CHAR) - target_compile_options(main_lib INTERFACE -funsigned-char) -endif() - target_compile_definitions(main_lib INTERFACE INCLUDE_GENERATED_DECLARATIONS) # Remove --sort-common from linker flags, as this seems to cause bugs (see #2641, #3374). diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index e0b5e6ea57..b508a3ee94 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -126,18 +126,24 @@ 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) +/// Wait until ui has connected on stdio channel if only_stdio +/// is true, otherwise any channel. +void remote_ui_wait_for_attach(bool only_stdio) { - Channel *channel = find_channel(CHAN_STDIO); - if (!channel) { - // this function should only be called in --embed mode, stdio channel - // can be assumed. - abort(); - } + if (only_stdio) { + 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, - map_has(uint64_t, &connected_uis, CHAN_STDIO)); + LOOP_PROCESS_EVENTS_UNTIL(&main_loop, channel->events, -1, + 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. diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 2537269c5c..bdb3983ab3 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -2570,6 +2570,9 @@ void do_autocmd_uienter(uint64_t chanid, bool attached) { static bool recursive = false; + if (starting == NO_SCREEN) { + return; // user config hasn't been sourced yet + } if (recursive) { return; // disallow recursion } diff --git a/src/nvim/main.c b/src/nvim/main.c index f6fd3abaec..88d198bfa5 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -392,9 +392,10 @@ int main(int argc, char **argv) // Wait for UIs to set up Nvim or show early messages // and prompts (--cmd, swapfile dialog, …). bool use_remote_ui = (embedded_mode && !headless_mode); + bool listen_and_embed = params.listen_addr != NULL; if (use_remote_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"); firstwin->w_prev_height = firstwin->w_height; // may have changed } @@ -588,7 +589,7 @@ int main(int argc, char **argv) apply_autocmds(EVENT_VIMENTER, NULL, NULL, false, curbuf); TIME_MSG("VimEnter autocommands"); if (use_remote_ui) { - do_autocmd_uienter(CHAN_STDIO, true); + do_autocmd_uienter_all(); TIME_MSG("UIEnter autocommands"); } diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 954d933d9c..90d475e7e7 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -337,6 +337,16 @@ void vim_beep(unsigned val) } } +/// Trigger UIEnter for all attached UIs. +/// Used on startup after VimEnter. +void do_autocmd_uienter_all(void) +{ + for (size_t i = 0; i < ui_count; i++) { + UIData *data = uis[i]->data; + do_autocmd_uienter(data->channel_id, true); + } +} + void ui_attach_impl(UI *ui, uint64_t chanid) { if (ui_count == MAX_UI_COUNT) { diff --git a/test/functional/api/ui_spec.lua b/test/functional/api/ui_spec.lua index 2cadfe117f..a668d47448 100644 --- a/test/functional/api/ui_spec.lua +++ b/test/functional/api/ui_spec.lua @@ -60,14 +60,13 @@ describe('nvim_ui_attach()', function() end) it('autocmds UIEnter/UILeave', function() - clear{ - args_rm={'--headless'}, - args={ - '--cmd', 'let g:evs = []', - '--cmd', 'autocmd UIEnter * :call add(g:evs, "UIEnter") | let g:uienter_ev = deepcopy(v:event)', - '--cmd', 'autocmd UILeave * :call add(g:evs, "UILeave") | let g:uileave_ev = deepcopy(v:event)', - '--cmd', 'autocmd VimEnter * :call add(g:evs, "VimEnter")', - }} + clear{args_rm={'--headless'}} + exec([[ + let g:evs = [] + autocmd UIEnter * call add(g:evs, "UIEnter") | let g:uienter_ev = deepcopy(v:event) + autocmd UILeave * call add(g:evs, "UILeave") | let g:uileave_ev = deepcopy(v:event) + autocmd VimEnter * call add(g:evs, "VimEnter") + ]]) local screen = Screen.new() screen:attach() eq({chan=1}, eval('g:uienter_ev')) diff --git a/test/functional/ui/embed_spec.lua b/test/functional/ui/embed_spec.lua index db01c55e23..fb2cdb3c4a 100644 --- a/test/functional/ui/embed_spec.lua +++ b/test/functional/ui/embed_spec.lua @@ -2,10 +2,13 @@ local uv = require'luv' local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') +local thelpers = require('test.functional.terminal.helpers') local feed = helpers.feed local eq = helpers.eq local clear = helpers.clear +local ok = helpers.ok + local function test_embed(ext_linegrid) local screen @@ -133,3 +136,61 @@ describe('--embed UI', function() ]]} 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, api_info = child_session:request('nvim_get_api_info') + ok(info_ok) + eq(2, #api_info) + ok(api_info[1] > 2, 'channel_id > 2', api_info[1]) + + child_session:request('nvim_exec2', [[ + let g:evs = [] + autocmd UIEnter * call add(g:evs, $"UIEnter:{v:event.chan}") + autocmd VimEnter * call add(g:evs, "VimEnter") + ]], {}) + + -- VimEnter and UIEnter shouldn't be triggered until after attach + local var_ok, var = child_session:request('nvim_get_var', 'evs') + ok(var_ok) + eq({}, var) + + 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}; + }} + + -- VimEnter and UIEnter should now be triggered + var_ok, var = child_session:request('nvim_get_var', 'evs') + ok(var_ok) + eq({'VimEnter', ('UIEnter:%d'):format(api_info[1])}, var) + end) +end) |