mirror of
https://github.com/neovim/neovim.git
synced 2025-10-04 00:46:30 +00:00
vim-patch:9.0.0632: calling a function from an "expr" option has overhead
Problem: Calling a function from an "expr" option has too much overhead.
Solution: Add call_simple_func() and use it for 'foldexpr'
87b4e5c5db
Cherry-pick a call_func() change from patch 8.2.1343.
Add expr-option-function docs to options.txt.
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
@@ -1349,7 +1349,7 @@ int eval_foldexpr(win_T *wp, int *cp)
|
||||
const sctx_T saved_sctx = current_sctx;
|
||||
const bool use_sandbox = was_set_insecurely(wp, kOptFoldexpr, OPT_LOCAL);
|
||||
|
||||
char *arg = wp->w_p_fde;
|
||||
char *arg = skipwhite(wp->w_p_fde);
|
||||
current_sctx = wp->w_p_script_ctx[WV_FDE].script_ctx;
|
||||
|
||||
emsg_off++;
|
||||
@@ -1360,8 +1360,23 @@ int eval_foldexpr(win_T *wp, int *cp)
|
||||
*cp = NUL;
|
||||
|
||||
typval_T tv;
|
||||
int r = NOTDONE;
|
||||
|
||||
// If the expression is "FuncName()" then we can skip a lot of overhead.
|
||||
char *parens = strstr(arg, "()");
|
||||
if (parens != NULL && *skipwhite(parens + 2) == NUL) {
|
||||
char *p = strncmp(arg, "<SNR>", 5) == 0 ? skipdigits(arg + 5) : arg;
|
||||
if (to_name_end(p, true) == parens) {
|
||||
r = call_simple_func(arg, (int)(parens - arg), &tv);
|
||||
}
|
||||
}
|
||||
|
||||
if (r == NOTDONE) {
|
||||
r = eval0(arg, &tv, NULL, &EVALARG_EVALUATE);
|
||||
}
|
||||
|
||||
varnumber_T retval;
|
||||
if (eval0(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL) {
|
||||
if (r == FAIL) {
|
||||
retval = 0;
|
||||
} else {
|
||||
// If the result is a number, just return the number.
|
||||
@@ -1428,6 +1443,31 @@ Object eval_foldtext(win_T *wp)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/// Find the end of a variable or function name. Unlike find_name_end() this
|
||||
/// does not recognize magic braces.
|
||||
/// When "use_namespace" is true recognize "b:", "s:", etc.
|
||||
/// Return a pointer to just after the name. Equal to "arg" if there is no
|
||||
/// valid name.
|
||||
static char *to_name_end(char *arg, bool use_namespace)
|
||||
{
|
||||
// Quick check for valid starting character.
|
||||
if (!eval_isnamec1(*arg)) {
|
||||
return arg;
|
||||
}
|
||||
|
||||
char *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
|
||||
// and can be used in slice "[n:]".
|
||||
if (*p == ':' && (p != arg + 1
|
||||
|| !use_namespace
|
||||
|| vim_strchr("bgstvw", *arg) == NULL)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/// Get an Dict lval variable that can be assigned a value to: "name",
|
||||
/// "name[expr]", "name[expr][expr]", "name.key", "name.key[expr]" etc.
|
||||
/// "name" points to the start of the name.
|
||||
|
Reference in New Issue
Block a user