mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 7.4.2072
Problem: substitute() does not support a Funcref argument. Solution: Support a Funcref like it supports a string starting with "\=".
This commit is contained in:
10
src/eval.c
10
src/eval.c
@@ -9769,7 +9769,7 @@ repeat:
|
|||||||
if (sub != NULL && str != NULL)
|
if (sub != NULL && str != NULL)
|
||||||
{
|
{
|
||||||
*usedlen = (int)(p + 1 - src);
|
*usedlen = (int)(p + 1 - src);
|
||||||
s = do_string_sub(str, pat, sub, flags);
|
s = do_string_sub(str, pat, sub, NULL, flags);
|
||||||
if (s != NULL)
|
if (s != NULL)
|
||||||
{
|
{
|
||||||
*fnamep = s;
|
*fnamep = s;
|
||||||
@@ -9813,6 +9813,7 @@ repeat:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform a substitution on "str" with pattern "pat" and substitute "sub".
|
* Perform a substitution on "str" with pattern "pat" and substitute "sub".
|
||||||
|
* When "sub" is NULL "expr" is used, must be a VAR_FUNC or VAR_PARTIAL.
|
||||||
* "flags" can be "g" to do a global substitute.
|
* "flags" can be "g" to do a global substitute.
|
||||||
* Returns an allocated string, NULL for error.
|
* Returns an allocated string, NULL for error.
|
||||||
*/
|
*/
|
||||||
@@ -9821,6 +9822,7 @@ do_string_sub(
|
|||||||
char_u *str,
|
char_u *str,
|
||||||
char_u *pat,
|
char_u *pat,
|
||||||
char_u *sub,
|
char_u *sub,
|
||||||
|
typval_T *expr,
|
||||||
char_u *flags)
|
char_u *flags)
|
||||||
{
|
{
|
||||||
int sublen;
|
int sublen;
|
||||||
@@ -9873,7 +9875,7 @@ do_string_sub(
|
|||||||
* - The substituted text.
|
* - The substituted text.
|
||||||
* - The text after the match.
|
* - The text after the match.
|
||||||
*/
|
*/
|
||||||
sublen = vim_regsub(®match, sub, tail, FALSE, TRUE, FALSE);
|
sublen = vim_regsub(®match, sub, expr, tail, FALSE, TRUE, FALSE);
|
||||||
if (ga_grow(&ga, (int)((end - tail) + sublen -
|
if (ga_grow(&ga, (int)((end - tail) + sublen -
|
||||||
(regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
|
(regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
|
||||||
{
|
{
|
||||||
@@ -9885,7 +9887,7 @@ do_string_sub(
|
|||||||
i = (int)(regmatch.startp[0] - tail);
|
i = (int)(regmatch.startp[0] - tail);
|
||||||
mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
|
mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
|
||||||
/* add the substituted text */
|
/* add the substituted text */
|
||||||
(void)vim_regsub(®match, sub, (char_u *)ga.ga_data
|
(void)vim_regsub(®match, sub, expr, (char_u *)ga.ga_data
|
||||||
+ ga.ga_len + i, TRUE, TRUE, FALSE);
|
+ ga.ga_len + i, TRUE, TRUE, FALSE);
|
||||||
ga.ga_len += i + sublen - 1;
|
ga.ga_len += i + sublen - 1;
|
||||||
tail = regmatch.endp[0];
|
tail = regmatch.endp[0];
|
||||||
@@ -9906,7 +9908,7 @@ do_string_sub(
|
|||||||
if (p_cpo == empty_option)
|
if (p_cpo == empty_option)
|
||||||
p_cpo = save_cpo;
|
p_cpo = save_cpo;
|
||||||
else
|
else
|
||||||
/* Darn, evaluating {sub} expression changed the value. */
|
/* Darn, evaluating {sub} expression or {expr} changed the value. */
|
||||||
free_string_option(save_cpo);
|
free_string_option(save_cpo);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -11061,14 +11061,21 @@ f_substitute(typval_T *argvars, typval_T *rettv)
|
|||||||
|
|
||||||
char_u *str = get_tv_string_chk(&argvars[0]);
|
char_u *str = get_tv_string_chk(&argvars[0]);
|
||||||
char_u *pat = get_tv_string_buf_chk(&argvars[1], patbuf);
|
char_u *pat = get_tv_string_buf_chk(&argvars[1], patbuf);
|
||||||
char_u *sub = get_tv_string_buf_chk(&argvars[2], subbuf);
|
char_u *sub = NULL;
|
||||||
|
typval_T *expr = NULL;
|
||||||
char_u *flg = get_tv_string_buf_chk(&argvars[3], flagsbuf);
|
char_u *flg = get_tv_string_buf_chk(&argvars[3], flagsbuf);
|
||||||
|
|
||||||
|
if (argvars[2].v_type == VAR_FUNC || argvars[2].v_type == VAR_PARTIAL)
|
||||||
|
expr = &argvars[2];
|
||||||
|
else
|
||||||
|
sub = get_tv_string_buf_chk(&argvars[2], subbuf);
|
||||||
|
|
||||||
rettv->v_type = VAR_STRING;
|
rettv->v_type = VAR_STRING;
|
||||||
if (str == NULL || pat == NULL || sub == NULL || flg == NULL)
|
if (str == NULL || pat == NULL || (sub == NULL && expr == NULL)
|
||||||
|
|| flg == NULL)
|
||||||
rettv->vval.v_string = NULL;
|
rettv->vval.v_string = NULL;
|
||||||
else
|
else
|
||||||
rettv->vval.v_string = do_string_sub(str, pat, sub, flg);
|
rettv->vval.v_string = do_string_sub(str, pat, sub, expr, flg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -126,6 +126,6 @@ void assert_exception(typval_T *argvars);
|
|||||||
void assert_fails(typval_T *argvars);
|
void assert_fails(typval_T *argvars);
|
||||||
void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str, typval_T *exp_tv, typval_T *got_tv, assert_type_T atype);
|
void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str, typval_T *exp_tv, typval_T *got_tv, assert_type_T atype);
|
||||||
int modify_fname(char_u *src, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen);
|
int modify_fname(char_u *src, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen);
|
||||||
char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, char_u *flags);
|
char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, typval_T *expr, char_u *flags);
|
||||||
void filter_map(typval_T *argvars, typval_T *rettv, int map);
|
void filter_map(typval_T *argvars, typval_T *rettv, int map);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@@ -7,7 +7,7 @@ void free_regexp_stuff(void);
|
|||||||
reg_extmatch_T *ref_extmatch(reg_extmatch_T *em);
|
reg_extmatch_T *ref_extmatch(reg_extmatch_T *em);
|
||||||
void unref_extmatch(reg_extmatch_T *em);
|
void unref_extmatch(reg_extmatch_T *em);
|
||||||
char_u *regtilde(char_u *source, int magic);
|
char_u *regtilde(char_u *source, int magic);
|
||||||
int vim_regsub(regmatch_T *rmp, char_u *source, char_u *dest, int copy, int magic, int backslash);
|
int vim_regsub(regmatch_T *rmp, char_u *source, typval_T *expr, char_u *dest, int copy, int magic, int backslash);
|
||||||
int vim_regsub_multi(regmmatch_T *rmp, linenr_T lnum, char_u *source, char_u *dest, int copy, int magic, int backslash);
|
int vim_regsub_multi(regmmatch_T *rmp, linenr_T lnum, char_u *source, char_u *dest, int copy, int magic, int backslash);
|
||||||
char_u *reg_submatch(int no);
|
char_u *reg_submatch(int no);
|
||||||
list_T *reg_submatch_list(int no);
|
list_T *reg_submatch_list(int no);
|
||||||
|
48
src/regexp.c
48
src/regexp.c
@@ -7169,7 +7169,7 @@ static fptr_T do_Upper(int *, int);
|
|||||||
static fptr_T do_lower(int *, int);
|
static fptr_T do_lower(int *, int);
|
||||||
static fptr_T do_Lower(int *, int);
|
static fptr_T do_Lower(int *, int);
|
||||||
|
|
||||||
static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, int backslash);
|
static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, int copy, int magic, int backslash);
|
||||||
|
|
||||||
static fptr_T
|
static fptr_T
|
||||||
do_upper(int *d, int c)
|
do_upper(int *d, int c)
|
||||||
@@ -7312,6 +7312,7 @@ static int submatch_line_lbr;
|
|||||||
vim_regsub(
|
vim_regsub(
|
||||||
regmatch_T *rmp,
|
regmatch_T *rmp,
|
||||||
char_u *source,
|
char_u *source,
|
||||||
|
typval_T *expr,
|
||||||
char_u *dest,
|
char_u *dest,
|
||||||
int copy,
|
int copy,
|
||||||
int magic,
|
int magic,
|
||||||
@@ -7322,7 +7323,7 @@ vim_regsub(
|
|||||||
reg_maxline = 0;
|
reg_maxline = 0;
|
||||||
reg_buf = curbuf;
|
reg_buf = curbuf;
|
||||||
reg_line_lbr = TRUE;
|
reg_line_lbr = TRUE;
|
||||||
return vim_regsub_both(source, dest, copy, magic, backslash);
|
return vim_regsub_both(source, expr, dest, copy, magic, backslash);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -7342,12 +7343,13 @@ vim_regsub_multi(
|
|||||||
reg_firstlnum = lnum;
|
reg_firstlnum = lnum;
|
||||||
reg_maxline = curbuf->b_ml.ml_line_count - lnum;
|
reg_maxline = curbuf->b_ml.ml_line_count - lnum;
|
||||||
reg_line_lbr = FALSE;
|
reg_line_lbr = FALSE;
|
||||||
return vim_regsub_both(source, dest, copy, magic, backslash);
|
return vim_regsub_both(source, NULL, dest, copy, magic, backslash);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vim_regsub_both(
|
vim_regsub_both(
|
||||||
char_u *source,
|
char_u *source,
|
||||||
|
typval_T *expr,
|
||||||
char_u *dest,
|
char_u *dest,
|
||||||
int copy,
|
int copy,
|
||||||
int magic,
|
int magic,
|
||||||
@@ -7368,7 +7370,7 @@ vim_regsub_both(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Be paranoid... */
|
/* Be paranoid... */
|
||||||
if (source == NULL || dest == NULL)
|
if ((source == NULL && expr == NULL) || dest == NULL)
|
||||||
{
|
{
|
||||||
EMSG(_(e_null));
|
EMSG(_(e_null));
|
||||||
return 0;
|
return 0;
|
||||||
@@ -7381,11 +7383,11 @@ vim_regsub_both(
|
|||||||
/*
|
/*
|
||||||
* When the substitute part starts with "\=" evaluate it as an expression.
|
* When the substitute part starts with "\=" evaluate it as an expression.
|
||||||
*/
|
*/
|
||||||
if (source[0] == '\\' && source[1] == '='
|
if (expr != NULL || (source[0] == '\\' && source[1] == '='
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
&& !can_f_submatch /* can't do this recursively */
|
&& !can_f_submatch /* can't do this recursively */
|
||||||
#endif
|
#endif
|
||||||
)
|
))
|
||||||
{
|
{
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
/* To make sure that the length doesn't change between checking the
|
/* To make sure that the length doesn't change between checking the
|
||||||
@@ -7406,6 +7408,7 @@ vim_regsub_both(
|
|||||||
{
|
{
|
||||||
win_T *save_reg_win;
|
win_T *save_reg_win;
|
||||||
int save_ireg_ic;
|
int save_ireg_ic;
|
||||||
|
int prev_can_f_submatch = can_f_submatch;
|
||||||
|
|
||||||
vim_free(eval_result);
|
vim_free(eval_result);
|
||||||
|
|
||||||
@@ -7422,7 +7425,40 @@ vim_regsub_both(
|
|||||||
save_ireg_ic = ireg_ic;
|
save_ireg_ic = ireg_ic;
|
||||||
can_f_submatch = TRUE;
|
can_f_submatch = TRUE;
|
||||||
|
|
||||||
|
if (expr != NULL)
|
||||||
|
{
|
||||||
|
typval_T argv[1];
|
||||||
|
int dummy;
|
||||||
|
char_u buf[NUMBUFLEN];
|
||||||
|
typval_T rettv;
|
||||||
|
|
||||||
|
rettv.v_type = VAR_STRING;
|
||||||
|
rettv.vval.v_string = NULL;
|
||||||
|
if (prev_can_f_submatch)
|
||||||
|
{
|
||||||
|
/* can't do this recursively */
|
||||||
|
}
|
||||||
|
else if (expr->v_type == VAR_FUNC)
|
||||||
|
{
|
||||||
|
s = expr->vval.v_string;
|
||||||
|
call_func(s, (int)STRLEN(s), &rettv, 0, argv,
|
||||||
|
0L, 0L, &dummy, TRUE, NULL, NULL);
|
||||||
|
}
|
||||||
|
else if (expr->v_type == VAR_PARTIAL)
|
||||||
|
{
|
||||||
|
partial_T *partial = expr->vval.v_partial;
|
||||||
|
|
||||||
|
s = partial->pt_name;
|
||||||
|
call_func(s, (int)STRLEN(s), &rettv, 0, argv,
|
||||||
|
0L, 0L, &dummy, TRUE, partial, NULL);
|
||||||
|
}
|
||||||
|
eval_result = get_tv_string_buf_chk(&rettv, buf);
|
||||||
|
if (eval_result != NULL)
|
||||||
|
eval_result = vim_strsave(eval_result);
|
||||||
|
}
|
||||||
|
else
|
||||||
eval_result = eval_to_string(source + 2, NULL, TRUE);
|
eval_result = eval_to_string(source + 2, NULL, TRUE);
|
||||||
|
|
||||||
if (eval_result != NULL)
|
if (eval_result != NULL)
|
||||||
{
|
{
|
||||||
int had_backslash = FALSE;
|
int had_backslash = FALSE;
|
||||||
|
@@ -135,3 +135,21 @@ function Test_printf_64bit()
|
|||||||
call assert_equal("123456789012345", printf('%d', 123456789012345))
|
call assert_equal("123456789012345", printf('%d', 123456789012345))
|
||||||
endif
|
endif
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_substitute_expr()
|
||||||
|
let g:val = 'XXX'
|
||||||
|
call assert_equal('XXX', substitute('yyy', 'y*', '\=g:val', ''))
|
||||||
|
call assert_equal('XXX', substitute('yyy', 'y*', {-> g:val}, ''))
|
||||||
|
call assert_equal("-\u1b \uf2-", substitute("-%1b %f2-", '%\(\x\x\)',
|
||||||
|
\ '\=nr2char("0x" . submatch(1))', 'g'))
|
||||||
|
call assert_equal("-\u1b \uf2-", substitute("-%1b %f2-", '%\(\x\x\)',
|
||||||
|
\ {-> nr2char("0x" . submatch(1))}, 'g'))
|
||||||
|
|
||||||
|
call assert_equal('231', substitute('123', '\(.\)\(.\)\(.\)',
|
||||||
|
\ {-> submatch(2) . submatch(3) . submatch(1)}, ''))
|
||||||
|
|
||||||
|
func Recurse()
|
||||||
|
return substitute('yyy', 'y*', {-> g:val}, '')
|
||||||
|
endfunc
|
||||||
|
call assert_equal('--', substitute('xxx', 'x*', {-> '-' . Recurse() . '-'}, ''))
|
||||||
|
endfunc
|
||||||
|
@@ -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 */
|
||||||
|
/**/
|
||||||
|
2072,
|
||||||
/**/
|
/**/
|
||||||
2071,
|
2071,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user