diff options
Diffstat (limited to 'src/nvim/api/vim.c')
-rw-r--r-- | src/nvim/api/vim.c | 727 |
1 files changed, 331 insertions, 396 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 349cc0e7da..3be45d0cf7 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -3,54 +3,54 @@ #include <assert.h> #include <inttypes.h> +#include <limits.h> #include <stdbool.h> #include <stdlib.h> #include <string.h> -#include <limits.h> -#include "nvim/api/vim.h" -#include "nvim/ascii.h" -#include "nvim/api/private/helpers.h" +#include "nvim/api/buffer.h" +#include "nvim/api/deprecated.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/dispatch.h" -#include "nvim/api/buffer.h" +#include "nvim/api/private/helpers.h" +#include "nvim/api/vim.h" #include "nvim/api/window.h" -#include "nvim/api/deprecated.h" -#include "nvim/msgpack_rpc/channel.h" -#include "nvim/msgpack_rpc/helpers.h" -#include "nvim/lua/executor.h" -#include "nvim/vim.h" +#include "nvim/ascii.h" #include "nvim/buffer.h" #include "nvim/context.h" -#include "nvim/file_search.h" -#include "nvim/highlight.h" -#include "nvim/window.h" -#include "nvim/types.h" -#include "nvim/ex_cmds2.h" -#include "nvim/ex_docmd.h" -#include "nvim/screen.h" -#include "nvim/memline.h" -#include "nvim/mark.h" -#include "nvim/memory.h" -#include "nvim/message.h" -#include "nvim/popupmnu.h" +#include "nvim/decoration.h" #include "nvim/edit.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/userfunc.h" +#include "nvim/ex_cmds2.h" +#include "nvim/ex_docmd.h" +#include "nvim/file_search.h" #include "nvim/fileio.h" +#include "nvim/getchar.h" +#include "nvim/highlight.h" +#include "nvim/lua/executor.h" +#include "nvim/mark.h" +#include "nvim/memline.h" +#include "nvim/memory.h" +#include "nvim/message.h" #include "nvim/move.h" +#include "nvim/msgpack_rpc/channel.h" +#include "nvim/msgpack_rpc/helpers.h" #include "nvim/ops.h" #include "nvim/option.h" -#include "nvim/state.h" -#include "nvim/decoration.h" -#include "nvim/syntax.h" -#include "nvim/getchar.h" #include "nvim/os/input.h" #include "nvim/os/process.h" +#include "nvim/popupmnu.h" +#include "nvim/screen.h" +#include "nvim/state.h" +#include "nvim/syntax.h" +#include "nvim/types.h" +#include "nvim/ui.h" +#include "nvim/vim.h" #include "nvim/viml/parser/expressions.h" #include "nvim/viml/parser/parser.h" -#include "nvim/ui.h" +#include "nvim/window.h" #define LINE_BUFFER_SIZE 4096 @@ -58,22 +58,16 @@ # include "api/vim.c.generated.h" #endif -void api_vim_init(void) - FUNC_API_NOEXPORT -{ - namespace_ids = map_new(String, handle_T)(); -} - void api_vim_free_all_mem(void) FUNC_API_NOEXPORT { String name; handle_T id; - map_foreach(namespace_ids, name, id, { + map_foreach(&namespace_ids, name, id, { (void)id; xfree(name.data); }) - map_free(String, handle_T)(namespace_ids); + map_destroy(String, handle_T)(&namespace_ids); } /// Executes Vimscript (multiline block of Ex-commands), like anonymous @@ -217,7 +211,7 @@ Dictionary nvim__get_hl_defs(Integer ns_id, Error *err) /// /// @param ns_id number of namespace for this highlight /// @param name highlight group name, like ErrorMsg -/// @param val highlight definiton map, like |nvim_get_hl_by_name|. +/// @param val highlight definition map, like |nvim_get_hl_by_name|. /// in addition the following keys are also recognized: /// `default`: don't override existing definition, /// like `hi default` @@ -281,9 +275,9 @@ static void on_redraw_event(void **argv) /// /// On execution error: does not fail, but updates v:errmsg. /// -/// If you need to input sequences like <C-o> use |nvim_replace_termcodes| to -/// replace the termcodes and then pass the resulting string to nvim_feedkeys. -/// You'll also want to enable escape_csi. +/// To input sequences like <C-o> use |nvim_replace_termcodes()| (typically +/// with escape_csi=true) to replace |keycodes|, then pass the result to +/// nvim_feedkeys(). /// /// Example: /// <pre> @@ -307,12 +301,18 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi) for (size_t i = 0; i < mode.size; ++i) { switch (mode.data[i]) { - case 'n': remap = false; break; - case 'm': remap = true; break; - case 't': typed = true; break; - case 'i': insert = true; break; - case 'x': execute = true; break; - case '!': dangerous = true; break; + case 'n': + remap = false; break; + case 'm': + remap = true; break; + case 't': + typed = true; break; + case 'i': + insert = true; break; + case 'x': + execute = true; break; + case '!': + dangerous = true; break; } } @@ -322,11 +322,11 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi) char *keys_esc; if (escape_csi) { - // Need to escape K_SPECIAL and CSI before putting the string in the - // typeahead buffer. - keys_esc = (char *)vim_strsave_escape_csi((char_u *)keys.data); + // Need to escape K_SPECIAL and CSI before putting the string in the + // typeahead buffer. + keys_esc = (char *)vim_strsave_escape_csi((char_u *)keys.data); } else { - keys_esc = keys.data; + keys_esc = keys.data; } ins_typebuf((char_u *)keys_esc, (remap ? REMAP_YES : REMAP_NONE), insert ? 0 : typebuf.tb_len, !typed, false); @@ -335,7 +335,7 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi) } if (escape_csi) { - xfree(keys_esc); + xfree(keys_esc); } if (execute) { @@ -384,7 +384,7 @@ Integer nvim_input(String keys) /// by calling it multiple times in a loop: the intermediate mouse /// positions will be ignored. It should be used to implement real-time /// mouse input in a GUI. The deprecated pseudokey form -/// ("<LeftMouse><col,row>") of |nvim_input()| has the same limitiation. +/// ("<LeftMouse><col,row>") of |nvim_input()| has the same limitation. /// /// @param button Mouse button: one of "left", "right", "middle", "wheel". /// @param action For ordinary buttons, one of "press", "drag", "release". @@ -397,8 +397,8 @@ Integer nvim_input(String keys) /// @param row Mouse row-position (zero-based, like redraw events) /// @param col Mouse column-position (zero-based, like redraw events) /// @param[out] err Error details, if any -void nvim_input_mouse(String button, String action, String modifier, - Integer grid, Integer row, Integer col, Error *err) +void nvim_input_mouse(String button, String action, String modifier, Integer grid, Integer row, + Integer col, Error *err) FUNC_API_SINCE(6) FUNC_API_FAST { if (button.data == NULL || action.data == NULL) { @@ -475,8 +475,7 @@ error: /// @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) +String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Boolean special) FUNC_API_SINCE(1) { if (str.size == 0) { @@ -505,32 +504,32 @@ Object nvim_eval(String expr, Error *err) Object rv = OBJECT_INIT; TRY_WRAP({ - // Initialize `force_abort` and `suppress_errthrow` at the top level. - if (!recursive) { - force_abort = false; - suppress_errthrow = false; - current_exception = NULL; - // `did_emsg` is set by emsg(), which cancels execution. - did_emsg = false; - } - recursive++; - try_start(); + // Initialize `force_abort` and `suppress_errthrow` at the top level. + if (!recursive) { + force_abort = false; + suppress_errthrow = false; + current_exception = NULL; + // `did_emsg` is set by emsg(), which cancels execution. + did_emsg = false; + } + recursive++; + try_start(); - typval_T rettv; - int ok = eval0((char_u *)expr.data, &rettv, NULL, true); + typval_T rettv; + int ok = eval0((char_u *)expr.data, &rettv, NULL, true); - if (!try_end(err)) { - if (ok == FAIL) { - // Should never happen, try_end() should get the error. #8371 - api_set_error(err, kErrorTypeException, - "Failed to evaluate expression: '%.*s'", 256, expr.data); - } else { - rv = vim_to_object(&rettv); + if (!try_end(err)) { + if (ok == FAIL) { + // Should never happen, try_end() should get the error. #8371 + api_set_error(err, kErrorTypeException, + "Failed to evaluate expression: '%.*s'", 256, expr.data); + } else { + rv = vim_to_object(&rettv); + } } - } - tv_clear(&rettv); - recursive--; + tv_clear(&rettv); + recursive--; }); return rv; @@ -558,7 +557,7 @@ Object nvim_exec_lua(String code, Array args, Error *err) /// Notify the user with a message /// /// Relays the call to vim.notify . By default forwards your message in the -/// echo area but can be overriden to trigger desktop notifications. +/// echo area but can be overridden to trigger desktop notifications. /// /// @param msg Message to display to the user /// @param log_level The log level @@ -603,28 +602,31 @@ static Object _call_function(String fn, Array args, dict_T *self, Error *err) } TRY_WRAP({ - // Initialize `force_abort` and `suppress_errthrow` at the top level. - if (!recursive) { - force_abort = false; - suppress_errthrow = false; - current_exception = NULL; - // `did_emsg` is set by emsg(), which cancels execution. - did_emsg = false; - } - recursive++; - try_start(); - typval_T rettv; - int dummy; - // call_func() retval is deceptive, ignore it. Instead we set `msg_list` - // (see above) to capture abort-causing non-exception errors. - (void)call_func((char_u *)fn.data, (int)fn.size, &rettv, (int)args.size, - vim_args, NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum, - &dummy, true, NULL, self); - if (!try_end(err)) { - rv = vim_to_object(&rettv); - } - tv_clear(&rettv); - recursive--; + // Initialize `force_abort` and `suppress_errthrow` at the top level. + if (!recursive) { + force_abort = false; + suppress_errthrow = false; + current_exception = NULL; + // `did_emsg` is set by emsg(), which cancels execution. + did_emsg = false; + } + recursive++; + try_start(); + typval_T rettv; + funcexe_T funcexe = FUNCEXE_INIT; + funcexe.firstline = curwin->w_cursor.lnum; + funcexe.lastline = curwin->w_cursor.lnum; + funcexe.evaluate = true; + funcexe.selfdict = self; + // call_func() retval is deceptive, ignore it. Instead we set `msg_list` + // (see above) to capture abort-causing non-exception errors. + (void)call_func((char_u *)fn.data, (int)fn.size, &rettv, (int)args.size, + vim_args, &funcexe); + if (!try_end(err)) { + rv = vim_to_object(&rettv); + } + tv_clear(&rettv); + recursive--; }); free_vim_args: @@ -666,31 +668,28 @@ Object nvim_call_dict_function(Object dict, String fn, Array args, Error *err) typval_T rettv; bool mustfree = false; switch (dict.type) { - case kObjectTypeString: { - try_start(); - if (eval0((char_u *)dict.data.string.data, &rettv, NULL, true) == FAIL) { - api_set_error(err, kErrorTypeException, - "Failed to evaluate dict expression"); - } - if (try_end(err)) { - return rv; - } - // Evaluation of the string arg created a new dict or increased the - // refcount of a dict. Not necessary for a RPC dict. - mustfree = true; - break; - } - case kObjectTypeDictionary: { - if (!object_to_vim(dict, &rettv, err)) { - goto end; - } - break; + case kObjectTypeString: + try_start(); + if (eval0((char_u *)dict.data.string.data, &rettv, NULL, true) == FAIL) { + api_set_error(err, kErrorTypeException, + "Failed to evaluate dict expression"); } - default: { - api_set_error(err, kErrorTypeValidation, - "dict argument type must be String or Dictionary"); + if (try_end(err)) { return rv; } + // Evaluation of the string arg created a new dict or increased the + // refcount of a dict. Not necessary for a RPC dict. + mustfree = true; + break; + case kObjectTypeDictionary: + if (!object_to_vim(dict, &rettv, err)) { + goto end; + } + break; + default: + api_set_error(err, kErrorTypeValidation, + "dict argument type must be String or Dictionary"); + return rv; } dict_T *self_dict = rettv.vval.v_dict; if (rettv.v_type != VAR_DICT || !self_dict) { @@ -753,47 +752,10 @@ Integer nvim_strwidth(String text, Error *err) /// Gets the paths contained in 'runtimepath'. /// /// @return List of paths -ArrayOf(String) nvim_list_runtime_paths(void) +ArrayOf(String) nvim_list_runtime_paths(Error *err) FUNC_API_SINCE(1) { - // TODO(bfredl): this should just work: - // return nvim_get_runtime_file(NULL_STRING, true); - - Array rv = ARRAY_DICT_INIT; - - char_u *rtp = p_rtp; - - if (*rtp == NUL) { - // No paths - return rv; - } - - // Count the number of paths in rtp - while (*rtp != NUL) { - if (*rtp == ',') { - rv.size++; - } - rtp++; - } - rv.size++; - - // Allocate memory for the copies - rv.items = xmalloc(sizeof(*rv.items) * rv.size); - // Reset the position - rtp = p_rtp; - // Start copying - 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] - size_t length = copy_option_part(&rtp, - (char_u *)rv.items[i].data.string.data, - MAXPATHL, - ","); - rv.items[i].data.string.size = length; - } - - return rv; + return nvim_get_runtime_file(NULL_STRING, true, err); } /// Find files in runtime directories @@ -805,10 +767,6 @@ ArrayOf(String) nvim_list_runtime_paths(void) /// /// It is not an error to not find any files. An empty array is returned then. /// -/// To find a directory, `name` must end with a forward slash, like -/// "rplugin/python/". Without the slash it would instead look for an ordinary -/// file called "rplugin/python". -/// /// @param name pattern of files to search for /// @param all whether to return all matches or only the first /// @return list of absolute paths to the found files @@ -818,11 +776,7 @@ ArrayOf(String) nvim_get_runtime_file(String name, Boolean all, Error *err) { Array rv = ARRAY_DICT_INIT; - int flags = DIP_START | (all ? DIP_ALL : 0); - - if (name.size == 0 || name.data[name.size-1] == '/') { - flags |= DIP_DIR; - } + int flags = DIP_DIRFILE | (all ? DIP_ALL : 0); do_in_runtimepath((char_u *)(name.size ? name.data : ""), flags, find_runtime_cb, &rv); @@ -1260,7 +1214,7 @@ fail: /// /// By default (and currently the only option) the terminal will not be /// connected to an external process. Instead, input send on the channel -/// will be echoed directly by the terminal. This is useful to disply +/// will be echoed directly by the terminal. This is useful to display /// ANSI terminal sequences returned as part of a rpc message, or similar. /// /// Note: to directly initiate the terminal using the right size, display the @@ -1290,7 +1244,7 @@ Integer nvim_open_term(Buffer buffer, Dictionary opts, Error *err) TerminalOptions topts; Channel *chan = channel_alloc(kChannelStreamInternal); topts.data = chan; - // NB: overriden in terminal_check_size if a window is already + // NB: overridden in terminal_check_size if a window is already // displaying the buffer topts.width = (uint16_t)MAX(curwin->w_width_inner - win_col_off(curwin), 0); topts.height = (uint16_t)curwin->w_height_inner; @@ -1468,8 +1422,7 @@ void nvim_chan_send(Integer chan, String data, Error *err) /// @param[out] err Error details, if any /// /// @return Window handle, or 0 on error -Window nvim_open_win(Buffer buffer, Boolean enter, Dictionary config, - Error *err) +Window nvim_open_win(Buffer buffer, Boolean enter, Dictionary config, Error *err) FUNC_API_SINCE(6) FUNC_API_CHECK_TEXTLOCK { @@ -1554,10 +1507,10 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err) } } -/// Creates a new namespace, or gets an existing one. +/// Creates a new *namespace*, or gets an existing one. /// /// Namespaces are used for buffer highlights and virtual text, see -/// |nvim_buf_add_highlight()| and |nvim_buf_set_virtual_text()|. +/// |nvim_buf_add_highlight()| and |nvim_buf_set_extmark()|. /// /// Namespaces can be named or anonymous. If `name` matches an existing /// namespace, the associated id is returned. If `name` is an empty string @@ -1568,14 +1521,14 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err) Integer nvim_create_namespace(String name) FUNC_API_SINCE(5) { - handle_T id = map_get(String, handle_T)(namespace_ids, name); + handle_T id = map_get(String, handle_T)(&namespace_ids, name); if (id > 0) { return id; } id = next_namespace_id++; if (name.size > 0) { String name_alloc = copy_string(name); - map_put(String, handle_T)(namespace_ids, name_alloc, id); + map_put(String, handle_T)(&namespace_ids, name_alloc, id); } return (Integer)id; } @@ -1590,7 +1543,7 @@ Dictionary nvim_get_namespaces(void) String name; handle_T id; - map_foreach(namespace_ids, name, id, { + map_foreach(&namespace_ids, name, id, { PUT(retval, name.data, INTEGER_OBJ(id)); }) @@ -1627,7 +1580,7 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err) bool cancel = false; if (phase < -1 || phase > 3) { - api_set_error(err, kErrorTypeValidation, "Invalid phase: %"PRId64, phase); + api_set_error(err, kErrorTypeValidation, "Invalid phase: %" PRId64, phase); return false; } Array args = ARRAY_DICT_INIT; @@ -1691,12 +1644,11 @@ theend: /// @param after If true insert after cursor (like |p|), or before (like |P|). /// @param follow If true place cursor at end of inserted text. /// @param[out] err Error details, if any -void nvim_put(ArrayOf(String) lines, String type, Boolean after, - Boolean follow, Error *err) +void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow, Error *err) FUNC_API_SINCE(6) FUNC_API_CHECK_TEXTLOCK { - yankreg_T *reg = xcalloc(sizeof(yankreg_T), 1); + yankreg_T *reg = xcalloc(1, sizeof(yankreg_T)); if (!prepare_yankreg_from_object(reg, type, lines.size)) { api_set_error(err, kErrorTypeValidation, "Invalid type: '%s'", type.data); goto cleanup; @@ -1933,8 +1885,7 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode) /// as keys excluding |<buffer>| but including |noremap|. /// Values are Booleans. Unknown key is an error. /// @param[out] err Error details, if any. -void nvim_set_keymap(String mode, String lhs, String rhs, - Dictionary opts, Error *err) +void nvim_set_keymap(String mode, String lhs, String rhs, Dictionary opts, Error *err) FUNC_API_SINCE(6) { modify_keymap(-1, false, mode, lhs, rhs, opts, err); @@ -2031,10 +1982,8 @@ Array nvim_get_api_info(uint64_t channel_id) /// .png or .svg format is preferred. /// /// @param[out] err Error details, if any -void nvim_set_client_info(uint64_t channel_id, String name, - Dictionary version, String type, - Dictionary methods, Dictionary attributes, - Error *err) +void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version, String type, + Dictionary methods, Dictionary attributes, Error *err) FUNC_API_SINCE(4) FUNC_API_REMOTE_ONLY { Dictionary info = ARRAY_DICT_INIT; @@ -2060,27 +2009,28 @@ void nvim_set_client_info(uint64_t channel_id, String name, rpc_set_client_info(channel_id, info); } -/// Get information about a channel. +/// Gets information about a channel. /// /// @returns Dictionary describing a channel, with these keys: -/// - "stream" the stream underlying the channel +/// - "id" Channel id. +/// - "argv" (optional) Job arguments list. +/// - "stream" Stream underlying the channel. /// - "stdio" stdin and stdout of this Nvim instance /// - "stderr" stderr of this Nvim instance /// - "socket" TCP/IP socket or named pipe -/// - "job" job with communication over its stdio -/// - "mode" how data received on the channel is interpreted -/// - "bytes" send and receive raw bytes -/// - "terminal" a |terminal| instance interprets ASCII sequences -/// - "rpc" |RPC| communication on the channel is active -/// - "pty" Name of pseudoterminal, if one is used (optional). -/// On a POSIX system, this will be a device path like -/// /dev/pts/1. Even if the name is unknown, the key will -/// still be present to indicate a pty is used. This is -/// currently the case when using winpty on windows. -/// - "buffer" buffer with connected |terminal| instance (optional) -/// - "client" information about the client on the other end of the -/// RPC channel, if it has added it using -/// |nvim_set_client_info()|. (optional) +/// - "job" Job with communication over its stdio. +/// - "mode" How data received on the channel is interpreted. +/// - "bytes" Send and receive raw bytes. +/// - "terminal" |terminal| instance interprets ASCII sequences. +/// - "rpc" |RPC| communication on the channel is active. +/// - "pty" (optional) Name of pseudoterminal. On a POSIX system this +/// is a device path like "/dev/pts/1". If the name is unknown, +/// the key will still be present if a pty is used (e.g. for +/// winpty on Windows). +/// - "buffer" (optional) Buffer with connected |terminal| instance. +/// - "client" (optional) Info about the peer (client on the other end of +/// the RPC channel), if provided by it via +/// |nvim_set_client_info()|. /// Dictionary nvim_get_chan_info(Integer chan, Error *err) FUNC_API_SINCE(4) @@ -2161,9 +2111,9 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err) Array args = call.items[1].data.array; MsgpackRpcRequestHandler handler = - msgpack_rpc_get_handler_for(name.data, - name.size, - &nested_error); + msgpack_rpc_get_handler_for(name.data, + name.size, + &nested_error); if (ERROR_SET(&nested_error)) { break; @@ -2237,7 +2187,7 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; /// - "arg": String, error message argument. /// - "len": Amount of bytes successfully parsed. With flags equal to "" /// that should be equal to the length of expr string. -/// (“Sucessfully parsed” here means “participated in AST +/// (“Successfully parsed” here means “participated in AST /// creation”, not “till the first error”.) /// - "ast": AST, either nil or a dictionary with these keys: /// - "type": node type, one of the value names from ExprASTNodeType @@ -2279,29 +2229,29 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; /// - "svalue": String, value for "SingleQuotedString" and /// "DoubleQuotedString" nodes. /// @param[out] err Error details, if any -Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, - Error *err) +Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, Error *err) FUNC_API_SINCE(4) FUNC_API_FAST { int pflags = 0; for (size_t i = 0 ; i < flags.size ; i++) { switch (flags.data[i]) { - case 'm': { pflags |= kExprFlagsMulti; break; } - case 'E': { pflags |= kExprFlagsDisallowEOC; break; } - case 'l': { pflags |= kExprFlagsParseLet; break; } - case NUL: { - api_set_error(err, kErrorTypeValidation, "Invalid flag: '\\0' (%u)", - (unsigned)flags.data[i]); - return (Dictionary)ARRAY_DICT_INIT; - } - default: { - api_set_error(err, kErrorTypeValidation, "Invalid flag: '%c' (%u)", - flags.data[i], (unsigned)flags.data[i]); - return (Dictionary)ARRAY_DICT_INIT; - } + case 'm': + pflags |= kExprFlagsMulti; break; + case 'E': + pflags |= kExprFlagsDisallowEOC; break; + case 'l': + pflags |= kExprFlagsParseLet; break; + case NUL: + api_set_error(err, kErrorTypeValidation, "Invalid flag: '\\0' (%u)", + (unsigned)flags.data[i]); + return (Dictionary)ARRAY_DICT_INIT; + default: + api_set_error(err, kErrorTypeValidation, "Invalid flag: '%c' (%u)", + flags.data[i], (unsigned)flags.data[i]); + return (Dictionary)ARRAY_DICT_INIT; } } - ParserLine plines[] = { + ParserLine parser_lines[] = { { .data = expr.data, .size = expr.size, @@ -2309,20 +2259,19 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, }, { NULL, 0, false }, }; - ParserLine *plines_p = plines; + ParserLine *plines_p = parser_lines; ParserHighlight colors; kvi_init(colors); ParserHighlight *const colors_p = (highlight ? &colors : NULL); ParserState pstate; - viml_parser_init( - &pstate, parser_simple_get_line, &plines_p, colors_p); + viml_parser_init(&pstate, parser_simple_get_line, &plines_p, colors_p); ExprAST east = viml_pexpr_parse(&pstate, pflags); const size_t ret_size = ( - 2 // "ast", "len" - + (size_t)(east.err.msg != NULL) // "error" - + (size_t)highlight // "highlight" - + 0); + 2 // "ast", "len" + + (size_t)(east.err.msg != NULL) // "error" + + (size_t)highlight // "highlight" + + 0); Dictionary ret = { .items = xmalloc(ret_size * sizeof(ret.items[0])), .size = 0, @@ -2335,7 +2284,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, ret.items[ret.size++] = (KeyValuePair) { .key = STATIC_CSTR_TO_STRING("len"), .value = INTEGER_OBJ((Integer)(pstate.pos.line == 1 - ? plines[0].size + ? parser_lines[0].size : pstate.pos.col)), }; if (east.err.msg != NULL) { @@ -2409,23 +2358,23 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, } else { if (cur_item.ret_node_p->type == kObjectTypeNil) { const size_t ret_node_items_size = (size_t)( - 3 // "type", "start" and "len" - + (node->children != NULL) // "children" - + (node->type == kExprNodeOption - || node->type == kExprNodePlainIdentifier) // "scope" - + (node->type == kExprNodeOption - || node->type == kExprNodePlainIdentifier - || node->type == kExprNodePlainKey - || node->type == kExprNodeEnvironment) // "ident" - + (node->type == kExprNodeRegister) // "name" - + (3 // "cmp_type", "ccs_strategy", "invert" - * (node->type == kExprNodeComparison)) - + (node->type == kExprNodeInteger) // "ivalue" - + (node->type == kExprNodeFloat) // "fvalue" - + (node->type == kExprNodeDoubleQuotedString - || node->type == kExprNodeSingleQuotedString) // "svalue" - + (node->type == kExprNodeAssignment) // "augmentation" - + 0); + 3 // "type", "start" and "len" + + (node->children != NULL) // "children" + + (node->type == kExprNodeOption + || node->type == kExprNodePlainIdentifier) // "scope" + + (node->type == kExprNodeOption + || node->type == kExprNodePlainIdentifier + || node->type == kExprNodePlainKey + || node->type == kExprNodeEnvironment) // "ident" + + (node->type == kExprNodeRegister) // "name" + + (3 // "cmp_type", "ccs_strategy", "invert" + * (node->type == kExprNodeComparison)) + + (node->type == kExprNodeInteger) // "ivalue" + + (node->type == kExprNodeFloat) // "fvalue" + + (node->type == kExprNodeDoubleQuotedString + || node->type == kExprNodeSingleQuotedString) // "svalue" + + (node->type == kExprNodeAssignment) // "augmentation" + + 0); Dictionary ret_node = { .items = xmalloc(ret_node_items_size * sizeof(ret_node.items[0])), .capacity = ret_node_items_size, @@ -2479,151 +2428,138 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, .value = INTEGER_OBJ((Integer)node->len), }; switch (node->type) { - case kExprNodeDoubleQuotedString: - case kExprNodeSingleQuotedString: { - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("svalue"), - .value = STRING_OBJ(((String) { - .data = node->data.str.value, - .size = node->data.str.size, - })), - }; - break; - } - case kExprNodeOption: { - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("scope"), - .value = INTEGER_OBJ(node->data.opt.scope), - }; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ident"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(node->data.opt.ident, - node->data.opt.ident_len), - .size = node->data.opt.ident_len, - })), - }; - break; - } - case kExprNodePlainIdentifier: { - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("scope"), - .value = INTEGER_OBJ(node->data.var.scope), - }; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ident"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(node->data.var.ident, - node->data.var.ident_len), - .size = node->data.var.ident_len, - })), - }; - break; - } - case kExprNodePlainKey: { - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ident"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(node->data.var.ident, - node->data.var.ident_len), - .size = node->data.var.ident_len, - })), - }; - break; - } - case kExprNodeEnvironment: { - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ident"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(node->data.env.ident, - node->data.env.ident_len), - .size = node->data.env.ident_len, - })), - }; - break; - } - case kExprNodeRegister: { - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("name"), - .value = INTEGER_OBJ(node->data.reg.name), - }; - break; - } - case kExprNodeComparison: { - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("cmp_type"), - .value = STRING_OBJ(cstr_to_string( - eltkn_cmp_type_tab[node->data.cmp.type])), - }; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ccs_strategy"), - .value = STRING_OBJ(cstr_to_string( - ccs_tab[node->data.cmp.ccs])), - }; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("invert"), - .value = BOOLEAN_OBJ(node->data.cmp.inv), - }; - break; - } - case kExprNodeFloat: { - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("fvalue"), - .value = FLOAT_OBJ(node->data.flt.value), - }; - break; - } - case kExprNodeInteger: { - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ivalue"), - .value = INTEGER_OBJ((Integer)( - node->data.num.value > API_INTEGER_MAX + case kExprNodeDoubleQuotedString: + case kExprNodeSingleQuotedString: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("svalue"), + .value = STRING_OBJ(((String) { + .data = node->data.str.value, + .size = node->data.str.size, + })), + }; + break; + case kExprNodeOption: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("scope"), + .value = INTEGER_OBJ(node->data.opt.scope), + }; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ident"), + .value = STRING_OBJ(((String) { + .data = xmemdupz(node->data.opt.ident, + node->data.opt.ident_len), + .size = node->data.opt.ident_len, + })), + }; + break; + case kExprNodePlainIdentifier: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("scope"), + .value = INTEGER_OBJ(node->data.var.scope), + }; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ident"), + .value = STRING_OBJ(((String) { + .data = xmemdupz(node->data.var.ident, + node->data.var.ident_len), + .size = node->data.var.ident_len, + })), + }; + break; + case kExprNodePlainKey: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ident"), + .value = STRING_OBJ(((String) { + .data = xmemdupz(node->data.var.ident, + node->data.var.ident_len), + .size = node->data.var.ident_len, + })), + }; + break; + case kExprNodeEnvironment: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ident"), + .value = STRING_OBJ(((String) { + .data = xmemdupz(node->data.env.ident, + node->data.env.ident_len), + .size = node->data.env.ident_len, + })), + }; + break; + case kExprNodeRegister: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("name"), + .value = INTEGER_OBJ(node->data.reg.name), + }; + break; + case kExprNodeComparison: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("cmp_type"), + .value = STRING_OBJ(cstr_to_string(eltkn_cmp_type_tab[node->data.cmp.type])), + }; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ccs_strategy"), + .value = STRING_OBJ(cstr_to_string(ccs_tab[node->data.cmp.ccs])), + }; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("invert"), + .value = BOOLEAN_OBJ(node->data.cmp.inv), + }; + break; + case kExprNodeFloat: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("fvalue"), + .value = FLOAT_OBJ(node->data.flt.value), + }; + break; + case kExprNodeInteger: + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ivalue"), + .value = INTEGER_OBJ((Integer)( + node->data.num.value > API_INTEGER_MAX ? API_INTEGER_MAX : (Integer)node->data.num.value)), - }; - break; - } - case kExprNodeAssignment: { - const ExprAssignmentType asgn_type = node->data.ass.type; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("augmentation"), - .value = STRING_OBJ( - asgn_type == kExprAsgnPlain + }; + break; + case kExprNodeAssignment: { + const ExprAssignmentType asgn_type = node->data.ass.type; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("augmentation"), + .value = STRING_OBJ(asgn_type == kExprAsgnPlain ? (String)STRING_INIT : cstr_to_string(expr_asgn_type_tab[asgn_type])), - }; - break; - } - case kExprNodeMissing: - case kExprNodeOpMissing: - case kExprNodeTernary: - case kExprNodeTernaryValue: - case kExprNodeSubscript: - case kExprNodeListLiteral: - case kExprNodeUnaryPlus: - case kExprNodeBinaryPlus: - case kExprNodeNested: - case kExprNodeCall: - case kExprNodeComplexIdentifier: - case kExprNodeUnknownFigure: - case kExprNodeLambda: - case kExprNodeDictLiteral: - case kExprNodeCurlyBracesIdentifier: - case kExprNodeComma: - case kExprNodeColon: - case kExprNodeArrow: - case kExprNodeConcat: - case kExprNodeConcatOrSubscript: - case kExprNodeOr: - case kExprNodeAnd: - case kExprNodeUnaryMinus: - case kExprNodeBinaryMinus: - case kExprNodeNot: - case kExprNodeMultiplication: - case kExprNodeDivision: - case kExprNodeMod: { - break; - } + }; + break; + } + case kExprNodeMissing: + case kExprNodeOpMissing: + case kExprNodeTernary: + case kExprNodeTernaryValue: + case kExprNodeSubscript: + case kExprNodeListLiteral: + case kExprNodeUnaryPlus: + case kExprNodeBinaryPlus: + case kExprNodeNested: + case kExprNodeCall: + case kExprNodeComplexIdentifier: + case kExprNodeUnknownFigure: + case kExprNodeLambda: + case kExprNodeDictLiteral: + case kExprNodeCurlyBracesIdentifier: + case kExprNodeComma: + case kExprNodeColon: + case kExprNodeArrow: + case kExprNodeConcat: + case kExprNodeConcatOrSubscript: + case kExprNodeOr: + case kExprNodeAnd: + case kExprNodeUnaryMinus: + case kExprNodeBinaryMinus: + case kExprNodeNot: + case kExprNodeMultiplication: + case kExprNodeDivision: + case kExprNodeMod: + break; } assert(cur_item.ret_node_p->data.dictionary.size == cur_item.ret_node_p->data.dictionary.capacity); @@ -2853,8 +2789,8 @@ Object nvim_get_proc(Integer pid, Error *err) /// `insert`. /// @param opts Optional parameters. Reserved for future use. /// @param[out] err Error details, if any -void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, - Dictionary opts, Error *err) +void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, Dictionary opts, + Error *err) FUNC_API_SINCE(6) { if (opts.size > 0) { @@ -2925,7 +2861,7 @@ void nvim__screenshot(String path) /// Note: this function should not be called often. Rather, the callbacks /// themselves can be used to throttle unneeded callbacks. the `on_start` /// callback can return `false` to disable the provider until the next redraw. -/// Similarily, return `false` in `on_win` will skip the `on_lines` calls +/// Similarly, return `false` in `on_win` will skip the `on_lines` calls /// for that window (but any extmarks set in `on_win` will still be used). /// A plugin managing multiple sources of decoration should ideally only set /// one provider, and merge the sources internally. You can use multiple `ns_id` @@ -2951,8 +2887,7 @@ void nvim__screenshot(String path) /// ["win", winid, bufnr, row] /// - on_end: called at the end of a redraw cycle /// ["end", tick] -void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts, - Error *err) +void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts, Error *err) FUNC_API_SINCE(7) FUNC_API_LUA_ONLY { DecorProvider *p = get_decor_provider((NS)ns_id, true); |