refactor(eval): treat v:lua call as simple function

This commit is contained in:
zeertzjq 2024-08-02 12:16:04 +08:00
parent 6d722f3309
commit 99bb0a10d3
3 changed files with 31 additions and 8 deletions

View File

@ -406,7 +406,14 @@ The value of a few options, such as 'foldexpr', is an expression that is
evaluated to get a value. The evaluation can have quite a bit of overhead. evaluated to get a value. The evaluation can have quite a bit of overhead.
One way to minimize the overhead, and also to keep the option value very One way to minimize the overhead, and also to keep the option value very
simple, is to define a function and set the option to call it without simple, is to define a function and set the option to call it without
arguments. arguments. A |v:lua-call| can also be used. Example: >vim
lua << EOF
function _G.MyFoldFunc()
-- ... compute fold level for line v:lnum
return level
end
EOF
set foldexpr=v:lua.MyFoldFunc()
Setting the filetype Setting the filetype

View File

@ -1466,14 +1466,14 @@ Object eval_foldtext(win_T *wp)
/// When "use_namespace" is true recognize "b:", "s:", etc. /// When "use_namespace" is true recognize "b:", "s:", etc.
/// Return a pointer to just after the name. Equal to "arg" if there is no /// Return a pointer to just after the name. Equal to "arg" if there is no
/// valid name. /// valid name.
static char *to_name_end(char *arg, bool use_namespace) static const char *to_name_end(const char *arg, bool use_namespace)
{ {
// Quick check for valid starting character. // Quick check for valid starting character.
if (!eval_isnamec1(*arg)) { if (!eval_isnamec1(*arg)) {
return arg; return arg;
} }
char *p; const char *p;
for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p)) { for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p)) {
// Include a namespace such as "s:var" and "v:var". But "n:" is not // Include a namespace such as "s:var" and "v:var". But "n:" is not
// and can be used in slice "[n:]". // and can be used in slice "[n:]".
@ -2621,18 +2621,25 @@ int eval0(char *arg, typval_T *rettv, exarg_T *eap, evalarg_T *const evalarg)
/// If "arg" is a simple function call without arguments then call it and return /// If "arg" is a simple function call without arguments then call it and return
/// the result. Otherwise return NOTDONE. /// the result. Otherwise return NOTDONE.
static int may_call_simple_func(char *arg, typval_T *rettv) static int may_call_simple_func(const char *arg, typval_T *rettv)
{ {
char *parens = strstr(arg, "()"); const char *parens = strstr(arg, "()");
int r = NOTDONE; int r = NOTDONE;
// If the expression is "FuncName()" then we can skip a lot of overhead. // If the expression is "FuncName()" then we can skip a lot of overhead.
if (parens != NULL && *skipwhite(parens + 2) == NUL) { if (parens != NULL && *skipwhite(parens + 2) == NUL) {
char *p = strncmp(arg, "<SNR>", 5) == 0 ? skipdigits(arg + 5) : arg; if (strnequal(arg, "v:lua.", 6)) {
const char *p = arg + 6;
if (skip_luafunc_name(p) == parens) {
r = call_simple_luafunc(p, (size_t)(parens - p), rettv);
}
} else {
const char *p = strncmp(arg, "<SNR>", 5) == 0 ? skipdigits(arg + 5) : arg;
if (to_name_end(p, true) == parens) { if (to_name_end(p, true) == parens) {
r = call_simple_func(arg, (size_t)(parens - arg), rettv); r = call_simple_func(arg, (size_t)(parens - arg), rettv);
} }
} }
}
return r; return r;
} }

View File

@ -1776,6 +1776,15 @@ theend:
return ret; return ret;
} }
int call_simple_luafunc(const char *funcname, size_t len, typval_T *rettv)
FUNC_ATTR_NONNULL_ALL
{
typval_T argvars[1];
argvars[0].v_type = VAR_UNKNOWN;
nlua_typval_call(funcname, len, argvars, 0, rettv);
return OK;
}
/// Call a function without arguments, partial or dict. /// Call a function without arguments, partial or dict.
/// This is like call_func() when the call is only "FuncName()". /// This is like call_func() when the call is only "FuncName()".
/// To be used by "expr" options. /// To be used by "expr" options.