diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2024-04-22 04:28:16 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-22 04:28:16 -0700 |
commit | fb5e2db4c72251ac8f59a7b80fc6d6b40dbec1d8 (patch) | |
tree | 99f8e8ddae86681814a47bb2ab4d7ccbe9ead8d3 | |
parent | 013afc6863b0bed401e1d9e70cb861ee347b158f (diff) | |
download | rneovim-fb5e2db4c72251ac8f59a7b80fc6d6b40dbec1d8.tar.gz rneovim-fb5e2db4c72251ac8f59a7b80fc6d6b40dbec1d8.tar.bz2 rneovim-fb5e2db4c72251ac8f59a7b80fc6d6b40dbec1d8.zip |
refactor(api): deprecate nvim_call_atomic #28433
TODO:
FUNC_API_REMOTE_ONLY APIs such as `nvim_ui_*` cannot (yet) be used in
`nvim_exec_lua`. We can change FUNC_API_REMOTE_ONLY to allow
Vimscript/Lua to pass an explicit `channel_id`. #28437
-rw-r--r-- | runtime/doc/api.txt | 27 | ||||
-rw-r--r-- | runtime/doc/deprecated.txt | 1 | ||||
-rw-r--r-- | runtime/doc/news.txt | 1 | ||||
-rw-r--r-- | src/nvim/api/deprecated.c | 89 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 84 |
5 files changed, 91 insertions, 111 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 91b80601da..cc5f228920 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -655,33 +655,6 @@ nvim__stats() *nvim__stats()* Return: ~ Map of various internal stats. -nvim_call_atomic({calls}) *nvim_call_atomic()* - Calls many API methods atomically. - - This has two main usages: - 1. To perform several requests from an async context atomically, i.e. - without interleaving redraws, RPC requests from other clients, or user - interactions (however API methods may trigger autocommands or event - processing which have such side effects, e.g. |:sleep| may wake - timers). - 2. To minimize RPC overhead (roundtrips) of a sequence of many requests. - - Attributes: ~ - |RPC| only - - Parameters: ~ - • {calls} an array of calls, where each call is described by an array - with two elements: the request name, and an array of - arguments. - - Return: ~ - Array of two elements. The first is an array of return values. The - second is NIL if all calls succeeded. If a call resulted in an error, - it is a three-element array with the zero-based index of the call - which resulted in an error, the error type and the error message. If - an error occurred, the values from all preceding calls will still be - returned. - nvim_chan_send({chan}, {data}) *nvim_chan_send()* Send data to channel `id`. For a job, it writes it to the stdin of the process. For the stdio channel |channel-stdio|, it writes to Nvim's diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index 834366f8ec..602b033ecc 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -16,6 +16,7 @@ API - *nvim_buf_clear_highlight()* Use |nvim_buf_clear_namespace()| instead. - *nvim_buf_set_virtual_text()* Use |nvim_buf_set_extmark()| instead. - *nvim_command_output()* Use |nvim_exec2()| instead. +- *nvim_call_atomic()* Use |nvim_exec_lua()| instead. - *nvim_execute_lua()* Use |nvim_exec_lua()| instead. - *nvim_get_hl_by_name()* Use |nvim_get_hl()| instead. - *nvim_get_hl_by_id()* Use |nvim_get_hl()| instead. diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 1247e56fb5..39a99a61d1 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -533,6 +533,7 @@ release. • |API| functions: - |nvim_buf_get_option()| Use |nvim_get_option_value()| instead. - |nvim_buf_set_option()| Use |nvim_set_option_value()| instead. + - nvim_call_atomic() Use |nvim_exec_lua()| instead. - |nvim_get_option()| Use |nvim_get_option_value()| instead. - |nvim_set_option()| Use |nvim_set_option_value()| instead. - |nvim_win_get_option()| Use |nvim_get_option_value()| instead. diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c index 6254e9fbd8..d63b8411e8 100644 --- a/src/nvim/api/deprecated.c +++ b/src/nvim/api/deprecated.c @@ -20,6 +20,9 @@ #include "nvim/lua/executor.h" #include "nvim/memory.h" #include "nvim/memory_defs.h" +#include "nvim/msgpack_rpc/channel.h" +#include "nvim/msgpack_rpc/channel_defs.h" +#include "nvim/msgpack_rpc/unpacker.h" #include "nvim/option.h" #include "nvim/option_defs.h" #include "nvim/pos_defs.h" @@ -697,3 +700,89 @@ static void set_option_to(uint64_t channel_id, void *to, OptReqScope req_scope, set_option_value_for(name.data, opt_idx, optval, opt_flags, req_scope, to, err); }); } + +/// @deprecated Use nvim_exec_lua() instead. +/// +/// Calls many API methods atomically. +/// +/// This has two main usages: +/// 1. To perform several requests from an async context atomically, i.e. +/// without interleaving redraws, RPC requests from other clients, or user +/// interactions (however API methods may trigger autocommands or event +/// processing which have such side effects, e.g. |:sleep| may wake timers). +/// 2. To minimize RPC overhead (roundtrips) of a sequence of many requests. +/// +/// @param channel_id +/// @param calls an array of calls, where each call is described by an array +/// with two elements: the request name, and an array of arguments. +/// @param[out] err Validation error details (malformed `calls` parameter), +/// if any. Errors from batched calls are given in the return value. +/// +/// @return Array of two elements. The first is an array of return +/// values. The second is NIL if all calls succeeded. If a call resulted in +/// an error, it is a three-element array with the zero-based index of the call +/// which resulted in an error, the error type and the error message. If an +/// error occurred, the values from all preceding calls will still be returned. +Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *err) + FUNC_API_SINCE(1) FUNC_API_DEPRECATED_SINCE(12) FUNC_API_REMOTE_ONLY +{ + Array rv = arena_array(arena, 2); + Array results = arena_array(arena, calls.size); + Error nested_error = ERROR_INIT; + + size_t i; // also used for freeing the variables + for (i = 0; i < calls.size; i++) { + VALIDATE_T("'calls' item", kObjectTypeArray, calls.items[i].type, { + goto theend; + }); + Array call = calls.items[i].data.array; + VALIDATE_EXP((call.size == 2), "'calls' item", "2-item Array", NULL, { + goto theend; + }); + VALIDATE_T("name", kObjectTypeString, call.items[0].type, { + goto theend; + }); + String name = call.items[0].data.string; + VALIDATE_T("call args", kObjectTypeArray, call.items[1].type, { + goto theend; + }); + Array args = call.items[1].data.array; + + MsgpackRpcRequestHandler handler = + msgpack_rpc_get_handler_for(name.data, + name.size, + &nested_error); + + if (ERROR_SET(&nested_error)) { + break; + } + + Object result = handler.fn(channel_id, args, arena, &nested_error); + if (ERROR_SET(&nested_error)) { + // error handled after loop + break; + } + // TODO(bfredl): wasteful copy. It could be avoided to encoding to msgpack + // directly here. But `result` might become invalid when next api function + // is called in the loop. + ADD_C(results, copy_object(result, arena)); + if (handler.ret_alloc) { + api_free_object(result); + } + } + + ADD_C(rv, ARRAY_OBJ(results)); + if (ERROR_SET(&nested_error)) { + Array errval = arena_array(arena, 3); + ADD_C(errval, INTEGER_OBJ((Integer)i)); + ADD_C(errval, INTEGER_OBJ(nested_error.type)); + ADD_C(errval, STRING_OBJ(copy_string(cstr_as_string(nested_error.msg), arena))); + ADD_C(rv, ARRAY_OBJ(errval)); + } else { + ADD_C(rv, NIL); + } + +theend: + api_clear_error(&nested_error); + return rv; +} diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 82e9ddff2d..d62ea46e1b 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1698,90 +1698,6 @@ Array nvim_list_chans(Arena *arena) return channel_all_info(arena); } -/// Calls many API methods atomically. -/// -/// This has two main usages: -/// 1. To perform several requests from an async context atomically, i.e. -/// without interleaving redraws, RPC requests from other clients, or user -/// interactions (however API methods may trigger autocommands or event -/// processing which have such side effects, e.g. |:sleep| may wake timers). -/// 2. To minimize RPC overhead (roundtrips) of a sequence of many requests. -/// -/// @param channel_id -/// @param calls an array of calls, where each call is described by an array -/// with two elements: the request name, and an array of arguments. -/// @param[out] err Validation error details (malformed `calls` parameter), -/// if any. Errors from batched calls are given in the return value. -/// -/// @return Array of two elements. The first is an array of return -/// values. The second is NIL if all calls succeeded. If a call resulted in -/// an error, it is a three-element array with the zero-based index of the call -/// which resulted in an error, the error type and the error message. If an -/// error occurred, the values from all preceding calls will still be returned. -Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *err) - FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY -{ - Array rv = arena_array(arena, 2); - Array results = arena_array(arena, calls.size); - Error nested_error = ERROR_INIT; - - size_t i; // also used for freeing the variables - for (i = 0; i < calls.size; i++) { - VALIDATE_T("'calls' item", kObjectTypeArray, calls.items[i].type, { - goto theend; - }); - Array call = calls.items[i].data.array; - VALIDATE_EXP((call.size == 2), "'calls' item", "2-item Array", NULL, { - goto theend; - }); - VALIDATE_T("name", kObjectTypeString, call.items[0].type, { - goto theend; - }); - String name = call.items[0].data.string; - VALIDATE_T("call args", kObjectTypeArray, call.items[1].type, { - goto theend; - }); - Array args = call.items[1].data.array; - - MsgpackRpcRequestHandler handler = - msgpack_rpc_get_handler_for(name.data, - name.size, - &nested_error); - - if (ERROR_SET(&nested_error)) { - break; - } - - Object result = handler.fn(channel_id, args, arena, &nested_error); - if (ERROR_SET(&nested_error)) { - // error handled after loop - break; - } - // TODO(bfredl): wasteful copy. It could be avoided to encoding to msgpack - // directly here. But `result` might become invalid when next api function - // is called in the loop. - ADD_C(results, copy_object(result, arena)); - if (handler.ret_alloc) { - api_free_object(result); - } - } - - ADD_C(rv, ARRAY_OBJ(results)); - if (ERROR_SET(&nested_error)) { - Array errval = arena_array(arena, 3); - ADD_C(errval, INTEGER_OBJ((Integer)i)); - ADD_C(errval, INTEGER_OBJ(nested_error.type)); - ADD_C(errval, STRING_OBJ(copy_string(cstr_as_string(nested_error.msg), arena))); - ADD_C(rv, ARRAY_OBJ(errval)); - } else { - ADD_C(rv, NIL); - } - -theend: - api_clear_error(&nested_error); - return rv; -} - /// Writes a message to vim output or error buffer. The string is split /// and flushed after each newline. Incomplete lines are kept for writing /// later. |