Merge #10615 'vim-patch:8.1.0053'

fix #10604
This commit is contained in:
Justin M. Keyes 2019-07-29 20:43:44 +02:00 committed by GitHub
commit 6e03f87e09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 72 deletions

View File

@ -3695,14 +3695,19 @@ expand_by_function (
return; return;
// Call 'completefunc' to obtain the list of matches. // 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; pos = curwin->w_cursor;
curwin_save = curwin; curwin_save = curwin;
curbuf_save = curbuf; curbuf_save = curbuf;
/* Call a function, which returns a list or dict. */ // Call a function, which returns a list or dict.
if (call_vim_function(funcname, 2, args, FALSE, FALSE, &rettv) == OK) { if (call_vim_function(funcname, 2, args, &rettv, false) == OK) {
switch (rettv.v_type) { switch (rettv.v_type) {
case VAR_LIST: case VAR_LIST:
matchlist = rettv.vval.v_list; matchlist = rettv.vval.v_list;
@ -4905,7 +4910,13 @@ static int ins_complete(int c, bool enable_pum)
return FAIL; 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; pos = curwin->w_cursor;
curwin_save = curwin; curwin_save = curwin;
curbuf_save = curbuf; curbuf_save = curbuf;

View File

@ -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". // Call some vim script function and return the result in "*rettv".
// Uses argv[argc] for the function arguments. Only Number and String // Uses argv[0] to argv[argc-1] for the function arguments. argv[argc]
// arguments are currently supported. // should have type VAR_UNKNOWN.
// //
// Return OK or FAIL. // Return OK or FAIL.
int call_vim_function( int call_vim_function(
const char_u *func, const char_u *func,
int argc, int argc,
const char_u *const *const argv, typval_T *argv,
bool safe, // use the sandbox typval_T *rettv,
int str_arg_only, // all arguments are strings bool safe // use the sandbox
typval_T *rettv
) )
{ {
varnumber_T n;
int len;
int doesrange; int doesrange;
void *save_funccalp = NULL; void *save_funccalp = NULL;
int ret; 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) { if (safe) {
save_funccalp = save_funccal(); save_funccalp = save_funccal();
++sandbox; ++sandbox;
} }
rettv->v_type = VAR_UNKNOWN; // tv_clear() uses this. 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, curwin->w_cursor.lnum, curwin->w_cursor.lnum,
&doesrange, true, NULL, NULL); &doesrange, true, NULL, NULL);
if (safe) { if (safe) {
--sandbox; --sandbox;
restore_funccal(save_funccalp); restore_funccal(save_funccalp);
} }
xfree(argvars);
if (ret == FAIL) { if (ret == FAIL) {
tv_clear(rettv); tv_clear(rettv);
@ -1365,47 +1332,44 @@ int call_vim_function(
return ret; return ret;
} }
/// Call Vim script function and return the result as a number /// Call Vim script function and return the result as a number
/// ///
/// @param[in] func Function name. /// @param[in] func Function name.
/// @param[in] argc Number of arguments. /// @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. /// @param[in] safe Use with sandbox.
/// ///
/// @return -1 when calling function fails, result of function otherwise. /// @return -1 when calling function fails, result of function otherwise.
varnumber_T call_func_retnr(char_u *func, int argc, 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; typval_T rettv;
varnumber_T retval; varnumber_T retval;
/* All arguments are passed as strings, no conversion to number. */ if (call_vim_function(func, argc, argv, &rettv, safe) == FAIL) {
if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL)
return -1; return -1;
}
retval = tv_get_number_chk(&rettv, NULL); retval = tv_get_number_chk(&rettv, NULL);
tv_clear(&rettv); tv_clear(&rettv);
return retval; return retval;
} }
/// Call Vim script function and return the result as a string /// Call Vim script function and return the result as a string
/// ///
/// @param[in] func Function name. /// @param[in] func Function name.
/// @param[in] argc Number of arguments. /// @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. /// @param[in] safe Use the sandbox.
/// ///
/// @return [allocated] NULL when calling function fails, allocated string /// @return [allocated] NULL when calling function fails, allocated string
/// otherwise. /// otherwise.
char *call_func_retstr(const char *const func, int argc, char *call_func_retstr(const char *const func, int argc,
const char_u *const *argv, typval_T *argv,
bool safe) bool safe)
FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC
{ {
typval_T rettv; typval_T rettv;
// All arguments are passed as strings, no conversion to number. // 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) { == FAIL) {
return NULL; return NULL;
} }
@ -1414,24 +1378,24 @@ char *call_func_retstr(const char *const func, int argc,
tv_clear(&rettv); tv_clear(&rettv);
return retval; return retval;
} }
/// Call Vim script function and return the result as a List /// Call Vim script function and return the result as a List
/// ///
/// @param[in] func Function name. /// @param[in] func Function name.
/// @param[in] argc Number of arguments. /// @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. /// @param[in] safe Use the sandbox.
/// ///
/// @return [allocated] NULL when calling function fails or return tv is not a /// @return [allocated] NULL when calling function fails or return tv is not a
/// List, allocated List otherwise. /// 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) bool safe)
{ {
typval_T rettv; typval_T rettv;
/* All arguments are passed as strings, no conversion to number. */ // 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 NULL; return NULL;
}
if (rettv.v_type != VAR_LIST) { if (rettv.v_type != VAR_LIST) {
tv_clear(&rettv); tv_clear(&rettv);
@ -24021,6 +23985,8 @@ bool eval_has_provider(const char *name)
static int has_python = -1; static int has_python = -1;
static int has_python3 = -1; static int has_python3 = -1;
static int has_ruby = -1; static int has_ruby = -1;
typval_T args[1];
args[0].v_type = VAR_UNKNOWN;
if (strequal(name, "clipboard")) { if (strequal(name, "clipboard")) {
CHECK_PROVIDER(clipboard); CHECK_PROVIDER(clipboard);
@ -24035,7 +24001,7 @@ bool eval_has_provider(const char *name)
bool need_check_ruby = (has_ruby == -1); bool need_check_ruby = (has_ruby == -1);
CHECK_PROVIDER(ruby); CHECK_PROVIDER(ruby);
if (need_check_ruby && has_ruby == 1) { 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) {
if (*rubyhost == NUL) { if (*rubyhost == NUL) {
// Invalid rubyhost executable. Gem is probably not installed. // Invalid rubyhost executable. Gem is probably not installed.

View File

@ -200,7 +200,7 @@ static Array cmdline_block = ARRAY_DICT_INIT;
*/ */
typedef void *(*user_expand_func_T)(const char_u *, typedef void *(*user_expand_func_T)(const char_u *,
int, int,
const char_u * const *, typval_T *,
bool); bool);
static histentry_T *(history[HIST_COUNT]) = {NULL, NULL, NULL, NULL, NULL}; 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) expand_T *xp, int *num_file, char_u ***file)
{ {
char_u keep = 0; char_u keep = 0;
char_u num[50]; typval_T args[4];
char_u *args[3]; char_u *pat = NULL;
int save_current_SID = current_SID; int save_current_SID = current_SID;
void *ret; void *ret;
struct cmdline_info save_ccline; 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; ccline.cmdbuff[ccline.cmdlen] = 0;
} }
args[0] = vim_strnsave(xp->xp_pattern, xp->xp_pattern_len); pat = vim_strnsave(xp->xp_pattern, xp->xp_pattern_len);
args[1] = xp->xp_line; args[0].v_type = VAR_STRING;
sprintf((char *)num, "%d", xp->xp_col); args[1].v_type = VAR_STRING;
args[2] = num; 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 the cmdline, we don't know what the function may do. */
save_ccline = ccline; 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, ret = user_expand_func(xp->xp_arg,
3, 3,
(const char_u * const *)args, args,
false); false);
ccline = save_ccline; ccline = save_ccline;
@ -5097,7 +5101,7 @@ static void * call_user_expand_func(user_expand_func_T user_expand_func,
if (ccline.cmdbuff != NULL) if (ccline.cmdbuff != NULL)
ccline.cmdbuff[ccline.cmdlen] = keep; ccline.cmdbuff[ccline.cmdlen] = keep;
xfree(args[0]); xfree(pat);
return ret; return ret;
} }

View File

@ -2096,13 +2096,15 @@ static void op_function(oparg_T *oap)
decl(&curbuf->b_op_end); decl(&curbuf->b_op_end);
} }
const char_u *const argv[1] = { typval_T argv[2];
(const char_u *)(((const char *const[]) { argv[0].v_type = VAR_STRING;
argv[1].v_type = VAR_UNKNOWN;
argv[0].vval.v_string =
(char_u *)(((const char *const[]) {
[kMTBlockWise] = "block", [kMTBlockWise] = "block",
[kMTLineWise] = "line", [kMTLineWise] = "line",
[kMTCharWise] = "char", [kMTCharWise] = "char",
})[oap->motion_type]), })[oap->motion_type]);
};
// Reset virtual_op so that 'virtualedit' can be changed in the // Reset virtual_op so that 'virtualedit' can be changed in the
// function. // function.

View File

@ -250,6 +250,31 @@ func Test_omni_dash()
set omnifunc= set omnifunc=
endfunc 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 " Check that when using feedkeys() typeahead does not interrupt searching for
" completions. " completions.
func Test_compl_feedkeys() func Test_compl_feedkeys()