forked from aniani/vim
patch 7.4.2090
Problem: Using submatch() in a lambda passed to substitute() is verbose. Solution: Use a static list and pass it as an optional argument to the function. Fix memory leak.
This commit is contained in:
parent
36edf0685c
commit
df48fb456f
@ -1,4 +1,4 @@
|
|||||||
*eval.txt* For Vim version 7.4. Last change: 2016 Jul 16
|
*eval.txt* For Vim version 7.4. Last change: 2016 Jul 22
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@ -1535,7 +1535,7 @@ v:false A Number with value zero. Used to put "false" in JSON. See
|
|||||||
echo v:false
|
echo v:false
|
||||||
< v:false ~
|
< v:false ~
|
||||||
That is so that eval() can parse the string back to the same
|
That is so that eval() can parse the string back to the same
|
||||||
value.
|
value. Read-only.
|
||||||
|
|
||||||
*v:fcs_reason* *fcs_reason-variable*
|
*v:fcs_reason* *fcs_reason-variable*
|
||||||
v:fcs_reason The reason why the |FileChangedShell| event was triggered.
|
v:fcs_reason The reason why the |FileChangedShell| event was triggered.
|
||||||
@ -1682,7 +1682,7 @@ v:none An empty String. Used to put an empty item in JSON. See
|
|||||||
echo v:none
|
echo v:none
|
||||||
< v:none ~
|
< v:none ~
|
||||||
That is so that eval() can parse the string back to the same
|
That is so that eval() can parse the string back to the same
|
||||||
value.
|
value. Read-only.
|
||||||
|
|
||||||
*v:null* *null-variable*
|
*v:null* *null-variable*
|
||||||
v:null An empty String. Used to put "null" in JSON. See
|
v:null An empty String. Used to put "null" in JSON. See
|
||||||
@ -1692,7 +1692,7 @@ v:null An empty String. Used to put "null" in JSON. See
|
|||||||
echo v:null
|
echo v:null
|
||||||
< v:null ~
|
< v:null ~
|
||||||
That is so that eval() can parse the string back to the same
|
That is so that eval() can parse the string back to the same
|
||||||
value.
|
value. Read-only.
|
||||||
|
|
||||||
*v:oldfiles* *oldfiles-variable*
|
*v:oldfiles* *oldfiles-variable*
|
||||||
v:oldfiles List of file names that is loaded from the |viminfo| file on
|
v:oldfiles List of file names that is loaded from the |viminfo| file on
|
||||||
@ -1890,7 +1890,7 @@ v:true A Number with value one. Used to put "true" in JSON. See
|
|||||||
echo v:true
|
echo v:true
|
||||||
< v:true ~
|
< v:true ~
|
||||||
That is so that eval() can parse the string back to the same
|
That is so that eval() can parse the string back to the same
|
||||||
value.
|
value. Read-only.
|
||||||
*v:val* *val-variable*
|
*v:val* *val-variable*
|
||||||
v:val Value of the current item of a |List| or |Dictionary|. Only
|
v:val Value of the current item of a |List| or |Dictionary|. Only
|
||||||
valid while evaluating the expression used with |map()| and
|
valid while evaluating the expression used with |map()| and
|
||||||
@ -7154,6 +7154,14 @@ substitute({expr}, {pat}, {sub}, {flags}) *substitute()*
|
|||||||
:echo substitute(s, '%\(\x\x\)',
|
:echo substitute(s, '%\(\x\x\)',
|
||||||
\ '\=nr2char("0x" . submatch(1))', 'g')
|
\ '\=nr2char("0x" . submatch(1))', 'g')
|
||||||
|
|
||||||
|
< When {sub} is a Funcref that function is called, with one
|
||||||
|
optional argument. Example: >
|
||||||
|
:echo substitute(s, '%\(\x\x\)', SubNr, 'g')
|
||||||
|
< The optional argument is a list which contains the whole
|
||||||
|
matched string and up to nine submatches,like what
|
||||||
|
|submatch()| returns. Example: >
|
||||||
|
:echo substitute(s, '\(\x\x\)', {m -> '0x' . m[1]}, 'g')
|
||||||
|
|
||||||
synID({lnum}, {col}, {trans}) *synID()*
|
synID({lnum}, {col}, {trans}) *synID()*
|
||||||
The result is a Number, which is the syntax ID at the position
|
The result is a Number, which is the syntax ID at the position
|
||||||
{lnum} and {col} in the current window.
|
{lnum} and {col} in the current window.
|
||||||
@ -7546,18 +7554,20 @@ trunc({expr}) *trunc()*
|
|||||||
{only available when compiled with the |+float| feature}
|
{only available when compiled with the |+float| feature}
|
||||||
|
|
||||||
*type()*
|
*type()*
|
||||||
type({expr}) The result is a Number, depending on the type of {expr}:
|
type({expr}) The result is a Number representing the type of {expr}.
|
||||||
Number: 0
|
Instead of using the number directly, it is better to use the
|
||||||
String: 1
|
v:t_ variable that has the value:
|
||||||
Funcref: 2
|
Number: 0 |v:t_number|
|
||||||
List: 3
|
String: 1 |v:t_string|
|
||||||
Dictionary: 4
|
Funcref: 2 |v:t_func|
|
||||||
Float: 5
|
List: 3 |v:t_list|
|
||||||
Boolean: 6 (v:false and v:true)
|
Dictionary: 4 |v:t_dict|
|
||||||
None 7 (v:null and v:none)
|
Float: 5 |v:t_float|
|
||||||
Job 8
|
Boolean: 6 |v:t_bool| (v:false and v:true)
|
||||||
Channel 9
|
None 7 |v:t_none| (v:null and v:none)
|
||||||
To avoid the magic numbers it should be used this way: >
|
Job 8 |v:t_job|
|
||||||
|
Channel 9 |v:t_channel|
|
||||||
|
For backward compatibility, this method can be used: >
|
||||||
:if type(myvar) == type(0)
|
:if type(myvar) == type(0)
|
||||||
:if type(myvar) == type("")
|
:if type(myvar) == type("")
|
||||||
:if type(myvar) == type(function("tr"))
|
:if type(myvar) == type(function("tr"))
|
||||||
@ -7566,6 +7576,8 @@ type({expr}) The result is a Number, depending on the type of {expr}:
|
|||||||
:if type(myvar) == type(0.0)
|
:if type(myvar) == type(0.0)
|
||||||
:if type(myvar) == type(v:false)
|
:if type(myvar) == type(v:false)
|
||||||
:if type(myvar) == type(v:none)
|
:if type(myvar) == type(v:none)
|
||||||
|
< To check if the v:t_ variables exist use this: >
|
||||||
|
:if exists('v:t_number')
|
||||||
|
|
||||||
undofile({name}) *undofile()*
|
undofile({name}) *undofile()*
|
||||||
Return the name of the undo file that would be used for a file
|
Return the name of the undo file that would be used for a file
|
||||||
|
@ -1533,8 +1533,8 @@ invoke_callback(channel_T *channel, char_u *callback, partial_T *partial,
|
|||||||
argv[0].v_type = VAR_CHANNEL;
|
argv[0].v_type = VAR_CHANNEL;
|
||||||
argv[0].vval.v_channel = channel;
|
argv[0].vval.v_channel = channel;
|
||||||
|
|
||||||
call_func(callback, (int)STRLEN(callback),
|
call_func(callback, (int)STRLEN(callback), &rettv, 2, argv, NULL,
|
||||||
&rettv, 2, argv, 0L, 0L, &dummy, TRUE, partial, NULL);
|
0L, 0L, &dummy, TRUE, partial, NULL);
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
channel_need_redraw = TRUE;
|
channel_need_redraw = TRUE;
|
||||||
}
|
}
|
||||||
@ -2695,7 +2695,7 @@ channel_close(channel_T *channel, int invoke_close_cb)
|
|||||||
argv[0].v_type = VAR_CHANNEL;
|
argv[0].v_type = VAR_CHANNEL;
|
||||||
argv[0].vval.v_channel = channel;
|
argv[0].vval.v_channel = channel;
|
||||||
call_func(channel->ch_close_cb, (int)STRLEN(channel->ch_close_cb),
|
call_func(channel->ch_close_cb, (int)STRLEN(channel->ch_close_cb),
|
||||||
&rettv, 1, argv, 0L, 0L, &dummy, TRUE,
|
&rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE,
|
||||||
channel->ch_close_partial, NULL);
|
channel->ch_close_partial, NULL);
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
channel_need_redraw = TRUE;
|
channel_need_redraw = TRUE;
|
||||||
@ -4758,7 +4758,7 @@ job_status(job_T *job)
|
|||||||
argv[1].v_type = VAR_NUMBER;
|
argv[1].v_type = VAR_NUMBER;
|
||||||
argv[1].vval.v_number = job->jv_exitval;
|
argv[1].vval.v_number = job->jv_exitval;
|
||||||
call_func(job->jv_exit_cb, (int)STRLEN(job->jv_exit_cb),
|
call_func(job->jv_exit_cb, (int)STRLEN(job->jv_exit_cb),
|
||||||
&rettv, 2, argv, 0L, 0L, &dummy, TRUE,
|
&rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE,
|
||||||
job->jv_exit_partial, NULL);
|
job->jv_exit_partial, NULL);
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
--job->jv_refcount;
|
--job->jv_refcount;
|
||||||
|
11
src/eval.c
11
src/eval.c
@ -988,7 +988,7 @@ call_vim_function(
|
|||||||
}
|
}
|
||||||
|
|
||||||
rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
|
rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
|
||||||
ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars,
|
ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars, NULL,
|
||||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
||||||
&doesrange, TRUE, NULL, NULL);
|
&doesrange, TRUE, NULL, NULL);
|
||||||
if (safe)
|
if (safe)
|
||||||
@ -9930,8 +9930,8 @@ filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
|
|||||||
if (expr->v_type == VAR_FUNC)
|
if (expr->v_type == VAR_FUNC)
|
||||||
{
|
{
|
||||||
s = expr->vval.v_string;
|
s = expr->vval.v_string;
|
||||||
if (call_func(s, (int)STRLEN(s),
|
if (call_func(s, (int)STRLEN(s), &rettv, 2, argv, NULL,
|
||||||
&rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL, NULL) == FAIL)
|
0L, 0L, &dummy, TRUE, NULL, NULL) == FAIL)
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
else if (expr->v_type == VAR_PARTIAL)
|
else if (expr->v_type == VAR_PARTIAL)
|
||||||
@ -9939,9 +9939,8 @@ filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
|
|||||||
partial_T *partial = expr->vval.v_partial;
|
partial_T *partial = expr->vval.v_partial;
|
||||||
|
|
||||||
s = partial->pt_name;
|
s = partial->pt_name;
|
||||||
if (call_func(s, (int)STRLEN(s),
|
if (call_func(s, (int)STRLEN(s), &rettv, 2, argv, NULL,
|
||||||
&rettv, 2, argv, 0L, 0L, &dummy, TRUE, partial, NULL)
|
0L, 0L, &dummy, TRUE, partial, NULL) == FAIL)
|
||||||
== FAIL)
|
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -10101,7 +10101,7 @@ item_compare2(const void *s1, const void *s2)
|
|||||||
|
|
||||||
rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
|
rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
|
||||||
res = call_func(func_name, (int)STRLEN(func_name),
|
res = call_func(func_name, (int)STRLEN(func_name),
|
||||||
&rettv, 2, argv, 0L, 0L, &dummy, TRUE,
|
&rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE,
|
||||||
partial, sortinfo->item_compare_selfdict);
|
partial, sortinfo->item_compare_selfdict);
|
||||||
clear_tv(&argv[0]);
|
clear_tv(&argv[0]);
|
||||||
clear_tv(&argv[1]);
|
clear_tv(&argv[1]);
|
||||||
|
@ -1163,7 +1163,7 @@ timer_callback(timer_T *timer)
|
|||||||
argv[1].v_type = VAR_UNKNOWN;
|
argv[1].v_type = VAR_UNKNOWN;
|
||||||
|
|
||||||
call_func(timer->tr_callback, (int)STRLEN(timer->tr_callback),
|
call_func(timer->tr_callback, (int)STRLEN(timer->tr_callback),
|
||||||
&rettv, 1, argv, 0L, 0L, &dummy, TRUE,
|
&rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE,
|
||||||
timer->tr_partial, NULL);
|
timer->tr_partial, NULL);
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
}
|
}
|
||||||
|
31
src/list.c
31
src/list.c
@ -924,4 +924,35 @@ write_list(FILE *fd, list_T *list, int binary)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize a static list with 10 items.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
init_static_list(staticList10_T *sl)
|
||||||
|
{
|
||||||
|
list_T *l = &sl->sl_list;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset(sl, 0, sizeof(staticList10_T));
|
||||||
|
l->lv_first = &sl->sl_items[0];
|
||||||
|
l->lv_last = &sl->sl_items[9];
|
||||||
|
l->lv_refcount = DO_NOT_FREE_CNT;
|
||||||
|
l->lv_lock = VAR_FIXED;
|
||||||
|
sl->sl_list.lv_len = 10;
|
||||||
|
|
||||||
|
for (i = 0; i < 10; ++i)
|
||||||
|
{
|
||||||
|
listitem_T *li = &sl->sl_items[i];
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
li->li_prev = NULL;
|
||||||
|
else
|
||||||
|
li->li_prev = li - 1;
|
||||||
|
if (i == 9)
|
||||||
|
li->li_next = NULL;
|
||||||
|
else
|
||||||
|
li->li_next = li + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* defined(FEAT_EVAL) */
|
#endif /* defined(FEAT_EVAL) */
|
||||||
|
@ -32,4 +32,5 @@ char_u *list2string(typval_T *tv, int copyID, int restore_copyID);
|
|||||||
int list_join(garray_T *gap, list_T *l, char_u *sep, int echo_style, int restore_copyID, int copyID);
|
int list_join(garray_T *gap, list_T *l, char_u *sep, int echo_style, int restore_copyID, int copyID);
|
||||||
int get_list_tv(char_u **arg, typval_T *rettv, int evaluate);
|
int get_list_tv(char_u **arg, typval_T *rettv, int evaluate);
|
||||||
int write_list(FILE *fd, list_T *list, int binary);
|
int write_list(FILE *fd, list_T *list, int binary);
|
||||||
|
void init_static_list(staticList10_T *sl);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@ -5,7 +5,7 @@ char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int no_au
|
|||||||
int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, partial_T *partial, dict_T *selfdict);
|
int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, partial_T *partial, dict_T *selfdict);
|
||||||
void free_all_functions(void);
|
void free_all_functions(void);
|
||||||
int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv);
|
int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv);
|
||||||
int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typval_T *argvars_in, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, partial_T *partial, dict_T *selfdict_in);
|
int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typval_T *argvars_in, int (*argv_func)(int, typval_T *, int), linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, partial_T *partial, dict_T *selfdict_in);
|
||||||
void ex_function(exarg_T *eap);
|
void ex_function(exarg_T *eap);
|
||||||
int eval_fname_script(char_u *p);
|
int eval_fname_script(char_u *p);
|
||||||
int translated_function_exists(char_u *name);
|
int translated_function_exists(char_u *name);
|
||||||
|
65
src/regexp.c
65
src/regexp.c
@ -7290,6 +7290,50 @@ static int submatch_line_lbr;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
|
#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Put the submatches in "argv[0]" which is a list passed into call_func() by
|
||||||
|
* vim_regsub_both().
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
fill_submatch_list(int argc UNUSED, typval_T *argv, int argcount)
|
||||||
|
{
|
||||||
|
listitem_T *li;
|
||||||
|
int i;
|
||||||
|
char_u *s;
|
||||||
|
|
||||||
|
if (argcount == 0)
|
||||||
|
/* called function doesn't take an argument */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Relies on sl_list to be the first item in staticList10_T. */
|
||||||
|
init_static_list((staticList10_T *)(argv->vval.v_list));
|
||||||
|
|
||||||
|
/* There are always 10 list items in staticList10_T. */
|
||||||
|
li = argv->vval.v_list->lv_first;
|
||||||
|
for (i = 0; i < 10; ++i)
|
||||||
|
{
|
||||||
|
s = submatch_match->startp[i];
|
||||||
|
if (s == NULL || submatch_match->endp[i] == NULL)
|
||||||
|
s = NULL;
|
||||||
|
else
|
||||||
|
s = vim_strnsave(s, (int)(submatch_match->endp[i] - s));
|
||||||
|
li->li_tv.v_type = VAR_STRING;
|
||||||
|
li->li_tv.vval.v_string = s;
|
||||||
|
li = li->li_next;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clear_submatch_list(staticList10_T *sl)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 10; ++i)
|
||||||
|
vim_free(sl->sl_items[i].li_tv.vval.v_string);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* vim_regsub() - perform substitutions after a vim_regexec() or
|
* vim_regsub() - perform substitutions after a vim_regexec() or
|
||||||
* vim_regexec_multi() match.
|
* vim_regexec_multi() match.
|
||||||
@ -7427,10 +7471,11 @@ vim_regsub_both(
|
|||||||
|
|
||||||
if (expr != NULL)
|
if (expr != NULL)
|
||||||
{
|
{
|
||||||
typval_T argv[1];
|
typval_T argv[2];
|
||||||
int dummy;
|
int dummy;
|
||||||
char_u buf[NUMBUFLEN];
|
char_u buf[NUMBUFLEN];
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
|
staticList10_T matchList;
|
||||||
|
|
||||||
rettv.v_type = VAR_STRING;
|
rettv.v_type = VAR_STRING;
|
||||||
rettv.vval.v_string = NULL;
|
rettv.vval.v_string = NULL;
|
||||||
@ -7438,10 +7483,16 @@ vim_regsub_both(
|
|||||||
{
|
{
|
||||||
/* can't do this recursively */
|
/* can't do this recursively */
|
||||||
}
|
}
|
||||||
else if (expr->v_type == VAR_FUNC)
|
else
|
||||||
|
{
|
||||||
|
argv[0].v_type = VAR_LIST;
|
||||||
|
argv[0].vval.v_list = &matchList.sl_list;
|
||||||
|
matchList.sl_list.lv_len = 0;
|
||||||
|
if (expr->v_type == VAR_FUNC)
|
||||||
{
|
{
|
||||||
s = expr->vval.v_string;
|
s = expr->vval.v_string;
|
||||||
call_func(s, (int)STRLEN(s), &rettv, 0, argv,
|
call_func(s, (int)STRLEN(s), &rettv,
|
||||||
|
1, argv, fill_submatch_list,
|
||||||
0L, 0L, &dummy, TRUE, NULL, NULL);
|
0L, 0L, &dummy, TRUE, NULL, NULL);
|
||||||
}
|
}
|
||||||
else if (expr->v_type == VAR_PARTIAL)
|
else if (expr->v_type == VAR_PARTIAL)
|
||||||
@ -7449,12 +7500,18 @@ vim_regsub_both(
|
|||||||
partial_T *partial = expr->vval.v_partial;
|
partial_T *partial = expr->vval.v_partial;
|
||||||
|
|
||||||
s = partial->pt_name;
|
s = partial->pt_name;
|
||||||
call_func(s, (int)STRLEN(s), &rettv, 0, argv,
|
call_func(s, (int)STRLEN(s), &rettv,
|
||||||
|
1, argv, fill_submatch_list,
|
||||||
0L, 0L, &dummy, TRUE, partial, NULL);
|
0L, 0L, &dummy, TRUE, partial, NULL);
|
||||||
}
|
}
|
||||||
|
if (matchList.sl_list.lv_len > 0)
|
||||||
|
/* fill_submatch_list() was called */
|
||||||
|
clear_submatch_list(&matchList);
|
||||||
|
}
|
||||||
eval_result = get_tv_string_buf_chk(&rettv, buf);
|
eval_result = get_tv_string_buf_chk(&rettv, buf);
|
||||||
if (eval_result != NULL)
|
if (eval_result != NULL)
|
||||||
eval_result = vim_strsave(eval_result);
|
eval_result = vim_strsave(eval_result);
|
||||||
|
clear_tv(&rettv);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
eval_result = eval_to_string(source + 2, NULL, TRUE);
|
eval_result = eval_to_string(source + 2, NULL, TRUE);
|
||||||
|
@ -1244,6 +1244,14 @@ struct listvar_S
|
|||||||
list_T *lv_used_prev; /* previous list in used lists list */
|
list_T *lv_used_prev; /* previous list in used lists list */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Static list with 10 items. Use init_static_list() to initialize.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
list_T sl_list; /* must be first */
|
||||||
|
listitem_T sl_items[10];
|
||||||
|
} staticList10_T;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Structure to hold an item of a Dictionary.
|
* Structure to hold an item of a Dictionary.
|
||||||
* Also used for a variable.
|
* Also used for a variable.
|
||||||
|
@ -153,3 +153,22 @@ func Test_substitute_expr()
|
|||||||
endfunc
|
endfunc
|
||||||
call assert_equal('--', substitute('xxx', 'x*', {-> '-' . Recurse() . '-'}, ''))
|
call assert_equal('--', substitute('xxx', 'x*', {-> '-' . Recurse() . '-'}, ''))
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_substitute_expr_arg()
|
||||||
|
call assert_equal('123456789-123456789=', substitute('123456789',
|
||||||
|
\ '\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)',
|
||||||
|
\ {m -> m[0] . '-' . m[1] . m[2] . m[3] . m[4] . m[5] . m[6] . m[7] . m[8] . m[9] . '='}, ''))
|
||||||
|
|
||||||
|
call assert_equal('123456-123456=789', substitute('123456789',
|
||||||
|
\ '\(.\)\(.\)\(.\)\(a*\)\(n*\)\(.\)\(.\)\(.\)\(x*\)',
|
||||||
|
\ {m -> m[0] . '-' . m[1] . m[2] . m[3] . m[4] . m[5] . m[6] . m[7] . m[8] . m[9] . '='}, ''))
|
||||||
|
|
||||||
|
call assert_equal('123456789-123456789x=', substitute('123456789',
|
||||||
|
\ '\(.\)\(.\)\(.*\)',
|
||||||
|
\ {m -> m[0] . '-' . m[1] . m[2] . m[3] . 'x' . m[4] . m[5] . m[6] . m[7] . m[8] . m[9] . '='}, ''))
|
||||||
|
|
||||||
|
call assert_fails("call substitute('xxx', '.', {m -> string(add(m, 'x'))}, '')", 'E742:')
|
||||||
|
call assert_fails("call substitute('xxx', '.', {m -> string(insert(m, 'x'))}, '')", 'E742:')
|
||||||
|
call assert_fails("call substitute('xxx', '.', {m -> string(extend(m, ['x']))}, '')", 'E742:')
|
||||||
|
call assert_fails("call substitute('xxx', '.', {m -> string(remove(m, 1))}, '')", 'E742:')
|
||||||
|
endfunc
|
||||||
|
@ -480,7 +480,7 @@ get_func_tv(
|
|||||||
&argvars[i];
|
&argvars[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = call_func(name, len, rettv, argcount, argvars,
|
ret = call_func(name, len, rettv, argcount, argvars, NULL,
|
||||||
firstline, lastline, doesrange, evaluate, partial, selfdict);
|
firstline, lastline, doesrange, evaluate, partial, selfdict);
|
||||||
|
|
||||||
funcargs.ga_len -= i;
|
funcargs.ga_len -= i;
|
||||||
@ -1139,7 +1139,7 @@ func_call(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (item == NULL)
|
if (item == NULL)
|
||||||
r = call_func(name, (int)STRLEN(name), rettv, argc, argv,
|
r = call_func(name, (int)STRLEN(name), rettv, argc, argv, NULL,
|
||||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
||||||
&dummy, TRUE, partial, selfdict);
|
&dummy, TRUE, partial, selfdict);
|
||||||
|
|
||||||
@ -1152,6 +1152,11 @@ func_call(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Call a function with its resolved parameters
|
* Call a function with its resolved parameters
|
||||||
|
*
|
||||||
|
* "argv_func", when not NULL, can be used to fill in arguments only when the
|
||||||
|
* invoked function uses them. It is called like this:
|
||||||
|
* new_argcount = argv_func(current_argcount, argv, called_func_argcount)
|
||||||
|
*
|
||||||
* Return FAIL when the function can't be called, OK otherwise.
|
* Return FAIL when the function can't be called, OK otherwise.
|
||||||
* Also returns OK when an error was encountered while executing the function.
|
* Also returns OK when an error was encountered while executing the function.
|
||||||
*/
|
*/
|
||||||
@ -1163,6 +1168,8 @@ call_func(
|
|||||||
int argcount_in, /* number of "argvars" */
|
int argcount_in, /* number of "argvars" */
|
||||||
typval_T *argvars_in, /* vars for arguments, must have "argcount"
|
typval_T *argvars_in, /* vars for arguments, must have "argcount"
|
||||||
PLUS ONE elements! */
|
PLUS ONE elements! */
|
||||||
|
int (* argv_func)(int, typval_T *, int),
|
||||||
|
/* function to fill in argvars */
|
||||||
linenr_T firstline, /* first line of range */
|
linenr_T firstline, /* first line of range */
|
||||||
linenr_T lastline, /* last line of range */
|
linenr_T lastline, /* last line of range */
|
||||||
int *doesrange, /* return: function handled range */
|
int *doesrange, /* return: function handled range */
|
||||||
@ -1254,6 +1261,9 @@ call_func(
|
|||||||
|
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
{
|
{
|
||||||
|
if (argv_func != NULL)
|
||||||
|
argcount = argv_func(argcount, argvars, fp->uf_args.ga_len);
|
||||||
|
|
||||||
if (fp->uf_flags & FC_RANGE)
|
if (fp->uf_flags & FC_RANGE)
|
||||||
*doesrange = TRUE;
|
*doesrange = TRUE;
|
||||||
if (argcount < fp->uf_args.ga_len)
|
if (argcount < fp->uf_args.ga_len)
|
||||||
|
@ -758,6 +758,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 */
|
||||||
|
/**/
|
||||||
|
2090,
|
||||||
/**/
|
/**/
|
||||||
2089,
|
2089,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user