mirror of
https://github.com/neovim/neovim.git
synced 2025-10-06 01:46:29 +00:00
Merge pull request #13664 from ivechan/win_exectute
vim-patch:8.1.{1418,1425,1832,2124},8.2.{0137, 2340}
This commit is contained in:
@@ -2529,6 +2529,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}
|
||||
@@ -3543,6 +3545,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
|
||||
@@ -9123,6 +9127,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
|
||||
|
@@ -54,7 +54,7 @@ void nvim_win_set_buf(Window window, Buffer buffer, Error *err)
|
||||
return;
|
||||
}
|
||||
|
||||
if (switch_win(&save_curwin, &save_curtab, win, tab, false) == FAIL) {
|
||||
if (switch_win_noblock(&save_curwin, &save_curtab, win, tab, false) == FAIL) {
|
||||
api_set_error(err,
|
||||
kErrorTypeException,
|
||||
"Failed to switch to window %d",
|
||||
@@ -74,7 +74,7 @@ void nvim_win_set_buf(Window window, Buffer buffer, Error *err)
|
||||
// So do it now.
|
||||
validate_cursor();
|
||||
|
||||
restore_win(save_curwin, save_curtab, false);
|
||||
restore_win_noblock(save_curwin, save_curtab, false);
|
||||
}
|
||||
|
||||
/// Gets the (1,0)-indexed cursor position in the window. |api-indexing|
|
||||
|
@@ -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}},
|
||||
|
@@ -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,39 @@ 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)
|
||||
{
|
||||
tabpage_T *tp;
|
||||
win_T *wp = win_id2wp_tp(argvars, &tp);
|
||||
win_T *save_curwin;
|
||||
tabpage_T *save_curtab;
|
||||
// Return an empty string if something fails.
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = NULL;
|
||||
|
||||
if (wp != NULL && tp != NULL) {
|
||||
pos_T curpos = wp->w_cursor;
|
||||
if (switch_win_noblock(&save_curwin, &save_curtab, wp, tp, true) ==
|
||||
OK) {
|
||||
check_cursor();
|
||||
execute_common(argvars, rettv, fptr, 1);
|
||||
}
|
||||
restore_win_noblock(save_curwin, save_curtab, true);
|
||||
|
||||
// Update the status line if the cursor moved.
|
||||
if (win_valid(wp) && !equalpos(curpos, wp->w_cursor)) {
|
||||
wp->w_redr_status = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// "exepath()" function
|
||||
static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
|
@@ -1,5 +1,7 @@
|
||||
" test execute()
|
||||
|
||||
source view_util.vim
|
||||
|
||||
func NestedEval()
|
||||
let nested = execute('echo "nested\nlines"')
|
||||
echo 'got: "' . nested . '"'
|
||||
@@ -82,3 +84,54 @@ 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)
|
||||
let line = win_execute(134343, 'echo getline(1)')
|
||||
call assert_equal('', 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 popup_close(popupwin)
|
||||
endif
|
||||
|
||||
call win_gotoid(otherwin)
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
func Test_win_execute_update_ruler()
|
||||
enew
|
||||
call setline(1, range(500))
|
||||
20
|
||||
split
|
||||
let winid = win_getid()
|
||||
set ruler
|
||||
wincmd w
|
||||
let height = winheight(winid)
|
||||
redraw
|
||||
call assert_match('20,1', Screenline(height + 1))
|
||||
let line = win_execute(winid, 'call cursor(100, 1)')
|
||||
redraw
|
||||
call assert_match('100,1', Screenline(height + 1))
|
||||
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
func Test_win_execute_other_tab()
|
||||
let thiswin = win_getid()
|
||||
tabnew
|
||||
call win_execute(thiswin, 'let xyz = 1')
|
||||
call assert_equal(1, xyz)
|
||||
tabclose
|
||||
unlet xyz
|
||||
endfunc
|
||||
|
@@ -160,7 +160,7 @@ func Test_winfixwidth_on_close()
|
||||
endfunction
|
||||
|
||||
" Test that 'winfixheight' will be respected even there is non-leaf frame
|
||||
fun! Test_winfixheight_non_leaf_frame()
|
||||
func Test_winfixheight_non_leaf_frame()
|
||||
vsplit
|
||||
botright 11new
|
||||
let l:wid = win_getid()
|
||||
@@ -173,7 +173,7 @@ fun! Test_winfixheight_non_leaf_frame()
|
||||
endf
|
||||
|
||||
" Test that 'winfixwidth' will be respected even there is non-leaf frame
|
||||
fun! Test_winfixwidth_non_leaf_frame()
|
||||
func Test_winfixwidth_non_leaf_frame()
|
||||
split
|
||||
topleft 11vnew
|
||||
let l:wid = win_getid()
|
||||
@@ -184,3 +184,13 @@ fun! Test_winfixwidth_non_leaf_frame()
|
||||
call assert_equal(11, winwidth(l:wid))
|
||||
%bwipe!
|
||||
endf
|
||||
|
||||
func Test_tabwin_close()
|
||||
enew
|
||||
let l:wid = win_getid()
|
||||
tabedit
|
||||
call win_execute(l:wid, 'close')
|
||||
" Should not crash.
|
||||
call assert_true(v:true)
|
||||
%bwipe!
|
||||
endfunc
|
||||
|
@@ -3466,6 +3466,9 @@ int win_alloc_first(void)
|
||||
first_tabpage = alloc_tabpage();
|
||||
first_tabpage->tp_topframe = topframe;
|
||||
curtab = first_tabpage;
|
||||
curtab->tp_firstwin = firstwin;
|
||||
curtab->tp_lastwin = lastwin;
|
||||
curtab->tp_curwin = curwin;
|
||||
|
||||
return OK;
|
||||
}
|
||||
@@ -3634,6 +3637,8 @@ int win_new_tabpage(int after, char_u *filename)
|
||||
newtp->tp_next = tp->tp_next;
|
||||
tp->tp_next = newtp;
|
||||
}
|
||||
newtp->tp_firstwin = newtp->tp_lastwin = newtp->tp_curwin = curwin;
|
||||
|
||||
win_init_size();
|
||||
firstwin->w_winrow = tabline_height();
|
||||
win_comp_scroll(curwin);
|
||||
@@ -6336,6 +6341,13 @@ static win_T *get_snapshot_focus(int idx)
|
||||
int switch_win(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage_T *tp, int no_display)
|
||||
{
|
||||
block_autocmds();
|
||||
return switch_win_noblock(save_curwin, save_curtab, win, tp, no_display);
|
||||
}
|
||||
|
||||
// As switch_win() but without blocking autocommands.
|
||||
int switch_win_noblock(win_T **save_curwin, tabpage_T **save_curtab,
|
||||
win_T *win, tabpage_T *tp, int no_display)
|
||||
{
|
||||
*save_curwin = curwin;
|
||||
if (tp != NULL) {
|
||||
*save_curtab = curtab;
|
||||
@@ -6360,6 +6372,14 @@ int switch_win(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage
|
||||
// When "no_display" is true the display won't be affected, no redraw is
|
||||
// triggered.
|
||||
void restore_win(win_T *save_curwin, tabpage_T *save_curtab, bool no_display)
|
||||
{
|
||||
restore_win_noblock(save_curwin, save_curtab, no_display);
|
||||
unblock_autocmds();
|
||||
}
|
||||
|
||||
// As restore_win() but without unblocking autocommands.
|
||||
void restore_win_noblock(win_T *save_curwin, tabpage_T *save_curtab,
|
||||
bool no_display)
|
||||
{
|
||||
if (save_curtab != NULL && valid_tabpage(save_curtab)) {
|
||||
if (no_display) {
|
||||
@@ -6375,7 +6395,6 @@ void restore_win(win_T *save_curwin, tabpage_T *save_curtab, bool no_display)
|
||||
curwin = save_curwin;
|
||||
curbuf = curwin->w_buffer;
|
||||
}
|
||||
unblock_autocmds();
|
||||
}
|
||||
|
||||
/// Make "buf" the current buffer.
|
||||
@@ -6807,11 +6826,20 @@ void win_id2tabwin(typval_T *const argvars, typval_T *const rettv)
|
||||
}
|
||||
|
||||
win_T * win_id2wp(typval_T *argvars)
|
||||
{
|
||||
return win_id2wp_tp(argvars, NULL);
|
||||
}
|
||||
|
||||
// Return the window and tab pointer of window "id".
|
||||
win_T * win_id2wp_tp(typval_T *argvars, tabpage_T **tpp)
|
||||
{
|
||||
int id = tv_get_number(&argvars[0]);
|
||||
|
||||
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
||||
if (wp->handle == id) {
|
||||
if (tpp != NULL) {
|
||||
*tpp = tp;
|
||||
}
|
||||
return wp;
|
||||
}
|
||||
}
|
||||
|
@@ -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, [[
|
||||
|
Reference in New Issue
Block a user