diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-08-01 10:41:08 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2024-08-02 11:56:51 +0800 |
commit | 582bf4f1e15988565da53a91395e2d0131628fbb (patch) | |
tree | 320f48a9beb4271a9ffd32eca0db526d3276de7c | |
parent | f7fde0173af95925e7324b7d3c09776173dab8a7 (diff) | |
download | rneovim-582bf4f1e15988565da53a91395e2d0131628fbb.tar.gz rneovim-582bf4f1e15988565da53a91395e2d0131628fbb.tar.bz2 rneovim-582bf4f1e15988565da53a91395e2d0131628fbb.zip |
vim-patch:9.0.0634: evaluating "expr" options has more overhead than needed
Problem: Evaluating "expr" options has more overhead than needed.
Solution: Use call_simple_func() for 'foldtext', 'includeexpr', 'printexpr',
"expr" of 'spellsuggest', 'diffexpr', 'patchexpr', 'balloonexpr',
'formatexpr', 'indentexpr' and 'charconvert'.
https://github.com/vim/vim/commit/a4e0b9785e409e9e660171cea76dfcc5fdafad9b
vim-patch:9.0.0635: build error and compiler warnings
Problem: Build error and compiler warnings.
Solution: Add missing change. Add type casts.
https://github.com/vim/vim/commit/3292a229402c9892f5ab90645fbfe2b1db342f5b
Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r-- | runtime/doc/diff.txt | 6 | ||||
-rw-r--r-- | runtime/doc/options.txt | 24 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/options.lua | 24 | ||||
-rw-r--r-- | src/nvim/digraph.c | 2 | ||||
-rw-r--r-- | src/nvim/eval.c | 120 | ||||
-rw-r--r-- | src/nvim/eval/vars.c | 2 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 2 | ||||
-rw-r--r-- | src/nvim/ex_eval.c | 6 | ||||
-rw-r--r-- | src/nvim/indent.c | 2 | ||||
-rw-r--r-- | src/nvim/mapping.c | 2 | ||||
-rw-r--r-- | src/nvim/ops.c | 2 | ||||
-rw-r--r-- | src/nvim/options.lua | 24 | ||||
-rw-r--r-- | src/nvim/path.c | 5 | ||||
-rw-r--r-- | src/nvim/regexp.c | 2 | ||||
-rw-r--r-- | src/nvim/runtime.c | 2 | ||||
-rw-r--r-- | src/nvim/statusline.c | 4 | ||||
-rw-r--r-- | src/nvim/textformat.c | 2 |
17 files changed, 164 insertions, 67 deletions
diff --git a/runtime/doc/diff.txt b/runtime/doc/diff.txt index 2f174a404e..c9de54342e 100644 --- a/runtime/doc/diff.txt +++ b/runtime/doc/diff.txt @@ -369,6 +369,9 @@ Additionally, 'diffexpr' should take care of "icase" and "iwhite" in the 'diffopt' option. 'diffexpr' cannot change the value of 'lines' and 'columns'. +The advantage of using a function call without arguments is that it is faster, +see |expr-option-function|. + Example (this does almost the same as 'diffexpr' being empty): > set diffexpr=MyDiff() @@ -434,6 +437,9 @@ will have the same effect. These variables are set to the file names used: v:fname_diff patch file v:fname_out resulting patched file +The advantage of using a function call without arguments is that it is faster, +see |expr-option-function|. + Example (this does the same as 'patchexpr' being empty): > set patchexpr=MyPatch() diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index a48d020a34..b4eb3b6f28 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1315,6 +1315,9 @@ A jump table for the options with a short description can be found at |Q_op|. v:fname_out name of the output file Note that v:fname_in and v:fname_out will never be the same. + The advantage of using a function call without arguments is that it is + faster, see |expr-option-function|. + If the 'charconvert' expression starts with s: or |<SID>|, then it is replaced with the script ID (|local-function|). Example: >vim set charconvert=s:MyConvert() @@ -2781,6 +2784,9 @@ A jump table for the options with a short description can be found at |Q_op|. < This will invoke the mylang#Format() function in the autoload/mylang.vim file in 'runtimepath'. |autoload| + The advantage of using a function call without arguments is that it is + faster, see |expr-option-function|. + The expression is also evaluated when 'textwidth' is set and adding text beyond that limit. This happens under the same conditions as when internal formatting is used. Make sure the cursor is kept in the @@ -3416,11 +3422,14 @@ A jump table for the options with a short description can be found at |Q_op|. If the expression starts with s: or |<SID>|, then it is replaced with the script ID (|local-function|). Example: >vim - setlocal includeexpr=s:MyIncludeExpr(v:fname) - setlocal includeexpr=<SID>SomeIncludeExpr(v:fname) + setlocal includeexpr=s:MyIncludeExpr() + setlocal includeexpr=<SID>SomeIncludeExpr() < Otherwise, the expression is evaluated in the context of the script where the option was set, thus script-local items are available. + It is more efficient if the value is just a function call without + arguments, see |expr-option-function|. + The expression will be evaluated in the |sandbox| when set from a modeline, see |sandbox-option|. This option cannot be set in a modeline when 'modelineexpr' is off. @@ -3483,6 +3492,9 @@ A jump table for the options with a short description can be found at |Q_op|. < Otherwise, the expression is evaluated in the context of the script where the option was set, thus script-local items are available. + The advantage of using a function call without arguments is that it is + faster, see |expr-option-function|. + The expression must return the number of spaces worth of indent. It can return "-1" to keep the current indent (this means 'autoindent' is used for the indent). @@ -5923,9 +5935,11 @@ A jump table for the options with a short description can be found at |Q_op|. The file is used for all languages. expr:{expr} Evaluate expression {expr}. Use a function to avoid - trouble with spaces. |v:val| holds the badly spelled - word. The expression must evaluate to a List of - Lists, each with a suggestion and a score. + trouble with spaces. Best is to call a function + without arguments, see |expr-option-function|. + |v:val| holds the badly spelled word. The expression + must evaluate to a List of Lists, each with a + suggestion and a score. Example: [['the', 33], ['that', 44]] ~ Set 'verbose' and use |z=| to see the scores that the diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index ebb6ee2329..10c888548c 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -786,6 +786,9 @@ vim.bo.channel = vim.o.channel --- v:fname_out name of the output file --- Note that v:fname_in and v:fname_out will never be the same. --- +--- The advantage of using a function call without arguments is that it is +--- faster, see `expr-option-function`. +--- --- If the 'charconvert' expression starts with s: or `<SID>`, then it is --- replaced with the script ID (`local-function`). Example: --- @@ -2521,6 +2524,9 @@ vim.wo.fdt = vim.wo.foldtext --- This will invoke the mylang#Format() function in the --- autoload/mylang.vim file in 'runtimepath'. `autoload` --- +--- The advantage of using a function call without arguments is that it is +--- faster, see `expr-option-function`. +--- --- The expression is also evaluated when 'textwidth' is set and adding --- text beyond that limit. This happens under the same conditions as --- when internal formatting is used. Make sure the cursor is kept in the @@ -3286,12 +3292,15 @@ vim.go.inc = vim.go.include --- the script ID (`local-function`). Example: --- --- ```vim ---- setlocal includeexpr=s:MyIncludeExpr(v:fname) ---- setlocal includeexpr=<SID>SomeIncludeExpr(v:fname) +--- setlocal includeexpr=s:MyIncludeExpr() +--- setlocal includeexpr=<SID>SomeIncludeExpr() --- ``` --- Otherwise, the expression is evaluated in the context of the script --- where the option was set, thus script-local items are available. --- +--- It is more efficient if the value is just a function call without +--- arguments, see `expr-option-function`. +--- --- The expression will be evaluated in the `sandbox` when set from a --- modeline, see `sandbox-option`. --- This option cannot be set in a modeline when 'modelineexpr' is off. @@ -3366,6 +3375,9 @@ vim.go.is = vim.go.incsearch --- Otherwise, the expression is evaluated in the context of the script --- where the option was set, thus script-local items are available. --- +--- The advantage of using a function call without arguments is that it is +--- faster, see `expr-option-function`. +--- --- The expression must return the number of spaces worth of indent. It --- can return "-1" to keep the current indent (this means 'autoindent' is --- used for the indent). @@ -6314,9 +6326,11 @@ vim.bo.spo = vim.bo.spelloptions --- The file is used for all languages. --- --- expr:{expr} Evaluate expression {expr}. Use a function to avoid ---- trouble with spaces. `v:val` holds the badly spelled ---- word. The expression must evaluate to a List of ---- Lists, each with a suggestion and a score. +--- trouble with spaces. Best is to call a function +--- without arguments, see `expr-option-function|. +--- |v:val` holds the badly spelled word. The expression +--- must evaluate to a List of Lists, each with a +--- suggestion and a score. --- Example: --- [['the', 33], ['that', 44]] ~ --- Set 'verbose' and use `z=` to see the scores that the diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c index 26fb77df30..8149c5964f 100644 --- a/src/nvim/digraph.c +++ b/src/nvim/digraph.c @@ -2198,7 +2198,7 @@ bool get_keymap_str(win_T *wp, char *fmt, char *buf, int len) curwin = wp; STRCPY(buf, "b:keymap_name"); // must be writable emsg_skip++; - char *s = p = eval_to_string(buf, false); + char *s = p = eval_to_string(buf, false, false); emsg_skip--; curbuf = old_curbuf; curwin = old_curwin; diff --git a/src/nvim/eval.c b/src/nvim/eval.c index c8451b7a28..6b4f49b6cb 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -703,7 +703,7 @@ int eval_charconvert(const char *const enc_from, const char *const enc_to, } bool err = false; - if (eval_to_bool(p_ccv, &err, NULL, false)) { + if (eval_to_bool(p_ccv, &err, NULL, false, true)) { err = true; } @@ -732,7 +732,7 @@ void eval_diff(const char *const origfile, const char *const newfile, const char } // errors are ignored - typval_T *tv = eval_expr(p_dex, NULL); + typval_T *tv = eval_expr_ext(p_dex, NULL, true); tv_free(tv); set_vim_var_string(VV_FNAME_IN, NULL, -1); @@ -754,7 +754,7 @@ void eval_patch(const char *const origfile, const char *const difffile, const ch } // errors are ignored - typval_T *tv = eval_expr(p_pex, NULL); + typval_T *tv = eval_expr_ext(p_pex, NULL, true); tv_free(tv); set_vim_var_string(VV_FNAME_IN, NULL, -1); @@ -783,7 +783,8 @@ void fill_evalarg_from_eap(evalarg_T *evalarg, exarg_T *eap, bool skip) /// @param skip only parse, don't execute /// /// @return true or false. -bool eval_to_bool(char *arg, bool *error, exarg_T *eap, bool skip) +bool eval_to_bool(char *arg, bool *error, exarg_T *eap, const bool skip, + const bool use_simple_function) { typval_T tv; bool retval = false; @@ -794,7 +795,9 @@ bool eval_to_bool(char *arg, bool *error, exarg_T *eap, bool skip) if (skip) { emsg_skip++; } - if (eval0(arg, &tv, eap, &evalarg) == FAIL) { + int r = use_simple_function ? eval0_simple_funccal(arg, &tv, eap, &evalarg) + : eval0(arg, &tv, eap, &evalarg); + if (r == FAIL) { *error = true; } else { *error = false; @@ -1042,14 +1045,17 @@ static char *typval2string(typval_T *tv, bool join_list) /// @param join_list when true convert a List into a sequence of lines. /// /// @return pointer to allocated memory, or NULL for failure. -char *eval_to_string_eap(char *arg, bool join_list, exarg_T *eap) +char *eval_to_string_eap(char *arg, const bool join_list, exarg_T *eap, + const bool use_simple_function) { typval_T tv; char *retval; evalarg_T evalarg; fill_evalarg_from_eap(&evalarg, eap, eap != NULL && eap->skip); - if (eval0(arg, &tv, NULL, &evalarg) == FAIL) { + int r = use_simple_function ? eval0_simple_funccal(arg, &tv, NULL, &evalarg) + : eval0(arg, &tv, NULL, &evalarg); + if (r == FAIL) { retval = NULL; } else { retval = typval2string(&tv, join_list); @@ -1060,16 +1066,16 @@ char *eval_to_string_eap(char *arg, bool join_list, exarg_T *eap) return retval; } -char *eval_to_string(char *arg, bool join_list) +char *eval_to_string(char *arg, const bool join_list, const bool use_simple_function) { - return eval_to_string_eap(arg, join_list, NULL); + return eval_to_string_eap(arg, join_list, NULL, use_simple_function); } /// Call eval_to_string() without using current local variables and using /// textlock. /// /// @param use_sandbox when true, use the sandbox. -char *eval_to_string_safe(char *arg, const bool use_sandbox) +char *eval_to_string_safe(char *arg, const bool use_sandbox, const bool use_simple_function) { char *retval; funccal_entry_T funccal_entry; @@ -1079,7 +1085,7 @@ char *eval_to_string_safe(char *arg, const bool use_sandbox) sandbox++; } textlock++; - retval = eval_to_string(arg, false); + retval = eval_to_string(arg, false, use_simple_function); if (use_sandbox) { sandbox--; } @@ -1092,15 +1098,22 @@ char *eval_to_string_safe(char *arg, const bool use_sandbox) /// Evaluates "expr" silently. /// /// @return -1 for an error. -varnumber_T eval_to_number(char *expr) +varnumber_T eval_to_number(char *expr, const bool use_simple_function) { typval_T rettv; varnumber_T retval; char *p = skipwhite(expr); + int r = NOTDONE; emsg_off++; - if (eval1(&p, &rettv, &EVALARG_EVALUATE) == FAIL) { + if (use_simple_function) { + r = may_call_simple_func(expr, &rettv); + } + if (r == NOTDONE) { + r = eval1(&p, &rettv, &EVALARG_EVALUATE); + } + if (r == FAIL) { retval = -1; } else { retval = tv_get_number_chk(&rettv, NULL); @@ -1117,12 +1130,26 @@ varnumber_T eval_to_number(char *expr) /// NULL when there is an error. typval_T *eval_expr(char *arg, exarg_T *eap) { + return eval_expr_ext(arg, eap, false); +} + +static typval_T *eval_expr_ext(char *arg, exarg_T *eap, const bool use_simple_function) +{ typval_T *tv = xmalloc(sizeof(*tv)); evalarg_T evalarg; fill_evalarg_from_eap(&evalarg, eap, eap != NULL && eap->skip); - if (eval0(arg, tv, eap, &evalarg) == FAIL) { + int r = NOTDONE; + + if (use_simple_function) { + r = eval0_simple_funccal(arg, tv, eap, &evalarg); + } + if (r == NOTDONE) { + r = eval0(arg, tv, eap, &evalarg); + } + + if (r == FAIL) { XFREE_CLEAR(tv); } @@ -1208,7 +1235,11 @@ list_T *eval_spell_expr(char *badword, char *expr) current_sctx = *ctx; } - if (eval1(&p, &rettv, &EVALARG_EVALUATE) == OK) { + int r = may_call_simple_func(p, &rettv); + if (r == NOTDONE) { + r = eval1(&p, &rettv, &EVALARG_EVALUATE); + } + if (r == OK) { if (rettv.v_type != VAR_LIST) { tv_clear(&rettv); } else { @@ -1360,23 +1391,10 @@ 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 (r == FAIL) { + // Evaluate the expression. If the expression is "FuncName()" call the + // function directly. + if (eval0_simple_funccal(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL) { retval = 0; } else { // If the result is a number, just return the number. @@ -1422,7 +1440,7 @@ Object eval_foldtext(win_T *wp) typval_T tv; Object retval; - if (eval0(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL) { + if (eval0_simple_funccal(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL) { retval = STRING_OBJ(NULL_STRING); } else { if (tv.v_type == VAR_LIST) { @@ -2539,9 +2557,10 @@ void clear_evalarg(evalarg_T *evalarg, exarg_T *eap) } } -/// The "evaluate" argument: When false, the argument is only parsed but not -/// executed. The function may return OK, but the rettv will be of type -/// VAR_UNKNOWN. The function still returns FAIL for a syntax error. +/// The "eval" functions have an "evalarg" argument: When NULL or +/// "evalarg->eval_flags" does not have EVAL_EVALUATE, then the argument is only +/// parsed but not executed. The functions may return OK, but the rettv will be +/// of type VAR_UNKNOWN. The functions still returns FAIL for a syntax error. /// Handle zero level expression. /// This calls eval1() and handles error message and nextcmd. @@ -2600,6 +2619,35 @@ int eval0(char *arg, typval_T *rettv, exarg_T *eap, evalarg_T *const evalarg) return ret; } +/// If "arg" is a simple function call without arguments then call it and return +/// the result. Otherwise return NOTDONE. +static int may_call_simple_func(char *arg, typval_T *rettv) +{ + char *parens = strstr(arg, "()"); + int r = NOTDONE; + + // If the expression is "FuncName()" then we can skip a lot of overhead. + 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), rettv); + } + } + return r; +} + +/// Handle zero level expression with optimization for a simple function call. +/// Same arguments and return value as eval0(). +static int eval0_simple_funccal(char *arg, typval_T *rettv, exarg_T *eap, evalarg_T *const evalarg) +{ + int r = may_call_simple_func(arg, rettv); + + if (r == NOTDONE) { + r = eval0(arg, rettv, eap, evalarg); + } + return r; +} + /// Handle top level expression: /// expr2 ? expr1 : expr1 /// expr2 ?? expr1 @@ -7412,7 +7460,7 @@ static char *make_expanded_name(const char *in_start, char *expr_start, char *ex char c1 = *in_end; *in_end = NUL; - char *temp_result = eval_to_string(expr_start + 1, false); + char *temp_result = eval_to_string(expr_start + 1, false, false); if (temp_result != NULL) { retval = xmalloc(strlen(temp_result) + (size_t)(expr_start - in_start) + (size_t)(in_end - expr_end) + 1); diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 2dca942bb5..3a5d056a9a 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -89,7 +89,7 @@ char *eval_one_expr_in_str(char *p, garray_T *gap, bool evaluate) } if (evaluate) { *block_end = NUL; - char *expr_val = eval_to_string(block_start, false); + char *expr_val = eval_to_string(block_start, false, false); *block_end = '}'; if (expr_val == NULL) { return NULL; diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index e384627fec..2142199c8a 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -4644,7 +4644,7 @@ static void ex_colorscheme(exarg_T *eap) char *expr = xstrdup("g:colors_name"); emsg_off++; - char *p = eval_to_string(expr, false); + char *p = eval_to_string(expr, false, false); emsg_off--; xfree(expr); diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index 6e7c1ff21c..f9936dd88e 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -849,7 +849,7 @@ void ex_if(exarg_T *eap) bool skip = CHECK_SKIP; bool error; - bool result = eval_to_bool(eap->arg, &error, eap, skip); + bool result = eval_to_bool(eap->arg, &error, eap, skip, false); if (!skip && !error) { if (result) { @@ -944,7 +944,7 @@ void ex_else(exarg_T *eap) if (skip && *eap->arg != '"' && ends_excmd(*eap->arg)) { semsg(_(e_invexpr2), eap->arg); } else { - result = eval_to_bool(eap->arg, &error, eap, skip); + result = eval_to_bool(eap->arg, &error, eap, skip, false); } // When throwing error exceptions, we want to throw always the first @@ -990,7 +990,7 @@ void ex_while(exarg_T *eap) int skip = CHECK_SKIP; if (eap->cmdidx == CMD_while) { // ":while bool-expr" - result = eval_to_bool(eap->arg, &error, eap, skip); + result = eval_to_bool(eap->arg, &error, eap, skip, false); } else { // ":for var in list-expr" evalarg_T evalarg; fill_evalarg_from_eap(&evalarg, eap, skip); diff --git a/src/nvim/indent.c b/src/nvim/indent.c index 66cb443e4d..2f994036ad 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -1161,7 +1161,7 @@ int get_expr_indent(void) // Need to make a copy, the 'indentexpr' option could be changed while // evaluating it. char *inde_copy = xstrdup(curbuf->b_p_inde); - int indent = (int)eval_to_number(inde_copy); + int indent = (int)eval_to_number(inde_copy, true); xfree(inde_copy); if (use_sandbox) { diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 7ca3f534b0..7c69ccbb1e 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -1656,7 +1656,7 @@ char *eval_map_expr(mapblock_T *mp, int c) api_clear_error(&err); } } else { - p = eval_to_string(expr, false); + p = eval_to_string(expr, false, false); xfree(expr); } expr_map_lock--; diff --git a/src/nvim/ops.c b/src/nvim/ops.c index a71317d75d..e418635d37 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -734,7 +734,7 @@ char *get_expr_line(void) } nested++; - char *rv = eval_to_string(expr_copy, true); + char *rv = eval_to_string(expr_copy, true, false); nested--; xfree(expr_copy); return rv; diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 7268a4351d..8506d0998a 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -1059,6 +1059,9 @@ return { v:fname_out name of the output file Note that v:fname_in and v:fname_out will never be the same. + The advantage of using a function call without arguments is that it is + faster, see |expr-option-function|. + If the 'charconvert' expression starts with s: or |<SID>|, then it is replaced with the script ID (|local-function|). Example: >vim set charconvert=s:MyConvert() @@ -3231,6 +3234,9 @@ return { < This will invoke the mylang#Format() function in the autoload/mylang.vim file in 'runtimepath'. |autoload| + The advantage of using a function call without arguments is that it is + faster, see |expr-option-function|. + The expression is also evaluated when 'textwidth' is set and adding text beyond that limit. This happens under the same conditions as when internal formatting is used. Make sure the cursor is kept in the @@ -4165,11 +4171,14 @@ return { If the expression starts with s: or |<SID>|, then it is replaced with the script ID (|local-function|). Example: >vim - setlocal includeexpr=s:MyIncludeExpr(v:fname) - setlocal includeexpr=<SID>SomeIncludeExpr(v:fname) + setlocal includeexpr=s:MyIncludeExpr() + setlocal includeexpr=<SID>SomeIncludeExpr() < Otherwise, the expression is evaluated in the context of the script where the option was set, thus script-local items are available. + It is more efficient if the value is just a function call without + arguments, see |expr-option-function|. + The expression will be evaluated in the |sandbox| when set from a modeline, see |sandbox-option|. This option cannot be set in a modeline when 'modelineexpr' is off. @@ -4249,6 +4258,9 @@ return { < Otherwise, the expression is evaluated in the context of the script where the option was set, thus script-local items are available. + The advantage of using a function call without arguments is that it is + faster, see |expr-option-function|. + The expression must return the number of spaces worth of indent. It can return "-1" to keep the current indent (this means 'autoindent' is used for the indent). @@ -7949,9 +7961,11 @@ return { The file is used for all languages. expr:{expr} Evaluate expression {expr}. Use a function to avoid - trouble with spaces. |v:val| holds the badly spelled - word. The expression must evaluate to a List of - Lists, each with a suggestion and a score. + trouble with spaces. Best is to call a function + without arguments, see |expr-option-function|. + |v:val| holds the badly spelled word. The expression + must evaluate to a List of Lists, each with a + suggestion and a score. Example: [['the', 33], ['that', 44]] ~ Set 'verbose' and use |z=| to see the scores that the diff --git a/src/nvim/path.c b/src/nvim/path.c index adea7ff0f7..67acc6e51b 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -1398,7 +1398,7 @@ static int expand_backtick(garray_T *gap, char *pat, int flags) char *cmd = xmemdupz(pat + 1, strlen(pat) - 2); if (*cmd == '=') { // `={expr}`: Expand expression - buffer = eval_to_string(cmd + 1, true); + buffer = eval_to_string(cmd + 1, true, false); } else { buffer = get_cmd_output(cmd, NULL, (flags & EW_SILENT) ? kShellOptSilent : 0, NULL); } @@ -1694,7 +1694,8 @@ static char *eval_includeexpr(const char *const ptr, const size_t len) current_sctx = curbuf->b_p_script_ctx[BV_INEX].script_ctx; char *res = eval_to_string_safe(curbuf->b_p_inex, - was_set_insecurely(curwin, kOptIncludeexpr, OPT_LOCAL)); + was_set_insecurely(curwin, kOptIncludeexpr, OPT_LOCAL), + true); set_vim_var_string(VV_FNAME, NULL, 0); current_sctx = save_sctx; diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 40c95eb221..e79c0c6259 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -2194,7 +2194,7 @@ static int vim_regsub_both(char *source, typval_T *expr, char *dest, int destlen } tv_clear(&rettv); } else { - eval_result[nested] = eval_to_string(source + 2, true); + eval_result[nested] = eval_to_string(source + 2, true, false); } nesting--; diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 2cae79c0fd..3aa558f305 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -1100,7 +1100,7 @@ static int load_pack_plugin(bool opt, char *fname) // If runtime/filetype.lua wasn't loaded yet, the scripts will be // found when it loads. - if (opt && eval_to_number(cmd) > 0) { + if (opt && eval_to_number(cmd, false) > 0) { do_cmdline_cmd("augroup filetypedetect"); vim_snprintf(pat, len, ftpat, ffname); gen_expand_wildcards_and_cb(1, &pat, EW_FILE, true, source_callback_vim_lua, NULL); diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index e94e33eebc..099ed37c12 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -954,7 +954,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op }; set_var(S_LEN("g:statusline_winid"), &tv, false); - usefmt = eval_to_string_safe(fmt + 2, use_sandbox); + usefmt = eval_to_string_safe(fmt + 2, use_sandbox, false); if (usefmt == NULL) { usefmt = fmt; } @@ -1429,7 +1429,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op } // Note: The result stored in `t` is unused. - str = eval_to_string_safe(out_p, use_sandbox); + str = eval_to_string_safe(out_p, use_sandbox, false); curwin = save_curwin; curbuf = save_curbuf; diff --git a/src/nvim/textformat.c b/src/nvim/textformat.c index 13607da043..96907362dd 100644 --- a/src/nvim/textformat.c +++ b/src/nvim/textformat.c @@ -869,7 +869,7 @@ int fex_format(linenr_T lnum, long count, int c) if (use_sandbox) { sandbox++; } - int r = (int)eval_to_number(fex); + int r = (int)eval_to_number(fex, true); if (use_sandbox) { sandbox--; } |