aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/eval.c4
-rw-r--r--src/nvim/eval.h2
-rw-r--r--src/nvim/regexp.c22
-rw-r--r--src/nvim/testdir/test_substitute.vim8
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']