diff options
Diffstat (limited to 'src/nvim/eval')
| -rw-r--r-- | src/nvim/eval/funcs.c | 27 | ||||
| -rw-r--r-- | src/nvim/eval/userfunc.c | 38 |
2 files changed, 65 insertions, 0 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index c319bd8214..22e7f383a5 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2372,6 +2372,33 @@ static void f_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) for (int i = 0; i < pt->pt_argc; i++) { tv_list_append_tv(rettv->vval.v_list, &pt->pt_argv[i]); } + } else if (strcmp(what, "arity") == 0) { + int required = 0; + int optional = 0; + bool varargs = false; + const char *name = partial_name(pt); + + get_func_arity(name, &required, &optional, &varargs); + + rettv->v_type = VAR_DICT; + tv_dict_alloc_ret(rettv); + dict_T *dict = rettv->vval.v_dict; + + // Take into account the arguments of the partial, if any. + // Note that it is possible to supply more arguments than the function + // accepts. + if (pt->pt_argc >= required + optional) { + required = optional = 0; + } else if (pt->pt_argc > required) { + optional -= pt->pt_argc - required; + required = 0; + } else { + required -= pt->pt_argc; + } + + tv_dict_add_nr(dict, S_LEN("required"), required); + tv_dict_add_nr(dict, S_LEN("optional"), optional); + tv_dict_add_bool(dict, S_LEN("varargs"), varargs); } else { semsg(_(e_invarg2), what); } diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 122a1ac8ab..42391ecec7 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -642,6 +642,44 @@ static char *fname_trans_sid(const char *const name, char *const fname_buf, char return fname; } +int get_func_arity(const char *name, int *required, int *optional, bool *varargs) +{ + int argcount = 0; + int min_argcount = 0; + + const EvalFuncDef *fdef = find_internal_func(name); + if (fdef != NULL) { + argcount = fdef->max_argc; + min_argcount = fdef->min_argc; + *varargs = false; + } else { + char fname_buf[FLEN_FIXED + 1]; + char *tofree = NULL; + int error = FCERR_NONE; + + // May need to translate <SNR>123_ to K_SNR. + char *fname = fname_trans_sid(name, fname_buf, &tofree, &error); + ufunc_T *ufunc = NULL; + if (error == FCERR_NONE) { + ufunc = find_func(fname); + } + xfree(tofree); + + if (ufunc == NULL) { + return FAIL; + } + + argcount = ufunc->uf_args.ga_len; + min_argcount = ufunc->uf_args.ga_len - ufunc->uf_def_args.ga_len; + *varargs = ufunc->uf_varargs; + } + + *required = min_argcount; + *optional = argcount - min_argcount; + + return OK; +} + /// Find a function by name, return pointer to it in ufuncs. /// /// @return NULL for unknown function. |