From 543e0256c19f397921a332e06b423215fd9aecb5 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 30 Nov 2023 15:51:05 +0800 Subject: build: don't define FUNC_ATTR_* as empty in headers (#26317) FUNC_ATTR_* should only be used in .c files with generated headers. Defining FUNC_ATTR_* as empty in headers causes misuses of them to be silently ignored. Instead don't define them by default, and only define them as empty after a .c file has included its generated header. --- src/nvim/eval/buffer.c | 1 - src/nvim/eval/decode.c | 1 - src/nvim/eval/encode.h | 4 +++- src/nvim/eval/executor.c | 3 +-- src/nvim/eval/funcs.c | 1 - src/nvim/eval/typval.h | 12 ++++++------ src/nvim/eval/userfunc.c | 1 - src/nvim/eval/vars.c | 1 - 8 files changed, 10 insertions(+), 14 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index c60a104381..1f3b92804d 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -14,7 +14,6 @@ #include "nvim/eval/funcs.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" -#include "nvim/func_attr.h" #include "nvim/globals.h" #include "nvim/macros_defs.h" #include "nvim/memline.h" diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index 03f79fca84..a6407693d7 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -14,7 +14,6 @@ #include "nvim/eval/encode.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" -#include "nvim/func_attr.h" #include "nvim/garray.h" #include "nvim/gettext.h" #include "nvim/macros_defs.h" diff --git a/src/nvim/eval/encode.h b/src/nvim/eval/encode.h index 26a3286f2b..699956d8ac 100644 --- a/src/nvim/eval/encode.h +++ b/src/nvim/eval/encode.h @@ -36,9 +36,11 @@ typedef struct { size_t li_length; ///< Length of the string inside the read item. } ListReaderState; +static inline ListReaderState encode_init_lrstate(const list_T *list) + REAL_FATTR_NONNULL_ALL; + /// Initialize ListReaderState structure static inline ListReaderState encode_init_lrstate(const list_T *const list) - FUNC_ATTR_NONNULL_ALL { return (ListReaderState) { .list = list, diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c index dc23fcdc72..b483f5fbef 100644 --- a/src/nvim/eval/executor.c +++ b/src/nvim/eval/executor.c @@ -5,7 +5,6 @@ #include "nvim/eval/executor.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" -#include "nvim/func_attr.h" #include "nvim/garray.h" #include "nvim/gettext.h" #include "nvim/globals.h" @@ -15,7 +14,7 @@ #include "nvim/vim_defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS -# include "eval/executor.c.generated.h" // IWYU pragma: export +# include "eval/executor.c.generated.h" #endif char *e_list_index_out_of_range_nr diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 13425b21d1..0054c47678 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -58,7 +58,6 @@ #include "nvim/ex_getln.h" #include "nvim/file_search.h" #include "nvim/fileio.h" -#include "nvim/func_attr.h" #include "nvim/garray.h" #include "nvim/getchar.h" #include "nvim/gettext.h" diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 58f74a9796..efa6017f4b 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -85,6 +85,9 @@ static inline void tv_list_set_lock(list_T *const l, const VarLockStatus lock) l->lv_lock = lock; } +static inline void tv_list_set_copyid(list_T *l, int copyid) + REAL_FATTR_NONNULL_ALL; + /// Set list copyID /// /// Does not expect NULL list, be careful. @@ -92,7 +95,6 @@ static inline void tv_list_set_lock(list_T *const l, const VarLockStatus lock) /// @param[out] l List to modify. /// @param[in] copyid New copyID. static inline void tv_list_set_copyid(list_T *const l, const int copyid) - FUNC_ATTR_NONNULL_ALL { l->lv_copyID = copyid; } @@ -442,22 +444,20 @@ static inline bool tv_get_float_chk(const typval_T *const tv, float_T *const ret } static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q) - REAL_FATTR_NONNULL_ALL REAL_FATTR_NONNULL_RET REAL_FATTR_PURE - REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE - FUNC_ATTR_NO_SANITIZE_ADDRESS; + REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL REAL_FATTR_NONNULL_RET + REAL_FATTR_NO_SANITIZE_ADDRESS REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; /// Compute the `DictWatcher` address from a QUEUE node. /// /// This only exists for .asan-blacklist (ASAN doesn't handle QUEUE_DATA pointer /// arithmetic). static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q) - FUNC_ATTR_NO_SANITIZE_ADDRESS { return QUEUE_DATA(q, DictWatcher, node); } static inline bool tv_is_func(typval_T tv) - FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_CONST; + REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE REAL_FATTR_CONST; /// Check whether given typval_T contains a function /// diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 23b3c4e1b2..e0bf30b158 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -23,7 +23,6 @@ #include "nvim/ex_docmd.h" #include "nvim/ex_eval.h" #include "nvim/ex_getln.h" -#include "nvim/func_attr.h" #include "nvim/garray.h" #include "nvim/getchar.h" #include "nvim/gettext.h" diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 2968f75f4d..670ee39f4b 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -25,7 +25,6 @@ #include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" #include "nvim/ex_eval.h" -#include "nvim/func_attr.h" #include "nvim/garray.h" #include "nvim/gettext.h" #include "nvim/globals.h" -- cgit From c8e37a589a4bffbdf374a5893ef269d2fe233ce6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 30 Nov 2023 19:52:23 +0800 Subject: refactor(IWYU): move typedefs out of globals.h (#26322) --- src/nvim/eval/encode.c | 1 + src/nvim/eval/typval_defs.h | 15 +++++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index 8505c30fad..38be10dbaf 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -21,6 +21,7 @@ #include "nvim/eval/typval_encode.h" #include "nvim/garray.h" #include "nvim/gettext.h" +#include "nvim/globals.h" #include "nvim/hashtab.h" #include "nvim/macros_defs.h" #include "nvim/math.h" diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index c6bd11ccdb..a6a0282fad 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -13,8 +13,10 @@ typedef int64_t varnumber_T; typedef uint64_t uvarnumber_T; -/// Refcount for dict or list that should not be freed -enum { DO_NOT_FREE_CNT = (INT_MAX / 2), }; +enum { + /// Refcount for dict or list that should not be freed + DO_NOT_FREE_CNT = (INT_MAX / 2), +}; /// Additional values for tv_list_alloc() len argument enum ListLenSpecials { @@ -291,12 +293,9 @@ typedef struct { uint64_t channel_id; /// Only used when script_id is SID_API_CLIENT. } LastSet; -/// Maximum number of function arguments -enum { MAX_FUNC_ARGS = 20, }; -/// Short variable name length -enum { VAR_SHORT_LEN = 20, }; -/// Number of fixed variables used for arguments -enum { FIXVAR_CNT = 12, }; +enum { MAX_FUNC_ARGS = 20, }; ///< Maximum number of function arguments +enum { VAR_SHORT_LEN = 20, }; ///< Short variable name length +enum { FIXVAR_CNT = 12, }; ///< Number of fixed variables used for arguments /// Structure to hold info for a function that is currently being executed. typedef struct funccall_S funccall_T; -- cgit From 0bbe8e7fc257bd06a857bfc762c2b1e8e84463e1 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 1 Dec 2023 09:38:04 +0800 Subject: refactor(IWYU): fix includes for highlight_group.h (#26340) --- src/nvim/eval/encode.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/encode.h b/src/nvim/eval/encode.h index 699956d8ac..11a0ce3932 100644 --- a/src/nvim/eval/encode.h +++ b/src/nvim/eval/encode.h @@ -5,7 +5,6 @@ #include #include -#include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" #include "nvim/garray_defs.h" -- cgit From 401ce9f3fdebed05a929de1b94e55c74d45e2ffb Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 6 Dec 2023 15:48:16 +0800 Subject: vim-patch:8.1.1583: set_ref_in_list() only sets ref in items (#26418) Problem: Set_ref_in_list() only sets ref in items. Solution: Rename to set_ref_in_list_items() to avoid confusion. https://github.com/vim/vim/commit/7be3ab25891fec711d8a2d9d242711a9155852b6 Omit set_ref_in_list() and set_ref_in_dict(): only used in popup window, if_pyth and if_lua. Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index e0bf30b158..ebc84922cb 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -3818,7 +3818,7 @@ bool set_ref_in_previous_funccal(int copyID) fc->fc_copyID = copyID + 1; if (set_ref_in_ht(&fc->fc_l_vars.dv_hashtab, copyID + 1, NULL) || set_ref_in_ht(&fc->fc_l_avars.dv_hashtab, copyID + 1, NULL) - || set_ref_in_list(&fc->fc_l_varlist, copyID + 1, NULL)) { + || set_ref_in_list_items(&fc->fc_l_varlist, copyID + 1, NULL)) { return true; } } @@ -3831,7 +3831,7 @@ static bool set_ref_in_funccal(funccall_T *fc, int copyID) fc->fc_copyID = copyID; if (set_ref_in_ht(&fc->fc_l_vars.dv_hashtab, copyID, NULL) || set_ref_in_ht(&fc->fc_l_avars.dv_hashtab, copyID, NULL) - || set_ref_in_list(&fc->fc_l_varlist, copyID, NULL) + || set_ref_in_list_items(&fc->fc_l_varlist, copyID, NULL) || set_ref_in_func(NULL, fc->fc_func, copyID)) { return true; } -- cgit From e057b38e7037808b3593fb1035794595b4e4a45e Mon Sep 17 00:00:00 2001 From: Emanuel Date: Wed, 6 Dec 2023 16:56:04 +0100 Subject: fix(json): allow objects with empty keys #25564 Problem: Empty string is a valid JSON key, but json_decode() treats an object with empty key as ":help msgpack-special-dict". #20757 :echo json_decode('{"": "1"}') {'_TYPE': [], '_VAL': [['', '1']]} Note: vim returns `{'': '1'}`. Solution: Allow empty string as an object key. Note that we still (currently) disallow empty keys in object_to_vim() (since 7c01d5ff9286d262097484c680e3a4eab49e2911): https://github.com/neovim/neovim/blob/f64e4b43e1191ff30d902730f752875aa55682ce/src/nvim/api/private/converter.c#L333-L334 Fix #20757 Co-authored-by: Justin M. Keyes --- src/nvim/eval/decode.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index a6407693d7..64b65b42a5 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -141,9 +141,7 @@ static inline int json_decoder_pop(ValuesStackItem obj, ValuesStack *const stack ValuesStackItem key = kv_pop(*stack); if (last_container.special_val == NULL) { // These cases should have already been handled. - assert(!(key.is_special_string - || key.val.vval.v_string == NULL - || *key.val.vval.v_string == NUL)); + assert(!(key.is_special_string || key.val.vval.v_string == NULL)); dictitem_T *const obj_di = tv_dict_item_alloc(key.val.vval.v_string); tv_clear(&key.val); if (tv_dict_add(last_container.container.vval.v_dict, obj_di) @@ -170,11 +168,10 @@ static inline int json_decoder_pop(ValuesStackItem obj, ValuesStack *const stack tv_clear(&obj.val); return FAIL; } - // Handle empty key and key represented as special dictionary + // Handle special dictionaries if (last_container.special_val == NULL && (obj.is_special_string || obj.val.vval.v_string == NULL - || *obj.val.vval.v_string == NUL || tv_dict_find(last_container.container.vval.v_dict, obj.val.vval.v_string, -1))) { tv_clear(&obj.val); @@ -404,13 +401,6 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, semsg(_("E474: Expected string end: %.*s"), (int)buf_len, buf); goto parse_json_string_fail; } - if (len == 0) { - POP(((typval_T) { - .v_type = VAR_STRING, - .vval = { .v_string = NULL }, - }), false); - goto parse_json_string_ret; - } char *str = xmalloc(len + 1); int fst_in_pair = 0; char *str_end = str; -- cgit From aba954b662cc1223d11ac3dc99323b9ebf687085 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 7 Dec 2023 19:14:56 +0800 Subject: fix(terminal): never propagate $COLORTERM from outer env (#26440) If $COLORTERM is "truecolor" but the user sets 'notermguicolors', propagating $COLORTERM to :terminal usually doesn't work well. --- src/nvim/eval/funcs.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 0054c47678..4029478072 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3898,12 +3898,13 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_number = 1; } -static const char *ignored_env_vars[] = { +static const char *pty_ignored_env_vars[] = { #ifndef MSWIN "COLUMNS", "LINES", "TERMCAP", "COLORFGBG", + "COLORTERM", #endif NULL }; @@ -3943,9 +3944,9 @@ static dict_T *create_environment(const dictitem_T *job_env, const bool clear_en // child process. We're removing them here so the user can still decide // they want to explicitly set them. for (size_t i = 0; - i < ARRAY_SIZE(ignored_env_vars) && ignored_env_vars[i]; + i < ARRAY_SIZE(pty_ignored_env_vars) && pty_ignored_env_vars[i]; i++) { - dictitem_T *dv = tv_dict_find(env, ignored_env_vars[i], -1); + dictitem_T *dv = tv_dict_find(env, pty_ignored_env_vars[i], -1); if (dv) { tv_dict_item_remove(env, dv); } @@ -3953,10 +3954,6 @@ static dict_T *create_environment(const dictitem_T *job_env, const bool clear_en #ifndef MSWIN // Set COLORTERM to "truecolor" if termguicolors is set if (p_tgc) { - dictitem_T *dv = tv_dict_find(env, S_LEN("COLORTERM")); - if (dv) { - tv_dict_item_remove(env, dv); - } tv_dict_add_str(env, S_LEN("COLORTERM"), "truecolor"); } #endif -- cgit From a16218d4c6773c474011149661470af6e8c90892 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 7 Dec 2023 13:01:42 +0100 Subject: refactor: object_to_vim() cannot fail Since the parent commit, object_to_vim() can't fail, so callers don't need to check its result. --- src/nvim/eval/funcs.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 4029478072..c1c865df60 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -355,10 +355,7 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) goto end; } - if (!object_to_vim(result, rettv, &err)) { - assert(ERROR_SET(&err)); - semsg(_("Error converting the call result: %s"), err.msg); - } + object_to_vim(result, rettv, &err); end: api_free_array(args); @@ -428,7 +425,7 @@ static void f_and(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) static void f_api_info(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { Dictionary metadata = api_metadata(); - (void)object_to_vim(DICTIONARY_OBJ(metadata), rettv, NULL); + object_to_vim(DICTIONARY_OBJ(metadata), rettv, NULL); } /// "atan2()" function @@ -1023,7 +1020,7 @@ static void f_ctxget(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) Dictionary ctx_dict = ctx_to_dict(ctx); Error err = ERROR_INIT; - (void)object_to_vim(DICTIONARY_OBJ(ctx_dict), rettv, &err); + object_to_vim(DICTIONARY_OBJ(ctx_dict), rettv, &err); api_free_dictionary(ctx_dict); api_clear_error(&err); } @@ -6751,10 +6748,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) goto end; } - if (!object_to_vim(result, rettv, &err)) { - assert(ERROR_SET(&err)); - semsg(_("Error converting the call result: %s"), err.msg); - } + object_to_vim(result, rettv, &err); end: arena_mem_free(res_mem); -- cgit From 5e78fd7784509dbbe146748e9264e5129cf68ab8 Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Thu, 7 Dec 2023 07:58:03 -0800 Subject: fix(terminal): ignore $VIM and $VIMRUNTIME in pty jobs --- src/nvim/eval/funcs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index c1c865df60..15b81f2f56 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3903,6 +3903,8 @@ static const char *pty_ignored_env_vars[] = { "COLORFGBG", "COLORTERM", #endif + "VIM", + "VIMRUNTIME", NULL }; -- cgit From 9ae7d36ff5ebaf75597b442e10890bd77df01fbe Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Thu, 7 Dec 2023 00:40:48 +0600 Subject: refactor(options): split `get_option_value()` into smaller functions Problem: Currently, `get_option_value()` returns 3 separate things: The actual value of the option, whether the option is hidden, and the option flags. This makes the function difficult to refactor, modify or otherwise reason about. Solution: Split `get_option_value()` into 3 functions, each with a single purpose. This also affects `get_option_value_for()`. --- src/nvim/eval/vars.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 670ee39f4b..8864edbf69 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -773,11 +773,14 @@ static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const, const char c1 = *p; *p = NUL; - uint32_t opt_p_flags; - bool hidden; - OptVal curval = get_option_value(arg, &opt_p_flags, scope, &hidden); + bool is_tty_opt = is_tty_option(arg); + int opt_idx = is_tty_opt ? -1 : findoption(arg); + uint32_t opt_p_flags = get_option_flags(opt_idx); + bool hidden = is_option_hidden(opt_idx); + OptVal curval = is_tty_opt ? get_tty_option(arg) : get_option_value(opt_idx, scope); OptVal newval = NIL_OPTVAL; - if (curval.type == kOptValTypeNil && arg[0] != 't' && arg[1] != '_') { + + if (curval.type == kOptValTypeNil) { semsg(_(e_unknown_option2), arg); goto theend; } -- cgit From 2ebd328a798778825be61015acd975d8a929dfec Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 9 Dec 2023 11:36:11 +0800 Subject: refactor: format casting of negative number better (#26482) --- src/nvim/eval/funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 15b81f2f56..b4f0be85e5 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2171,7 +2171,7 @@ static void f_float2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - if (f <= (float_T) - VARNUMBER_MAX + DBL_EPSILON) { + if (f <= (float_T)(-VARNUMBER_MAX) + DBL_EPSILON) { rettv->vval.v_number = -VARNUMBER_MAX; } else if (f >= (float_T)VARNUMBER_MAX - DBL_EPSILON) { rettv->vval.v_number = VARNUMBER_MAX; -- cgit From 6346987601a28b00564295ee8be0a8b00d9ff911 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Thu, 7 Dec 2023 23:46:57 +0600 Subject: refactor(options): reduce `findoption()` usage Problem: Many places in the code use `findoption()` to access an option using its name, even if the option index is available. This is very slow because it requires looping through the options array over and over. Solution: Use option index instead of name wherever possible. Also introduce an `OptIndex` enum which contains the index for every option as enum constants, this eliminates the need to pass static option names as strings. --- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/vars.c | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index b4f0be85e5..c35e0b2ada 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -7239,7 +7239,7 @@ int do_searchpair(const char *spat, const char *mpat, const char *epat, int dir, // If it's still empty it was changed and restored, need to restore in // the complicated way. if (*p_cpo == NUL) { - set_option_value_give_err("cpo", CSTR_AS_OPTVAL(save_cpo), 0); + set_option_value_give_err(kOptCpoptions, CSTR_AS_OPTVAL(save_cpo), 0); } free_string_option(save_cpo); } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 8864edbf69..9b7a61f969 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -834,7 +834,7 @@ static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const, } } - const char *err = set_option_value(arg, newval, scope); + const char *err = set_option_value_handle_tty(arg, opt_idx, newval, scope); arg_end = p; if (err != NULL) { emsg(_(err)); @@ -1945,15 +1945,18 @@ static void set_option_from_tv(const char *varname, typval_T *varp) semsg(_(e_unknown_option2), varname); return; } - uint32_t opt_p_flags = get_option(opt_idx)->flags; bool error = false; + uint32_t opt_p_flags = get_option_flags(opt_idx); OptVal value = tv_to_optval(varp, varname, opt_p_flags, &error); if (!error) { - set_option_value_give_err(varname, value, OPT_LOCAL); - } + const char *errmsg = set_option_value_handle_tty(varname, opt_idx, value, OPT_LOCAL); + if (errmsg) { + emsg(errmsg); + } + } optval_free(value); } -- cgit From bf3bc1cec9f00b9644815001a8732ecedf3ce07f Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Thu, 7 Dec 2023 23:59:30 +0600 Subject: refactor(options): convert `opt_idx` variables to `OptIndex` --- src/nvim/eval/vars.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 9b7a61f969..73c8ae1191 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -774,7 +774,7 @@ static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const, *p = NUL; bool is_tty_opt = is_tty_option(arg); - int opt_idx = is_tty_opt ? -1 : findoption(arg); + OptIndex opt_idx = is_tty_opt ? kOptInvalid : findoption(arg); uint32_t opt_p_flags = get_option_flags(opt_idx); bool hidden = is_option_hidden(opt_idx); OptVal curval = is_tty_opt ? get_tty_option(arg) : get_option_value(opt_idx, scope); @@ -1940,8 +1940,8 @@ typval_T optval_as_tv(OptVal value) /// Set option "varname" to the value of "varp" for the current buffer/window. static void set_option_from_tv(const char *varname, typval_T *varp) { - int opt_idx = findoption(varname); - if (opt_idx < 0) { + OptIndex opt_idx = findoption(varname); + if (opt_idx == kOptInvalid) { semsg(_(e_unknown_option2), varname); return; } -- cgit From 1d4a5cd18537d054a564ff19b9361120597d9dd7 Mon Sep 17 00:00:00 2001 From: Raphael Date: Tue, 12 Dec 2023 19:06:22 +0800 Subject: feat(eval): exists() function supports checking v:lua functions (#26485) Problem: Vimscript function exists() can't check v:lua functions. Solution: Add support for v:lua functions to exists(). --- src/nvim/eval/funcs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index c35e0b2ada..1468c5564e 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1716,6 +1716,8 @@ static void f_exists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } else { n = au_exists(p + 1); } + } else if (strncmp(p, "v:lua.", 6) == 0 && nlua_func_exists(p + 6)) { + n = true; } else { // Internal variable. n = var_exists(p); } -- cgit From 3c2c022e5e299ecac4663c3813e2db5e2b099ffa Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Thu, 7 Dec 2023 01:34:29 +0600 Subject: refactor(options): remove option type macros Problem: We have `P_(BOOL|NUM|STRING)` macros to represent an option's type, which is redundant because `OptValType` can already do that. The current implementation of option type flags is also too limited to allow adding multitype options in the future. Solution: Remove `P_(BOOL|NUM|STRING)` and replace it with a new `type_flags` attribute in `vimoption_T`. Also do some groundwork for adding multitype options in the future. Side-effects: Attempting to set an invalid keycode option (e.g. `set t_foo=123`) no longer gives an error. --- src/nvim/eval/vars.c | 64 +++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 31 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 73c8ae1191..6fd707a0b0 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -761,11 +761,12 @@ static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const, // Find the end of the name. char *arg_end = NULL; + OptIndex opt_idx; int scope; - char *const p = (char *)find_option_end((const char **)&arg, &scope); - if (p == NULL - || (endchars != NULL - && vim_strchr(endchars, (uint8_t)(*skipwhite(p))) == NULL)) { + + char *const p = (char *)find_option_var_end((const char **)&arg, &opt_idx, &scope); + + if (p == NULL || (endchars != NULL && vim_strchr(endchars, (uint8_t)(*skipwhite(p))) == NULL)) { emsg(_(e_letunexp)); return NULL; } @@ -774,8 +775,6 @@ static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const, *p = NUL; bool is_tty_opt = is_tty_option(arg); - OptIndex opt_idx = is_tty_opt ? kOptInvalid : findoption(arg); - uint32_t opt_p_flags = get_option_flags(opt_idx); bool hidden = is_option_hidden(opt_idx); OptVal curval = is_tty_opt ? get_tty_option(arg) : get_option_value(opt_idx, scope); OptVal newval = NIL_OPTVAL; @@ -792,7 +791,7 @@ static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const, } bool error; - newval = tv_to_optval(tv, arg, opt_p_flags, &error); + newval = tv_to_optval(tv, opt_idx, arg, &error); if (error) { goto theend; } @@ -1849,22 +1848,27 @@ static void getwinvar(typval_T *argvars, typval_T *rettv, int off) /// /// @return Typval converted to OptVal. Must be freed by caller. /// Returns NIL_OPTVAL for invalid option name. -static OptVal tv_to_optval(typval_T *tv, const char *option, uint32_t flags, bool *error) +/// +/// TODO(famiu): Refactor this to support multitype options. +static OptVal tv_to_optval(typval_T *tv, OptIndex opt_idx, const char *option, bool *error) { OptVal value = NIL_OPTVAL; char nbuf[NUMBUFLEN]; bool err = false; + const bool is_tty_opt = is_tty_option(option); + const bool option_has_bool = !is_tty_opt && option_has_type(opt_idx, kOptValTypeBoolean); + const bool option_has_num = !is_tty_opt && option_has_type(opt_idx, kOptValTypeNumber); + const bool option_has_str = is_tty_opt || option_has_type(opt_idx, kOptValTypeString); - if ((flags & P_FUNC) && tv_is_func(*tv)) { + if (!is_tty_opt && (get_option(opt_idx)->flags & P_FUNC) && tv_is_func(*tv)) { // If the option can be set to a function reference or a lambda // and the passed value is a function reference, then convert it to // the name (string) of the function reference. char *strval = encode_tv2string(tv, NULL); err = strval == NULL; value = CSTR_AS_OPTVAL(strval); - } else if (flags & (P_NUM | P_BOOL)) { - varnumber_T n = (flags & P_NUM) ? tv_get_number_chk(tv, &err) - : tv_get_bool_chk(tv, &err); + } else if (option_has_bool || option_has_num) { + varnumber_T n = option_has_num ? tv_get_number_chk(tv, &err) : tv_get_bool_chk(tv, &err); // This could be either "0" or a string that's not a number. // So we need to check if it's actually a number. if (!err && tv->v_type == VAR_STRING && n == 0) { @@ -1877,14 +1881,14 @@ static OptVal tv_to_optval(typval_T *tv, const char *option, uint32_t flags, boo semsg(_("E521: Number required: &%s = '%s'"), option, tv->vval.v_string); } } - value = (flags & P_NUM) ? NUMBER_OPTVAL((OptInt)n) : BOOLEAN_OPTVAL(TRISTATE_FROM_INT(n)); - } else if ((flags & P_STRING) || is_tty_option(option)) { + value = option_has_num ? NUMBER_OPTVAL((OptInt)n) : BOOLEAN_OPTVAL(TRISTATE_FROM_INT(n)); + } else if (option_has_str) { // Avoid setting string option to a boolean or a special value. if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL) { const char *strval = tv_get_string_buf_chk(tv, nbuf); err = strval == NULL; value = CSTR_TO_OPTVAL(strval); - } else if (flags & P_STRING) { + } else if (!is_tty_opt) { err = true; emsg(_(e_stringreq)); } @@ -1900,10 +1904,12 @@ static OptVal tv_to_optval(typval_T *tv, const char *option, uint32_t flags, boo /// Convert an option value to typval. /// -/// @param[in] value Option value to convert. +/// @param[in] value Option value to convert. +/// @param numbool Whether to convert boolean values to number. +/// Used for backwards compatibility. /// /// @return OptVal converted to typval. -typval_T optval_as_tv(OptVal value) +typval_T optval_as_tv(OptVal value, bool numbool) { typval_T rettv = { .v_type = VAR_SPECIAL, .vval = { .v_special = kSpecialVarNull } }; @@ -1911,19 +1917,16 @@ typval_T optval_as_tv(OptVal value) case kOptValTypeNil: break; case kOptValTypeBoolean: - switch (value.data.boolean) { - case kTrue: - rettv.v_type = VAR_BOOL; - rettv.vval.v_bool = kBoolVarTrue; - break; - case kFalse: - rettv.v_type = VAR_BOOL; - rettv.vval.v_bool = kBoolVarFalse; - break; - case kNone: - break; // return v:null for None boolean value + if (value.data.boolean != kNone) { + if (numbool) { + rettv.v_type = VAR_NUMBER; + rettv.vval.v_number = value.data.boolean == kTrue; + } else { + rettv.v_type = VAR_BOOL; + rettv.vval.v_bool = value.data.boolean == kTrue; + } } - break; + break; // return v:null for None boolean value. case kOptValTypeNumber: rettv.v_type = VAR_NUMBER; rettv.vval.v_number = value.data.number; @@ -1947,8 +1950,7 @@ static void set_option_from_tv(const char *varname, typval_T *varp) } bool error = false; - uint32_t opt_p_flags = get_option_flags(opt_idx); - OptVal value = tv_to_optval(varp, varname, opt_p_flags, &error); + OptVal value = tv_to_optval(varp, opt_idx, varname, &error); if (!error) { const char *errmsg = set_option_value_handle_tty(varname, opt_idx, value, OPT_LOCAL); -- cgit From 8f08b1efbd096850c04c2e8e2890d993bd4d9f95 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sun, 17 Dec 2023 05:23:33 +0600 Subject: refactor(options): use hashy for finding options (#26573) Problem: `findoption()` searches through the options[] table linearly for option names, even though hashy can be used to generate a compile-time hash table for it. Solution: Use hashy to generate a compile time hash table for finding options. This also allows handling option aliases, so we don't need separate options[] table entries for things like 'viminfo'. --- src/nvim/eval/vars.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 6fd707a0b0..9897ca77f1 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1943,7 +1943,7 @@ typval_T optval_as_tv(OptVal value, bool numbool) /// Set option "varname" to the value of "varp" for the current buffer/window. static void set_option_from_tv(const char *varname, typval_T *varp) { - OptIndex opt_idx = findoption(varname); + OptIndex opt_idx = find_option(varname); if (opt_idx == kOptInvalid) { semsg(_(e_unknown_option2), varname); return; -- cgit From 69bc519b53ebf78fd95c8256468e7d538ebcb948 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Tue, 12 Dec 2023 15:40:21 +0100 Subject: refactor: move non-symbols to defs.h headers --- src/nvim/eval/funcs.c | 1 + src/nvim/eval/gc.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 1468c5564e..ea68c010d6 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -48,6 +48,7 @@ #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" #include "nvim/eval/window.h" +#include "nvim/event/defs.h" #include "nvim/event/loop.h" #include "nvim/event/multiqueue.h" #include "nvim/event/process.h" diff --git a/src/nvim/eval/gc.h b/src/nvim/eval/gc.h index 36149ec060..ea91952fff 100644 --- a/src/nvim/eval/gc.h +++ b/src/nvim/eval/gc.h @@ -6,5 +6,5 @@ extern dict_T *gc_first_dict; extern list_T *gc_first_list; #ifdef INCLUDE_GENERATED_DECLARATIONS -# include "eval/gc.h.generated.h" // IWYU pragma: export +# include "eval/gc.h.generated.h" #endif -- cgit From 6abdc1ac1f904173d01efcf440d1460c001bc299 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 18 Dec 2023 09:05:59 +0800 Subject: refactor: split WIN_EXECUTE() into two functions (#26627) --- src/nvim/eval/window.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++---- src/nvim/eval/window.h | 70 ++++++++----------------------------------- 2 files changed, 86 insertions(+), 64 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index e0abbad477..d1ee2ea356 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -9,7 +9,6 @@ #include "nvim/ascii_defs.h" #include "nvim/autocmd.h" #include "nvim/buffer.h" -#include "nvim/buffer_defs.h" #include "nvim/cursor.h" #include "nvim/eval/funcs.h" #include "nvim/eval/typval.h" @@ -19,9 +18,12 @@ #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/macros_defs.h" +#include "nvim/mark.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/move.h" +#include "nvim/option_vars.h" +#include "nvim/os/fs.h" #include "nvim/pos_defs.h" #include "nvim/types_defs.h" #include "nvim/vim_defs.h" @@ -480,6 +482,68 @@ void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_number = nr; } +/// Switch to a window for executing user code. +/// Caller must call win_execute_after() later regardless of return value. +/// +/// @return whether switching the window succeded. +bool win_execute_before(win_execute_T *args, win_T *wp, tabpage_T *tp) +{ + args->wp = wp; + args->curpos = wp->w_cursor; + args->cwd_status = FAIL; + args->apply_acd = false; + + // Getting and setting directory can be slow on some systems, only do + // this when the current or target window/tab have a local directory or + // 'acd' is set. + if (curwin != wp + && (curwin->w_localdir != NULL || wp->w_localdir != NULL + || (curtab != tp && (curtab->tp_localdir != NULL || tp->tp_localdir != NULL)) + || p_acd)) { + args->cwd_status = os_dirname(args->cwd, MAXPATHL); + } + + // If 'acd' is set, check we are using that directory. If yes, then + // apply 'acd' afterwards, otherwise restore the current directory. + if (args->cwd_status == OK && p_acd) { + do_autochdir(); + char autocwd[MAXPATHL]; + if (os_dirname(autocwd, MAXPATHL) == OK) { + args->apply_acd = strcmp(args->cwd, autocwd) == 0; + } + } + + if (switch_win_noblock(&args->switchwin, wp, tp, true) == OK) { + check_cursor(); + return true; + } + return false; +} + +/// Restore the previous window after executing user code. +void win_execute_after(win_execute_T *args) +{ + restore_win_noblock(&args->switchwin, true); + + if (args->apply_acd) { + do_autochdir(); + } else if (args->cwd_status == OK) { + os_chdir(args->cwd); + } + + // Update the status line if the cursor moved. + if (win_valid(args->wp) && !equalpos(args->curpos, args->wp->w_cursor)) { + args->wp->w_redr_status = true; + } + + // In case the command moved the cursor or changed the Visual area, + // check it is valid. + check_cursor(); + if (VIsual_active) { + check_pos(curbuf, &VIsual); + } +} + /// "win_execute(win_id, command)" function void f_win_execute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -494,7 +558,11 @@ void f_win_execute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - WIN_EXECUTE(wp, tp, execute_common(argvars, rettv, 1)); + win_execute_T win_execute_args; + if (win_execute_before(&win_execute_args, wp, tp)) { + execute_common(argvars, rettv, 1); + } + win_execute_after(&win_execute_args); } /// "win_findbuf()" function @@ -914,16 +982,16 @@ int switch_win_noblock(switchwin_T *switchwin, win_T *win, tabpage_T *tp, bool n return OK; } -// Restore current tabpage and window saved by switch_win(), if still valid. -// When "no_display" is true the display won't be affected, no redraw is -// triggered. +/// Restore current tabpage and window saved by switch_win(), if still valid. +/// When "no_display" is true the display won't be affected, no redraw is +/// triggered. void restore_win(switchwin_T *switchwin, bool no_display) { restore_win_noblock(switchwin, no_display); unblock_autocmds(); } -// As restore_win() but without unblocking autocommands. +/// As restore_win() but without unblocking autocommands. void restore_win_noblock(switchwin_T *switchwin, bool no_display) { if (switchwin->sw_curtab != NULL && valid_tabpage(switchwin->sw_curtab)) { diff --git a/src/nvim/eval/window.h b/src/nvim/eval/window.h index ed879c895a..1b2817edf0 100644 --- a/src/nvim/eval/window.h +++ b/src/nvim/eval/window.h @@ -1,20 +1,12 @@ #pragma once #include -#include -#include "nvim/buffer.h" #include "nvim/buffer_defs.h" -#include "nvim/cursor.h" -#include "nvim/eval/typval_defs.h" -#include "nvim/globals.h" -#include "nvim/mark.h" -#include "nvim/option_defs.h" -#include "nvim/option_vars.h" -#include "nvim/os/fs.h" +#include "nvim/eval/typval_defs.h" // IWYU pragma: keep +#include "nvim/os/os_defs.h" #include "nvim/pos_defs.h" -#include "nvim/vim_defs.h" -#include "nvim/window.h" +#include "nvim/types_defs.h" // IWYU pragma: keep /// Structure used by switch_win() to pass values to restore_win() typedef struct { @@ -24,53 +16,15 @@ typedef struct { bool sw_visual_active; } switchwin_T; -/// Execute a block of code in the context of window `wp` in tabpage `tp`. -/// Ensures the status line is redrawn and cursor position is valid if it is moved. -#define WIN_EXECUTE(wp, tp, block) \ - do { \ - win_T *const wp_ = (wp); \ - const pos_T curpos_ = wp_->w_cursor; \ - char cwd_[MAXPATHL]; \ - char autocwd_[MAXPATHL]; \ - bool apply_acd_ = false; \ - int cwd_status_ = FAIL; \ - /* Getting and setting directory can be slow on some systems, only do */ \ - /* this when the current or target window/tab have a local directory or */ \ - /* 'acd' is set. */ \ - if (curwin != wp \ - && (curwin->w_localdir != NULL || wp->w_localdir != NULL \ - || (curtab != tp && (curtab->tp_localdir != NULL || tp->tp_localdir != NULL)) \ - || p_acd)) { \ - cwd_status_ = os_dirname(cwd_, MAXPATHL); \ - } \ - /* If 'acd' is set, check we are using that directory. If yes, then */ \ - /* apply 'acd' afterwards, otherwise restore the current directory. */ \ - if (cwd_status_ == OK && p_acd) { \ - do_autochdir(); \ - apply_acd_ = os_dirname(autocwd_, MAXPATHL) == OK && strcmp(cwd_, autocwd_) == 0; \ - } \ - switchwin_T switchwin_; \ - if (switch_win_noblock(&switchwin_, wp_, (tp), true) == OK) { \ - check_cursor(); \ - block; \ - } \ - restore_win_noblock(&switchwin_, true); \ - if (apply_acd_) { \ - do_autochdir(); \ - } else if (cwd_status_ == OK) { \ - os_chdir(cwd_); \ - } \ - /* Update the status line if the cursor moved. */ \ - if (win_valid(wp_) && !equalpos(curpos_, wp_->w_cursor)) { \ - wp_->w_redr_status = true; \ - } \ - /* In case the command moved the cursor or changed the Visual area, */ \ - /* check it is valid. */ \ - check_cursor(); \ - if (VIsual_active) { \ - check_pos(curbuf, &VIsual); \ - } \ - } while (false) +/// Structure used by win_execute_before() to pass values to win_execute_after() +typedef struct { + win_T *wp; + pos_T curpos; + char cwd[MAXPATHL]; + int cwd_status; + bool apply_acd; + switchwin_T switchwin; +} win_execute_T; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/window.h.generated.h" -- cgit From 6cb78e2d1c4c6c63c628c965076a07ce5f7adbb6 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sat, 16 Dec 2023 22:14:28 +0100 Subject: docs: add style rule regarding initialization Specifically, specify that each initialization should be done on a separate line. --- src/nvim/eval/funcs.c | 11 ++++++----- src/nvim/eval/userfunc.c | 6 ++---- src/nvim/eval/window.c | 3 ++- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index ea68c010d6..81ae208560 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -4054,8 +4054,8 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) bool clear_env = false; bool overlapped = false; ChannelStdinMode stdin_mode = kChannelStdinPipe; - CallbackReader on_stdout = CALLBACK_READER_INIT, - on_stderr = CALLBACK_READER_INIT; + CallbackReader on_stdout = CALLBACK_READER_INIT; + CallbackReader on_stderr = CALLBACK_READER_INIT; Callback on_exit = CALLBACK_NONE; char *cwd = NULL; dictitem_T *job_env = NULL; @@ -4118,7 +4118,8 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } } - uint16_t width = 0, height = 0; + uint16_t width = 0; + uint16_t height = 0; char *term_name = NULL; if (pty) { @@ -8553,8 +8554,8 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - CallbackReader on_stdout = CALLBACK_READER_INIT, - on_stderr = CALLBACK_READER_INIT; + CallbackReader on_stdout = CALLBACK_READER_INIT; + CallbackReader on_stderr = CALLBACK_READER_INIT; Callback on_exit = CALLBACK_NONE; dict_T *job_opts = NULL; const char *cwd = "."; diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index ebc84922cb..cce02e6daf 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -105,7 +105,6 @@ static int get_function_args(char **argp, char endchar, garray_T *newargs, int * char *arg = *argp; char *p = arg; uint8_t c; - int i; if (newargs != NULL) { ga_init(newargs, (int)sizeof(char *), 3); @@ -147,7 +146,7 @@ static int get_function_args(char **argp, char endchar, garray_T *newargs, int * arg = xstrdup(arg); // Check for duplicate argument name. - for (i = 0; i < newargs->ga_len; i++) { + for (int i = 0; i < newargs->ga_len; i++) { if (strcmp(((char **)(newargs->ga_data))[i], arg) == 0) { semsg(_("E853: Duplicate argument name: %s"), arg); xfree(arg); @@ -922,7 +921,6 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett static int depth = 0; dictitem_T *v; int fixvar_idx = 0; // index in fc_fixvar[] - int ai; bool islambda = false; char numbuf[NUMBUFLEN]; char *name; @@ -1025,7 +1023,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett bool isdefault = false; typval_T def_rettv; - ai = i - fp->uf_args.ga_len; + int ai = i - fp->uf_args.ga_len; if (ai < 0) { // named argument a:name name = FUNCARG(fp, i); diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index d1ee2ea356..02f214f262 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -710,7 +710,8 @@ void f_win_splitmove(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - int flags = 0, size = 0; + int flags = 0; + int size = 0; if (argvars[2].v_type != VAR_UNKNOWN) { dict_T *d; -- cgit From 7f6b775b45de5011ff1c44e63e57551566d80704 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sat, 16 Dec 2023 22:14:28 +0100 Subject: refactor: use `bool` to represent boolean values --- src/nvim/eval/funcs.c | 4 ++-- src/nvim/eval/userfunc.c | 8 ++++---- src/nvim/eval/vars.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 81ae208560..f13235c3e9 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -305,7 +305,7 @@ int call_internal_method(const char *const fname, const int argcount, typval_T * } /// @return true for a non-zero Number and a non-empty String. -static int non_zero_arg(typval_T *argvars) +static bool non_zero_arg(typval_T *argvars) { return ((argvars[0].v_type == VAR_NUMBER && argvars[0].vval.v_number != 0) @@ -2443,7 +2443,7 @@ static void getpos_both(typval_T *argvars, typval_T *rettv, bool getcurpos, bool : (varnumber_T)0)); tv_list_append_number(l, (fp != NULL) ? (varnumber_T)fp->coladd : (varnumber_T)0); if (getcurpos) { - const int save_set_curswant = curwin->w_set_curswant; + const bool save_set_curswant = curwin->w_set_curswant; const colnr_T save_curswant = curwin->w_curswant; const colnr_T save_virtcol = curwin->w_virtcol; diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index cce02e6daf..5e943711d1 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -928,7 +928,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett int tv_to_free_len = 0; proftime_T wait_start; proftime_T call_start; - int started_profiling = false; + bool started_profiling = false; bool did_save_redo = false; save_redo_T save_redo; @@ -3035,7 +3035,7 @@ static inline bool fc_referenced(const funccall_T *const fc) /// @return true if items in "fc" do not have "copyID". That means they are not /// referenced from anywhere that is in use. -static int can_free_funccal(funccall_T *fc, int copyID) +static bool can_free_funccal(funccall_T *fc, int copyID) { return fc->fc_l_varlist.lv_copyID != copyID && fc->fc_l_vars.dv_copyID != copyID @@ -3048,7 +3048,7 @@ void ex_return(exarg_T *eap) { char *arg = eap->arg; typval_T rettv; - int returning = false; + bool returning = false; if (current_funccal == NULL) { emsg(_("E133: :return not inside a function")); @@ -3395,7 +3395,7 @@ end: /// /// @return true when the return can be carried out, /// false when the return gets pending. -int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv) +bool do_return(exarg_T *eap, bool reanimate, bool is_cmd, void *rettv) { cstack_T *const cstack = eap->cstack; diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 9897ca77f1..de2fddb083 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -616,7 +616,7 @@ static void list_tab_vars(int *first) /// List variables in "arg". static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first) { - int error = false; + bool error = false; int len; const char *name; const char *name_start; -- cgit From 0c120307ca1ab613e63865c634d7e10ad67fb0ba Mon Sep 17 00:00:00 2001 From: dundargoc Date: Wed, 20 Dec 2023 14:32:22 +0100 Subject: refactor: eliminate cyclic includes --- src/nvim/eval/userfunc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 5e943711d1..d0b3fe7993 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -10,6 +10,7 @@ #include "nvim/ascii_defs.h" #include "nvim/autocmd.h" +#include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/cmdexpand_defs.h" #include "nvim/debugger.h" -- cgit From 8533adb4844b771b84dac2141fa2fa60e0487b47 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 21 Dec 2023 16:50:05 +0800 Subject: refactor(IWYU): move decor provider types to decoration_defs.h (#26692) --- src/nvim/eval/funcs.c | 1 - src/nvim/eval/funcs.h | 1 - 2 files changed, 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index f13235c3e9..5b6904269d 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -28,7 +28,6 @@ #include "nvim/assert_defs.h" #include "nvim/autocmd.h" #include "nvim/buffer.h" -#include "nvim/buffer_defs.h" #include "nvim/channel.h" #include "nvim/charset.h" #include "nvim/cmdexpand.h" diff --git a/src/nvim/eval/funcs.h b/src/nvim/eval/funcs.h index 0c345dacb4..e3a574b233 100644 --- a/src/nvim/eval/funcs.h +++ b/src/nvim/eval/funcs.h @@ -3,7 +3,6 @@ #include #include -#include "nvim/buffer_defs.h" // IWYU pragma: keep #include "nvim/cmdexpand_defs.h" // IWYU pragma: keep #include "nvim/eval/typval_defs.h" #include "nvim/pos_defs.h" // IWYU pragma: keep -- cgit From af93a74a0f4afa9a3a4f55ffdf28141eaf776d22 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 18 Dec 2023 10:55:23 +0100 Subject: refactor: run IWYU on entire repo Reference: https://github.com/neovim/neovim/issues/6371. --- src/nvim/eval/encode.h | 4 +--- src/nvim/eval/funcs.c | 3 --- src/nvim/eval/typval.c | 3 +-- src/nvim/eval/typval.h | 3 +-- src/nvim/eval/userfunc.h | 2 +- src/nvim/eval/vars.c | 2 +- 6 files changed, 5 insertions(+), 12 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/encode.h b/src/nvim/eval/encode.h index 11a0ce3932..fe1b951e3c 100644 --- a/src/nvim/eval/encode.h +++ b/src/nvim/eval/encode.h @@ -1,12 +1,10 @@ #pragma once -#include #include -#include #include #include "nvim/eval/typval.h" -#include "nvim/eval/typval_defs.h" +#include "nvim/func_attr.h" #include "nvim/garray_defs.h" /// Convert Vimscript value to msgpack string diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 5b6904269d..30a86b1917 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -14,13 +14,11 @@ #include #include #include -#include #include #include #include "auto/config.h" #include "nvim/api/private/converter.h" -#include "nvim/api/private/defs.h" #include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" @@ -47,7 +45,6 @@ #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" #include "nvim/eval/window.h" -#include "nvim/event/defs.h" #include "nvim/event/loop.h" #include "nvim/event/multiqueue.h" #include "nvim/event/process.h" diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 069cdced34..42b105b2a2 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include "nvim/ascii_defs.h" #include "nvim/assert_defs.h" @@ -19,7 +19,6 @@ #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" #include "nvim/garray.h" -#include "nvim/garray_defs.h" #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/hashtab.h" diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index efa6017f4b..0013c8ffe5 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -8,12 +8,11 @@ #include "nvim/eval/typval_defs.h" // IWYU pragma: export #include "nvim/func_attr.h" -#include "nvim/garray_defs.h" #include "nvim/gettext.h" #include "nvim/hashtab.h" #include "nvim/lib/queue.h" #include "nvim/macros_defs.h" -#include "nvim/mbyte_defs.h" +#include "nvim/mbyte_defs.h" // IWYU pragma: keep #include "nvim/message.h" #include "nvim/types_defs.h" diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index 8050caab2b..65a96a13c5 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -4,7 +4,7 @@ #include #include "nvim/cmdexpand_defs.h" // IWYU pragma: keep -#include "nvim/eval.h" +#include "nvim/eval.h" // IWYU pragma: keep #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" // IWYU pragma: keep #include "nvim/hashtab_defs.h" // IWYU pragma: keep diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index de2fddb083..8ed76341b0 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include "nvim/ascii_defs.h" #include "nvim/autocmd.h" -- cgit From 089b934352437ab310a6dd3b138c7ed9445a3d7b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 22 Dec 2023 12:24:23 +0800 Subject: refactor(options): generate BV_ and WV_ constants (#26705) --- src/nvim/eval/userfunc.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index 65a96a13c5..270ca7db4e 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -11,8 +11,6 @@ #include "nvim/pos_defs.h" #include "nvim/types_defs.h" // IWYU pragma: keep -struct funccal_entry; - // From user function to hashitem and back. #define UF2HIKEY(fp) ((fp)->uf_name) #define HIKEY2UF(p) ((ufunc_T *)((p) - offsetof(ufunc_T, uf_name))) -- cgit From 242261d4e77806cdb4559c2be58613113a393a4e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 23 Dec 2023 08:28:17 +0800 Subject: refactor(IWYU): move evalarg_T to eval_defs.h (#26716) --- src/nvim/eval/typval_encode.c.h | 3 ++- src/nvim/eval/userfunc.h | 2 +- src/nvim/eval/vars.c | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h index 2e0b68d486..c0cd0ce557 100644 --- a/src/nvim/eval/typval_encode.c.h +++ b/src/nvim/eval/typval_encode.c.h @@ -246,11 +246,12 @@ #include #include +#include "klib/kvec.h" +#include "nvim/eval.h" #include "nvim/eval/encode.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_encode.h" #include "nvim/func_attr.h" -#include "klib/kvec.h" /// Dummy variable used because some macros need lvalue /// diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index 270ca7db4e..b3488b15a7 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -4,8 +4,8 @@ #include #include "nvim/cmdexpand_defs.h" // IWYU pragma: keep -#include "nvim/eval.h" // IWYU pragma: keep #include "nvim/eval/typval_defs.h" +#include "nvim/eval_defs.h" // IWYU pragma: keep #include "nvim/ex_cmds_defs.h" // IWYU pragma: keep #include "nvim/hashtab_defs.h" // IWYU pragma: keep #include "nvim/pos_defs.h" diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 8ed76341b0..dd984e8819 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -43,6 +43,8 @@ #include "nvim/vim_defs.h" #include "nvim/window.h" +typedef int (*ex_unletlock_callback)(lval_T *, char *, exarg_T *, int); + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/vars.c.generated.h" #endif -- cgit From ab2aad509d6e4fc57a6afe056275405ec6451671 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Wed, 20 Dec 2023 17:22:19 +0100 Subject: refactor: follow style guide --- src/nvim/eval/userfunc.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index d0b3fe7993..5d8c173dd1 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -105,7 +105,6 @@ static int get_function_args(char **argp, char endchar, garray_T *newargs, int * bool mustend = false; char *arg = *argp; char *p = arg; - uint8_t c; if (newargs != NULL) { ga_init(newargs, (int)sizeof(char *), 3); @@ -142,7 +141,7 @@ static int get_function_args(char **argp, char endchar, garray_T *newargs, int * } if (newargs != NULL) { ga_grow(newargs, 1); - c = (uint8_t)(*p); + uint8_t c = (uint8_t)(*p); *p = NUL; arg = xstrdup(arg); @@ -173,7 +172,7 @@ static int get_function_args(char **argp, char endchar, garray_T *newargs, int * while (p > expr && ascii_iswhite(p[-1])) { p--; } - c = (uint8_t)(*p); + uint8_t c = (uint8_t)(*p); *p = NUL; expr = xstrdup(expr); ((char **)(default_args->ga_data))[default_args->ga_len] = expr; @@ -325,7 +324,6 @@ int get_lambda_tv(char **arg, typval_T *rettv, evalarg_T *evalarg) if (evaluate) { int flags = 0; - char *p; garray_T newlines; char *name = get_lambda_name(); @@ -338,7 +336,7 @@ int get_lambda_tv(char **arg, typval_T *rettv, evalarg_T *evalarg) // Add "return " before the expression. size_t len = (size_t)(7 + end - start + 1); - p = xmalloc(len); + char *p = xmalloc(len); ((char **)(newlines.ga_data))[newlines.ga_len++] = p; STRCPY(p, "return "); xstrlcpy(p + 7, start, (size_t)(end - start) + 1); @@ -918,7 +916,6 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett FUNC_ATTR_NONNULL_ARG(1, 3, 4) { bool using_sandbox = false; - int save_did_emsg; static int depth = 0; dictitem_T *v; int fixvar_idx = 0; // index in fc_fixvar[] @@ -1167,7 +1164,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett const sctx_T save_current_sctx = current_sctx; current_sctx = fp->uf_script_ctx; - save_did_emsg = did_emsg; + int save_did_emsg = did_emsg; did_emsg = false; if (default_arg_err && (fp->uf_flags & FC_ABORT)) { -- cgit From 714b075197c02d27d5c05133759ae97bed279b50 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Thu, 28 Dec 2023 03:28:48 +0100 Subject: docs: small fixes (#26651) Co-authored-by: Gregory Anders Co-authored-by: WillLillis --- src/nvim/eval/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index 02f214f262..230aec6abc 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -485,7 +485,7 @@ void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// Switch to a window for executing user code. /// Caller must call win_execute_after() later regardless of return value. /// -/// @return whether switching the window succeded. +/// @return whether switching the window succeeded. bool win_execute_before(win_execute_T *args, win_T *wp, tabpage_T *tp) { args->wp = wp; -- cgit From c89292fcb7f2ebf06efb7c1d00c28f34c6f68fec Mon Sep 17 00:00:00 2001 From: dundargoc Date: Thu, 28 Dec 2023 13:42:24 +0100 Subject: refactor: follow style guide --- src/nvim/eval/buffer.c | 3 ++- src/nvim/eval/funcs.c | 34 +++++++++++++++++----------------- src/nvim/eval/typval.c | 2 +- src/nvim/eval/userfunc.c | 6 +++--- src/nvim/eval/vars.c | 6 +++--- src/nvim/eval/window.c | 6 +++--- 6 files changed, 29 insertions(+), 28 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index 1f3b92804d..2ae2b94ce9 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -583,7 +583,8 @@ void f_getbufinfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// /// @return range (from start to end) of lines in rettv from the specified /// buffer. -static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retlist, typval_T *rettv) +static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, bool retlist, + typval_T *rettv) { rettv->v_type = (retlist ? VAR_LIST : VAR_STRING); rettv->vval.v_string = NULL; diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 30a86b1917..6fae90134a 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1668,7 +1668,7 @@ static void f_exepath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) char *path = NULL; - (void)os_can_exe(tv_get_string(&argvars[0]), &path, true); + os_can_exe(tv_get_string(&argvars[0]), &path, true); #ifdef BACKSLASH_IN_FILENAME if (path != NULL) { @@ -2214,8 +2214,8 @@ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) len = strlen(fname); if (*mods != NUL) { size_t usedlen = 0; - (void)modify_fname((char *)mods, false, &usedlen, - (char **)&fname, &fbuf, &len); + modify_fname((char *)mods, false, &usedlen, + (char **)&fname, &fbuf, &len); } } @@ -3634,7 +3634,7 @@ static void f_inputlist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) }); // Ask for choice. - int mouse_used; + bool mouse_used; int selected = prompt_for_number(&mouse_used); if (mouse_used) { selected -= lines_left; @@ -4163,7 +4163,7 @@ static void f_jobstop(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) const char *error = NULL; if (data->is_rpc) { // Ignore return code, but show error later. - (void)channel_close(data->id, kChannelPartRpc, &error); + channel_close(data->id, kChannelPartRpc, &error); } process_stop(&data->stream.proc); rettv->vval.v_number = 1; @@ -5211,7 +5211,7 @@ static void f_printf(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (!did_emsg) { char *s = xmalloc((size_t)len + 1); rettv->vval.v_string = s; - (void)vim_vsnprintf_typval(s, (size_t)len + 1, fmt, dummy_ap, argvars + 1); + vim_vsnprintf_typval(s, (size_t)len + 1, fmt, dummy_ap, argvars + 1); } did_emsg |= saved_did_emsg; } @@ -5802,7 +5802,7 @@ static void f_getreginfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (list == NULL) { return; } - (void)tv_dict_add_list(dict, S_LEN("regcontents"), list); + tv_dict_add_list(dict, S_LEN("regcontents"), list); char buf[NUMBUFLEN + 2]; buf[0] = NUL; @@ -5821,15 +5821,15 @@ static void f_getreginfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) case kMTUnknown: abort(); } - (void)tv_dict_add_str(dict, S_LEN("regtype"), buf); + tv_dict_add_str(dict, S_LEN("regtype"), buf); buf[0] = (char)get_register_name(get_unname_register()); buf[1] = NUL; if (regname == '"') { - (void)tv_dict_add_str(dict, S_LEN("points_to"), buf); + tv_dict_add_str(dict, S_LEN("points_to"), buf); } else { - (void)tv_dict_add_bool(dict, S_LEN("isunnamed"), - regname == buf[0] ? kBoolVarTrue : kBoolVarFalse); + tv_dict_add_bool(dict, S_LEN("isunnamed"), + regname == buf[0] ? kBoolVarTrue : kBoolVarFalse); } } @@ -8082,7 +8082,7 @@ static void f_str2float(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (*p == '+' || *p == '-') { p = skipwhite(p + 1); } - (void)string2float(p, &rettv->vval.v_float); + string2float(p, &rettv->vval.v_float); if (isneg) { rettv->vval.v_float *= -1; } @@ -8397,7 +8397,7 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, EvalFuncData fptr if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count && col >= 0 && (size_t)col <= strlen(ml_get(lnum)) && curwin->w_p_cole > 0) { - (void)syn_get_id(curwin, lnum, col, false, NULL, false); + syn_get_id(curwin, lnum, col, false, NULL, false); syntax_flags = get_syntax_info(&matchid); // get the conceal character @@ -8435,7 +8435,7 @@ static void f_synstack(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) && col >= 0 && (size_t)col <= strlen(ml_get(lnum))) { tv_list_alloc_ret(rettv, kListLenMayKnow); - (void)syn_get_id(curwin, lnum, col, false, NULL, true); + syn_get_id(curwin, lnum, col, false, NULL, true); int id; int i = 0; @@ -8509,8 +8509,8 @@ static void f_taglist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (argvars[1].v_type != VAR_UNKNOWN) { fname = tv_get_string(&argvars[1]); } - (void)get_tags(tv_list_alloc_ret(rettv, kListLenUnknown), - (char *)tag_pattern, (char *)fname); + get_tags(tv_list_alloc_ret(rettv, kListLenUnknown), + (char *)tag_pattern, (char *)fname); } /// "tempname()" function @@ -8629,7 +8629,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) curbuf->b_p_swf = false; apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, false, curbuf); - (void)setfname(curbuf, NameBuff, NULL, true); + setfname(curbuf, NameBuff, NULL, true); apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, false, curbuf); // Save the job id and pid in b:terminal_job_{id,pid} diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 42b105b2a2..18168d77b7 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2909,7 +2909,7 @@ static int tv_blob_index(const blob_T *blob, int len, varnumber_T idx, typval_T return OK; } -int tv_blob_slice_or_index(const blob_T *blob, int is_range, varnumber_T n1, varnumber_T n2, +int tv_blob_slice_or_index(const blob_T *blob, bool is_range, varnumber_T n1, varnumber_T n2, bool exclusive, typval_T *rettv) { int len = tv_blob_len(rettv->vval.v_blob); diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 5d8c173dd1..e74bf39476 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1175,7 +1175,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett // A Lambda always has the command "return {expr}". It is much faster // to evaluate {expr} directly. ex_nesting_level++; - (void)eval1(&p, rettv, &EVALARG_EVALUATE); + eval1(&p, rettv, &EVALARG_EVALUATE); ex_nesting_level--; } else { // call do_cmdline() to execute the lines @@ -2069,7 +2069,7 @@ char *save_function_name(char **name, bool skip, int flags, funcdict_T *fudi) if (strncmp(p, "", 8) == 0) { p += 8; - (void)getdigits(&p, false, 0); + getdigits(&p, false, 0); saved = xmemdupz(*name, (size_t)(p - *name)); if (fudi != NULL) { CLEAR_POINTER(fudi); @@ -3658,7 +3658,7 @@ bool free_unref_funccal(int copyID, int testing) if (did_free_funccal) { // When a funccal was freed some more items might be garbage // collected, so run again. - (void)garbage_collect(testing); + garbage_collect(testing); } return did_free; } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index dd984e8819..d57874480d 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -378,7 +378,7 @@ void ex_let(exarg_T *eap) if (!eap->skip) { op[0] = '='; op[1] = NUL; - (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op); + ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op); } tv_clear(&rettv); } @@ -415,7 +415,7 @@ void ex_let(exarg_T *eap) clear_evalarg(&evalarg, eap); if (!eap->skip && eval_res != FAIL) { - (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op); + ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op); } if (eval_res != FAIL) { tv_clear(&rettv); @@ -1303,7 +1303,7 @@ void vars_clear(hashtab_T *ht) } /// Like vars_clear(), but only free the value if "free_val" is true. -void vars_clear_ext(hashtab_T *ht, int free_val) +void vars_clear_ext(hashtab_T *ht, bool free_val) { int todo; hashitem_T *hi; diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index 230aec6abc..cb9e9293ae 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -675,13 +675,13 @@ static void win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags // Remove the old window and frame from the tree of frames int dir; - (void)winframe_remove(wp, &dir, NULL); + winframe_remove(wp, &dir, NULL); win_remove(wp, NULL); last_status(false); // may need to remove last status line - (void)win_comp_pos(); // recompute window positions + win_comp_pos(); // recompute window positions // Split a window on the desired side and put the old window there - (void)win_split_ins(size, flags, wp, dir); + win_split_ins(size, flags, wp, dir); // If splitting horizontally, try to preserve height if (size == 0 && !(flags & WSP_VERT)) { -- cgit From b49d4e18a67d16548fa72013237a87564656170e Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 1 Jan 2024 15:56:00 +0100 Subject: refactor: remove redundant NOLINT comments --- src/nvim/eval/typval.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 0013c8ffe5..0928fdea62 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -360,7 +360,7 @@ extern bool tv_in_free_unref_items; /// @param li Name of the variable with current listitem_T entry. /// @param code Cycle body. #define TV_LIST_ITER(l, li, code) \ - TV_LIST_ITER_MOD( , l, li, code) // NOLINT(whitespace/parens) + TV_LIST_ITER_MOD( , l, li, code) /// Iterate over a list /// -- cgit From 735aa4c4c89943b26f1d6ba0d3e076002490c09d Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sun, 31 Dec 2023 01:54:34 +0100 Subject: refactor: remove redundant struct names A struct can be anonymous if only its typedef is used. --- src/nvim/eval/typval_defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index a6a0282fad..9c94542d11 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -74,7 +74,7 @@ typedef struct { #define CALLBACK_NONE ((Callback)CALLBACK_INIT) /// Structure holding dictionary watcher -typedef struct dict_watcher { +typedef struct { Callback callback; char *key_pattern; size_t key_pattern_len; -- cgit From aeb053907d2f27713764e345b00a6618e23220d8 Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 3 Jan 2024 13:31:39 +0100 Subject: refactor(options): use schar_T representation for fillchars and listchars A bit big, but practically it was a lot simpler to change over all fillchars and all listchars at once, to not need to maintain two parallel implementations. This is mostly an internal refactor, but it also removes an arbitrary limitation: that 'fillchars' and 'listchars' values can only be single-codepoint characters. Now any character which fits into a single screen cell can be used. --- src/nvim/eval/funcs.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 6fae90134a..d843c37082 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -6881,15 +6881,8 @@ static void f_screenchar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) ScreenGrid *grid; screenchar_adjust(&grid, &row, &col); - int c; - if (row < 0 || row >= grid->rows || col < 0 || col >= grid->cols) { - c = -1; - } else { - char buf[MAX_SCHAR_SIZE + 1]; - schar_get(buf, grid_getchar(grid, row, col, NULL)); - c = utf_ptr2char(buf); - } - rettv->vval.v_number = c; + rettv->vval.v_number = (row < 0 || row >= grid->rows || col < 0 || col >= grid->cols) + ? -1 : schar_get_first_codepoint(grid_getchar(grid, row, col, NULL)); } /// "screenchars()" function @@ -8383,7 +8376,6 @@ static void f_synIDtrans(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) static void f_synconcealed(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { int syntax_flags = 0; - int cchar; int matchid = 0; char str[NUMBUFLEN]; @@ -8402,14 +8394,13 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, EvalFuncData fptr // get the conceal character if ((syntax_flags & HL_CONCEAL) && curwin->w_p_cole < 3) { - cchar = syn_get_sub_char(); + schar_T cchar = schar_from_char(syn_get_sub_char()); if (cchar == NUL && curwin->w_p_cole == 1) { cchar = (curwin->w_p_lcs_chars.conceal == NUL) - ? ' ' - : curwin->w_p_lcs_chars.conceal; + ? schar_from_ascii(' ') : curwin->w_p_lcs_chars.conceal; } if (cchar != NUL) { - utf_char2bytes(cchar, str); + schar_get(str, cchar); } } } -- cgit From 1813661a6197c76ea6621284570aca1d56597099 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Thu, 4 Jan 2024 15:38:16 +0100 Subject: refactor(IWYU): fix headers Remove `export` pramgas from defs headers as it causes IWYU to believe that the definitions from the defs headers comes from main header, which is not what we really want. --- src/nvim/eval/buffer.c | 1 + src/nvim/eval/decode.c | 3 ++- src/nvim/eval/encode.c | 16 +++++++++++++++- src/nvim/eval/encode.h | 19 +------------------ src/nvim/eval/executor.c | 2 +- src/nvim/eval/funcs.c | 24 +++++++++++++++++++++++- src/nvim/eval/typval.c | 6 ++++-- src/nvim/eval/typval.h | 6 +++--- src/nvim/eval/typval_defs.h | 3 ++- src/nvim/eval/userfunc.c | 8 +++++++- src/nvim/eval/vars.c | 5 ++++- src/nvim/eval/window.c | 5 +++-- src/nvim/eval/window.h | 2 +- 13 files changed, 67 insertions(+), 33 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index 2ae2b94ce9..291a57657d 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -5,6 +5,7 @@ #include "nvim/ascii_defs.h" #include "nvim/autocmd.h" +#include "nvim/autocmd_defs.h" #include "nvim/buffer.h" #include "nvim/buffer_defs.h" #include "nvim/change.h" diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index 64b65b42a5..d7df7bb150 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -14,8 +14,9 @@ #include "nvim/eval/encode.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" +#include "nvim/eval_defs.h" #include "nvim/garray.h" -#include "nvim/gettext.h" +#include "nvim/gettext_defs.h" #include "nvim/macros_defs.h" #include "nvim/mbyte.h" #include "nvim/memory.h" diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index 38be10dbaf..d35ac4eb7b 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -20,7 +20,7 @@ #include "nvim/eval/typval.h" #include "nvim/eval/typval_encode.h" #include "nvim/garray.h" -#include "nvim/gettext.h" +#include "nvim/gettext_defs.h" #include "nvim/globals.h" #include "nvim/hashtab.h" #include "nvim/macros_defs.h" @@ -1056,3 +1056,17 @@ char *encode_tv2json(typval_T *tv, size_t *len) #undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS #undef TYPVAL_ENCODE_CONV_RECURSE #undef TYPVAL_ENCODE_ALLOW_SPECIALS + +/// Initialize ListReaderState structure +ListReaderState encode_init_lrstate(const list_T *const list) + FUNC_ATTR_NONNULL_ALL +{ + return (ListReaderState) { + .list = list, + .li = tv_list_first(list), + .offset = 0, + .li_length = (TV_LIST_ITEM_TV(tv_list_first(list))->vval.v_string == NULL + ? 0 + : strlen(TV_LIST_ITEM_TV(tv_list_first(list))->vval.v_string)), + }; +} diff --git a/src/nvim/eval/encode.h b/src/nvim/eval/encode.h index fe1b951e3c..6d1c0b61c5 100644 --- a/src/nvim/eval/encode.h +++ b/src/nvim/eval/encode.h @@ -3,8 +3,7 @@ #include #include -#include "nvim/eval/typval.h" -#include "nvim/func_attr.h" +#include "nvim/eval/typval_defs.h" #include "nvim/garray_defs.h" /// Convert Vimscript value to msgpack string @@ -33,22 +32,6 @@ typedef struct { size_t li_length; ///< Length of the string inside the read item. } ListReaderState; -static inline ListReaderState encode_init_lrstate(const list_T *list) - REAL_FATTR_NONNULL_ALL; - -/// Initialize ListReaderState structure -static inline ListReaderState encode_init_lrstate(const list_T *const list) -{ - return (ListReaderState) { - .list = list, - .li = tv_list_first(list), - .offset = 0, - .li_length = (TV_LIST_ITEM_TV(tv_list_first(list))->vval.v_string == NULL - ? 0 - : strlen(TV_LIST_ITEM_TV(tv_list_first(list))->vval.v_string)), - }; -} - /// Array mapping values from SpecialVarValue enum to names extern const char *const encode_bool_var_names[]; extern const char *const encode_special_var_names[]; diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c index b483f5fbef..1b8c057d7c 100644 --- a/src/nvim/eval/executor.c +++ b/src/nvim/eval/executor.c @@ -6,7 +6,7 @@ #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" #include "nvim/garray.h" -#include "nvim/gettext.h" +#include "nvim/gettext_defs.h" #include "nvim/globals.h" #include "nvim/message.h" #include "nvim/strings.h" diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index d843c37082..4d60cd3660 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -19,14 +19,18 @@ #include "auto/config.h" #include "nvim/api/private/converter.h" +#include "nvim/api/private/defs.h" #include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" #include "nvim/ascii_defs.h" #include "nvim/assert_defs.h" #include "nvim/autocmd.h" +#include "nvim/autocmd_defs.h" #include "nvim/buffer.h" +#include "nvim/buffer_defs.h" #include "nvim/channel.h" +#include "nvim/channel_defs.h" #include "nvim/charset.h" #include "nvim/cmdexpand.h" #include "nvim/cmdexpand_defs.h" @@ -45,21 +49,26 @@ #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" #include "nvim/eval/window.h" +#include "nvim/event/defs.h" #include "nvim/event/loop.h" #include "nvim/event/multiqueue.h" #include "nvim/event/process.h" #include "nvim/event/time.h" #include "nvim/ex_cmds.h" +#include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" #include "nvim/ex_eval.h" #include "nvim/ex_getln.h" #include "nvim/file_search.h" #include "nvim/fileio.h" #include "nvim/garray.h" +#include "nvim/garray_defs.h" #include "nvim/getchar.h" -#include "nvim/gettext.h" +#include "nvim/getchar_defs.h" +#include "nvim/gettext_defs.h" #include "nvim/globals.h" #include "nvim/grid.h" +#include "nvim/grid_defs.h" #include "nvim/highlight_defs.h" #include "nvim/highlight_group.h" #include "nvim/indent.h" @@ -71,24 +80,34 @@ #include "nvim/macros_defs.h" #include "nvim/main.h" #include "nvim/mark.h" +#include "nvim/mark_defs.h" #include "nvim/math.h" #include "nvim/mbyte.h" +#include "nvim/mbyte_defs.h" #include "nvim/memline.h" #include "nvim/memory.h" +#include "nvim/memory_defs.h" #include "nvim/menu.h" +#include "nvim/menu_defs.h" #include "nvim/message.h" #include "nvim/move.h" #include "nvim/msgpack_rpc/channel.h" +#include "nvim/msgpack_rpc/channel_defs.h" #include "nvim/msgpack_rpc/server.h" #include "nvim/normal.h" +#include "nvim/normal_defs.h" #include "nvim/ops.h" #include "nvim/option.h" +#include "nvim/option_defs.h" #include "nvim/option_vars.h" #include "nvim/optionstr.h" #include "nvim/os/dl.h" #include "nvim/os/fileio.h" +#include "nvim/os/fileio_defs.h" #include "nvim/os/fs.h" +#include "nvim/os/fs_defs.h" #include "nvim/os/os.h" +#include "nvim/os/os_defs.h" #include "nvim/os/pty_process.h" #include "nvim/os/shell.h" #include "nvim/os/stdpaths_defs.h" @@ -99,12 +118,15 @@ #include "nvim/pos_defs.h" #include "nvim/profile.h" #include "nvim/regexp.h" +#include "nvim/regexp_defs.h" #include "nvim/runtime.h" +#include "nvim/runtime_defs.h" #include "nvim/search.h" #include "nvim/sha256.h" #include "nvim/spell.h" #include "nvim/spellsuggest.h" #include "nvim/state.h" +#include "nvim/state_defs.h" #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/tag.h" diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 18168d77b7..2892cb60f9 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -19,10 +19,12 @@ #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" #include "nvim/garray.h" -#include "nvim/gettext.h" +#include "nvim/garray_defs.h" +#include "nvim/gettext_defs.h" #include "nvim/globals.h" #include "nvim/hashtab.h" -#include "nvim/lib/queue.h" +#include "nvim/hashtab_defs.h" +#include "nvim/lib/queue_defs.h" #include "nvim/lua/executor.h" #include "nvim/macros_defs.h" #include "nvim/mbyte.h" diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 0928fdea62..f9ebd2f778 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -6,11 +6,11 @@ #include #include -#include "nvim/eval/typval_defs.h" // IWYU pragma: export +#include "nvim/eval/typval_defs.h" // IWYU pragma: keep #include "nvim/func_attr.h" -#include "nvim/gettext.h" +#include "nvim/gettext_defs.h" #include "nvim/hashtab.h" -#include "nvim/lib/queue.h" +#include "nvim/lib/queue_defs.h" #include "nvim/macros_defs.h" #include "nvim/mbyte_defs.h" // IWYU pragma: keep #include "nvim/message.h" diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index 9c94542d11..0d6ee28adc 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -2,10 +2,11 @@ #include #include +#include #include "nvim/garray_defs.h" #include "nvim/hashtab_defs.h" -#include "nvim/lib/queue.h" +#include "nvim/lib/queue_defs.h" #include "nvim/pos_defs.h" #include "nvim/types_defs.h" diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index e74bf39476..fe10d56d49 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -10,6 +10,7 @@ #include "nvim/ascii_defs.h" #include "nvim/autocmd.h" +#include "nvim/autocmd_defs.h" #include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/cmdexpand_defs.h" @@ -23,10 +24,13 @@ #include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" #include "nvim/ex_eval.h" +#include "nvim/ex_eval_defs.h" #include "nvim/ex_getln.h" #include "nvim/garray.h" +#include "nvim/garray_defs.h" #include "nvim/getchar.h" -#include "nvim/gettext.h" +#include "nvim/getchar_defs.h" +#include "nvim/gettext_defs.h" #include "nvim/globals.h" #include "nvim/hashtab.h" #include "nvim/insexpand.h" @@ -41,11 +45,13 @@ #include "nvim/path.h" #include "nvim/profile.h" #include "nvim/regexp.h" +#include "nvim/regexp_defs.h" #include "nvim/runtime.h" #include "nvim/search.h" #include "nvim/strings.h" #include "nvim/types_defs.h" #include "nvim/ui.h" +#include "nvim/ui_defs.h" #include "nvim/vim_defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index d57874480d..14498a19fc 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -11,6 +11,7 @@ #include "nvim/ascii_defs.h" #include "nvim/autocmd.h" +#include "nvim/autocmd_defs.h" #include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/drawscreen.h" @@ -18,15 +19,17 @@ #include "nvim/eval/encode.h" #include "nvim/eval/funcs.h" #include "nvim/eval/typval.h" +#include "nvim/eval/typval_defs.h" #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" #include "nvim/eval/window.h" +#include "nvim/eval_defs.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" #include "nvim/ex_eval.h" #include "nvim/garray.h" -#include "nvim/gettext.h" +#include "nvim/gettext_defs.h" #include "nvim/globals.h" #include "nvim/hashtab.h" #include "nvim/macros_defs.h" diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index cb9e9293ae..b621cec5f4 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -15,10 +15,11 @@ #include "nvim/eval/typval_defs.h" #include "nvim/eval/window.h" #include "nvim/garray.h" -#include "nvim/gettext.h" +#include "nvim/garray_defs.h" +#include "nvim/gettext_defs.h" #include "nvim/globals.h" #include "nvim/macros_defs.h" -#include "nvim/mark.h" +#include "nvim/mark_defs.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/move.h" diff --git a/src/nvim/eval/window.h b/src/nvim/eval/window.h index 1b2817edf0..37cb138404 100644 --- a/src/nvim/eval/window.h +++ b/src/nvim/eval/window.h @@ -6,7 +6,7 @@ #include "nvim/eval/typval_defs.h" // IWYU pragma: keep #include "nvim/os/os_defs.h" #include "nvim/pos_defs.h" -#include "nvim/types_defs.h" // IWYU pragma: keep +#include "nvim/types_defs.h" /// Structure used by switch_win() to pass values to restore_win() typedef struct { -- cgit From 73e1942abe7a96d63ce3749af4187f2cdff87e69 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 16 Jan 2024 08:00:08 +0800 Subject: vim-patch:9.1.0009: Cannot easily get the list of matches (#27028) Problem: Cannot easily get the list of matches Solution: Add the matchstrlist() and matchbufline() Vim script functions (Yegappan Lakshmanan) closes: vim/vim#13766 Omit CHECK_LIST_MATERIALIZE(): it populates a List with numbers only, and there is a check for strings below. https://github.com/vim/vim/commit/f93b1c881a99fa847a1bafa71877d7e16f18e6ef vim-patch:eb3475df0d92 runtime(doc): Replace non-breaking space with normal space (vim/vim#13868) https://github.com/vim/vim/commit/eb3475df0d927a178789cf8e7fc4983932e1cdbe Co-authored-by: Yegappan Lakshmanan <4298407+yegappan@users.noreply.github.com> --- src/nvim/eval/funcs.c | 212 +++++++++++++++++++++++++++++++++++++++++++++++++ src/nvim/eval/typval.c | 16 ++++ 2 files changed, 228 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 4d60cd3660..26e4e24124 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -4731,6 +4731,151 @@ theend: p_cpo = save_cpo; } +/// Return all the matches in string "str" for pattern "rmp". +/// The matches are returned in the List "mlist". +/// If "submatches" is true, then submatch information is also returned. +/// "matchbuf" is true when called for matchbufline(). +static void get_matches_in_str(const char *str, regmatch_T *rmp, list_T *mlist, int idx, + bool submatches, bool matchbuf) +{ + size_t len = strlen(str); + int match = 0; + colnr_T startidx = 0; + + while (true) { + match = vim_regexec_nl(rmp, str, startidx); + if (!match) { + break; + } + + dict_T *d = tv_dict_alloc(); + tv_list_append_dict(mlist, d); + + if (matchbuf) { + tv_dict_add_nr(d, S_LEN("lnum"), idx); + } else { + tv_dict_add_nr(d, S_LEN("idx"), idx); + } + + tv_dict_add_nr(d, S_LEN("byteidx"), + (colnr_T)(rmp->startp[0] - str)); + + tv_dict_add_str_len(d, S_LEN("text"), rmp->startp[0], + (int)(rmp->endp[0] - rmp->startp[0])); + + if (submatches) { + list_T *sml = tv_list_alloc(NSUBEXP - 1); + + tv_dict_add_list(d, S_LEN("submatches"), sml); + + // return a list with the submatches + for (int i = 1; i < NSUBEXP; i++) { + if (rmp->endp[i] == NULL) { + tv_list_append_string(sml, "", 0); + } else { + tv_list_append_string(sml, rmp->startp[i], rmp->endp[i] - rmp->startp[i]); + } + } + } + startidx = (colnr_T)(rmp->endp[0] - str); + if (startidx >= (colnr_T)len || str + startidx <= rmp->startp[0]) { + break; + } + } +} + +/// "matchbufline()" function +static void f_matchbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + rettv->vval.v_number = -1; + tv_list_alloc_ret(rettv, kListLenUnknown); + list_T *retlist = rettv->vval.v_list; + + if (tv_check_for_buffer_arg(argvars, 0) == FAIL + || tv_check_for_string_arg(argvars, 1) == FAIL + || tv_check_for_lnum_arg(argvars, 2) == FAIL + || tv_check_for_lnum_arg(argvars, 3) == FAIL + || tv_check_for_opt_dict_arg(argvars, 4) == FAIL) { + return; + } + + const int prev_did_emsg = did_emsg; + buf_T *buf = tv_get_buf(&argvars[0], false); + if (buf == NULL) { + if (did_emsg == prev_did_emsg) { + semsg(_(e_invalid_buffer_name_str), tv_get_string(&argvars[0])); + } + return; + } + if (buf->b_ml.ml_mfp == NULL) { + emsg(_(e_buffer_is_not_loaded)); + return; + } + + char patbuf[NUMBUFLEN]; + const char *pat = tv_get_string_buf(&argvars[1], patbuf); + + const int did_emsg_before = did_emsg; + linenr_T slnum = tv_get_lnum_buf(&argvars[2], buf); + if (did_emsg > did_emsg_before) { + return; + } + if (slnum < 1) { + semsg(_(e_invargval), "lnum"); + return; + } + + linenr_T elnum = tv_get_lnum_buf(&argvars[3], buf); + if (did_emsg > did_emsg_before) { + return; + } + if (elnum < 1 || elnum < slnum) { + semsg(_(e_invargval), "end_lnum"); + return; + } + + if (elnum > buf->b_ml.ml_line_count) { + elnum = buf->b_ml.ml_line_count; + } + + bool submatches = false; + if (argvars[4].v_type != VAR_UNKNOWN) { + dict_T *d = argvars[4].vval.v_dict; + if (d != NULL) { + dictitem_T *di = tv_dict_find(d, S_LEN("submatches")); + if (di != NULL) { + if (di->di_tv.v_type != VAR_BOOL) { + semsg(_(e_invargval), "submatches"); + return; + } + submatches = tv_get_bool(&di->di_tv); + } + } + } + + // Make 'cpoptions' empty, the 'l' flag should not be used here. + char *const save_cpo = p_cpo; + p_cpo = empty_string_option; + + regmatch_T regmatch; + regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); + if (regmatch.regprog == NULL) { + goto theend; + } + regmatch.rm_ic = p_ic; + + while (slnum <= elnum) { + const char *str = ml_get_buf(buf, slnum); + get_matches_in_str(str, ®match, retlist, slnum, submatches, true); + slnum++; + } + + vim_regfree(regmatch.regprog); + +theend: + p_cpo = save_cpo; +} + /// "match()" function static void f_match(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -4755,6 +4900,73 @@ static void f_matchstr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) find_some_match(argvars, rettv, kSomeMatchStr); } +/// "matchstrlist()" function +static void f_matchstrlist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + rettv->vval.v_number = -1; + tv_list_alloc_ret(rettv, kListLenUnknown); + list_T *retlist = rettv->vval.v_list; + + if (tv_check_for_list_arg(argvars, 0) == FAIL + || tv_check_for_string_arg(argvars, 1) == FAIL + || tv_check_for_opt_dict_arg(argvars, 2) == FAIL) { + return; + } + + list_T *l = NULL; + if ((l = argvars[0].vval.v_list) == NULL) { + return; + } + + char patbuf[NUMBUFLEN]; + const char *pat = tv_get_string_buf_chk(&argvars[1], patbuf); + if (pat == NULL) { + return; + } + + // Make 'cpoptions' empty, the 'l' flag should not be used here. + char *const save_cpo = p_cpo; + p_cpo = empty_string_option; + + regmatch_T regmatch; + regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); + if (regmatch.regprog == NULL) { + goto theend; + } + regmatch.rm_ic = p_ic; + + bool submatches = false; + if (argvars[2].v_type != VAR_UNKNOWN) { + dict_T *d = argvars[2].vval.v_dict; + if (d != NULL) { + dictitem_T *di = tv_dict_find(d, S_LEN("submatches")); + if (di != NULL) { + if (di->di_tv.v_type != VAR_BOOL) { + semsg(_(e_invargval), "submatches"); + goto cleanup; + } + submatches = tv_get_bool(&di->di_tv); + } + } + } + + int idx = 0; + TV_LIST_ITER_CONST(l, li, { + const typval_T *const li_tv = TV_LIST_ITEM_TV(li); + if (li_tv->v_type == VAR_STRING && li_tv->vval.v_string != NULL) { + const char *str = li_tv->vval.v_string; + get_matches_in_str(str, ®match, retlist, idx, submatches, false); + } + idx++; + }); + +cleanup: + vim_regfree(regmatch.regprog); + +theend: + p_cpo = save_cpo; +} + /// "matchstrpos()" function static void f_matchstrpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 2892cb60f9..d510cf2a3d 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -4346,6 +4346,22 @@ int tv_check_for_string_or_number_arg(const typval_T *const args, const int idx) return OK; } +/// Give an error and return FAIL unless "args[idx]" is a buffer number. +/// Buffer number can be a number or a string. +int tv_check_for_buffer_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + return tv_check_for_string_or_number_arg(args, idx); +} + +/// Give an error and return FAIL unless "args[idx]" is a line number. +/// Line number can be a number or a string. +int tv_check_for_lnum_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + return tv_check_for_string_or_number_arg(args, idx); +} + /// Give an error and return FAIL unless "args[idx]" is a string or a list. int tv_check_for_string_or_list_arg(const typval_T *const args, const int idx) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE -- cgit From 12d123959f56636473112d86ec5977ef993c58e5 Mon Sep 17 00:00:00 2001 From: Raphael Date: Mon, 22 Jan 2024 16:04:50 +0800 Subject: fix(eval): properly support checking v:lua function in exists() (#27124) --- src/nvim/eval/funcs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 26e4e24124..d5d16fb1ef 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1726,7 +1726,7 @@ static void f_exists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) n = false; // Trailing garbage. } } else if (*p == '*') { // Internal or user defined function. - n = function_exists(p + 1, false); + n = strncmp(p, "*v:lua.", 7) == 0 ? nlua_func_exists(p + 7) : function_exists(p + 1, false); } else if (*p == ':') { n = cmd_exists(p + 1); } else if (*p == '#') { @@ -1735,8 +1735,6 @@ static void f_exists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } else { n = au_exists(p + 1); } - } else if (strncmp(p, "v:lua.", 6) == 0 && nlua_func_exists(p + 6)) { - n = true; } else { // Internal variable. n = var_exists(p); } -- cgit From 9af2be292db3db7b28a6210263f719a6bbc4059f Mon Sep 17 00:00:00 2001 From: bfredl Date: Fri, 12 Jan 2024 14:38:18 +0100 Subject: perf(extmarks): add metadata for efficient filtering of special decorations This expands on the global "don't pay for what you don't use" rules for these special extmark decorations: - inline virtual text, which needs to be processed in plines.c when we calculate the size of text on screen - virtual lines, which are needed when calculating "filler" lines - signs, with text and/or highlights, both of which needs to be processed for the entire line already at the beginning of a line. This adds a count to each node of the marktree, for how many special marks of each kind can be found in the subtree for this node. This makes it possible to quickly skip over these extra checks, when working in regions of the buffer not containing these kind of marks, instead of before where this could just be skipped if the entire _buffer_ didn't contain such marks. --- src/nvim/eval/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index 291a57657d..c43ef50410 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -507,7 +507,7 @@ static dict_T *get_buffer_info(buf_T *buf) } tv_dict_add_list(dict, S_LEN("windows"), windows); - if (buf->b_signs) { + if (buf_has_signs(buf)) { // List of signs placed in this buffer tv_dict_add_list(dict, S_LEN("signs"), get_buffer_signs(buf)); } -- cgit From cf140fb25b94c556396fe942a4af3e8db9effa37 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Thu, 27 Jul 2023 01:38:23 +0100 Subject: vim-patch:9.1.0047: issues with temp curwin/buf while cmdwin is open Problem: Things that temporarily change/restore curwin/buf (e.g: win_execute, some autocmds) may break assumptions that curwin/buf is the cmdwin when "cmdwin_type != 0", causing issues. Solution: Expose the cmdwin's real win/buf and check that instead. Also try to ensure these variables are NULL if "cmdwin_type == 0", allowing them to be used directly in most cases without checking cmdwin_type. (Sean Dewar) Reset and save `cmdwin_old_curwin` in a similar fashion. Apply suitable changes for API functions and add Lua tests. https://github.com/vim/vim/commit/988f74311c26ea9917e84fbae608de226dba7e5f --- src/nvim/eval/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index b621cec5f4..b8aa0c9641 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -755,7 +755,7 @@ void f_win_gettype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_string = xstrdup("preview"); } else if (wp->w_floating) { rettv->vval.v_string = xstrdup("popup"); - } else if (wp == curwin && cmdwin_type != 0) { + } else if (wp == cmdwin_win) { rettv->vval.v_string = xstrdup("command"); } else if (bt_quickfix(wp->w_buffer)) { rettv->vval.v_string = xstrdup((wp->w_llist_ref != NULL ? "loclist" : "quickfix")); -- cgit From d85f180f26c0570c2510c899a0bf0023ec55a692 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Tue, 15 Aug 2023 19:38:52 +0100 Subject: vim-patch:9.1.0049: Make "[Command Line]" a special buffer name Problem: E95 is possible if a buffer called "[Command Line]" already exists when opening the cmdwin. This can also happen if the cmdwin's buffer could not be deleted when closing. Solution: Un-name the cmdwin buffer, and give it a special name instead, similar to what's done for quickfix buffers and for unnamed prompt and scratch buffers. As a result, BufFilePre/Post are no longer fired when opening the cmdwin. Add a "command" key to the dictionary returned by getbufinfo() to differentiate the cmdwin buffer instead. (Sean Dewar) Cherry-pick test_normal changes from v9.0.0954. https://github.com/vim/vim/commit/1fb41032060df09ca2640dc49541f11062f6dfaa --- src/nvim/eval/buffer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index c43ef50410..7b8f71ef3f 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -494,6 +494,7 @@ static dict_T *get_buffer_info(buf_T *buf) tv_dict_add_nr(dict, S_LEN("changed"), bufIsChanged(buf)); tv_dict_add_nr(dict, S_LEN("changedtick"), buf_get_changedtick(buf)); tv_dict_add_nr(dict, S_LEN("hidden"), buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0); + tv_dict_add_nr(dict, S_LEN("command"), buf == cmdwin_buf); // Get a reference to buffer variables tv_dict_add_dict(dict, S_LEN("variables"), buf->b_vars); -- cgit From 8fa67fdae539a13cf78621ab5a628da1fd745be2 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 1 Feb 2024 09:39:48 +0800 Subject: vim-patch:8.2.0085: dead code in builtin functions (#27281) Problem: Dead code in builtin functions. Solution: Clean up the code. https://github.com/vim/vim/commit/3d8a513b46b586cb5d2893e7f28c5f51c4dfdc17 Co-authored-by: Bram Moolenaar --- src/nvim/eval/vars.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 14498a19fc..e149796fac 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1968,7 +1968,7 @@ static void set_option_from_tv(const char *varname, typval_T *varp) } /// "setwinvar()" and "settabwinvar()" functions -static void setwinvar(typval_T *argvars, typval_T *rettv, int off) +static void setwinvar(typval_T *argvars, int off) { if (check_secure()) { return; @@ -2077,8 +2077,6 @@ void f_getbufvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "settabvar()" function void f_settabvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - rettv->vval.v_number = 0; - if (check_secure()) { return; } @@ -2110,13 +2108,13 @@ void f_settabvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "settabwinvar()" function void f_settabwinvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - setwinvar(argvars, rettv, 1); + setwinvar(argvars, 1); } /// "setwinvar()" function void f_setwinvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - setwinvar(argvars, rettv, 0); + setwinvar(argvars, 0); } /// "setbufvar()" function -- cgit From 1f40b4e22232f22551a9ae89a9f8d59b5ba0c0b6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 3 Feb 2024 09:42:04 +0800 Subject: vim-patch:9.0.1105: code is indented too much (#27314) Problem: Code is indented too much. Solution: Use an early return. (Yegappan Lakshmanan, closes vim/vim#11756) https://github.com/vim/vim/commit/87c1cbbe984e60582f2536e4d3c2ce88cd474bb7 Omit free_eval_tofree_later(): Vim9 script only. Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 144 +++++++++++++++++++++++++++----------------------- 1 file changed, 77 insertions(+), 67 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index d5d16fb1ef..655d6c9ab3 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1937,44 +1937,47 @@ static void extend_list(typval_T *argvars, const char *arg_errmsg, bool is_new, list_T *l1 = argvars[0].vval.v_list; list_T *const l2 = argvars[1].vval.v_list; - if (is_new || !value_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) { - if (is_new) { - l1 = tv_list_copy(NULL, l1, false, get_copyID()); - if (l1 == NULL) { - return; - } - } - listitem_T *item; - if (argvars[2].v_type != VAR_UNKNOWN) { - int before = (int)tv_get_number_chk(&argvars[2], &error); - if (error) { - return; // Type error; errmsg already given. - } + if (!is_new && value_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) { + return; + } - if (before == tv_list_len(l1)) { - item = NULL; - } else { - item = tv_list_find(l1, before); - if (item == NULL) { - semsg(_(e_list_index_out_of_range_nr), (int64_t)before); - return; - } - } - } else { - item = NULL; + if (is_new) { + l1 = tv_list_copy(NULL, l1, false, get_copyID()); + if (l1 == NULL) { + return; } - tv_list_extend(l1, l2, item); + } - if (is_new) { - *rettv = (typval_T){ - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval.v_list = l1, - }; + listitem_T *item; + if (argvars[2].v_type != VAR_UNKNOWN) { + int before = (int)tv_get_number_chk(&argvars[2], &error); + if (error) { + return; // Type error; errmsg already given. + } + + if (before == tv_list_len(l1)) { + item = NULL; } else { - tv_copy(&argvars[0], rettv); + item = tv_list_find(l1, before); + if (item == NULL) { + semsg(_(e_list_index_out_of_range_nr), (int64_t)before); + return; + } } + } else { + item = NULL; + } + tv_list_extend(l1, l2, item); + + if (is_new) { + *rettv = (typval_T){ + .v_type = VAR_LIST, + .v_lock = VAR_UNLOCKED, + .vval.v_list = l1, + }; + } else { + tv_copy(&argvars[0], rettv); } } @@ -1985,54 +1988,61 @@ static void extend_list(typval_T *argvars, const char *arg_errmsg, bool is_new, static void extend_dict(typval_T *argvars, const char *arg_errmsg, bool is_new, typval_T *rettv) { dict_T *d1 = argvars[0].vval.v_dict; - dict_T *const d2 = argvars[1].vval.v_dict; if (d1 == NULL) { const bool locked = value_check_lock(VAR_FIXED, arg_errmsg, TV_TRANSLATE); (void)locked; assert(locked == true); - } else if (d2 == NULL) { + return; + } + dict_T *const d2 = argvars[1].vval.v_dict; + if (d2 == NULL) { // Do nothing tv_copy(&argvars[0], rettv); - } else if (is_new || !value_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) { - if (is_new) { - d1 = tv_dict_copy(NULL, d1, false, get_copyID()); - if (d1 == NULL) { - return; - } + return; + } + + if (!is_new && value_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) { + return; + } + + if (is_new) { + d1 = tv_dict_copy(NULL, d1, false, get_copyID()); + if (d1 == NULL) { + return; } + } - const char *action = "force"; - // Check the third argument. - if (argvars[2].v_type != VAR_UNKNOWN) { - const char *const av[] = { "keep", "force", "error" }; + const char *action = "force"; + // Check the third argument. + if (argvars[2].v_type != VAR_UNKNOWN) { + const char *const av[] = { "keep", "force", "error" }; - action = tv_get_string_chk(&argvars[2]); - if (action == NULL) { - return; // Type error; error message already given. - } - size_t i; - for (i = 0; i < ARRAY_SIZE(av); i++) { - if (strcmp(action, av[i]) == 0) { - break; - } - } - if (i == 3) { - semsg(_(e_invarg2), action); - return; + action = tv_get_string_chk(&argvars[2]); + if (action == NULL) { + return; // Type error; error message already given. + } + size_t i; + for (i = 0; i < ARRAY_SIZE(av); i++) { + if (strcmp(action, av[i]) == 0) { + break; } } + if (i == 3) { + semsg(_(e_invarg2), action); + return; + } + } - tv_dict_extend(d1, d2, action); + tv_dict_extend(d1, d2, action); - if (is_new) { - *rettv = (typval_T){ - .v_type = VAR_DICT, - .v_lock = VAR_UNLOCKED, - .vval.v_dict = d1, - }; - } else { - tv_copy(&argvars[0], rettv); - } + if (is_new) { + *rettv = (typval_T){ + .v_type = VAR_DICT, + .v_lock = VAR_UNLOCKED, + .vval.v_dict = d1, + }; + } else { + tv_copy(&argvars[0], rettv); } } -- cgit From 9ab9cde2ca7b917a894068698ef2fec3a851fdd5 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 3 Feb 2024 10:22:11 +0800 Subject: vim-patch:partial:9.0.1196: code is indented more than necessary (#27315) Problem: Code is indented more than necessary. Solution: Use an early return where it makes sense. (Yegappan Lakshmanan, closes vim/vim#11813) https://github.com/vim/vim/commit/e8575988969579f9e1439181ae338b2ff74054a8 Skip list_alloc_with_items(). Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/typval.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index d510cf2a3d..fb9e7ff9a8 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -623,13 +623,14 @@ tv_list_copy_error: listitem_T *tv_list_check_range_index_one(list_T *const l, int *const n1, const bool quiet) { listitem_T *li = tv_list_find_index(l, n1); - if (li == NULL) { - if (!quiet) { - semsg(_(e_list_index_out_of_range_nr), (int64_t)(*n1)); - } - return NULL; + if (li != NULL) { + return li; } - return li; + + if (!quiet) { + semsg(_(e_list_index_out_of_range_nr), (int64_t)(*n1)); + } + return NULL; } /// Check that "n2" can be used as the second index in a range of list "l". @@ -1634,11 +1635,13 @@ static listitem_T *tv_list_find_index(list_T *const l, int *const idx) FUNC_ATTR_WARN_UNUSED_RESULT { listitem_T *li = tv_list_find(l, *idx); - if (li == NULL) { - if (*idx < 0) { - *idx = 0; - li = tv_list_find(l, *idx); - } + if (li != NULL) { + return li; + } + + if (*idx < 0) { + *idx = 0; + li = tv_list_find(l, *idx); } return li; } @@ -2130,10 +2133,12 @@ void tv_dict_free_dict(dict_T *const d) void tv_dict_free(dict_T *const d) FUNC_ATTR_NONNULL_ALL { - if (!tv_in_free_unref_items) { - tv_dict_free_contents(d); - tv_dict_free_dict(d); + if (tv_in_free_unref_items) { + return; } + + tv_dict_free_contents(d); + tv_dict_free_dict(d); } /// Unreference a dictionary -- cgit From e0e5b7f0ba1b0440bdc2b557e2b2cfae24706cbd Mon Sep 17 00:00:00 2001 From: bfredl Date: Fri, 9 Feb 2024 11:42:40 +0100 Subject: refactor(api): make cstr_as_string accept "const char*" In the context a String inside an Object/Dictionary etc is consumed, it is considered to be read-only. --- src/nvim/eval/funcs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 655d6c9ab3..e4d2a219d9 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2093,8 +2093,8 @@ static void f_feedkeys(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) flags = tv_get_string_buf(&argvars[1], nbuf); } - nvim_feedkeys(cstr_as_string((char *)keys), - cstr_as_string((char *)flags), true); + nvim_feedkeys(cstr_as_string(keys), + cstr_as_string(flags), true); } /// "filereadable()" function @@ -4528,7 +4528,7 @@ static void f_luaeval(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - nlua_typval_eval(cstr_as_string((char *)str), &argvars[1], rettv); + nlua_typval_eval(cstr_as_string(str), &argvars[1], rettv); } static void find_some_match(typval_T *const argvars, typval_T *const rettv, -- cgit From 2493fd020d6f294c78a87b0f7f35c0398b248f1f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 13 Feb 2024 07:27:27 +0800 Subject: vim-patch:9.1.0102: settabvar() may change the last accessed tabpage (#27450) Problem: settabvar() may change the last accessed tabpage. Solution: Save and restore lastused_tabpage. (zeertzjq) closes: vim/vim#14017 https://github.com/vim/vim/commit/b47fbb40837512cdd2d8c25eaf9952154836b99d --- src/nvim/eval/vars.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index e149796fac..e016c65d90 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -2090,6 +2090,7 @@ void f_settabvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } tabpage_T *const save_curtab = curtab; + tabpage_T *const save_lu_tp = lastused_tabpage; goto_tabpage_tp(tp, false, false); const size_t varname_len = strlen(varname); @@ -2099,9 +2100,12 @@ void f_settabvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) set_var(tabvarname, varname_len + 2, varp, true); xfree(tabvarname); - // Restore current tabpage. + // Restore current tabpage and last accessed tabpage. if (valid_tabpage(save_curtab)) { goto_tabpage_tp(save_curtab, false, false); + if (valid_tabpage(save_lu_tp)) { + lastused_tabpage = save_lu_tp; + } } } -- cgit From 0353dd3029f9ce31c3894530385443a90f6677ee Mon Sep 17 00:00:00 2001 From: bfredl Date: Sun, 11 Feb 2024 15:46:14 +0100 Subject: refactor(lua): use Arena when converting from lua stack to API args and for return value of nlua_exec/nlua_call_ref, as this uses the same family of functions. NB: the handling of luaref:s is a bit of a mess. add api_luarefs_free_XX functions as a stop-gap as refactoring luarefs is a can of worms for another PR:s. as a minor feature/bug-fix, nvim_buf_call and nvim_win_call now preserves arbitrary return values. --- src/nvim/eval/funcs.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index e4d2a219d9..726b9ce758 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3278,13 +3278,11 @@ static bool has_wsl(void) static TriState has_wsl = kNone; if (has_wsl == kNone) { Error err = ERROR_INIT; - Object o = nlua_exec(STATIC_CSTR_AS_STRING("return vim.uv.os_uname()['release']:lower()" - ":match('microsoft') and true or false"), - (Array)ARRAY_DICT_INIT, &err); + Object o = NLUA_EXEC_STATIC("return vim.uv.os_uname()['release']:lower()" + ":match('microsoft')", + (Array)ARRAY_DICT_INIT, kRetNilBool, NULL, &err); assert(!ERROR_SET(&err)); - assert(o.type == kObjectTypeBoolean); - has_wsl = o.data.boolean ? kTrue : kFalse; - api_free_object(o); + has_wsl = LUARET_TRUTHY(o) ? kTrue : kFalse; } return has_wsl == kTrue; } @@ -6963,6 +6961,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) ArenaMem res_mem = NULL; Object result = rpc_send_call(chan_id, method, args, &res_mem, &err); + api_free_array(args); if (l_provider_call_nesting) { current_sctx = save_current_sctx; -- cgit From d60412b18e4e21f301baa2ac3f3fb7be89655e4b Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 12 Feb 2024 20:40:27 +0100 Subject: refactor(eval): use arena when converting typvals to Object Note: this contains two _temporary_ changes which can be reverted once the Arena vs no-Arena distinction in API wrappers has been removed. Both nlua_push_Object and object_to_vim_take_luaref() has been changed to take the object argument as a pointer. This is not going to be necessary once these are only used with arena (or not at all) allocated Objects. The object_to_vim() variant which leaves luaref untouched might need to stay for a little longer. --- src/nvim/eval/funcs.c | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 726b9ce758..28365e16df 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -359,15 +359,15 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) MsgpackRpcRequestHandler handler = *fptr.api_handler; - Array args = ARRAY_DICT_INIT; + MAXSIZE_TEMP_ARRAY(args, MAX_FUNC_ARGS); + Arena arena = ARENA_EMPTY; for (typval_T *tv = argvars; tv->v_type != VAR_UNKNOWN; tv++) { - ADD(args, vim_to_object(tv)); + ADD_C(args, vim_to_object(tv, &arena, false)); } Error err = ERROR_INIT; - Arena res_arena = ARENA_EMPTY; - Object result = handler.fn(VIML_INTERNAL_CALL, args, &res_arena, &err); + Object result = handler.fn(VIML_INTERNAL_CALL, args, &arena, &err); if (ERROR_SET(&err)) { semsg_multiline(e_api_error, err.msg); @@ -377,12 +377,10 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) object_to_vim(result, rettv, &err); end: - api_free_array(args); - if (handler.arena_return) { - arena_mem_free(arena_finish(&res_arena)); - } else { + if (!handler.arena_return) { api_free_object(result); } + arena_mem_free(arena_finish(&arena)); api_clear_error(&err); } @@ -1037,10 +1035,11 @@ static void f_ctxget(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - Dictionary ctx_dict = ctx_to_dict(ctx); + Arena arena = ARENA_EMPTY; + Dictionary ctx_dict = ctx_to_dict(ctx, &arena); Error err = ERROR_INIT; object_to_vim(DICTIONARY_OBJ(ctx_dict), rettv, &err); - api_free_dictionary(ctx_dict); + arena_mem_free(arena_finish(&arena)); api_clear_error(&err); } @@ -1108,7 +1107,8 @@ static void f_ctxset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) const int save_did_emsg = did_emsg; did_emsg = false; - Dictionary dict = vim_to_object(&argvars[0]).data.dictionary; + Arena arena = ARENA_EMPTY; + Dictionary dict = vim_to_object(&argvars[0], &arena, true).data.dictionary; Context tmp = CONTEXT_INIT; Error err = ERROR_INIT; ctx_from_dict(dict, &tmp, &err); @@ -1121,7 +1121,7 @@ static void f_ctxset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) *ctx = tmp; } - api_free_dictionary(dict); + arena_mem_free(arena_finish(&arena)); api_clear_error(&err); did_emsg = save_did_emsg; } @@ -6883,16 +6883,17 @@ static void f_rpcnotify(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - Array args = ARRAY_DICT_INIT; + MAXSIZE_TEMP_ARRAY(args, MAX_FUNC_ARGS); + Arena arena = ARENA_EMPTY; for (typval_T *tv = argvars + 2; tv->v_type != VAR_UNKNOWN; tv++) { - ADD(args, vim_to_object(tv)); + ADD_C(args, vim_to_object(tv, &arena, true)); } bool ok = rpc_send_event((uint64_t)argvars[0].vval.v_number, tv_get_string(&argvars[1]), args); - api_free_array(args); + arena_mem_free(arena_finish(&arena)); if (!ok) { semsg(_(e_invarg2), "Channel doesn't exist"); @@ -6922,10 +6923,11 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - Array args = ARRAY_DICT_INIT; + MAXSIZE_TEMP_ARRAY(args, MAX_FUNC_ARGS); + Arena arena = ARENA_EMPTY; for (typval_T *tv = argvars + 2; tv->v_type != VAR_UNKNOWN; tv++) { - ADD(args, vim_to_object(tv)); + ADD_C(args, vim_to_object(tv, &arena, true)); } sctx_T save_current_sctx; @@ -6961,7 +6963,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) ArenaMem res_mem = NULL; Object result = rpc_send_call(chan_id, method, args, &res_mem, &err); - api_free_array(args); + arena_mem_free(arena_finish(&arena)); if (l_provider_call_nesting) { current_sctx = save_current_sctx; @@ -8868,10 +8870,10 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) Error err = ERROR_INIT; // deprecated: use 'channel' buffer option dict_set_var(curbuf->b_vars, cstr_as_string("terminal_job_id"), - INTEGER_OBJ((Integer)chan->id), false, false, &err); + INTEGER_OBJ((Integer)chan->id), false, false, NULL, &err); api_clear_error(&err); dict_set_var(curbuf->b_vars, cstr_as_string("terminal_job_pid"), - INTEGER_OBJ(pid), false, false, &err); + INTEGER_OBJ(pid), false, false, NULL, &err); api_clear_error(&err); channel_incref(chan); -- cgit From f25fcc68a34c2d51b0715fadc62cb50509de338b Mon Sep 17 00:00:00 2001 From: bfredl Date: Sat, 17 Feb 2024 20:31:21 +0100 Subject: refactor(api): use an arena for mappings --- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/typval.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 28365e16df..f4253df63e 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -374,7 +374,7 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) goto end; } - object_to_vim(result, rettv, &err); + object_to_vim_take_luaref(&result, rettv, true, &err); end: if (!handler.arena_return) { diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index fb9e7ff9a8..9328f53dbd 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1805,10 +1805,10 @@ void callback_copy(Callback *dest, Callback *src) } /// Generate a string description of a callback -char *callback_to_string(Callback *cb) +char *callback_to_string(Callback *cb, Arena *arena) { if (cb->type == kCallbackLua) { - return nlua_funcref_str(cb->data.luaref); + return nlua_funcref_str(cb->data.luaref, arena); } const size_t msglen = 100; -- cgit From b8c34efe3399b0786a0e00012cfa3a05a4aa4654 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 18 Feb 2024 19:11:44 +0800 Subject: fix(eval): skip over v:lua properly (#27517) Problem: Error when parsing v:lua in a ternary expression. Solution: Set rettv->v_type for v:lua even if not evaluating. --- src/nvim/eval/funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 28365e16df..8dbff8a7a6 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1726,7 +1726,7 @@ static void f_exists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) n = false; // Trailing garbage. } } else if (*p == '*') { // Internal or user defined function. - n = strncmp(p, "*v:lua.", 7) == 0 ? nlua_func_exists(p + 7) : function_exists(p + 1, false); + n = strnequal(p, "*v:lua.", 7) ? nlua_func_exists(p + 7) : function_exists(p + 1, false); } else if (*p == ':') { n = cmd_exists(p + 1); } else if (*p == '#') { -- cgit From 3cc54586be7760652e8bad88cae82ce74ef9432e Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 20 Feb 2024 13:44:50 +0100 Subject: refactor(api): make freeing of return-value opt-in instead of opt out As only a few API functions make use of explicit freeing of the return value, make it opt-in instead. The arena is always present under the hood, so `Arena *arena` arg now doesn't mean anything other than getting access to this arena. Also it is in principle possible to return an allocated value while still using the arena as scratch space for other stuff (unlikely, but there no reason to not allow it). --- src/nvim/eval/funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index e5af50c8f8..01e666887a 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -377,7 +377,7 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) object_to_vim_take_luaref(&result, rettv, true, &err); end: - if (!handler.arena_return) { + if (handler.ret_alloc) { api_free_object(result); } arena_mem_free(arena_finish(&arena)); -- cgit From 20e4001eeedc80b1f2857fcaca81f7a211a09b40 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 22 Feb 2024 20:32:52 +0800 Subject: vim-patch:9.1.0120: hard to get visual region using Vim script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: hard to get visual region using Vim script Solution: Add getregion() Vim script function (Shougo Matsushita, Jakub Łuczyński) closes: vim/vim#13998 closes: vim/vim#11579 https://github.com/vim/vim/commit/3f905ab3c4f66562f4a224bf00f49d98a0b0da91 Cherry-pick changes from patch 9.1.0122, with :echom instead of :echow. Co-authored-by: Shougo Matsushita Co-authored-by: Jakub Łuczyński --- src/nvim/eval/funcs.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 01e666887a..b62ed557e4 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -130,6 +130,7 @@ #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/tag.h" +#include "nvim/types_defs.h" #include "nvim/ui.h" #include "nvim/version.h" #include "nvim/vim_defs.h" @@ -2801,6 +2802,149 @@ static void f_getpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) getpos_both(argvars, rettv, false, false); } +/// Convert from block_def to string +static char *block_def2str(struct block_def *bd) +{ + size_t size = (size_t)bd->startspaces + (size_t)bd->endspaces + (size_t)bd->textlen; + char *ret = xmalloc(size + 1); + char *p = ret; + memset(p, ' ', (size_t)bd->startspaces); + p += bd->startspaces; + memmove(p, bd->textstart, (size_t)bd->textlen); + p += bd->textlen; + memset(p, ' ', (size_t)bd->endspaces); + *(p + bd->endspaces) = NUL; + return ret; +} + +/// "getregion()" function +static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + tv_list_alloc_ret(rettv, kListLenMayKnow); + + if (tv_check_for_string_arg(argvars, 0) == FAIL + || tv_check_for_string_arg(argvars, 1) == FAIL + || tv_check_for_string_arg(argvars, 2) == FAIL) { + return; + } + + int fnum = -1; + // NOTE: var2fpos() returns static pointer. + pos_T *fp = var2fpos(&argvars[0], true, &fnum, false); + if (fp == NULL) { + return; + } + pos_T p1 = *fp; + + fp = var2fpos(&argvars[1], true, &fnum, false); + if (fp == NULL) { + return; + } + pos_T p2 = *fp; + + const char *pos1 = tv_get_string(&argvars[0]); + const char *pos2 = tv_get_string(&argvars[1]); + const char *type = tv_get_string(&argvars[2]); + + const bool is_visual + = (pos1[0] == 'v' && pos1[1] == NUL) || (pos2[0] == 'v' && pos2[1] == NUL); + + if (is_visual && !VIsual_active) { + return; + } + + MotionType region_type = kMTUnknown; + if (type[0] == 'v' && type[1] == NUL) { + region_type = kMTCharWise; + } else if (type[0] == 'V' && type[1] == NUL) { + region_type = kMTLineWise; + } else if (type[0] == Ctrl_V && type[1] == NUL) { + region_type = kMTBlockWise; + } else { + return; + } + + const TriState save_virtual = virtual_op; + virtual_op = virtual_active(); + + if (!lt(p1, p2)) { + // swap position + pos_T p = p1; + p1 = p2; + p2 = p; + } + + oparg_T oap; + bool inclusive = true; + + if (region_type == kMTCharWise) { + // handle 'selection' == "exclusive" + if (*p_sel == 'e' && !equalpos(p1, p2)) { + if (p2.coladd > 0) { + p2.coladd--; + } else if (p2.col > 0) { + p2.col--; + mark_mb_adjustpos(curbuf, &p2); + } else if (p2.lnum > 1) { + p2.lnum--; + p2.col = (colnr_T)strlen(ml_get(p2.lnum)); + if (p2.col > 0) { + p2.col--; + mark_mb_adjustpos(curbuf, &p2); + } + } + } + // if fp2 is on NUL (empty line) inclusive becomes false + if (*ml_get_pos(&p2) == NUL && !virtual_op) { + inclusive = false; + } + } else if (region_type == kMTBlockWise) { + colnr_T sc1, ec1, sc2, ec2; + getvvcol(curwin, &p1, &sc1, NULL, &ec1); + getvvcol(curwin, &p2, &sc2, NULL, &ec2); + oap.motion_type = kMTBlockWise; + oap.inclusive = true; + oap.op_type = OP_NOP; + oap.start = p1; + oap.end = p2; + oap.start_vcol = MIN(sc1, sc2); + if (*p_sel == 'e' && ec1 < sc2 && 0 < sc2 && ec2 > ec1) { + oap.end_vcol = sc2 - 1; + } else { + oap.end_vcol = MAX(ec1, ec2); + } + } + + // Include the trailing byte of a multi-byte char. + int l = utfc_ptr2len(ml_get_pos(&p2)); + if (l > 1) { + p2.col += l - 1; + } + + for (linenr_T lnum = p1.lnum; lnum <= p2.lnum; lnum++) { + char *akt = NULL; + + if (region_type == kMTLineWise) { + akt = xstrdup(ml_get(lnum)); + } else if (region_type == kMTBlockWise) { + struct block_def bd; + block_prep(&oap, &bd, lnum, false); + akt = block_def2str(&bd); + } else if (p1.lnum < lnum && lnum < p2.lnum) { + akt = xstrdup(ml_get(lnum)); + } else { + struct block_def bd; + charwise_block_prep(p1, p2, &bd, lnum, inclusive); + akt = block_def2str(&bd); + } + + assert(akt != NULL); + tv_list_append_allocated_string(rettv->vval.v_list, akt); + } + + virtual_op = save_virtual; +} + /// Common between getreg(), getreginfo() and getregtype(): get the register /// name from the first argument. /// Returns zero on error. -- cgit From 06df895e71720b65f98b6b9c579ca5918a12bc04 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 23 Feb 2024 06:35:40 +0800 Subject: vim-patch:9.1.0126: Internal error when using upper-case mark in getregion() Problem: Internal error when passing mark in another buffer to getregion(). Solution: Don't allow marks in another buffer (zeertzjq) closes: vim/vim#14076 Internal error when passing mark in another buffer to getregion() https://github.com/vim/vim/commit/421b597470c118871c7081de00dd065e0e000b7e --- src/nvim/eval/funcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index b62ed557e4..b679b64bf6 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2831,13 +2831,13 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) int fnum = -1; // NOTE: var2fpos() returns static pointer. pos_T *fp = var2fpos(&argvars[0], true, &fnum, false); - if (fp == NULL) { + if (fp == NULL || (fnum >= 0 && fnum != curbuf->b_fnum)) { return; } pos_T p1 = *fp; fp = var2fpos(&argvars[1], true, &fnum, false); - if (fp == NULL) { + if (fp == NULL || (fnum >= 0 && fnum != curbuf->b_fnum)) { return; } pos_T p2 = *fp; -- cgit From 1f75184b5cd4db7c250b1eb4d39ea06d3c906e5f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 23 Feb 2024 06:37:19 +0800 Subject: vim-patch:9.1.0127: Naming a non-pointer variable "oap" is strange Problem: Naming a non-pointer variable "oap" is strange. Solution: Rename it to "oa". Also prevent using freed memory in case of memory allocation failure. (zeertzjq) closes: vim/vim#14075 https://github.com/vim/vim/commit/5e3674b42da10b7e7c72d1f20f9a15379af1b60a --- src/nvim/eval/funcs.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index b679b64bf6..2e2640604b 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2874,7 +2874,7 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) p2 = p; } - oparg_T oap; + oparg_T oa; bool inclusive = true; if (region_type == kMTCharWise) { @@ -2902,16 +2902,16 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) colnr_T sc1, ec1, sc2, ec2; getvvcol(curwin, &p1, &sc1, NULL, &ec1); getvvcol(curwin, &p2, &sc2, NULL, &ec2); - oap.motion_type = kMTBlockWise; - oap.inclusive = true; - oap.op_type = OP_NOP; - oap.start = p1; - oap.end = p2; - oap.start_vcol = MIN(sc1, sc2); + oa.motion_type = kMTBlockWise; + oa.inclusive = true; + oa.op_type = OP_NOP; + oa.start = p1; + oa.end = p2; + oa.start_vcol = MIN(sc1, sc2); if (*p_sel == 'e' && ec1 < sc2 && 0 < sc2 && ec2 > ec1) { - oap.end_vcol = sc2 - 1; + oa.end_vcol = sc2 - 1; } else { - oap.end_vcol = MAX(ec1, ec2); + oa.end_vcol = MAX(ec1, ec2); } } @@ -2928,7 +2928,7 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) akt = xstrdup(ml_get(lnum)); } else if (region_type == kMTBlockWise) { struct block_def bd; - block_prep(&oap, &bd, lnum, false); + block_prep(&oa, &bd, lnum, false); akt = block_def2str(&bd); } else if (p1.lnum < lnum && lnum < p2.lnum) { akt = xstrdup(ml_get(lnum)); -- cgit From de5cf09cf98e20d8d3296ad6933ff2741acf83f7 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 26 Feb 2024 18:00:46 +0100 Subject: refactor(metadata): generate all metadata in lua Then we can just load metadata in C as a single msgpack blob. Which also can be used directly as binarly data, instead of first unpacking all the functions and ui_events metadata to immediately pack it again, which was a bit of a silly walk (and one extra usecase of `msgpack_rpc_from_object` which will get yak shaved in the next PR) --- src/nvim/eval/funcs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 2e2640604b..c16fc1d708 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -442,8 +442,7 @@ static void f_and(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "api_info()" function static void f_api_info(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - Dictionary metadata = api_metadata(); - object_to_vim(DICTIONARY_OBJ(metadata), rettv, NULL); + object_to_vim(api_metadata(), rettv, NULL); } /// "atan2()" function -- cgit From ce7c51a1a3b2b38cdba730aeb53840d0ace32173 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 29 Feb 2024 07:19:26 +0800 Subject: vim-patch:9.1.0142: getregion() can be improved (#27662) Problem: getregion() can be improved (after v9.1.120) Solution: change getregion() implementation to use pos as lists and one optional {opt} dictionary (Shougo Matsushita) Note: The following is a breaking change! Currently, the getregion() function (included as of patch v9.1.120) takes 3 arguments: the first 2 arguments are strings, describing a position, arg3 is the type string. However, that is slightly inflexible, there is no way to specify additional arguments. So let's instead change the function signature to: getregion(pos1, pos2 [, {Dict}]) where both pos1 and pos2 are lists. This is slightly cleaner, and gives us the flexibility to specify additional arguments as key/value pairs to the optional Dict arg. Now it supports the "type" key to specify the selection type (characterwise, blockwise or linewise) and now in addition one can also define the selection type, independently of what the 'selection' option actually is. Technically, this is a breaking change, but since the getregion() Vimscript function is still quite new, this should be fine. closes: vim/vim#14090 https://github.com/vim/vim/commit/19b718828d8d5fab52d94c6cdba694641879ab38 Co-authored-by: Shougo Matsushita --- src/nvim/eval/funcs.c | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index c16fc1d708..3b387e3fd6 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2821,35 +2821,38 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { tv_list_alloc_ret(rettv, kListLenMayKnow); - if (tv_check_for_string_arg(argvars, 0) == FAIL - || tv_check_for_string_arg(argvars, 1) == FAIL - || tv_check_for_string_arg(argvars, 2) == FAIL) { + if (tv_check_for_list_arg(argvars, 0) == FAIL + || tv_check_for_list_arg(argvars, 1) == FAIL + || tv_check_for_opt_dict_arg(argvars, 2) == FAIL) { return; } int fnum = -1; - // NOTE: var2fpos() returns static pointer. - pos_T *fp = var2fpos(&argvars[0], true, &fnum, false); - if (fp == NULL || (fnum >= 0 && fnum != curbuf->b_fnum)) { + pos_T p1; + if (list2fpos(&argvars[0], &p1, &fnum, NULL, false) != OK + || (fnum >= 0 && fnum != curbuf->b_fnum)) { return; } - pos_T p1 = *fp; - fp = var2fpos(&argvars[1], true, &fnum, false); - if (fp == NULL || (fnum >= 0 && fnum != curbuf->b_fnum)) { + pos_T p2; + if (list2fpos(&argvars[1], &p2, &fnum, NULL, false) != OK + || (fnum >= 0 && fnum != curbuf->b_fnum)) { return; } - pos_T p2 = *fp; - - const char *pos1 = tv_get_string(&argvars[0]); - const char *pos2 = tv_get_string(&argvars[1]); - const char *type = tv_get_string(&argvars[2]); - - const bool is_visual - = (pos1[0] == 'v' && pos1[1] == NUL) || (pos2[0] == 'v' && pos2[1] == NUL); - if (is_visual && !VIsual_active) { - return; + bool is_select_exclusive; + char *type; + char default_type[] = "v"; + if (argvars[2].v_type == VAR_DICT) { + is_select_exclusive = tv_dict_get_bool(argvars[2].vval.v_dict, "exclusive", + *p_sel == 'e'); + type = tv_dict_get_string(argvars[2].vval.v_dict, "type", false); + if (type == NULL) { + type = default_type; + } + } else { + is_select_exclusive = *p_sel == 'e'; + type = default_type; } MotionType region_type = kMTUnknown; @@ -2866,6 +2869,10 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) const TriState save_virtual = virtual_op; virtual_op = virtual_active(); + // NOTE: Adjust is needed. + p1.col--; + p2.col--; + if (!lt(p1, p2)) { // swap position pos_T p = p1; @@ -2878,7 +2885,7 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (region_type == kMTCharWise) { // handle 'selection' == "exclusive" - if (*p_sel == 'e' && !equalpos(p1, p2)) { + if (is_select_exclusive && !equalpos(p1, p2)) { if (p2.coladd > 0) { p2.coladd--; } else if (p2.col > 0) { @@ -2907,7 +2914,7 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) oa.start = p1; oa.end = p2; oa.start_vcol = MIN(sc1, sc2); - if (*p_sel == 'e' && ec1 < sc2 && 0 < sc2 && ec2 > ec1) { + if (is_select_exclusive && ec1 < sc2 && 0 < sc2 && ec2 > ec1) { oa.end_vcol = sc2 - 1; } else { oa.end_vcol = MAX(ec1, ec2); -- cgit From bf0c69e50410a77d3a7b1a0760f2e574e85d028a Mon Sep 17 00:00:00 2001 From: Sean Dewar <6256228+seandewar@users.noreply.github.com> Date: Sun, 3 Mar 2024 22:33:28 +0000 Subject: fix(eval): correct failure return value for readfile/blob (#27722) Currently returns 0 on failure, but should return an empty list (or blob). Regressed in the big blob port of '21 (#15211). --- src/nvim/eval/funcs.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 3b387e3fd6..fa57d41032 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -6005,6 +6005,12 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl } } + if (blob) { + tv_blob_alloc_ret(rettv); + } else { + tv_list_alloc_ret(rettv, kListLenUnknown); + } + // Always open the file in binary mode, library functions have a mind of // their own about CR-LF conversion. const char *const fname = tv_get_string(&argvars[0]); @@ -6019,7 +6025,6 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl } if (blob) { - tv_blob_alloc_ret(rettv); if (read_blob(fd, rettv, offset, size) == FAIL) { semsg(_(e_notread), fname); } @@ -6027,7 +6032,7 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl return; } - list_T *const l = tv_list_alloc_ret(rettv, kListLenUnknown); + list_T *const l = rettv->vval.v_list; while (maxline < 0 || tv_list_len(l) < maxline) { int readlen = (int)fread(buf, 1, (size_t)io_size, fd); -- cgit From 5b312cd5f67646005312d2ebb2ef0d1bc584dcff Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 5 Mar 2024 15:54:41 +0800 Subject: fix(eval): make has('pythonx') work properly (#27739) Problem: has('pythonx') always returns 1. Solution: Make it the same as has('python3'). --- src/nvim/eval/funcs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index fa57d41032..605170610c 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3315,7 +3315,6 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) "path_extra", "persistent_undo", "profile", - "pythonx", "reltime", "quickfix", "rightleft", @@ -3406,6 +3405,8 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) n = syntax_present(curwin); } else if (STRICMP(name, "clipboard_working") == 0) { n = eval_has_provider("clipboard"); + } else if (STRICMP(name, "pythonx") == 0) { + n = eval_has_provider("python3"); } else if (STRICMP(name, "wsl") == 0) { n = has_wsl(); #ifdef UNIX -- cgit From 6525832a8c4d44a8ebabba02a5ea1ce09b389a4f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 7 Mar 2024 06:43:08 +0800 Subject: vim-patch:9.1.0155: can only get getregion() from current buffer (#27757) Problem: can only call getregion() for current buffer Solution: Allow to retrieve selections from different buffers (Shougo Matsushita) closes: vim/vim#14131 https://github.com/vim/vim/commit/84bf6e658da51126bdd2e50af1f40cabd149343f Co-authored-by: Shougo Matsushita --- src/nvim/eval/funcs.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 605170610c..67443b66bc 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2827,16 +2827,12 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - int fnum = -1; - pos_T p1; - if (list2fpos(&argvars[0], &p1, &fnum, NULL, false) != OK - || (fnum >= 0 && fnum != curbuf->b_fnum)) { - return; - } - - pos_T p2; - if (list2fpos(&argvars[1], &p2, &fnum, NULL, false) != OK - || (fnum >= 0 && fnum != curbuf->b_fnum)) { + int fnum1 = -1; + int fnum2 = -1; + pos_T p1, p2; + if (list2fpos(&argvars[0], &p1, &fnum1, NULL, false) != OK + || list2fpos(&argvars[1], &p2, &fnum2, NULL, false) != OK + || fnum1 != fnum2) { return; } @@ -2866,6 +2862,18 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } + buf_T *save_curbuf = curbuf; + + if (fnum1 != 0) { + buf_T *findbuf = buflist_findnr(fnum1); + // buffer not loaded + if (findbuf == NULL || findbuf->b_ml.ml_mfp == NULL) { + return; + } + save_curbuf = curbuf; + curbuf = findbuf; + } + const TriState save_virtual = virtual_op; virtual_op = virtual_active(); @@ -2948,6 +2956,10 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) tv_list_append_allocated_string(rettv->vval.v_list, akt); } + if (curbuf != save_curbuf) { + curbuf = save_curbuf; + } + virtual_op = save_virtual; } -- cgit From 5f3579e6ea12659d48e92b2126f83777908c28fc Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 8 Mar 2024 06:44:57 +0800 Subject: vim-patch:9.1.0157: Duplicate assignment in f_getregion() (#27766) Problem: Duplicate assignment in f_getregion(). Solution: Remove the duplicate assignment. Also improve getregion() docs wording and fix an unrelated typo (zeertzjq) closes: vim/vim#14154 https://github.com/vim/vim/commit/0df8f93bdaea77a1afb9f4eca94fe67ec73e6df2 --- src/nvim/eval/funcs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 67443b66bc..2f9472f158 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2862,7 +2862,7 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - buf_T *save_curbuf = curbuf; + buf_T *const save_curbuf = curbuf; if (fnum1 != 0) { buf_T *findbuf = buflist_findnr(fnum1); @@ -2870,7 +2870,6 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (findbuf == NULL || findbuf->b_ml.ml_mfp == NULL) { return; } - save_curbuf = curbuf; curbuf = findbuf; } -- cgit