diff options
-rw-r--r-- | src/nvim/eval.c | 4 | ||||
-rw-r--r-- | src/nvim/eval.h | 2 | ||||
-rw-r--r-- | src/nvim/regexp.c | 22 | ||||
-rw-r--r-- | src/nvim/testdir/test_substitute.vim | 8 |
4 files changed, 25 insertions, 11 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index dc20940166..7c7e9da8ac 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -6382,7 +6382,9 @@ call_func( error = ERROR_DELETED; } else if (fp != NULL) { if (argv_func != NULL) { - argcount = argv_func(argcount, argvars, fp->uf_args.ga_len); + // postponed filling in the arguments, do it now + argcount = argv_func(argcount, argvars, argv_clear, + fp->uf_args.ga_len); } if (fp->uf_flags & FC_RANGE) { *doesrange = true; diff --git a/src/nvim/eval.h b/src/nvim/eval.h index 918823c311..7606d16f5d 100644 --- a/src/nvim/eval.h +++ b/src/nvim/eval.h @@ -187,7 +187,7 @@ extern const list_T *eval_msgpack_type_lists[LAST_MSGPACK_TYPE + 1]; #undef LAST_MSGPACK_TYPE -typedef int (*ArgvFunc)(int current_argcount, typval_T *argv, +typedef int (*ArgvFunc)(int current_argcount, typval_T *argv, int argskip, int called_func_argcount); /// trans_function_name() flags diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 90dc8ab90f..dba7c53c10 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -6491,20 +6491,24 @@ typedef struct { static regsubmatch_T rsm; // can only be used when can_f_submatch is true -/// 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, typval_T *argv, int argcount) +/// Put the submatches in "argv[argskip]" which is a list passed into +/// call_func() by vim_regsub_both(). +static int fill_submatch_list(int argc FUNC_ATTR_UNUSED, typval_T *argv, + int argskip, int argcount) + FUNC_ATTR_NONNULL_ALL { - if (argcount == 0) { - // called function doesn't take an argument - return 0; + typval_T *listarg = argv + argskip; + + if (argcount == argskip) { + // called function doesn't take a submatches argument + return argskip; } // Relies on sl_list to be the first item in staticList10_T. - tv_list_init_static10((staticList10_T *)argv->vval.v_list); + tv_list_init_static10((staticList10_T *)listarg->vval.v_list); // There are always 10 list items in staticList10_T. - listitem_T *li = tv_list_first(argv->vval.v_list); + listitem_T *li = tv_list_first(listarg->vval.v_list); for (int i = 0; i < 10; i++) { char_u *s = rsm.sm_match->startp[i]; if (s == NULL || rsm.sm_match->endp[i] == NULL) { @@ -6516,7 +6520,7 @@ static int fill_submatch_list(int argc, typval_T *argv, int argcount) TV_LIST_ITEM_TV(li)->vval.v_string = s; li = TV_LIST_ITEM_NEXT(argv->vval.v_list, li); } - return 1; + return argskip + 1; } static void clear_submatch_list(staticList10_T *sl) diff --git a/src/nvim/testdir/test_substitute.vim b/src/nvim/testdir/test_substitute.vim index e94bd22cea..25a8676b0c 100644 --- a/src/nvim/testdir/test_substitute.vim +++ b/src/nvim/testdir/test_substitute.vim @@ -613,6 +613,14 @@ func Test_sub_replace_10() call assert_equal('1aaa', substitute('123', '1\zs\|[23]', 'a', 'g')) endfunc +func SubReplacer(text, submatches) + return a:text .. a:submatches[0] .. a:text +endfunc + +func Test_substitute_partial() + call assert_equal('1foo2foo3', substitute('123', '2', function('SubReplacer', ['foo']), 'g')) +endfunc + func Test_sub_cmd_9() new let input = ['1 aaa', '2 aaa', '3 aaa'] |