summaryrefslogtreecommitdiffstats
path: root/runtime/doc/userfunc.txt
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--runtime/doc/userfunc.txt546
1 files changed, 546 insertions, 0 deletions
diff --git a/runtime/doc/userfunc.txt b/runtime/doc/userfunc.txt
new file mode 100644
index 0000000..210c2c5
--- /dev/null
+++ b/runtime/doc/userfunc.txt
@@ -0,0 +1,546 @@
+*userfunc.txt* For Vim version 9.0. Last change: 2023 Feb 02
+
+
+ VIM REFERENCE MANUAL by Bram Moolenaar
+
+
+Defining and using functions.
+
+This is introduced in section |41.7| of the user manual.
+
+1. Defining a function |define-function|
+2. Calling a function |:call|
+3. Cleaning up in a function |:defer|
+4. Automatically loading functions |autoload-functions|
+
+==============================================================================
+
+1. Defining a function ~
+ *define-function*
+New functions can be defined. These can be called just like builtin
+functions. The function executes a sequence of Ex commands. Normal mode
+commands can be executed with the |:normal| command.
+
+The function name must start with an uppercase letter, to avoid confusion with
+builtin functions. To prevent from using the same name in different scripts
+make them script-local. If you do use a global function then avoid obvious,
+short names. A good habit is to start the function name with the name of the
+script, e.g., "HTMLcolor()".
+
+In legacy script it is also possible to use curly braces, see
+|curly-braces-names|.
+
+The |autoload| facility is useful to define a function only when it's called.
+
+ *local-function*
+A function local to a legacy script must start with "s:". A local script
+function can only be called from within the script and from functions, user
+commands and autocommands defined in the script. It is also possible to call
+the function from a mapping defined in the script, but then |<SID>| must be
+used instead of "s:" when the mapping is expanded outside of the script.
+There are only script-local functions, no buffer-local or window-local
+functions.
+
+In |Vim9| script functions are local to the script by default, prefix "g:" to
+define a global function.
+
+ *:fu* *:function* *E128* *E129* *E123* *E454*
+:fu[nction] List all functions and their arguments.
+
+:fu[nction] {name} List function {name}.
+ {name} can also be a |Dictionary| entry that is a
+ |Funcref|: >
+ :function dict.init
+
+:fu[nction] /{pattern} List functions with a name matching {pattern}.
+ Example that lists all functions ending with "File": >
+ :function /File$
+<
+ *:function-verbose*
+When 'verbose' is non-zero, listing a function will also display where it was
+last defined. Example: >
+
+ :verbose function SetFileTypeSH
+ function SetFileTypeSH(name)
+ Last set from /usr/share/vim/vim-7.0/filetype.vim
+<
+See |:verbose-cmd| for more information.
+
+ *E124* *E125* *E853* *E884*
+:fu[nction][!] {name}([arguments]) [range] [abort] [dict] [closure]
+ Define a new function by the name {name}. The body of
+ the function follows in the next lines, until the
+ matching |:endfunction|.
+ *E1267*
+ The name must be made of alphanumeric characters and
+ '_', and must start with a capital or "s:" (see
+ above). Note that using "b:" or "g:" is not allowed.
+ (since patch 7.4.260 E884 is given if the function
+ 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|: >
+ :function dict.init(arg)
+< "dict" must be an existing dictionary. The entry
+ "init" is added if it didn't exist yet. Otherwise [!]
+ is required to overwrite an existing function. The
+ result is a |Funcref| to a numbered function. The
+ function can only be used with a |Funcref| and will be
+ deleted if there are no more references to it.
+ *E127* *E122*
+ When a function by this name already exists and [!] is
+ not used an error message is given. There is one
+ exception: When sourcing a script again, a function
+ that was previously defined in that script will be
+ silently replaced.
+ When [!] is used, an existing function is silently
+ replaced. Unless it is currently being executed, that
+ is an error.
+ NOTE: Use ! wisely. If used without care it can cause
+ an existing function to be replaced unexpectedly,
+ which is hard to debug.
+ NOTE: In Vim9 script script-local functions cannot be
+ deleted or redefined.
+
+ For the {arguments} see |function-argument|.
+
+ *:func-range* *a:firstline* *a:lastline*
+ When the [range] argument is added, the function is
+ expected to take care of a range itself. The range is
+ passed as "a:firstline" and "a:lastline". If [range]
+ is excluded, ":{range}call" will call the function for
+ each line in the range, with the cursor on the start
+ of each line. See |function-range-example|.
+ The cursor is still moved to the first line of the
+ range, as is the case with all Ex commands.
+ *:func-abort*
+ When the [abort] argument is added, the function will
+ abort as soon as an error is detected.
+ *:func-dict*
+ When the [dict] argument is added, the function must
+ be invoked through an entry in a |Dictionary|. The
+ local variable "self" will then be set to the
+ dictionary. See |Dictionary-function|.
+ *:func-closure* *E932*
+ When the [closure] argument is added, the function
+ can access variables and arguments from the outer
+ scope. This is usually called a closure. In this
+ example Bar() uses "x" from the scope of Foo(). It
+ remains referenced even after Foo() returns: >
+ :function! Foo()
+ : let x = 0
+ : function! Bar() closure
+ : let x += 1
+ : return x
+ : endfunction
+ : return funcref('Bar')
+ :endfunction
+
+ :let F = Foo()
+ :echo F()
+< 1 >
+ :echo F()
+< 2 >
+ :echo F()
+< 3
+
+ *function-search-undo*
+ The last used search pattern and the redo command "."
+ will not be changed by the function. This also
+ implies that the effect of |:nohlsearch| is undone
+ when the function returns.
+
+ *:endf* *:endfunction* *E126* *E193* *W22* *E1151*
+:endf[unction] [argument]
+ The end of a function definition. Best is to put it
+ on a line by its own, without [argument].
+
+ [argument] can be:
+ | command command to execute next
+ \n command command to execute next
+ " comment always ignored
+ anything else ignored, warning given when
+ 'verbose' is non-zero
+ The support for a following command was added in Vim
+ 8.0.0654, before that any argument was silently
+ ignored.
+
+ To be able to define a function inside an `:execute`
+ command, use line breaks instead of |:bar|: >
+ :exe "func Foo()\necho 'foo'\nendfunc"
+<
+ *:delf* *:delfunction* *E131* *E933* *E1084*
+:delf[unction][!] {name}
+ Delete function {name}.
+ {name} can also be a |Dictionary| entry that is a
+ |Funcref|: >
+ :delfunc dict.init
+< This will remove the "init" entry from "dict". The
+ function is deleted if there are no more references to
+ it.
+ With the ! there is no error if the function does not
+ exist.
+ *:retu* *:return* *E133*
+:retu[rn] [expr] Return from a function. When "[expr]" is given, it is
+ evaluated and returned as the result of the function.
+ If "[expr]" is not given, the number 0 is returned.
+ When a function ends without an explicit ":return",
+ the number 0 is returned.
+
+ In a :def function *E1095* is given if unreachable
+ code follows after the `:return`.
+ In legacy script there is no check for unreachable
+ lines, thus there is no warning if commands follow
+ `:return`. Also, there is no check if the following
+ line contains a valid command. Forgetting the line
+ continuation backslash may go unnoticed: >
+ return 'some text'
+ .. ' some more text'
+< Will happily return "some text" without an error. It
+ should have been: >
+ return 'some text'
+ \ .. ' some more text'
+<
+ If the ":return" is used after a |:try| but before the
+ matching |:finally| (if present), the commands
+ following the ":finally" up to the matching |:endtry|
+ are executed first. This process applies to all
+ nested ":try"s inside the function. The function
+ returns at the outermost ":endtry".
+
+ *function-argument* *a:var*
+An argument can be defined by giving its name. In the function this can then
+be used as "a:name" ("a:" for argument) (in a `:def` function "a:" is not
+used).
+ *a:0* *a:1* *a:000* *E740* *...*
+Up to 20 arguments can be given, separated by commas. After the named
+arguments an argument "..." can be specified, which means that more arguments
+may optionally be following. In the function the extra arguments can be used
+as "a:1", "a:2", etc. "a:0" is set to the number of extra arguments (which
+can be 0). "a:000" is set to a |List| that contains these arguments. Note
+that "a:1" is the same as "a:000[0]".
+ *E742* *E1090*
+The a: scope and the variables in it cannot be changed, they are fixed.
+However, if a composite type is used, such as |List| or |Dictionary| , you can
+change their contents. Thus you can pass a |List| to a function and have the
+function add an item to it. If you want to make sure the function cannot
+change a |List| or |Dictionary| use |:lockvar|.
+
+It is also possible to define a function without any arguments. You must
+still supply the () then.
+
+It is allowed to define another function inside a function body.
+
+ *optional-function-argument*
+You can provide default values for positional named arguments. This makes
+them optional for function calls. When a positional argument is not
+specified at a call, the default expression is used to initialize it.
+This only works for functions declared with `:function` or `:def`, not for
+lambda expressions |expr-lambda|.
+
+Example: >
+ function Something(key, value = 10)
+ echo a:key .. ": " .. a:value
+ endfunction
+ call Something('empty') "empty: 10"
+ call Something('key', 20) "key: 20"
+
+The argument default expressions are evaluated at the time of the function
+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.
+ *none-function_argument*
+You can pass |v:none| to use the default expression. Note that this means you
+cannot pass v:none as an ordinary value when an argument has a default
+expression.
+
+Example: >
+ function Something(a = 10, b = 20, c = 30)
+ endfunction
+ call Something(1, v:none, 3) " b = 20
+<
+ *E989*
+Optional arguments with default expressions must occur after any mandatory
+arguments. You can use "..." after all optional named arguments.
+
+It is possible for later argument defaults to refer to prior arguments,
+but not the other way around. They must be prefixed with "a:", as with all
+arguments.
+
+Example that works: >
+ :function Okay(mandatory, optional = a:mandatory)
+ :endfunction
+Example that does NOT work: >
+ :function NoGood(first = a:second, second = 10)
+ :endfunction
+<
+When not using "...", the number of arguments in a function call must be at
+least equal to the number of mandatory named arguments. When using "...", the
+number of arguments may be larger than the total of mandatory and optional
+arguments.
+
+ *local-variables*
+Inside a function local variables can be used. These will disappear when the
+function returns. Global variables need to be accessed with "g:".
+Inside functions local variables are accessed without prepending anything.
+But you can also prepend "l:" if you like. This is required for some reserved
+names, such as "count".
+
+Example: >
+ :function Table(title, ...)
+ : echohl Title
+ : echo a:title
+ : echohl None
+ : echo a:0 .. " items:"
+ : for s in a:000
+ : echon ' ' .. s
+ : endfor
+ :endfunction
+
+This function can then be called with: >
+ call Table("Table", "line1", "line2")
+ call Table("Empty Table")
+
+To return more than one value, return a |List|: >
+ :function Compute(n1, n2)
+ : if a:n2 == 0
+ : return ["fail", 0]
+ : endif
+ : return ["ok", a:n1 / a:n2]
+ :endfunction
+
+This function can then be called with: >
+ :let [success, div] = Compute(102, 6)
+ :if success == "ok"
+ : echo div
+ :endif
+<
+==============================================================================
+
+2. Calling a function ~
+ *:cal* *:call* *E107*
+:[range]cal[l] {name}([arguments])
+ Call a function. The name of the function and its arguments
+ are as specified with `:function`. Up to 20 arguments can be
+ used. The returned value is discarded.
+ In |Vim9| script using `:call` is optional, these two lines do
+ the same thing: >
+ call SomeFunc(arg)
+ SomeFunc(arg)
+< Without a range and for functions that accept a range, the
+ function is called once. When a range is given the cursor is
+ positioned at the start of the first line before executing the
+ function.
+ When a range is given and the function doesn't handle it
+ itself, the function is executed for each line in the range,
+ with the cursor in the first column of that line. The cursor
+ is left at the last line (possibly moved by the last function
+ call). The arguments are re-evaluated for each line. Thus
+ this works:
+ *function-range-example* >
+ :function Mynumber(arg)
+ : echo line(".") .. " " .. a:arg
+ :endfunction
+ :1,5call Mynumber(getline("."))
+<
+ The "a:firstline" and "a:lastline" are defined anyway, they
+ can be used to do something different at the start or end of
+ the range.
+
+ Example of a function that handles the range itself: >
+
+ :function Cont() range
+ : execute (a:firstline + 1) .. "," .. a:lastline .. 's/^/\t\\ '
+ :endfunction
+ :4,8call Cont()
+<
+ This function inserts the continuation character "\" in front
+ of all the lines in the range, except the first one.
+
+ When the function returns a composite value it can be further
+ dereferenced, but the range will not be used then. Example: >
+ :4,8call GetDict().method()
+< Here GetDict() gets the range but method() does not.
+
+ *E117*
+When a function cannot be found the error "E117: Unknown function" will be
+given. If the function was using an autoload path or an autoload import and
+the script is a |Vim9| script, this may also be caused by the function not
+being exported.
+
+ *E132*
+The recursiveness of user functions is restricted with the |'maxfuncdepth'|
+option.
+
+It is also possible to use `:eval`. It does not support a range, but does
+allow for method chaining, e.g.: >
+ eval GetList()->Filter()->append('$')
+
+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.
+
+No range is accepted. The function can be a partial with extra arguments, but
+not with a dictionary. *E1300*
+
+==============================================================================
+
+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
+the "autoload" directory in 'runtimepath'.
+
+In |Vim9| script there is also an autoload mechanism for imported scripts, see
+|import-autoload|.
+
+
+Using an autocommand ~
+
+This is introduced in the user manual, section |51.4|.
+
+The autocommand is useful if you have a plugin that is a long Vim script file.
+You can define the autocommand and quickly quit the script with `:finish`.
+That makes Vim startup faster. The autocommand should then load the same file
+again, setting a variable to skip the `:finish` command.
+
+Use the FuncUndefined autocommand event with a pattern that matches the
+function(s) to be defined. Example: >
+
+ :au FuncUndefined BufNet* source ~/vim/bufnetfuncs.vim
+
+The file "~/vim/bufnetfuncs.vim" should then define functions that start with
+"BufNet". Also see |FuncUndefined|.
+
+
+Using an autoload script ~
+ *autoload* *E746*
+This is introduced in the user manual, section |52.2|.
+
+Using a script in the "autoload" directory is simpler, but requires using
+exactly the right file name. A function that can be autoloaded has a name
+like this: >
+
+ :call filename#funcname()
+
+These functions are always global, in Vim9 script "g:" needs to be used: >
+ :call g:filename#funcname()
+
+When such a function is called, and it is not defined yet, Vim will search the
+"autoload" directories in 'runtimepath' for a script file called
+"filename.vim". For example "~/.vim/autoload/filename.vim". That file should
+then define the function like this: >
+
+ function filename#funcname()
+ echo "Done!"
+ endfunction
+
+If the file doesn't exist, Vim will also search in 'packpath' (under "start")
+to allow calling packages' functions from your .vimrc when the packages have
+not been added to 'runtimepath' yet (see |packages|).
+
+The file name and the name used before the # in the function must match
+exactly, and the defined function must have the name exactly as it will be
+called. In Vim9 script the "g:" prefix must be used: >
+ function g:filename#funcname()
+
+or for a compiled function: >
+ def g:filename#funcname()
+
+It is possible to use subdirectories. Every # in the function name works like
+a path separator. Thus when calling a function: >
+
+ :call foo#bar#func()
+
+Vim will look for the file "autoload/foo/bar.vim" in 'runtimepath'.
+
+This also works when reading a variable that has not been set yet: >
+
+ :let l = foo#bar#lvar
+
+However, when the autoload script was already loaded it won't be loaded again
+for an unknown variable.
+
+When assigning a value to such a variable nothing special happens. This can
+be used to pass settings to the autoload script before it's loaded: >
+
+ :let foo#bar#toggle = 1
+ :call foo#bar#func()
+
+Note that when you make a mistake and call a function that is supposed to be
+defined in an autoload script, but the script doesn't actually define the
+function, you will get an error message for the missing function. If you fix
+the autoload script it won't be automatically loaded again. Either restart
+Vim or manually source the script.
+
+Also note that if you have two script files, and one calls a function in the
+other and vice versa, before the used function is defined, it won't work.
+Avoid using the autoload functionality at the toplevel.
+
+In |Vim9| script you will get error *E1263* if you define a function with
+a "#" character in the name. You should use a name without "#" and use
+`:export`.
+
+Hint: If you distribute a bunch of scripts you can pack them together with the
+|vimball| utility. Also read the user manual |distribute-script|.
+
+
+ vim:tw=78:ts=8:noet:ft=help:norl: