From 6cc6e11929ad76a2dc5204aed95cb9ed1dafde23 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 23 Aug 2022 22:00:19 +0800 Subject: vim-patch:9.0.0206: redraw flags are not named specifically (#19913) Problem: Redraw flags are not named specifically. Solution: Prefix "UPD_" to the flags, for UPDate_screen(). https://github.com/vim/vim/commit/a4d158b3c839e96ed98ff87c7b7124ff4518c4ff --- src/nvim/api/extmark.c | 2 +- src/nvim/api/vim.c | 2 +- src/nvim/api/win_config.c | 2 +- src/nvim/api/window.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 933aa85530..3ac373283c 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -993,7 +993,7 @@ void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts, Erro decor_provider_clear(p); // regardless of what happens, it seems good idea to redraw - redraw_all_later(NOT_VALID); // TODO(bfredl): too soon? + redraw_all_later(UPD_NOT_VALID); // TODO(bfredl): too soon? struct { const char *name; diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index ce91c1b4af..7fccacdb23 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -198,7 +198,7 @@ void nvim_set_hl_ns(Integer ns_id, Error *err) ns_hl_global = (NS)ns_id; hl_check_ns(); - redraw_all_later(NOT_VALID); + redraw_all_later(UPD_NOT_VALID); } /// Set active namespace for highlights while redrawing. diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index 6c37df6af8..96c560efa1 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -202,7 +202,7 @@ void nvim_win_set_config(Window window, Dict(float_config) *config, Error *err) if (!win_new_float(win, false, fconfig, err)) { return; } - redraw_later(win, NOT_VALID); + redraw_later(win, UPD_NOT_VALID); } else { win_config_float(win, fconfig); win->w_pos_changed = true; diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index 580dfd8639..5203003369 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -118,7 +118,7 @@ void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err) // make sure cursor is in visible range even if win != curwin update_topline_win(win); - redraw_later(win, VALID); + redraw_later(win, UPD_VALID); win->w_redr_status = true; } @@ -449,5 +449,5 @@ void nvim_win_set_hl_ns(Window window, Integer ns_id, Error *err) win->w_ns_hl = (NS)ns_id; win->w_hl_needs_update = true; - redraw_later(win, NOT_VALID); + redraw_later(win, UPD_NOT_VALID); } -- cgit From c0d60526541a3cf977ae623471ae4a347b492af1 Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 23 Aug 2022 09:33:08 +0200 Subject: perf(api): allow to use an arena for return values --- src/nvim/api/buffer.c | 4 ++-- src/nvim/api/private/dispatch.h | 9 +++++++-- src/nvim/api/vim.c | 30 +++++++++++++++++------------- 3 files changed, 26 insertions(+), 17 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 5e90e40dd3..43027473a0 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1021,7 +1021,7 @@ void nvim_buf_del_var(Buffer buffer, String name, Error *err) /// @param buffer Buffer handle, or 0 for current buffer /// @param[out] err Error details, if any /// @return Buffer name -String nvim_buf_get_name(Buffer buffer, Error *err) +String nvim_buf_get_name(Buffer buffer, Arena *arena, Error *err) FUNC_API_SINCE(1) { String rv = STRING_INIT; @@ -1031,7 +1031,7 @@ String nvim_buf_get_name(Buffer buffer, Error *err) return rv; } - return cstr_to_string((char *)buf->b_ffname); + return cstr_as_string((char *)buf->b_ffname); } /// Sets the full file name for a buffer diff --git a/src/nvim/api/private/dispatch.h b/src/nvim/api/private/dispatch.h index 4b7c394944..f92b205531 100644 --- a/src/nvim/api/private/dispatch.h +++ b/src/nvim/api/private/dispatch.h @@ -5,18 +5,23 @@ typedef Object (*ApiDispatchWrapper)(uint64_t channel_id, Array args, + Arena *arena, Error *error); /// The rpc_method_handlers table, used in msgpack_rpc_dispatch(), stores /// functions of this type. -typedef struct { +struct MsgpackRpcRequestHandler { const char *name; ApiDispatchWrapper fn; bool fast; // Function is safe to be executed immediately while running the // uv loop (the loop is run very frequently due to breakcheck). // If "fast" is false, the function is deferred, i e the call will // be put in the event queue, for safe handling later. -} MsgpackRpcRequestHandler; + bool arena_return; // return value is allocated in the arena (or statically) + // and should not be freed as such. +}; + +extern const MsgpackRpcRequestHandler method_handlers[]; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "api/private/dispatch.h.generated.h" diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index ce91c1b4af..c333db1b37 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1629,11 +1629,11 @@ Array nvim_list_chans(void) /// 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, Error *err) +Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *err) FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { - Array rv = ARRAY_DICT_INIT; - Array results = ARRAY_DICT_INIT; + 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 @@ -1676,29 +1676,32 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err) if (ERROR_SET(&nested_error)) { break; } - Object result = handler.fn(channel_id, args, &nested_error); + + Object result = handler.fn(channel_id, args, arena, &nested_error); if (ERROR_SET(&nested_error)) { // error handled after loop break; } + if (!handler.arena_return && result.type != kObjectTypeNil) { + // TODO: fix to not leak memory as fuck + } - ADD(results, result); + ADD_C(results, result); } - ADD(rv, ARRAY_OBJ(results)); + ADD_C(rv, ARRAY_OBJ(results)); if (ERROR_SET(&nested_error)) { - 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)); + 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(cstr_to_string(nested_error.msg))); // TODO + ADD_C(rv, ARRAY_OBJ(errval)); } else { - ADD(rv, NIL); + ADD_C(rv, NIL); } goto theend; validation_error: - api_free_array(results); theend: api_clear_error(&nested_error); return rv; @@ -1803,6 +1806,7 @@ Dictionary nvim__stats(void) PUT(rv, "log_skip", INTEGER_OBJ(g_stats.log_skip)); PUT(rv, "lua_refcount", INTEGER_OBJ(nlua_get_global_ref_count())); PUT(rv, "redraw", INTEGER_OBJ(g_stats.redraw)); + PUT(rv, "arena_alloc_count", INTEGER_OBJ((Integer)arena_alloc_count)); return rv; } -- cgit From 7784dc9e0d90284b0d9c9cf0833c27d4de22b7f4 Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 23 Aug 2022 13:52:09 +0200 Subject: refactor(api): provide a temporary copy solution for nvim_call_atomic Make the copy_object() family accept an optional arena. More than half of the callsites should be refactored to use an arena later anyway. --- src/nvim/api/autocmd.c | 4 ++-- src/nvim/api/extmark.c | 2 +- src/nvim/api/private/helpers.c | 33 +++++++++++++++++------------- src/nvim/api/ui.c | 6 +++--- src/nvim/api/vim.c | 46 +++++++++++++++++++++--------------------- 5 files changed, 48 insertions(+), 43 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c index 79ae7994f7..1cf0211f43 100644 --- a/src/nvim/api/autocmd.c +++ b/src/nvim/api/autocmd.c @@ -887,12 +887,12 @@ static bool check_autocmd_string_array(Array arr, char *k, Error *err) static bool unpack_string_or_array(Array *array, Object *v, char *k, bool required, Error *err) { if (v->type == kObjectTypeString) { - ADD(*array, copy_object(*v)); + ADD(*array, copy_object(*v, NULL)); } else if (v->type == kObjectTypeArray) { if (!check_autocmd_string_array(v->data.array, k, err)) { return false; } - *array = copy_array(v->data.array); + *array = copy_array(v->data.array, NULL); } else { if (required) { api_set_error(err, diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 933aa85530..1d6eaa42b0 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -51,7 +51,7 @@ Integer nvim_create_namespace(String name) } id = next_namespace_id++; if (name.size > 0) { - String name_alloc = copy_string(name); + String name_alloc = copy_string(name, NULL); map_put(String, handle_T)(&namespace_ids, name_alloc, id); } return (Integer)id; diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index c466fc53e1..e35c58bf1b 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -618,6 +618,7 @@ void api_clear_error(Error *value) value->type = kErrorTypeNone; } +/// @returns a shared value. caller must not modify it! Dictionary api_metadata(void) { static Dictionary metadata = ARRAY_DICT_INIT; @@ -630,7 +631,7 @@ Dictionary api_metadata(void) init_type_metadata(&metadata); } - return copy_object(DICTIONARY_OBJ(metadata)).data.dictionary; + return metadata; } static void init_function_metadata(Dictionary *metadata) @@ -715,36 +716,40 @@ static void init_type_metadata(Dictionary *metadata) PUT(*metadata, "types", DICTIONARY_OBJ(types)); } -String copy_string(String str) +// all the copy_[object] functions allow arena=NULL, +// then global allocations are used, and the resulting object +// should be freed with an api_free_[object] function + +String copy_string(String str, Arena *arena) { if (str.data != NULL) { - return (String){ .data = xmemdupz(str.data, str.size), .size = str.size }; + return (String){ .data = arena_memdupz(arena, str.data, str.size), .size = str.size }; } else { return (String)STRING_INIT; } } -Array copy_array(Array array) +Array copy_array(Array array, Arena *arena) { - Array rv = ARRAY_DICT_INIT; + Array rv = arena_array(arena, array.size); for (size_t i = 0; i < array.size; i++) { - ADD(rv, copy_object(array.items[i])); + ADD(rv, copy_object(array.items[i], arena)); } return rv; } -Dictionary copy_dictionary(Dictionary dict) +Dictionary copy_dictionary(Dictionary dict, Arena *arena) { - Dictionary rv = ARRAY_DICT_INIT; + Dictionary rv = arena_dict(arena, dict.size); for (size_t i = 0; i < dict.size; i++) { KeyValuePair item = dict.items[i]; - PUT(rv, item.key.data, copy_object(item.value)); + PUT_C(rv, copy_string(item.key, arena).data, copy_object(item.value, arena)); } return rv; } /// Creates a deep clone of an object -Object copy_object(Object obj) +Object copy_object(Object obj, Arena *arena) { switch (obj.type) { case kObjectTypeBuffer: @@ -757,13 +762,13 @@ Object copy_object(Object obj) return obj; case kObjectTypeString: - return STRING_OBJ(copy_string(obj.data.string)); + return STRING_OBJ(copy_string(obj.data.string, arena)); case kObjectTypeArray: - return ARRAY_OBJ(copy_array(obj.data.array)); + return ARRAY_OBJ(copy_array(obj.data.array, arena)); case kObjectTypeDictionary: - return DICTIONARY_OBJ(copy_dictionary(obj.data.dictionary)); + return DICTIONARY_OBJ(copy_dictionary(obj.data.dictionary, arena)); case kObjectTypeLuaRef: return LUAREF_OBJ(api_new_luaref(obj.data.luaref)); @@ -844,7 +849,7 @@ HlMessage parse_hl_msg(Array chunks, Error *err) goto free_exit; } - String str = copy_string(chunk.items[0].data.string); + String str = copy_string(chunk.items[0].data.string, NULL); int attr = 0; if (chunk.size == 2) { diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 6f7bfa244a..e34dcbdb46 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -965,7 +965,7 @@ static Array translate_contents(UI *ui, Array contents) } else { ADD(new_item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT)); } - ADD(new_item, copy_object(item.items[1])); + ADD(new_item, copy_object(item.items[1], NULL)); ADD(new_contents, ARRAY_OBJ(new_item)); } return new_contents; @@ -978,7 +978,7 @@ static Array translate_firstarg(UI *ui, Array args) ADD(new_args, ARRAY_OBJ(translate_contents(ui, contents))); for (size_t i = 1; i < args.size; i++) { - ADD(new_args, copy_object(args.items[i])); + ADD(new_args, copy_object(args.items[i], NULL)); } return new_args; } @@ -1024,7 +1024,7 @@ static void remote_ui_event(UI *ui, char *name, Array args) Array items = args.items[0].data.array; Array new_items = ARRAY_DICT_INIT; for (size_t i = 0; i < items.size; i++) { - ADD(new_items, copy_object(items.items[i].data.array.items[0])); + ADD(new_items, copy_object(items.items[i].data.array.items[0], NULL)); } ADD_C(new_args, ARRAY_OBJ(new_items)); push_call(ui, "wildmenu_show", new_args); diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index c333db1b37..7b70de7b12 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1479,14 +1479,14 @@ void nvim_del_keymap(uint64_t channel_id, String mode, String lhs, Error *err) /// 1 is the |api-metadata| map (Dictionary). /// /// @returns 2-tuple [{channel-id}, {api-metadata}] -Array nvim_get_api_info(uint64_t channel_id) +Array nvim_get_api_info(uint64_t channel_id, Arena *arena) FUNC_API_SINCE(1) FUNC_API_FAST FUNC_API_REMOTE_ONLY { - Array rv = ARRAY_DICT_INIT; + Array rv = arena_array(arena, 2); assert(channel_id <= INT64_MAX); - ADD(rv, INTEGER_OBJ((int64_t)channel_id)); - ADD(rv, DICTIONARY_OBJ(api_metadata())); + ADD_C(rv, INTEGER_OBJ((int64_t)channel_id)); + ADD_C(rv, DICTIONARY_OBJ(api_metadata())); return rv; } @@ -1545,9 +1545,9 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version, FUNC_API_SINCE(4) FUNC_API_REMOTE_ONLY { Dictionary info = ARRAY_DICT_INIT; - PUT(info, "name", copy_object(STRING_OBJ(name))); + PUT(info, "name", copy_object(STRING_OBJ(name), NULL)); - version = copy_dictionary(version); + version = copy_dictionary(version, NULL); bool has_major = false; for (size_t i = 0; i < version.size; i++) { if (strequal(version.items[i].key.data, "major")) { @@ -1560,9 +1560,9 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version, } PUT(info, "version", DICTIONARY_OBJ(version)); - PUT(info, "type", copy_object(STRING_OBJ(type))); - PUT(info, "methods", DICTIONARY_OBJ(copy_dictionary(methods))); - PUT(info, "attributes", DICTIONARY_OBJ(copy_dictionary(attributes))); + PUT(info, "type", copy_object(STRING_OBJ(type), NULL)); + PUT(info, "methods", DICTIONARY_OBJ(copy_dictionary(methods, NULL))); + PUT(info, "attributes", DICTIONARY_OBJ(copy_dictionary(attributes, NULL))); rpc_set_client_info(channel_id, info); } @@ -1642,21 +1642,21 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *er api_set_error(err, kErrorTypeValidation, "Items in calls array must be arrays"); - goto validation_error; + goto theend; } Array call = calls.items[i].data.array; if (call.size != 2) { api_set_error(err, kErrorTypeValidation, "Items in calls array must be arrays of size 2"); - goto validation_error; + goto theend; } if (call.items[0].type != kObjectTypeString) { api_set_error(err, kErrorTypeValidation, "Name must be String"); - goto validation_error; + goto theend; } String name = call.items[0].data.string; @@ -1664,7 +1664,7 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *er api_set_error(err, kErrorTypeValidation, "Args must be Array"); - goto validation_error; + goto theend; } Array args = call.items[1].data.array; @@ -1682,11 +1682,13 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *er // error handled after loop break; } - if (!handler.arena_return && result.type != kObjectTypeNil) { - // TODO: fix to not leak memory as fuck + // TODO(bfredl): wastefull 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.arena_return) { + api_free_object(result); } - - ADD_C(results, result); } ADD_C(rv, ARRAY_OBJ(results)); @@ -1694,14 +1696,12 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *er 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(cstr_to_string(nested_error.msg))); // TODO + 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); } - goto theend; -validation_error: theend: api_clear_error(&nested_error); return rv; @@ -1754,7 +1754,7 @@ static void write_msg(String message, bool to_err) /// @return its argument. Object nvim__id(Object obj) { - return copy_object(obj); + return copy_object(obj, NULL); } /// Returns array given as argument. @@ -1767,7 +1767,7 @@ Object nvim__id(Object obj) /// @return its argument. Array nvim__id_array(Array arr) { - return copy_object(ARRAY_OBJ(arr)).data.array; + return copy_array(arr, NULL); } /// Returns dictionary given as argument. @@ -1780,7 +1780,7 @@ Array nvim__id_array(Array arr) /// @return its argument. Dictionary nvim__id_dictionary(Dictionary dct) { - return copy_object(DICTIONARY_OBJ(dct)).data.dictionary; + return copy_dictionary(dct, NULL); } /// Returns floating-point value given as argument. -- cgit From 40855b0143a864739a6037921e15699445dcf8a7 Mon Sep 17 00:00:00 2001 From: Dundar Goc Date: Sun, 31 Jul 2022 16:20:57 +0200 Subject: refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/api/buffer.c | 2 +- src/nvim/api/vim.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 43027473a0..199650fc55 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1031,7 +1031,7 @@ String nvim_buf_get_name(Buffer buffer, Arena *arena, Error *err) return rv; } - return cstr_as_string((char *)buf->b_ffname); + return cstr_as_string(buf->b_ffname); } /// Sets the full file name for a buffer diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 2fa0277df7..ca98aeb34a 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -2044,7 +2044,7 @@ Array nvim_get_mark(String name, Dictionary opts, Error *err) // Marks are from an open buffer it fnum is non zero if (mark->fmark.fnum != 0) { bufnr = mark->fmark.fnum; - filename = (char *)buflist_nr2name(bufnr, true, true); + filename = buflist_nr2name(bufnr, true, true); allocated = true; // Marks comes from shada } else { @@ -2232,7 +2232,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * // If first character doesn't have a defined highlight, // add the default highlight at the beginning of the highlight list - if (hltab->start == NULL || ((char *)hltab->start - buf) != 0) { + if (hltab->start == NULL || (hltab->start - buf) != 0) { Dictionary hl_info = ARRAY_DICT_INIT; grpname = get_default_stl_hl(wp, use_winbar); -- cgit From 2498e9feb025361576603a0101c86393d211e31e Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 25 Aug 2022 14:41:02 +0100 Subject: refactor: change FALSE/TRUE to false/true Co-authored-by: zeertzjq --- src/nvim/api/vim.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index ca98aeb34a..b164106cef 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -2092,7 +2092,7 @@ Array nvim_get_mark(String name, Dictionary opts, Error *err) /// 'fillchars'). Treated as single-width even if it isn't. /// - highlights: (boolean) Return highlight information. /// - use_winbar: (boolean) Evaluate winbar instead of statusline. -/// - use_tabline: (boolean) Evaluate tabline instead of statusline. When |TRUE|, {winid} +/// - use_tabline: (boolean) Evaluate tabline instead of statusline. When true, {winid} /// is ignored. Mutually exclusive with {use_winbar}. /// /// @param[out] err Error details, if any. @@ -2100,7 +2100,7 @@ Array nvim_get_mark(String name, Dictionary opts, Error *err) /// - str: (string) Characters that will be displayed on the statusline. /// - width: (number) Display width of the statusline. /// - highlights: Array containing highlight information of the statusline. Only included when -/// the "highlights" key in {opts} is |TRUE|. Each element of the array is a +/// the "highlights" key in {opts} is true. Each element of the array is a /// |Dictionary| with these keys: /// - start: (number) Byte index (0-based) of first character that uses the highlight. /// - group: (string) Name of highlight group. -- cgit From 813476bf7291dfaf9fc0ef77c9f53a07258a3801 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Tue, 30 Aug 2022 23:13:52 +0100 Subject: fix(exceptions): restore `did_throw` (#20000) `!did_throw` doesn't exactly imply `!current_exception`, as `did_throw = false` is sometimes used to defer exception handling for later (without forgetting the exception). E.g: uncaught exception handling in `do_cmdline()` may be deferred to a different call (e.g: when `try_level > 0`). In #7881, `current_exception = NULL` in `do_cmdline()` is used as an analogue of `did_throw = false`, but also causes the pending exception to be lost, which also leaks as `discard_exception()` wasn't used. It may be possible to fix this by saving/restoring `current_exception`, but handling all of `did_throw`'s edge cases seems messier. Maybe not worth diverging over. This fix also uncovers a `man_spec.lua` bug on Windows: exceptions are thrown due to Windows missing `man`, but they're lost; skip these tests if `man` isn't executable. --- src/nvim/api/private/helpers.c | 8 ++++++-- src/nvim/api/private/helpers.h | 1 + src/nvim/api/vimscript.c | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index e35c58bf1b..ebcf6cca6d 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -58,6 +58,7 @@ void try_enter(TryState *const tstate) .private_msg_list = NULL, .trylevel = trylevel, .got_int = got_int, + .did_throw = did_throw, .need_rethrow = need_rethrow, .did_emsg = did_emsg, }; @@ -65,6 +66,7 @@ void try_enter(TryState *const tstate) current_exception = NULL; trylevel = 1; got_int = false; + did_throw = false; need_rethrow = false; did_emsg = false; } @@ -85,6 +87,7 @@ bool try_leave(const TryState *const tstate, Error *const err) assert(trylevel == 0); assert(!need_rethrow); assert(!got_int); + assert(!did_throw); assert(!did_emsg); assert(msg_list == &tstate->private_msg_list); assert(*msg_list == NULL); @@ -93,6 +96,7 @@ bool try_leave(const TryState *const tstate, Error *const err) current_exception = tstate->current_exception; trylevel = tstate->trylevel; got_int = tstate->got_int; + did_throw = tstate->did_throw; need_rethrow = tstate->need_rethrow; did_emsg = tstate->did_emsg; return ret; @@ -127,7 +131,7 @@ bool try_end(Error *err) force_abort = false; if (got_int) { - if (current_exception) { + if (did_throw) { // If we got an interrupt, discard the current exception discard_current_exception(); } @@ -146,7 +150,7 @@ bool try_end(Error *err) if (should_free) { xfree(msg); } - } else if (current_exception) { + } else if (did_throw) { api_set_error(err, kErrorTypeException, "%s", current_exception->value); discard_current_exception(); } diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index 4608554448..2157ad0ec2 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -134,6 +134,7 @@ typedef struct { const msglist_T *const *msg_list; int trylevel; int got_int; + bool did_throw; int need_rethrow; int did_emsg; } TryState; diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c index a28bfd2ab9..f6d0e39327 100644 --- a/src/nvim/api/vimscript.c +++ b/src/nvim/api/vimscript.c @@ -137,7 +137,7 @@ Object nvim_eval(String expr, Error *err) if (!recursive) { force_abort = false; suppress_errthrow = false; - current_exception = NULL; + did_throw = false; // `did_emsg` is set by emsg(), which cancels execution. did_emsg = false; } @@ -196,7 +196,7 @@ static Object _call_function(String fn, Array args, dict_T *self, Error *err) if (!recursive) { force_abort = false; suppress_errthrow = false; - current_exception = NULL; + did_throw = false; // `did_emsg` is set by emsg(), which cancels execution. did_emsg = false; } -- cgit From fa747d004a1e91b30066020f2f592e4dc5d94084 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 31 Aug 2022 19:47:10 +0800 Subject: fix(api): nvim_set_hl bail out on invalid group name (#20021) --- src/nvim/api/vim.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index b164106cef..a1721d433f 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -86,8 +86,7 @@ Dictionary nvim_get_hl_by_name(String name, Boolean rgb, Error *err) int id = syn_name2id(name.data); if (id == 0) { - api_set_error(err, kErrorTypeException, "Invalid highlight name: %s", - name.data); + api_set_error(err, kErrorTypeException, "Invalid highlight name: %s", name.data); return result; } result = nvim_get_hl_by_id(id, rgb, err); @@ -105,8 +104,7 @@ Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Error *err) { 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); + api_set_error(err, kErrorTypeException, "Invalid highlight id: %" PRId64, hl_id); return dic; } int attrcode = syn_id2attr((int)hl_id); @@ -175,6 +173,10 @@ void nvim_set_hl(Integer ns_id, String name, Dict(highlight) *val, Error *err) FUNC_API_SINCE(7) { int hl_id = syn_check_group(name.data, name.size); + if (hl_id == 0) { + api_set_error(err, kErrorTypeException, "Invalid highlight name: %s", name.data); + return; + } int link_id = -1; HlAttrs attrs = dict2hlattrs(val, true, &link_id, err); -- cgit From 933c80e8f9d7ff4ab634c14d370440702c7c8ed7 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 31 Aug 2022 21:14:14 +0800 Subject: refactor(mappings)!: mapblock_fill_dict() use API Dictionary (#20020) This introduces the following breaking changes: - nvim_get_keymap now always returns a LuaRef object as "callback" for a Lua mapping regardless of how it is called. The LuaRef object can be called from Lua and Vim script, but is lost over RPC. - maparg() now returns a Funcref instead of a ref number as "callback" for a Lua mapping. The Funcref can be called from Lua and Vim script, but is lost over RPC. This may also make nvim_get_keymap faster, but make maparg() slower. --- src/nvim/api/buffer.c | 4 ++-- src/nvim/api/vim.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 199650fc55..16f574f46d 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -945,7 +945,7 @@ Integer nvim_buf_get_changedtick(Buffer buffer, Error *err) /// @param[out] err Error details, if any /// @returns Array of |maparg()|-like dictionaries describing mappings. /// The "buffer" key holds the associated buffer handle. -ArrayOf(Dictionary) nvim_buf_get_keymap(uint64_t channel_id, Buffer buffer, String mode, Error *err) +ArrayOf(Dictionary) nvim_buf_get_keymap(Buffer buffer, String mode, Error *err) FUNC_API_SINCE(3) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -954,7 +954,7 @@ ArrayOf(Dictionary) nvim_buf_get_keymap(uint64_t channel_id, Buffer buffer, Stri return (Array)ARRAY_DICT_INIT; } - return keymap_array(mode, buf, channel_id == LUA_INTERNAL_CALL); + return keymap_array(mode, buf); } /// Sets a buffer-local |mapping| for the given mode. diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index a1721d433f..9e1f2dd631 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1421,10 +1421,10 @@ Dictionary nvim_get_mode(void) /// @param mode Mode short-name ("n", "i", "v", ...) /// @returns Array of |maparg()|-like dictionaries describing mappings. /// The "buffer" key is always zero. -ArrayOf(Dictionary) nvim_get_keymap(uint64_t channel_id, String mode) +ArrayOf(Dictionary) nvim_get_keymap(String mode) FUNC_API_SINCE(3) { - return keymap_array(mode, NULL, channel_id == LUA_INTERNAL_CALL); + return keymap_array(mode, NULL); } /// Sets a global |mapping| for the given mode. -- cgit From f31db30975479cb6b57247f124a65f4362f80bfe Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 30 Jun 2022 13:26:31 +0600 Subject: feat(lua): vim.ui_attach to get ui events from lua Co-authored-by: Famiu Haque --- src/nvim/api/extmark.c | 2 +- src/nvim/api/ui.c | 1 + src/nvim/api/ui_events.in.h | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 09b004637f..6ff0a2ed21 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -87,7 +87,7 @@ const char *describe_ns(NS ns_id) } // Is the Namespace in use? -static bool ns_initialized(uint32_t ns) +bool ns_initialized(uint32_t ns) { if (ns < 1) { return false; diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index e34dcbdb46..654eb19bec 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -223,6 +223,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona ui->msg_set_pos = remote_ui_msg_set_pos; ui->event = remote_ui_event; ui->inspect = remote_ui_inspect; + ui->win_viewport = remote_ui_win_viewport; CLEAR_FIELD(ui->ui_ext); diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index 8b7e01e1c3..17930dca85 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -100,7 +100,7 @@ void raw_line(Integer grid, Integer row, Integer startcol, FUNC_API_NOEXPORT FUNC_API_COMPOSITOR_IMPL; void event(char *name, Array args) - FUNC_API_NOEXPORT; + FUNC_API_NOEXPORT FUNC_API_COMPOSITOR_IMPL; void win_pos(Integer grid, Window win, Integer startrow, Integer startcol, Integer width, Integer height) @@ -121,7 +121,7 @@ void msg_set_pos(Integer grid, Integer row, Boolean scrolled, String sep_char) void win_viewport(Integer grid, Window win, Integer topline, Integer botline, Integer curline, Integer curcol, Integer line_count) - FUNC_API_SINCE(7) FUNC_API_REMOTE_ONLY; + FUNC_API_SINCE(7) FUNC_API_BRIDGE_IMPL; void win_extmark(Integer grid, Window win, Integer ns_id, Integer mark_id, Integer row, Integer col) -- cgit From ba8be7446d440053b24358046e8e4033e3447633 Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 31 Aug 2022 14:49:15 +0200 Subject: refactor(highlight): make hlattrs2dict always use pre-allocated dict hlattrs2dict used to work with both allocated and unallocated dicts which was quite messy. Now always delegate allocation to caller. --- src/nvim/api/ui.c | 64 +++++++++++++++++++++++++++++------------------------- src/nvim/api/vim.c | 22 +++++++++---------- 2 files changed, 45 insertions(+), 41 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index e34dcbdb46..110bd6920e 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -748,10 +748,12 @@ static void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAt UIData *data = ui->data; Array args = data->call_buf; ADD_C(args, INTEGER_OBJ(id)); - MAXSIZE_TEMP_DICT(rgb, 16); - MAXSIZE_TEMP_DICT(cterm, 16); - ADD_C(args, DICTIONARY_OBJ(hlattrs2dict(&rgb, rgb_attrs, true))); - ADD_C(args, DICTIONARY_OBJ(hlattrs2dict(&cterm, cterm_attrs, false))); + MAXSIZE_TEMP_DICT(rgb, HLATTRS_DICT_SIZE); + MAXSIZE_TEMP_DICT(cterm, HLATTRS_DICT_SIZE); + hlattrs2dict(&rgb, rgb_attrs, true); + hlattrs2dict(&cterm, rgb_attrs, false); + ADD_C(args, DICTIONARY_OBJ(rgb)); + ADD_C(args, DICTIONARY_OBJ(cterm)); if (ui->ui_ext[kUIHlState]) { ADD_C(args, ARRAY_OBJ(info)); @@ -771,8 +773,9 @@ static void remote_ui_highlight_set(UI *ui, int id) return; } data->hl_id = id; - MAXSIZE_TEMP_DICT(dict, 16); - ADD_C(args, DICTIONARY_OBJ(hlattrs2dict(&dict, syn_attr2entry(id), ui->rgb))); + MAXSIZE_TEMP_DICT(dict, HLATTRS_DICT_SIZE); + hlattrs2dict(&dict, syn_attr2entry(id), ui->rgb); + ADD_C(args, DICTIONARY_OBJ(dict)); push_call(ui, "highlight_set", args); } @@ -952,65 +955,63 @@ static void remote_ui_flush(UI *ui) } } -static Array translate_contents(UI *ui, Array contents) +static Array translate_contents(UI *ui, Array contents, Arena *arena) { - Array new_contents = ARRAY_DICT_INIT; + Array new_contents = arena_array(arena, contents.size); for (size_t i = 0; i < contents.size; i++) { Array item = contents.items[i].data.array; - Array new_item = ARRAY_DICT_INIT; + Array new_item = arena_array(arena, 2); int attr = (int)item.items[0].data.integer; if (attr) { - Dictionary rgb_attrs = hlattrs2dict(NULL, syn_attr2entry(attr), ui->rgb); + Dictionary rgb_attrs = arena_dict(arena, HLATTRS_DICT_SIZE); + hlattrs2dict(&rgb_attrs, syn_attr2entry(attr), ui->rgb); ADD(new_item, DICTIONARY_OBJ(rgb_attrs)); } else { ADD(new_item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT)); } - ADD(new_item, copy_object(item.items[1], NULL)); + ADD(new_item, item.items[1]); ADD(new_contents, ARRAY_OBJ(new_item)); } return new_contents; } -static Array translate_firstarg(UI *ui, Array args) +static Array translate_firstarg(UI *ui, Array args, Arena *arena) { - Array new_args = ARRAY_DICT_INIT; + Array new_args = arena_array(arena, args.size); Array contents = args.items[0].data.array; - ADD(new_args, ARRAY_OBJ(translate_contents(ui, contents))); + ADD_C(new_args, ARRAY_OBJ(translate_contents(ui, contents, arena))); for (size_t i = 1; i < args.size; i++) { - ADD(new_args, copy_object(args.items[i], NULL)); + ADD(new_args, args.items[i]); } return new_args; } static void remote_ui_event(UI *ui, char *name, Array args) { + Arena arena = ARENA_EMPTY; UIData *data = ui->data; if (!ui->ui_ext[kUILinegrid]) { // the representation of highlights in cmdline changed, translate back // never consumes args if (strequal(name, "cmdline_show")) { - Array new_args = translate_firstarg(ui, args); + Array new_args = translate_firstarg(ui, args, &arena); push_call(ui, name, new_args); - api_free_array(new_args); - return; + goto free_ret; } else if (strequal(name, "cmdline_block_show")) { Array new_args = data->call_buf; Array block = args.items[0].data.array; - Array new_block = ARRAY_DICT_INIT; + Array new_block = arena_array(&arena, block.size); for (size_t i = 0; i < block.size; i++) { - ADD(new_block, - ARRAY_OBJ(translate_contents(ui, block.items[i].data.array))); + ADD_C(new_block, ARRAY_OBJ(translate_contents(ui, block.items[i].data.array, &arena))); } ADD_C(new_args, ARRAY_OBJ(new_block)); push_call(ui, name, new_args); - api_free_array(new_block); - return; + goto free_ret; } else if (strequal(name, "cmdline_block_append")) { - Array new_args = translate_firstarg(ui, args); + Array new_args = translate_firstarg(ui, args, &arena); push_call(ui, name, new_args); - api_free_array(new_args); - return; + goto free_ret; } } @@ -1022,19 +1023,18 @@ static void remote_ui_event(UI *ui, char *name, Array args) if (data->wildmenu_active) { Array new_args = data->call_buf; Array items = args.items[0].data.array; - Array new_items = ARRAY_DICT_INIT; + Array new_items = arena_array(&arena, items.size); for (size_t i = 0; i < items.size; i++) { - ADD(new_items, copy_object(items.items[i].data.array.items[0], NULL)); + ADD_C(new_items, items.items[i].data.array.items[0]); } ADD_C(new_args, ARRAY_OBJ(new_items)); push_call(ui, "wildmenu_show", new_args); - api_free_array(new_items); if (args.items[1].data.integer != -1) { Array new_args2 = data->call_buf; ADD_C(new_args2, args.items[1]); push_call(ui, "wildmenu_select", new_args2); } - return; + goto free_ret; } } else if (strequal(name, "popupmenu_select")) { if (data->wildmenu_active) { @@ -1048,6 +1048,10 @@ static void remote_ui_event(UI *ui, char *name, Array args) } push_call(ui, name, args); + return; + +free_ret: + arena_mem_free(arena_finish(&arena)); } static void remote_ui_inspect(UI *ui, Dictionary *info) diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 9e1f2dd631..83d6ba8dc7 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -79,7 +79,7 @@ /// @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) +Dictionary nvim_get_hl_by_name(String name, Boolean rgb, Arena *arena, Error *err) FUNC_API_SINCE(3) { Dictionary result = ARRAY_DICT_INIT; @@ -89,8 +89,7 @@ Dictionary nvim_get_hl_by_name(String name, Boolean rgb, Error *err) api_set_error(err, kErrorTypeException, "Invalid highlight name: %s", name.data); return result; } - result = nvim_get_hl_by_id(id, rgb, err); - return result; + return nvim_get_hl_by_id(id, rgb, arena, err); } /// Gets a highlight definition by id. |hlID()| @@ -99,7 +98,7 @@ Dictionary nvim_get_hl_by_name(String name, Boolean rgb, Error *err) /// @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) +Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Arena *arena, Error *err) FUNC_API_SINCE(3) { Dictionary dic = ARRAY_DICT_INIT; @@ -108,7 +107,7 @@ Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Error *err) return dic; } int attrcode = syn_id2attr((int)hl_id); - return hl_get_attr_by_id(attrcode, rgb, err); + return hl_get_attr_by_id(attrcode, rgb, arena, err); } /// Gets a highlight group by name @@ -120,10 +119,10 @@ Integer nvim_get_hl_id_by_name(String name) return syn_check_group(name.data, name.size); } -Dictionary nvim__get_hl_defs(Integer ns_id, Error *err) +Dictionary nvim__get_hl_defs(Integer ns_id, Arena *arena, Error *err) { if (ns_id == 0) { - return get_global_hl_defs(); + return get_global_hl_defs(arena); } abort(); } @@ -1934,7 +1933,7 @@ void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, Di } /// NB: if your UI doesn't use hlstate, this will not return hlstate first time -Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Error *err) +Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Arena *arena, Error *err) { Array ret = ARRAY_DICT_INIT; @@ -1958,13 +1957,14 @@ Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Error *err) || col < 0 || col >= g->cols) { return ret; } + ret = arena_array(arena, 3); size_t off = g->line_offset[(size_t)row] + (size_t)col; - ADD(ret, STRING_OBJ(cstr_to_string((char *)g->chars[off]))); + ADD_C(ret, STRING_OBJ(cstr_as_string((char *)g->chars[off]))); int attr = g->attrs[off]; - ADD(ret, DICTIONARY_OBJ(hl_get_attr_by_id(attr, true, err))); + ADD_C(ret, DICTIONARY_OBJ(hl_get_attr_by_id(attr, true, arena, err))); // will not work first time if (!highlight_use_hlstate()) { - ADD(ret, ARRAY_OBJ(hl_inspect(attr))); + ADD_C(ret, ARRAY_OBJ(hl_inspect(attr))); } return ret; } -- cgit From 689f5d604e59eba1ddab6f91b458a8163dc6629d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 1 Sep 2022 20:32:59 +0800 Subject: feat(api): add support for :horizontal modifier --- src/nvim/api/command.c | 7 +++++++ src/nvim/api/keysets.lua | 1 + 2 files changed, 8 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index 1323fc347b..b821e07d60 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -62,6 +62,7 @@ /// - browse: (boolean) |:browse|. /// - confirm: (boolean) |:confirm|. /// - hide: (boolean) |:hide|. +/// - horizontal: (boolean) |:horizontal|. /// - keepalt: (boolean) |:keepalt|. /// - keepjumps: (boolean) |:keepjumps|. /// - keepmarks: (boolean) |:keepmarks|. @@ -250,6 +251,7 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err) PUT(mods, "lockmarks", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_LOCKMARKS)); PUT(mods, "noswapfile", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_NOSWAPFILE)); PUT(mods, "vertical", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_split & WSP_VERT)); + PUT(mods, "horizontal", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_split & WSP_HOR)); const char *split; if (cmdinfo.cmdmod.cmod_split & WSP_BOT) { @@ -576,6 +578,10 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error OBJ_TO_BOOL(vertical, mods.vertical, false, "'mods.vertical'"); cmdinfo.cmdmod.cmod_split |= (vertical ? WSP_VERT : 0); + bool horizontal; + OBJ_TO_BOOL(horizontal, mods.horizontal, false, "'mods.horizontal'"); + cmdinfo.cmdmod.cmod_split |= (horizontal ? WSP_HOR : 0); + if (HAS_KEY(mods.split)) { if (mods.split.type != kObjectTypeString) { VALIDATION_ERROR("'mods.split' must be a String"); @@ -753,6 +759,7 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin } while (0) CMDLINE_APPEND_IF(cmdinfo->cmdmod.cmod_split & WSP_VERT, "vertical "); + CMDLINE_APPEND_IF(cmdinfo->cmdmod.cmod_split & WSP_HOR, "horizontal "); CMDLINE_APPEND_IF(cmdinfo->cmdmod.cmod_flags & CMOD_SANDBOX, "sandbox "); CMDLINE_APPEND_IF(cmdinfo->cmdmod.cmod_flags & CMOD_NOAUTOCMD, "noautocmd "); CMDLINE_APPEND_IF(cmdinfo->cmdmod.cmod_flags & CMOD_BROWSE, "browse "); diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua index 6fad52ba75..af3dc24f51 100644 --- a/src/nvim/api/keysets.lua +++ b/src/nvim/api/keysets.lua @@ -188,6 +188,7 @@ return { "browse"; "confirm"; "hide"; + "horizontal"; "keepalt"; "keepjumps"; "keepmarks"; -- cgit From 1ef7720567b08caec0c077605fb2a01a9d6eafbc Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 1 Sep 2022 18:46:34 +0800 Subject: fix(api)!: correctly deal with number before :tab Now nvim_parse_cmd and nvim_create_user_command use a "tab" value which is the same as the number passed before :tab modifier instead of the number plus 1, and "tab" value is -1 if :tab modifier is not used. --- src/nvim/api/command.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index b821e07d60..11715a49dc 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -69,7 +69,7 @@ /// - keeppatterns: (boolean) |:keeppatterns|. /// - lockmarks: (boolean) |:lockmarks|. /// - noswapfile: (boolean) |:noswapfile|. -/// - tab: (integer) |:tab|. +/// - tab: (integer) |:tab|. -1 when omitted. /// - verbose: (integer) |:verbose|. -1 when omitted. /// - vertical: (boolean) |:vertical|. /// - split: (string) Split modifier string, is an empty string when there's no split @@ -239,7 +239,7 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err) PUT(mods, "unsilent", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_UNSILENT)); PUT(mods, "sandbox", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_SANDBOX)); PUT(mods, "noautocmd", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_NOAUTOCMD)); - PUT(mods, "tab", INTEGER_OBJ(cmdinfo.cmdmod.cmod_tab)); + PUT(mods, "tab", INTEGER_OBJ(cmdinfo.cmdmod.cmod_tab - 1)); PUT(mods, "verbose", INTEGER_OBJ(cmdinfo.cmdmod.cmod_verbose - 1)); PUT(mods, "browse", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_BROWSE)); PUT(mods, "confirm", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_CONFIRM)); @@ -559,15 +559,17 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error } if (HAS_KEY(mods.tab)) { - if (mods.tab.type != kObjectTypeInteger || mods.tab.data.integer < 0) { - VALIDATION_ERROR("'mods.tab' must be a non-negative Integer"); + if (mods.tab.type != kObjectTypeInteger) { + VALIDATION_ERROR("'mods.tab' must be an Integer"); + } else if ((int)mods.tab.data.integer >= 0) { + // Silently ignore negative integers to allow mods.tab to be set to -1. + cmdinfo.cmdmod.cmod_tab = (int)mods.tab.data.integer + 1; } - cmdinfo.cmdmod.cmod_tab = (int)mods.tab.data.integer + 1; } if (HAS_KEY(mods.verbose)) { if (mods.verbose.type != kObjectTypeInteger) { - VALIDATION_ERROR("'mods.verbose' must be a Integer"); + VALIDATION_ERROR("'mods.verbose' must be an Integer"); } else if ((int)mods.verbose.data.integer >= 0) { // Silently ignore negative integers to allow mods.verbose to be set to -1. cmdinfo.cmdmod.cmod_verbose = (int)mods.verbose.data.integer + 1; -- cgit From ceb09701f29dcabcf219f458fffbb64f5adced9b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 24 Jul 2022 13:58:29 +0800 Subject: feat(api): add "move" to nvim_input_mouse --- src/nvim/api/vim.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 83d6ba8dc7..95c9919522 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -336,9 +336,9 @@ Integer nvim_input(String keys) /// mouse input in a GUI. The deprecated pseudokey form /// ("") of |nvim_input()| has the same limitation. /// -/// @param button Mouse button: one of "left", "right", "middle", "wheel". +/// @param button Mouse button: one of "left", "right", "middle", "wheel", "move". /// @param action For ordinary buttons, one of "press", "drag", "release". -/// For the wheel, one of "up", "down", "left", "right". +/// For the wheel, one of "up", "down", "left", "right". Ignored for "move". /// @param modifier String of modifiers each represented by a single char. /// The same specifiers are used as for a key press, except /// that the "-" separator is optional, so "C-A-", "c-a" @@ -365,6 +365,8 @@ void nvim_input_mouse(String button, String action, String modifier, Integer gri code = KE_RIGHTMOUSE; } else if (strequal(button.data, "wheel")) { code = KE_MOUSEDOWN; + } else if (strequal(button.data, "move")) { + code = KE_MOUSEMOVE; } else { goto error; } @@ -381,7 +383,7 @@ void nvim_input_mouse(String button, String action, String modifier, Integer gri } else { goto error; } - } else { + } else if (code != KE_MOUSEMOVE) { if (strequal(action.data, "press")) { // pass } else if (strequal(action.data, "drag")) { -- cgit From 75adfefc85bcf0d62d2c0f51a951e6003b595cea Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Mon, 18 Jul 2022 14:21:40 +0200 Subject: feat(extmarks,ts,spell): full support for spelling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added 'spell' option to extmarks: Extmarks with this set will have the region spellchecked. - Added 'noplainbuffer' option to 'spelloptions': This is used to tell Neovim not to spellcheck the buffer. The old behaviour was to spell check the whole buffer unless :syntax was set. - Added spelling support to the treesitter highlighter: @spell captures in highlights.scm are used to define regions which should be spell checked. - Added support for navigating spell errors for extmarks: Works for both ephemeral and static extmarks - Added '_on_spell_nav' callback for decoration providers: Since ephemeral callbacks are only drawn for the visible screen, providers must implement this callback to instruct Neovim which regions in the buffer need can be spell checked. The callback takes a start position and an end position. Note: this callback is subject to change hence the _ prefix. - Added spell captures for built-in support languages Co-authored-by: Lewis Russell Co-authored-by: Björn Linse --- src/nvim/api/extmark.c | 65 +++++++++++++++++++++++++----------------------- src/nvim/api/keysets.lua | 10 ++++++++ 2 files changed, 44 insertions(+), 31 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 6ff0a2ed21..ae051d8cab 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -473,6 +473,8 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e /// When a character is supplied it is used as |:syn-cchar|. /// "hl_group" is used as highlight for the cchar if provided, /// otherwise it defaults to |hl-Conceal|. +/// - spell: boolean indicating that spell checking should be +/// performed within this extmark /// - ui_watched: boolean that indicates the mark should be drawn /// by a UI. When set, the UI will receive win_extmark events. /// Note: the mark is positioned by virt_text attributes. Can be @@ -719,6 +721,11 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer bool ephemeral = false; OPTION_TO_BOOL(ephemeral, ephemeral, false); + OPTION_TO_BOOL(decor.spell, spell, false); + if (decor.spell) { + has_decor = true; + } + OPTION_TO_BOOL(decor.ui_watched, ui_watched, false); if (decor.ui_watched) { has_decor = true; @@ -972,20 +979,21 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start, /// for the moment. /// /// @param ns_id Namespace id from |nvim_create_namespace()| -/// @param opts Callbacks invoked during redraw: +/// @param opts Table of callbacks: /// - on_start: called first on each screen redraw /// ["start", tick] -/// - on_buf: called for each buffer being redrawn (before window -/// callbacks) +/// - on_buf: called for each buffer being redrawn (before +/// window callbacks) /// ["buf", bufnr, tick] -/// - on_win: called when starting to redraw a specific window. +/// - on_win: called when starting to redraw a +/// specific window. /// ["win", winid, bufnr, topline, botline_guess] -/// - on_line: called for each buffer line being redrawn. (The -/// interaction with fold lines is subject to change) +/// - on_line: called for each buffer line being redrawn. +/// (The interaction with fold lines is subject to change) /// ["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, Dict(set_decoration_provider) *opts, Error *err) FUNC_API_SINCE(7) FUNC_API_LUA_ONLY { DecorProvider *p = get_decor_provider((NS)ns_id, true); @@ -997,37 +1005,32 @@ void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts, Erro struct { const char *name; + Object *source; LuaRef *dest; } cbs[] = { - { "on_start", &p->redraw_start }, - { "on_buf", &p->redraw_buf }, - { "on_win", &p->redraw_win }, - { "on_line", &p->redraw_line }, - { "on_end", &p->redraw_end }, - { "_on_hl_def", &p->hl_def }, - { NULL, NULL }, + { "on_start", &opts->on_start, &p->redraw_start }, + { "on_buf", &opts->on_buf, &p->redraw_buf }, + { "on_win", &opts->on_win, &p->redraw_win }, + { "on_line", &opts->on_line, &p->redraw_line }, + { "on_end", &opts->on_end, &p->redraw_end }, + { "_on_hl_def", &opts->_on_hl_def, &p->hl_def }, + { "_on_spell_nav", &opts->_on_spell_nav, &p->spell_nav }, + { NULL, NULL, NULL }, }; - for (size_t i = 0; i < opts.size; i++) { - String k = opts.items[i].key; - Object *v = &opts.items[i].value; - size_t j; - for (j = 0; cbs[j].name && cbs[j].dest; j++) { - if (strequal(cbs[j].name, k.data)) { - if (v->type != kObjectTypeLuaRef) { - api_set_error(err, kErrorTypeValidation, - "%s is not a function", cbs[j].name); - goto error; - } - *(cbs[j].dest) = v->data.luaref; - v->data.luaref = LUA_NOREF; - break; - } + for (size_t i = 0; cbs[i].source && cbs[i].dest && cbs[i].name; i++) { + Object *v = cbs[i].source; + if (v->type == kObjectTypeNil) { + continue; } - if (!cbs[j].name) { - api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); + + if (v->type != kObjectTypeLuaRef) { + api_set_error(err, kErrorTypeValidation, + "%s is not a function", cbs[i].name); goto error; } + *(cbs[i].dest) = v->data.luaref; + v->data.luaref = LUA_NOREF; } p->active = true; diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua index af3dc24f51..ea8949bd2c 100644 --- a/src/nvim/api/keysets.lua +++ b/src/nvim/api/keysets.lua @@ -2,6 +2,15 @@ return { context = { "types"; }; + set_decoration_provider = { + "on_start"; + "on_buf"; + "on_win"; + "on_line"; + "on_end"; + "_on_hl_def"; + "_on_spell_nav"; + }; set_extmark = { "id"; "end_line"; @@ -28,6 +37,7 @@ return { "line_hl_group"; "cursorline_hl_group"; "conceal"; + "spell"; "ui_watched"; }; keymap = { -- cgit From 73207cae611a1efb8cd17139e8228772daeb9866 Mon Sep 17 00:00:00 2001 From: Dundar Göc Date: Fri, 26 Aug 2022 23:11:25 +0200 Subject: refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/api/buffer.c | 6 +++--- src/nvim/api/private/helpers.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 16f574f46d..6f8cad3e33 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -570,7 +570,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In char *str_at_end = NULL; // Another call to ml_get_buf() may free the line, so make a copy. - str_at_start = xstrdup((char *)ml_get_buf(buf, (linenr_T)start_row, false)); + str_at_start = xstrdup(ml_get_buf(buf, (linenr_T)start_row, false)); size_t len_at_start = strlen(str_at_start); if (start_col < 0 || (size_t)start_col > len_at_start) { api_set_error(err, kErrorTypeValidation, "start_col out of bounds"); @@ -578,7 +578,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In } // Another call to ml_get_buf() may free the line, so make a copy. - str_at_end = xstrdup((char *)ml_get_buf(buf, (linenr_T)end_row, false)); + str_at_end = xstrdup(ml_get_buf(buf, (linenr_T)end_row, false)); size_t len_at_end = strlen(str_at_end); if (end_col < 0 || (size_t)end_col > len_at_end) { api_set_error(err, kErrorTypeValidation, "end_col out of bounds"); @@ -608,7 +608,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In for (int64_t i = 1; i < end_row - start_row; i++) { int64_t lnum = start_row + i; - const char *bufline = (char *)ml_get_buf(buf, (linenr_T)lnum, false); + const char *bufline = ml_get_buf(buf, (linenr_T)lnum, false); old_byte += (bcount_t)(strlen(bufline)) + 1; } old_byte += (bcount_t)end_col + 1; diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index ebcf6cca6d..22d2ffbaf1 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -466,7 +466,7 @@ bool buf_collect_lines(buf_T *buf, size_t n, int64_t start, bool replace_nl, Arr return false; } - const char *bufstr = (char *)ml_get_buf(buf, (linenr_T)lnum, false); + const char *bufstr = ml_get_buf(buf, (linenr_T)lnum, false); Object str = STRING_OBJ(cstr_to_string(bufstr)); if (replace_nl) { @@ -499,7 +499,7 @@ String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col return rv; } - const char *bufstr = (char *)ml_get_buf(buf, (linenr_T)lnum, false); + const char *bufstr = ml_get_buf(buf, (linenr_T)lnum, false); size_t line_length = strlen(bufstr); start_col = start_col < 0 ? (int64_t)line_length + start_col + 1 : start_col; -- cgit From db9b8b08e74ae8cfb08960eca0a7273538ebcdf1 Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 6 Sep 2022 22:23:54 +0200 Subject: refactor(typval): change FC_CFUNC abstraction into FC_LUAREF "cfuncs" was only ever used to wrap luarefs. As vim8script is finished and will not be developed further, support for "cfuncs" for other usecases are not planned. This abstraction was immediately broken anyway in order to get luarefs out of userfuncs again. Even if a new kind of userfunc needs to be invented in the future, likely just extending the FC_... flag union directy, instead of invoking unnecessary heap object and c function pointer indirection, will be a more straightforward design pattern. --- src/nvim/api/private/converter.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/converter.c b/src/nvim/api/private/converter.c index 8724ef4432..b6b3c83f3c 100644 --- a/src/nvim/api/private/converter.c +++ b/src/nvim/api/private/converter.c @@ -65,8 +65,8 @@ typedef struct { #define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ do { \ ufunc_T *fp = find_func(fun); \ - if (fp != NULL && fp->uf_cb == nlua_CFunction_func_call) { \ - LuaRef ref = api_new_luaref(((LuaCFunctionState *)fp->uf_cb_state)->lua_callable.func_ref); \ + if (fp != NULL && (fp->uf_flags & FC_LUAREF)) { \ + LuaRef ref = api_new_luaref(fp->uf_luaref); \ kvi_push(edata->stack, LUAREF_OBJ(ref)); \ } else { \ TYPVAL_ENCODE_CONV_NIL(tv); \ @@ -351,10 +351,7 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err) } case kObjectTypeLuaRef: { - LuaCFunctionState *state = xmalloc(sizeof(LuaCFunctionState)); - state->lua_callable.func_ref = api_new_luaref(obj.data.luaref); - char *name = - (char *)register_cfunc(&nlua_CFunction_func_call, &nlua_CFunction_func_free, state); + char *name = (char *)register_luafunc(api_new_luaref(obj.data.luaref)); tv->v_type = VAR_FUNC; tv->vval.v_string = xstrdup(name); break; -- cgit From c5322e752e9e568de907f7a1ef733bbfe342140c Mon Sep 17 00:00:00 2001 From: Dundar Göc Date: Fri, 26 Aug 2022 23:11:25 +0200 Subject: refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/api/command.c | 14 +++++++------- src/nvim/api/ui.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index 11715a49dc..b3518f1b0f 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -591,15 +591,15 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error if (*mods.split.data.string.data == NUL) { // Empty string, do nothing. - } else if (STRCMP(mods.split.data.string.data, "aboveleft") == 0 - || STRCMP(mods.split.data.string.data, "leftabove") == 0) { + } else if (strcmp(mods.split.data.string.data, "aboveleft") == 0 + || strcmp(mods.split.data.string.data, "leftabove") == 0) { cmdinfo.cmdmod.cmod_split |= WSP_ABOVE; - } else if (STRCMP(mods.split.data.string.data, "belowright") == 0 - || STRCMP(mods.split.data.string.data, "rightbelow") == 0) { + } else if (strcmp(mods.split.data.string.data, "belowright") == 0 + || strcmp(mods.split.data.string.data, "rightbelow") == 0) { cmdinfo.cmdmod.cmod_split |= WSP_BELOW; - } else if (STRCMP(mods.split.data.string.data, "topleft") == 0) { + } else if (strcmp(mods.split.data.string.data, "topleft") == 0) { cmdinfo.cmdmod.cmod_split |= WSP_TOP; - } else if (STRCMP(mods.split.data.string.data, "botright") == 0) { + } else if (strcmp(mods.split.data.string.data, "botright") == 0) { cmdinfo.cmdmod.cmod_split |= WSP_BOT; } else { VALIDATION_ERROR("Invalid value for 'mods.split'"); @@ -938,7 +938,7 @@ void nvim_buf_del_user_command(Buffer buffer, String name, Error *err) for (int i = 0; i < gap->ga_len; i++) { ucmd_T *cmd = USER_CMD_GA(gap, i); - if (!STRCMP(name.data, cmd->uc_name)) { + if (!strcmp(name.data, cmd->uc_name)) { free_ucmd(cmd); gap->ga_len -= 1; diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 1534e547b0..27fb4b8e16 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -845,7 +845,7 @@ static void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startc for (size_t i = 0; i < ncells; i++) { repeat++; if (i == ncells - 1 || attrs[i] != attrs[i + 1] - || STRCMP(chunk[i], chunk[i + 1])) { + || strcmp(chunk[i], chunk[i + 1])) { if (UI_BUF_SIZE - BUF_POS(data) < 2 * (1 + 2 + sizeof(schar_T) + 5 + 5)) { // close to overflowing the redraw buffer. finish this event, // flush, and start a new "grid_line" event at the current position. -- cgit From 3ff46544c9872b4161fd098569c30b55fe3abd36 Mon Sep 17 00:00:00 2001 From: Dundar Göc Date: Fri, 26 Aug 2022 23:11:25 +0200 Subject: refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/api/autocmd.c | 2 +- src/nvim/api/command.c | 2 +- src/nvim/api/extmark.c | 6 +++--- src/nvim/api/ui.c | 2 +- src/nvim/api/vimscript.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c index 1cf0211f43..99340a3c59 100644 --- a/src/nvim/api/autocmd.c +++ b/src/nvim/api/autocmd.c @@ -240,7 +240,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) assert(pattern_filters[i]); char *pat = pattern_filters[i]; - int patlen = (int)STRLEN(pat); + int patlen = (int)strlen(pat); if (aupat_is_buflocal(pat, patlen)) { aupat_normalize_buflocal_pat(pattern_buflocal, diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index b3518f1b0f..ed0907e8f8 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -105,7 +105,7 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err) // Parse arguments Array args = ARRAY_DICT_INIT; - size_t length = STRLEN(ea.arg); + size_t length = strlen(ea.arg); // For nargs = 1 or '?', pass the entire argument list as a single argument, // otherwise split arguments by whitespace. diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index ae051d8cab..edcea52838 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -742,7 +742,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer line = buf->b_ml.ml_line_count; } } else if (line < buf->b_ml.ml_line_count) { - len = ephemeral ? MAXCOL : STRLEN(ml_get_buf(buf, (linenr_T)line + 1, false)); + len = ephemeral ? MAXCOL : strlen(ml_get_buf(buf, (linenr_T)line + 1, false)); } if (col == -1) { @@ -761,7 +761,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer if (col2 >= 0) { if (line2 >= 0 && line2 < buf->b_ml.ml_line_count) { - len = ephemeral ? MAXCOL : STRLEN(ml_get_buf(buf, (linenr_T)line2 + 1, false)); + len = ephemeral ? MAXCOL : strlen(ml_get_buf(buf, (linenr_T)line2 + 1, false)); } else if (line2 == buf->b_ml.ml_line_count) { // We are trying to add an extmark past final newline len = 0; @@ -1106,7 +1106,7 @@ static int init_sign_text(char **sign_text, char *text) { char *s; - char *endp = text + (int)STRLEN(text); + char *endp = text + (int)strlen(text); // Count cells and check for non-printable chars int cells = 0; diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 27fb4b8e16..45c20d07e1 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -122,7 +122,7 @@ static char *mpack_array_dyn16(char **buf) static void mpack_str(char **buf, const char *str) { assert(sizeof(schar_T) - 1 < 0x20); - size_t len = STRLEN(str); + size_t len = strlen(str); mpack_w(buf, 0xa0 | len); memcpy(*buf, str, len); *buf += len; diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c index f6d0e39327..1758f18926 100644 --- a/src/nvim/api/vimscript.c +++ b/src/nvim/api/vimscript.c @@ -304,7 +304,7 @@ Object nvim_call_dict_function(Object dict, String fn, Array args, Error *err) } fn = (String) { .data = di->di_tv.vval.v_string, - .size = STRLEN(di->di_tv.vval.v_string), + .size = strlen(di->di_tv.vval.v_string), }; } -- cgit From 0f93aa12fdb07fd452706da8d13c590c86ce21de Mon Sep 17 00:00:00 2001 From: kylo252 <59826753+kylo252@users.noreply.github.com> Date: Fri, 16 Sep 2022 09:18:42 +0200 Subject: docs(autocmds): re-add buffer param to docstring (#20204) --- src/nvim/api/autocmd.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c index 99340a3c59..ac4cb953b8 100644 --- a/src/nvim/api/autocmd.c +++ b/src/nvim/api/autocmd.c @@ -59,6 +59,9 @@ static int64_t next_autocmd_id = 1; /// - group (string|integer): the autocommand group name or id to match against. /// - event (string|array): event or events to match against |autocmd-events|. /// - pattern (string|array): pattern or patterns to match against |autocmd-pattern|. +/// Cannot be used with {buffer} +/// - buffer: Buffer number or list of buffer numbers for buffer local autocommands +/// |autocmd-buflocal|. Cannot be used with {pattern} /// @return Array of autocommands matching the criteria, with each item /// containing the following fields: /// - id (number): the autocommand id (only when defined with the API). -- cgit From 3dda52d860eb4937127693d4660db18305069370 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 16 Sep 2022 17:31:42 +0800 Subject: vim-patch:8.2.3796: the funcexe_T struct members are not named consistently (#20214) Problem: The funcexe_T struct members are not named consistently. Solution: Prefix "fe_" to all the members. https://github.com/vim/vim/commit/851f86b951cdd67ad9cf3149e46169d1375c8d82 Omit fe_check_type: always NULL in legacy Vim script. --- src/nvim/api/vimscript.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c index 1758f18926..71209c9ab6 100644 --- a/src/nvim/api/vimscript.c +++ b/src/nvim/api/vimscript.c @@ -204,10 +204,10 @@ static Object _call_function(String fn, Array args, dict_T *self, Error *err) 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; + funcexe.fe_firstline = curwin->w_cursor.lnum; + funcexe.fe_lastline = curwin->w_cursor.lnum; + funcexe.fe_evaluate = true; + funcexe.fe_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(fn.data, (int)fn.size, &rettv, (int)args.size, -- cgit From 6d557e324fd4223fff3279a0112f40431c540163 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sun, 18 Sep 2022 03:17:15 +0200 Subject: vim-patch:8.1.0941: macros for MS-Windows are inconsistent (#20215) Problem: Macros for MS-Windows are inconsistent, using "32", "3264 and others. Solution: Use MSWIN for all MS-Windows builds. Use FEAT_GUI_MSWIN for the GUI build. (Hirohito Higashi, closes vim/vim#3932) https://github.com/vim/vim/commit/4f97475d326c2773a78561fb874e4f23c25cbcd9 --- src/nvim/api/vim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 95c9919522..ad9ed72f43 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1882,7 +1882,7 @@ Object nvim_get_proc(Integer pid, Error *err) api_set_error(err, kErrorTypeException, "Invalid pid: %" PRId64, pid); return NIL; } -#ifdef WIN32 +#ifdef MSWIN rvobj.data.dictionary = os_proc_info((int)pid); if (rvobj.data.dictionary.size == 0) { // Process not found. return NIL; -- cgit From 91e912f8d40284c74d4a997c8c95961eebb35d91 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sun, 25 Sep 2022 15:26:37 +0200 Subject: refactor: move klib out of src/nvim/ #20341 It's confusing to mix vendored dependencies with neovim source code. A clean separation is simpler to keep track of and simpler to document. --- src/nvim/api/private/defs.h | 2 +- src/nvim/api/private/helpers.c | 2 +- src/nvim/api/private/helpers.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h index 9c7e59e4b3..2ae3ee6c7c 100644 --- a/src/nvim/api/private/defs.h +++ b/src/nvim/api/private/defs.h @@ -5,8 +5,8 @@ #include #include +#include "klib/kvec.h" #include "nvim/func_attr.h" -#include "nvim/lib/kvec.h" #include "nvim/types.h" #define ARRAY_DICT_INIT KV_INITIAL_VALUE diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 22d2ffbaf1..b888d09343 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -8,6 +8,7 @@ #include #include +#include "klib/kvec.h" #include "nvim/api/private/converter.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" @@ -22,7 +23,6 @@ #include "nvim/ex_eval.h" #include "nvim/extmark.h" #include "nvim/highlight_group.h" -#include "nvim/lib/kvec.h" #include "nvim/lua/executor.h" #include "nvim/map.h" #include "nvim/map_defs.h" diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index 2157ad0ec2..65215fa8c8 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -1,11 +1,11 @@ #ifndef NVIM_API_PRIVATE_HELPERS_H #define NVIM_API_PRIVATE_HELPERS_H +#include "klib/kvec.h" #include "nvim/api/private/defs.h" #include "nvim/decoration.h" #include "nvim/ex_eval_defs.h" #include "nvim/getchar.h" -#include "nvim/lib/kvec.h" #include "nvim/memory.h" #include "nvim/vim.h" -- cgit From 63be7651829f8b77c4974d08ebe09f7775e41a8a Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 25 Sep 2022 19:58:27 -0400 Subject: fix(docs): invalid :help links #20345 Fix those naughty single quotes. closes #20159 --- src/nvim/api/autocmd.c | 8 ++++---- src/nvim/api/extmark.c | 6 +++--- src/nvim/api/options.c | 4 ++-- src/nvim/api/vim.c | 14 +++++++------- src/nvim/api/win_config.c | 2 +- src/nvim/api/window.c | 2 +- 6 files changed, 18 insertions(+), 18 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c index ac4cb953b8..b5c695b9ce 100644 --- a/src/nvim/api/autocmd.c +++ b/src/nvim/api/autocmd.c @@ -599,7 +599,7 @@ void nvim_del_autocmd(Integer id, Error *err) } /// Clear all autocommands that match the corresponding {opts}. To delete -/// a particular autocmd, see |nvim_del_autocmd|. +/// a particular autocmd, see |nvim_del_autocmd()|. /// @param opts Parameters /// - event: (string|table) /// Examples: @@ -728,7 +728,7 @@ Integer nvim_create_augroup(uint64_t channel_id, String name, Dict(create_augrou /// /// To get a group id one can use |nvim_get_autocmds()|. /// -/// NOTE: behavior differs from |augroup-delete|. When deleting a group, autocommands contained in +/// NOTE: behavior differs from |:augroup-delete|. When deleting a group, autocommands contained in /// this group will also be deleted and cleared. This group will no longer exist. /// @param id Integer The id of the group. /// @see |nvim_del_augroup_by_name()| @@ -746,10 +746,10 @@ void nvim_del_augroup_by_id(Integer id, Error *err) /// Delete an autocommand group by name. /// -/// NOTE: behavior differs from |augroup-delete|. When deleting a group, autocommands contained in +/// NOTE: behavior differs from |:augroup-delete|. When deleting a group, autocommands contained in /// this group will also be deleted and cleared. This group will no longer exist. /// @param name String The name of the group. -/// @see |autocommand-groups| +/// @see |autocmd-groups| void nvim_del_augroup_by_name(String name, Error *err) FUNC_API_SINCE(9) { diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index edcea52838..c92a97519d 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -393,7 +393,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e /// multiple highlight groups that will be stacked /// (highest priority last). A highlight group can be supplied /// either as a string or as an integer, the latter which -/// can be obtained using |nvim_get_hl_id_by_name|. +/// can be obtained using |nvim_get_hl_id_by_name()|. /// - virt_text_pos : position of virtual text. Possible values: /// - "eol": right after eol character (default) /// - "overlay": display over the specified column, without @@ -430,7 +430,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e /// column of the window, bypassing /// sign and number columns. /// -/// - ephemeral : for use with |nvim_set_decoration_provider| +/// - ephemeral : for use with |nvim_set_decoration_provider()| /// callbacks. The mark will only be used for the current /// redraw cycle, and not be permantently stored in the /// buffer. @@ -958,7 +958,7 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start, /// being triggered during the redraw code. /// /// The expected usage is to set extmarks for the currently -/// redrawn buffer. |nvim_buf_set_extmark| can be called to add marks +/// redrawn buffer. |nvim_buf_set_extmark()| can be called to add marks /// on a per-window or per-lines basis. Use the `ephemeral` key to only /// use the mark for the current screen redraw (the callback will be called /// again for the next redraw ). diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c index 867584dd71..ec1f19cf6a 100644 --- a/src/nvim/api/options.c +++ b/src/nvim/api/options.c @@ -147,7 +147,7 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err) /// @param name Option name /// @param value New option value /// @param opts Optional parameters -/// - scope: One of 'global' or 'local'. Analogous to +/// - scope: One of "global" or "local". Analogous to /// |:setglobal| and |:setlocal|, respectively. /// - win: |window-ID|. Used for setting window local option. /// - buf: Buffer number. Used for setting buffer local option. @@ -202,7 +202,7 @@ void nvim_set_option_value(String name, Object value, Dict(option) *opts, Error /// Gets the option information for all options. /// /// The dictionary has the full option names as keys and option metadata -/// dictionaries as detailed at |nvim_get_option_info|. +/// dictionaries as detailed at |nvim_get_option_info()|. /// /// @return dictionary of all options Dictionary nvim_get_all_options_info(Error *err) diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index ad9ed72f43..d65127e406 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -160,8 +160,8 @@ Dictionary nvim__get_hl_defs(Integer ns_id, Arena *arena, Error *err) /// - nocombine: boolean /// - link: name of another highlight group to link to, see |:hi-link|. /// - default: Don't override existing definition |:hi-default| -/// - ctermfg: Sets foreground of cterm color |highlight-ctermfg| -/// - ctermbg: Sets background of cterm color |highlight-ctermbg| +/// - ctermfg: Sets foreground of cterm color |ctermfg| +/// - ctermbg: Sets background of cterm color |ctermbg| /// - cterm: cterm attribute map, like |highlight-args|. If not set, /// cterm attributes will match those from the attribute map /// documented above. @@ -185,7 +185,7 @@ void nvim_set_hl(Integer ns_id, String name, Dict(highlight) *val, Error *err) } /// Set active namespace for highlights. This can be set for a single window, -/// see |nvim_win_set_hl_ns|. +/// see |nvim_win_set_hl_ns()|. /// /// @param ns_id the namespace to use /// @param[out] err Error details, if any @@ -205,7 +205,7 @@ void nvim_set_hl_ns(Integer ns_id, Error *err) /// Set active namespace for highlights while redrawing. /// /// This function meant to be called while redrawing, primarily from -/// |nvim_set_decoration_provider| on_win and on_line callbacks, which +/// |nvim_set_decoration_provider()| on_win and on_line callbacks, which /// are allowed to change the namespace during a redraw cycle. /// /// @param ns_id the namespace to activate @@ -523,7 +523,7 @@ Array nvim__runtime_inspect(void) /// Find files in runtime directories /// -/// 'name' can contain wildcards. For example +/// "name" can contain wildcards. For example /// nvim_get_runtime_file("colors/*.vim", true) will return all color /// scheme files. Always use forward slashes (/) in the search pattern for /// subdirectories regardless of platform. @@ -964,7 +964,7 @@ fail: /// mode. Note: keypresses are sent raw as they would be to the pty /// master end. For instance, a carriage return is sent /// as a "\r", not as a "\n". |textlock| applies. It is possible -/// to call |nvim_chan_send| directly in the callback however. +/// to call |nvim_chan_send()| directly in the callback however. /// ["input", term, bufnr, data] /// @param[out] err Error details, if any /// @return Channel id, or 0 on error @@ -1452,7 +1452,7 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode) /// @param rhs Right-hand-side |{rhs}| of the mapping. /// @param opts Optional parameters map: keys are |:map-arguments|, values are booleans (default /// false). Accepts all |:map-arguments| as keys excluding || but including -/// |noremap| and "desc". Unknown key is an error. +/// |:noremap| and "desc". Unknown key is an error. /// "desc" can be used to give a description to the mapping. /// When called from Lua, also accepts a "callback" key that takes a Lua function to /// call when the mapping is executed. diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index 96c560efa1..636b9566ce 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -109,7 +109,7 @@ /// is changed to `auto` and 'colorcolumn' is cleared. The /// end-of-buffer region is hidden by setting `eob` flag of /// 'fillchars' to a space char, and clearing the -/// |EndOfBuffer| region in 'winhighlight'. +/// |hl-EndOfBuffer| region in 'winhighlight'. /// - border: Style of (optional) window border. This can either be a string /// or an array. The string values are /// - "none": No border (default). diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index 5203003369..59e806adb1 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -340,7 +340,7 @@ Boolean nvim_win_is_valid(Window window) /// /// Like |:hide| the buffer becomes hidden unless another window is editing it, /// or 'bufhidden' is `unload`, `delete` or `wipe` as opposed to |:close| or -/// |nvim_win_close|, which will close the buffer. +/// |nvim_win_close()|, which will close the buffer. /// /// @param window Window handle, or 0 for current window /// @param[out] err Error details, if any -- cgit From c815aadfccd6bada47ecfb09fe188ee7f7c5caf3 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Mon, 26 Sep 2022 11:43:23 +0200 Subject: docs: fix typos (#20150) Co-authored-by: Miguel Carneiro Co-authored-by: Gregory Anders Co-authored-by: Raphael Co-authored-by: C.D. MacEachern Co-authored-by: zeertzjq --- src/nvim/api/ui.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 45c20d07e1..e6d8cb2fdb 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -453,7 +453,7 @@ void nvim_ui_try_resize_grid(uint64_t channel_id, Integer grid, Integer width, I } } -/// Tells Nvim the number of elements displaying in the popumenu, to decide +/// Tells Nvim the number of elements displaying in the popupmenu, to decide /// and movement. /// /// @param channel_id @@ -483,7 +483,7 @@ void nvim_ui_pum_set_height(uint64_t channel_id, Integer height, Error *err) ui->pum_nlines = (int)height; } -/// Tells Nvim the geometry of the popumenu, to align floating windows with an +/// Tells Nvim the geometry of the popupmenu, to align floating windows with an /// external popup menu. /// /// Note that this method is not to be confused with |nvim_ui_pum_set_height()|, -- cgit From c7d30c152d1639523d05154e245ea60ed9a51a2b Mon Sep 17 00:00:00 2001 From: smolck <46855713+smolck@users.noreply.github.com> Date: Sat, 14 Aug 2021 12:19:05 -0500 Subject: fix(api): notify dict watchers on nvim_set_var and vim.g setter Co-authored-by: bfredl Co-authored-by: Christian Clason --- src/nvim/api/private/helpers.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index b888d09343..73b5489d5c 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -218,6 +218,8 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva return rv; } + bool watched = tv_dict_is_watched(dict); + if (del) { // Delete the key if (di == NULL) { @@ -225,6 +227,10 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva api_set_error(err, kErrorTypeValidation, "Key not found: %s", key.data); } else { + // Notify watchers + if (watched) { + tv_dict_watcher_notify(dict, key.data, NULL, &di->di_tv); + } // Return the old value if (retval) { rv = vim_to_object(&di->di_tv); @@ -241,11 +247,16 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva return rv; } + typval_T oldtv = TV_INITIAL_VALUE; + if (di == NULL) { // Need to create an entry di = tv_dict_item_alloc_len(key.data, key.size); tv_dict_add(dict, di); } else { + if (watched) { + tv_copy(&di->di_tv, &oldtv); + } // Return the old value if (retval) { rv = vim_to_object(&di->di_tv); @@ -255,6 +266,13 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva // Update the value tv_copy(&tv, &di->di_tv); + + // Notify watchers + if (watched) { + tv_dict_watcher_notify(dict, key.data, &tv, &oldtv); + tv_clear(&oldtv); + } + // Clear the temporary variable tv_clear(&tv); } -- cgit From 35e2c4a2edd28f72c48c70530c5486365c2502a4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 28 Sep 2022 18:27:59 +0800 Subject: fix(lua): fix architecture-dependent behavior in usercmd "reg" (#20384) I don't think using an integer as a NUL-terminated string can work on big-endian systems, at least. This is also not tested. Add a test. Also fix a mistake in the docs of nvim_parse_cmd. --- src/nvim/api/command.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index ed0907e8f8..699c62c15c 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -37,7 +37,7 @@ /// specified and two elements if both range items were specified. /// - count: (number) Any || that was supplied to the command. -1 if command cannot /// take a count. -/// - reg: (number) The optional command ||, if specified. Empty string if not +/// - reg: (string) The optional command ||, if specified. Empty string if not /// specified or if command cannot take a register. /// - bang: (boolean) Whether command contains a || (!) modifier. /// - args: (array) Command arguments. @@ -165,9 +165,7 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err) PUT(result, "count", INTEGER_OBJ(-1)); } - char reg[2]; - reg[0] = (char)ea.regname; - reg[1] = '\0'; + char reg[2] = { (char)ea.regname, NUL }; PUT(result, "reg", CSTR_TO_OBJ(reg)); PUT(result, "bang", BOOLEAN_OBJ(ea.forceit)); -- cgit From 45707c1eae62667e5c482a09f6d9a62e01db0e21 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 29 Sep 2022 16:04:14 +0800 Subject: fix(api): fix nvim_cmd crash with filename expansion (#20397) --- src/nvim/api/command.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index 699c62c15c..ab166c6b38 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -830,13 +830,12 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin // Replace, :make and :grep with 'makeprg' and 'grepprg'. char *p = replace_makeprg(eap, eap->arg, cmdlinep); if (p != eap->arg) { - // If replace_makeprg modified the cmdline string, correct the argument pointers. + // If replace_makeprg() modified the cmdline string, correct the eap->arg pointer. eap->arg = p; - // We can only know the position of the first argument because the argument list can be used - // multiple times in makeprg / grepprg. - if (argc >= 1) { - eap->args[0] = p; - } + // This cannot be a user command, so eap->args will not be used. + XFREE_CLEAR(eap->args); + XFREE_CLEAR(eap->arglens); + eap->argc = 0; } } -- cgit From e46eef75ac2c3336928269e28a1fa138f7327207 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Wed, 28 Sep 2022 17:43:18 +0600 Subject: feat(nvim_cmd): allow using first argument as count Allows `nvim_cmd` to use the first argument as count for applicable commands. Also adds support for non-String arguments to `nvim_cmd`. --- src/nvim/api/command.c | 67 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 20 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index ab166c6b38..d410466c44 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -283,7 +283,11 @@ end: /// Unlike |nvim_command()| this command takes a structured Dictionary instead of a String. This /// allows for easier construction and manipulation of an Ex command. This also allows for things /// such as having spaces inside a command argument, expanding filenames in a command that otherwise -/// doesn't expand filenames, etc. +/// doesn't expand filenames, etc. Command arguments may also be Number, Boolean or String. +/// +/// The first argument may also be used instead of count for commands that support it in order to +/// make their usage simpler with |vim.cmd()|. For example, instead of +/// `vim.cmd.bdelete{ count = 2 }`, you may do `vim.cmd.bdelete(2)`. /// /// On execution error: fails with VimL error, updates v:errmsg. /// @@ -308,8 +312,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error char *cmdline = NULL; char *cmdname = NULL; - ArrayOf(String) args; - size_t argc = 0; + ArrayOf(String) args = ARRAY_DICT_INIT; String retv = (String)STRING_INIT; @@ -381,48 +384,70 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error if (cmd->args.type != kObjectTypeArray) { VALIDATION_ERROR("'args' must be an Array"); } - // Check if every argument is valid + + // Process all arguments. Convert non-String arguments to String and check if String arguments + // have non-whitespace characters. for (size_t i = 0; i < cmd->args.data.array.size; i++) { Object elem = cmd->args.data.array.items[i]; - if (elem.type != kObjectTypeString) { - VALIDATION_ERROR("Command argument must be a String"); - } else if (string_iswhite(elem.data.string)) { - VALIDATION_ERROR("Command argument must have non-whitespace characters"); + char *data_str; + + switch (elem.type) { + case kObjectTypeBoolean: + data_str = xcalloc(2, sizeof(char)); + data_str[0] = elem.data.boolean ? '1' : '0'; + data_str[1] = '\0'; + break; + case kObjectTypeBuffer: + case kObjectTypeWindow: + case kObjectTypeTabpage: + case kObjectTypeInteger: + data_str = xcalloc(NUMBUFLEN, sizeof(char)); + snprintf(data_str, NUMBUFLEN, "%" PRId64, elem.data.integer); + break; + case kObjectTypeString: + if (string_iswhite(elem.data.string)) { + VALIDATION_ERROR("String command argument must have at least one non-whitespace " + "character"); + } + data_str = xstrndup(elem.data.string.data, elem.data.string.size); + break; + default: + VALIDATION_ERROR("Invalid type for command argument"); + break; } + + ADD(args, STRING_OBJ(cstr_as_string(data_str))); } - argc = cmd->args.data.array.size; bool argc_valid; // Check if correct number of arguments is used. switch (ea.argt & (EX_EXTRA | EX_NOSPC | EX_NEEDARG)) { case EX_EXTRA | EX_NOSPC | EX_NEEDARG: - argc_valid = argc == 1; + argc_valid = args.size == 1; break; case EX_EXTRA | EX_NOSPC: - argc_valid = argc <= 1; + argc_valid = args.size <= 1; break; case EX_EXTRA | EX_NEEDARG: - argc_valid = argc >= 1; + argc_valid = args.size >= 1; break; case EX_EXTRA: argc_valid = true; break; default: - argc_valid = argc == 0; + argc_valid = args.size == 0; break; } if (!argc_valid) { VALIDATION_ERROR("Incorrect number of arguments supplied"); } - - args = cmd->args.data.array; } // Simply pass the first argument (if it exists) as the arg pointer to `set_cmd_addr_type()` // since it only ever checks the first argument. - set_cmd_addr_type(&ea, argc > 0 ? args.items[0].data.string.data : NULL); + set_cmd_addr_type(&ea, args.size > 0 ? args.items[0].data.string.data : NULL); if (HAS_KEY(cmd->range)) { if (!(ea.argt & EX_RANGE)) { @@ -626,7 +651,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error // Finally, build the command line string that will be stored inside ea.cmdlinep. // This also sets the values of ea.cmd, ea.arg, ea.args and ea.arglens. - build_cmdline_str(&cmdline, &ea, &cmdinfo, args, argc); + build_cmdline_str(&cmdline, &ea, &cmdinfo, args); ea.cmdlinep = &cmdline; garray_T capture_local; @@ -682,6 +707,7 @@ clear_ga: ga_clear(&capture_local); } end: + api_free_array(args); xfree(cmdline); xfree(cmdname); xfree(ea.args); @@ -711,8 +737,9 @@ static bool string_iswhite(String str) /// Build cmdline string for command, used by `nvim_cmd()`. static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdinfo, - ArrayOf(String) args, size_t argc) + ArrayOf(String) args) { + size_t argc = args.size; StringBuilder cmdline = KV_INITIAL_VALUE; kv_resize(cmdline, 32); // Make it big enough to handle most typical commands @@ -798,7 +825,7 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin } eap->argc = argc; - eap->arglens = xcalloc(argc, sizeof(size_t)); + eap->arglens = eap->argc > 0 ? xcalloc(argc, sizeof(size_t)) : NULL; size_t argstart_idx = cmdline.size; for (size_t i = 0; i < argc; i++) { String s = args.items[i].data.string; @@ -813,7 +840,7 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin // Now that all the arguments are appended, use the command index and argument indices to set the // values of eap->cmd, eap->arg and eap->args. eap->cmd = cmdline.items + cmdname_idx; - eap->args = xcalloc(argc, sizeof(char *)); + eap->args = eap->argc > 0 ? xcalloc(argc, sizeof(char *)) : NULL; size_t offset = argstart_idx; for (size_t i = 0; i < argc; i++) { offset++; // Account for space -- cgit From cb62592bcb03d7934416cf46bede3b8296254c87 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 27 Sep 2022 14:40:10 +0800 Subject: fix(api)!: nvim_parse_cmd omit "count" "range" "reg" if not supported --- src/nvim/api/command.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index ab166c6b38..53701a8c7c 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -31,14 +31,15 @@ /// @param[out] err Error details, if any. /// @return Dictionary containing command information, with these keys: /// - cmd: (string) Command name. -/// - range: (array) Command . Can have 0-2 elements depending on how many items the -/// range contains. Has no elements if command doesn't accept a range or if -/// no range was specified, one element if only a single range item was -/// specified and two elements if both range items were specified. -/// - count: (number) Any || that was supplied to the command. -1 if command cannot -/// take a count. -/// - reg: (string) The optional command ||, if specified. Empty string if not -/// specified or if command cannot take a register. +/// - range: (array) (optional) Command range (|| ||). +/// Omitted if command doesn't accept a range. +/// Otherwise, has no elements if no range was specified, one element if +/// only a single range item was specified, or two elements if both range +/// items were specified. +/// - count: (number) (optional) Command ||. +/// Omitted if command cannot take a count. +/// - reg: (string) (optional) Command ||. +/// Omitted if command cannot take a register. /// - bang: (boolean) Whether command contains a || (!) modifier. /// - args: (array) Command arguments. /// - addr: (string) Value of |:command-addr|. Uses short name. @@ -142,15 +143,15 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err) PUT(result, "cmd", CSTR_TO_OBJ((char *)get_command_name(NULL, ea.cmdidx))); } - if ((ea.argt & EX_RANGE) && ea.addr_count > 0) { + if (ea.argt & EX_RANGE) { Array range = ARRAY_DICT_INIT; - if (ea.addr_count > 1) { - ADD(range, INTEGER_OBJ(ea.line1)); + if (ea.addr_count > 0) { + if (ea.addr_count > 1) { + ADD(range, INTEGER_OBJ(ea.line1)); + } + ADD(range, INTEGER_OBJ(ea.line2)); } - ADD(range, INTEGER_OBJ(ea.line2)); PUT(result, "range", ARRAY_OBJ(range)); - } else { - PUT(result, "range", ARRAY_OBJ(ARRAY_DICT_INIT)); } if (ea.argt & EX_COUNT) { @@ -161,12 +162,12 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err) } else { PUT(result, "count", INTEGER_OBJ(0)); } - } else { - PUT(result, "count", INTEGER_OBJ(-1)); } - char reg[2] = { (char)ea.regname, NUL }; - PUT(result, "reg", CSTR_TO_OBJ(reg)); + if (ea.argt & EX_REGSTR) { + char reg[2] = { (char)ea.regname, NUL }; + PUT(result, "reg", CSTR_TO_OBJ(reg)); + } PUT(result, "bang", BOOLEAN_OBJ(ea.forceit)); PUT(result, "args", ARRAY_OBJ(args)); -- cgit From df646572c53f55268a5dbb61628d7c3b302d5663 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Fri, 30 Sep 2022 09:53:52 +0200 Subject: docs: fix typos (#20394) Co-authored-by: Raphael Co-authored-by: smjonas Co-authored-by: zeertzjq --- src/nvim/api/extmark.c | 2 +- src/nvim/api/window.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index c92a97519d..3b1b470629 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -389,7 +389,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e /// - virt_text : virtual text to link to this mark. /// A list of [text, highlight] tuples, each representing a /// text chunk with specified highlight. `highlight` element -/// can either be a a single highlight group, or an array of +/// can either be a single highlight group, or an array of /// multiple highlight groups that will be stacked /// (highest priority last). A highlight group can be supplied /// either as a string or as an integer, the latter which diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index 59e806adb1..aaff00d640 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -430,7 +430,7 @@ Object nvim_win_call(Window window, LuaRef fun, Error *err) /// Set highlight namespace for a window. This will use highlights defined in /// this namespace, but fall back to global highlights (ns=0) when missing. /// -/// This takes predecence over the 'winhighlight' option. +/// This takes precedence over the 'winhighlight' option. /// /// @param ns_id the namespace to use /// @param[out] err Error details, if any -- cgit From 2a12faaec18115bf057427834832ff20ccb3ffd4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 8 Oct 2022 20:10:00 +0800 Subject: fix(api): dynamically allocate line buffer for nvim_out_write (#20537) --- src/nvim/api/vim.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index d65127e406..fa8d26914a 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -66,7 +66,7 @@ #include "nvim/viml/parser/parser.h" #include "nvim/window.h" -#define LINE_BUFFER_SIZE 4096 +#define LINE_BUFFER_MIN_SIZE 4096 #ifdef INCLUDE_GENERATED_DECLARATIONS # include "api/vim.c.generated.h" @@ -1718,17 +1718,21 @@ theend: /// @param to_err true: message is an error (uses `emsg` instead of `msg`) static void write_msg(String message, bool to_err) { - static size_t out_pos = 0, err_pos = 0; - static char out_line_buf[LINE_BUFFER_SIZE], err_line_buf[LINE_BUFFER_SIZE]; + static StringBuilder out_line_buf = KV_INITIAL_VALUE; + static StringBuilder err_line_buf = KV_INITIAL_VALUE; -#define PUSH_CHAR(i, pos, line_buf, msg) \ - if (message.data[i] == NL || (pos) == LINE_BUFFER_SIZE - 1) { \ - (line_buf)[pos] = NUL; \ - msg(line_buf); \ - (pos) = 0; \ +#define PUSH_CHAR(i, line_buf, msg) \ + if (kv_max(line_buf) == 0) { \ + kv_resize(line_buf, LINE_BUFFER_MIN_SIZE); \ + } \ + if (message.data[i] == NL) { \ + kv_push(line_buf, NUL); \ + msg(line_buf.items); \ + kv_drop(line_buf, kv_size(line_buf)); \ + kv_resize(line_buf, LINE_BUFFER_MIN_SIZE); \ continue; \ } \ - (line_buf)[(pos)++] = message.data[i]; + kv_push(line_buf, message.data[i]); no_wait_return++; for (uint32_t i = 0; i < message.size; i++) { @@ -1736,9 +1740,9 @@ static void write_msg(String message, bool to_err) break; } if (to_err) { - PUSH_CHAR(i, err_pos, err_line_buf, emsg); + PUSH_CHAR(i, err_line_buf, emsg); } else { - PUSH_CHAR(i, out_pos, out_line_buf, msg); + PUSH_CHAR(i, out_line_buf, msg); } } no_wait_return--; -- cgit From 09dffb9db7d16496e55e86f78ab60241533d86f6 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 9 Oct 2022 08:21:52 -0400 Subject: docs: various #12823 - increase python line-length limit from 88 => 100. - gen_help_html: fix bug in "tag" case (tbl_count => tbl_contains) ref #15632 fix #18215 fix #18479 fix #20527 fix #20532 Co-authored-by: Ben Weedon --- src/nvim/api/buffer.c | 4 ++++ src/nvim/api/window.c | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 6f8cad3e33..51fedb302a 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -355,6 +355,8 @@ static bool check_string_array(Array arr, bool disallow_nl, Error *err) /// Out-of-bounds indices are clamped to the nearest valid value, unless /// `strict_indexing` is set. /// +/// @see |nvim_buf_set_text()| +/// /// @param channel_id /// @param buffer Buffer handle, or 0 for current buffer /// @param start First line index @@ -527,6 +529,8 @@ end: /// /// Prefer |nvim_buf_set_lines()| if you are only adding or deleting entire lines. /// +/// @see |nvim_buf_set_lines()| +/// /// @param channel_id /// @param buffer Buffer handle, or 0 for current buffer /// @param start_row First line index diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index aaff00d640..08dcc113da 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -51,7 +51,9 @@ void nvim_win_set_buf(Window window, Buffer buffer, Error *err) win_set_buf(window, buffer, false, err); } -/// Gets the (1,0)-indexed cursor position in the window. |api-indexing| +/// Gets the (1,0)-indexed, buffer-relative cursor position for a given window +/// (different windows showing the same buffer have independent cursor +/// positions). |api-indexing| /// /// @param window Window handle, or 0 for current window /// @param[out] err Error details, if any -- cgit