diff options
Diffstat (limited to 'src/nvim/api/vim.c')
-rw-r--r-- | src/nvim/api/vim.c | 373 |
1 files changed, 260 insertions, 113 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 413456c615..f4ccf07bec 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <stdint.h> #include <inttypes.h> @@ -10,8 +13,10 @@ #include "nvim/ascii.h" #include "nvim/api/private/helpers.h" #include "nvim/api/private/defs.h" +#include "nvim/api/private/dispatch.h" #include "nvim/api/buffer.h" #include "nvim/msgpack_rpc/channel.h" +#include "nvim/lua/executor.h" #include "nvim/vim.h" #include "nvim/buffer.h" #include "nvim/file_search.h" @@ -22,7 +27,9 @@ #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/eval.h" +#include "nvim/eval/typval.h" #include "nvim/option.h" +#include "nvim/state.h" #include "nvim/syntax.h" #include "nvim/getchar.h" #include "nvim/os/input.h" @@ -39,7 +46,7 @@ /// @param command Ex-command string /// @param[out] err Error details (including actual VimL error), if any void nvim_command(String command, Error *err) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { // Run the command try_start(); @@ -48,6 +55,48 @@ void nvim_command(String command, Error *err) try_end(err); } +/// Gets a highlight definition by name. +/// +/// @param name Highlight group name +/// @param rgb Export RGB colors +/// @param[out] err Error details, if any +/// @return Highlight definition map +/// @see nvim_get_hl_by_id +Dictionary nvim_get_hl_by_name(String name, Boolean rgb, Error *err) + FUNC_API_SINCE(3) +{ + Dictionary result = ARRAY_DICT_INIT; + int id = syn_name2id((const char_u *)name.data); + + if (id == 0) { + api_set_error(err, kErrorTypeException, "Invalid highlight name: %s", + name.data); + return result; + } + result = nvim_get_hl_by_id(id, rgb, err); + return result; +} + +/// Gets a highlight definition by id. |hlID()| +/// +/// @param hl_id Highlight id as returned by |hlID()| +/// @param rgb Export RGB colors +/// @param[out] err Error details, if any +/// @return Highlight definition map +/// @see nvim_get_hl_by_name +Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Error *err) + FUNC_API_SINCE(3) +{ + Dictionary dic = ARRAY_DICT_INIT; + if (syn_get_final_id((int)hl_id) == 0) { + api_set_error(err, kErrorTypeException, + "Invalid highlight id: %" PRId64, hl_id); + return dic; + } + int attrcode = syn_id2attr((int)hl_id); + return hl_get_attr_by_id(attrcode, rgb, err); +} + /// Passes input keys to Nvim. /// On VimL error: Does not fail, but updates v:errmsg. /// @@ -57,7 +106,7 @@ void nvim_command(String command, Error *err) /// @see feedkeys() /// @see vim_strsave_escape_csi void nvim_feedkeys(String keys, String mode, Boolean escape_csi) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { bool remap = true; bool insert = false; @@ -118,51 +167,53 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi) /// On VimL error: Does not fail, but updates v:errmsg. /// /// Unlike `nvim_feedkeys`, this uses a lower-level input buffer and the call -/// is not deferred. This is the most reliable way to emulate real user input. +/// is not deferred. This is the most reliable way to send real user input. +/// +/// @note |keycodes| like <CR> are translated, so "<" is special. +/// To input a literal "<", send <LT>. /// /// @param keys to be typed /// @return Number of bytes actually written (can be fewer than /// requested if the buffer becomes full). Integer nvim_input(String keys) - FUNC_API_SINCE(1) FUNC_API_ASYNC + FUNC_API_SINCE(1) FUNC_API_ASYNC { return (Integer)input_enqueue(keys); } -/// Replaces any terminal codes with the internal representation +/// Replaces terminal codes and |keycodes| (<CR>, <Esc>, ...) in a string with +/// the internal representation. /// +/// @param str String to be converted. +/// @param from_part Legacy Vim parameter. Usually true. +/// @param do_lt Also translate <lt>. Ignored if `special` is false. +/// @param special Replace |keycodes|, e.g. <CR> becomes a "\n" char. /// @see replace_termcodes /// @see cpoptions String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Boolean special) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { if (str.size == 0) { // Empty string - return str; + return (String) { .data = NULL, .size = 0 }; } char *ptr = NULL; - // Set 'cpoptions' the way we want it. - // FLAG_CPO_BSLASH set - backslashes are *not* treated specially - // FLAG_CPO_KEYCODE set - keycodes are *not* reverse-engineered - // FLAG_CPO_SPECI unset - <Key> sequences *are* interpreted - // The third from end parameter of replace_termcodes() is true so that the - // <lt> sequence is recognised - needed for a real backslash. replace_termcodes((char_u *)str.data, str.size, (char_u **)&ptr, from_part, do_lt, special, CPO_TO_CPO_FLAGS); return cstr_as_string(ptr); } String nvim_command_output(String str, Error *err) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { do_cmdline_cmd("redir => v:command_output"); nvim_command(str, err); do_cmdline_cmd("redir END"); - if (err->set) { - return (String) STRING_INIT; + if (ERROR_SET(err)) { + return (String)STRING_INIT; } return cstr_to_string((char *)get_vim_var_str(VV_COMMAND_OUTPUT)); @@ -176,28 +227,30 @@ String nvim_command_output(String str, Error *err) /// @param[out] err Error details, if any /// @return Evaluation result or expanded object Object nvim_eval(String expr, Error *err) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { Object rv = OBJECT_INIT; // Evaluate the expression try_start(); - typval_T *expr_result = eval_expr((char_u *)expr.data, NULL); - if (!expr_result) { - api_set_error(err, Exception, _("Failed to evaluate expression")); + typval_T rettv; + if (eval0((char_u *)expr.data, &rettv, NULL, true) == FAIL) { + api_set_error(err, kErrorTypeException, "Failed to evaluate expression"); } if (!try_end(err)) { // No errors, convert the result - rv = vim_to_object(expr_result); + rv = vim_to_object(&rettv); } - // Free the vim object - free_tv(expr_result); + // Free the Vim object + tv_clear(&rettv); + return rv; } -/// Calls a VimL function with the given arguments. +/// Calls a VimL function with the given arguments +/// /// On VimL error: Returns a generic error; v:errmsg is not updated. /// /// @param fname Function to call @@ -205,12 +258,12 @@ Object nvim_eval(String expr, Error *err) /// @param[out] err Error details, if any /// @return Result of the function call Object nvim_call_function(String fname, Array args, Error *err) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { Object rv = OBJECT_INIT; if (args.size > MAX_FUNC_ARGS) { - api_set_error(err, Validation, - _("Function called with too many arguments.")); + api_set_error(err, kErrorTypeValidation, + "Function called with too many arguments."); return rv; } @@ -232,46 +285,64 @@ Object nvim_call_function(String fname, Array args, Error *err) curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy, true, NULL, NULL); if (r == FAIL) { - api_set_error(err, Exception, _("Error calling function.")); + api_set_error(err, kErrorTypeException, "Error calling function."); } if (!try_end(err)) { rv = vim_to_object(&rettv); } - clear_tv(&rettv); + tv_clear(&rettv); free_vim_args: while (i > 0) { - clear_tv(&vim_args[--i]); + tv_clear(&vim_args[--i]); } return rv; } +/// Execute lua code. Parameters (if any) are available as `...` inside the +/// chunk. The chunk can return a value. +/// +/// Only statements are executed. To evaluate an expression, prefix it +/// with `return`: return my_function(...) +/// +/// @param code lua code to execute +/// @param args Arguments to the code +/// @param[out] err Details of an error encountered while parsing +/// or executing the lua code. +/// +/// @return Return value of lua code if present or NIL. +Object nvim_execute_lua(String code, Array args, Error *err) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY +{ + return executor_exec_lua_api(code, args, err); +} + /// Calculates the number of display cells occupied by `text`. /// <Tab> counts as one cell. /// /// @param text Some text /// @param[out] err Error details, if any /// @return Number of cells -Integer nvim_strwidth(String str, Error *err) - FUNC_API_SINCE(1) +Integer nvim_strwidth(String text, Error *err) + FUNC_API_SINCE(1) { - if (str.size > INT_MAX) { - api_set_error(err, Validation, _("String length is too high")); + if (text.size > INT_MAX) { + api_set_error(err, kErrorTypeValidation, "String length is too high"); return 0; } - return (Integer) mb_string2cells((char_u *) str.data); + return (Integer)mb_string2cells((char_u *)text.data); } /// Gets the paths contained in 'runtimepath'. /// /// @return List of paths ArrayOf(String) nvim_list_runtime_paths(void) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; - uint8_t *rtp = p_rtp; + char_u *rtp = p_rtp; if (*rtp == NUL) { // No paths @@ -285,13 +356,14 @@ ArrayOf(String) nvim_list_runtime_paths(void) } rtp++; } + rv.size++; // Allocate memory for the copies - rv.items = xmalloc(sizeof(Object) * rv.size); + rv.items = xmalloc(sizeof(*rv.items) * rv.size); // Reset the position rtp = p_rtp; // Start copying - for (size_t i = 0; i < rv.size && *rtp != NUL; i++) { + for (size_t i = 0; i < rv.size; i++) { rv.items[i].type = kObjectTypeString; rv.items[i].data.string.data = xmalloc(MAXPATHL); // Copy the path from 'runtimepath' to rv.items[i] @@ -310,10 +382,10 @@ ArrayOf(String) nvim_list_runtime_paths(void) /// @param dir Directory path /// @param[out] err Error details, if any void nvim_set_current_dir(String dir, Error *err) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { if (dir.size >= MAXPATHL) { - api_set_error(err, Validation, _("Directory string is too long")); + api_set_error(err, kErrorTypeValidation, "Directory string is too long"); return; } @@ -325,7 +397,7 @@ void nvim_set_current_dir(String dir, Error *err) if (vim_chdir((char_u *)string, kCdScopeGlobal)) { if (!try_end(err)) { - api_set_error(err, Exception, _("Failed to change directory")); + api_set_error(err, kErrorTypeException, "Failed to change directory"); } return; } @@ -339,7 +411,7 @@ void nvim_set_current_dir(String dir, Error *err) /// @param[out] err Error details, if any /// @return Current line string String nvim_get_current_line(Error *err) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { return buffer_get_line(curbuf->handle, curwin->w_cursor.lnum - 1, err); } @@ -349,7 +421,7 @@ String nvim_get_current_line(Error *err) /// @param line Line contents /// @param[out] err Error details, if any void nvim_set_current_line(String line, Error *err) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { buffer_set_line(curbuf->handle, curwin->w_cursor.lnum - 1, line, err); } @@ -358,7 +430,7 @@ void nvim_set_current_line(String line, Error *err) /// /// @param[out] err Error details, if any void nvim_del_current_line(Error *err) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { buffer_del_line(curbuf->handle, curwin->w_cursor.lnum - 1, err); } @@ -369,7 +441,7 @@ void nvim_del_current_line(Error *err) /// @param[out] err Error details, if any /// @return Variable value Object nvim_get_var(String name, Error *err) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { return dict_get_value(&globvardict, name, err); } @@ -380,7 +452,7 @@ Object nvim_get_var(String name, Error *err) /// @param value Variable value /// @param[out] err Error details, if any void nvim_set_var(String name, Object value, Error *err) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { dict_set_var(&globvardict, name, value, false, false, err); } @@ -390,34 +462,23 @@ void nvim_set_var(String name, Object value, Error *err) /// @param name Variable name /// @param[out] err Error details, if any void nvim_del_var(String name, Error *err) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { dict_set_var(&globvardict, name, NIL, true, false, err); } -/// Sets a global variable -/// /// @deprecated -/// -/// @param name Variable name -/// @param value Variable value -/// @param[out] err Error details, if any +/// @see nvim_set_var /// @return Old value or nil if there was no previous value. -/// -/// @warning It may return nil if there was no previous value -/// or if previous value was `v:null`. +/// @warning May return nil if there was no previous value +/// OR if previous value was `v:null`. Object vim_set_var(String name, Object value, Error *err) { return dict_set_var(&globvardict, name, value, false, true, err); } -/// Removes a global variable -/// /// @deprecated -/// -/// @param name Variable name -/// @param[out] err Error details, if any -/// @return Old value +/// @see nvim_del_var Object vim_del_var(String name, Error *err) { return dict_set_var(&globvardict, name, NIL, true, true, err); @@ -429,7 +490,7 @@ Object vim_del_var(String name, Error *err) /// @param[out] err Error details, if any /// @return Variable value Object nvim_get_vvar(String name, Error *err) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { return dict_get_value(&vimvardict, name, err); } @@ -438,9 +499,9 @@ Object nvim_get_vvar(String name, Error *err) /// /// @param name Option name /// @param[out] err Error details, if any -/// @return Option value +/// @return Option value (global) Object nvim_get_option(String name, Error *err) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { return get_option_from(NULL, SREQ_GLOBAL, name, err); } @@ -451,36 +512,38 @@ Object nvim_get_option(String name, Error *err) /// @param value New option value /// @param[out] err Error details, if any void nvim_set_option(String name, Object value, Error *err) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { set_option_to(NULL, SREQ_GLOBAL, name, value, err); } -/// Writes a message to vim output buffer +/// Writes a message to the Vim output buffer. Does not append "\n", the +/// message is buffered (won't display) until a linefeed is written. /// /// @param str Message void nvim_out_write(String str) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { write_msg(str, false); } -/// Writes a message to vim error buffer +/// Writes a message to the Vim error buffer. Does not append "\n", the +/// message is buffered (won't display) until a linefeed is written. /// /// @param str Message void nvim_err_write(String str) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { write_msg(str, true); } -/// Writes a message to vim error buffer. Appends a linefeed to ensure all -/// contents are written. +/// Writes a message to the Vim error buffer. Appends "\n", so the buffer is +/// flushed (and displayed). /// /// @param str Message /// @see nvim_err_write() void nvim_err_writeln(String str) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { nvim_err_write(str); nvim_err_write((String) { .data = "\n", .size = 1 }); @@ -490,7 +553,7 @@ void nvim_err_writeln(String str) /// /// @return List of buffer handles ArrayOf(Buffer) nvim_list_bufs(void) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; @@ -512,17 +575,17 @@ ArrayOf(Buffer) nvim_list_bufs(void) /// /// @return Buffer handle Buffer nvim_get_current_buf(void) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { return curbuf->handle; } /// Sets the current buffer /// -/// @param id Buffer handle +/// @param buffer Buffer handle /// @param[out] err Error details, if any void nvim_set_current_buf(Buffer buffer, Error *err) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -534,8 +597,8 @@ void nvim_set_current_buf(Buffer buffer, Error *err) int result = do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, buf->b_fnum, 0); if (!try_end(err) && result == FAIL) { api_set_error(err, - Exception, - _("Failed to switch to buffer %d"), + kErrorTypeException, + "Failed to switch to buffer %d", buffer); } } @@ -544,7 +607,7 @@ void nvim_set_current_buf(Buffer buffer, Error *err) /// /// @return List of window handles ArrayOf(Window) nvim_list_wins(void) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; @@ -566,16 +629,16 @@ ArrayOf(Window) nvim_list_wins(void) /// /// @return Window handle Window nvim_get_current_win(void) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { return curwin->handle; } /// Sets the current window /// -/// @param handle Window handle +/// @param window Window handle void nvim_set_current_win(Window window, Error *err) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -587,8 +650,8 @@ void nvim_set_current_win(Window window, Error *err) goto_tabpage_win(win_find_tabpage(win), win); if (!try_end(err) && win != curwin) { api_set_error(err, - Exception, - _("Failed to switch to window %d"), + kErrorTypeException, + "Failed to switch to window %d", window); } } @@ -597,7 +660,7 @@ void nvim_set_current_win(Window window, Error *err) /// /// @return List of tabpage handles ArrayOf(Tabpage) nvim_list_tabpages(void) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; @@ -619,17 +682,17 @@ ArrayOf(Tabpage) nvim_list_tabpages(void) /// /// @return Tabpage handle Tabpage nvim_get_current_tabpage(void) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { return curtab->handle; } /// Sets the current tabpage /// -/// @param handle Tabpage handle +/// @param tabpage Tabpage handle /// @param[out] err Error details, if any void nvim_set_current_tabpage(Tabpage tabpage, Error *err) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { tabpage_T *tp = find_tab_by_handle(tabpage, err); @@ -641,8 +704,8 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err) goto_tabpage_tp(tp, true, true); if (!try_end(err) && tp != curtab) { api_set_error(err, - Exception, - _("Failed to switch to tabpage %d"), + kErrorTypeException, + "Failed to switch to tabpage %d", tabpage); } } @@ -652,13 +715,13 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err) /// @param channel_id Channel id (passed automatically by the dispatcher) /// @param event Event type string void nvim_subscribe(uint64_t channel_id, String event) - FUNC_API_SINCE(1) FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { size_t length = (event.size < METHOD_MAXLEN ? event.size : METHOD_MAXLEN); char e[METHOD_MAXLEN + 1]; memcpy(e, event.data, length); e[length] = NUL; - channel_subscribe(channel_id, e); + rpc_subscribe(channel_id, e); } /// Unsubscribes to event broadcasts @@ -666,7 +729,7 @@ void nvim_subscribe(uint64_t channel_id, String event) /// @param channel_id Channel id (passed automatically by the dispatcher) /// @param event Event type string void nvim_unsubscribe(uint64_t channel_id, String event) - FUNC_API_SINCE(1) FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { size_t length = (event.size < METHOD_MAXLEN ? event.size : @@ -674,17 +737,17 @@ void nvim_unsubscribe(uint64_t channel_id, String event) char e[METHOD_MAXLEN + 1]; memcpy(e, event.data, length); e[length] = NUL; - channel_unsubscribe(channel_id, e); + rpc_unsubscribe(channel_id, e); } Integer nvim_get_color_by_name(String name) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { - return name_to_color((uint8_t *)name.data); + return name_to_color((char_u *)name.data); } Dictionary nvim_get_color_map(void) - FUNC_API_SINCE(1) + FUNC_API_SINCE(1) { Dictionary colors = ARRAY_DICT_INIT; @@ -696,8 +759,36 @@ Dictionary nvim_get_color_map(void) } +/// Gets the current mode. |mode()| +/// "blocking" is true if Nvim is waiting for input. +/// +/// @returns Dictionary { "mode": String, "blocking": Boolean } +Dictionary nvim_get_mode(void) + FUNC_API_SINCE(2) FUNC_API_ASYNC +{ + Dictionary rv = ARRAY_DICT_INIT; + char *modestr = get_mode(); + bool blocked = input_blocking(); + + PUT(rv, "mode", STRING_OBJ(cstr_as_string(modestr))); + PUT(rv, "blocking", BOOLEAN_OBJ(blocked)); + + return rv; +} + +/// Gets a list of dictionaries describing global (non-buffer) mappings. +/// The "buffer" key in the returned dictionary is always zero. +/// +/// @param mode Mode short-name ("n", "i", "v", ...) +/// @returns Array of maparg()-like dictionaries describing mappings +ArrayOf(Dictionary) nvim_get_keymap(String mode) + FUNC_API_SINCE(3) +{ + return keymap_array(mode, NULL); +} + Array nvim_get_api_info(uint64_t channel_id) - FUNC_API_SINCE(1) FUNC_API_ASYNC FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_ASYNC FUNC_API_REMOTE_ONLY { Array rv = ARRAY_DICT_INIT; @@ -730,7 +821,7 @@ Array nvim_get_api_info(uint64_t channel_id) /// 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_SINCE(1) FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { Array rv = ARRAY_DICT_INIT; Array results = ARRAY_DICT_INIT; @@ -740,30 +831,30 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err) 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")); + kErrorTypeValidation, + "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")); + kErrorTypeValidation, + "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")); + kErrorTypeValidation, + "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")); + kErrorTypeValidation, + "Args must be Array"); goto validation_error; } Array args = call.items[1].data.array; @@ -771,7 +862,7 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err) MsgpackRpcRequestHandler handler = msgpack_rpc_get_handler_for(name.data, name.size); Object result = handler.fn(channel_id, args, &nested_error); - if (nested_error.set) { + if (ERROR_SET(&nested_error)) { // error handled after loop break; } @@ -780,7 +871,7 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err) } ADD(rv, ARRAY_OBJ(results)); - if (nested_error.set) { + if (ERROR_SET(&nested_error)) { Array errval = ARRAY_DICT_INIT; ADD(errval, INTEGER_OBJ((Integer)i)); ADD(errval, INTEGER_OBJ(nested_error.type)); @@ -789,10 +880,12 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err) } else { ADD(rv, NIL); } - return rv; + goto theend; validation_error: api_free_array(results); +theend: + api_clear_error(&nested_error); return rv; } @@ -811,7 +904,7 @@ static void write_msg(String message, bool to_err) #define PUSH_CHAR(i, pos, line_buf, msg) \ if (message.data[i] == NL || pos == LINE_BUFFER_SIZE - 1) { \ line_buf[pos] = NUL; \ - msg((uint8_t *)line_buf); \ + msg((char_u *)line_buf); \ pos = 0; \ continue; \ } \ @@ -829,3 +922,57 @@ static void write_msg(String message, bool to_err) --no_wait_return; msg_end(); } + +// Functions used for testing purposes + +/// Returns object given as argument +/// +/// This API function is used for testing. One should not rely on its presence +/// in plugins. +/// +/// @param[in] obj Object to return. +/// +/// @return its argument. +Object nvim__id(Object obj) +{ + return copy_object(obj); +} + +/// Returns array given as argument +/// +/// This API function is used for testing. One should not rely on its presence +/// in plugins. +/// +/// @param[in] arr Array to return. +/// +/// @return its argument. +Array nvim__id_array(Array arr) +{ + return copy_object(ARRAY_OBJ(arr)).data.array; +} + +/// Returns dictionary given as argument +/// +/// This API function is used for testing. One should not rely on its presence +/// in plugins. +/// +/// @param[in] dct Dictionary to return. +/// +/// @return its argument. +Dictionary nvim__id_dictionary(Dictionary dct) +{ + return copy_object(DICTIONARY_OBJ(dct)).data.dictionary; +} + +/// Returns floating-point value given as argument +/// +/// This API function is used for testing. One should not rely on its presence +/// in plugins. +/// +/// @param[in] flt Value to return. +/// +/// @return its argument. +Float nvim__id_float(Float flt) +{ + return flt; +} |