diff options
-rw-r--r-- | src/nvim/edit.c | 19 | ||||
-rw-r--r-- | src/nvim/eval.c | 76 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 22 | ||||
-rw-r--r-- | src/nvim/normal.c | 10 | ||||
-rw-r--r-- | src/nvim/testdir/test_ins_complete.vim | 25 |
5 files changed, 80 insertions, 72 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 06f8cc9413..5a9549cc89 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -3695,14 +3695,19 @@ expand_by_function ( return; // Call 'completefunc' to obtain the list of matches. - const char_u *const args[2] = { (char_u *)"0", base }; + typval_T args[3]; + args[0].v_type = VAR_NUMBER; + args[1].v_type = VAR_STRING; + args[2].v_type = VAR_UNKNOWN; + args[0].vval.v_number = 0; + args[1].vval.v_string = base != NULL ? base : (char_u *)""; pos = curwin->w_cursor; curwin_save = curwin; curbuf_save = curbuf; - /* Call a function, which returns a list or dict. */ - if (call_vim_function(funcname, 2, args, FALSE, FALSE, &rettv) == OK) { + // Call a function, which returns a list or dict. + if (call_vim_function(funcname, 2, args, &rettv, false) == OK) { switch (rettv.v_type) { case VAR_LIST: matchlist = rettv.vval.v_list; @@ -4905,7 +4910,13 @@ static int ins_complete(int c, bool enable_pum) return FAIL; } - const char_u *const args[2] = { (char_u *)"1", NULL }; + typval_T args[3]; + args[0].v_type = VAR_NUMBER; + args[1].v_type = VAR_STRING; + args[2].v_type = VAR_UNKNOWN; + args[0].vval.v_number = 1; + args[1].vval.v_string = (char_u *)""; + pos = curwin->w_cursor; curwin_save = curwin; curbuf_save = curbuf; diff --git a/src/nvim/eval.c b/src/nvim/eval.c index d13b5965f9..cefd351dd7 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1296,68 +1296,35 @@ int get_spellword(list_T *const list, const char **ret_word) // Call some vim script function and return the result in "*rettv". -// Uses argv[argc] for the function arguments. Only Number and String -// arguments are currently supported. +// Uses argv[0] to argv[argc-1] for the function arguments. argv[argc] +// should have type VAR_UNKNOWN. // // Return OK or FAIL. int call_vim_function( const char_u *func, int argc, - const char_u *const *const argv, - bool safe, // use the sandbox - int str_arg_only, // all arguments are strings - typval_T *rettv + typval_T *argv, + typval_T *rettv, + bool safe // use the sandbox ) { - varnumber_T n; - int len; int doesrange; void *save_funccalp = NULL; int ret; - typval_T *argvars = xmalloc((argc + 1) * sizeof(typval_T)); - - for (int i = 0; i < argc; i++) { - // Pass a NULL or empty argument as an empty string - if (argv[i] == NULL || *argv[i] == NUL) { - argvars[i].v_type = VAR_STRING; - argvars[i].vval.v_string = (char_u *)""; - continue; - } - - if (str_arg_only) { - len = 0; - } else { - // Recognize a number argument, the others must be strings. A dash - // is a string too. - vim_str2nr(argv[i], NULL, &len, STR2NR_ALL, &n, NULL, 0); - if (len == 1 && *argv[i] == '-') { - len = 0; - } - } - if (len != 0 && len == (int)STRLEN(argv[i])) { - argvars[i].v_type = VAR_NUMBER; - argvars[i].vval.v_number = n; - } else { - argvars[i].v_type = VAR_STRING; - argvars[i].vval.v_string = (char_u *)argv[i]; - } - } - if (safe) { save_funccalp = save_funccal(); ++sandbox; } rettv->v_type = VAR_UNKNOWN; // tv_clear() uses this. - ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars, NULL, + ret = call_func(func, (int)STRLEN(func), rettv, argc, argv, NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &doesrange, true, NULL, NULL); if (safe) { --sandbox; restore_funccal(save_funccalp); } - xfree(argvars); if (ret == FAIL) { tv_clear(rettv); @@ -1365,47 +1332,44 @@ int call_vim_function( return ret; } - /// Call Vim script function and return the result as a number /// /// @param[in] func Function name. /// @param[in] argc Number of arguments. -/// @param[in] argv Array with string arguments. +/// @param[in] argv Array with typval_T arguments. /// @param[in] safe Use with sandbox. /// /// @return -1 when calling function fails, result of function otherwise. varnumber_T call_func_retnr(char_u *func, int argc, - const char_u *const *const argv, int safe) + typval_T *argv, int safe) { typval_T rettv; varnumber_T retval; - /* All arguments are passed as strings, no conversion to number. */ - if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL) + if (call_vim_function(func, argc, argv, &rettv, safe) == FAIL) { return -1; - + } retval = tv_get_number_chk(&rettv, NULL); tv_clear(&rettv); return retval; } - /// Call Vim script function and return the result as a string /// /// @param[in] func Function name. /// @param[in] argc Number of arguments. -/// @param[in] argv Array with string arguments. +/// @param[in] argv Array with typval_T arguments. /// @param[in] safe Use the sandbox. /// /// @return [allocated] NULL when calling function fails, allocated string /// otherwise. char *call_func_retstr(const char *const func, int argc, - const char_u *const *argv, + typval_T *argv, bool safe) FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC { typval_T rettv; // All arguments are passed as strings, no conversion to number. - if (call_vim_function((const char_u *)func, argc, argv, safe, true, &rettv) + if (call_vim_function((const char_u *)func, argc, argv, &rettv, safe) == FAIL) { return NULL; } @@ -1414,24 +1378,24 @@ char *call_func_retstr(const char *const func, int argc, tv_clear(&rettv); return retval; } - /// Call Vim script function and return the result as a List /// /// @param[in] func Function name. /// @param[in] argc Number of arguments. -/// @param[in] argv Array with string arguments. +/// @param[in] argv Array with typval_T arguments. /// @param[in] safe Use the sandbox. /// /// @return [allocated] NULL when calling function fails or return tv is not a /// List, allocated List otherwise. -void *call_func_retlist(char_u *func, int argc, const char_u *const *argv, +void *call_func_retlist(char_u *func, int argc, typval_T *argv, bool safe) { typval_T rettv; - /* All arguments are passed as strings, no conversion to number. */ - if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL) + // All arguments are passed as strings, no conversion to number. + if (call_vim_function(func, argc, argv, &rettv, safe) == FAIL) { return NULL; + } if (rettv.v_type != VAR_LIST) { tv_clear(&rettv); @@ -24021,6 +23985,8 @@ bool eval_has_provider(const char *name) static int has_python = -1; static int has_python3 = -1; static int has_ruby = -1; + typval_T args[1]; + args[0].v_type = VAR_UNKNOWN; if (strequal(name, "clipboard")) { CHECK_PROVIDER(clipboard); @@ -24035,7 +24001,7 @@ bool eval_has_provider(const char *name) bool need_check_ruby = (has_ruby == -1); CHECK_PROVIDER(ruby); if (need_check_ruby && has_ruby == 1) { - char *rubyhost = call_func_retstr("provider#ruby#Detect", 0, NULL, true); + char *rubyhost = call_func_retstr("provider#ruby#Detect", 0, args, true); if (rubyhost) { if (*rubyhost == NUL) { // Invalid rubyhost executable. Gem is probably not installed. diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index c4b0ef01d5..38432a34db 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -200,7 +200,7 @@ static Array cmdline_block = ARRAY_DICT_INIT; */ typedef void *(*user_expand_func_T)(const char_u *, int, - const char_u * const *, + typval_T *, bool); static histentry_T *(history[HIST_COUNT]) = {NULL, NULL, NULL, NULL, NULL}; @@ -5060,8 +5060,8 @@ static void * call_user_expand_func(user_expand_func_T user_expand_func, expand_T *xp, int *num_file, char_u ***file) { char_u keep = 0; - char_u num[50]; - char_u *args[3]; + typval_T args[4]; + char_u *pat = NULL; int save_current_SID = current_SID; void *ret; struct cmdline_info save_ccline; @@ -5076,10 +5076,14 @@ static void * call_user_expand_func(user_expand_func_T user_expand_func, ccline.cmdbuff[ccline.cmdlen] = 0; } - args[0] = vim_strnsave(xp->xp_pattern, xp->xp_pattern_len); - args[1] = xp->xp_line; - sprintf((char *)num, "%d", xp->xp_col); - args[2] = num; + pat = vim_strnsave(xp->xp_pattern, xp->xp_pattern_len); + args[0].v_type = VAR_STRING; + args[1].v_type = VAR_STRING; + args[2].v_type = VAR_NUMBER; + args[3].v_type = VAR_UNKNOWN; + args[0].vval.v_string = pat; + args[1].vval.v_string = xp->xp_line; + args[2].vval.v_number = xp->xp_col; /* Save the cmdline, we don't know what the function may do. */ save_ccline = ccline; @@ -5089,7 +5093,7 @@ static void * call_user_expand_func(user_expand_func_T user_expand_func, ret = user_expand_func(xp->xp_arg, 3, - (const char_u * const *)args, + args, false); ccline = save_ccline; @@ -5097,7 +5101,7 @@ static void * call_user_expand_func(user_expand_func_T user_expand_func, if (ccline.cmdbuff != NULL) ccline.cmdbuff[ccline.cmdlen] = keep; - xfree(args[0]); + xfree(pat); return ret; } diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 2e4cdc1fe1..c3b4f4e376 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -2096,13 +2096,15 @@ static void op_function(oparg_T *oap) decl(&curbuf->b_op_end); } - const char_u *const argv[1] = { - (const char_u *)(((const char *const[]) { + typval_T argv[2]; + argv[0].v_type = VAR_STRING; + argv[1].v_type = VAR_UNKNOWN; + argv[0].vval.v_string = + (char_u *)(((const char *const[]) { [kMTBlockWise] = "block", [kMTLineWise] = "line", [kMTCharWise] = "char", - })[oap->motion_type]), - }; + })[oap->motion_type]); // Reset virtual_op so that 'virtualedit' can be changed in the // function. diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim index 071e82579e..7f52481ba8 100644 --- a/src/nvim/testdir/test_ins_complete.vim +++ b/src/nvim/testdir/test_ins_complete.vim @@ -250,6 +250,31 @@ func Test_omni_dash() set omnifunc= endfunc +func Test_completefunc_args() + let s:args = [] + func! CompleteFunc(findstart, base) + let s:args += [[a:findstart, empty(a:base)]] + endfunc + new + + set completefunc=CompleteFunc + call feedkeys("i\<C-X>\<C-U>\<Esc>", 'x') + call assert_equal([1, 1], s:args[0]) + call assert_equal(0, s:args[1][0]) + set completefunc= + + let s:args = [] + set omnifunc=CompleteFunc + call feedkeys("i\<C-X>\<C-O>\<Esc>", 'x') + call assert_equal([1, 1], s:args[0]) + call assert_equal(0, s:args[1][0]) + set omnifunc= + + bwipe! + unlet s:args + delfunc CompleteFunc +endfunc + " Check that when using feedkeys() typeahead does not interrupt searching for " completions. func Test_compl_feedkeys() |