From f7fde0173af95925e7324b7d3c09776173dab8a7 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 1 Aug 2024 10:13:45 +0800 Subject: 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' https://github.com/vim/vim/commit/87b4e5c5db9d1cfd6f2e79656e1a6cff3c69d15f Cherry-pick a call_func() change from patch 8.2.1343. Add expr-option-function docs to options.txt. Co-authored-by: Bram Moolenaar --- runtime/doc/fold.txt | 6 ++++-- runtime/doc/options.txt | 8 ++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/fold.txt b/runtime/doc/fold.txt index 8f7393f5e3..b844e0ed85 100644 --- a/runtime/doc/fold.txt +++ b/runtime/doc/fold.txt @@ -69,8 +69,6 @@ method. The value of the 'foldexpr' option is evaluated to get the foldlevel of a line. Examples: This will create a fold for all consecutive lines that start with a tab: > :set foldexpr=getline(v:lnum)[0]==\"\\t\" -This will call a function to compute the fold level: > - :set foldexpr=MyFoldLevel(v:lnum) This will make a fold out of paragraphs separated by blank lines: > :set foldexpr=getline(v:lnum)=~'^\\s*$'&&getline(v:lnum+1)=~'\\S'?'<1':1 This does the same: > @@ -79,6 +77,10 @@ This does the same: > Note that backslashes must be used to escape characters that ":set" handles differently (space, backslash, double quote, etc., see |option-backslash|). +The most efficient is to call a function without arguments: > + :set foldexpr=MyFoldLevel() +The function must use v:lnum. See |expr-option-function|. + These are the conditions with which the expression is evaluated: - The current buffer and window are set for the line. - The variable "v:lnum" is set to the line number. diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 875767283a..a48d020a34 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -400,6 +400,14 @@ Set using a variable with lambda expression: > let L = {a, b, c -> MyTagFunc(a, b , c)} let &tagfunc = L +Calling a function in an expr option *expr-option-function* + +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. +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 +arguments. + Setting the filetype -- cgit From 582bf4f1e15988565da53a91395e2d0131628fbb Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 1 Aug 2024 10:41:08 +0800 Subject: 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 --- runtime/doc/diff.txt | 6 ++++++ runtime/doc/options.txt | 24 +++++++++++++++++++----- runtime/lua/vim/_meta/options.lua | 24 +++++++++++++++++++----- 3 files changed, 44 insertions(+), 10 deletions(-) (limited to 'runtime') 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 ||, 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 ||, then it is replaced with the script ID (|local-function|). Example: >vim - setlocal includeexpr=s:MyIncludeExpr(v:fname) - setlocal includeexpr=SomeIncludeExpr(v:fname) + setlocal includeexpr=s:MyIncludeExpr() + setlocal includeexpr=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 ``, 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=SomeIncludeExpr(v:fname) +--- setlocal includeexpr=s:MyIncludeExpr() +--- setlocal includeexpr=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 -- cgit From 99bb0a10d3400ee8b9b2773d51a957dacbf52b33 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 2 Aug 2024 12:16:04 +0800 Subject: refactor(eval): treat v:lua call as simple function --- runtime/doc/options.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'runtime') diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index b4eb3b6f28..bc2a8ae263 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -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. 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 -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 -- cgit