aboutsummaryrefslogtreecommitdiff
path: root/runtime/doc/userfunc.txt
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-30 20:35:25 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-11-30 20:35:25 +0000
commit1b7b916b7631ddf73c38e3a0070d64e4636cb2f3 (patch)
treecd08258054db80bb9a11b1061bb091c70b76926a /runtime/doc/userfunc.txt
parenteaa89c11d0f8aefbb512de769c6c82f61a8baca3 (diff)
parent4a8bf24ac690004aedf5540fa440e788459e5e34 (diff)
downloadrneovim-aucmd_textputpost.tar.gz
rneovim-aucmd_textputpost.tar.bz2
rneovim-aucmd_textputpost.zip
Merge remote-tracking branch 'upstream/master' into aucmd_textputpostaucmd_textputpost
Diffstat (limited to 'runtime/doc/userfunc.txt')
-rw-r--r--runtime/doc/userfunc.txt78
1 files changed, 72 insertions, 6 deletions
diff --git a/runtime/doc/userfunc.txt b/runtime/doc/userfunc.txt
index 9c428175bb..b0384df454 100644
--- a/runtime/doc/userfunc.txt
+++ b/runtime/doc/userfunc.txt
@@ -44,6 +44,13 @@ functions.
unless "!" is given.
{name} may be a |Dictionary| |Funcref| entry: >
:function dict.init
+< Note that {name} is not an expression, you cannot use
+ a variable that is a function reference. You can use
+ this dirty trick to list the function referred to with
+ variable "Funcref": >
+ let g:MyFuncref = Funcref
+ func g:MyFuncref
+ unlet g:MyFuncref
:fu[nction] /{pattern} List functions with a name matching {pattern}.
Example that lists all functions ending with "File": >
@@ -72,8 +79,7 @@ See |:verbose-cmd| for more information.
name has a colon in the name, e.g. for "foo:bar()".
Before that patch no error was given).
- {name} can also be a |Dictionary| entry that is a
- |Funcref|: >
+ {name} may be a |Dictionary| |Funcref| entry: >
:function dict.init(arg)
< "dict" must be an existing dictionary. The entry
"init" is added if it didn't exist yet. Otherwise [!]
@@ -234,9 +240,10 @@ Example: >
call Something('key', 20) "key: 20"
The argument default expressions are evaluated at the time of the function
-call, not definition. Thus it is possible to use an expression which is
-invalid the moment the function is defined. The expressions are also only
-evaluated when arguments are not specified during a call.
+call, not when the function is defined. Thus it is possible to use an
+expression which is invalid the moment the function is defined. The
+expressions are also only evaluated when arguments are not specified during a
+call.
*E989*
Optional arguments with default expressions must occur after any mandatory
@@ -349,10 +356,69 @@ A function can also be called as part of evaluating an expression or when it
is used as a method: >
let x = GetList()
let y = GetList()->Filter()
+<
+==============================================================================
+3. Cleaning up in a function ~
+ *:defer*
+:defer {func}({args}) Call {func} when the current function is done.
+ {args} are evaluated here.
+
+Quite often a command in a function has a global effect, which must be undone
+when the function finishes. Handling this in all kinds of situations can be a
+hassle. Especially when an unexpected error is encountered. This can be done
+with `try` / `finally` blocks, but this gets complicated when there is more
+than one.
+
+A much simpler solution is using `defer`. It schedules a function call when
+the function is returning, no matter if there is an error. Example: >
+ func Filter(text) abort
+ call writefile(a:text, 'Tempfile')
+ call system('filter < Tempfile > Outfile')
+ call Handle('Outfile')
+ call delete('Tempfile')
+ call delete('Outfile')
+ endfunc
+
+Here 'Tempfile' and 'Outfile' will not be deleted if something causes the
+function to abort. `:defer` can be used to avoid that: >
+ func Filter(text) abort
+ call writefile(a:text, 'Tempfile')
+ defer delete('Tempfile')
+ defer delete('Outfile')
+ call system('filter < Tempfile > Outfile')
+ call Handle('Outfile')
+ endfunc
+
+Note that deleting "Outfile" is scheduled before calling `system()`, since it
+can be created even when `system()` fails.
+
+The deferred functions are called in reverse order, the last one added is
+executed first. A useless example: >
+ func Useless() abort
+ for s in range(3)
+ defer execute('echomsg "number ' .. s .. '"')
+ endfor
+ endfunc
+
+Now `:messages` shows:
+ number 2
+ number 1
+ number 0
+
+Any return value of the deferred function is discarded. The function cannot
+be followed by anything, such as "->func" or ".member". Currently `:defer
+GetArg()->TheFunc()` does not work, it may work in a later version.
+
+Errors are reported but do not cause aborting execution of deferred functions
+or altering execution outside of deferred functions.
+
+No range is accepted. The function can be a partial with extra arguments, but
+not with a dictionary. *E1300*
==============================================================================
-3. Automatically loading functions ~
+
+4. Automatically loading functions ~
*autoload-functions*
When using many or large functions, it's possible to automatically define them
only when they are used. There are two methods: with an autocommand and with