diff options
-rw-r--r-- | src/nvim/api/buffer.c | 38 | ||||
-rw-r--r-- | test/functional/lua/vim_spec.lua | 25 |
2 files changed, 63 insertions, 0 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 21f7c8e931..6f74ec905c 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1666,6 +1666,44 @@ Integer nvim_buf_set_virtual_text(Buffer buffer, return src_id; } +/// call a function with buffer as temporary current buffer +/// +/// This temporarily switches current buffer to "buffer". +/// If the current window already shows "buffer", the window is not switched +/// If a window inside the current tabpage (including a float) already shows the +/// buffer One of these windows will be set as current window temporarily. +/// Otherwise a temporary scratch window (calleed the "autocmd window" for +/// historical reasons) will be used. +/// +/// This is useful e.g. to call vimL functions that only work with the current +/// buffer/window currently, like |termopen()|. +/// +/// @param buffer Buffer handle, or 0 for current buffer +/// @param fun Function to call inside the buffer (currently lua callable +/// only) +/// @param[out] err Error details, if any +/// @return Return value of function. NB: will deepcopy lua values +/// currently, use upvalues to send lua references in and out. +Object nvim_buf_call(Buffer buffer, LuaRef fun, Error *err) + FUNC_API_SINCE(7) + FUNC_API_LUA_ONLY +{ + buf_T *buf = find_buffer_by_handle(buffer, err); + if (!buf) { + return NIL; + } + try_start(); + aco_save_T aco; + aucmd_prepbuf(&aco, (buf_T *)buf); + + Array args = ARRAY_DICT_INIT; + Object res = nlua_call_ref(fun, NULL, args, true, err); + + aucmd_restbuf(&aco); + try_end(err); + return res; +} + Dictionary nvim__buf_stats(Buffer buffer, Error *err) { Dictionary rv = ARRAY_DICT_INIT; diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index a9e8ca9686..61447f1152 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -1330,4 +1330,29 @@ describe('lua stdlib', function() eq(false, pcall_result) end) end) + + describe('vim.api.nvim_buf_call', function() + it('can access buf options', function() + local buf1 = meths.get_current_buf() + local buf2 = exec_lua [[ + buf2 = vim.api.nvim_create_buf(false, true) + return buf2 + ]] + + eq(false, meths.buf_get_option(buf1, 'autoindent')) + eq(false, meths.buf_get_option(buf2, 'autoindent')) + + local val = exec_lua [[ + return vim.api.nvim_buf_call(buf2, function() + vim.cmd "set autoindent" + return vim.api.nvim_get_current_buf() + end) + ]] + + eq(false, meths.buf_get_option(buf1, 'autoindent')) + eq(true, meths.buf_get_option(buf2, 'autoindent')) + eq(buf1, meths.get_current_buf()) + eq(buf2, val) + end) + end) end) |