Quick links: help overview · quick reference · user manual toc · reference manual toc · faq
userfunc.txt  For Vim version 9.0.  Last change: 2022 Sep 09


                  VIM REFERENCE MANUAL    by Bram Moolenaar


Defining and using functions.

This is introduced in section 41.7 of the user manual.

1. Defining a fuction                   define-function
2. Calling a fuction                    :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.

                        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).
                                        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 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.
                                                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

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:

Quick links: help overview · quick reference · user manual toc · reference manual toc · faq