aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/eval.txt10
-rw-r--r--src/nvim/eval.lua1
-rw-r--r--src/nvim/eval/funcs.c40
-rw-r--r--src/nvim/testdir/test_execute_func.vim24
-rw-r--r--test/functional/ui/float_spec.lua18
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, [[