mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
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'.a4e0b9785e
vim-patch:9.0.0635: build error and compiler warnings Problem: Build error and compiler warnings. Solution: Add missing change. Add type casts.3292a22940
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
parent
f7fde0173a
commit
582bf4f1e1
@ -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
|
'diffopt' option. 'diffexpr' cannot change the value of 'lines' and
|
||||||
'columns'.
|
'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): >
|
Example (this does almost the same as 'diffexpr' being empty): >
|
||||||
|
|
||||||
set diffexpr=MyDiff()
|
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_diff patch file
|
||||||
v:fname_out resulting patched 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): >
|
Example (this does the same as 'patchexpr' being empty): >
|
||||||
|
|
||||||
set patchexpr=MyPatch()
|
set patchexpr=MyPatch()
|
||||||
|
@ -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
|
v:fname_out name of the output file
|
||||||
Note that v:fname_in and v:fname_out will never be the same.
|
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
|
If the 'charconvert' expression starts with s: or |<SID>|, then it is
|
||||||
replaced with the script ID (|local-function|). Example: >vim
|
replaced with the script ID (|local-function|). Example: >vim
|
||||||
set charconvert=s:MyConvert()
|
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
|
< This will invoke the mylang#Format() function in the
|
||||||
autoload/mylang.vim file in 'runtimepath'. |autoload|
|
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
|
The expression is also evaluated when 'textwidth' is set and adding
|
||||||
text beyond that limit. This happens under the same conditions as
|
text beyond that limit. This happens under the same conditions as
|
||||||
when internal formatting is used. Make sure the cursor is kept in the
|
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
|
If the expression starts with s: or |<SID>|, then it is replaced with
|
||||||
the script ID (|local-function|). Example: >vim
|
the script ID (|local-function|). Example: >vim
|
||||||
setlocal includeexpr=s:MyIncludeExpr(v:fname)
|
setlocal includeexpr=s:MyIncludeExpr()
|
||||||
setlocal includeexpr=<SID>SomeIncludeExpr(v:fname)
|
setlocal includeexpr=<SID>SomeIncludeExpr()
|
||||||
< Otherwise, the expression is evaluated in the context of the script
|
< Otherwise, the expression is evaluated in the context of the script
|
||||||
where the option was set, thus script-local items are available.
|
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
|
The expression will be evaluated in the |sandbox| when set from a
|
||||||
modeline, see |sandbox-option|.
|
modeline, see |sandbox-option|.
|
||||||
This option cannot be set in a modeline when 'modelineexpr' is off.
|
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
|
< Otherwise, the expression is evaluated in the context of the script
|
||||||
where the option was set, thus script-local items are available.
|
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
|
The expression must return the number of spaces worth of indent. It
|
||||||
can return "-1" to keep the current indent (this means 'autoindent' is
|
can return "-1" to keep the current indent (this means 'autoindent' is
|
||||||
used for the indent).
|
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.
|
The file is used for all languages.
|
||||||
|
|
||||||
expr:{expr} Evaluate expression {expr}. Use a function to avoid
|
expr:{expr} Evaluate expression {expr}. Use a function to avoid
|
||||||
trouble with spaces. |v:val| holds the badly spelled
|
trouble with spaces. Best is to call a function
|
||||||
word. The expression must evaluate to a List of
|
without arguments, see |expr-option-function|.
|
||||||
Lists, each with a suggestion and a score.
|
|v:val| holds the badly spelled word. The expression
|
||||||
|
must evaluate to a List of Lists, each with a
|
||||||
|
suggestion and a score.
|
||||||
Example:
|
Example:
|
||||||
[['the', 33], ['that', 44]] ~
|
[['the', 33], ['that', 44]] ~
|
||||||
Set 'verbose' and use |z=| to see the scores that the
|
Set 'verbose' and use |z=| to see the scores that the
|
||||||
|
24
runtime/lua/vim/_meta/options.lua
generated
24
runtime/lua/vim/_meta/options.lua
generated
@ -786,6 +786,9 @@ vim.bo.channel = vim.o.channel
|
|||||||
--- v:fname_out name of the output file
|
--- v:fname_out name of the output file
|
||||||
--- Note that v:fname_in and v:fname_out will never be the same.
|
--- 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
|
--- If the 'charconvert' expression starts with s: or `<SID>`, then it is
|
||||||
--- replaced with the script ID (`local-function`). Example:
|
--- 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
|
--- This will invoke the mylang#Format() function in the
|
||||||
--- autoload/mylang.vim file in 'runtimepath'. `autoload`
|
--- 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
|
--- The expression is also evaluated when 'textwidth' is set and adding
|
||||||
--- text beyond that limit. This happens under the same conditions as
|
--- text beyond that limit. This happens under the same conditions as
|
||||||
--- when internal formatting is used. Make sure the cursor is kept in the
|
--- 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:
|
--- the script ID (`local-function`). Example:
|
||||||
---
|
---
|
||||||
--- ```vim
|
--- ```vim
|
||||||
--- setlocal includeexpr=s:MyIncludeExpr(v:fname)
|
--- setlocal includeexpr=s:MyIncludeExpr()
|
||||||
--- setlocal includeexpr=<SID>SomeIncludeExpr(v:fname)
|
--- setlocal includeexpr=<SID>SomeIncludeExpr()
|
||||||
--- ```
|
--- ```
|
||||||
--- Otherwise, the expression is evaluated in the context of the script
|
--- Otherwise, the expression is evaluated in the context of the script
|
||||||
--- where the option was set, thus script-local items are available.
|
--- 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
|
--- The expression will be evaluated in the `sandbox` when set from a
|
||||||
--- modeline, see `sandbox-option`.
|
--- modeline, see `sandbox-option`.
|
||||||
--- This option cannot be set in a modeline when 'modelineexpr' is off.
|
--- 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
|
--- Otherwise, the expression is evaluated in the context of the script
|
||||||
--- where the option was set, thus script-local items are available.
|
--- 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
|
--- The expression must return the number of spaces worth of indent. It
|
||||||
--- can return "-1" to keep the current indent (this means 'autoindent' is
|
--- can return "-1" to keep the current indent (this means 'autoindent' is
|
||||||
--- used for the indent).
|
--- used for the indent).
|
||||||
@ -6314,9 +6326,11 @@ vim.bo.spo = vim.bo.spelloptions
|
|||||||
--- The file is used for all languages.
|
--- The file is used for all languages.
|
||||||
---
|
---
|
||||||
--- expr:{expr} Evaluate expression {expr}. Use a function to avoid
|
--- expr:{expr} Evaluate expression {expr}. Use a function to avoid
|
||||||
--- trouble with spaces. `v:val` holds the badly spelled
|
--- trouble with spaces. Best is to call a function
|
||||||
--- word. The expression must evaluate to a List of
|
--- without arguments, see `expr-option-function|.
|
||||||
--- Lists, each with a suggestion and a score.
|
--- |v:val` holds the badly spelled word. The expression
|
||||||
|
--- must evaluate to a List of Lists, each with a
|
||||||
|
--- suggestion and a score.
|
||||||
--- Example:
|
--- Example:
|
||||||
--- [['the', 33], ['that', 44]] ~
|
--- [['the', 33], ['that', 44]] ~
|
||||||
--- Set 'verbose' and use `z=` to see the scores that the
|
--- Set 'verbose' and use `z=` to see the scores that the
|
||||||
|
@ -2198,7 +2198,7 @@ bool get_keymap_str(win_T *wp, char *fmt, char *buf, int len)
|
|||||||
curwin = wp;
|
curwin = wp;
|
||||||
STRCPY(buf, "b:keymap_name"); // must be writable
|
STRCPY(buf, "b:keymap_name"); // must be writable
|
||||||
emsg_skip++;
|
emsg_skip++;
|
||||||
char *s = p = eval_to_string(buf, false);
|
char *s = p = eval_to_string(buf, false, false);
|
||||||
emsg_skip--;
|
emsg_skip--;
|
||||||
curbuf = old_curbuf;
|
curbuf = old_curbuf;
|
||||||
curwin = old_curwin;
|
curwin = old_curwin;
|
||||||
|
120
src/nvim/eval.c
120
src/nvim/eval.c
@ -703,7 +703,7 @@ int eval_charconvert(const char *const enc_from, const char *const enc_to,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool err = false;
|
bool err = false;
|
||||||
if (eval_to_bool(p_ccv, &err, NULL, false)) {
|
if (eval_to_bool(p_ccv, &err, NULL, false, true)) {
|
||||||
err = true;
|
err = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -732,7 +732,7 @@ void eval_diff(const char *const origfile, const char *const newfile, const char
|
|||||||
}
|
}
|
||||||
|
|
||||||
// errors are ignored
|
// errors are ignored
|
||||||
typval_T *tv = eval_expr(p_dex, NULL);
|
typval_T *tv = eval_expr_ext(p_dex, NULL, true);
|
||||||
tv_free(tv);
|
tv_free(tv);
|
||||||
|
|
||||||
set_vim_var_string(VV_FNAME_IN, NULL, -1);
|
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
|
// errors are ignored
|
||||||
typval_T *tv = eval_expr(p_pex, NULL);
|
typval_T *tv = eval_expr_ext(p_pex, NULL, true);
|
||||||
tv_free(tv);
|
tv_free(tv);
|
||||||
|
|
||||||
set_vim_var_string(VV_FNAME_IN, NULL, -1);
|
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
|
/// @param skip only parse, don't execute
|
||||||
///
|
///
|
||||||
/// @return true or false.
|
/// @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;
|
typval_T tv;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
@ -794,7 +795,9 @@ bool eval_to_bool(char *arg, bool *error, exarg_T *eap, bool skip)
|
|||||||
if (skip) {
|
if (skip) {
|
||||||
emsg_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;
|
*error = true;
|
||||||
} else {
|
} else {
|
||||||
*error = false;
|
*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.
|
/// @param join_list when true convert a List into a sequence of lines.
|
||||||
///
|
///
|
||||||
/// @return pointer to allocated memory, or NULL for failure.
|
/// @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;
|
typval_T tv;
|
||||||
char *retval;
|
char *retval;
|
||||||
|
|
||||||
evalarg_T evalarg;
|
evalarg_T evalarg;
|
||||||
fill_evalarg_from_eap(&evalarg, eap, eap != NULL && eap->skip);
|
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;
|
retval = NULL;
|
||||||
} else {
|
} else {
|
||||||
retval = typval2string(&tv, join_list);
|
retval = typval2string(&tv, join_list);
|
||||||
@ -1060,16 +1066,16 @@ char *eval_to_string_eap(char *arg, bool join_list, exarg_T *eap)
|
|||||||
return retval;
|
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
|
/// Call eval_to_string() without using current local variables and using
|
||||||
/// textlock.
|
/// textlock.
|
||||||
///
|
///
|
||||||
/// @param use_sandbox when true, use the sandbox.
|
/// @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;
|
char *retval;
|
||||||
funccal_entry_T funccal_entry;
|
funccal_entry_T funccal_entry;
|
||||||
@ -1079,7 +1085,7 @@ char *eval_to_string_safe(char *arg, const bool use_sandbox)
|
|||||||
sandbox++;
|
sandbox++;
|
||||||
}
|
}
|
||||||
textlock++;
|
textlock++;
|
||||||
retval = eval_to_string(arg, false);
|
retval = eval_to_string(arg, false, use_simple_function);
|
||||||
if (use_sandbox) {
|
if (use_sandbox) {
|
||||||
sandbox--;
|
sandbox--;
|
||||||
}
|
}
|
||||||
@ -1092,15 +1098,22 @@ char *eval_to_string_safe(char *arg, const bool use_sandbox)
|
|||||||
/// Evaluates "expr" silently.
|
/// Evaluates "expr" silently.
|
||||||
///
|
///
|
||||||
/// @return -1 for an error.
|
/// @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;
|
typval_T rettv;
|
||||||
varnumber_T retval;
|
varnumber_T retval;
|
||||||
char *p = skipwhite(expr);
|
char *p = skipwhite(expr);
|
||||||
|
int r = NOTDONE;
|
||||||
|
|
||||||
emsg_off++;
|
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;
|
retval = -1;
|
||||||
} else {
|
} else {
|
||||||
retval = tv_get_number_chk(&rettv, NULL);
|
retval = tv_get_number_chk(&rettv, NULL);
|
||||||
@ -1116,13 +1129,27 @@ varnumber_T eval_to_number(char *expr)
|
|||||||
/// @return an allocated typval_T with the result or
|
/// @return an allocated typval_T with the result or
|
||||||
/// NULL when there is an error.
|
/// NULL when there is an error.
|
||||||
typval_T *eval_expr(char *arg, exarg_T *eap)
|
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));
|
typval_T *tv = xmalloc(sizeof(*tv));
|
||||||
evalarg_T evalarg;
|
evalarg_T evalarg;
|
||||||
|
|
||||||
fill_evalarg_from_eap(&evalarg, eap, eap != NULL && eap->skip);
|
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);
|
XFREE_CLEAR(tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1208,7 +1235,11 @@ list_T *eval_spell_expr(char *badword, char *expr)
|
|||||||
current_sctx = *ctx;
|
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) {
|
if (rettv.v_type != VAR_LIST) {
|
||||||
tv_clear(&rettv);
|
tv_clear(&rettv);
|
||||||
} else {
|
} else {
|
||||||
@ -1360,23 +1391,10 @@ int eval_foldexpr(win_T *wp, int *cp)
|
|||||||
*cp = NUL;
|
*cp = NUL;
|
||||||
|
|
||||||
typval_T tv;
|
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;
|
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;
|
retval = 0;
|
||||||
} else {
|
} else {
|
||||||
// If the result is a number, just return the number.
|
// If the result is a number, just return the number.
|
||||||
@ -1422,7 +1440,7 @@ Object eval_foldtext(win_T *wp)
|
|||||||
|
|
||||||
typval_T tv;
|
typval_T tv;
|
||||||
Object retval;
|
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);
|
retval = STRING_OBJ(NULL_STRING);
|
||||||
} else {
|
} else {
|
||||||
if (tv.v_type == VAR_LIST) {
|
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
|
/// The "eval" functions have an "evalarg" argument: When NULL or
|
||||||
/// executed. The function may return OK, but the rettv will be of type
|
/// "evalarg->eval_flags" does not have EVAL_EVALUATE, then the argument is only
|
||||||
/// VAR_UNKNOWN. The function still returns FAIL for a syntax error.
|
/// 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.
|
/// Handle zero level expression.
|
||||||
/// This calls eval1() and handles error message and nextcmd.
|
/// 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;
|
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:
|
/// Handle top level expression:
|
||||||
/// expr2 ? expr1 : expr1
|
/// expr2 ? expr1 : expr1
|
||||||
/// expr2 ?? 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;
|
char c1 = *in_end;
|
||||||
*in_end = NUL;
|
*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) {
|
if (temp_result != NULL) {
|
||||||
retval = xmalloc(strlen(temp_result) + (size_t)(expr_start - in_start)
|
retval = xmalloc(strlen(temp_result) + (size_t)(expr_start - in_start)
|
||||||
+ (size_t)(in_end - expr_end) + 1);
|
+ (size_t)(in_end - expr_end) + 1);
|
||||||
|
@ -89,7 +89,7 @@ char *eval_one_expr_in_str(char *p, garray_T *gap, bool evaluate)
|
|||||||
}
|
}
|
||||||
if (evaluate) {
|
if (evaluate) {
|
||||||
*block_end = NUL;
|
*block_end = NUL;
|
||||||
char *expr_val = eval_to_string(block_start, false);
|
char *expr_val = eval_to_string(block_start, false, false);
|
||||||
*block_end = '}';
|
*block_end = '}';
|
||||||
if (expr_val == NULL) {
|
if (expr_val == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -4644,7 +4644,7 @@ static void ex_colorscheme(exarg_T *eap)
|
|||||||
char *expr = xstrdup("g:colors_name");
|
char *expr = xstrdup("g:colors_name");
|
||||||
|
|
||||||
emsg_off++;
|
emsg_off++;
|
||||||
char *p = eval_to_string(expr, false);
|
char *p = eval_to_string(expr, false, false);
|
||||||
emsg_off--;
|
emsg_off--;
|
||||||
xfree(expr);
|
xfree(expr);
|
||||||
|
|
||||||
|
@ -849,7 +849,7 @@ void ex_if(exarg_T *eap)
|
|||||||
bool skip = CHECK_SKIP;
|
bool skip = CHECK_SKIP;
|
||||||
|
|
||||||
bool error;
|
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 (!skip && !error) {
|
||||||
if (result) {
|
if (result) {
|
||||||
@ -944,7 +944,7 @@ void ex_else(exarg_T *eap)
|
|||||||
if (skip && *eap->arg != '"' && ends_excmd(*eap->arg)) {
|
if (skip && *eap->arg != '"' && ends_excmd(*eap->arg)) {
|
||||||
semsg(_(e_invexpr2), eap->arg);
|
semsg(_(e_invexpr2), eap->arg);
|
||||||
} else {
|
} 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
|
// 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;
|
int skip = CHECK_SKIP;
|
||||||
if (eap->cmdidx == CMD_while) { // ":while bool-expr"
|
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"
|
} else { // ":for var in list-expr"
|
||||||
evalarg_T evalarg;
|
evalarg_T evalarg;
|
||||||
fill_evalarg_from_eap(&evalarg, eap, skip);
|
fill_evalarg_from_eap(&evalarg, eap, skip);
|
||||||
|
@ -1161,7 +1161,7 @@ int get_expr_indent(void)
|
|||||||
// Need to make a copy, the 'indentexpr' option could be changed while
|
// Need to make a copy, the 'indentexpr' option could be changed while
|
||||||
// evaluating it.
|
// evaluating it.
|
||||||
char *inde_copy = xstrdup(curbuf->b_p_inde);
|
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);
|
xfree(inde_copy);
|
||||||
|
|
||||||
if (use_sandbox) {
|
if (use_sandbox) {
|
||||||
|
@ -1656,7 +1656,7 @@ char *eval_map_expr(mapblock_T *mp, int c)
|
|||||||
api_clear_error(&err);
|
api_clear_error(&err);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p = eval_to_string(expr, false);
|
p = eval_to_string(expr, false, false);
|
||||||
xfree(expr);
|
xfree(expr);
|
||||||
}
|
}
|
||||||
expr_map_lock--;
|
expr_map_lock--;
|
||||||
|
@ -734,7 +734,7 @@ char *get_expr_line(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nested++;
|
nested++;
|
||||||
char *rv = eval_to_string(expr_copy, true);
|
char *rv = eval_to_string(expr_copy, true, false);
|
||||||
nested--;
|
nested--;
|
||||||
xfree(expr_copy);
|
xfree(expr_copy);
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -1059,6 +1059,9 @@ return {
|
|||||||
v:fname_out name of the output file
|
v:fname_out name of the output file
|
||||||
Note that v:fname_in and v:fname_out will never be the same.
|
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
|
If the 'charconvert' expression starts with s: or |<SID>|, then it is
|
||||||
replaced with the script ID (|local-function|). Example: >vim
|
replaced with the script ID (|local-function|). Example: >vim
|
||||||
set charconvert=s:MyConvert()
|
set charconvert=s:MyConvert()
|
||||||
@ -3231,6 +3234,9 @@ return {
|
|||||||
< This will invoke the mylang#Format() function in the
|
< This will invoke the mylang#Format() function in the
|
||||||
autoload/mylang.vim file in 'runtimepath'. |autoload|
|
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
|
The expression is also evaluated when 'textwidth' is set and adding
|
||||||
text beyond that limit. This happens under the same conditions as
|
text beyond that limit. This happens under the same conditions as
|
||||||
when internal formatting is used. Make sure the cursor is kept in the
|
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
|
If the expression starts with s: or |<SID>|, then it is replaced with
|
||||||
the script ID (|local-function|). Example: >vim
|
the script ID (|local-function|). Example: >vim
|
||||||
setlocal includeexpr=s:MyIncludeExpr(v:fname)
|
setlocal includeexpr=s:MyIncludeExpr()
|
||||||
setlocal includeexpr=<SID>SomeIncludeExpr(v:fname)
|
setlocal includeexpr=<SID>SomeIncludeExpr()
|
||||||
< Otherwise, the expression is evaluated in the context of the script
|
< Otherwise, the expression is evaluated in the context of the script
|
||||||
where the option was set, thus script-local items are available.
|
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
|
The expression will be evaluated in the |sandbox| when set from a
|
||||||
modeline, see |sandbox-option|.
|
modeline, see |sandbox-option|.
|
||||||
This option cannot be set in a modeline when 'modelineexpr' is off.
|
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
|
< Otherwise, the expression is evaluated in the context of the script
|
||||||
where the option was set, thus script-local items are available.
|
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
|
The expression must return the number of spaces worth of indent. It
|
||||||
can return "-1" to keep the current indent (this means 'autoindent' is
|
can return "-1" to keep the current indent (this means 'autoindent' is
|
||||||
used for the indent).
|
used for the indent).
|
||||||
@ -7949,9 +7961,11 @@ return {
|
|||||||
The file is used for all languages.
|
The file is used for all languages.
|
||||||
|
|
||||||
expr:{expr} Evaluate expression {expr}. Use a function to avoid
|
expr:{expr} Evaluate expression {expr}. Use a function to avoid
|
||||||
trouble with spaces. |v:val| holds the badly spelled
|
trouble with spaces. Best is to call a function
|
||||||
word. The expression must evaluate to a List of
|
without arguments, see |expr-option-function|.
|
||||||
Lists, each with a suggestion and a score.
|
|v:val| holds the badly spelled word. The expression
|
||||||
|
must evaluate to a List of Lists, each with a
|
||||||
|
suggestion and a score.
|
||||||
Example:
|
Example:
|
||||||
[['the', 33], ['that', 44]] ~
|
[['the', 33], ['that', 44]] ~
|
||||||
Set 'verbose' and use |z=| to see the scores that the
|
Set 'verbose' and use |z=| to see the scores that the
|
||||||
|
@ -1398,7 +1398,7 @@ static int expand_backtick(garray_T *gap, char *pat, int flags)
|
|||||||
char *cmd = xmemdupz(pat + 1, strlen(pat) - 2);
|
char *cmd = xmemdupz(pat + 1, strlen(pat) - 2);
|
||||||
|
|
||||||
if (*cmd == '=') { // `={expr}`: Expand expression
|
if (*cmd == '=') { // `={expr}`: Expand expression
|
||||||
buffer = eval_to_string(cmd + 1, true);
|
buffer = eval_to_string(cmd + 1, true, false);
|
||||||
} else {
|
} else {
|
||||||
buffer = get_cmd_output(cmd, NULL, (flags & EW_SILENT) ? kShellOptSilent : 0, NULL);
|
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;
|
current_sctx = curbuf->b_p_script_ctx[BV_INEX].script_ctx;
|
||||||
|
|
||||||
char *res = eval_to_string_safe(curbuf->b_p_inex,
|
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);
|
set_vim_var_string(VV_FNAME, NULL, 0);
|
||||||
current_sctx = save_sctx;
|
current_sctx = save_sctx;
|
||||||
|
@ -2194,7 +2194,7 @@ static int vim_regsub_both(char *source, typval_T *expr, char *dest, int destlen
|
|||||||
}
|
}
|
||||||
tv_clear(&rettv);
|
tv_clear(&rettv);
|
||||||
} else {
|
} else {
|
||||||
eval_result[nested] = eval_to_string(source + 2, true);
|
eval_result[nested] = eval_to_string(source + 2, true, false);
|
||||||
}
|
}
|
||||||
nesting--;
|
nesting--;
|
||||||
|
|
||||||
|
@ -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
|
// If runtime/filetype.lua wasn't loaded yet, the scripts will be
|
||||||
// found when it loads.
|
// found when it loads.
|
||||||
if (opt && eval_to_number(cmd) > 0) {
|
if (opt && eval_to_number(cmd, false) > 0) {
|
||||||
do_cmdline_cmd("augroup filetypedetect");
|
do_cmdline_cmd("augroup filetypedetect");
|
||||||
vim_snprintf(pat, len, ftpat, ffname);
|
vim_snprintf(pat, len, ftpat, ffname);
|
||||||
gen_expand_wildcards_and_cb(1, &pat, EW_FILE, true, source_callback_vim_lua, NULL);
|
gen_expand_wildcards_and_cb(1, &pat, EW_FILE, true, source_callback_vim_lua, NULL);
|
||||||
|
@ -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);
|
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) {
|
if (usefmt == NULL) {
|
||||||
usefmt = fmt;
|
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.
|
// 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;
|
curwin = save_curwin;
|
||||||
curbuf = save_curbuf;
|
curbuf = save_curbuf;
|
||||||
|
@ -869,7 +869,7 @@ int fex_format(linenr_T lnum, long count, int c)
|
|||||||
if (use_sandbox) {
|
if (use_sandbox) {
|
||||||
sandbox++;
|
sandbox++;
|
||||||
}
|
}
|
||||||
int r = (int)eval_to_number(fex);
|
int r = (int)eval_to_number(fex, true);
|
||||||
if (use_sandbox) {
|
if (use_sandbox) {
|
||||||
sandbox--;
|
sandbox--;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user