diff options
-rw-r--r-- | runtime/doc/eval.txt | 10 | ||||
-rw-r--r-- | src/nvim/eval.lua | 1 | ||||
-rw-r--r-- | src/nvim/eval/funcs.c | 40 | ||||
-rw-r--r-- | src/nvim/testdir/test_execute_func.vim | 24 | ||||
-rw-r--r-- | test/functional/ui/float_spec.lua | 18 |
5 files changed, 85 insertions, 8 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index b8dcfd0ff4..4d6de151f9 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2498,6 +2498,8 @@ visualmode([expr]) String last visual mode used wait({timeout}, {condition}[, {interval}]) Number Wait until {condition} is satisfied wildmenumode() Number whether 'wildmenu' mode is active +win_execute({id}, {command} [, {silent}]) + String execute {command} in window {id} win_findbuf({bufnr}) List find windows containing {bufnr} win_getid([{win} [, {tab}]]) Number get |window-ID| for {win} in {tab} win_gettype([{nr}]) String type of window {nr} @@ -3616,6 +3618,8 @@ execute({command} [, {silent}]) *execute()* Note: If nested, an outer execute() will not observe output of the inner calls. Note: Text attributes (highlights) are not captured. + To execute a command in another window than the current one + use `win_execute()`. exepath({expr}) *exepath()* Returns the full path of {expr} if it is an executable and @@ -9477,6 +9481,12 @@ wildmenumode() *wildmenumode()* < (Note, this needs the 'wildcharm' option set appropriately). +win_execute({id}, {command} [, {silent}]) *win_execute()* + Like `execute()` but in the context of window {id}. + The window will temporarily be made the current window, + without triggering autocommands. + Example: > + call win_execute(winid, 'syntax enable') win_findbuf({bufnr}) *win_findbuf()* Returns a list with |window-ID|s for windows that contain diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 77e7c7b3a9..148804e54c 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -390,6 +390,7 @@ return { visualmode={args={0, 1}}, wait={args={2,3}}, wildmenumode={}, + win_execute={args={2, 3}}, win_findbuf={args=1}, win_getid={args={0,2}}, win_gettype={args={0,1}}, diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 6d328953f6..fe0a4c29a2 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1953,8 +1953,8 @@ static char_u *get_list_line(int c, void *cookie, int indent, bool do_concat) return (char_u *)(s == NULL ? NULL : xstrdup(s)); } -// "execute(command)" function -static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void execute_common(typval_T *argvars, typval_T *rettv, FunPtr fptr, + int arg_off) { const int save_msg_silent = msg_silent; const int save_emsg_silent = emsg_silent; @@ -1968,9 +1968,9 @@ static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - if (argvars[1].v_type != VAR_UNKNOWN) { + if (argvars[arg_off + 1].v_type != VAR_UNKNOWN) { char buf[NUMBUFLEN]; - const char *const s = tv_get_string_buf_chk(&argvars[1], buf); + const char *const s = tv_get_string_buf_chk(&argvars[arg_off + 1], buf); if (s == NULL) { return; @@ -1997,10 +1997,10 @@ static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr) msg_col = 0; // prevent leading spaces } - if (argvars[0].v_type != VAR_LIST) { - do_cmdline_cmd(tv_get_string(&argvars[0])); - } else if (argvars[0].vval.v_list != NULL) { - list_T *const list = argvars[0].vval.v_list; + if (argvars[arg_off].v_type != VAR_LIST) { + do_cmdline_cmd(tv_get_string(&argvars[arg_off])); + } else if (argvars[arg_off].vval.v_list != NULL) { + list_T *const list = argvars[arg_off].vval.v_list; tv_list_ref(list); GetListLineCookie cookie = { .l = list, @@ -2032,6 +2032,30 @@ static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr) capture_ga = save_capture_ga; } +// "execute(command)" function +static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + execute_common(argvars, rettv, fptr, 0); +} + +// "win_execute(win_id, command)" function +static void f_win_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + win_T *wp = win_id2wp(argvars); + win_T *save_curwin = curwin; + + if (wp != NULL) { + curwin = wp; + curbuf = curwin->w_buffer; + check_cursor(); + execute_common(argvars, rettv, fptr, 1); + if (win_valid(save_curwin)) { + curwin = save_curwin; + curbuf = curwin->w_buffer; + } + } +} + /// "exepath()" function static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr) { diff --git a/src/nvim/testdir/test_execute_func.vim b/src/nvim/testdir/test_execute_func.vim index eb84a6739d..98e0ea4e09 100644 --- a/src/nvim/testdir/test_execute_func.vim +++ b/src/nvim/testdir/test_execute_func.vim @@ -82,3 +82,27 @@ func Test_execute_not_silent() endfor call assert_equal('xyz ', text2) endfunc + +func Test_win_execute() + let thiswin = win_getid() + new + let otherwin = win_getid() + call setline(1, 'the new window') + call win_gotoid(thiswin) + let line = win_execute(otherwin, 'echo getline(1)') + call assert_match('the new window', line) + + if has('textprop') + let popupwin = popup_create('the popup win', {'line': 2, 'col': 3}) + redraw + let line = win_execute(popupwin, 'echo getline(1)') + call assert_match('the popup win', line) + + call assert_fails('call win_execute(popupwin, "bwipe!")', 'E937:') + + call popup_close(popupwin) + endif + + call win_gotoid(otherwin) + bwipe! +endfunc diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 3e73d8b3de..6b75803727 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -62,6 +62,24 @@ describe('float window', function() eq(1000, funcs.win_getid()) end) + it('win_execute() should work' , function() + local buf = meths.create_buf(false, false) + meths.buf_set_lines(buf, 0, -1, true, {'the floatwin'}) + local win = meths.open_win(buf, false, {relative='win', width=16, height=1, row=0, col=10}) + local line = funcs.win_execute(win, 'echo getline(1)') + eq('\nthe floatwin', line) + funcs.win_execute(win, 'bwipe!') + end) + + it('win_execute() call commands that not allowed' , function() + local buf = meths.create_buf(false, false) + meths.buf_set_lines(buf, 0, -1, true, {'the floatwin'}) + local win = meths.open_win(buf, true, {relative='win', width=16, height=1, row=0, col=10}) + eq(pcall_err(funcs.win_execute, win, 'close'), 'Vim(close):E37: No write since last change (add ! to override)') + eq(pcall_err(funcs.win_execute, win, 'bdelete'), 'Vim(bdelete):E89: No write since last change for buffer 2 (add ! to override)') + funcs.win_execute(win, 'bwipe!') + end) + it('closed immediately by autocmd #11383', function() eq('Error executing lua: [string "<nvim>"]:0: Window was closed immediately', pcall_err(exec_lua, [[ |