代码拉取完成,页面将自动刷新
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>usr_41 - Vim Documentation</title>
<meta name="Generator" content="Vim/8.0">
<meta name="plugin-version" content="vim8.0">
<meta name="syntax" content="help">
<meta name="settings" content="no_pre,use_css,expand_tabs">
<link rel="stylesheet" href="style.css" type="text/css" />
<script src="jquery.min.js" type="text/javascript"></script>
<script src="mark-current-page.js" type="text/javascript"></script>
</head>
<body>
<header>
<div class="header">
<a href="http://vim-jp.org/">vim-jp</a>
/ <a href="http://vim-jp.org/vimdoc-en/">vimdoc-en</a>
/ usr_41<br />
<a name="top"></a><h1>usr_41 - Vim Documentation</h1>
<a href="index.html">Return to main</a>
<span class="EnglishJapaneseLink">
<span class="CurrentLanguage">English</span>
</span>
</div>
</header>
<nav>
<dl>
<dt>BASIC</dt>
<dd><ul>
<li><a href="quickref.html">quickref</a></li>
<li><a href="sponsor.html">sponsor</a></li>
</ul></dd>
<dt>USER MANUAL</dt>
<dd><ul>
<li><a href="usr_toc.html">usr_toc</a></li>
</ul></dd>
<dt>Getting Started</dt>
<dd><ul>
<li><a href="usr_01.html">usr_01</a></li>
<li><a href="usr_02.html">usr_02</a></li>
<li><a href="usr_03.html">usr_03</a></li>
<li><a href="usr_04.html">usr_04</a></li>
<li><a href="usr_05.html">usr_05</a></li>
<li><a href="usr_06.html">usr_06</a></li>
<li><a href="usr_07.html">usr_07</a></li>
<li><a href="usr_08.html">usr_08</a></li>
<li><a href="usr_09.html">usr_09</a></li>
<li><a href="usr_10.html">usr_10</a></li>
<li><a href="usr_11.html">usr_11</a></li>
<li><a href="usr_12.html">usr_12</a></li>
</ul></dd>
<dt>Editing Effectively</dt>
<dd><ul>
<li><a href="usr_20.html">usr_20</a></li>
<li><a href="usr_21.html">usr_21</a></li>
<li><a href="usr_22.html">usr_22</a></li>
<li><a href="usr_23.html">usr_23</a></li>
<li><a href="usr_24.html">usr_24</a></li>
<li><a href="usr_25.html">usr_25</a></li>
<li><a href="usr_26.html">usr_26</a></li>
<li><a href="usr_27.html">usr_27</a></li>
<li><a href="usr_28.html">usr_28</a></li>
<li><a href="usr_29.html">usr_29</a></li>
<li><a href="usr_30.html">usr_30</a></li>
<li><a href="usr_31.html">usr_31</a></li>
<li><a href="usr_32.html">usr_32</a></li>
</ul></dd>
<dt>Tuning Vim</dt>
<dd><ul>
<li><a href="usr_40.html">usr_40</a></li>
<li><a href="usr_41.html">usr_41</a></li>
<li><a href="usr_42.html">usr_42</a></li>
<li><a href="usr_43.html">usr_43</a></li>
<li><a href="usr_44.html">usr_44</a></li>
<li><a href="usr_45.html">usr_45</a></li>
</ul></dd>
<dt>Making Vim Run</dt>
<dd><ul>
<li><a href="usr_90.html">usr_90</a></li>
</ul></dd>
<dt>General subjects</dt>
<dd><ul>
<li><a href="intro.html">intro</a></li>
<li><a href="index.html">help</a></li>
<li><a href="helphelp.html">helphelp</a></li>
<li><a href="vimindex.html">index</a></li>
<li><a href="tags.html">tags</a></li>
<li><a href="howto.html">howto</a></li>
<li><a href="tips.html">tips</a></li>
<li><a href="message.html">message</a></li>
<li><a href="quotes.html">quotes</a></li>
<li><a href="todo.html">todo</a></li>
<li><a href="debug.html">debug</a></li>
<li><a href="develop.html">develop</a></li>
<li><a href="uganda.html">uganda</a></li>
</ul></dd>
<dt>Basic editing</dt>
<dd><ul>
<li><a href="starting.html">starting</a></li>
<li><a href="editing.html">editing</a></li>
<li><a href="motion.html">motion</a></li>
<li><a href="scroll.html">scroll</a></li>
<li><a href="insert.html">insert</a></li>
<li><a href="change.html">change</a></li>
<li><a href="indent.html">indent</a></li>
<li><a href="undo.html">undo</a></li>
<li><a href="repeat.html">repeat</a></li>
<li><a href="visual.html">visual</a></li>
<li><a href="various.html">various</a></li>
<li><a href="recover.html">recover</a></li>
</ul></dd>
<dt>Advanced editing</dt>
<dd><ul>
<li><a href="cmdline.html">cmdline</a></li>
<li><a href="options.html">options</a></li>
<li><a href="pattern.html">pattern</a></li>
<li><a href="map.html">map</a></li>
<li><a href="tagsrch.html">tagsrch</a></li>
<li><a href="quickfix.html">quickfix</a></li>
<li><a href="windows.html">windows</a></li>
<li><a href="tabpage.html">tabpage</a></li>
<li><a href="syntax.html">syntax</a></li>
<li><a href="spell.html">spell</a></li>
<li><a href="diff.html">diff</a></li>
<li><a href="autocmd.html">autocmd</a></li>
<li><a href="filetype.html">filetype</a></li>
<li><a href="eval.html">eval</a></li>
<li><a href="channel.html">channel</a></li>
<li><a href="fold.html">fold</a></li>
</ul></dd>
<dt>Special issues</dt>
<dd><ul>
<li><a href="print.html">print</a></li>
<li><a href="remote.html">remote</a></li>
<li><a href="term.html">term</a></li>
<li><a href="digraph.html">digraph</a></li>
<li><a href="mbyte.html">mbyte</a></li>
<li><a href="mlang.html">mlang</a></li>
<li><a href="arabic.html">arabic</a></li>
<li><a href="farsi.html">farsi</a></li>
<li><a href="hebrew.html">hebrew</a></li>
<li><a href="russian.html">russian</a></li>
<li><a href="ft_ada.html">ft_ada</a></li>
<li><a href="ft_sql.html">ft_sql</a></li>
<li><a href="hangulin.html">hangulin</a></li>
<li><a href="rileft.html">rileft</a></li>
</ul></dd>
<dt>GUI</dt>
<dd><ul>
<li><a href="gui.html">gui</a></li>
<li><a href="gui_w32.html">gui_w32</a></li>
<li><a href="gui_x11.html">gui_x11</a></li>
</ul></dd>
<dt>Interfaces</dt>
<dd><ul>
<li><a href="if_cscop.html">if_cscop</a></li>
<li><a href="if_lua.html">if_lua</a></li>
<li><a href="if_mzsch.html">if_mzsch</a></li>
<li><a href="if_perl.html">if_perl</a></li>
<li><a href="if_pyth.html">if_pyth</a></li>
<li><a href="if_tcl.html">if_tcl</a></li>
<li><a href="if_ole.html">if_ole</a></li>
<li><a href="if_ruby.html">if_ruby</a></li>
<li><a href="debugger.html">debugger</a></li>
<li><a href="workshop.html">workshop</a></li>
<li><a href="netbeans.html">netbeans</a></li>
<li><a href="sign.html">sign</a></li>
</ul></dd>
<dt>Versions</dt>
<dd><ul>
<li><a href="vi_diff.html">vi_diff</a></li>
<li><a href="version4.html">version4</a></li>
<li><a href="version5.html">version5</a></li>
<li><a href="version6.html">version6</a></li>
<li><a href="version7.html">version7</a></li>
<li><a href="version8.html">version8</a></li>
</ul></dd>
<dt>Remarks about specific systems</dt>
<dd><ul>
<li><a href="os_390.html">os_390</a></li>
<li><a href="os_amiga.html">os_amiga</a></li>
<li><a href="os_beos.html">os_beos</a></li>
<li><a href="os_dos.html">os_dos</a></li>
<li><a href="os_mac.html">os_mac</a></li>
<li><a href="os_mint.html">os_mint</a></li>
<li><a href="os_msdos.html">os_msdos</a></li>
<li><a href="os_os2.html">os_os2</a></li>
<li><a href="os_qnx.html">os_qnx</a></li>
<li><a href="os_risc.html">os_risc</a></li>
<li><a href="os_unix.html">os_unix</a></li>
<li><a href="os_vms.html">os_vms</a></li>
<li><a href="os_win32.html">os_win32</a></li>
</ul></dd>
<dt>Standard plugins</dt>
<dd><ul>
<li><a href="pi_getscript.html">pi_getscript</a></li>
<li><a href="pi_gzip.html">pi_gzip</a></li>
<li><a href="pi_logipat.html">pi_logipat</a></li>
<li><a href="pi_netrw.html">pi_netrw</a></li>
<li><a href="pi_paren.html">pi_paren</a></li>
<li><a href="pi_tar.html">pi_tar</a></li>
<li><a href="pi_vimball.html">pi_vimball</a></li>
<li><a href="pi_zip.html">pi_zip</a></li>
</ul></dd>
<dt>Filetype plugins</dt>
<dd><ul>
<li><a href="pi_spec.html">pi_spec</a></li>
</ul></dd>
<dt>Others</dt>
<dd><ul>
<li><a href="vim_faq.html">vim_faq</a></li>
</ul></dd>
</dl>
</nav>
<article class="Vimdoc VimdocJa">
<div id='vimCodeElement'>
<a class="Constant" href="usr_41.html" name="usr_41.txt">usr_41.txt</a> For <span class="Identifier">Vim version 8.0.</span> Last change: 2017 Jul 19<br>
<br>
VIM USER MANUAL - by Bram Moolenaar<br>
<br>
Write a Vim script<br>
<br>
<br>
The Vim script language is used for the startup vimrc file, syntax files, and<br>
many other things. This chapter explains the items that can be used in a Vim<br>
script. There are a lot of them, thus this is a long chapter.<br>
<br>
<a class="Identifier" href="usr_41.html#41.1">41.1</a> Introduction<br>
<a class="Identifier" href="usr_41.html#41.2">41.2</a> Variables<br>
<a class="Identifier" href="usr_41.html#41.3">41.3</a> Expressions<br>
<a class="Identifier" href="usr_41.html#41.4">41.4</a> Conditionals<br>
<a class="Identifier" href="usr_41.html#41.5">41.5</a> Executing an expression<br>
<a class="Identifier" href="usr_41.html#41.6">41.6</a> Using functions<br>
<a class="Identifier" href="usr_41.html#41.7">41.7</a> Defining a function<br>
<a class="Identifier" href="usr_41.html#41.8">41.8</a> Lists and Dictionaries<br>
<a class="Identifier" href="usr_41.html#41.9">41.9</a> Exceptions<br>
<a class="Identifier" href="usr_41.html#41.10">41.10</a> Various remarks<br>
<a class="Identifier" href="usr_41.html#41.11">41.11</a> Writing a plugin<br>
<a class="Identifier" href="usr_41.html#41.12">41.12</a> Writing a filetype plugin<br>
<a class="Identifier" href="usr_41.html#41.13">41.13</a> Writing a compiler plugin<br>
<a class="Identifier" href="usr_41.html#41.14">41.14</a> Writing a plugin that loads quickly<br>
<a class="Identifier" href="usr_41.html#41.15">41.15</a> Writing library scripts<br>
<a class="Identifier" href="usr_41.html#41.16">41.16</a> Distributing Vim scripts<br>
<br>
Next chapter: <a class="Identifier" href="usr_42.html">usr_42.txt</a> Add new menus<br>
Previous chapter: <a class="Identifier" href="usr_40.html">usr_40.txt</a> Make new commands<br>
Table of contents: <a class="Identifier" href="usr_toc.html">usr_toc.txt</a><br>
<br>
<span class="PreProc">==============================================================================</span><br>
<a class="Constant" href="usr_41.html#41.1" name="41.1">41.1</a> Introduction <a class="Constant" href="usr_41.html#vim-script-intro" name="vim-script-intro">vim-script-intro</a> <a class="Constant" href="usr_41.html#script" name="script">script</a><br>
<br>
Your first experience with Vim scripts is the vimrc file. Vim reads it when<br>
it starts up and executes the commands. You can set options to values you<br>
prefer. And you can use any colon command in it (commands that start with a<br>
":"; these are sometimes referred to as Ex commands or command-line commands).<br>
Syntax files are also Vim scripts. As are files that set options for a<br>
specific file type. A complicated macro can be defined by a separate Vim<br>
script file. You can think of other uses yourself.<br>
<br>
Let's start with a simple example:<br>
<br>
<div class="helpExample"> :let i = 1<br>
:while i < 5<br>
: echo "count is" i<br>
: let i += 1<br>
:endwhile</div>
<br>
<span class="Todo">Note</span>:<br>
The ":" characters are not really needed here. You only need to use<br>
them when you type a command. In a Vim script file they can be left<br>
out. We will use them here anyway to make clear these are colon<br>
commands and make them stand out from Normal mode commands.<br>
<span class="Todo">Note</span>:<br>
You can try out the examples by yanking the lines from the text here<br>
and executing them with :@"<br>
<br>
The output of the example code is:<br>
<br>
<span class="PreProc">count is 1</span><br>
<span class="PreProc">count is 2</span><br>
<span class="PreProc">count is 3</span><br>
<span class="PreProc">count is 4</span><br>
<br>
In the first line the ":let" command assigns a value to a variable. The<br>
generic form is:<br>
<br>
<div class="helpExample"> :let {variable} = {expression}</div>
<br>
In this case the variable name is "i" and the expression is a simple value,<br>
the number one.<br>
The ":while" command starts a loop. The generic form is:<br>
<br>
<div class="helpExample"> :while {condition}<br>
: {statements}<br>
:endwhile</div>
<br>
The statements until the matching ":endwhile" are executed for as long as the<br>
condition is true. The condition used here is the expression "i < 5". This<br>
is true when the variable i is smaller than five.<br>
<span class="Todo">Note</span>:<br>
If you happen to write a while loop that keeps on running, you can<br>
interrupt it by pressing <span class="Special">CTRL-C</span> (<span class="Special">CTRL-Break</span> on MS-Windows).<br>
<br>
The ":echo" command prints its arguments. In this case the string "count is"<br>
and the value of the variable i. Since i is one, this will print:<br>
<br>
<span class="PreProc">count is 1</span><br>
<br>
Then there is the ":let i += 1" command. This does the same thing as<br>
":let i = i + 1". This adds one to the variable i and assigns the new value<br>
to the same variable.<br>
<br>
The example was given to explain the commands, but would you really want to<br>
make such a loop, it can be written much more compact:<br>
<br>
<div class="helpExample"> :for i in range(1, 4)<br>
: echo "count is" i<br>
:endfor</div>
<br>
We won't explain how <a class="Identifier" href="eval.html#:for">:for</a> and <a class="Identifier" href="eval.html#range()">range()</a> work until later. Follow the links<br>
if you are impatient.<br>
<br>
<br>
THREE KINDS OF NUMBERS<br>
<br>
Numbers can be decimal, hexadecimal or octal. A hexadecimal number starts<br>
with "0x" or "0X". For example "0x1f" is decimal 31. An octal number starts<br>
with a zero. "017" is decimal 15. Careful: don't put a zero before a decimal<br>
number, it will be interpreted as an octal number!<br>
The ":echo" command always prints decimal numbers. Example:<br>
<br>
<div class="helpExample"> :echo 0x7f 036</div>
<span class="PreProc">127 30</span><br>
<br>
A number is made negative with a minus sign. This also works for hexadecimal<br>
and octal numbers. A minus sign is also used for subtraction. Compare this<br>
with the previous example:<br>
<br>
<div class="helpExample"> :echo 0x7f -036</div>
<span class="PreProc">97</span><br>
<br>
White space in an expression is ignored. However, it's recommended to use it<br>
for separating items, to make the expression easier to read. For example, to<br>
avoid the confusion with a negative number above, put a space between the<br>
minus sign and the following number:<br>
<br>
<div class="helpExample"> :echo 0x7f - 036</div>
<br>
<span class="PreProc">==============================================================================</span><br>
<a class="Constant" href="usr_41.html#41.2" name="41.2">41.2</a> Variables<br>
<br>
A variable name consists of ASCII letters, digits and the underscore. It<br>
cannot start with a digit. Valid variable names are:<br>
<br>
counter<br>
_aap3<br>
very_long_variable_name_with_underscores<br>
FuncLength<br>
LENGTH<br>
<br>
Invalid names are "foo+bar" and "6var".<br>
These variables are global. To see a list of currently defined variables<br>
use this command:<br>
<br>
<div class="helpExample"> :let</div>
<br>
You can use global variables everywhere. This also means that when the<br>
variable "count" is used in one script file, it might also be used in another<br>
file. This leads to confusion at least, and real problems at worst. To avoid<br>
this, you can use a variable local to a script file by prepending "s:". For<br>
example, one script contains this code:<br>
<br>
<div class="helpExample"> :let s:count = 1<br>
:while s:count < 5<br>
: source other.vim<br>
: let s:count += 1<br>
:endwhile</div>
<br>
Since "s:count" is local to this script, you can be sure that sourcing the<br>
"other.vim" script will not change this variable. If "other.vim" also uses an<br>
"s:count" variable, it will be a different copy, local to that script. More<br>
about script-local variables here: <a class="Identifier" href="eval.html#script-variable">script-variable</a>.<br>
<br>
There are more kinds of variables, see <a class="Identifier" href="eval.html#internal-variables">internal-variables</a>. The most often<br>
used ones are:<br>
<br>
b:name variable local to a buffer<br>
w:name variable local to a window<br>
g:name global variable (also in a function)<br>
v:name variable predefined by Vim<br>
<br>
<br>
DELETING VARIABLES<br>
<br>
Variables take up memory and show up in the output of the ":let" command. To<br>
delete a variable use the ":unlet" command. Example:<br>
<br>
<div class="helpExample"> :unlet s:count</div>
<br>
This deletes the script-local variable "s:count" to free up the memory it<br>
uses. If you are not sure if the variable exists, and don't want an error<br>
message when it doesn't, append !:<br>
<br>
<div class="helpExample"> :unlet! s:count</div>
<br>
When a script finishes, the local variables used there will not be<br>
automatically freed. The next time the script executes, it can still use the<br>
old value. Example:<br>
<br>
<div class="helpExample"> :if !exists("s:call_count")<br>
: let s:call_count = 0<br>
:endif<br>
:let s:call_count = s:call_count + 1<br>
:echo "called" s:call_count "times"</div>
<br>
The "exists()" function checks if a variable has already been defined. Its<br>
argument is the name of the variable you want to check. Not the variable<br>
itself! If you would do this:<br>
<br>
<div class="helpExample"> :if !exists(s:call_count)</div>
<br>
Then the value of s:call_count will be used as the name of the variable that<br>
exists() checks. That's not what you want.<br>
The exclamation mark ! negates a value. When the value was true, it<br>
becomes false. When it was false, it becomes true. You can read it as "not".<br>
Thus "if !exists()" can be read as "if not exists()".<br>
What Vim calls true is anything that is not zero. Zero is false.<br>
<span class="Todo">Note</span>:<br>
Vim automatically converts a string to a number when it is looking for<br>
a number. When using a string that doesn't start with a digit the<br>
resulting number is zero. Thus look out for this:<br>
<div class="helpExample"> :if "true"</div>
The "true" will be interpreted as a zero, thus as false!<br>
<br>
<br>
STRING VARIABLES AND CONSTANTS<br>
<br>
So far only numbers were used for the variable value. Strings can be used as<br>
well. Numbers and strings are the basic types of variables that Vim supports.<br>
The type is dynamic, it is set each time when assigning a value to the<br>
variable with ":let". More about types in <a class="Identifier" href="usr_41.html#41.8">41.8</a>.<br>
To assign a string value to a variable, you need to use a string constant.<br>
There are two types of these. First the string in double quotes:<br>
<br>
<div class="helpExample"> :let name = "peter"<br>
:echo name</div>
<span class="PreProc">peter</span><br>
<br>
If you want to include a double quote inside the string, put a backslash in<br>
front of it:<br>
<br>
<div class="helpExample"> :let name = "\"peter\""<br>
:echo name</div>
<span class="PreProc">"peter"</span><br>
<br>
To avoid the need for a backslash, you can use a string in single quotes:<br>
<br>
<div class="helpExample"> :let name = '"peter"'<br>
:echo name</div>
<span class="PreProc">"peter"</span><br>
<br>
Inside a single-quote string all the characters are as they are. Only the<br>
single quote itself is special: you need to use two to get one. A backslash<br>
is taken literally, thus you can't use it to change the meaning of the<br>
character after it.<br>
In double-quote strings it is possible to use special characters. Here are<br>
a few useful ones:<br>
<br>
\t <span class="Special"><Tab></span><br>
\n <span class="Special"><NL></span>, line break<br>
\r <span class="Special"><CR></span>, <span class="Special"><Enter></span><br>
\e <span class="Special"><Esc></span><br>
\b <span class="Special"><BS></span>, backspace<br>
\" "<br>
\\ \, backslash<br>
\<span class="Special"><Esc></span> <span class="Special"><Esc></span><br>
\<span class="Special"><C-W></span> <span class="Special">CTRL-W</span><br>
<br>
The last two are just examples. The "\<span class="Special"><name></span>" form can be used to include<br>
the special key "name".<br>
See <a class="Identifier" href="eval.html#expr-quote">expr-quote</a> for the full list of special items in a string.<br>
<br>
<span class="PreProc">==============================================================================</span><br>
<a class="Constant" href="usr_41.html#41.3" name="41.3">41.3</a> Expressions<br>
<br>
Vim has a rich, yet simple way to handle expressions. You can read the<br>
definition here: <a class="Identifier" href="eval.html#expression-syntax">expression-syntax</a>. Here we will show the most common<br>
items.<br>
The numbers, strings and variables mentioned above are expressions by<br>
themselves. Thus everywhere an expression is expected, you can use a number,<br>
string or variable. Other basic items in an expression are:<br>
<br>
$NAME environment variable<br>
&name option<br>
@r register<br>
<br>
Examples:<br>
<br>
<div class="helpExample"> :echo "The value of 'tabstop' is" &ts<br>
:echo "Your home directory is" $HOME<br>
:if @a > 5</div>
<br>
The &name form can be used to save an option value, set it to a new value,<br>
do something and restore the old value. Example:<br>
<br>
<div class="helpExample"> :let save_ic = &ic<br>
:set noic<br>
:/The Start/,$delete<br>
:let &ic = save_ic</div>
<br>
This makes sure the "The Start" pattern is used with the <a class="Type" href="options.html#'ignorecase'">'ignorecase'</a> option<br>
off. Still, it keeps the value that the user had set. (Another way to do<br>
this would be to add "\C" to the pattern, see <a class="Identifier" href="pattern.html#/\C">/\C</a>.)<br>
<br>
<br>
MATHEMATICS<br>
<br>
It becomes more interesting if we combine these basic items. Let's start with<br>
mathematics on numbers:<br>
<br>
a + b add<br>
a - b subtract<br>
a * b multiply<br>
a / b divide<br>
a % b modulo<br>
<br>
The usual precedence is used. Example:<br>
<br>
<div class="helpExample"> :echo 10 + 5 * 2</div>
<span class="PreProc">20</span><br>
<br>
Grouping is done with parentheses. No surprises here. Example:<br>
<br>
<div class="helpExample"> :echo (10 + 5) * 2</div>
<span class="PreProc">30</span><br>
<br>
Strings can be concatenated with ".". Example:<br>
<br>
<div class="helpExample"> :echo "foo" . "bar"</div>
<span class="PreProc">foobar</span><br>
<br>
When the ":echo" command gets multiple arguments, it separates them with a<br>
space. In the example the argument is a single expression, thus no space is<br>
inserted.<br>
<br>
Borrowed from the C language is the conditional expression:<br>
<br>
a ? b : c<br>
<br>
If "a" evaluates to true "b" is used, otherwise "c" is used. Example:<br>
<br>
<div class="helpExample"> :let i = 4<br>
:echo i > 5 ? "i is big" : "i is small"</div>
<span class="PreProc">i is small</span><br>
<br>
The three parts of the constructs are always evaluated first, thus you could<br>
see it work as:<br>
<br>
(a) ? (b) : (c)<br>
<br>
<span class="PreProc">==============================================================================</span><br>
<a class="Constant" href="usr_41.html#41.4" name="41.4">41.4</a> Conditionals<br>
<br>
The ":if" commands executes the following statements, until the matching<br>
":endif", only when a condition is met. The generic form is:<br>
<br>
:if <span class="Special">{condition}</span><br>
<span class="Special">{statements}</span><br>
:endif<br>
<br>
Only when the expression <span class="Special">{condition}</span> evaluates to true (non-zero) will the<br>
<span class="Special">{statements}</span> be executed. These must still be valid commands. If they<br>
contain garbage, Vim won't be able to find the ":endif".<br>
You can also use ":else". The generic form for this is:<br>
<br>
:if <span class="Special">{condition}</span><br>
<span class="Special">{statements}</span><br>
:else<br>
<span class="Special">{statements}</span><br>
:endif<br>
<br>
The second <span class="Special">{statements}</span> is only executed if the first one isn't.<br>
Finally, there is ":elseif":<br>
<br>
:if <span class="Special">{condition}</span><br>
<span class="Special">{statements}</span><br>
:elseif <span class="Special">{condition}</span><br>
<span class="Special">{statements}</span><br>
:endif<br>
<br>
This works just like using ":else" and then "if", but without the need for an<br>
extra ":endif".<br>
A useful example for your vimrc file is checking the <a class="Type" href="options.html#'term'">'term'</a> option and<br>
doing something depending upon its value:<br>
<br>
<div class="helpExample"> :if &term == "xterm"<br>
: " Do stuff for xterm<br>
:elseif &term == "vt100"<br>
: " Do stuff for a vt100 terminal<br>
:else<br>
: " Do something for other terminals<br>
:endif</div>
<br>
<br>
LOGIC OPERATIONS<br>
<br>
We already used some of them in the examples. These are the most often used<br>
ones:<br>
<br>
a == b equal to<br>
a != b not equal to<br>
a > b greater than<br>
a >= b greater than or equal to<br>
a < b less than<br>
a <= b less than or equal to<br>
<br>
The result is one if the condition is met and zero otherwise. An example:<br>
<br>
<div class="helpExample"> :if v:version >= 700<br>
: echo "congratulations"<br>
:else<br>
: echo "you are using an old version, upgrade!"<br>
:endif</div>
<br>
Here "v:version" is a variable defined by Vim, which has the value of the Vim<br>
version. 600 is for version 6.0. Version 6.1 has the value 601. This is<br>
very useful to write a script that works with multiple versions of Vim.<br>
<a class="Identifier" href="eval.html#v:version">v:version</a><br>
<br>
The logic operators work both for numbers and strings. When comparing two<br>
strings, the mathematical difference is used. This compares byte values,<br>
which may not be right for some languages.<br>
When comparing a string with a number, the string is first converted to a<br>
number. This is a bit tricky, because when a string doesn't look like a<br>
number, the number zero is used. Example:<br>
<br>
<div class="helpExample"> :if 0 == "one"<br>
: echo "yes"<br>
:endif</div>
<br>
This will echo "yes", because "one" doesn't look like a number, thus it is<br>
converted to the number zero.<br>
<br>
For strings there are two more items:<br>
<br>
a =~ b matches with<br>
a !~ b does not match with<br>
<br>
The left item "a" is used as a string. The right item "b" is used as a<br>
pattern, like what's used for searching. Example:<br>
<br>
<div class="helpExample"> :if str =~ " "<br>
: echo "str contains a space"<br>
:endif<br>
:if str !~ '\.$'<br>
: echo "str does not end in a full stop"<br>
:endif</div>
<br>
Notice the use of a single-quote string for the pattern. This is useful,<br>
because backslashes would need to be doubled in a double-quote string and<br>
patterns tend to contain many backslashes.<br>
<br>
The <a class="Type" href="options.html#'ignorecase'">'ignorecase'</a> option is used when comparing strings. When you don't want<br>
that, append "#" to match case and "?" to ignore case. Thus "==?" compares<br>
two strings to be equal while ignoring case. And "!~#" checks if a pattern<br>
doesn't match, also checking the case of letters. For the full table see<br>
<a class="Identifier" href="eval.html#expr-==">expr-==</a>.<br>
<br>
<br>
MORE LOOPING<br>
<br>
The ":while" command was already mentioned. Two more statements can be used<br>
in between the ":while" and the ":endwhile":<br>
<br>
:continue Jump back to the start of the while loop; the<br>
loop continues.<br>
:break Jump forward to the ":endwhile"; the loop is<br>
discontinued.<br>
<br>
Example:<br>
<br>
<div class="helpExample"> :while counter < 40<br>
: call do_something()<br>
: if skip_flag<br>
: continue<br>
: endif<br>
: if finished_flag<br>
: break<br>
: endif<br>
: sleep 50m<br>
:endwhile</div>
<br>
The ":sleep" command makes Vim take a nap. The "50m" specifies fifty<br>
milliseconds. Another example is ":sleep 4", which sleeps for four seconds.<br>
<br>
Even more looping can be done with the ":for" command, see below in <a class="Identifier" href="usr_41.html#41.8">41.8</a>.<br>
<br>
<span class="PreProc">==============================================================================</span><br>
<a class="Constant" href="usr_41.html#41.5" name="41.5">41.5</a> Executing an expression<br>
<br>
So far the commands in the script were executed by Vim directly. The<br>
":execute" command allows executing the result of an expression. This is a<br>
very powerful way to build commands and execute them.<br>
An example is to jump to a tag, which is contained in a variable:<br>
<br>
<div class="helpExample"> :execute "tag " . tag_name</div>
<br>
The "." is used to concatenate the string "tag " with the value of variable<br>
"tag_name". Suppose "tag_name" has the value "get_cmd", then the command that<br>
will be executed is:<br>
<br>
<div class="helpExample"> :tag get_cmd</div>
<br>
The ":execute" command can only execute colon commands. The ":normal" command<br>
executes Normal mode commands. However, its argument is not an expression but<br>
the literal command characters. Example:<br>
<br>
<div class="helpExample"> :normal gg=G</div>
<br>
This jumps to the first line and formats all lines with the "=" operator.<br>
To make ":normal" work with an expression, combine ":execute" with it.<br>
Example:<br>
<br>
<div class="helpExample"> :execute "normal " . normal_commands</div>
<br>
The variable "normal_commands" must contain the Normal mode commands.<br>
Make sure that the argument for ":normal" is a complete command. Otherwise<br>
Vim will run into the end of the argument and abort the command. For example,<br>
if you start Insert mode, you must leave Insert mode as well. This works:<br>
<br>
<div class="helpExample"> :execute "normal Inew text \<Esc>"</div>
<br>
This inserts "new text " in the current line. Notice the use of the special<br>
key "\<span class="Special"><Esc></span>". This avoids having to enter a real <span class="Special"><Esc></span> character in your<br>
script.<br>
<br>
If you don't want to execute a string but evaluate it to get its expression<br>
value, you can use the eval() function:<br>
<br>
<div class="helpExample"> :let optname = "path"<br>
:let optval = eval('&' . optname)</div>
<br>
A "&" character is prepended to "path", thus the argument to eval() is<br>
"&path". The result will then be the value of the <a class="Type" href="options.html#'path'">'path'</a> option.<br>
The same thing can be done with:<br>
<div class="helpExample"> :exe 'let optval = &' . optname</div>
<br>
<span class="PreProc">==============================================================================</span><br>
<a class="Constant" href="usr_41.html#41.6" name="41.6">41.6</a> Using functions<br>
<br>
Vim defines many functions and provides a large amount of functionality that<br>
way. A few examples will be given in this section. You can find the whole<br>
list here: <a class="Identifier" href="eval.html#functions">functions</a>.<br>
<br>
A function is called with the ":call" command. The parameters are passed in<br>
between parentheses separated by commas. Example:<br>
<br>
<div class="helpExample"> :call search("Date: ", "W")</div>
<br>
This calls the search() function, with arguments "Date: " and "W". The<br>
search() function uses its first argument as a search pattern and the second<br>
one as flags. The "W" flag means the search doesn't wrap around the end of<br>
the file.<br>
<br>
A function can be called in an expression. Example:<br>
<br>
<div class="helpExample"> :let line = getline(".")<br>
:let repl = substitute(line, '\a', "*", "g")<br>
:call setline(".", repl)</div>
<br>
The getline() function obtains a line from the current buffer. Its argument<br>
is a specification of the line number. In this case "." is used, which means<br>
the line where the cursor is.<br>
The substitute() function does something similar to the ":substitute"<br>
command. The first argument is the string on which to perform the<br>
substitution. The second argument is the pattern, the third the replacement<br>
string. Finally, the last arguments are the flags.<br>
The setline() function sets the line, specified by the first argument, to a<br>
new string, the second argument. In this example the line under the cursor is<br>
replaced with the result of the substitute(). Thus the effect of the three<br>
statements is equal to:<br>
<br>
<div class="helpExample"> :substitute/\a/*/g</div>
<br>
Using the functions becomes more interesting when you do more work before and<br>
after the substitute() call.<br>
<br>
<br>
<span class="Statement">FUNCTIONS </span><a class="Constant" href="usr_41.html#function-list" name="function-list">function-list</a><br>
<br>
There are many functions. We will mention them here, grouped by what they are<br>
used for. You can find an alphabetical list here: <a class="Identifier" href="eval.html#functions">functions</a>. Use <span class="Special">CTRL-]</span> on<br>
the function name to jump to detailed help on it.<br>
<br>
String manipulation: <a class="Constant" href="usr_41.html#string-functions" name="string-functions">string-functions</a><br>
nr2char() get a character by its ASCII value<br>
char2nr() get ASCII value of a character<br>
str2nr() convert a string to a Number<br>
str2float() convert a string to a Float<br>
printf() format a string according to % items<br>
escape() escape characters in a string with a '\'<br>
shellescape() escape a string for use with a shell command<br>
fnameescape() escape a file name for use with a Vim command<br>
tr() translate characters from one set to another<br>
strtrans() translate a string to make it printable<br>
tolower() turn a string to lowercase<br>
toupper() turn a string to uppercase<br>
match() position where a pattern matches in a string<br>
matchend() position where a pattern match ends in a string<br>
matchstr() match of a pattern in a string<br>
matchstrpos() match and positions of a pattern in a string<br>
matchlist() like matchstr() and also return submatches<br>
stridx() first index of a short string in a long string<br>
strridx() last index of a short string in a long string<br>
strlen() length of a string in bytes<br>
strchars() length of a string in characters<br>
strwidth() size of string when displayed<br>
strdisplaywidth() size of string when displayed, deals with tabs<br>
substitute() substitute a pattern match with a string<br>
submatch() get a specific match in ":s" and substitute()<br>
strpart() get part of a string using byte index<br>
strcharpart() get part of a string using char index<br>
strgetchar() get character from a string using char index<br>
expand() expand special keywords<br>
iconv() convert text from one encoding to another<br>
byteidx() byte index of a character in a string<br>
byteidxcomp() like byteidx() but count composing characters<br>
repeat() repeat a string multiple times<br>
eval() evaluate a string expression<br>
execute() execute an Ex command and get the output<br>
<br>
List manipulation: <a class="Constant" href="usr_41.html#list-functions" name="list-functions">list-functions</a><br>
get() get an item without error for wrong index<br>
len() number of items in a List<br>
empty() check if List is empty<br>
insert() insert an item somewhere in a List<br>
add() append an item to a List<br>
extend() append a List to a List<br>
remove() remove one or more items from a List<br>
copy() make a shallow copy of a List<br>
deepcopy() make a full copy of a List<br>
filter() remove selected items from a List<br>
map() change each List item<br>
sort() sort a List<br>
reverse() reverse the order of a List<br>
uniq() remove copies of repeated adjacent items<br>
split() split a String into a List<br>
join() join List items into a String<br>
range() return a List with a sequence of numbers<br>
string() String representation of a List<br>
call() call a function with List as arguments<br>
index() index of a value in a List<br>
max() maximum value in a List<br>
min() minimum value in a List<br>
count() count number of times a value appears in a List<br>
repeat() repeat a List multiple times<br>
<br>
Dictionary manipulation: <a class="Constant" href="usr_41.html#dict-functions" name="dict-functions">dict-functions</a><br>
get() get an entry without an error for a wrong key<br>
len() number of entries in a Dictionary<br>
has_key() check whether a key appears in a Dictionary<br>
empty() check if Dictionary is empty<br>
remove() remove an entry from a Dictionary<br>
extend() add entries from one Dictionary to another<br>
filter() remove selected entries from a Dictionary<br>
map() change each Dictionary entry<br>
keys() get List of Dictionary keys<br>
values() get List of Dictionary values<br>
items() get List of Dictionary key-value pairs<br>
copy() make a shallow copy of a Dictionary<br>
deepcopy() make a full copy of a Dictionary<br>
string() String representation of a Dictionary<br>
max() maximum value in a Dictionary<br>
min() minimum value in a Dictionary<br>
count() count number of times a value appears<br>
<br>
Floating point computation: <a class="Constant" href="usr_41.html#float-functions" name="float-functions">float-functions</a><br>
float2nr() convert Float to Number<br>
abs() absolute value (also works for Number)<br>
round() round off<br>
ceil() round up<br>
floor() round down<br>
trunc() remove value after decimal point<br>
fmod() remainder of division<br>
exp() exponential<br>
log() natural logarithm (logarithm to base e)<br>
log10() logarithm to base 10<br>
pow() value of x to the exponent y<br>
sqrt() square root<br>
sin() sine<br>
cos() cosine<br>
tan() tangent<br>
asin() arc sine<br>
acos() arc cosine<br>
atan() arc tangent<br>
atan2() arc tangent<br>
sinh() hyperbolic sine<br>
cosh() hyperbolic cosine<br>
tanh() hyperbolic tangent<br>
isnan() check for not a number<br>
<br>
Other computation: <a class="Constant" href="usr_41.html#bitwise-function" name="bitwise-function">bitwise-function</a><br>
and() bitwise AND<br>
invert() bitwise invert<br>
or() bitwise OR<br>
xor() bitwise XOR<br>
sha256() SHA-256 hash<br>
<br>
Variables: <a class="Constant" href="usr_41.html#var-functions" name="var-functions">var-functions</a><br>
type() type of a variable<br>
islocked() check if a variable is locked<br>
funcref() get a Funcref for a function reference<br>
function() get a Funcref for a function name<br>
getbufvar() get a variable value from a specific buffer<br>
setbufvar() set a variable in a specific buffer<br>
getwinvar() get a variable from specific window<br>
gettabvar() get a variable from specific tab page<br>
gettabwinvar() get a variable from specific window & tab page<br>
setwinvar() set a variable in a specific window<br>
settabvar() set a variable in a specific tab page<br>
settabwinvar() set a variable in a specific window & tab page<br>
garbagecollect() possibly free memory<br>
<br>
Cursor and mark position: <a class="Constant" href="usr_41.html#cursor-functions" name="cursor-functions">cursor-functions</a> <a class="Constant" href="usr_41.html#mark-functions" name="mark-functions">mark-functions</a><br>
col() column number of the cursor or a mark<br>
virtcol() screen column of the cursor or a mark<br>
line() line number of the cursor or mark<br>
wincol() window column number of the cursor<br>
winline() window line number of the cursor<br>
cursor() position the cursor at a line/column<br>
screencol() get screen column of the cursor<br>
screenrow() get screen row of the cursor<br>
getcurpos() get position of the cursor<br>
getpos() get position of cursor, mark, etc.<br>
setpos() set position of cursor, mark, etc.<br>
byte2line() get line number at a specific byte count<br>
line2byte() byte count at a specific line<br>
diff_filler() get the number of filler lines above a line<br>
screenattr() get attribute at a screen line/row<br>
screenchar() get character code at a screen line/row<br>
<br>
Working with text in the current buffer: <a class="Constant" href="usr_41.html#text-functions" name="text-functions">text-functions</a><br>
getline() get a line or list of lines from the buffer<br>
setline() replace a line in the buffer<br>
append() append line or list of lines in the buffer<br>
indent() indent of a specific line<br>
cindent() indent according to C indenting<br>
lispindent() indent according to Lisp indenting<br>
nextnonblank() find next non-blank line<br>
prevnonblank() find previous non-blank line<br>
search() find a match for a pattern<br>
searchpos() find a match for a pattern<br>
searchpair() find the other end of a start/skip/end<br>
searchpairpos() find the other end of a start/skip/end<br>
searchdecl() search for the declaration of a name<br>
getcharsearch() return character search information<br>
setcharsearch() set character search information<br>
<br>
<a class="Constant" href="usr_41.html#system-functions" name="system-functions">system-functions</a> <a class="Constant" href="usr_41.html#file-functions" name="file-functions">file-functions</a><br>
System functions and manipulation of files:<br>
glob() expand wildcards<br>
globpath() expand wildcards in a number of directories<br>
glob2regpat() convert a glob pattern into a search pattern<br>
findfile() find a file in a list of directories<br>
finddir() find a directory in a list of directories<br>
resolve() find out where a shortcut points to<br>
fnamemodify() modify a file name<br>
pathshorten() shorten directory names in a path<br>
simplify() simplify a path without changing its meaning<br>
executable() check if an executable program exists<br>
exepath() full path of an executable program<br>
filereadable() check if a file can be read<br>
filewritable() check if a file can be written to<br>
getfperm() get the permissions of a file<br>
setfperm() set the permissions of a file<br>
getftype() get the kind of a file<br>
isdirectory() check if a directory exists<br>
getfsize() get the size of a file<br>
getcwd() get the current working directory<br>
haslocaldir() check if current window used <a class="Identifier" href="editing.html#:lcd">:lcd</a><br>
tempname() get the name of a temporary file<br>
mkdir() create a new directory<br>
delete() delete a file<br>
rename() rename a file<br>
system() get the result of a shell command as a string<br>
systemlist() get the result of a shell command as a list<br>
hostname() name of the system<br>
readfile() read a file into a List of lines<br>
writefile() write a List of lines into a file<br>
<br>
Date and Time: <a class="Constant" href="usr_41.html#date-functions" name="date-functions">date-functions</a> <a class="Constant" href="usr_41.html#time-functions" name="time-functions">time-functions</a><br>
getftime() get last modification time of a file<br>
localtime() get current time in seconds<br>
strftime() convert time to a string<br>
reltime() get the current or elapsed time accurately<br>
reltimestr() convert reltime() result to a string<br>
reltimefloat() convert reltime() result to a Float<br>
<br>
<a class="Constant" href="usr_41.html#buffer-functions" name="buffer-functions">buffer-functions</a> <a class="Constant" href="usr_41.html#window-functions" name="window-functions">window-functions</a> <a class="Constant" href="usr_41.html#arg-functions" name="arg-functions">arg-functions</a><br>
Buffers, windows and the argument list:<br>
argc() number of entries in the argument list<br>
argidx() current position in the argument list<br>
arglistid() get id of the argument list<br>
argv() get one entry from the argument list<br>
bufexists() check if a buffer exists<br>
buflisted() check if a buffer exists and is listed<br>
bufloaded() check if a buffer exists and is loaded<br>
bufname() get the name of a specific buffer<br>
bufnr() get the buffer number of a specific buffer<br>
tabpagebuflist() return List of buffers in a tab page<br>
tabpagenr() get the number of a tab page<br>
tabpagewinnr() like winnr() for a specified tab page<br>
winnr() get the window number for the current window<br>
bufwinid() get the window ID of a specific buffer<br>
bufwinnr() get the window number of a specific buffer<br>
winbufnr() get the buffer number of a specific window<br>
getbufline() get a list of lines from the specified buffer<br>
win_findbuf() find windows containing a buffer<br>
win_getid() get window ID of a window<br>
win_gotoid() go to window with ID<br>
win_id2tabwin() get tab and window nr from window ID<br>
win_id2win() get window nr from window ID<br>
getbufinfo() get a list with buffer information<br>
gettabinfo() get a list with tab page information<br>
getwininfo() get a list with window information<br>
<br>
Command line: <a class="Constant" href="usr_41.html#command-line-functions" name="command-line-functions">command-line-functions</a><br>
getcmdline() get the current command line<br>
getcmdpos() get position of the cursor in the command line<br>
setcmdpos() set position of the cursor in the command line<br>
getcmdtype() return the current command-line type<br>
getcmdwintype() return the current command-line window type<br>
getcompletion() list of command-line completion matches<br>
<br>
Quickfix and location lists: <a class="Constant" href="usr_41.html#quickfix-functions" name="quickfix-functions">quickfix-functions</a><br>
getqflist() list of quickfix errors<br>
setqflist() modify a quickfix list<br>
getloclist() list of location list items<br>
setloclist() modify a location list<br>
<br>
Insert mode completion: <a class="Constant" href="usr_41.html#completion-functions" name="completion-functions">completion-functions</a><br>
complete() set found matches<br>
complete_add() add to found matches<br>
complete_check() check if completion should be aborted<br>
pumvisible() check if the popup menu is displayed<br>
<br>
Folding: <a class="Constant" href="usr_41.html#folding-functions" name="folding-functions">folding-functions</a><br>
foldclosed() check for a closed fold at a specific line<br>
foldclosedend() like foldclosed() but return the last line<br>
foldlevel() check for the fold level at a specific line<br>
foldtext() generate the line displayed for a closed fold<br>
foldtextresult() get the text displayed for a closed fold<br>
<br>
Syntax and highlighting: <a class="Constant" href="usr_41.html#syntax-functions" name="syntax-functions">syntax-functions</a> <a class="Constant" href="usr_41.html#highlighting-functions" name="highlighting-functions">highlighting-functions</a><br>
clearmatches() clear all matches defined by <a class="Identifier" href="eval.html#matchadd()">matchadd()</a> and<br>
the <a class="Identifier" href="pattern.html#:match">:match</a> commands<br>
getmatches() get all matches defined by <a class="Identifier" href="eval.html#matchadd()">matchadd()</a> and<br>
the <a class="Identifier" href="pattern.html#:match">:match</a> commands<br>
hlexists() check if a highlight group exists<br>
hlID() get ID of a highlight group<br>
synID() get syntax ID at a specific position<br>
synIDattr() get a specific attribute of a syntax ID<br>
synIDtrans() get translated syntax ID<br>
synstack() get list of syntax IDs at a specific position<br>
synconcealed() get info about concealing<br>
diff_hlID() get highlight ID for diff mode at a position<br>
matchadd() define a pattern to highlight (a "match")<br>
matchaddpos() define a list of positions to highlight<br>
matcharg() get info about <a class="Identifier" href="pattern.html#:match">:match</a> arguments<br>
matchdelete() delete a match defined by <a class="Identifier" href="eval.html#matchadd()">matchadd()</a> or a<br>
<a class="Identifier" href="pattern.html#:match">:match</a> command<br>
setmatches() restore a list of matches saved by<br>
<a class="Identifier" href="eval.html#getmatches()">getmatches()</a><br>
<br>
Spelling: <a class="Constant" href="usr_41.html#spell-functions" name="spell-functions">spell-functions</a><br>
spellbadword() locate badly spelled word at or after cursor<br>
spellsuggest() return suggested spelling corrections<br>
soundfold() return the sound-a-like equivalent of a word<br>
<br>
History: <a class="Constant" href="usr_41.html#history-functions" name="history-functions">history-functions</a><br>
histadd() add an item to a history<br>
histdel() delete an item from a history<br>
histget() get an item from a history<br>
histnr() get highest index of a history list<br>
<br>
Interactive: <a class="Constant" href="usr_41.html#interactive-functions" name="interactive-functions">interactive-functions</a><br>
browse() put up a file requester<br>
browsedir() put up a directory requester<br>
confirm() let the user make a choice<br>
getchar() get a character from the user<br>
getcharmod() get modifiers for the last typed character<br>
feedkeys() put characters in the typeahead queue<br>
input() get a line from the user<br>
inputlist() let the user pick an entry from a list<br>
inputsecret() get a line from the user without showing it<br>
inputdialog() get a line from the user in a dialog<br>
inputsave() save and clear typeahead<br>
inputrestore() restore typeahead<br>
<br>
GUI: <a class="Constant" href="usr_41.html#gui-functions" name="gui-functions">gui-functions</a><br>
getfontname() get name of current font being used<br>
getwinposx() X position of the GUI Vim window<br>
getwinposy() Y position of the GUI Vim window<br>
balloon_show() set the balloon content<br>
<br>
Vim server: <a class="Constant" href="usr_41.html#server-functions" name="server-functions">server-functions</a><br>
serverlist() return the list of server names<br>
remote_startserve() run a server<br>
remote_send() send command characters to a Vim server<br>
remote_expr() evaluate an expression in a Vim server<br>
server2client() send a reply to a client of a Vim server<br>
remote_peek() check if there is a reply from a Vim server<br>
remote_read() read a reply from a Vim server<br>
foreground() move the Vim window to the foreground<br>
remote_foreground() move the Vim server window to the foreground<br>
<br>
Window size and position: <a class="Constant" href="usr_41.html#window-size-functions" name="window-size-functions">window-size-functions</a><br>
winheight() get height of a specific window<br>
winwidth() get width of a specific window<br>
winrestcmd() return command to restore window sizes<br>
winsaveview() get view of current window<br>
winrestview() restore saved view of current window<br>
<br>
Mappings: <a class="Constant" href="usr_41.html#mapping-functions" name="mapping-functions">mapping-functions</a><br>
hasmapto() check if a mapping exists<br>
mapcheck() check if a matching mapping exists<br>
maparg() get rhs of a mapping<br>
wildmenumode() check if the wildmode is active<br>
<br>
Testing: <a class="Constant" href="usr_41.html#test-functions" name="test-functions">test-functions</a><br>
assert_equal() assert that two expressions values are equal<br>
assert_notequal() assert that two expressions values are not equal<br>
assert_inrange() assert that an expression is inside a range<br>
assert_match() assert that a pattern matches the value<br>
assert_notmatch() assert that a pattern does not match the value<br>
assert_false() assert that an expression is false<br>
assert_true() assert that an expression is true<br>
assert_exception() assert that a command throws an exception<br>
assert_fails() assert that a function call fails<br>
assert_report() report a test failure<br>
test_alloc_fail() make memory allocation fail<br>
test_autochdir() enable <a class="Type" href="options.html#'autochdir'">'autochdir'</a> during startup<br>
test_override() test with Vim internal overrides<br>
test_garbagecollect_now() free memory right now<br>
test_ignore_error() ignore a specific error message<br>
test_null_channel() return a null Channel<br>
test_null_dict() return a null Dict<br>
test_null_job() return a null Job<br>
test_null_list() return a null List<br>
test_null_partial() return a null Partial function<br>
test_null_string() return a null String<br>
test_settime() set the time Vim uses internally<br>
<br>
Inter-process communication: <a class="Constant" href="usr_41.html#channel-functions" name="channel-functions">channel-functions</a><br>
ch_canread() check if there is something to read<br>
ch_open() open a channel<br>
ch_close() close a channel<br>
ch_close_in() close the in part of a channel<br>
ch_read() read a message from a channel<br>
ch_readraw() read a raw message from a channel<br>
ch_sendexpr() send a JSON message over a channel<br>
ch_sendraw() send a raw message over a channel<br>
ch_evalexpr() evaluates an expression over channel<br>
ch_evalraw() evaluates a raw string over channel<br>
ch_status() get status of a channel<br>
ch_getbufnr() get the buffer number of a channel<br>
ch_getjob() get the job associated with a channel<br>
ch_info() get channel information<br>
ch_log() write a message in the channel log file<br>
ch_logfile() set the channel log file<br>
ch_setoptions() set the options for a channel<br>
json_encode() encode an expression to a JSON string<br>
json_decode() decode a JSON string to Vim types<br>
js_encode() encode an expression to a JSON string<br>
js_decode() decode a JSON string to Vim types<br>
<br>
Jobs: <a class="Constant" href="usr_41.html#job-functions" name="job-functions">job-functions</a><br>
job_start() start a job<br>
job_stop() stop a job<br>
job_status() get the status of a job<br>
job_getchannel() get the channel used by a job<br>
job_info() get information about a job<br>
job_setoptions() set options for a job<br>
<br>
Timers: <a class="Constant" href="usr_41.html#timer-functions" name="timer-functions">timer-functions</a><br>
timer_start() create a timer<br>
timer_pause() pause or unpause a timer<br>
timer_stop() stop a timer<br>
timer_stopall() stop all timers<br>
timer_info() get information about timers<br>
<br>
Various: <a class="Constant" href="usr_41.html#various-functions" name="various-functions">various-functions</a><br>
mode() get current editing mode<br>
visualmode() last visual mode used<br>
exists() check if a variable, function, etc. exists<br>
has() check if a feature is supported in Vim<br>
changenr() return number of most recent change<br>
cscope_connection() check if a cscope connection exists<br>
did_filetype() check if a FileType autocommand was used<br>
eventhandler() check if invoked by an event handler<br>
getpid() get process ID of Vim<br>
<br>
libcall() call a function in an external library<br>
libcallnr() idem, returning a number<br>
<br>
undofile() get the name of the undo file<br>
undotree() return the state of the undo tree<br>
<br>
getreg() get contents of a register<br>
getregtype() get type of a register<br>
setreg() set contents and type of a register<br>
<br>
shiftwidth() effective value of <a class="Type" href="options.html#'shiftwidth'">'shiftwidth'</a><br>
<br>
wordcount() get byte/word/char count of buffer<br>
<br>
taglist() get list of matching tags<br>
tagfiles() get a list of tags files<br>
<br>
luaeval() evaluate Lua expression<br>
mzeval() evaluate <a class="Identifier" href="if_mzsch.html#MzScheme">MzScheme</a> expression<br>
perleval() evaluate Perl expression (<a class="Identifier" href="various.html#+perl">+perl</a>)<br>
py3eval() evaluate Python expression (<a class="Identifier" href="various.html#+python3">+python3</a>)<br>
pyeval() evaluate Python expression (<a class="Identifier" href="various.html#+python">+python</a>)<br>
pyxeval() evaluate <a class="Identifier" href="if_pyth.html#python_x">python_x</a> expression<br>
<br>
<span class="PreProc">==============================================================================</span><br>
<a class="Constant" href="usr_41.html#41.7" name="41.7">41.7</a> Defining a function<br>
<br>
Vim enables you to define your own functions. The basic function declaration<br>
begins as follows:<br>
<br>
<div class="helpExample"> :function {name}({var1}, {var2}, ...)<br>
: {body}<br>
:endfunction</div>
<br>
<span class="Todo">Note</span>:<br>
Function names must begin with a capital letter.<br>
<br>
Let's define a short function to return the smaller of two numbers. It starts<br>
with this line:<br>
<br>
<div class="helpExample"> :function Min(num1, num2)</div>
<br>
This tells Vim that the function is named "Min" and it takes two arguments:<br>
"num1" and "num2".<br>
The first thing you need to do is to check to see which number is smaller:<br>
<br>
<div class="helpExample"> : if a:num1 < a:num2</div>
<br>
The special prefix "a:" tells Vim that the variable is a function argument.<br>
Let's assign the variable "smaller" the value of the smallest number:<br>
<br>
<div class="helpExample"> : if a:num1 < a:num2<br>
: let smaller = a:num1<br>
: else<br>
: let smaller = a:num2<br>
: endif</div>
<br>
The variable "smaller" is a local variable. Variables used inside a function<br>
are local unless prefixed by something like "g:", "a:", or "s:".<br>
<br>
<span class="Todo">Note</span>:<br>
To access a global variable from inside a function you must prepend<br>
"g:" to it. Thus "g:today" inside a function is used for the global<br>
variable "today", and "today" is another variable, local to the<br>
function.<br>
<br>
You now use the ":return" statement to return the smallest number to the user.<br>
Finally, you end the function:<br>
<br>
<div class="helpExample"> : return smaller<br>
:endfunction</div>
<br>
The complete function definition is as follows:<br>
<br>
<div class="helpExample"> :function Min(num1, num2)<br>
: if a:num1 < a:num2<br>
: let smaller = a:num1<br>
: else<br>
: let smaller = a:num2<br>
: endif<br>
: return smaller<br>
:endfunction</div>
<br>
For people who like short functions, this does the same thing:<br>
<br>
<div class="helpExample"> :function Min(num1, num2)<br>
: if a:num1 < a:num2<br>
: return a:num1<br>
: endif<br>
: return a:num2<br>
:endfunction</div>
<br>
A user defined function is called in exactly the same way as a built-in<br>
function. Only the name is different. The Min function can be used like<br>
this:<br>
<br>
<div class="helpExample"> :echo Min(5, 8)</div>
<br>
Only now will the function be executed and the lines be interpreted by Vim.<br>
If there are mistakes, like using an undefined variable or function, you will<br>
now get an error message. When defining the function these errors are not<br>
detected.<br>
<br>
When a function reaches ":endfunction" or ":return" is used without an<br>
argument, the function returns zero.<br>
<br>
To redefine a function that already exists, use the ! for the ":function"<br>
command:<br>
<br>
<div class="helpExample"> :function! Min(num1, num2, num3)</div>
<br>
<br>
USING A RANGE<br>
<br>
The ":call" command can be given a line range. This can have one of two<br>
meanings. When a function has been defined with the "range" keyword, it will<br>
take care of the line range itself.<br>
The function will be passed the variables "a:firstline" and "a:lastline".<br>
These will have the line numbers from the range the function was called with.<br>
Example:<br>
<br>
<div class="helpExample"> :function Count_words() range<br>
: let lnum = a:firstline<br>
: let n = 0<br>
: while lnum <= a:lastline<br>
: let n = n + len(split(getline(lnum)))<br>
: let lnum = lnum + 1<br>
: endwhile<br>
: echo "found " . n . " words"<br>
:endfunction</div>
<br>
You can call this function with:<br>
<br>
<div class="helpExample"> :10,30call Count_words()</div>
<br>
It will be executed once and echo the number of words.<br>
The other way to use a line range is by defining a function without the<br>
"range" keyword. The function will be called once for every line in the<br>
range, with the cursor in that line. Example:<br>
<br>
<div class="helpExample"> :function Number()<br>
: echo "line " . line(".") . " contains: " . getline(".")<br>
:endfunction</div>
<br>
If you call this function with:<br>
<br>
<div class="helpExample"> :10,15call Number()</div>
<br>
The function will be called six times.<br>
<br>
<br>
VARIABLE NUMBER OF ARGUMENTS<br>
<br>
Vim enables you to define functions that have a variable number of arguments.<br>
The following command, for instance, defines a function that must have 1<br>
argument (start) and can have up to 20 additional arguments:<br>
<br>
<div class="helpExample"> :function Show(start, ...)</div>
<br>
The variable "a:1" contains the first optional argument, "a:2" the second, and<br>
so on. The variable "a:0" contains the number of extra arguments.<br>
For example:<br>
<br>
<div class="helpExample"> :function Show(start, ...)<br>
: echohl Title<br>
: echo "start is " . a:start<br>
: echohl None<br>
: let index = 1<br>
: while index <= a:0<br>
: echo " Arg " . index . " is " . a:{index}<br>
: let index = index + 1<br>
: endwhile<br>
: echo ""<br>
:endfunction</div>
<br>
This uses the ":echohl" command to specify the highlighting used for the<br>
following ":echo" command. ":echohl None" stops it again. The ":echon"<br>
command works like ":echo", but doesn't output a line break.<br>
<br>
You can also use the a:000 variable, it is a List of all the "..." arguments.<br>
See <a class="Identifier" href="eval.html#a:000">a:000</a>.<br>
<br>
<br>
LISTING FUNCTIONS<br>
<br>
The ":function" command lists the names and arguments of all user-defined<br>
functions:<br>
<br>
<div class="helpExample"> :function</div>
<span class="PreProc">function Show(start, ...)</span><br>
<span class="PreProc">function GetVimIndent()</span><br>
<span class="PreProc">function SetSyn(name)</span><br>
<br>
To see what a function does, use its name as an argument for ":function":<br>
<br>
<div class="helpExample"> :function SetSyn</div>
<span class="PreProc">1 if &syntax == ''</span><br>
<span class="PreProc">2 let &syntax = a:name</span><br>
<span class="PreProc">3 endif</span><br>
<span class="PreProc">endfunction</span><br>
<br>
<br>
DEBUGGING<br>
<br>
The line number is useful for when you get an error message or when debugging.<br>
See <a class="Identifier" href="repeat.html#debug-scripts">debug-scripts</a> about debugging mode.<br>
You can also set the <a class="Type" href="options.html#'verbose'">'verbose'</a> option to 12 or higher to see all function<br>
calls. Set it to 15 or higher to see every executed line.<br>
<br>
<br>
DELETING A FUNCTION<br>
<br>
To delete the Show() function:<br>
<br>
<div class="helpExample"> :delfunction Show</div>
<br>
You get an error when the function doesn't exist.<br>
<br>
<br>
FUNCTION REFERENCES<br>
<br>
Sometimes it can be useful to have a variable point to one function or<br>
another. You can do it with the function() function. It turns the name of a<br>
function into a reference:<br>
<br>
<div class="helpExample"> :let result = 0 " or 1<br>
:function! Right()<br>
: return 'Right!'<br>
:endfunc<br>
:function! Wrong()<br>
: return 'Wrong!'<br>
:endfunc<br>
:<br>
:if result == 1<br>
: let Afunc = function('Right')<br>
:else<br>
: let Afunc = function('Wrong')<br>
:endif<br>
:echo call(Afunc, [])</div>
<span class="PreProc">Wrong!</span><br>
<br>
<span class="Todo">Note</span> that the name of a variable that holds a function reference must start<br>
with a capital. Otherwise it could be confused with the name of a builtin<br>
function.<br>
The way to invoke a function that a variable refers to is with the call()<br>
function. Its first argument is the function reference, the second argument<br>
is a List with arguments.<br>
<br>
Function references are most useful in combination with a Dictionary, as is<br>
explained in the next section.<br>
<br>
<span class="PreProc">==============================================================================</span><br>
<a class="Constant" href="usr_41.html#41.8" name="41.8">41.8</a> Lists and Dictionaries<br>
<br>
So far we have used the basic types String and Number. Vim also supports two<br>
composite types: List and Dictionary.<br>
<br>
A List is an ordered sequence of things. The things can be any kind of value,<br>
thus you can make a List of numbers, a List of Lists and even a List of mixed<br>
items. To create a List with three strings:<br>
<br>
<div class="helpExample"> :let alist = ['aap', 'mies', 'noot']</div>
<br>
The List items are enclosed in square brackets and separated by commas. To<br>
create an empty List:<br>
<br>
<div class="helpExample"> :let alist = []</div>
<br>
You can add items to a List with the add() function:<br>
<br>
<div class="helpExample"> :let alist = []<br>
:call add(alist, 'foo')<br>
:call add(alist, 'bar')<br>
:echo alist</div>
<span class="PreProc">['foo', 'bar']</span><br>
<br>
List concatenation is done with +:<br>
<br>
<div class="helpExample"> :echo alist + ['foo', 'bar']</div>
<span class="PreProc">['foo', 'bar', 'foo', 'bar']</span><br>
<br>
Or, if you want to extend a List directly:<br>
<br>
<div class="helpExample"> :let alist = ['one']<br>
:call extend(alist, ['two', 'three'])<br>
:echo alist</div>
<span class="PreProc">['one', 'two', 'three']</span><br>
<br>
Notice that using add() will have a different effect:<br>
<br>
<div class="helpExample"> :let alist = ['one']<br>
:call add(alist, ['two', 'three'])<br>
:echo alist</div>
<span class="PreProc">['one', ['two', 'three']]</span><br>
<br>
The second argument of add() is added as a single item.<br>
<br>
<br>
FOR LOOP<br>
<br>
One of the nice things you can do with a List is iterate over it:<br>
<br>
<div class="helpExample"> :let alist = ['one', 'two', 'three']<br>
:for n in alist<br>
: echo n<br>
:endfor</div>
<span class="PreProc">one</span><br>
<span class="PreProc">two</span><br>
<span class="PreProc">three</span><br>
<br>
This will loop over each element in List "alist", assigning the value to<br>
variable "n". The generic form of a for loop is:<br>
<br>
<div class="helpExample"> :for {varname} in {listexpression}<br>
: {commands}<br>
:endfor</div>
<br>
To loop a certain number of times you need a List of a specific length. The<br>
range() function creates one for you:<br>
<br>
<div class="helpExample"> :for a in range(3)<br>
: echo a<br>
:endfor</div>
<span class="PreProc">0</span><br>
<span class="PreProc">1</span><br>
<span class="PreProc">2</span><br>
<br>
Notice that the first item of the List that range() produces is zero, thus the<br>
last item is one less than the length of the list.<br>
You can also specify the maximum value, the stride and even go backwards:<br>
<br>
<div class="helpExample"> :for a in range(8, 4, -2)<br>
: echo a<br>
:endfor</div>
<span class="PreProc">8</span><br>
<span class="PreProc">6</span><br>
<span class="PreProc">4</span><br>
<br>
A more useful example, looping over lines in the buffer:<br>
<br>
<div class="helpExample"> :for line in getline(1, 20)<br>
: if line =~ "Date: "<br>
: echo matchstr(line, 'Date: \zs.*')<br>
: endif<br>
:endfor</div>
<br>
This looks into lines 1 to 20 (inclusive) and echoes any date found in there.<br>
<br>
<br>
DICTIONARIES<br>
<br>
A Dictionary stores key-value pairs. You can quickly lookup a value if you<br>
know the key. A Dictionary is created with curly braces:<br>
<br>
<div class="helpExample"> :let uk2nl = {'one': 'een', 'two': 'twee', 'three': 'drie'}</div>
<br>
Now you can lookup words by putting the key in square brackets:<br>
<br>
<div class="helpExample"> :echo uk2nl['two']</div>
<span class="PreProc">twee</span><br>
<br>
The generic form for defining a Dictionary is:<br>
<br>
<div class="helpExample"> {<key> : <value>, ...}</div>
<br>
An empty Dictionary is one without any keys:<br>
<br>
<div class="helpExample"> {}</div>
<br>
The possibilities with Dictionaries are numerous. There are various functions<br>
for them as well. For example, you can obtain a list of the keys and loop<br>
over them:<br>
<br>
<div class="helpExample"> :for key in keys(uk2nl)<br>
: echo key<br>
:endfor</div>
<span class="PreProc">three</span><br>
<span class="PreProc">one</span><br>
<span class="PreProc">two</span><br>
<br>
You will notice the keys are not ordered. You can sort the list to get a<br>
specific order:<br>
<br>
<div class="helpExample"> :for key in sort(keys(uk2nl))<br>
: echo key<br>
:endfor</div>
<span class="PreProc">one</span><br>
<span class="PreProc">three</span><br>
<span class="PreProc">two</span><br>
<br>
But you can never get back the order in which items are defined. For that you<br>
need to use a List, it stores items in an ordered sequence.<br>
<br>
<br>
DICTIONARY FUNCTIONS<br>
<br>
The items in a Dictionary can normally be obtained with an index in square<br>
brackets:<br>
<br>
<div class="helpExample"> :echo uk2nl['one']</div>
<span class="PreProc">een</span><br>
<br>
A method that does the same, but without so many punctuation characters:<br>
<br>
<div class="helpExample"> :echo uk2nl.one</div>
<span class="PreProc">een</span><br>
<br>
This only works for a key that is made of ASCII letters, digits and the<br>
underscore. You can also assign a new value this way:<br>
<br>
<div class="helpExample"> :let uk2nl.four = 'vier'<br>
:echo uk2nl</div>
<span class="PreProc">{'three': 'drie', 'four': 'vier', 'one': 'een', 'two': 'twee'}</span><br>
<br>
And now for something special: you can directly define a function and store a<br>
reference to it in the dictionary:<br>
<br>
<div class="helpExample"> :function uk2nl.translate(line) dict<br>
: return join(map(split(a:line), 'get(self, v:val, "???")'))<br>
:endfunction</div>
<br>
Let's first try it out:<br>
<br>
<div class="helpExample"> :echo uk2nl.translate('three two five one')</div>
<span class="PreProc">drie twee ??? een</span><br>
<br>
The first special thing you notice is the "dict" at the end of the ":function"<br>
line. This marks the function as being used from a Dictionary. The "self"<br>
local variable will then refer to that Dictionary.<br>
Now let's break up the complicated return command:<br>
<br>
<div class="helpExample"> split(a:line)</div>
<br>
The split() function takes a string, chops it into whitespace separated words<br>
and returns a list with these words. Thus in the example it returns:<br>
<br>
<div class="helpExample"> :echo split('three two five one')</div>
<span class="PreProc">['three', 'two', 'five', 'one']</span><br>
<br>
This list is the first argument to the map() function. This will go through<br>
the list, evaluating its second argument with "v:val" set to the value of each<br>
item. This is a shortcut to using a for loop. This command:<br>
<br>
<div class="helpExample"> :let alist = map(split(a:line), 'get(self, v:val, "???")')</div>
<br>
Is equivalent to:<br>
<br>
<div class="helpExample"> :let alist = split(a:line)<br>
:for idx in range(len(alist))<br>
: let alist[idx] = get(self, alist[idx], "???")<br>
:endfor</div>
<br>
The get() function checks if a key is present in a Dictionary. If it is, then<br>
the value is retrieved. If it isn't, then the default value is returned, in<br>
the example it's '???'. This is a convenient way to handle situations where a<br>
key may not be present and you don't want an error message.<br>
<br>
The join() function does the opposite of split(): it joins together a list of<br>
words, putting a space in between.<br>
This combination of split(), map() and join() is a nice way to filter a line<br>
of words in a very compact way.<br>
<br>
<br>
OBJECT ORIENTED PROGRAMMING<br>
<br>
Now that you can put both values and functions in a Dictionary, you can<br>
actually use a Dictionary like an object.<br>
Above we used a Dictionary for translating Dutch to English. We might want<br>
to do the same for other languages. Let's first make an object (aka<br>
Dictionary) that has the translate function, but no words to translate:<br>
<br>
<div class="helpExample"> :let transdict = {}<br>
:function transdict.translate(line) dict<br>
: return join(map(split(a:line), 'get(self.words, v:val, "???")'))<br>
:endfunction</div>
<br>
It's slightly different from the function above, using 'self.words' to lookup<br>
word translations. But we don't have a self.words. Thus you could call this<br>
an abstract class.<br>
<br>
Now we can instantiate a Dutch translation object:<br>
<br>
<div class="helpExample"> :let uk2nl = copy(transdict)<br>
:let uk2nl.words = {'one': 'een', 'two': 'twee', 'three': 'drie'}<br>
:echo uk2nl.translate('three one')</div>
<span class="PreProc">drie een</span><br>
<br>
And a German translator:<br>
<br>
<div class="helpExample"> :let uk2de = copy(transdict)<br>
:let uk2de.words = {'one': 'eins', 'two': 'zwei', 'three': 'drei'}<br>
:echo uk2de.translate('three one')</div>
<span class="PreProc">drei eins</span><br>
<br>
You see that the copy() function is used to make a copy of the "transdict"<br>
Dictionary and then the copy is changed to add the words. The original<br>
remains the same, of course.<br>
<br>
Now you can go one step further, and use your preferred translator:<br>
<br>
<div class="helpExample"> :if $LANG =~ "de"<br>
: let trans = uk2de<br>
:else<br>
: let trans = uk2nl<br>
:endif<br>
:echo trans.translate('one two three')</div>
<span class="PreProc">een twee drie</span><br>
<br>
Here "trans" refers to one of the two objects (Dictionaries). No copy is<br>
made. More about List and Dictionary identity can be found at <a class="Identifier" href="eval.html#list-identity">list-identity</a><br>
and <a class="Identifier" href="eval.html#dict-identity">dict-identity</a>.<br>
<br>
Now you might use a language that isn't supported. You can overrule the<br>
translate() function to do nothing:<br>
<br>
<div class="helpExample"> :let uk2uk = copy(transdict)<br>
:function! uk2uk.translate(line)<br>
: return a:line<br>
:endfunction<br>
:echo uk2uk.translate('three one wladiwostok')</div>
<span class="PreProc">three one wladiwostok</span><br>
<br>
Notice that a ! was used to overwrite the existing function reference. Now<br>
use "uk2uk" when no recognized language is found:<br>
<br>
<div class="helpExample"> :if $LANG =~ "de"<br>
: let trans = uk2de<br>
:elseif $LANG =~ "nl"<br>
: let trans = uk2nl<br>
:else<br>
: let trans = uk2uk<br>
:endif<br>
:echo trans.translate('one two three')</div>
<span class="PreProc">one two three</span><br>
<br>
For further reading see <a class="Identifier" href="eval.html#Lists">Lists</a> and <a class="Identifier" href="eval.html#Dictionaries">Dictionaries</a>.<br>
<br>
<span class="PreProc">==============================================================================</span><br>
<a class="Constant" href="usr_41.html#41.9" name="41.9">41.9</a> Exceptions<br>
<br>
Let's start with an example:<br>
<br>
<div class="helpExample"> :try<br>
: read ~/templates/pascal.tmpl<br>
:catch /E484:/<br>
: echo "Sorry, the Pascal template file cannot be found."<br>
:endtry</div>
<br>
The ":read" command will fail if the file does not exist. Instead of<br>
generating an error message, this code catches the error and gives the user a<br>
nice message.<br>
<br>
For the commands in between ":try" and ":endtry" errors are turned into<br>
exceptions. An exception is a string. In the case of an error the string<br>
contains the error message. And every error message has a number. In this<br>
case, the error we catch contains "E484:". This number is guaranteed to stay<br>
the same (the text may change, e.g., it may be translated).<br>
<br>
When the ":read" command causes another error, the pattern "E484:" will not<br>
match in it. Thus this exception will not be caught and result in the usual<br>
error message.<br>
<br>
You might be tempted to do this:<br>
<br>
<div class="helpExample"> :try<br>
: read ~/templates/pascal.tmpl<br>
:catch<br>
: echo "Sorry, the Pascal template file cannot be found."<br>
:endtry</div>
<br>
This means all errors are caught. But then you will not see errors that are<br>
useful, such as "E21: Cannot make changes, <a class="Type" href="options.html#'modifiable'">'modifiable'</a> is off".<br>
<br>
Another useful mechanism is the ":finally" command:<br>
<br>
<div class="helpExample"> :let tmp = tempname()<br>
:try<br>
: exe ".,$write " . tmp<br>
: exe "!filter " . tmp<br>
: .,$delete<br>
: exe "$read " . tmp<br>
:finally<br>
: call delete(tmp)<br>
:endtry</div>
<br>
This filters the lines from the cursor until the end of the file through the<br>
"filter" command, which takes a file name argument. No matter if the<br>
filtering works, something goes wrong in between ":try" and ":finally" or the<br>
user cancels the filtering by pressing <span class="Special">CTRL-C</span>, the "call delete(tmp)" is<br>
always executed. This makes sure you don't leave the temporary file behind.<br>
<br>
More information about exception handling can be found in the reference<br>
manual: <a class="Identifier" href="eval.html#exception-handling">exception-handling</a>.<br>
<br>
<span class="PreProc">==============================================================================</span><br>
<a class="Constant" href="usr_41.html#41.10" name="41.10">41.10</a> Various remarks<br>
<br>
Here is a summary of items that apply to Vim scripts. They are also mentioned<br>
elsewhere, but form a nice checklist.<br>
<br>
The end-of-line character depends on the system. For Unix a single <span class="Special"><NL></span><br>
character is used. For MS-DOS, Windows, OS/2 and the like, <span class="Special"><CR><LF></span> is used.<br>
This is important when using mappings that end in a <span class="Special"><CR></span>. See <a class="Identifier" href="repeat.html#:source_crnl">:source_crnl</a>.<br>
<br>
<br>
WHITE SPACE<br>
<br>
Blank lines are allowed and ignored.<br>
<br>
Leading whitespace characters (blanks and TABs) are always ignored. The<br>
whitespaces between parameters (e.g. between the "set" and the "cpoptions" in<br>
the example below) are reduced to one blank character and plays the role of a<br>
separator, the whitespaces after the last (visible) character may or may not<br>
be ignored depending on the situation, see below.<br>
<br>
For a ":set" command involving the "=" (equal) sign, such as in:<br>
<br>
<div class="helpExample"> :set cpoptions =aABceFst</div>
<br>
the whitespace immediately before the "=" sign is ignored. But there can be<br>
no whitespace after the "=" sign!<br>
<br>
To include a whitespace character in the value of an option, it must be<br>
escaped by a "\" (backslash) as in the following example:<br>
<br>
<div class="helpExample"> :set tags=my\ nice\ file</div>
<br>
The same example written as:<br>
<br>
<div class="helpExample"> :set tags=my nice file</div>
<br>
will issue an error, because it is interpreted as:<br>
<br>
<div class="helpExample"> :set tags=my<br>
:set nice<br>
:set file</div>
<br>
<br>
COMMENTS<br>
<br>
The character " (the double quote mark) starts a comment. Everything after<br>
and including this character until the end-of-line is considered a comment and<br>
is ignored, except for commands that don't consider comments, as shown in<br>
examples below. A comment can start on any character position on the line.<br>
<br>
There is a little "catch" with comments for some commands. Examples:<br>
<br>
<div class="helpExample"> :abbrev dev development " shorthand<br>
:map <F3> o#include " insert include<br>
:execute cmd " do it<br>
:!ls *.c " list C files</div>
<br>
The abbreviation <span class="MissingTag">'dev'</span> will be expanded to 'development " shorthand'. The<br>
mapping of <span class="Special"><F3></span> will actually be the whole line after the 'o# ....' including<br>
the '" insert include'. The "execute" command will give an error. The "!"<br>
command will send everything after it to the shell, causing an error for an<br>
unmatched '"' character.<br>
There can be no comment after ":map", ":abbreviate", ":execute" and "!"<br>
commands (there are a few more commands with this restriction). For the<br>
":map", ":abbreviate" and ":execute" commands there is a trick:<br>
<br>
<div class="helpExample"> :abbrev dev development|" shorthand<br>
:map <F3> o#include|" insert include<br>
:execute cmd |" do it</div>
<br>
With the '|' character the command is separated from the next one. And that<br>
next command is only a comment. For the last command you need to do two<br>
things: <a class="Identifier" href="eval.html#:execute">:execute</a> and use '|':<br>
<div class="helpExample"> :exe '!ls *.c' |" list C files</div>
<br>
Notice that there is no white space before the '|' in the abbreviation and<br>
mapping. For these commands, any character until the end-of-line or '|' is<br>
included. As a consequence of this behavior, you don't always see that<br>
trailing whitespace is included:<br>
<br>
<div class="helpExample"> :map <F4> o#include </div>
<br>
To spot these problems, you can set the <a class="Type" href="options.html#'list'">'list'</a> option when editing vimrc<br>
files.<br>
<br>
For Unix there is one special way to comment a line, that allows making a Vim<br>
script executable:<br>
<div class="helpExample"> #!/usr/bin/env vim -S<br>
echo "this is a Vim script"<br>
quit</div>
<br>
The "#" command by itself lists a line with the line number. Adding an<br>
exclamation mark changes it into doing nothing, so that you can add the shell<br>
command to execute the rest of the file. <a class="Identifier" href="various.html#:#!">:#!</a> <a class="Identifier" href="starting.html#-S">-S</a><br>
<br>
<br>
PITFALLS<br>
<br>
Even bigger problem arises in the following example:<br>
<br>
<div class="helpExample"> :map ,ab o#include<br>
:unmap ,ab </div>
<br>
Here the unmap command will not work, because it tries to unmap ",ab ". This<br>
does not exist as a mapped sequence. An error will be issued, which is very<br>
hard to identify, because the ending whitespace character in ":unmap ,ab " is<br>
not visible.<br>
<br>
And this is the same as what happens when one uses a comment after an <span class="MissingTag">'unmap'</span><br>
command:<br>
<br>
<div class="helpExample"> :unmap ,ab " comment</div>
<br>
Here the comment part will be ignored. However, Vim will try to unmap<br>
',ab ', which does not exist. Rewrite it as:<br>
<br>
<div class="helpExample"> :unmap ,ab| " comment</div>
<br>
<br>
RESTORING THE VIEW<br>
<br>
Sometimes you want to make a change and go back to where the cursor was.<br>
Restoring the relative position would also be nice, so that the same line<br>
appears at the top of the window.<br>
This example yanks the current line, puts it above the first line in the<br>
file and then restores the view:<br>
<br>
<div class="helpExample"> map ,p ma"aYHmbgg"aP`bzt`a</div>
<br>
What this does:<br>
<div class="helpExample"> ma"aYHmbgg"aP`bzt`a</div>
ma set mark a at cursor position<br>
"aY yank current line into register a<br>
Hmb go to top line in window and set mark b there<br>
gg go to first line in file<br>
"aP put the yanked line above it<br>
`b go back to top line in display<br>
zt position the text in the window as before<br>
`a go back to saved cursor position<br>
<br>
<br>
PACKAGING<br>
<br>
To avoid your function names to interfere with functions that you get from<br>
others, use this scheme:<br>
- Prepend a unique string before each function name. I often use an<br>
abbreviation. For example, "OW_" is used for the option window functions.<br>
- Put the definition of your functions together in a file. Set a global<br>
variable to indicate that the functions have been loaded. When sourcing the<br>
file again, first unload the functions.<br>
Example:<br>
<br>
<div class="helpExample"> " This is the XXX package</div>
<br>
<div class="helpExample"> if exists("XXX_loaded")<br>
delfun XXX_one<br>
delfun XXX_two<br>
endif</div>
<br>
<div class="helpExample"> function XXX_one(a)<br>
... body of function ...<br>
endfun</div>
<br>
<div class="helpExample"> function XXX_two(b)<br>
... body of function ...<br>
endfun</div>
<br>
<div class="helpExample"> let XXX_loaded = 1</div>
<br>
<span class="PreProc">==============================================================================</span><br>
<a class="Constant" href="usr_41.html#41.11" name="41.11">41.11</a> Writing a plugin <a class="Constant" href="usr_41.html#write-plugin" name="write-plugin">write-plugin</a><br>
<br>
You can write a Vim script in such a way that many people can use it. This is<br>
called a plugin. Vim users can drop your script in their plugin directory and<br>
use its features right away <a class="Identifier" href="usr_05.html#add-plugin">add-plugin</a>.<br>
<br>
There are actually two types of plugins:<br>
<br>
global plugins: For all types of files.<br>
filetype plugins: Only for files of a specific type.<br>
<br>
In this section the first type is explained. Most items are also relevant for<br>
writing filetype plugins. The specifics for filetype plugins are in the next<br>
section <a class="Identifier" href="usr_41.html#write-filetype-plugin">write-filetype-plugin</a>.<br>
<br>
<br>
NAME<br>
<br>
First of all you must choose a name for your plugin. The features provided<br>
by the plugin should be clear from its name. And it should be unlikely that<br>
someone else writes a plugin with the same name but which does something<br>
different. And please limit the name to 8 characters, to avoid problems on<br>
old Windows systems.<br>
<br>
A script that corrects typing mistakes could be called "typecorr.vim". We<br>
will use it here as an example.<br>
<br>
For the plugin to work for everybody, it should follow a few guidelines. This<br>
will be explained step-by-step. The complete example plugin is at the end.<br>
<br>
<br>
BODY<br>
<br>
Let's start with the body of the plugin, the lines that do the actual work:<br>
<br>
<div class="helpExample"> 14 iabbrev teh the<br>
15 iabbrev otehr other<br>
16 iabbrev wnat want<br>
17 iabbrev synchronisation<br>
18 \ synchronization<br>
19 let s:count = 4</div>
<br>
The actual list should be much longer, of course.<br>
<br>
The line numbers have only been added to explain a few things, don't put them<br>
in your plugin file!<br>
<br>
<br>
HEADER<br>
<br>
You will probably add new corrections to the plugin and soon have several<br>
versions lying around. And when distributing this file, people will want to<br>
know who wrote this wonderful plugin and where they can send remarks.<br>
Therefore, put a header at the top of your plugin:<br>
<br>
<div class="helpExample"> 1 " Vim global plugin for correcting typing mistakes<br>
2 " Last Change: 2000 Oct 15<br>
3 " Maintainer: Bram Moolenaar <Bram@vim.org></div>
<br>
About copyright and licensing: Since plugins are very useful and it's hardly<br>
worth restricting their distribution, please consider making your plugin<br>
either public domain or use the Vim <a class="Identifier" href="uganda.html#license">license</a>. A short <span class="Todo">note</span> about this near<br>
the top of the plugin should be sufficient. Example:<br>
<br>
<div class="helpExample"> 4 " License: This file is placed in the public domain.</div>
<br>
<br>
LINE CONTINUATION, AVOIDING SIDE EFFECTS <a class="Constant" href="usr_41.html#use-cpo-save" name="use-cpo-save">use-cpo-save</a><br>
<br>
In line 18 above, the line-continuation mechanism is used <a class="Identifier" href="repeat.html#line-continuation">line-continuation</a>.<br>
Users with <a class="Type" href="options.html#'compatible'">'compatible'</a> set will run into trouble here, they will get an error<br>
message. We can't just reset <a class="Type" href="options.html#'compatible'">'compatible'</a>, because that has a lot of side<br>
effects. To avoid this, we will set the <a class="Type" href="options.html#'cpoptions'">'cpoptions'</a> option to its Vim default<br>
value and restore it later. That will allow the use of line-continuation and<br>
make the script work for most people. It is done like this:<br>
<br>
<div class="helpExample"> 11 let s:save_cpo = &cpo<br>
12 set cpo&vim<br>
..<br>
42 let &cpo = s:save_cpo<br>
43 unlet s:save_cpo</div>
<br>
We first store the old value of <a class="Type" href="options.html#'cpoptions'">'cpoptions'</a> in the s:save_cpo variable. At<br>
the end of the plugin this value is restored.<br>
<br>
Notice that a script-local variable is used <a class="Identifier" href="eval.html#s:var">s:var</a>. A global variable could<br>
already be in use for something else. Always use script-local variables for<br>
things that are only used in the script.<br>
<br>
<br>
NOT LOADING<br>
<br>
It's possible that a user doesn't always want to load this plugin. Or the<br>
system administrator has dropped it in the system-wide plugin directory, but a<br>
user has his own plugin he wants to use. Then the user must have a chance to<br>
disable loading this specific plugin. This will make it possible:<br>
<br>
<div class="helpExample"> 6 if exists("g:loaded_typecorr")<br>
7 finish<br>
8 endif<br>
9 let g:loaded_typecorr = 1</div>
<br>
This also avoids that when the script is loaded twice it would cause error<br>
messages for redefining functions and cause trouble for autocommands that are<br>
added twice.<br>
<br>
The name is recommended to start with "loaded_" and then the file name of the<br>
plugin, literally. The "g:" is prepended just to avoid mistakes when using<br>
the variable in a function (without "g:" it would be a variable local to the<br>
function).<br>
<br>
Using "finish" stops Vim from reading the rest of the file, it's much quicker<br>
than using if-endif around the whole file.<br>
<br>
<br>
MAPPING<br>
<br>
Now let's make the plugin more interesting: We will add a mapping that adds a<br>
correction for the word under the cursor. We could just pick a key sequence<br>
for this mapping, but the user might already use it for something else. To<br>
allow the user to define which keys a mapping in a plugin uses, the <span class="Special"><Leader></span><br>
item can be used:<br>
<br>
<div class="helpExample"> 22 map <unique> <Leader>a <Plug>TypecorrAdd</div>
<br>
The "<span class="Special"><Plug></span>TypecorrAdd" thing will do the work, more about that further on.<br>
<br>
The user can set the "mapleader" variable to the key sequence that he wants<br>
this mapping to start with. Thus if the user has done:<br>
<br>
<div class="helpExample"> let mapleader = "_"</div>
<br>
the mapping will define "_a". If the user didn't do this, the default value<br>
will be used, which is a backslash. Then a map for "\a" will be defined.<br>
<br>
<span class="Todo">Note</span> that <span class="Special"><unique></span> is used, this will cause an error message if the mapping<br>
already happened to exist. <a class="Identifier" href="map.html#:map-<unique>">:map-<unique></a><br>
<br>
But what if the user wants to define his own key sequence? We can allow that<br>
with this mechanism:<br>
<br>
<div class="helpExample"> 21 if !hasmapto('<Plug>TypecorrAdd')<br>
22 map <unique> <Leader>a <Plug>TypecorrAdd<br>
23 endif</div>
<br>
This checks if a mapping to "<span class="Special"><Plug></span>TypecorrAdd" already exists, and only<br>
defines the mapping from "<span class="Special"><Leader></span>a" if it doesn't. The user then has a<br>
chance of putting this in his vimrc file:<br>
<br>
<div class="helpExample"> map ,c <Plug>TypecorrAdd</div>
<br>
Then the mapped key sequence will be ",c" instead of "_a" or "\a".<br>
<br>
<br>
PIECES<br>
<br>
If a script gets longer, you often want to break up the work in pieces. You<br>
can use functions or mappings for this. But you don't want these functions<br>
and mappings to interfere with the ones from other scripts. For example, you<br>
could define a function Add(), but another script could try to define the same<br>
function. To avoid this, we define the function local to the script by<br>
prepending it with "s:".<br>
<br>
We will define a function that adds a new typing correction:<br>
<br>
<div class="helpExample"> 30 function s:Add(from, correct)<br>
31 let to = input("type the correction for " . a:from . ": ")<br>
32 exe ":iabbrev " . a:from . " " . to<br>
..<br>
36 endfunction</div>
<br>
Now we can call the function s:Add() from within this script. If another<br>
script also defines s:Add(), it will be local to that script and can only<br>
be called from the script it was defined in. There can also be a global Add()<br>
function (without the "s:"), which is again another function.<br>
<br>
<span class="Special"><SID></span> can be used with mappings. It generates a script ID, which identifies<br>
the current script. In our typing correction plugin we use it like this:<br>
<br>
<div class="helpExample"> 24 noremap <unique> <script> <Plug>TypecorrAdd <SID>Add<br>
..<br>
28 noremap <SID>Add :call <SID>Add(expand("<cword>"), 1)<CR></div>
<br>
Thus when a user types "\a", this sequence is invoked:<br>
<br>
<div class="helpExample"> \a -> <Plug>TypecorrAdd -> <SID>Add -> :call <SID>Add()</div>
<br>
If another script would also map <span class="Special"><SID></span>Add, it would get another script ID and<br>
thus define another mapping.<br>
<br>
<span class="Todo">Note</span> that instead of s:Add() we use <span class="Special"><SID></span>Add() here. That is because the<br>
mapping is typed by the user, thus outside of the script. The <span class="Special"><SID></span> is<br>
translated to the script ID, so that Vim knows in which script to look for<br>
the Add() function.<br>
<br>
This is a bit complicated, but it's required for the plugin to work together<br>
with other plugins. The basic rule is that you use <span class="Special"><SID></span>Add() in mappings and<br>
s:Add() in other places (the script itself, autocommands, user commands).<br>
<br>
We can also add a menu entry to do the same as the mapping:<br>
<br>
<div class="helpExample"> 26 noremenu <script> Plugin.Add\ Correction <SID>Add</div>
<br>
The "Plugin" menu is recommended for adding menu items for plugins. In this<br>
case only one item is used. When adding more items, creating a submenu is<br>
recommended. For example, "Plugin.CVS" could be used for a plugin that offers<br>
CVS operations "Plugin.CVS.checkin", "Plugin.CVS.checkout", etc.<br>
<br>
<span class="Todo">Note</span> that in line 28 ":noremap" is used to avoid that any other mappings cause<br>
trouble. Someone may have remapped ":call", for example. In line 24 we also<br>
use ":noremap", but we do want "<span class="Special"><SID></span>Add" to be remapped. This is why<br>
"<span class="Special"><script></span>" is used here. This only allows mappings which are local to the<br>
script. <a class="Identifier" href="map.html#:map-<script>">:map-<script></a> The same is done in line 26 for ":noremenu".<br>
<a class="Identifier" href="gui.html#:menu-<script>">:menu-<script></a><br>
<br>
<br>
<span class="Special"><SID></span> AND <span class="Special"><Plug></span> <a class="Constant" href="usr_41.html#using-<Plug>" name="using-<Plug>">using-<Plug></a><br>
<br>
Both <span class="Special"><SID></span> and <span class="Special"><Plug></span> are used to avoid that mappings of typed keys interfere<br>
with mappings that are only to be used from other mappings. <span class="Todo">Note</span> the<br>
difference between using <span class="Special"><SID></span> and <span class="Special"><Plug></span>:<br>
<br>
<span class="Special"><Plug></span> is visible outside of the script. It is used for mappings which the<br>
user might want to map a key sequence to. <span class="Special"><Plug></span> is a special code<br>
that a typed key will never produce.<br>
To make it very unlikely that other plugins use the same sequence of<br>
characters, use this structure: <span class="Special"><Plug></span> scriptname mapname<br>
In our example the scriptname is "Typecorr" and the mapname is "Add".<br>
This results in "<span class="Special"><Plug></span>TypecorrAdd". Only the first character of<br>
scriptname and mapname is uppercase, so that we can see where mapname<br>
starts.<br>
<br>
<span class="Special"><SID></span> is the script ID, a unique identifier for a script.<br>
Internally Vim translates <span class="Special"><SID></span> to "<span class="Special"><SNR></span>123_", where "123" can be any<br>
number. Thus a function "<span class="Special"><SID></span>Add()" will have a name "<span class="Special"><SNR></span>11_Add()"<br>
in one script, and "<span class="Special"><SNR></span>22_Add()" in another. You can see this if<br>
you use the ":function" command to get a list of functions. The<br>
translation of <span class="Special"><SID></span> in mappings is exactly the same, that's how you<br>
can call a script-local function from a mapping.<br>
<br>
<br>
USER COMMAND<br>
<br>
Now let's add a user command to add a correction:<br>
<br>
<div class="helpExample"> 38 if !exists(":Correct")<br>
39 command -nargs=1 Correct :call s:Add(<q-args>, 0)<br>
40 endif</div>
<br>
The user command is defined only if no command with the same name already<br>
exists. Otherwise we would get an error here. Overriding the existing user<br>
command with ":command!" is not a good idea, this would probably make the user<br>
wonder why the command he defined himself doesn't work. <a class="Identifier" href="map.html#:command">:command</a><br>
<br>
<br>
SCRIPT VARIABLES<br>
<br>
When a variable starts with "s:" it is a script variable. It can only be used<br>
inside a script. Outside the script it's not visible. This avoids trouble<br>
with using the same variable name in different scripts. The variables will be<br>
kept as long as Vim is running. And the same variables are used when sourcing<br>
the same script again. <a class="Identifier" href="eval.html#s:var">s:var</a><br>
<br>
The fun is that these variables can also be used in functions, autocommands<br>
and user commands that are defined in the script. In our example we can add<br>
a few lines to count the number of corrections:<br>
<br>
<div class="helpExample"> 19 let s:count = 4<br>
..<br>
30 function s:Add(from, correct)<br>
..<br>
34 let s:count = s:count + 1<br>
35 echo s:count . " corrections now"<br>
36 endfunction</div>
<br>
First s:count is initialized to 4 in the script itself. When later the<br>
s:Add() function is called, it increments s:count. It doesn't matter from<br>
where the function was called, since it has been defined in the script, it<br>
will use the local variables from this script.<br>
<br>
<br>
THE RESULT<br>
<br>
Here is the resulting complete example:<br>
<br>
<div class="helpExample"> 1 " Vim global plugin for correcting typing mistakes<br>
2 " Last Change: 2000 Oct 15<br>
3 " Maintainer: Bram Moolenaar <Bram@vim.org><br>
4 " License: This file is placed in the public domain.<br>
5<br>
6 if exists("g:loaded_typecorr")<br>
7 finish<br>
8 endif<br>
9 let g:loaded_typecorr = 1<br>
10<br>
11 let s:save_cpo = &cpo<br>
12 set cpo&vim<br>
13<br>
14 iabbrev teh the<br>
15 iabbrev otehr other<br>
16 iabbrev wnat want<br>
17 iabbrev synchronisation<br>
18 \ synchronization<br>
19 let s:count = 4<br>
20<br>
21 if !hasmapto('<Plug>TypecorrAdd')<br>
22 map <unique> <Leader>a <Plug>TypecorrAdd<br>
23 endif<br>
24 noremap <unique> <script> <Plug>TypecorrAdd <SID>Add<br>
25<br>
26 noremenu <script> Plugin.Add\ Correction <SID>Add<br>
27<br>
28 noremap <SID>Add :call <SID>Add(expand("<cword>"), 1)<CR><br>
29<br>
30 function s:Add(from, correct)<br>
31 let to = input("type the correction for " . a:from . ": ")<br>
32 exe ":iabbrev " . a:from . " " . to<br>
33 if a:correct | exe "normal viws\<C-R>\" \b\e" | endif<br>
34 let s:count = s:count + 1<br>
35 echo s:count . " corrections now"<br>
36 endfunction<br>
37<br>
38 if !exists(":Correct")<br>
39 command -nargs=1 Correct :call s:Add(<q-args>, 0)<br>
40 endif<br>
41<br>
42 let &cpo = s:save_cpo<br>
43 unlet s:save_cpo</div>
<br>
Line 33 wasn't explained yet. It applies the new correction to the word under<br>
the cursor. The <a class="Identifier" href="various.html#:normal">:normal</a> command is used to use the new abbreviation. <span class="Todo">Note</span><br>
that mappings and abbreviations are expanded here, even though the function<br>
was called from a mapping defined with ":noremap".<br>
<br>
Using "unix" for the <a class="Type" href="options.html#'fileformat'">'fileformat'</a> option is recommended. The Vim scripts will<br>
then work everywhere. Scripts with <a class="Type" href="options.html#'fileformat'">'fileformat'</a> set to "dos" do not work on<br>
Unix. Also see <a class="Identifier" href="repeat.html#:source_crnl">:source_crnl</a>. To be sure it is set right, do this before<br>
writing the file:<br>
<br>
<div class="helpExample"> :set fileformat=unix</div>
<br>
<br>
<span class="Statement">DOCUMENTATION </span><a class="Constant" href="usr_41.html#write-local-help" name="write-local-help">write-local-help</a><br>
<br>
It's a good idea to also write some documentation for your plugin. Especially<br>
when its behavior can be changed by the user. See <a class="Identifier" href="usr_05.html#add-local-help">add-local-help</a> for how<br>
they are installed.<br>
<br>
Here is a simple example for a plugin help file, called "typecorr.txt":<br>
<br>
<div class="helpExample"> 1 *typecorr.txt* Plugin for correcting typing mistakes<br>
2<br>
3 If you make typing mistakes, this plugin will have them corrected<br>
4 automatically.<br>
5<br>
6 There are currently only a few corrections. Add your own if you like.<br>
7<br>
8 Mappings:<br>
9 <Leader>a or <Plug>TypecorrAdd<br>
10 Add a correction for the word under the cursor.<br>
11<br>
12 Commands:<br>
13 :Correct {word}<br>
14 Add a correction for {word}.<br>
15<br>
16 *typecorr-settings*<br>
17 This plugin doesn't have any settings.</div>
<br>
The first line is actually the only one for which the format matters. It will<br>
be extracted from the help file to be put in the "LOCAL ADDITIONS:" section of<br>
help.txt <a class="Identifier" href="index.html#local-additions">local-additions</a>. The first "*" must be in the first column of the<br>
first line. After adding your help file do ":help" and check that the entries<br>
line up nicely.<br>
<br>
You can add more tags inside ** in your help file. But be careful not to use<br>
existing help tags. You would probably use the name of your plugin in most of<br>
them, like "typecorr-settings" in the example.<br>
<br>
Using references to other parts of the help in || is recommended. This makes<br>
it easy for the user to find associated help.<br>
<br>
<br>
<span class="Statement">FILETYPE DETECTION </span><a class="Constant" href="usr_41.html#plugin-filetype" name="plugin-filetype">plugin-filetype</a><br>
<br>
If your filetype is not already detected by Vim, you should create a filetype<br>
detection snippet in a separate file. It is usually in the form of an<br>
autocommand that sets the filetype when the file name matches a pattern.<br>
Example:<br>
<br>
<div class="helpExample"> au BufNewFile,BufRead *.foo set filetype=foofoo</div>
<br>
Write this single-line file as "ftdetect/foofoo.vim" in the first directory<br>
that appears in <a class="Type" href="options.html#'runtimepath'">'runtimepath'</a>. For Unix that would be<br>
"~/.vim/ftdetect/foofoo.vim". The convention is to use the name of the<br>
filetype for the script name.<br>
<br>
You can make more complicated checks if you like, for example to inspect the<br>
contents of the file to recognize the language. Also see <a class="Identifier" href="filetype.html#new-filetype">new-filetype</a>.<br>
<br>
<br>
<span class="Statement">SUMMARY </span><a class="Constant" href="usr_41.html#plugin-special" name="plugin-special">plugin-special</a><br>
<br>
Summary of special things to use in a plugin:<br>
<br>
s:name Variables local to the script.<br>
<br>
<span class="Special"><SID></span> Script-ID, used for mappings and functions local to<br>
the script.<br>
<br>
hasmapto() Function to test if the user already defined a mapping<br>
for functionality the script offers.<br>
<br>
<span class="Special"><Leader></span> Value of "mapleader", which the user defines as the<br>
keys that plugin mappings start with.<br>
<br>
:map <span class="Special"><unique></span> Give a warning if a mapping already exists.<br>
<br>
:noremap <span class="Special"><script></span> Use only mappings local to the script, not global<br>
mappings.<br>
<br>
exists(":Cmd") Check if a user command already exists.<br>
<br>
<span class="PreProc">==============================================================================</span><br>
<a class="Constant" href="usr_41.html#41.12" name="41.12">41.12</a> Writing a filetype plugin <a class="Constant" href="usr_41.html#write-filetype-plugin" name="write-filetype-plugin">write-filetype-plugin</a> <a class="Constant" href="usr_41.html#ftplugin" name="ftplugin">ftplugin</a><br>
<br>
A filetype plugin is like a global plugin, except that it sets options and<br>
defines mappings for the current buffer only. See <a class="Identifier" href="usr_05.html#add-filetype-plugin">add-filetype-plugin</a> for<br>
how this type of plugin is used.<br>
<br>
First read the section on global plugins above <a class="Identifier" href="usr_41.html#41.11">41.11</a>. All that is said there<br>
also applies to filetype plugins. There are a few extras, which are explained<br>
here. The essential thing is that a filetype plugin should only have an<br>
effect on the current buffer.<br>
<br>
<br>
DISABLING<br>
<br>
If you are writing a filetype plugin to be used by many people, they need a<br>
chance to disable loading it. Put this at the top of the plugin:<br>
<br>
<div class="helpExample"> " Only do this when not done yet for this buffer<br>
if exists("b:did_ftplugin")<br>
finish<br>
endif<br>
let b:did_ftplugin = 1</div>
<br>
This also needs to be used to avoid that the same plugin is executed twice for<br>
the same buffer (happens when using an ":edit" command without arguments).<br>
<br>
Now users can disable loading the default plugin completely by making a<br>
filetype plugin with only this line:<br>
<br>
<div class="helpExample"> let b:did_ftplugin = 1</div>
<br>
This does require that the filetype plugin directory comes before $VIMRUNTIME<br>
in <a class="Type" href="options.html#'runtimepath'">'runtimepath'</a>!<br>
<br>
If you do want to use the default plugin, but overrule one of the settings,<br>
you can write the different setting in a script:<br>
<br>
<div class="helpExample"> setlocal textwidth=70</div>
<br>
Now write this in the "after" directory, so that it gets sourced after the<br>
distributed "vim.vim" ftplugin <a class="Identifier" href="options.html#after-directory">after-directory</a>. For Unix this would be<br>
"~/.vim/after/ftplugin/vim.vim". <span class="Todo">Note</span> that the default plugin will have set<br>
"b:did_ftplugin", but it is ignored here.<br>
<br>
<br>
OPTIONS<br>
<br>
To make sure the filetype plugin only affects the current buffer use the<br>
<br>
<div class="helpExample"> :setlocal</div>
<br>
command to set options. And only set options which are local to a buffer (see<br>
the help for the option to check that). When using <a class="Identifier" href="options.html#:setlocal">:setlocal</a> for global<br>
options or options local to a window, the value will change for many buffers,<br>
and that is not what a filetype plugin should do.<br>
<br>
When an option has a value that is a list of flags or items, consider using<br>
"+=" and "-=" to keep the existing value. Be aware that the user may have<br>
changed an option value already. First resetting to the default value and<br>
then changing it is often a good idea. Example:<br>
<br>
<div class="helpExample"> :setlocal formatoptions& formatoptions+=ro</div>
<br>
<br>
MAPPINGS<br>
<br>
To make sure mappings will only work in the current buffer use the<br>
<br>
<div class="helpExample"> :map <buffer></div>
<br>
command. This needs to be combined with the two-step mapping explained above.<br>
An example of how to define functionality in a filetype plugin:<br>
<br>
<div class="helpExample"> if !hasmapto('<Plug>JavaImport')<br>
map <buffer> <unique> <LocalLeader>i <Plug>JavaImport<br>
endif<br>
noremap <buffer> <unique> <Plug>JavaImport oimport ""<Left><Esc></div>
<br>
<a class="Identifier" href="eval.html#hasmapto()">hasmapto()</a> is used to check if the user has already defined a map to<br>
<span class="Special"><Plug></span>JavaImport. If not, then the filetype plugin defines the default<br>
mapping. This starts with <a class="Identifier" href="map.html#<LocalLeader>"><LocalLeader></a>, which allows the user to select<br>
the key(s) he wants filetype plugin mappings to start with. The default is a<br>
backslash.<br>
"<span class="Special"><unique></span>" is used to give an error message if the mapping already exists or<br>
overlaps with an existing mapping.<br>
<a class="Identifier" href="map.html#:noremap">:noremap</a> is used to avoid that any other mappings that the user has defined<br>
interferes. You might want to use ":noremap <span class="Special"><script></span>" to allow remapping<br>
mappings defined in this script that start with <span class="Special"><SID></span>.<br>
<br>
The user must have a chance to disable the mappings in a filetype plugin,<br>
without disabling everything. Here is an example of how this is done for a<br>
plugin for the mail filetype:<br>
<br>
<div class="helpExample"> " Add mappings, unless the user didn't want this.<br>
if !exists("no_plugin_maps") && !exists("no_mail_maps")<br>
" Quote text by inserting "> "<br>
if !hasmapto('<Plug>MailQuote')<br>
vmap <buffer> <LocalLeader>q <Plug>MailQuote<br>
nmap <buffer> <LocalLeader>q <Plug>MailQuote<br>
endif<br>
vnoremap <buffer> <Plug>MailQuote :s/^/> /<CR><br>
nnoremap <buffer> <Plug>MailQuote :.,$s/^/> /<CR><br>
endif</div>
<br>
Two global variables are used:<br>
<a class="Identifier" href="filetype.html#no_plugin_maps">no_plugin_maps</a> disables mappings for all filetype plugins<br>
<a class="Identifier" href="filetype.html#no_mail_maps">no_mail_maps</a> disables mappings for the "mail" filetype<br>
<br>
<br>
USER COMMANDS<br>
<br>
To add a user command for a specific file type, so that it can only be used in<br>
one buffer, use the "-buffer" argument to <a class="Identifier" href="map.html#:command">:command</a>. Example:<br>
<br>
<div class="helpExample"> :command -buffer Make make %:r.s</div>
<br>
<br>
VARIABLES<br>
<br>
A filetype plugin will be sourced for each buffer of the type it's for. Local<br>
script variables <a class="Identifier" href="eval.html#s:var">s:var</a> will be shared between all invocations. Use local<br>
buffer variables <a class="Identifier" href="eval.html#b:var">b:var</a> if you want a variable specifically for one buffer.<br>
<br>
<br>
FUNCTIONS<br>
<br>
When defining a function, this only needs to be done once. But the filetype<br>
plugin will be sourced every time a file with this filetype will be opened.<br>
This construct makes sure the function is only defined once:<br>
<br>
<div class="helpExample"> :if !exists("*s:Func")<br>
: function s:Func(arg)<br>
: ...<br>
: endfunction<br>
:endif</div>
<br>
<br>
<span class="Statement">UNDO </span><a class="Constant" href="usr_41.html#undo_indent" name="undo_indent">undo_indent</a> <a class="Constant" href="usr_41.html#undo_ftplugin" name="undo_ftplugin">undo_ftplugin</a><br>
<br>
When the user does ":setfiletype xyz" the effect of the previous filetype<br>
should be undone. Set the b:undo_ftplugin variable to the commands that will<br>
undo the settings in your filetype plugin. Example:<br>
<br>
<div class="helpExample"> let b:undo_ftplugin = "setlocal fo< com< tw< commentstring<"<br>
\ . "| unlet b:match_ignorecase b:match_words b:match_skip"</div>
<br>
Using ":setlocal" with "<" after the option name resets the option to its<br>
global value. That is mostly the best way to reset the option value.<br>
<br>
This does require removing the "C" flag from <a class="Type" href="options.html#'cpoptions'">'cpoptions'</a> to allow line<br>
continuation, as mentioned above <a class="Identifier" href="usr_41.html#use-cpo-save">use-cpo-save</a>.<br>
<br>
For undoing the effect of an indent script, the b:undo_indent variable should<br>
be set accordingly.<br>
<br>
<br>
FILE NAME<br>
<br>
The filetype must be included in the file name <a class="Identifier" href="usr_05.html#ftplugin-name">ftplugin-name</a>. Use one of<br>
these three forms:<br>
<br>
.../ftplugin/stuff.vim<br>
.../ftplugin/stuff_foo.vim<br>
.../ftplugin/stuff/bar.vim<br>
<br>
"stuff" is the filetype, "foo" and "bar" are arbitrary names.<br>
<br>
<br>
<span class="Statement">SUMMARY </span><a class="Constant" href="usr_41.html#ftplugin-special" name="ftplugin-special">ftplugin-special</a><br>
<br>
Summary of special things to use in a filetype plugin:<br>
<br>
<span class="Special"><LocalLeader></span> Value of "maplocalleader", which the user defines as<br>
the keys that filetype plugin mappings start with.<br>
<br>
:map <span class="Special"><buffer></span> Define a mapping local to the buffer.<br>
<br>
:noremap <span class="Special"><script></span> Only remap mappings defined in this script that start<br>
with <span class="Special"><SID></span>.<br>
<br>
:setlocal Set an option for the current buffer only.<br>
<br>
:command -buffer Define a user command local to the buffer.<br>
<br>
exists("*s:Func") Check if a function was already defined.<br>
<br>
Also see <a class="Identifier" href="usr_41.html#plugin-special">plugin-special</a>, the special things used for all plugins.<br>
<br>
<span class="PreProc">==============================================================================</span><br>
<a class="Constant" href="usr_41.html#41.13" name="41.13">41.13</a> Writing a compiler plugin <a class="Constant" href="usr_41.html#write-compiler-plugin" name="write-compiler-plugin">write-compiler-plugin</a><br>
<br>
A compiler plugin sets options for use with a specific compiler. The user can<br>
load it with the <a class="Identifier" href="quickfix.html#:compiler">:compiler</a> command. The main use is to set the<br>
<a class="Type" href="options.html#'errorformat'">'errorformat'</a> and <a class="Type" href="options.html#'makeprg'">'makeprg'</a> options.<br>
<br>
Easiest is to have a look at examples. This command will edit all the default<br>
compiler plugins:<br>
<br>
<div class="helpExample"> :next $VIMRUNTIME/compiler/*.vim</div>
<br>
Use <a class="Identifier" href="editing.html#:next">:next</a> to go to the next plugin file.<br>
<br>
There are two special items about these files. First is a mechanism to allow<br>
a user to overrule or add to the default file. The default files start with:<br>
<br>
<div class="helpExample"> :if exists("current_compiler")<br>
: finish<br>
:endif<br>
:let current_compiler = "mine"</div>
<br>
When you write a compiler file and put it in your personal runtime directory<br>
(e.g., ~/.vim/compiler for Unix), you set the "current_compiler" variable to<br>
make the default file skip the settings.<br>
<a class="Constant" href="usr_41.html#:CompilerSet" name=":CompilerSet">:CompilerSet</a><br>
The second mechanism is to use ":set" for ":compiler!" and ":setlocal" for<br>
":compiler". Vim defines the ":CompilerSet" user command for this. However,<br>
older Vim versions don't, thus your plugin should define it then. This is an<br>
example:<br>
<br>
<div class="helpExample"> if exists(":CompilerSet") != 2<br>
command -nargs=* CompilerSet setlocal <args><br>
endif<br>
CompilerSet errorformat& " use the default 'errorformat'<br>
CompilerSet makeprg=nmake</div>
<br>
When you write a compiler plugin for the Vim distribution or for a system-wide<br>
runtime directory, use the mechanism mentioned above. When<br>
"current_compiler" was already set by a user plugin nothing will be done.<br>
<br>
When you write a compiler plugin to overrule settings from a default plugin,<br>
don't check "current_compiler". This plugin is supposed to be loaded<br>
last, thus it should be in a directory at the end of <a class="Type" href="options.html#'runtimepath'">'runtimepath'</a>. For Unix<br>
that could be ~/.vim/after/compiler.<br>
<br>
<span class="PreProc">==============================================================================</span><br>
<a class="Constant" href="usr_41.html#41.14" name="41.14">41.14</a> Writing a plugin that loads quickly <a class="Constant" href="usr_41.html#write-plugin-quickload" name="write-plugin-quickload">write-plugin-quickload</a><br>
<br>
A plugin may grow and become quite long. The startup delay may become<br>
noticeable, while you hardly ever use the plugin. Then it's time for a<br>
quickload plugin.<br>
<br>
The basic idea is that the plugin is loaded twice. The first time user<br>
commands and mappings are defined that offer the functionality. The second<br>
time the functions that implement the functionality are defined.<br>
<br>
It may sound surprising that quickload means loading a script twice. What we<br>
mean is that it loads quickly the first time, postponing the bulk of the<br>
script to the second time, which only happens when you actually use it. When<br>
you always use the functionality it actually gets slower!<br>
<br>
<span class="Todo">Note</span> that since Vim 7 there is an alternative: use the <a class="Identifier" href="eval.html#autoload">autoload</a><br>
functionality <a class="Identifier" href="usr_41.html#41.15">41.15</a>.<br>
<br>
The following example shows how it's done:<br>
<br>
<div class="helpExample"> " Vim global plugin for demonstrating quick loading<br>
" Last Change: 2005 Feb 25<br>
" Maintainer: Bram Moolenaar <Bram@vim.org><br>
" License: This file is placed in the public domain.</div>
<br>
<div class="helpExample"> if !exists("s:did_load")<br>
command -nargs=* BNRead call BufNetRead(<f-args>)<br>
map <F19> :call BufNetWrite('something')<CR></div>
<br>
<div class="helpExample"> let s:did_load = 1<br>
exe 'au FuncUndefined BufNet* source ' . expand('<sfile>')<br>
finish<br>
endif</div>
<br>
<div class="helpExample"> function BufNetRead(...)<br>
echo 'BufNetRead(' . string(a:000) . ')'<br>
" read functionality here<br>
endfunction</div>
<br>
<div class="helpExample"> function BufNetWrite(...)<br>
echo 'BufNetWrite(' . string(a:000) . ')'<br>
" write functionality here<br>
endfunction</div>
<br>
When the script is first loaded "s:did_load" is not set. The commands between<br>
the "if" and "endif" will be executed. This ends in a <a class="Identifier" href="repeat.html#:finish">:finish</a> command, thus<br>
the rest of the script is not executed.<br>
<br>
The second time the script is loaded "s:did_load" exists and the commands<br>
after the "endif" are executed. This defines the (possible long)<br>
BufNetRead() and BufNetWrite() functions.<br>
<br>
If you drop this script in your plugin directory Vim will execute it on<br>
startup. This is the sequence of events that happens:<br>
<br>
1. The "BNRead" command is defined and the <span class="Special"><F19></span> key is mapped when the script<br>
is sourced at startup. A <a class="Identifier" href="autocmd.html#FuncUndefined">FuncUndefined</a> autocommand is defined. The<br>
":finish" command causes the script to terminate early.<br>
<br>
2. The user types the BNRead command or presses the <span class="Special"><F19></span> key. The<br>
BufNetRead() or BufNetWrite() function will be called.<br>
<br>
3. Vim can't find the function and triggers the <a class="Identifier" href="autocmd.html#FuncUndefined">FuncUndefined</a> autocommand<br>
event. Since the pattern "BufNet*" matches the invoked function, the<br>
command "source fname" will be executed. "fname" will be equal to the name<br>
of the script, no matter where it is located, because it comes from<br>
expanding "<span class="Special"><sfile></span>" (see <a class="Identifier" href="eval.html#expand()">expand()</a>).<br>
<br>
4. The script is sourced again, the "s:did_load" variable exists and the<br>
functions are defined.<br>
<br>
Notice that the functions that are loaded afterwards match the pattern in the<br>
<a class="Identifier" href="autocmd.html#FuncUndefined">FuncUndefined</a> autocommand. You must make sure that no other plugin defines<br>
functions that match this pattern.<br>
<br>
<span class="PreProc">==============================================================================</span><br>
<a class="Constant" href="usr_41.html#41.15" name="41.15">41.15</a> Writing library scripts <a class="Constant" href="usr_41.html#write-library-script" name="write-library-script">write-library-script</a><br>
<br>
Some functionality will be required in several places. When this becomes more<br>
than a few lines you will want to put it in one script and use it from many<br>
scripts. We will call that one script a library script.<br>
<br>
Manually loading a library script is possible, so long as you avoid loading it<br>
when it's already done. You can do this with the <a class="Identifier" href="eval.html#exists()">exists()</a> function.<br>
Example:<br>
<br>
<div class="helpExample"> if !exists('*MyLibFunction')<br>
runtime library/mylibscript.vim<br>
endif<br>
call MyLibFunction(arg)</div>
<br>
Here you need to know that MyLibFunction() is defined in a script<br>
"library/mylibscript.vim" in one of the directories in <a class="Type" href="options.html#'runtimepath'">'runtimepath'</a>.<br>
<br>
To make this a bit simpler Vim offers the autoload mechanism. Then the<br>
example looks like this:<br>
<br>
<div class="helpExample"> call mylib#myfunction(arg)</div>
<br>
That's a lot simpler, isn't it? Vim will recognize the function name and when<br>
it's not defined search for the script "autoload/mylib.vim" in <a class="Type" href="options.html#'runtimepath'">'runtimepath'</a>.<br>
That script must define the "mylib#myfunction()" function.<br>
<br>
You can put many other functions in the mylib.vim script, you are free to<br>
organize your functions in library scripts. But you must use function names<br>
where the part before the '#' matches the script name. Otherwise Vim would<br>
not know what script to load.<br>
<br>
If you get really enthusiastic and write lots of library scripts, you may<br>
want to use subdirectories. Example:<br>
<br>
<div class="helpExample"> call netlib#ftp#read('somefile')</div>
<br>
For Unix the library script used for this could be:<br>
<br>
~/.vim/autoload/netlib/ftp.vim<br>
<br>
Where the function is defined like this:<br>
<br>
<div class="helpExample"> function netlib#ftp#read(fname)<br>
" Read the file fname through ftp<br>
endfunction</div>
<br>
Notice that the name the function is defined with is exactly the same as the<br>
name used for calling the function. And the part before the last '#'<br>
exactly matches the subdirectory and script name.<br>
<br>
You can use the same mechanism for variables:<br>
<br>
<div class="helpExample"> let weekdays = dutch#weekdays</div>
<br>
This will load the script "autoload/dutch.vim", which should contain something<br>
like:<br>
<br>
<div class="helpExample"> let dutch#weekdays = ['zondag', 'maandag', 'dinsdag', 'woensdag',<br>
\ 'donderdag', 'vrijdag', 'zaterdag']</div>
<br>
Further reading: <a class="Identifier" href="eval.html#autoload">autoload</a>.<br>
<br>
<span class="PreProc">==============================================================================</span><br>
<a class="Constant" href="usr_41.html#41.16" name="41.16">41.16</a> Distributing Vim scripts <a class="Constant" href="usr_41.html#distribute-script" name="distribute-script">distribute-script</a><br>
<br>
Vim users will look for scripts on the Vim website: <span class="Constant"><a href="http://www.vim.org">http://www.vim.org</a></span>.<br>
If you made something that is useful for others, share it!<br>
<br>
Vim scripts can be used on any system. There might not be a tar or gzip<br>
command. If you want to pack files together and/or compress them the "zip"<br>
utility is recommended.<br>
<br>
For utmost portability use Vim itself to pack scripts together. This can be<br>
done with the Vimball utility. See <a class="Identifier" href="pi_vimball.html#vimball">vimball</a>.<br>
<br>
It's good if you add a line to allow automatic updating. See <a class="Identifier" href="pi_getscript.html#glvs-plugins">glvs-plugins</a>.<br>
<br>
<span class="PreProc">==============================================================================</span><br>
<br>
Next chapter: <a class="Identifier" href="usr_42.html">usr_42.txt</a> Add new menus<br>
<br>
Copyright: see <a class="Identifier" href="usr_01.html#manual-copyright">manual-copyright</a> vim:tw=78:ts=8:ft=help:norl:<br>
</div>
</article>
<footer>
<a href="#top">Return to the top</a> - <a href="index.html">Return to main</a>
<span class="EnglishJapaneseLink">
<span class="CurrentLanguage">English</span>
</span>
<br />
<div style="text-align:right;">
Hosted by <a href="https://github.com/vim-jp/vimdoc-en">vimdoc-en project</a><br />
If you met any problem, please report it to <a href="https://github.com/vim-jp/vimdoc-en/issues">issue</a>.<br />
</div>
</footer>
<!--<script src="js/check-referrer.js" type="text/javascript"></script>-->
</body>
</html>
<!-- vim:set ts=8 sts=2 sw=2 tw=0 et: -->
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。