userfunc.txt ForVim version 9.2. Last change: 2026 Feb 14VIM REFERENCE MANUAL by Bram MoolenaarDefining and using functions.Thisis introduced insection41.7 of the user manual.1. Defininga functiondefine-function2. Callinga function:call3. Cleaning up ina function:defer4. Automatically loadingfunctionsautoload-functions==============================================================================1. Defining a functiondefine-functionNewfunctions can be defined. These can be called just like builtinfunctions. The function executesa sequence ofEx commands.Normal modecommands can be executed with the:normal command.The function namemust start with anuppercase letter, to avoid confusion withbuiltin functions. To prevent from using the same name in different scriptsmake them script-local. If youdo usea global function then avoid obvious,short names.A good habitis to start the function name with the name of thescript, e.g., "HTMLcolor()".In legacyscriptitis also possible to use curly braces, seecurly-braces-names.Theautoload facilityis useful to definea function only when it's called.local-functionA function local toa legacyscriptmust start with "s:".A localscriptfunction can only be called from within thescript and from functions, usercommands andautocommands defined in the script. Itis also possible to callthe function fromamapping defined in the script, but then<SID>must beused instead of "s:" when themappingis expanded outside of the script.There are onlyscript-local functions, no buffer-local or window-localfunctions.InVim9scriptfunctions are local to thescript by default, prefix "g:" todefinea global function.:fu:functionE128E129E123E454:fu[nction]List allfunctions and their arguments.:fu[nction]{name}List function{name}.{name} can also beaDictionary entry thatisaFuncref::function dict.initNote that{name}is not an expression, you cannot usea variable thatisa function reference. You can usethis dirty trick tolist the function referred to withvariable "Funcref":let g:MyFuncref = Funcreffunc g:MyFuncrefunlet g:MyFuncref:fu[nction] /{pattern}Listfunctions witha name matching{pattern}.Example that lists allfunctions ending with "File"::function /File$:function-verboseWhen'verbose'is non-zero, listinga function will also display whereit waslast defined. Example: :verbose function SetFileTypeSHfunction SetFileTypeSH(name) Last set from /usr/share/vim/vim-7.0/filetype.vimSee:verbose-cmd for more information.E124E125E853E884:fu[nction][!]{name}([arguments])[range][abort][dict][closure]Definea new function by the name{name}. The body ofthe function follows in the next lines, until thematching:endfunction.E1267The namemust be made of alphanumeric characters and'_' andmust start witha capital or "s:" (see above).Note that using "b:", "l:", etc.is not allowed (sincepatch 7.4.260E884is given if the function name hasacolon, e.g. for "foo:bar()"), whilea leading "g:"isskipped and still requiresa following capital letter.{name} can also beaDictionary entry thatisaFuncref::function dict.init(arg)"dict"must be an existing dictionary. The entry"init"is added ifit didn't exist yet. Otherwise [!]is required to overwrite an existing function. TheresultisaFuncref toa numbered function. Thefunction can only be used withaFuncref and will bedeleted if there are no more references to it.E127E122Whena function by this name already exists and [!]isnot used an error messageis given. Thereis oneexception: When sourcingascript again,a functionthat was previously defined in thatscript will besilently replaced.When [!]is used, an existing functionis silentlyreplaced. Unlessitis currently being executed, thatis an error.NOTE: Use! wisely. If used without careit can causean existing function to be replaced unexpectedly,whichis hard to debug.NOTE: InVim9scriptscript-localfunctions cannot bedeleted or redefined.For the{arguments} seefunction-argument.:func-rangea:firstlinea:lastlineWhen the[range] argumentis added, the functionisexpected to take care ofa range itself. The rangeispassedas "a:firstline" and "a:lastline". If[range]is excluded, ":{range}call" will call the function foreach line in the range, with the cursor on the startof each line. Seefunction-range-example.The cursoris still moved to the first line of therange,asis thecase with allEx commands.:func-abortWhen the[abort] argumentis added, the function willabortas soonas an erroris detected.:func-dictWhen the[dict] argumentis added, the functionmustbe invoked through an entry inaDictionary. Thelocal variable "self" will then be set to thedictionary. SeeDictionary-function.:func-closureE932When the[closure] argumentis added, the functioncan accessvariables and arguments from the outerscope. Thisis usually calleda closure. In thisexample Bar() uses "x" from the scope of Foo(). Itremains 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()3function-search-undoThe last used searchpattern and theredo command "."will not be changed by the function. This alsoimplies that the effect of:nohlsearchis undonewhen the function returns.:endf:endfunctionE126E193W22E1151:endf[unction][argument]Theend ofa function definition. Bestis toputitona line by its own, without[argument].[argument] can be:| commandcommand to execute next\n commandcommand to execute next" commentalways ignoredanything elseignored, warning given when'verbose'is non-zeroThe support fora following command was added in Vim8.0.0654, before that any argument was silentlyignored.To be able to definea function inside an:executecommand, use line breaks instead of:bar::exe "func Foo()\necho 'foo'\nendfunc":delf:delfunctionE131E933E1084:delf[unction][!]{name}Delete function{name}.{name} can also beaDictionary entry thatisaFuncref::delfunc dict.initThis will remove the "init" entry from "dict". Thefunctionis deleted if there are no more references toit.With the! thereis no error if the function does notexist.:retu:returnE133:retu[rn][expr]Return froma function. When[expr]is given,itisevaluated and returnedas the result of the function.If[expr]is not given, the number0is returned.Whena function ends without an explicit ":return",the number0is returned.Ina:def functionE1095is given if unreachablecode follows after the:return.In legacyscript thereis no check for unreachablelines, thus thereis no warning if commands follow:return. Also, thereis no check if the followingline containsa valid command. Forgetting the linecontinuationbackslash maygo unnoticed:return 'some text' .. ' some more text'Will happily return "some text" without an error. Itshould have been:return 'some text' \ .. ' some more text'If the ":return"is used aftera:try but before thematching:finally (if present), the commandsfollowing the ":finally" up to the matching:endtryare executed first. This process applies to allnested ":try"s inside the function. The functionreturnsat the outermost ":endtry".function-argumenta:varAn argument can be defined by giving its name. In the function this can thenbe usedas "a:name"("a:" for argument) (ina:def function "a:"is notused).a:0a:1a:000E740...Up to 20 arguments can be given, separated by commas. After the namedarguments an argument "..." can be specified, which means that more argumentsmay optionally be following. In the function the extra arguments can be usedas "a:1", "a:2", etc. "a:0"is set to the number of extra arguments (whichcan be 0). "a:000"is set toaList that contains these arguments.Notethat "a:1"is the sameas "a:000[0]".E742E1090The a: scope and thevariables init cannot be changed, they are fixed.However, ifa composite typeis used, suchasList orDictionary, you canchange their contents. Thus you can passaList toa function and have thefunction add an item to it. If you want to make sure the function cannotchangeaList orDictionary use:lockvar.Itis also possible to definea function without any arguments. Youmuststill supply the () then.Itis allowed to define another function insidea function body.optional-function-argumentYou can provide default values for positional named arguments. This makesthem optional for function calls. Whena positional argumentis notspecifiedata call, the defaultexpressionis used to initialize it.This only works forfunctions declared with:function or:def, not forlambda expressionsexpr-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 evaluatedat the time of the functioncall, not when the functionis defined. Thusitis possible to use anexpression whichis invalid the moment the functionis defined. Theexpressions are also only evaluated when arguments are not specified duringacall.none-function_argumentYou can passv:none to use the default expression.Note that this means youcannot passv:noneas an ordinary value when an argument hasa defaultexpression.Example: function Something(a = 10, b = 20, c = 30) endfunction call Something(1, v:none, 3) " b = 20E989Optional arguments with default expressionsmust occur after any mandatoryarguments. You can use "..." after all optional named arguments.Itis possible for later argument defaults to refer to prior arguments,but not the other way around. Theymust be prefixed with "a:",as with allarguments.Example that works: :function Okay(mandatory, optional = a:mandatory) :endfunctionExample that does NOT work: :function NoGood(first = a:second, second = 10) :endfunctionWhen not using "...", the number of arguments ina function callmust beatleast equal to the number of mandatory named arguments. When using "...", thenumber of arguments may be larger than the total of mandatory and optionalarguments.local-variablesInsidea function localvariables can be used. These will disappear when thefunction returns. Globalvariables need to be accessed with "g:".Insidefunctions localvariables are accessed without prepending anything.But you can also prepend "l:" if you like. Thisis required for some reservednames, suchas "count".Example: :function Table(title, ...) : echohl Title : echo a:title : echohl None : echo a:0 .. " items:" : for s in a:000 : echon ' ' .. s : endfor :endfunctionThis function can then be called with: call Table("Table", "line1", "line2") call Table("Empty Table")To return more than one value, returnaList: :function Compute(n1, n2) : if a:n2 == 0 : return ["fail", 0] : endif : return ["ok", a:n1 / a:n2] :endfunctionThis function can then be called with: :let [success, div] = Compute(102, 6) :if success == "ok" : echo div :endif==============================================================================2. Calling a function:cal:callE107:[range]cal[l]{name}([arguments])Calla function. The name of the function and its argumentsareas specified with:function. Up to 20 arguments can beused. The returned valueis discarded.InVim9script using:callis optional, these two linesdothe same thing:call SomeFunc(arg)SomeFunc(arg)Withouta range and forfunctions that accepta range, thefunctionis called once. Whena rangeis given the cursorispositionedat the start of the first line before executing thefunction.Whena rangeis given and the function doesn't handleititself, the functionis executed for each line in the range,with the cursor in the first column of that line. The cursoris leftat the last line (possibly moved by the last functioncall). The arguments are re-evaluated for each line. Thusthis 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, theycan be used todo something differentat the start orend ofthe range.Example ofa 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 frontof all the lines in the range, except the first one.When the function returnsa composite valueit can be furtherdereferenced, but the range will not be used then. Example::4,8call GetDict().method()Here GetDict() gets the range but method() does not.E117Whena function cannot be found the error "E117: Unknown function" will begiven. If the function was using anautoload path or anautoload import andthescriptisaVim9 script, this may also be caused by the function notbeing exported.E132The recursiveness of userfunctionsis restricted with the'maxfuncdepth'option.Itis also possible to use:eval. It does not supporta range, but doesallow formethod chaining, e.g.:eval GetList()->Filter()->append('$')A function can also be calledas part of evaluating anexpression or whenitis usedasa method:let x = GetList()let y = GetList()->Filter()==============================================================================3. Cleaning up in a function:defe:defer:defe[r]{func}({args})Call{func} when the current functionis done.{args} are evaluated here.Quite oftena command ina function hasa global effect, whichmust be undonewhen the function finishes. Handling this in all kinds of situations can beahassle. Especially when an unexpected erroris encountered. This can be donewithtry/finally blocks, but this gets complicated when thereis morethan one.A much simpler solutionis usingdefer. It schedulesa function call whenthe functionis returning, no matter if thereis 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')endfuncHere 'Tempfile' and 'Outfile' will not be deleted if something causes thefunction 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')endfuncNote thatdeleting "Outfile"is scheduled before callingsystem(), sinceitcan be created even whensystem() fails.The deferredfunctions are called in reverse order, the last one addedisexecuted first.A useless example:func Useless() abort for s in range(3) defer execute('echomsg "number ' .. s .. '"') endforendfuncNow:messages shows:number 2number 1number0Any return value of the deferred functionis discarded. The function cannotbe followed by anything, suchas "->func" or ".member". Currently `:deferGetArg()->TheFunc()` does not work,it may work ina later version.Errors are reported butdo not cause aborting execution of deferredfunctionsor altering execution outside of deferred functions.No rangeis accepted. The function can beapartial with extra arguments, butnot witha dictionary.E1300Ina:def function,alambda can be used with:defer. Example: def Fn() set lazyredraw defer () => { set lazyredraw& }() enddef==============================================================================4. Automatically loading functionsautoload-functionsWhen using many or large functions, it's possible to automatically define themonly when they are used. There are two methods: with anautocommand and withthe "autoload" directory in'runtimepath'.InVim9script thereis also anautoload mechanism for imported scripts, seeimport-autoload.Using an autocommandThisis introduced in the user manual,section51.4.Theautocommandis useful if you haveaplugin thatisa long Vimscript file.You can define theautocommand and quickly quit thescript with:finish.That makes Vimstartup faster. Theautocommand should then load the same fileagain, settinga variable to skip the:finish command.Use theFuncUndefinedautocommand event withapattern that matches thefunction(s) to be defined. Example::au FuncUndefined BufNet* source ~/vim/bufnetfuncs.vimThe file "~/vim/bufnetfuncs.vim" should then definefunctions that start with"BufNet". Also seeFuncUndefined.Using an autoload scriptautoloadE746Thisis introduced in the user manual,section52.2.Usingascript in the "autoload" directoryis simpler, but requires usingexactly the right file name.A function that can be autoloaded hasa namelike this::call filename#funcname()Thesefunctions are always global, inVim9script "g:" needs to be used::call g:filename#funcname()When sucha functionis called, anditis not defined yet, Vim will search the"autoload" directories in'runtimepath' forascript file called"filename.vim". For example "~/.vim/autoload/filename.vim". That file shouldthen define the function like this:function filename#funcname() echo "Done!"endfunctionIf the file doesn't exist, Vim will also search in'packpath' (under "start")to allow calling packages'functions from your.vimrc when thepackages havenot been added to'runtimepath' yet (seepackages).The file name and the name used before the# in the functionmust matchexactly, and the defined functionmust have the name exactlyasit will becalled. InVim9script the "g:" prefixmust be used:function g:filename#funcname()or fora compiled function:def g:filename#funcname()Itis possible to use subdirectories. Every# in the function name works likea path separator. Thus when callinga function::call foo#bar#func()Vim will look for the file "autoload/foo/bar.vim" in'runtimepath'.This also works when readinga variable that has not been set yet::let l = foo#bar#lvarHowever, when theautoloadscript was already loadedit won't be loaded againfor an unknown variable.When assigninga value to sucha variable nothing special happens. This canbe used to pass settings to theautoloadscript before it's loaded::let foo#bar#toggle = 1:call foo#bar#func()Note that when you makea mistake and calla function thatis supposed to bedefined in anautoload script, but thescript doesn't actually define thefunction, you will get an error message for the missing function. If you fixtheautoloadscriptit won't be automatically loaded again. Either restartVim or manually source the script.Alsonote that if you have twoscript files, and one callsa function in theother and vice versa, before the used functionis defined,it won't work.Avoid using theautoload functionalityat the toplevel.InVim9script you will get errorE1263 if you definea function witha "#" character in the name. You should usea name without "#" and use:export.Hint: If you distributea bunch of scripts you can pack them together with thevimball utility. Also read the user manualdistribute-script. vim:tw=78:ts=8:noet:ft=help:norl: