Vim briefly goes to the tab page {tabnr}, this may trigger TabLeave and TabEnter autocommands. Examples: :call settabwinvar(1, 1, "&list", 0) :call settabwinvar(3, 2, "myvar", "foobar") This function is not available in the |sandbox|. setwinvar({nr}, {varname}, {val}) *setwinvar()* Like |settabwinvar()| for the current tab page. Examples: :call setwinvar(1, "&list", 0) :call setwinvar(2, "myvar", "foobar") shellescape({string} [, {special}]) *shellescape()* Escape {string} for use as shell command argument. On MS-Windows and MS-DOS, when 'shellslash' is not set, it will enclose {string} in double quotes and double all double quotes within {string}. For other systems, it will enclose {string} in single quotes and replace all "'"' with "'\''"'. When the {special} argument is present and it's a non-zero Number or a non-empty String (|non-zero-arg|), then special items such as "!", "%", "#" and "<cword>" will be preceded by a backslash. This backslash will be removed again by the |:!| command. The "!" character will be escaped (again with a |non-zero-arg| {special}) when 'shell' contains "csh" in the tail. That is because for csh and tcsh "!" is used for history replacement even when inside single quotes. The <NL> character is also escaped. With a |non-zero-arg| {special} and 'shell' containing "csh" in the tail it's escaped a second time. Example of use with a |:!| command: :exe '!dir ' . shellescape(expand('<cfile>'), 1) This results in a directory listing for the file under the cursor. Example of use with YXXYsystem()|: :call system("chmod +w -- " . shellescape(expand("%"))) simplify({filename}) *simplify()* Simplify the file name as much as possible without changing the meaning. Shortcuts (on MS-Windows) or symbolic links (on Unix) are not resolved. If the first path component in {filename} designates the current directory, this will be valid for the result as well. A trailing path separator is not removed either. Example: simplify("./dir/.././/file/") == "./file/" Note: The combination "dir/.." is only removed if "dir" is a searchable directory or does not exist. On Unix, it is also removed when "dir" is a symbolic link within the same directory. In order to resolve all the involved symbolic links before simplifying the path name, use |resolve()|. sin({expr}) *sin()* Return the sine of {expr}, measured in radians, as a |Float|. {expr} must evaluate to a |Float| or a |Number|. Examples: :echo sin(100) -0.506366 :echo sin(-4.01) 0.763301 {only available when compiled with the |+float| feature} sort({list} [, {func}]) *sort()* *E702* Sort the items in {list} in-place. Returns {list}. If you want a list to remain unmodified make a copy first: :let sortedlist = sort(copy(mylist)) Uses the string representation of each item to sort on. Numbers sort after Strings, |Lists| after Numbers. For sorting text in the current buffer use |:sort|. When {func} is given and it is one then case is ignored. When {func} is a |Funcref| or a function name, this function is called to compare items. The function is invoked with two items as argument and must return zero if they are equal, 1 if the first one sorts after the second one, -1 if the first one sorts before the second one. Example: func MyCompare(i1, i2) return a:i1 == a:i2 ? 0 : a:i1 > a:i2 ? 1 : -1 endfunc let sortedlist = sort(mylist, "MyCompare") *soundfold()* soundfold({word}) Return the sound-folded equivalent of {word}. Uses the first language in 'spelllang' for the current window that supports soundfolding. 'spell' must be set. When no sound folding is possible the {word} is returned unmodified. This can be used for making spelling suggestions. Note that the method can be quite slow. *spellbadword()* spellbadword([{sentence}]) Without argument: The result is the badly spelled word under or after the cursor. The cursor is moved to the start of the bad word. When no bad word is found in the cursor line the result is an empty string and the cursor doesn't move. With argument: The result is the first word in {sentence} that is badly spelled. If there are no spelling mistakes the result is an empty string. The return value is a list with two items: - The badly spelled word or an empty string. - The type of the spelling error: "bad" spelling mistake "rare" rare word "local" word only valid in another region "caps" word should start with Capital Example: echo spellbadword("the quik brown fox") ['quik', 'bad'] The spelling information for the current window is used. The 'spell' option must be set and the value of 'spelllang' is used. *spellsuggest()* spellsuggest({word} [, {max} [, {capital}]]) Return a |List| with spelling suggestions to replace {word}. When {max} is given up to this number of suggestions are returned. Otherwise up to 25 suggestions are returned. When the {capital} argument is given and it's non-zero only suggestions with a leading capital will be given. Use this after a match with 'spellcapcheck'. {word} can be a badly spelled word followed by other text. This allows for joining two words that were split. The suggestions also include the following text, thus you can replace a line. {word} may also be a good word. Similar words will then be returned. {word} itself is not included in the suggestions, although it may appear capitalized. The spelling information for the current window is used. The 'spell' option must be set and the values of 'spelllang' and 'spellsuggest' are used. split({expr} [, {pattern} [, {keepempty}]]) *split()* Make a |List| out of {expr}. When {pattern} is omitted or empty each white-separated sequence of characters becomes an item. Otherwise the string is split where {pattern} matches, removing the matched characters. When the first or last item is empty it is omitted, unless the {keepempty} argument is given and it's non-zero. Other empty items are kept when {pattern} matches at least one character or when {keepempty} is non-zero. Example: :let words = split(getline('.'), '\W\+') To split a string in individual characters: :for c in split(mystring, '\zs') If you want to keep the separator you can also use '\zs': :echo split('abc:def:ghi', ':\zs') ['abc:', 'def:', 'ghi'] Splitting a table where the first element can be empty: :let items = split(line, ':', 1) The opposite function is |join()|. sqrt({expr}) *sqrt()* Return the non-negative square root of Float {expr} as a |Float|. {expr} must evaluate to a |Float| or a |Number|. When {expr} is negative the result is NaN (Not a Number). Examples: :echo sqrt(100) 10.0 :echo sqrt(-4.01) nan "nan" may be different, it depends on system libraries. {only available when compiled with the |+float| feature} str2float( {expr}) *str2float()* Convert String {expr} to a Float. This mostly works the same as when using a floating point number in an expression, see |floating-point-format|. But it's a bit more permissive. E.g., "1e40" is accepted, while in an expression you need to write "1.0e40". Text after the number is silently ignored. The decimal point is always '.', no matter what the locale is set to. A comma ends the number: "12,345.67" is converted to 12.0. You can strip out thousands separators with YXXYsubstitute()|: let f = str2float(substitute(text, ',', '', 'g')) {only available when compiled with the |+float| feature} str2nr( {expr} [, {base}]) *str2nr()* Convert string {expr} to a number. {base} is the conversion base, it can be 8, 10 or 16. When {base} is omitted base 10 is used. This also means that a leading zero doesn't cause octal conversion to be used, as with the default String to Number conversion. When {base} is 16 a leading "0x" or "0X" is ignored. With a different base the result will be zero. Text after the number is silently ignored. strftime({format} [, {time}]) *strftime()* The result is a String, which is a formatted date and time, as specified by the {format} string. The given {time} is used, or the current time if no time is given. The accepted {format} depends on your system, thus this is not portable! See the manual page of the C function strftime() for the format. The maximum length of the result is 80 characters. See also |localtime()| and |getftime()|. The language can be changed with the |:language| command. Examples: :echo strftime("%c") Sun Apr 27 11:49:23 1997 :echo strftime("%Y %b %d %X") 1997 Apr 27 11:53:25 :echo strftime("%y%m%d %T") 970427 11:53:55 :echo strftime("%H:%M") 11:55 :echo strftime("%c", getftime("file.c")) Show mod time of file.c. Not available on all systems. To check use: :if exists("*strftime") stridx({haystack}, {needle} [, {start}]) *stridx()* The result is a Number, which gives the byte index in {haystack} of the first occurrence of the String {needle}. If {start} is specified, the search starts at index {start}. This can be used to find a second match: :let comma1 = stridx(line, ",") :let comma2 = stridx(line, ",", comma1 + 1) The search is done case-sensitive. For pattern searches use |match()|. -1 is returned if the {needle} does not occur in {haystack}. See also |strridx()|. Examples: :echo stridx("An Example", "Example") 3 :echo stridx("Starting point", "Start") 0 :echo stridx("Starting point", "start") -1 *strstr()* *strchr()* stridx() works similar to the C function strstr(). When used with a single character it works similar to strchr(). *string()* string({expr}) Return {expr} converted to a String. If {expr} is a Number, Float, String or a composition of them, then the result can be parsed back with |eval()|. {expr} type result String 'string' Number 123 Float 123.123456 or 1.123456e8 Funcref function('name') List [item, item] Dictionary {key: value, key: value} Note that in String values the '' character is doubled. Also see |strtrans()|. *strlen()* strlen({expr}) The result is a Number, which is the length of the String {expr} in bytes. If you want to count the number of multi-byte characters (not counting composing characters) use something like this: :let len = strlen(substitute(str, ".", "x", "g")) If the argument is a Number it is first converted to a String. For other types an error is given. Also see |len()|. strpart({src}, {start}[, {len}]) *strpart()* The result is a String, which is part of {src}, starting from byte {start}, with the byte length {len}. When non-existing bytes are included, this doesn't result in an error, the bytes are simply omitted. If {len} is missing, the copy continues from {start} till the end of the {src}. strpart("abcdefg", 3, 2) == "de" strpart("abcdefg", -2, 4) == "ab" strpart("abcdefg", 5, 4) == "fg" strpart("abcdefg", 3) == "defg" Note: To get the first character, {start} must be 0. For example, to get three bytes under and after the cursor: strpart(getline("."), col(".") - 1, 3) strridx({haystack}, {needle} [, {start}]) *strridx()* The result is a Number, which gives the byte index in {haystack} of the last occurrence of the String {needle}. When {start} is specified, matches beyond this index are ignored. This can be used to find a match before a previous match: :let lastcomma = strridx(line, ",") :let comma2 = strridx(line, ",", lastcomma - 1) The search is done case-sensitive. For pattern searches use |match()|. -1 is returned if the {needle} does not occur in {haystack}. If the {needle} is empty the length of {haystack} is returned. See also |stridx()|. Examples: :echo strridx("an angry armadillo", "an") 3 *strrchr()* When used with a single character it works similar to the C function strrchr(). strtrans({expr}) *strtrans()* The result is a String, which is {expr} with all unprintable characters translated into printable characters |'isprint'|. Like they are shown in a window. Example: echo strtrans(@a) This displays a newline in register a as "^@" instead of starting a new line. submatch({nr}) *submatch()* Only for an expression in a |:substitute| command. Returns the {nr}'th submatch of the matched text. When {nr} is 0 the whole matched text is returned. Example: :s/\d\+/\=submatch(0) + 1/ This finds the first number in the line and adds one to it. A line break is included as a newline character. substitute({expr}, {pat}, {sub}, {flags}) *substitute()* The result is a String, which is a copy of {expr}, in which the first match of {pat} is replaced with {sub}. This works like the ":substitute" command (without any flags). But the matching with {pat} is always done like the 'magic' option is set and 'cpoptions' is empty (to make scripts portable). 'ignorecase' is still relevant. 'smartcase' is not used. See |string-match| for how {pat} is used. And a "~" in {sub} is not replaced with the previous {sub}. Note that some codes in {sub} have a special meaning |sub-replace-special|. For example, to replace something with "\n" (two characters), use "\\\\n" or '\\n'. When {pat} does not match in {expr}, {expr} is returned unmodified. When {flags} is "g", all matches of {pat} in {expr} are replaced. Otherwise {flags} should be "". Example: :let &path = substitute(&path, ",\\=[^,]*$", "", "") This removes the last component of the 'path' option. :echo substitute("testing", ".*", "\\U\\0", "") results in "TESTING". synID({lnum}, {col}, {trans}) *synID()* The result is a Number, which is the syntax ID at the position {lnum} and {col} in the current window. The syntax ID can be used with |synIDattr()| and |synIDtrans()| to obtain syntax information about text. {col} is 1 for the leftmost column, {lnum} is 1 for the first line. 'synmaxcol' applies, in a longer line zero is returned. When {trans} is non-zero, transparent items are reduced to the item that they reveal. This is useful when wanting to know the effective color. When {trans} is zero, the transparent item is returned. This is useful when wanting to know which syntax item is effective (e.g. inside parens). Warning: This function can be very slow. Best speed is obtained by going through the file in forward direction. Example (echoes the name of the syntax item under the cursor): :echo synIDattr(synID(line("."), col("."), 1), "name") synIDattr({synID}, {what} [, {mode}]) *synIDattr()* The result is a String, which is the {what} attribute of syntax ID {synID}. This can be used to obtain information about a syntax item. {mode} can be "gui", "cterm" or "term", to get the attributes for that mode. When {mode} is omitted, or an invalid value is used, the attributes for the currently active highlighting are used (GUI, cterm or term). Use synIDtrans() to follow linked highlight groups. {what} result "name" the name of the syntax item "fg" foreground color (GUI: color name used to set the color, cterm: color number as a string, term: empty string) "bg" background color (as with "fg") "sp" special color (as with "fg") |highlight-guisp| "fg#" like "fg", but for the GUI and the GUI is running the name in "#RRGGBB" form "bg#" like "fg#" for "bg" "sp#" like "fg#" for "sp" "bold" "1" if bold "italic" "1" if italic "reverse" "1" if reverse "inverse" "1" if inverse (= reverse) "underline" "1" if underlined "undercurl" "1" if undercurled Example (echoes the color of the syntax item under the cursor): :echo synIDattr(synIDtrans(synID(line("."), col("."), 1)), "fg") synIDtrans({synID}) *synIDtrans()* The result is a Number, which is the translated syntax ID of {synID}. This is the syntax group ID of what is being used to highlight the character. Highlight links given with ":highlight link" are followed. synstack({lnum}, {col}) *synstack()* Return a |List|, which is the stack of syntax items at the position {lnum} and {col} in the current window. Each item in the List is an ID like what |synID()| returns. The first item in the List is the outer region, following are items contained in that one. The last one is what |synID()| returns, unless not the whole item is highlighted or it is a transparent item. This function is useful for debugging a syntax file. Example that shows the syntax stack under the cursor: for id in synstack(line("."), col(".")) echo synIDattr(id, "name") endfor system({expr} [, {input}]) *system()* *E677* Get the output of the shell command {expr}. When {input} is given, this string is written to a file and passed as stdin to the command. The string is written as-is, you need to take care of using the correct line separators yourself. Pipes are not used. Note: Use |shellescape()| to escape special characters in a command argument. Newlines in {expr} may cause the command to fail. The characters in 'shellquote' and 'shellxquote' may also cause trouble. This is not to be used for interactive commands. The result is a String. Example: :let files = system("ls " . shellescape(expand('%:h'))) To make the result more system-independent, the shell output is filtered to replace <CR> with <NL> for Macintosh, and <CR><NL> with <NL> for DOS-like systems. The command executed is constructed using several options: 'shell' 'shellcmdflag' 'shellxquote' {expr} 'shellredir' {tmp} 'shellxquote' ({tmp} is an automatically generated file name). For Unix and OS/2 braces are put around {expr} to allow for concatenated commands. The command will be executed in "cooked" mode, so that a CTRL-C will interrupt the command (on Unix at least). The resulting error code can be found in |v:shell_error|. This function will fail in |restricted-mode|. Note that any wrong value in the options mentioned above may make the function fail. It has also been reported to fail when using a security agent application. Unlike ":!cmd" there is no automatic check for changed files. Use |:checktime| to force a check. tabpagebuflist([{arg}]) *tabpagebuflist()* The result is a |List|, where each item is the number of the buffer associated with each window in the current tab page. {arg} specifies the number of tab page to be used. When omitted the current tab page is used. When {arg} is invalid the number zero is returned. To get a list of all buffers in all tabs use this: tablist = [] for i in range(tabpagenr('$')) call extend(tablist, tabpagebuflist(i + 1)) endfor Note that a buffer may appear in more than one window. tabpagenr([{arg}]) *tabpagenr()* The result is a Number, which is the number of the current tab page. The first tab page has number 1. When the optional argument is "$", the number of the last tab page is returned (the tab page count). The number can be used with the |:tab| command. tabpagewinnr({tabarg}, [{arg}]) *tabpagewinnr()* Like |winnr()| but for tab page {arg}. {tabarg} specifies the number of tab page to be used. {arg} is used like with YXXYwinnr()|: - When omitted the current window number is returned. This is the window which will be used when going to this tab page. - When "$" the number of windows is returned. - When "#" the previous window nr is returned. Useful examples: tabpagewinnr(1) " current window of tab page 1 tabpagewinnr(4, '$') " number of windows in tab page 4 When {tabarg} is invalid zero is returned. *tagfiles()* tagfiles() Returns a |List| with the file names used to search for tags for the current buffer. This is the 'tags' option expanded. taglist({expr}) *taglist()* Returns a list of tags matching the regular expression {expr}. Each list item is a dictionary with at least the following entries: name Name of the tag. filename Name of the file where the tag is defined. It is either relative to the current directory or a full path. cmd Ex command used to locate the tag in the file. kind Type of the tag. The value for this entry depends on the language specific kind values. Only available when using a tags file generated by Exuberant ctags or hdrtag. static A file specific tag. Refer to |static-tag| for more information. More entries may be present, depending on the content of the tags file: access, implementation, inherits and signature. Refer to the ctags documentation for information about these fields. For C code the fields "struct", "class" and "enum" may appear, they give the name of the entity the tag is contained in. The ex-command 'cmd' can be either an ex search pattern, a line number or a line number followed by a byte number. If there are no matching tags, then an empty list is returned. To get an exact tag match, the anchors '^' and '$' should be used in {expr}. Refer to |tag-regexp| for more information about the tag search regular expression pattern. Refer to |'tags'| for information about how the tags file is located by Vim. Refer to |tags-file-format| for the format of the tags file generated by the different ctags tools. tempname() *tempname()* *temp-file-name* The result is a String, which is the name of a file that doesn't exist. It can be used for a temporary file. The name is different for at least 26 consecutive calls. Example: :let tmpfile = tempname() :exe "redir > " . tmpfile For Unix, the file will be in a private directory (only accessible by the current user) to avoid security problems (e.g., a symlink attack or other people reading your file). When Vim exits the directory and all files in it are deleted. For MS-Windows forward slashes are used when the 'shellslash' option is set or when 'shellcmdflag' starts with '-'. tolower({expr}) *tolower()* The result is a copy of the String given, with all uppercase characters turned into lowercase (just like applying |gu| to the string). toupper({expr}) *toupper()* The result is a copy of the String given, with all lowercase characters turned into uppercase (just like applying |gU| to the string). tr({src}, {fromstr}, {tostr}) *tr()* The result is a copy of the {src} string with all characters which appear in {fromstr} replaced by the character in that position in the {tostr} string. Thus the first character in {fromstr} is translated into the first character in {tostr} and so on. Exactly like the unix "tr" command. This code also deals with multibyte characters properly. Examples: echo tr("hello there", "ht", "HT") returns "Hello THere" echo tr("<blob>", "<>", "{}") returns "{blob}" trunc({expr}) *trunc()* Return the largest integral value with magnitude less than or equal to {expr} as a |Float| (truncate towards zero). {expr} must evaluate to a |Float| or a |Number|. Examples: echo trunc(1.456) 1.0 echo trunc(-5.456) -5.0 echo trunc(4.0) 4.0 {only available when compiled with the |+float| feature} *type()* type({expr}) The result is a Number, depending on the type of {expr}: Number: 0 String: 1 Funcref: 2 List: 3 Dictionary: 4 Float: 5 To avoid the magic numbers it should be used this way: :if type(myvar) == type(0) :if type(myvar) == type("") :if type(myvar) == type(function("tr")) :if type(myvar) == type([]) :if type(myvar) == type({}) :if type(myvar) == type(0.0) values({dict}) *values()* Return a |List| with all the values of {dict}. The |List| is in arbitrary order. virtcol({expr}) *virtcol()* The result is a Number, which is the screen column of the file position given with {expr}. That is, the last screen position occupied by the character at that position, when the screen would be of unlimited width. When there is a <Tab> at the position, the returned Number will be the column at the end of the <Tab>. For example, for a <Tab> in column 1, with 'ts' set to 8, it returns 8. For the byte position use |col()|. For the use of {expr} see |col()|. When 'virtualedit' is used {expr} can be [lnum, col, off], where "off" is the offset in screen columns from the start of the character. E.g., a position within a <Tab> or after the last character. When Virtual editing is active in the current mode, a position beyond the end of the line can be returned. |'virtualedit'| The accepted positions are: . the cursor position $ the end of the cursor line (the result is the number of displayed characters in the cursor line plus one) 'x position of mark x (if the mark is not set, 0 is returned) Note that only marks in the current file can be used. Examples: virtcol(".") with text "foo^Lbar", with cursor on the "^L", returns 5 virtcol("$") with text "foo^Lbar", returns 9 virtcol("'t") with text " there", with 't at 'h', returns 6 The first column is 1. 0 is returned for an error. A more advanced example that echoes the maximum length of all lines: echo max(map(range(1, line('$')), "virtcol([v:val, '$'])")) visualmode([expr]) *visualmode()* The result is a String, which describes the last Visual mode used in the current buffer. Initially it returns an empty string, but once Visual mode has been used, it returns "v", "V", or "<CTRL-V>" (a single CTRL-V character) for character-wise, line-wise, or block-wise Visual mode respectively. Example: :exe "normal " . visualmode() This enters the same Visual mode as before. It is also useful in scripts if you wish to act differently depending on the Visual mode that was used. If Visual mode is active, use |mode()| to get the Visual mode (e.g., in a |:vmap|). *non-zero-arg* If [expr] is supplied and it evaluates to a non-zero Number or a non-empty String, then the Visual mode will be cleared and the old value is returned. Note that " " and "0" are also non-empty strings, thus cause the mode to be cleared. A List, Dictionary or Float is not a Number or String, thus does not cause the mode to be cleared. *winbufnr()* winbufnr({nr}) The result is a Number, which is the number of the buffer associated with window {nr}. When {nr} is zero, the number of the buffer in the current window is returned. When window {nr} doesn't exist, -1 is returned. Example: :echo "The file in the current window is " . bufname(winbufnr(0)) *wincol()* wincol() The result is a Number, which is the virtual column of the cursor in the window. This is counting screen cells from the left side of the window. The leftmost column is one. winheight({nr}) *winheight()* The result is a Number, which is the height of window {nr}. When {nr} is zero, the height of the current window is returned. When window {nr} doesn't exist, -1 is returned. An existing window always has a height of zero or more. Examples: :echo "The current window has " . winheight(0) . " lines." *winline()* winline() The result is a Number, which is the screen line of the cursor in the window. This is counting screen lines from the top of the window. The first line is one. If the cursor was moved the view on the file will be updated first, this may cause a scroll. *winnr()* winnr([{arg}]) The result is a Number, which is the number of the current window. The top window has number 1. When the optional argument is "$", the number of the last window is returned (the window count). When the optional argument is "#", the number of the last accessed window is returned (where |CTRL-W_p| goes to). If there is no previous window or it is in another tab page 0 is returned. The number can be used with |CTRL-W_w| and ":wincmd w" |:wincmd|. Also see |tabpagewinnr()|. *winrestcmd()* winrestcmd() Returns a sequence of |:resize| commands that should restore the current window sizes. Only works properly when no windows are opened or closed and the current window and tab page is unchanged. Example: :let cmd = winrestcmd() :call MessWithWindowSizes() :exe cmd *winrestview()* winrestview({dict}) Uses the |Dictionary| returned by |winsaveview()| to restore the view of the current window. If you have changed the values the result is unpredictable. If the window size changed the result won't be the same. *winsaveview()* winsaveview() Returns a |Dictionary| that contains information to restore the view of the current window. Use |winrestview()| to restore the view. This is useful if you have a mapping that jumps around in the buffer and you want to go back to the original view. This does not save fold information. Use the 'foldenable' option to temporarily switch off folding, so that folds are not opened when moving around. The return value includes: lnum cursor line number col cursor column coladd cursor column offset for 'virtualedit' curswant column for vertical movement topline first line in the window topfill filler lines, only in diff mode leftcol first column displayed skipcol columns skipped Note that no option values are saved. winwidth({nr}) *winwidth()* The result is a Number, which is the width of window {nr}. When {nr} is zero, the width of the current window is returned. When window {nr} doesn't exist, -1 is returned. An existing window always has a width of zero or more. Examples: :echo "The current window has " . winwidth(0) . " columns." :if winwidth(0) <= 50 : exe "normal 50\<C-W>|" :endif *writefile()* writefile({list}, {fname} [, {binary}]) Write |List| {list} to file {fname}. Each list item is separated with a NL. Each list item must be a String or Number. When {binary} is equal to "b" binary mode is used: There will not be a NL after the last list item. An empty item at the end does cause the last line in the file to end in a NL. All NL characters are replaced with a NUL character. Inserting CR characters needs to be done before passing {list} to writefile(). An existing file is overwritten, if possible. When the write fails -1 is returned, otherwise 0. There is an error message if the file can't be created or when writing fails. Also see |readfile()|. To copy a file byte for byte: :let fl = readfile("foo", "b") :call writefile(fl, "foocopy", "b") *feature-list* There are three types of features: 1. Features that are only supported when they have been enabled when Vim was compiled |+feature-list|. Example: :if has("cindent") 2. Features that are only supported when certain conditions have been met. Example: :if has("gui_running") *has-patch* 3. Included patches. First check |v:version| for the version of Vim. Then the "patch123" feature means that patch 123 has been included for this version. Example (checking version 6.2.148 or later): :if v:version > 602 || v:version == 602 && has("patch148") Note that it's possible for patch 147 to be omitted even though 148 is included. all_builtin_terms Compiled with all builtin terminals enabled. amiga Amiga version of Vim. arabic Compiled with Arabic support |Arabic|. arp Compiled with ARP support (Amiga). autocmd Compiled with autocommand support. |autocommand| balloon_eval Compiled with |balloon-eval| support. balloon_multiline GUI supports multiline balloons. beos BeOS version of Vim. browse Compiled with |:browse| support, and browse() will work. builtin_terms Compiled with some builtin terminals. byte_offset Compiled with support for 'o' in 'statusline' cindent Compiled with 'cindent' support. clientserver Compiled with remote invocation support |clientserver|. clipboard Compiled with 'clipboard' support. cmdline_compl Compiled with |cmdline-completion| support. cmdline_hist Compiled with |cmdline-history| support. cmdline_info Compiled with 'showcmd' and 'ruler' support. comments Compiled with |'comments'| support. cryptv Compiled with encryption support |encryption|. cscope Compiled with |cscope| support. compatible Compiled to be very Vi compatible. debug Compiled with "DEBUG" defined. dialog_con Compiled with console dialog support. dialog_gui Compiled with GUI dialog support. diff Compiled with |vimdiff| and 'diff' support. digraphs Compiled with support for digraphs. dnd Compiled with support for the "~ register |quote_~|. dos32 32 bits DOS (DJGPP) version of Vim. dos16 16 bits DOS version of Vim. ebcdic Compiled on a machine with ebcdic character set. emacs_tags Compiled with support for Emacs tags. eval Compiled with expression evaluation support. Always true, of course! ex_extra Compiled with extra Ex commands |+ex_extra|. extra_search Compiled with support for |'incsearch'| and |'hlsearch'| farsi Compiled with Farsi support |farsi|. file_in_path Compiled with support for |gf| and |<cfile>| filterpipe When 'shelltemp' is off pipes are used for shell read/write/filter commands find_in_path Compiled with support for include file searches |+find_in_path|. float Compiled with support for |Float|. fname_case Case in file names matters (for Amiga, MS-DOS, and Windows this is not present). folding Compiled with |folding| support. footer Compiled with GUI footer support. |gui-footer| fork Compiled to use fork()/exec() instead of system(). gettext Compiled with message translation |multi-lang| gui Compiled with GUI enabled. gui_athena Compiled with Athena GUI. gui_gtk Compiled with GTK+ GUI (any version). gui_gtk2 Compiled with GTK+ 2 GUI (gui_gtk is also defined). gui_gnome Compiled with Gnome support (gui_gtk is also defined). gui_mac Compiled with Macintosh GUI. gui_motif Compiled with Motif GUI. gui_photon Compiled with Photon GUI. gui_win32 Compiled with MS Windows Win32 GUI. gui_win32s idem, and Win32s system being used (Windows 3.1) gui_running Vim is running in the GUI, or it will start soon. hangul_input Compiled with Hangul input support. |hangul| iconv Can use iconv() for conversion. insert_expand Compiled with support for CTRL-X expansion commands in Insert mode. jumplist Compiled with |jumplist| support. keymap Compiled with 'keymap' support. langmap Compiled with 'langmap' support. libcall Compiled with |libcall()| support. linebreak Compiled with 'linebreak', 'breakat' and 'showbreak' support. lispindent Compiled with support for lisp indenting. listcmds Compiled with commands for the buffer list |:files| and the argument list |arglist|. localmap Compiled with local mappings and abbr. |:map-local| mac Macintosh version of Vim. macunix Macintosh version of Vim, using Unix files (OS-X). menu Compiled with support for |:menu|. mksession Compiled with support for |:mksession|. modify_fname Compiled with file name modifiers. |filename-modifiers| mouse Compiled with support mouse. mouseshape Compiled with support for 'mouseshape'. mouse_dec Compiled with support for Dec terminal mouse. mouse_gpm Compiled with support for gpm (Linux console mouse) mouse_netterm Compiled with support for netterm mouse. mouse_pterm Compiled with support for qnx pterm mouse. mouse_sysmouse Compiled with support for sysmouse (*BSD console mouse) mouse_xterm Compiled with support for xterm mouse. multi_byte Compiled with support for 'encoding' multi_byte_encoding 'encoding' is set to a multi-byte encoding. multi_byte_ime Compiled with support for IME input method. multi_lang Compiled with support for multiple languages. mzscheme Compiled with MzScheme interface |mzscheme|. netbeans_intg Compiled with support for |netbeans|. netbeans_enabled Compiled with support for |netbeans| and it's used. ole Compiled with OLE automation support for Win32. os2 OS/2 version of Vim. osfiletype Compiled with support for osfiletypes |+osfiletype| path_extra Compiled with up/downwards search in 'path' and 'tags' perl Compiled with Perl interface. postscript Compiled with PostScript file printing. printer Compiled with |:hardcopy| support. profile Compiled with |:profile| support. python Compiled with Python interface. qnx QNX version of Vim. quickfix Compiled with |quickfix| support. reltime Compiled with |reltime()| support. rightleft Compiled with 'rightleft' support. ruby Compiled with Ruby interface |ruby|. scrollbind Compiled with 'scrollbind' support. showcmd Compiled with 'showcmd' support. signs Compiled with |:sign| support. smartindent Compiled with 'smartindent' support. sniff Compiled with SNiFF interface support. statusline Compiled with support for 'statusline', 'rulerformat' and special formats of 'titlestring' and 'iconstring'. sun_workshop Compiled with support for Sun |workshop|. spell Compiled with spell checking support |spell|. syntax Compiled with syntax highlighting support |syntax|. syntax_items There are active syntax highlighting items for the current buffer. system Compiled to use system() instead of fork()/exec(). tag_binary Compiled with binary searching in tags files |tag-binary-search|. tag_old_static Compiled with support for old static tags |tag-old-static|. tag_any_white Compiled with support for any white characters in tags files |tag-any-white|. tcl Compiled with Tcl interface. terminfo Compiled with terminfo instead of termcap. termresponse Compiled with support for |t_RV| and |v:termresponse|. textobjects Compiled with support for |text-objects|. tgetent Compiled with tgetent support, able to use a termcap or terminfo file. title Compiled with window title support |'title'|. toolbar Compiled with support for |gui-toolbar|. unix Unix version of Vim. user_commands User-defined commands. viminfo Compiled with viminfo support. vim_starting True while initial source'ing takes place. vertsplit Compiled with vertically split windows |:vsplit|. virtualedit Compiled with 'virtualedit' option. visual Compiled with Visual mode. visualextra Compiled with extra Visual mode commands. |blockwise-operators|. vms VMS version of Vim. vreplace Compiled with |gR| and |gr| commands. wildignore Compiled with 'wildignore' option. wildmenu Compiled with 'wildmenu' option. windows Compiled with support for more than one window. winaltkeys Compiled with 'winaltkeys' option. win16 Win16 version of Vim (MS-Windows 3.1). win32 Win32 version of Vim (MS-Windows 95/98/ME/NT/2000/XP). win64 Win64 version of Vim (MS-Windows 64 bit). win32unix Win32 version of Vim, using Unix files (Cygwin) win95 Win32 version for MS-Windows 95/98/ME. writebackup Compiled with 'writebackup' default on. xfontset Compiled with X fontset support |xfontset|. xim Compiled with X input method support |xim|. xsmp Compiled with X session management support. xsmp_interact Compiled with interactive X session management support. xterm_clipboard Compiled with support for xterm clipboard. xterm_save Compiled with support for saving and restoring the xterm screen. x11 Compiled with X11 support. *string-match* Matching a pattern in a String A regexp pattern as explained at |pattern| is normally used to find a match in the buffer lines. When a pattern is used to find a match in a String, almost everything works in the same way. The difference is that a String is handled like it is one line. When it contains a "\n" character, this is not seen as a line break for the pattern. It can be matched with a "\n" in the pattern, or with ".". Example: :let a = "aaaa\nxxxx" :echo matchstr(a, "..\n..") aa xx :echo matchstr(a, "a.x") a x Don't forget that "^" will only match at the first character of the String and "$" at the last character of the string. They don't match after or before a "\n".
5. Defining functions *user-functions* 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 avoid obvious, short names. A good habit is to start the function name with the name of the script, e.g., "HTMLcolor()". It's also possible to use curly braces, see |curly-braces-names|. And the |autoload| facility is useful to define a function only when it's called. *local-function* A function local to a 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. *:fu* *:function* *E128* *E129* *E123* :fu[nction] List all functions and their arguments. :fu[nction] {name} List function {name}. {name} can also be a |Dictionary| entry that is a YXXYFuncref|: :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* :fu[nction][!] {name}([arguments]) [range] [abort] [dict] Define a new function by the name {name}. The name must be made of alphanumeric characters and '_', and must start with a capital or "s:" (see above). {name} can also be a |Dictionary| entry that is a YXXYFuncref|: :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. When [!] is used, an existing function is silently replaced. Unless it is currently being executed, that is an error. For the {arguments} see |function-argument|. *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|. When the [abort] argument is added, the function will abort as soon as an error is detected. 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|. *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* :endf[unction] The end of a function definition. Must be on a line by its own, without other commands. *:delf* *:delfunction* *E130* *E131* :delf[unction] {name} Delete function {name}. {name} can also be a |Dictionary| entry that is a YXXYFuncref|: :delfunc dict.init This will remove the "init" entry from "dict". The function is deleted if there are no more references to it. *: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. Note that 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* The a: scope and the variables in it cannot be changed, they are fixed. However, if a |List| or |Dictionary| is used, 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|. When not using "...", the number of arguments in a function call must be equal to the number of named arguments. When using "...", the number of arguments may be larger. It is also possible to define a function without any arguments. You must still supply the () then. The body of the function follows in the next lines, until the matching |:endfunction|. It is allowed to define another function inside a function body. *local-variables* Inside a function variables can be used. These are local variables, which will disappear when the function returns. Global variables need to be accessed with "g:". 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 YXXYList|: :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 *:cal* *:call* *E107* *E117* :[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. 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. *E132* The recursiveness of user functions is restricted with the |'maxfuncdepth'| option. 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'. Using an autocommand This is introduced in the user manual, section |41.14|. 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 |41.15|. 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() 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. 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, the script will be sourced every time you try to call the function. And you will get an error message every time. 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.  Also read the user manual |distribute-script|.
6. Curly braces names *curly-braces-names* Wherever you can use a variable, you can use a "curly braces name" variable. This is a regular variable name with one or more expressions wrapped in braces {} like this: my_{adjective}_variable When Vim encounters this, it evaluates the expression inside the braces, puts that in place of the expression, and re-interprets the whole as a variable name. So in the above example, if the variable "adjective" was set to "noisy", then the reference would be to "my_noisy_variable", whereas if "adjective" was set to "quiet", then it would be to "my_quiet_variable". One application for this is to create a set of variables governed by an option value. For example, the statement echo my_{&background}_message would output the contents of "my_dark_message" or "my_light_message" depending on the current value of 'background'. You can use multiple brace pairs: echo my_{adverb}_{adjective}_message ..or even nest them: echo my_{ad{end_of_word}}_message where "end_of_word" is either "verb" or "jective". However, the expression inside the braces must evaluate to a valid single variable name, e.g. this is invalid: :let foo='a + b' :echo c{foo}d .. since the result of expansion is "ca + bd", which is not a variable name. *curly-braces-function-names* You can call and define functions by an evaluated name in a similar way. Example: :let func_end='whizz' :call my_func_{func_end}(parameter) This would call the function "my_func_whizz(parameter)".
7. Commands *expression-commands* :let {var-name} = {expr1} *:let* *E18* Set internal variable {var-name} to the result of the expression {expr1}. The variable will get the type from the {expr}. If {var-name} didn't exist yet, it is created. :let {var-name}[{idx}] = {expr1} *E689* Set a list item to the result of the expression {expr1}. {var-name} must refer to a list and {idx} must be a valid index in that list. For nested list the index can be repeated. This cannot be used to add an item to a |List|. This cannot be used to set a byte in a String. You can do that like this: :let var = var[0:2] . 'X' . var[4:] *E711* *E719* :let {var-name}[{idx1}:{idx2}] = {expr1} *E708* *E709* *E710* Set a sequence of items in a |List| to the result of the expression {expr1}, which must be a list with the correct number of items. {idx1} can be omitted, zero is used instead. {idx2} can be omitted, meaning the end of the list. When the selected range of items is partly past the end of the list, items will be added. *:let+=* *:let-=* *:let.=* *E734* :let {var} += {expr1} Like ":let {var} = {var} + {expr1}". :let {var} -= {expr1} Like ":let {var} = {var} - {expr1}". :let {var} .= {expr1} Like ":let {var} = {var} . {expr1}". These fail if {var} was not set yet and when the type of {var} and {expr1} don't fit the operator. :let ${env-name} = {expr1} *:let-environment* *:let-$* Set environment variable {env-name} to the result of the expression {expr1}. The type is always String. :let ${env-name} .= {expr1} Append {expr1} to the environment variable {env-name}. If the environment variable didn't exist yet this works like "=". :let @{reg-name} = {expr1} *:let-register* *:let-@* Write the result of the expression {expr1} in register {reg-name}. {reg-name} must be a single letter, and must be the name of a writable register (see |registers|). "@@" can be used for the unnamed register, "@/" for the search pattern. If the result of {expr1} ends in a <CR> or <NL>, the register will be linewise, otherwise it will be set to characterwise. This can be used to clear the last search pattern: :let @/ = "" This is different from searching for an empty string, that would match everywhere. :let @{reg-name} .= {expr1} Append {expr1} to register {reg-name}. If the register was empty it's like setting it to {expr1}. :let &{option-name} = {expr1} *:let-option* *:let-&* Set option {option-name} to the result of the expression {expr1}. A String or Number value is always converted to the type of the option. For an option local to a window or buffer the effect is just like using the |:set| command: both the local value and the global value are changed. Example: :let &path = &path . ',/usr/local/include' :let &{option-name} .= {expr1} For a string option: Append {expr1} to the value. Does not insert a comma like |:set+=|. :let &{option-name} += {expr1} :let &{option-name} -= {expr1} For a number or boolean option: Add or subtract {expr1}. :let &l:{option-name} = {expr1} :let &l:{option-name} .= {expr1} :let &l:{option-name} += {expr1} :let &l:{option-name} -= {expr1} Like above, but only set the local value of an option (if there is one). Works like |:setlocal|. :let &g:{option-name} = {expr1} :let &g:{option-name} .= {expr1} :let &g:{option-name} += {expr1} :let &g:{option-name} -= {expr1} Like above, but only set the global value of an option (if there is one). Works like |:setglobal|. :let [{name1}, {name2}, ...] = {expr1} *:let-unpack* *E687* *E688* {expr1} must evaluate to a |List|. The first item in the list is assigned to {name1}, the second item to {name2}, etc. The number of names must match the number of items in the |List|. Each name can be one of the items of the ":let" command as mentioned above. Example: :let [s, item] = GetItem(s) Detail: {expr1} is evaluated first, then the assignments are done in sequence. This matters if {name2} depends on {name1}. Example: :let x = [0, 1] :let i = 0 :let [i, x[i]] = [1, 2] :echo x The result is [0, 2]. :let [{name1}, {name2}, ...] .= {expr1} :let [{name1}, {name2}, ...] += {expr1} :let [{name1}, {name2}, ...] -= {expr1} Like above, but append/add/subtract the value for each |List| item. :let [{name}, ..., ; {lastname}] = {expr1} Like |:let-unpack| above, but the |List| may have more items than there are names. A list of the remaining items is assigned to {lastname}. If there are no remaining items {lastname} is set to an empty list. Example: :let [a, b; rest] = ["aval", "bval", 3, 4] :let [{name}, ..., ; {lastname}] .= {expr1} :let [{name}, ..., ; {lastname}] += {expr1} :let [{name}, ..., ; {lastname}] -= {expr1} Like above, but append/add/subtract the value for each |List| item. *E106* :let {var-name} .. List the value of variable {var-name}. Multiple variable names may be given. Special names recognized here: *E738* g: global variables b: local buffer variables w: local window variables t: local tab page variables s: script-local variables l: local function variables v: Vim variables. :let List the values of all variables. The type of the variable is indicated before the value: <nothing> String # Number * Funcref :unl[et][!] {name} ... *:unlet* *:unl* *E108* *E795* Remove the internal variable {name}. Several variable names can be given, they are all removed. The name may also be a |List| or |Dictionary| item. With [!] no error message is given for non-existing variables. One or more items from a |List| can be removed: :unlet list[3] " remove fourth item :unlet list[3:] " remove fourth item to last One item from a |Dictionary| can be removed at a time: :unlet dict['two'] :unlet dict.two This is especially useful to clean up used global variables and script-local variables (these are not deleted when the script ends). Function-local variables are automatically deleted when the function ends. :lockv[ar][!] [depth] {name} ... *:lockvar* *:lockv* Lock the internal variable {name}. Locking means that it can no longer be changed (until it is unlocked). A locked variable can be deleted: :lockvar v :let v = 'asdf' " fails! :unlet v *E741* If you try to change a locked variable you get an error message: "E741: Value of {name} is locked" [depth] is relevant when locking a |List| or |Dictionary|. It specifies how deep the locking goes: 1 Lock the |List| or |Dictionary| itself, cannot add or remove items, but can still change their values. 2 Also lock the values, cannot change the items. If an item is a |List| or |Dictionary|, cannot add or remove items, but can still change the values. 3 Like 2 but for the |List| / |Dictionary| in the |List| / |Dictionary|, one level deeper. The default [depth] is 2, thus when {name} is a |List| or |Dictionary| the values cannot be changed. *E743* For unlimited depth use [!] and omit [depth]. However, there is a maximum depth of 100 to catch loops. Note that when two variables refer to the same |List| and you lock one of them, the |List| will also be locked when used through the other variable. Example: :let l = [0, 1, 2, 3] :let cl = l :lockvar l :let cl[1] = 99 " won't work! You may want to make a copy of a list to avoid this. See |deepcopy()|. :unlo[ckvar][!] [depth] {name} ... *:unlockvar* *:unlo* Unlock the internal variable {name}. Does the opposite of |:lockvar|. :if {expr1} *:if* *:endif* *:en* *E171* *E579* *E580* :en[dif] Execute the commands until the next matching ":else" or ":endif" if {expr1} evaluates to non-zero. From Vim version 4.5 until 5.0, every Ex command in between the ":if" and ":endif" is ignored. These two commands were just to allow for future expansions in a backwards compatible way. Nesting was allowed. Note that any ":else" or ":elseif" was ignored, the "else" part was not executed either. You can use this to remain compatible with older versions: :if version >= 500 : version-5-specific-commands :endif The commands still need to be parsed to find the "endif". Sometimes an older Vim has a problem with a new command. For example, ":silent" is recognized as a ":substitute" command. In that case ":execute" can avoid problems: :if version >= 600 : execute "silent 1,$delete" :endif NOTE: The ":append" and ":insert" commands don't work properly in between ":if" and ":endif". *:else* *:el* *E581* *E583* :el[se] Execute the commands until the next matching ":else" or ":endif" if they previously were not being executed. *:elseif* *:elsei* *E582* *E584* :elsei[f] {expr1} Short for ":else" ":if", with the addition that there is no extra ":endif". :wh[ile] {expr1} *:while* *:endwhile* *:wh* *:endw* *E170* *E585* *E588* *E733* :endw[hile] Repeat the commands between ":while" and ":endwhile", as long as {expr1} evaluates to non-zero. When an error is detected from a command inside the loop, execution continues after the "endwhile". Example: :let lnum = 1 :while lnum <= line("$") :call FixLine(lnum) :let lnum = lnum + 1 :endwhile NOTE: The ":append" and ":insert" commands don't work properly inside a ":while" and ":for" loop. :for {var} in {list} *:for* *E690* *E732* :endfo[r] *:endfo* *:endfor* Repeat the commands between ":for" and ":endfor" for each item in {list}. Variable {var} is set to the value of each item. When an error is detected for a command inside the loop, execution continues after the "endfor". Changing {list} inside the loop affects what items are used. Make a copy if this is unwanted: :for item in copy(mylist) When not making a copy, Vim stores a reference to the next item in the list, before executing the commands with the current item. Thus the current item can be removed without effect. Removing any later item means it will not be found. Thus the following example works (an inefficient way to make a list empty): :for item in mylist :call remove(mylist, 0) :endfor Note that reordering the list (e.g., with sort() or reverse()) may have unexpected effects. Note that the type of each list item should be identical to avoid errors for the type of {var} changing. Unlet the variable at the end of the loop to allow multiple item types. :for [{var1}, {var2}, ...] in {listlist} :endfo[r] Like ":for" above, but each item in {listlist} must be a list, of which each item is assigned to {var1}, {var2}, etc. Example: :for [lnum, col] in [[1, 3], [2, 5], [3, 8]] :echo getline(lnum)[col] :endfor *:continue* *:con* *E586* :con[tinue] When used inside a ":while" or ":for" loop, jumps back to the start of the loop. If it is used after a |:try| inside the loop 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 loop. The outermost ":endtry" then jumps back to the start of the loop. *:break* *:brea* *E587* :brea[k] When used inside a ":while" or ":for" loop, skips to the command after the matching ":endwhile" or ":endfor". If it is used after a |:try| inside the loop 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 loop. The outermost ":endtry" then jumps to the command after the loop. :try *:try* *:endt* *:endtry* *E600* *E601* *E602* :endt[ry] Change the error handling for the commands between ":try" and ":endtry" including everything being executed across ":source" commands, function calls, or autocommand invocations. When an error or interrupt is detected and there is a |:finally| command following, execution continues after the ":finally". Otherwise, or when the ":endtry" is reached thereafter, the next (dynamically) surrounding ":try" is checked for a corresponding ":finally" etc. Then the script processing is terminated. (Whether a function definition has an "abort" argument does not matter.) Example: :try | edit too much | finally | echo "cleanup" | endtry :echo "impossible" " not reached, script terminated above Moreover, an error or interrupt (dynamically) inside ":try" and ":endtry" is converted to an exception. It can be caught as if it were thrown by a |:throw| command (see |:catch|). In this case, the script processing is not terminated. The value "Vim:Interrupt" is used for an interrupt exception. An error in a Vim command is converted to a value of the form "Vim({command}):{errmsg}", other errors are converted to a value of the form "Vim:{errmsg}". {command} is the full command name, and {errmsg} is the message that is displayed if the error exception is not caught, always beginning with the error number. Examples: :try | sleep 100 | catch /^Vim:Interrupt$/ | endtry :try | edit | catch /^Vim(edit):E\d\+/ | echo "error" | endtry *:cat* *:catch* *E603* *E604* *E605* :cat[ch] /{pattern}/ The following commands until the next ":catch", |:finally|, or |:endtry| that belongs to the same |:try| as the ":catch" are executed when an exception matching {pattern} is being thrown and has not yet been caught by a previous ":catch". Otherwise, these commands are skipped. When {pattern} is omitted all errors are caught.  Another character can be used instead of / around the {pattern}, so long as it does not have a special meaning (e.g., '|' or '"'') and doesn't occur inside {pattern}. NOTE: It is not reliable to ":catch" the TEXT of an error message because it may vary in different locales. *:fina* *:finally* *E606* *E607* :fina[lly] The following commands until the matching |:endtry| are executed whenever the part between the matching |:try| and the ":finally" is left: either by falling through to the ":finally" or by a |:continue|, |:break|, |:finish|, or |:return|, or by an error or interrupt or exception (see |:throw|). *:th* *:throw* *E608* :th[row] {expr1} The {expr1} is evaluated and thrown as an exception. If the ":throw" is used after a |:try| but before the first corresponding |:catch|, commands are skipped until the first ":catch" matching {expr1} is reached. If there is no such ":catch" or if the ":throw" is used after a ":catch" but before the |:finally|, the commands following the ":finally" (if present) up to the matching |:endtry| are executed. If the ":throw" is after the ":finally", commands up to the ":endtry" are skipped. At the ":endtry", this process applies again for the next dynamically surrounding ":try" (which may be found in a calling function or sourcing script), until a matching ":catch" has been found. If the exception is not caught, the command processing is terminated. Example: :try | throw "oops" | catch /^oo/ | echo "caught" | endtry *:ec* *:echo* :ec[ho] {expr1} .. Echoes each {expr1}, with a space in between. The first {expr1} starts on a new line. Also see |:comment|. Use "\n" to start a new line. Use "\r" to move the cursor to the first column. Uses the highlighting set by the |:echohl| command. Cannot be followed by a comment. Example: :echo "the value of 'shell' is" &shell *:echo-redraw* A later redraw may make the message disappear again. And since Vim mostly postpones redrawing until it's finished with a sequence of commands this happens quite often. To avoid that a command from before the ":echo" causes a redraw afterwards (redraws are often postponed until you type something), force a redraw with the |:redraw| command. Example: :new | redraw | echo "there is a new window" *:echon* :echon {expr1} .. Echoes each {expr1}, without anything added. Also see |:comment|. Uses the highlighting set by the |:echohl| command. Cannot be followed by a comment. Example: :echon "the value of 'shell' is " &shell Note the difference between using ":echo", which is a Vim command, and ":!echo", which is an external shell command: :!echo % --> filename The arguments of ":!" are expanded, see |:_%|. :!echo "%" --> filename or "filename" Like the previous example. Whether you see the double quotes or not depends on your 'shell'. :echo % --> nothing The '%' is an illegal character in an expression. :echo "%" --> % This just echoes the '%' character. :echo expand("%") --> filename This calls the expand() function to expand the '%'. *:echoh* *:echohl* :echoh[l] {name} Use the highlight group {name} for the following |:echo|, |:echon| and |:echomsg| commands. Also used for the |input()| prompt. Example: :echohl WarningMsg | echo "Don't panic!" | echohl None Don't forget to set the group back to "None", otherwise all following echo's will be highlighted. *:echom* *:echomsg* :echom[sg] {expr1} .. Echo the expression(s) as a true message, saving the message in the |message-history|. Spaces are placed between the arguments as with the |:echo| command. But unprintable characters are displayed, not interpreted. The parsing works slightly different from |:echo|, more like |:execute|. All the expressions are first evaluated and concatenated before echoing anything. The expressions must evaluate to a Number or String, a Dictionary or List causes an error. Uses the highlighting set by the |:echohl| command. Example: :echomsg "It's a Zizzer Zazzer Zuzz, as you can plainly see." See |:echo-redraw| to avoid the message disappearing when the screen is redrawn. *:echoe* *:echoerr* :echoe[rr] {expr1} .. Echo the expression(s) as an error message, saving the message in the |message-history|. When used in a script or function the line number will be added. Spaces are placed between the arguments as with the :echo command. When used inside a try conditional, the message is raised as an error exception instead (see |try-echoerr|). Example: :echoerr "This script just failed!" If you just want a highlighted message use |:echohl|. And to get a beep: :exe "normal \<Esc>" *:exe* *:execute* :exe[cute] {expr1} .. Executes the string that results from the evaluation of {expr1} as an Ex command. Multiple arguments are concatenated, with a space in between. {expr1} is used as the processed command, command line editing keys are not recognized. Cannot be followed by a comment. Examples: :execute "buffer " nextbuf :execute "normal " count . "w" ":execute" can be used to append a command to commands that don't accept a '|'. Example: :execute '!ls' | echo "theend" ":execute" is also a nice way to avoid having to type control characters in a Vim script for a ":normal" command: :execute "normal ixxx\<Esc>" This has an <Esc> character, see |expr-string|. Be careful to correctly escape special characters in file names. The |fnameescape()| function can be used for Vim commands, |shellescape()| for |:!| commands. Examples: :execute "e " . fnameescape(filename) :execute "!ls " . shellescape(expand('%:h'), 1) Note: The executed string may be any command-line, but you cannot start or end a "while", "for" or "if" command. Thus this is illegal: :execute 'while i > 5' :execute 'echo "test" | break' It is allowed to have a "while" or "if" command completely in the executed string: :execute 'while i < 5 | echo i | let i = i + 1 | endwhile' *:comment* ":execute", ":echo" and ":echon" cannot be followed by a comment directly, because they see the '"'' as the start of a string. But, you can use '|' followed by a comment. Example: :echo "foo" | "this is a comment
8. Exception handling *exception-handling* The Vim script language comprises an exception handling feature. This section explains how it can be used in a Vim script. Exceptions may be raised by Vim on an error or on interrupt, see |catch-errors| and |catch-interrupt|. You can also explicitly throw an exception by using the ":throw" command, see |throw-catch|. TRY CONDITIONALS *try-conditionals* Exceptions can be caught or can cause cleanup code to be executed. You can use a try conditional to specify catch clauses (that catch exceptions) and/or a finally clause (to be executed for cleanup). A try conditional begins with a |:try| command and ends at the matching |:endtry| command. In between, you can use a |:catch| command to start a catch clause, or a |:finally| command to start a finally clause. There may be none or multiple catch clauses, but there is at most one finally clause, which must not be followed by any catch clauses. The lines before the catch clauses and the finally clause is called a try block. :try : ... : ... TRY BLOCK : ... :catch /{pattern}/ : ... : ... CATCH CLAUSE : ... :catch /{pattern}/ : ... : ... CATCH CLAUSE : ... :finally : ... : ... FINALLY CLAUSE : ... :endtry The try conditional allows to watch code for exceptions and to take the appropriate actions. Exceptions from the try block may be caught. Exceptions from the try block and also the catch clauses may cause cleanup actions. When no exception is thrown during execution of the try block, the control is transferred to the finally clause, if present. After its execution, the script continues with the line following the ":endtry". When an exception occurs during execution of the try block, the remaining lines in the try block are skipped. The exception is matched against the patterns specified as arguments to the ":catch" commands. The catch clause after the first matching ":catch" is taken, other catch clauses are not executed. The catch clause ends when the next ":catch", ":finally", or ":endtry" command is reached - whatever is first.  When the ":endtry" is reached, the script execution continues in the following line as usual. When an exception that does not match any of the patterns specified by the ":catch" commands is thrown in the try block, the exception is not caught by that try conditional and none of the catch clauses is executed. Only the finally clause, if present, is taken. The exception pends during execution of the finally clause. It is resumed at the ":endtry", so that commands after the ":endtry" are not executed and the exception might be caught elsewhere, see |try-nesting|. When during execution of a catch clause another exception is thrown, the remaining lines in that catch clause are not executed. The new exception is not matched against the patterns in any of the ":catch" commands of the same try conditional and none of its catch clauses is taken. If there is, however, a finally clause, it is executed, and the exception pends during its execution. The commands following the ":endtry" are not executed. The new exception might, however, be caught elsewhere, see |try-nesting|. When during execution of the finally clause (if present) an exception is thrown, the remaining lines in the finally clause are skipped. If the finally clause has been taken because of an exception from the try block or one of the catch clauses, the original (pending) exception is discarded. The commands following the ":endtry" are not executed, and the exception from the finally clause is propagated and can be caught elsewhere, see |try-nesting|. The finally clause is also executed, when a ":break" or ":continue" for a ":while" loop enclosing the complete try conditional is executed from the try block or a catch clause. Or when a ":return" or ":finish" is executed from the try block or a catch clause of a try conditional in a function or sourced script, respectively. The ":break", ":continue", ":return", or ":finish" pends during execution of the finally clause and is resumed when the ":endtry" is reached. It is, however, discarded when an exception is thrown from the finally clause.  If the finally clause has been taken because of an exception or an earlier ":break", ":continue", ":return", or ":finish" from the try block or a catch clause, this pending exception or command is discarded. For examples see |throw-catch| and |try-finally|. NESTING OF TRY CONDITIONALS *try-nesting* Try conditionals can be nested arbitrarily.  If the inner try conditional does not catch an exception thrown in its try block or throws a new exception from one of its catch clauses or its finally clause, the outer try conditional is checked according to the rules above. If the inner try conditional is in the try block of the outer try conditional, its catch clauses are checked, but otherwise only the finally clause is executed. It does not matter for nesting, whether the inner try conditional is directly contained in the outer one, or whether the outer one sources a script or calls a function containing the inner try conditional. When none of the active try conditionals catches an exception, just their finally clauses are executed. Thereafter, the script processing terminates. An error message is displayed in case of an uncaught exception explicitly thrown by a ":throw" command. For uncaught error and interrupt exceptions implicitly raised by Vim, the error message(s) or interrupt message are shown as usual. For examples see |throw-catch|. EXAMINING EXCEPTION HANDLING CODE *except-examine* Exception handling code can get tricky. If you are in doubt what happens, set 'verbose' to 13 or use the ":13verbose" command modifier when sourcing your script file. Then you see when an exception is thrown, discarded, caught, or finished. When using a verbosity level of at least 14, things pending in a finally clause are also shown. This information is also given in debug mode (see |debug-scripts|). THROWING AND CATCHING EXCEPTIONS *throw-catch* You can throw any number or string as an exception. Use the |:throw| command and pass the value to be thrown as argument: :throw 4711 :throw "string" *throw-expression* You can also specify an expression argument. The expression is then evaluated first, and the result is thrown: :throw 4705 + strlen("string") :throw strpart("strings", 0, 6) An exception might be thrown during evaluation of the argument of the ":throw" command. Unless it is caught there, the expression evaluation is abandoned. The ":throw" command then does not throw a new exception. Example: :function! Foo(arg) : try : throw a:arg : catch /foo/ : endtry : return 1 :endfunction : :function! Bar() : echo "in Bar" : return 4710 :endfunction : :throw Foo("arrgh") + Bar() This throws "arrgh", and "in Bar" is not displayed since Bar() is not executed. :throw Foo("foo") + Bar() however displays "in Bar" and throws 4711. Any other command that takes an expression as argument might also be abandoned by an (uncaught) exception during the expression evaluation. The exception is then propagated to the caller of the command. Example: :if Foo("arrgh") : echo "then" :else : echo "else" :endif Here neither of "then" or "else" is displayed. *catch-order* Exceptions can be caught by a try conditional with one or more |:catch| commands, see |try-conditionals|. The values to be caught by each ":catch" command can be specified as a pattern argument. The subsequent catch clause gets executed when a matching exception is caught. Example: :function! Foo(value) : try : throw a:value : catch /^\d\+$/ : echo "Number thrown" : catch /.*/ : echo "String thrown" : endtry :endfunction : :call Foo(0x1267) :call Foo('string') The first call to Foo() displays "Number thrown", the second "String thrown". An exception is matched against the ":catch" commands in the order they are specified. Only the first match counts. So you should place the more specific ":catch" first. The following order does not make sense: : catch /.*/ : echo "String thrown" : catch /^\d\+$/ : echo "Number thrown" The first ":catch" here matches always, so that the second catch clause is never taken. *throw-variables* If you catch an exception by a general pattern, you may access the exact value in the variable YXXYv:exception|: : catch /^\d\+$/ : echo "Number thrown. Value is" v:exception You may also be interested where an exception was thrown. This is stored in |v:throwpoint|. Note that "v:exception" and "v:throwpoint" are valid for the exception most recently caught as long it is not finished. Example: :function! Caught() : if v:exception != "" : echo 'Caught "' . v:exception . '" in ' . v:throwpoint : else : echo 'Nothing caught' : endif :endfunction : :function! Foo() : try : try : try : throw 4711 : finally : call Caught() : endtry : catch /.*/ : call Caught() : throw "oops" : endtry : catch /.*/ : call Caught() : finally : call Caught() : endtry :endfunction : :call Foo() This displays Nothing caught Caught "4711" in function Foo, line 4 Caught "oops" in function Foo, line 10 Nothing caught A practical example: The following command ":LineNumber" displays the line number in the script or function where it has been used: :function! LineNumber() : return substitute(v:throwpoint, '.*\D\(\d\+\).*', '\1', "") :endfunction :command! LineNumber try | throw "" | catch | echo LineNumber() | endtry *try-nested* An exception that is not caught by a try conditional can be caught by a surrounding try conditional: :try : try : throw "foo" : catch /foobar/ : echo "foobar" : finally : echo "inner finally" : endtry :catch /foo/ : echo "foo" :endtry The inner try conditional does not catch the exception, just its finally clause is executed. The exception is then caught by the outer try conditional. The example displays "inner finally" and then "foo". *throw-from-catch* You can catch an exception and throw a new one to be caught elsewhere from the catch clause: :function! Foo() : throw "foo" :endfunction : :function!  Bar() : try : call Foo() : catch /.*/ : echo "Rethrow" v:exception : throw v:exception : endtry :endfunction *try-echoerr* Note that this method cannot be used to "rethrow" Vim error or interrupt exceptions, because it is not possible to fake Vim internal exceptions. Trying so causes an error exception.  If you want to cause a Vim error exception containing the original error exception value, you can use the |:echoerr| command: :try : try : asdf : catch /.*/ : echoerr v:exception : endtry :catch /.*/ : echo v:exception :endtry This code displays Vim(echoerr):Vim:E492: Not an editor command: asdf CLEANUP CODE *try-finally* Scripts often change global settings and restore them at their end. If the user however interrupts the script by pressing CTRL-C, the settings remain in an inconsistent state. The same may happen to you in the development phase of a script when an error occurs or you explicitly throw an exception without catching it. You can solve these problems by using a try conditional with a finally clause for restoring the settings. Its execution is guaranteed on normal control flow, on error, on an explicit ":throw", and on interrupt. (Note that errors and interrupts from inside the try conditional are converted to exceptions. When not caught, they terminate the script after the finally clause has been executed.) Example: :try : let s:saved_ts = &ts : set ts=17 : : " Do the hard work here. : :finally : let &ts = s:saved_ts : unlet s:saved_ts :endtry This method should be used locally whenever a function or part of a script changes global settings which need to be restored on failure or normal exit of that function or script part. *break-finally* Cleanup code works also when the try block or a catch clause is left by a ":continue", ":break", ":return", or ":finish". Example: :let first = 1 :while 1 : try : if first : echo "first" : let first = 0 : continue : else : throw "second" : endif : catch /.*/ : echo v:exception : break : finally : echo "cleanup" : endtry : echo "still in while" :endwhile :echo "end" This displays "first", "cleanup", "second", "cleanup", and "end". :function! Foo() : try : return 4711 : finally : echo "cleanup\n" : endtry : echo "Foo still active" :endfunction : :echo Foo() "returned by Foo" This displays "cleanup" and "4711 returned by Foo". You don't need to add an extra ":return" in the finally clause. (Above all, this would override the return value.) *except-from-finally* Using either of ":continue", ":break", ":return", ":finish", or ":throw" in a finally clause is possible, but not recommended since it abandons the cleanup actions for the try conditional. But, of course, interrupt and error exceptions might get raised from a finally clause. Example where an error in the finally clause stops an interrupt from working correctly: :try : try : echo "Press CTRL-C for interrupt" : while 1 : endwhile : finally : unlet novar : endtry :catch /novar/ :endtry :echo "Script still running" :sleep 1 If you need to put commands that could fail into a finally clause, you should think about catching or ignoring the errors in these commands, see |catch-errors| and |ignore-errors|. CATCHING ERRORS *catch-errors* If you want to catch specific errors, you just have to put the code to be watched in a try block and add a catch clause for the error message. The presence of the try conditional causes all errors to be converted to an exception. No message is displayed and |v:errmsg| is not set then. To find the right pattern for the ":catch" command, you have to know how the format of the error exception is. Error exceptions have the following format: Vim({cmdname}):{errmsg} or Vim:{errmsg} {cmdname} is the name of the command that failed; the second form is used when the command name is not known. {errmsg} is the error message usually produced when the error occurs outside try conditionals. It always begins with a capital "E", followed by a two or three-digit error number, a colon, and a space. Examples: The command :unlet novar normally produces the error message E108: No such variable: "novar" which is converted inside try conditionals to an exception Vim(unlet):E108: No such variable: "novar" The command :dwim normally produces the error message E492: Not an editor command: dwim which is converted inside try conditionals to an exception Vim:E492: Not an editor command: dwim You can catch all ":unlet" errors by a :catch /^Vim(unlet):/ or all errors for misspelled command names by a :catch /^Vim:E492:/ Some error messages may be produced by different commands: :function nofunc and :delfunction nofunc both produce the error message E128: Function name must start with a capital: nofunc which is converted inside try conditionals to an exception Vim(function):E128: Function name must start with a capital: nofunc or Vim(delfunction):E128: Function name must start with a capital: nofunc respectively. You can catch the error by its number independently on the command that caused it if you use the following pattern: :catch /^Vim(\a\+):E128:/ Some commands like :let x = novar produce multiple error messages, here: E121: Undefined variable: novar E15: Invalid expression: novar Only the first is used for the exception value, since it is the most specific one (see |except-several-errors|). So you can catch it by :catch /^Vim(\a\+):E121:/ You can catch all errors related to the name "nofunc" by :catch /\<nofunc\>/ You can catch all Vim errors in the ":write" and ":read" commands by :catch /^Vim(\(write\|read\)):E\d\+:/ You can catch all Vim errors by the pattern :catch /^Vim\((\a\+)\)\=:E\d\+:/ *catch-text* NOTE: You should never catch the error message text itself: :catch /No such variable/ only works in the english locale, but not when the user has selected a different language by the |:language| command. It is however helpful to cite the message text in a comment: :catch /^Vim(\a\+):E108:/ " No such variable IGNORING ERRORS *ignore-errors* You can ignore errors in a specific Vim command by catching them locally: :try : write :catch :endtry But you are strongly recommended NOT to use this simple form, since it could catch more than you want. With the ":write" command, some autocommands could be executed and cause errors not related to writing, for instance: :au BufWritePre * unlet novar There could even be such errors you are not responsible for as a script writer: a user of your script might have defined such autocommands. You would then hide the error from the user. It is much better to use :try : write :catch /^Vim(write):/ :endtry which only catches real write errors. So catch only what you'd like to ignore intentionally. For a single command that does not cause execution of autocommands, you could even suppress the conversion of errors to exceptions by the ":silent!" command: :silent! nunmap k This works also when a try conditional is active. CATCHING INTERRUPTS *catch-interrupt* When there are active try conditionals, an interrupt (CTRL-C) is converted to the exception "Vim:Interrupt". You can catch it like every exception. The script is not terminated, then. Example: :function! TASK1() : sleep 10 :endfunction :function! TASK2() : sleep 20 :endfunction :while 1 : let command = input("Type a command: ") : try : if command == "" : continue : elseif command == "END" : break : elseif command == "TASK1" : call TASK1() : elseif command == "TASK2" : call TASK2() : else : echo "\nIllegal command:" command : continue : endif : catch /^Vim:Interrupt$/ : echo "\nCommand interrupted" : " Caught the interrupt. Continue with next prompt. : endtry :endwhile You can interrupt a task here by pressing CTRL-C; the script then asks for a new command. If you press CTRL-C at the prompt, the script is terminated. For testing what happens when CTRL-C would be pressed on a specific line in your script, use the debug mode and execute the |>quit| or |>interrupt| command on that line. See |debug-scripts|. CATCHING ALL *catch-all* The commands :catch /.*/ :catch // :catch catch everything, error exceptions, interrupt exceptions and exceptions explicitly thrown by the |:throw| command. This is useful at the top level of a script in order to catch unexpected things. Example: :try : : " do the hard work here : :catch /MyException/ : : " handle known problem : :catch /^Vim:Interrupt$/ : echo "Script interrupted" :catch /.*/ : echo "Internal error (" . v:exception . ")" : echo " - occurred at " . v:throwpoint :endtry :" end of script Note: Catching all might catch more things than you want. Thus, you are strongly encouraged to catch only for problems that you can really handle by specifying a pattern argument to the ":catch". Example: Catching all could make it nearly impossible to interrupt a script by pressing CTRL-C: :while 1 : try : sleep 1 : catch : endtry :endwhile EXCEPTIONS AND AUTOCOMMANDS *except-autocmd* Exceptions may be used during execution of autocommands. Example: :autocmd User x try :autocmd User x throw "Oops!" :autocmd User x catch :autocmd User x echo v:exception :autocmd User x endtry :autocmd User x throw "Arrgh!" :autocmd User x echo "Should not be displayed" : :try : doautocmd User x :catch : echo v:exception :endtry This displays "Oops!" and "Arrgh!". *except-autocmd-Pre* For some commands, autocommands get executed before the main action of the command takes place. If an exception is thrown and not caught in the sequence of autocommands, the sequence and the command that caused its execution are abandoned and the exception is propagated to the caller of the command. Example: :autocmd BufWritePre * throw "FAIL" :autocmd BufWritePre * echo "Should not be displayed" : :try : write :catch : echo "Caught:" v:exception "from" v:throwpoint :endtry Here, the ":write" command does not write the file currently being edited (as you can see by checking 'modified'), since the exception from the BufWritePre autocommand abandons the ":write". The exception is then caught and the script displays: Caught: FAIL from BufWrite Auto commands for "*" *except-autocmd-Post* For some commands, autocommands get executed after the main action of the command has taken place. If this main action fails and the command is inside an active try conditional, the autocommands are skipped and an error exception is thrown that can be caught by the caller of the command. Example: :autocmd BufWritePost * echo "File successfully written!" : :try : write /i/m/p/o/s/s/i/b/l/e :catch : echo v:exception :endtry This just displays: Vim(write):E212: Can't open file for writing (/i/m/p/o/s/s/i/b/l/e) If you really need to execute the autocommands even when the main action fails, trigger the event from the catch clause. Example: :autocmd BufWritePre * set noreadonly :autocmd BufWritePost * set readonly : :try : write /i/m/p/o/s/s/i/b/l/e :catch : doautocmd BufWritePost /i/m/p/o/s/s/i/b/l/e :endtry You can also use ":silent!": :let x = "ok" :let v:errmsg = "" :autocmd BufWritePost * if v:errmsg != "" :autocmd BufWritePost * let x = "after fail" :autocmd BufWritePost * endif :try : silent! write /i/m/p/o/s/s/i/b/l/e :catch :endtry :echo x This displays "after fail". If the main action of the command does not fail, exceptions from the autocommands will be catchable by the caller of the command: :autocmd BufWritePost * throw ":-(" :autocmd BufWritePost * echo "Should not be displayed" : :try : write :catch : echo v:exception :endtry *except-autocmd-Cmd* For some commands, the normal action can be replaced by a sequence of autocommands. Exceptions from that sequence will be catchable by the caller of the command. Example: For the ":write" command, the caller cannot know whether the file had actually been written when the exception occurred. You need to tell it in some way. :if !exists("cnt") : let cnt = 0 : : autocmd BufWriteCmd * if &modified : autocmd BufWriteCmd * let cnt = cnt + 1 : autocmd BufWriteCmd * if cnt % 3 == 2 : autocmd BufWriteCmd * throw "BufWriteCmdError" : autocmd BufWriteCmd * endif : autocmd BufWriteCmd * write | set nomodified : autocmd BufWriteCmd * if cnt % 3 == 0 : autocmd BufWriteCmd * throw "BufWriteCmdError" : autocmd BufWriteCmd * endif : autocmd BufWriteCmd * echo "File successfully written!" : autocmd BufWriteCmd * endif :endif : :try : write :catch /^BufWriteCmdError$/ : if &modified : echo "Error on writing (file contents not changed)" : else : echo "Error after writing" : endif :catch /^Vim(write):/ : echo "Error on writing" :endtry When this script is sourced several times after making changes, it displays first File successfully written! then Error on writing (file contents not changed) then Error after writing etc. *except-autocmd-ill* You cannot spread a try conditional over autocommands for different events. The following code is ill-formed: :autocmd BufWritePre * try : :autocmd BufWritePost * catch :autocmd BufWritePost * echo v:exception :autocmd BufWritePost * endtry : :write EXCEPTION HIERARCHIES AND PARAMETERIZED EXCEPTIONS *except-hier-param* Some programming languages allow to use hierarchies of exception classes or to pass additional information with the object of an exception class. You can do similar things in Vim. In order to throw an exception from a hierarchy, just throw the complete class name with the components separated by a colon, for instance throw the string "EXCEPT:MATHERR:OVERFLOW" for an overflow in a mathematical library. When you want to pass additional information with your exception class, add it in parentheses, for instance throw the string "EXCEPT:IO:WRITEERR(myfile)" for an error when writing "myfile". With the appropriate patterns in the ":catch" command, you can catch for base classes or derived classes of your hierarchy. Additional information in parentheses can be cut out from |v:exception| with the ":substitute" command. Example: :function! CheckRange(a, func) : if a:a < 0 : throw "EXCEPT:MATHERR:RANGE(" . a:func . ")" : endif :endfunction : :function! Add(a, b) : call CheckRange(a:a, "Add") : call CheckRange(a:b, "Add") : let c = a:a + a:b : if c < 0 : throw "EXCEPT:MATHERR:OVERFLOW" : endif : return c :endfunction : :function! Div(a, b) : call CheckRange(a:a, "Div") : call CheckRange(a:b, "Div") : if (a:b == 0) : throw "EXCEPT:MATHERR:ZERODIV" : endif : return a:a / a:b :endfunction : :function! Write(file) : try : execute "write" fnameescape(a:file) : catch /^Vim(write):/ : throw "EXCEPT:IO(" . getcwd() . ", " . a:file . "):WRITEERR" : endtry :endfunction : :try : : " something with arithmetics and I/O : :catch /^EXCEPT:MATHERR:RANGE/ : let function = substitute(v:exception, '.*(\(\a\+\)).*', '\1', "") : echo "Range error in" function : :catch /^EXCEPT:MATHERR/ " catches OVERFLOW and ZERODIV : echo "Math error" : :catch /^EXCEPT:IO/ : let dir = substitute(v:exception, '.*(\(.\+\),\s*.\+).*', '\1', "") : let file = substitute(v:exception, '.*(.\+,\s*\(.\+\)).*', '\1', "") : if file !~ '^/' : let file = dir . "/" . file : endif : echo 'I/O error for "' . file . '"' : :catch /^EXCEPT/ : echo "Unspecified error" : :endtry The exceptions raised by Vim itself (on error or when pressing CTRL-C) use a flat hierarchy: they are all in the "Vim" class. You cannot throw yourself exceptions with the "Vim" prefix; they are reserved for Vim. Vim error exceptions are parameterized with the name of the command that failed, if known. See |catch-errors|. PECULIARITIES *except-compat* The exception handling concept requires that the command sequence causing the exception is aborted immediately and control is transferred to finally clauses and/or a catch clause. In the Vim script language there are cases where scripts and functions continue after an error: in functions without the "abort" flag or in a command after ":silent!", control flow goes to the following line, and outside functions, control flow goes to the line following the outermost ":endwhile" or ":endif". On the other hand, errors should be catchable as exceptions (thus, requiring the immediate abortion). This problem has been solved by converting errors to exceptions and using immediate abortion (if not suppressed by ":silent!") only when a try conditional is active. This is no restriction since an (error) exception can be caught only from an active try conditional. If you want an immediate termination without catching the error, just use a try conditional without catch clause. (You can cause cleanup code being executed before termination by specifying a finally clause.) When no try conditional is active, the usual abortion and continuation behavior is used instead of immediate abortion. This ensures compatibility of scripts written for Vim 6.1 and earlier. However, when sourcing an existing script that does not use exception handling commands (or when calling one of its functions) from inside an active try conditional of a new script, you might change the control flow of the existing script on error. You get the immediate abortion on error and can catch the error in the new script. If however the sourced script suppresses error messages by using the ":silent!" command (checking for errors by testing |v:errmsg| if appropriate), its execution path is not changed. The error is not converted to an exception. (See |:silent|.) So the only remaining cause where this happens is for scripts that don't care about errors and produce error messages. You probably won't want to use such code from your new scripts. *except-syntax-err* Syntax errors in the exception handling commands are never caught by any of the ":catch" commands of the try conditional they belong to. Its finally clauses, however, is executed. Example: :try : try : throw 4711 : catch /\(/ : echo "in catch with syntax error" : catch : echo "inner catch-all" : finally : echo "inner finally" : endtry :catch : echo 'outer catch-all caught "' . v:exception . '"' : finally : echo "outer finally" :endtry This displays: inner finally outer catch-all caught "Vim(catch):E54: Unmatched \(" outer finally The original exception is discarded and an error exception is raised, instead. *except-single-line* The ":try", ":catch", ":finally", and ":endtry" commands can be put on a single line, but then syntax errors may make it difficult to recognize the "catch" line, thus you better avoid this. Example: :try | unlet! foo # | catch | endtry raises an error exception for the trailing characters after the ":unlet!" argument, but does not see the ":catch" and ":endtry" commands, so that the error exception is discarded and the "E488: Trailing characters" message gets displayed. *except-several-errors* When several errors appear in a single command, the first error message is usually the most specific one and therefor converted to the error exception. Example: echo novar causes E121: Undefined variable: novar E15: Invalid expression: novar The value of the error exception inside try conditionals is: Vim(echo):E121: Undefined variable: novar *except-syntax-error* But when a syntax error is detected after a normal error in the same command, the syntax error is used for the exception being thrown. Example: unlet novar # causes E108: No such variable: "novar" E488: Trailing characters The value of the error exception inside try conditionals is: Vim(unlet):E488: Trailing characters This is done because the syntax error might change the execution path in a way not intended by the user. Example: try try | unlet novar # | catch | echo v:exception | endtry catch /.*/ echo "outer catch:" v:exception endtry This displays "outer catch: Vim(unlet):E488: Trailing characters", and then a "E600: Missing :endtry" error message is given, see |except-single-line|.
9. Examples *eval-examples* Printing in Binary :" The function Nr2Bin() returns the Hex string of a number. :func Nr2Bin(nr) : let n = a:nr : let r = "" : while n : let r = '01'[n % 2] . r : let n = n / 2 : endwhile : return r :endfunc :" The function String2Bin() converts each character in a string to a :" binary string, separated with dashes. :func String2Bin(str) : let out = '' : for ix in range(strlen(a:str)) : let out = out . '-' . Nr2Bin(char2nr(a:str[ix])) : endfor : return out[1:] :endfunc Example of its use: :echo Nr2Bin(32) result: "100000" :echo String2Bin("32") result: "110011-110010" Sorting lines This example sorts lines with a specific compare function. :func SortBuffer() : let lines = getline(1, '$') : call sort(lines, function("Strcmp")) : call setline(1, lines) :endfunction As a one-liner: :call setline(1, sort(getline(1, '$'), function("Strcmp"))) scanf() replacement *sscanf* There is no sscanf() function in Vim. If you need to extract parts from a line, you can use matchstr() and substitute() to do it. This example shows how to get the file name, line number and column number out of a line like "foobar.txt, 123, 45". :" Set up the match bit :let mx='\(\f\+\),\s*\(\d\+\),\s*\(\d\+\)' :"get the part matching the whole expression :let l = matchstr(line, mx) :"get each item out of the match :let file = substitute(l, mx, '\1', '') :let lnum = substitute(l, mx, '\2', '') :let col = substitute(l, mx, '\3', '') The input is in the variable "line", the results in the variables "file", "lnum" and "col". (idea from Michael Geddes) getting the scriptnames in a Dictionary *scriptnames-dictionary* The |:scriptnames| command can be used to get a list of all script files that have been sourced. There is no equivalent function or variable for this (because it's rarely needed). In case you need to manipulate the list this code can be used: " Get the output of ":scriptnames" in the scriptnames_output variable. let scriptnames_output = '' redir => scriptnames_output silent scriptnames redir END " Split the output into lines and parse each line. Add an entry to the " "scripts" dictionary. let scripts = {} for line in split(scriptnames_output, "\n") " Only do non-blank lines. if line =~ '\S' " Get the first number in the line. let nr = matchstr(line, '\d\+') " Get the file name, remove the script number " 123: ". let name = substitute(line, '.\+:\s*', '', '') " Add an item to the Dictionary let scripts[nr] = name endif endfor unlet scriptnames_output
10. No +eval feature *no-eval-feature* When the |+eval| feature was disabled at compile time, none of the expression evaluation commands are available. To prevent this from causing Vim scripts to generate all kinds of errors, the ":if" and ":endif" commands are still recognized, though the argument of the ":if" and everything between the ":if" and the matching ":endif" is ignored. Nesting of ":if" blocks is allowed, but only if the commands are at the start of the line. The ":else" command is not recognized. Example of how to avoid executing commands when the |+eval| feature is missing: :if 1 : echo "Expression evaluation is compiled in" :else : echo "You will _never_ see this message" :endif
11. The sandbox *eval-sandbox* *sandbox* *E48* The 'foldexpr', 'includeexpr', 'indentexpr', 'statusline' and 'foldtext' options are evaluated in a sandbox. This means that you are protected from these expressions having nasty side effects. This gives some safety for when these options are set from a modeline. It is also used when the command from a tags file is executed and for CTRL-R = in the command line. The sandbox is also used for the |:sandbox| command. These items are not allowed in the sandbox: - changing the buffer text - defining or changing mapping, autocommands, functions, user commands - setting certain options (see |option-summary|) - setting certain v: variables (see |v:var|) *E794* - executing a shell command - reading or writing a file - jumping to another buffer or editing a file - executing Python, Perl, etc. commands This is not guaranteed 100% secure, but it should block most attacks. *:san* *:sandbox* :san[dbox] {cmd} Execute {cmd} in the sandbox. Useful to evaluate an option that may have been set from a modeline, e.g. 'foldexpr'. *sandbox-option* A few options contain an expression. When this expression is evaluated it may have to be done in the sandbox to avoid a security risk. But the sandbox is restrictive, thus this only happens when the option was set from an insecure location. Insecure in this context are: - sourcing a .vimrc or .exrc in the current directory - while executing in the sandbox - value coming from a modeline Note that when in the sandbox and saving an option value and restoring it, the option will still be marked as it was set in the sandbox.
12. Textlock *textlock* In a few situations it is not allowed to change the text in the buffer, jump to another window and some other things that might confuse or break what Vim is currently doing. This mostly applies to things that happen when Vim is actually doing something else. For example, evaluating the 'balloonexpr' may happen any moment the mouse cursor is resting at some position. This is not allowed when the textlock is active: - changing the buffer text - jumping to another buffer or window - editing another file - closing a window or quitting Vim - etc. top - main help file