diff options
author | Björn Linse <bjorn.linse@gmail.com> | 2016-10-22 12:50:50 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-10-22 12:50:50 +0200 |
commit | 31df051ed9a3f8cc9ad7a4e408e3ba03a1c5272b (patch) | |
tree | 5e62dbb09dc5d02818d2a080b08af2168f306f8b /src/nvim/api/vim.c | |
parent | e9041862776715cfb24e29fb7f18fa0830bd5555 (diff) | |
parent | f6968dc0f7775591108aebbfe30e597dd0882c91 (diff) | |
download | rneovim-31df051ed9a3f8cc9ad7a4e408e3ba03a1c5272b.tar.gz rneovim-31df051ed9a3f8cc9ad7a4e408e3ba03a1c5272b.tar.bz2 rneovim-31df051ed9a3f8cc9ad7a4e408e3ba03a1c5272b.zip |
Merge pull request #4568 from bfredl/multirequest
atomic multi request for async remote plugins
Diffstat (limited to 'src/nvim/api/vim.c')
-rw-r--r-- | src/nvim/api/vim.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index d8cdad961b..9f3a84c88b 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -663,6 +663,95 @@ Array nvim_get_api_info(uint64_t channel_id) return rv; } +/// Call many api methods atomically +/// +/// This has two main usages: Firstly, to perform several requests from an +/// async context atomically, i.e. without processing requests from other rpc +/// clients or redrawing or allowing user interaction in between. Note that api +/// methods that could fire autocommands or do event processing still might do +/// so. For instance invoking the :sleep command might call timer callbacks. +/// Secondly, it can be used to reduce rpc overhead (roundtrips) when doing +/// many requests in sequence. +/// +/// @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 Details of a validation error of the nvim_multi_request call +/// itself, i e malformatted `calls` parameter. Errors from called methods will +/// be indicated in the return value, see below. +/// +/// @return an array with 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 ocurred, the values from all preceding calls will still be returned. +Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err) + FUNC_API_NOEVAL +{ + Array rv = ARRAY_DICT_INIT; + Array results = ARRAY_DICT_INIT; + Error nested_error = ERROR_INIT; + + size_t i; // also used for freeing the variables + for (i = 0; i < calls.size; i++) { + if (calls.items[i].type != kObjectTypeArray) { + api_set_error(err, + Validation, + _("All items in calls array must be arrays")); + goto validation_error; + } + Array call = calls.items[i].data.array; + if (call.size != 2) { + api_set_error(err, + Validation, + _("All items in calls array must be arrays of size 2")); + goto validation_error; + } + + if (call.items[0].type != kObjectTypeString) { + api_set_error(err, + Validation, + _("name must be String")); + goto validation_error; + } + String name = call.items[0].data.string; + + if (call.items[1].type != kObjectTypeArray) { + api_set_error(err, + Validation, + _("args must be Array")); + goto validation_error; + } + Array args = call.items[1].data.array; + + MsgpackRpcRequestHandler handler = msgpack_rpc_get_handler_for(name.data, + name.size); + Object result = handler.fn(channel_id, args, &nested_error); + if (nested_error.set) { + // error handled after loop + break; + } + + ADD(results, result); + } + + ADD(rv, ARRAY_OBJ(results)); + if (nested_error.set) { + Array errval = ARRAY_DICT_INIT; + ADD(errval, INTEGER_OBJ((Integer)i)); + ADD(errval, INTEGER_OBJ(nested_error.type)); + ADD(errval, STRING_OBJ(cstr_to_string(nested_error.msg))); + ADD(rv, ARRAY_OBJ(errval)); + } else { + ADD(rv, NIL); + } + return rv; + +validation_error: + api_free_array(results); + 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. |