mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 8.2.2449: Vim9: flatten() always changes the list type
Problem: Vim9: flatten() always changes the list type. Solution: Disallow using flatten() and add flattennew().
This commit is contained in:
@@ -2549,6 +2549,8 @@ finddir({name} [, {path} [, {count}]])
|
|||||||
findfile({name} [, {path} [, {count}]])
|
findfile({name} [, {path} [, {count}]])
|
||||||
String find file {name} in {path}
|
String find file {name} in {path}
|
||||||
flatten({list} [, {maxdepth}]) List flatten {list} up to {maxdepth} levels
|
flatten({list} [, {maxdepth}]) List flatten {list} up to {maxdepth} levels
|
||||||
|
flattennew({list} [, {maxdepth}])
|
||||||
|
List flatten a copy of {list}
|
||||||
float2nr({expr}) Number convert Float {expr} to a Number
|
float2nr({expr}) Number convert Float {expr} to a Number
|
||||||
floor({expr}) Float round {expr} down
|
floor({expr}) Float round {expr} down
|
||||||
fmod({expr1}, {expr2}) Float remainder of {expr1} / {expr2}
|
fmod({expr1}, {expr2}) Float remainder of {expr1} / {expr2}
|
||||||
@@ -4712,8 +4714,10 @@ flatten({list} [, {maxdepth}]) *flatten()*
|
|||||||
Flatten {list} up to {maxdepth} levels. Without {maxdepth}
|
Flatten {list} up to {maxdepth} levels. Without {maxdepth}
|
||||||
the result is a |List| without nesting, as if {maxdepth} is
|
the result is a |List| without nesting, as if {maxdepth} is
|
||||||
a very large number.
|
a very large number.
|
||||||
The {list} is changed in place, make a copy first if you do
|
The {list} is changed in place, use |flattennew()| if you do
|
||||||
not want that.
|
not want that.
|
||||||
|
In Vim9 script flatten() cannot be used, you must always use
|
||||||
|
|flattennew()|.
|
||||||
*E900*
|
*E900*
|
||||||
{maxdepth} means how deep in nested lists changes are made.
|
{maxdepth} means how deep in nested lists changes are made.
|
||||||
{list} is not modified when {maxdepth} is 0.
|
{list} is not modified when {maxdepth} is 0.
|
||||||
@@ -4727,6 +4731,10 @@ flatten({list} [, {maxdepth}]) *flatten()*
|
|||||||
:echo flatten([1, [2, [3, 4]], 5], 1)
|
:echo flatten([1, [2, [3, 4]], 5], 1)
|
||||||
< [1, 2, [3, 4], 5]
|
< [1, 2, [3, 4], 5]
|
||||||
|
|
||||||
|
flattennew({list} [, {maxdepth}]) *flattennew()*
|
||||||
|
Like |flatten()| but first make a copy of {list}.
|
||||||
|
|
||||||
|
|
||||||
float2nr({expr}) *float2nr()*
|
float2nr({expr}) *float2nr()*
|
||||||
Convert {expr} to a Number by omitting the part after the
|
Convert {expr} to a Number by omitting the part after the
|
||||||
decimal point.
|
decimal point.
|
||||||
|
@@ -665,6 +665,7 @@ List manipulation: *list-functions*
|
|||||||
count() count number of times a value appears in a List
|
count() count number of times a value appears in a List
|
||||||
repeat() repeat a List multiple times
|
repeat() repeat a List multiple times
|
||||||
flatten() flatten a List
|
flatten() flatten a List
|
||||||
|
flattennew() flatten a copy of a List
|
||||||
|
|
||||||
Dictionary manipulation: *dict-functions*
|
Dictionary manipulation: *dict-functions*
|
||||||
get() get an entry without an error for a wrong key
|
get() get an entry without an error for a wrong key
|
||||||
|
@@ -351,3 +351,5 @@ EXTERN char e_cannot_change_arglist_recursively[]
|
|||||||
INIT(= N_("E1156: Cannot change the argument list recursively"));
|
INIT(= N_("E1156: Cannot change the argument list recursively"));
|
||||||
EXTERN char e_missing_return_type[]
|
EXTERN char e_missing_return_type[]
|
||||||
INIT(= N_("E1157: Missing return type"));
|
INIT(= N_("E1157: Missing return type"));
|
||||||
|
EXTERN char e_cannot_use_flatten_in_vim9_script[]
|
||||||
|
INIT(= N_("E1158: Cannot use flatten() in Vim9 script"));
|
||||||
|
@@ -954,6 +954,8 @@ static funcentry_T global_functions[] =
|
|||||||
ret_string, f_findfile},
|
ret_string, f_findfile},
|
||||||
{"flatten", 1, 2, FEARG_1, NULL,
|
{"flatten", 1, 2, FEARG_1, NULL,
|
||||||
ret_list_any, f_flatten},
|
ret_list_any, f_flatten},
|
||||||
|
{"flattennew", 1, 2, FEARG_1, NULL,
|
||||||
|
ret_list_any, f_flattennew},
|
||||||
{"float2nr", 1, 1, FEARG_1, NULL,
|
{"float2nr", 1, 1, FEARG_1, NULL,
|
||||||
ret_number, FLOAT_FUNC(f_float2nr)},
|
ret_number, FLOAT_FUNC(f_float2nr)},
|
||||||
{"floor", 1, 1, FEARG_1, NULL,
|
{"floor", 1, 1, FEARG_1, NULL,
|
||||||
|
62
src/list.c
62
src/list.c
@@ -740,7 +740,7 @@ list_insert(list_T *l, listitem_T *ni, listitem_T *item)
|
|||||||
* It does nothing if "maxdepth" is 0.
|
* It does nothing if "maxdepth" is 0.
|
||||||
* Returns FAIL when out of memory.
|
* Returns FAIL when out of memory.
|
||||||
*/
|
*/
|
||||||
static int
|
static void
|
||||||
list_flatten(list_T *list, long maxdepth)
|
list_flatten(list_T *list, long maxdepth)
|
||||||
{
|
{
|
||||||
listitem_T *item;
|
listitem_T *item;
|
||||||
@@ -748,7 +748,7 @@ list_flatten(list_T *list, long maxdepth)
|
|||||||
int n;
|
int n;
|
||||||
|
|
||||||
if (maxdepth == 0)
|
if (maxdepth == 0)
|
||||||
return OK;
|
return;
|
||||||
CHECK_LIST_MATERIALIZE(list);
|
CHECK_LIST_MATERIALIZE(list);
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
@@ -757,7 +757,7 @@ list_flatten(list_T *list, long maxdepth)
|
|||||||
{
|
{
|
||||||
fast_breakcheck();
|
fast_breakcheck();
|
||||||
if (got_int)
|
if (got_int)
|
||||||
return FAIL;
|
return;
|
||||||
|
|
||||||
if (item->li_tv.v_type == VAR_LIST)
|
if (item->li_tv.v_type == VAR_LIST)
|
||||||
{
|
{
|
||||||
@@ -765,7 +765,7 @@ list_flatten(list_T *list, long maxdepth)
|
|||||||
|
|
||||||
vimlist_remove(list, item, item);
|
vimlist_remove(list, item, item);
|
||||||
if (list_extend(list, item->li_tv.vval.v_list, next) == FAIL)
|
if (list_extend(list, item->li_tv.vval.v_list, next) == FAIL)
|
||||||
return FAIL;
|
return;
|
||||||
clear_tv(&item->li_tv);
|
clear_tv(&item->li_tv);
|
||||||
tofree = item;
|
tofree = item;
|
||||||
|
|
||||||
@@ -787,15 +787,13 @@ list_flatten(list_T *list, long maxdepth)
|
|||||||
item = item->li_next;
|
item = item->li_next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "flatten(list[, {maxdepth}])" function
|
* "flatten()" and "flattennew()" functions
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
f_flatten(typval_T *argvars, typval_T *rettv)
|
flatten_common(typval_T *argvars, typval_T *rettv, int make_copy)
|
||||||
{
|
{
|
||||||
list_T *l;
|
list_T *l;
|
||||||
long maxdepth;
|
long maxdepth;
|
||||||
@@ -822,10 +820,48 @@ f_flatten(typval_T *argvars, typval_T *rettv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
l = argvars[0].vval.v_list;
|
l = argvars[0].vval.v_list;
|
||||||
if (l != NULL && !value_check_lock(l->lv_lock,
|
rettv->v_type = VAR_LIST;
|
||||||
(char_u *)N_("flatten() argument"), TRUE)
|
rettv->vval.v_list = l;
|
||||||
&& list_flatten(l, maxdepth) == OK)
|
if (l == NULL)
|
||||||
copy_tv(&argvars[0], rettv);
|
return;
|
||||||
|
|
||||||
|
if (make_copy)
|
||||||
|
{
|
||||||
|
l = list_copy(l, TRUE, get_copyID());
|
||||||
|
rettv->vval.v_list = l;
|
||||||
|
if (l == NULL)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (value_check_lock(l->lv_lock,
|
||||||
|
(char_u *)N_("flatten() argument"), TRUE))
|
||||||
|
return;
|
||||||
|
++l->lv_refcount;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_flatten(l, maxdepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "flatten(list[, {maxdepth}])" function
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
f_flatten(typval_T *argvars, typval_T *rettv)
|
||||||
|
{
|
||||||
|
if (in_vim9script())
|
||||||
|
emsg(_(e_cannot_use_flatten_in_vim9_script));
|
||||||
|
else
|
||||||
|
flatten_common(argvars, rettv, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "flattennew(list[, {maxdepth}])" function
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
f_flattennew(typval_T *argvars, typval_T *rettv)
|
||||||
|
{
|
||||||
|
flatten_common(argvars, rettv, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -31,6 +31,7 @@ int list_append_number(list_T *l, varnumber_T n);
|
|||||||
int list_insert_tv(list_T *l, typval_T *tv, listitem_T *item);
|
int list_insert_tv(list_T *l, typval_T *tv, listitem_T *item);
|
||||||
void list_insert(list_T *l, listitem_T *ni, listitem_T *item);
|
void list_insert(list_T *l, listitem_T *ni, listitem_T *item);
|
||||||
void f_flatten(typval_T *argvars, typval_T *rettv);
|
void f_flatten(typval_T *argvars, typval_T *rettv);
|
||||||
|
void f_flattennew(typval_T *argvars, typval_T *rettv);
|
||||||
int list_extend(list_T *l1, list_T *l2, listitem_T *bef);
|
int list_extend(list_T *l1, list_T *l2, listitem_T *bef);
|
||||||
int list_concat(list_T *l1, list_T *l2, typval_T *tv);
|
int list_concat(list_T *l1, list_T *l2, typval_T *tv);
|
||||||
list_T *list_slice(list_T *ol, long n1, long n2);
|
list_T *list_slice(list_T *ol, long n1, long n2);
|
||||||
|
@@ -81,4 +81,13 @@ func Test_flatten()
|
|||||||
call assert_equal([2, l:x], l:y)
|
call assert_equal([2, l:x], l:y)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_flattennew()
|
||||||
|
let l = [1, [2, [3, 4]], 5]
|
||||||
|
call assert_equal([1, 2, 3, 4, 5], flattennew(l))
|
||||||
|
call assert_equal([1, [2, [3, 4]], 5], l)
|
||||||
|
|
||||||
|
call assert_equal([1, 2, [3, 4], 5], flattennew(l, 1))
|
||||||
|
call assert_equal([1, [2, [3, 4]], 5], l)
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@@ -382,6 +382,23 @@ def Test_findfile()
|
|||||||
CheckDefExecFailure(['echo findfile("")'], 'E1142:')
|
CheckDefExecFailure(['echo findfile("")'], 'E1142:')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_flattennew()
|
||||||
|
var lines =<< trim END
|
||||||
|
var l = [1, [2, [3, 4]], 5]
|
||||||
|
call assert_equal([1, 2, 3, 4, 5], flattennew(l))
|
||||||
|
call assert_equal([1, [2, [3, 4]], 5], l)
|
||||||
|
|
||||||
|
call assert_equal([1, 2, [3, 4], 5], flattennew(l, 1))
|
||||||
|
call assert_equal([1, [2, [3, 4]], 5], l)
|
||||||
|
END
|
||||||
|
CheckDefAndScriptSuccess(lines)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
echo flatten([1, 2, 3])
|
||||||
|
END
|
||||||
|
CheckDefAndScriptFailure(lines, 'E1158:')
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_fnamemodify()
|
def Test_fnamemodify()
|
||||||
CheckDefSuccess(['echo fnamemodify(test_null_string(), ":p")'])
|
CheckDefSuccess(['echo fnamemodify(test_null_string(), ":p")'])
|
||||||
CheckDefSuccess(['echo fnamemodify("", ":p")'])
|
CheckDefSuccess(['echo fnamemodify("", ":p")'])
|
||||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2449,
|
||||||
/**/
|
/**/
|
||||||
2448,
|
2448,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -2900,6 +2900,12 @@ compile_call(
|
|||||||
idx = find_internal_func(name);
|
idx = find_internal_func(name);
|
||||||
if (idx >= 0)
|
if (idx >= 0)
|
||||||
{
|
{
|
||||||
|
if (STRCMP(name, "flatten") == 0)
|
||||||
|
{
|
||||||
|
emsg(_(e_cannot_use_flatten_in_vim9_script));
|
||||||
|
goto theend;
|
||||||
|
}
|
||||||
|
|
||||||
if (STRCMP(name, "add") == 0 && argcount == 2)
|
if (STRCMP(name, "add") == 0 && argcount == 2)
|
||||||
{
|
{
|
||||||
garray_T *stack = &cctx->ctx_type_stack;
|
garray_T *stack = &cctx->ctx_type_stack;
|
||||||
|
Reference in New Issue
Block a user