From 6b4970f6e0ac36021b2a8bd0533f5078040d31f7 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Sun, 23 Jul 2023 19:50:20 +0100 Subject: feat(api): allow open_win/win_set_buf in the cmdwin in some cases Problem: As discussed on Matrix, there was some interest in having `nvim_open_win` again be able to open floats in the cmdwin (e.g: displaying a hover doc related to what's in the cmdwin). After #23228, this was disallowed. Solution: Allow `nvim_open_win` in the cmdwin as long as `!enter` and `buffer != curbuf` (the former can cause all sorts of issues, and the latter can crash Nvim after closing cmdwin). Also allow `nvim_win_set_buf` in a similar fashion. Note that we're not *entirely* sure if this is 100% safe (cmdwin is a global-state-using-main-loop-calling beast), but this seems to work OK..? Also: - Check the buffer argument of `nvim_open_win` earlier, and abort if it's invalid (it used to still open a window in this case). - Untranslate `e_cmdwin` errors in the API (other errors in the API are not translated: although not detailed in the API contract yet, errors are supposed to be stable). --- test/functional/api/window_spec.lua | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'test/functional/api') diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index 19511f30f1..e7e767817b 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -43,6 +43,22 @@ describe('API/win', function() eq('Invalid buffer id: 23', pcall_err(window, 'set_buf', nvim('get_current_win'), 23)) eq('Invalid window id: 23', pcall_err(window, 'set_buf', 23, nvim('get_current_buf'))) end) + + it('disallowed in cmdwin if win=curwin or buf=curbuf', function() + local new_buf = meths.create_buf(true, true) + local new_win = meths.open_win(new_buf, false, { + relative='editor', row=10, col=10, width=50, height=10, + }) + feed('q:') + eq('E11: Invalid in command-line window; executes, CTRL-C quits', + pcall_err(meths.win_set_buf, 0, new_buf)) + eq('E11: Invalid in command-line window; executes, CTRL-C quits', + pcall_err(meths.win_set_buf, new_win, 0)) + + local next_buf = meths.create_buf(true, true) + meths.win_set_buf(new_win, next_buf) + eq(next_buf, meths.win_get_buf(new_win)) + end) end) describe('{get,set}_cursor', function() @@ -821,6 +837,31 @@ describe('API/win', function() }) eq(1, funcs.exists('g:fired')) end) + + it('disallowed in cmdwin if enter=true or buf=curbuf', function() + local new_buf = meths.create_buf(true, true) + feed('q:') + eq('E11: Invalid in command-line window; executes, CTRL-C quits', + pcall_err(meths.open_win, new_buf, true, { + relative='editor', row=5, col=5, width=5, height=5, + })) + eq('E11: Invalid in command-line window; executes, CTRL-C quits', + pcall_err(meths.open_win, 0, false, { + relative='editor', row=5, col=5, width=5, height=5, + })) + + eq(new_buf, meths.win_get_buf(meths.open_win(new_buf, false, { + relative='editor', row=5, col=5, width=5, height=5, + }))) + end) + + it('aborts if buffer is invalid', function() + local wins_before = meths.list_wins() + eq('Invalid buffer id: 1337', pcall_err(meths.open_win, 1337, false, { + relative='editor', row=5, col=5, width=5, height=5, + })) + eq(wins_before, meths.list_wins()) + end) end) describe('get_config', function() -- cgit From 5d921e28c1cc33eced22bbfa823460ca241e3dc1 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Sun, 23 Jul 2023 23:10:28 +0100 Subject: feat(api): allow win_close in cmdwin to close wins except previous Disallow closing the previous window from `nvim_win_close`, as this will cause issues. Again, no telling how safe this is. It also requires exposing old_curwin. :/ Also note that it's possible for the `&cmdheight` to change if, for example, there are 2 tabpages and `nvim_win_close` is used to close the last window in the other tabpage while `&stal` is 1. This is addressed in a later commit. --- test/functional/api/window_spec.lua | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'test/functional/api') diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index e7e767817b..74aaae0c6f 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -540,15 +540,21 @@ describe('API/win', function() command('split') eq(2, #meths.list_wins()) local oldwin = meths.get_current_win() + local otherwin = meths.open_win(0, false, { + relative='editor', row=10, col=10, width=10, height=10, + }) -- Open cmdline-window. feed('q:') - eq(3, #meths.list_wins()) + eq(4, #meths.list_wins()) eq(':', funcs.getcmdwintype()) - -- Vim: not allowed to close other windows from cmdline-window. + -- Not allowed to close previous window from cmdline-window. eq('E11: Invalid in command-line window; executes, CTRL-C quits', - pcall_err(meths.win_close, oldwin, true)) + pcall_err(meths.win_close, oldwin, true)) + -- Closing other windows is fine. + meths.win_close(otherwin, true) + eq(false, meths.win_is_valid(otherwin)) -- Close cmdline-window. - meths.win_close(0,true) + meths.win_close(0, true) eq(2, #meths.list_wins()) eq('', funcs.getcmdwintype()) end) -- cgit From 472271199e483d3f23d62c272b20c5290eec5474 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Mon, 24 Jul 2023 14:19:01 +0100 Subject: feat(api): allow win_hide to close cmdwin or non-previous windows This aligns its behaviour better with `nvim_win_close`. Note that `:hide` is actually incapable of closing the cmdwin, unlike `:close` and `:quit`, so this is a bit of a difference in behaviour. --- test/functional/api/window_spec.lua | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'test/functional/api') diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index 74aaae0c6f..00896a97d8 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -615,6 +615,24 @@ describe('API/win', function() eq({oldwin}, meths.list_wins()) eq({oldbuf}, meths.list_bufs()) end) + it('in the cmdwin', function() + feed('q:') + -- Can close the cmdwin. + meths.win_hide(0) + eq('', funcs.getcmdwintype()) + + local old_win = meths.get_current_win() + local other_win = meths.open_win(0, false, { + relative='win', row=3, col=3, width=12, height=3 + }) + feed('q:') + -- Cannot close the previous window. + eq('E11: Invalid in command-line window; executes, CTRL-C quits', + pcall_err(meths.win_hide, old_win)) + -- Can close other windows. + meths.win_hide(other_win) + eq(false, meths.win_is_valid(other_win)) + end) end) describe('text_height', function() -- cgit