summaryrefslogtreecommitdiffstats
path: root/src/evalfunc.c
diff options
context:
space:
mode:
authorErnie Rael <errael@raelity.com>2024-01-13 11:47:33 +0100
committerChristian Brabandt <cb@256bit.org>2024-01-13 11:47:33 +0100
commite79e2077607e8f829ba823308c91104a795736ba (patch)
treee3e126ee9503e37e90e83868aa1c0ac42e359ccb /src/evalfunc.c
parentd8cb1ddab7b8cb19267a8877d62bbe3a06626fa2 (diff)
patch 9.1.0027: Vim is missing a foreach() funcv9.1.0027
Problem: Vim is missing a foreach() func Solution: Implement foreach({expr1}, {expr2}) function, which applies {expr2} for each item in {expr1} without changing it (Ernie Rael) closes: #12166 Signed-off-by: Ernie Rael <errael@raelity.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
Diffstat (limited to 'src/evalfunc.c')
-rw-r--r--src/evalfunc.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c
index e37b3a412a..9b3bdf756d 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -607,10 +607,11 @@ arg_list_or_dict_or_blob_or_string_mod(
}
/*
- * Check second argument of map() or filter().
+ * Check second argument of map(), filter(), foreach().
*/
static int
-check_map_filter_arg2(type_T *type, argcontext_T *context, int is_map)
+check_map_filter_arg2(type_T *type, argcontext_T *context,
+ filtermap_T filtermap)
{
type_T *expected_member = NULL;
type_T *(args[2]);
@@ -663,12 +664,14 @@ check_map_filter_arg2(type_T *type, argcontext_T *context, int is_map)
{
where_T where = WHERE_INIT;
- if (is_map)
+ if (filtermap == FILTERMAP_MAP)
t_func_exp.tt_member = expected_member == NULL
|| type_any_or_unknown(type->tt_member)
? &t_any : expected_member;
- else
+ else if (filtermap == FILTERMAP_FILTER)
t_func_exp.tt_member = &t_bool;
+ else // filtermap == FILTERMAP_FOREACH
+ t_func_exp.tt_member = &t_unknown;
if (args[0] == NULL)
args[0] = &t_unknown;
if (type->tt_argcount == -1)
@@ -693,7 +696,7 @@ arg_filter_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
return OK;
if (type->tt_type == VAR_FUNC)
- return check_map_filter_arg2(type, context, FALSE);
+ return check_map_filter_arg2(type, context, FILTERMAP_FILTER);
semsg(_(e_string_or_function_required_for_argument_nr), 2);
return FAIL;
}
@@ -710,7 +713,24 @@ arg_map_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
return OK;
if (type->tt_type == VAR_FUNC)
- return check_map_filter_arg2(type, context, TRUE);
+ return check_map_filter_arg2(type, context, FILTERMAP_MAP);
+ semsg(_(e_string_or_function_required_for_argument_nr), 2);
+ return FAIL;
+}
+
+/*
+ * Check second argument of foreach(), the function.
+ */
+ static int
+arg_foreach_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
+{
+ if (type->tt_type == VAR_STRING
+ || type->tt_type == VAR_PARTIAL
+ || type_any_or_unknown(type))
+ return OK;
+
+ if (type->tt_type == VAR_FUNC)
+ return check_map_filter_arg2(type, context, FILTERMAP_FOREACH);
semsg(_(e_string_or_function_required_for_argument_nr), 2);
return FAIL;
}
@@ -1173,6 +1193,7 @@ static argcheck_T arg1_len[] = {arg_len1};
static argcheck_T arg3_libcall[] = {arg_string, arg_string, arg_string_or_nr};
static argcheck_T arg14_maparg[] = {arg_string, arg_string, arg_bool, arg_bool};
static argcheck_T arg2_filter[] = {arg_list_or_dict_or_blob_or_string_mod, arg_filter_func};
+static argcheck_T arg2_foreach[] = {arg_list_or_dict_or_blob_or_string, arg_foreach_func};
static argcheck_T arg2_instanceof[] = {arg_object, varargs_class, NULL };
static argcheck_T arg2_map[] = {arg_list_or_dict_or_blob_or_string_mod, arg_map_func};
static argcheck_T arg2_mapnew[] = {arg_list_or_dict_or_blob_or_string, arg_any};
@@ -2013,6 +2034,8 @@ static funcentry_T global_functions[] =
ret_string, f_foldtext},
{"foldtextresult", 1, 1, FEARG_1, arg1_lnum,
ret_string, f_foldtextresult},
+ {"foreach", 2, 2, FEARG_1, arg2_foreach,
+ ret_first_arg, f_foreach},
{"foreground", 0, 0, 0, NULL,
ret_void, f_foreground},
{"fullcommand", 1, 2, FEARG_1, arg2_string_bool,