]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
runtime(doc): document how to minimize fold computation costs
authorKonfekt <Konfekt@users.noreply.github.com>
Mon, 16 Dec 2024 20:10:45 +0000 (21:10 +0100)
committerChristian Brabandt <cb@256bit.org>
Mon, 16 Dec 2024 20:11:55 +0000 (21:11 +0100)
closes: #16224

Signed-off-by: Konfekt <Konfekt@users.noreply.github.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime/doc/fold.txt
runtime/doc/tags

index b290492050508e4e1d26eaa98e5d9d4ffbc54fe6..61f3b67f393331de5a51d1127f87a41ea2d369ef 100644 (file)
@@ -1,4 +1,4 @@
-*fold.txt*      For Vim version 9.1.  Last change: 2023 Mar 24
+*fold.txt*      For Vim version 9.1.  Last change: 2024 Dec 16
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -87,9 +87,11 @@ The most efficient is to call a compiled function without arguments: >
 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.
-- The result is used for the fold level in this way:
+
+The result of foldexpr then determines the fold level as follows:
   value                        meaning ~
   0                    the line is not in a fold
   1, 2, ..             the line is in a fold with this level
@@ -104,6 +106,8 @@ These are the conditions with which the expression is evaluated:
   "<1", "<2", ..       a fold with this level ends at this line
   ">1", ">2", ..       a fold with this level starts at this line
 
+The result values "=", "s" and "a" are more expensive, please see |fold-expr-slow|.
+
 It is not required to mark the start (end) of a fold with ">1" ("<1"), a fold
 will also start (end) when the fold level is higher (lower) than the fold
 level of the previous line.
@@ -117,12 +121,6 @@ recognized, there is no error message and the fold level will be zero.
 For debugging the 'debug' option can be set to "msg", the error messages will
 be visible then.
 
-Note: Since the expression has to be evaluated for every line, this fold
-method can be very slow!
-
-Try to avoid the "=", "a" and "s" return values, since Vim often has to search
-backwards for a line for which the fold level is defined.  This can be slow.
-
 If the 'foldexpr' expression starts with s: or |<SID>|, then it is replaced
 with the script ID (|local-function|). Examples: >
                set foldexpr=s:MyFoldExpr()
@@ -148,6 +146,36 @@ end in that line.
 It may happen that folds are not updated properly.  You can use |zx| or |zX|
 to force updating folds.
 
+Minimizing Computational Cost                               *fold-expr-slow*
+
+Due to its computational cost, this fold method can make Vim unresponsive,
+especially when the fold level of all lines have to be initially computed.
+Afterwards, after each change, Vim restricts the computation of foldlevels
+to those lines whose fold level was affected by it (and reuses the known
+foldlevels of all the others).
+
+The fold expression should therefore strive to minimize the number of dependent
+lines needed for the computation of a given line: For example, try to avoid the
+"=", "a" and "s" return values, because these will require the evaluation of the
+fold levels on previous lines until an independent fold level is found.
+
+If this proves difficult, the next best thing could be to cache all fold levels
+in a buffer-local variable (b:foldlevels) that is only updated on |b:changedtick|: 
+>vim
+  vim9script
+  def MyFoldFunc(): number
+    if b:lasttick == b:changedtick
+      return b:foldlevels[v:lnum - 1]
+    endif
+    b:lasttick = b:changedtick
+    b:foldlevels = []
+    # compute foldlevels ...
+    return b:foldlevels[v:lnum - 1]
+  enddef
+  set foldexpr=s:MyFoldFunc()
+<
+In above example further speedup was gained by using a precompiled Vim9script
+function without arguments (that must still use v:lnum). See |expr-option-function|.
 
 SYNTAX                                         *fold-syntax*
 
index 0f8b2051f4598d814a2ce0cad962304fbfe6ccef..9f46c6e061f06fa0e807a28395570517a9886f63 100644 (file)
@@ -7218,6 +7218,7 @@ fold-create-marker        fold.txt        /*fold-create-marker*
 fold-delete-marker     fold.txt        /*fold-delete-marker*
 fold-diff      fold.txt        /*fold-diff*
 fold-expr      fold.txt        /*fold-expr*
+fold-expr-slow fold.txt        /*fold-expr-slow*
 fold-foldcolumn        fold.txt        /*fold-foldcolumn*
 fold-foldlevel fold.txt        /*fold-foldlevel*
 fold-foldtext  fold.txt        /*fold-foldtext*