Revision 1.1
Nate SoaresThis is the in-depth vimscript guide. If you're just a casual user looking to write a plugin, the abbreviated style guide is for you.
This rather rotund guide dives into justifications and clarifications. It provides an idealized set of rules that are rather too draconian to push on casual scripters.
It's for users who want to know why certain decisions were made in the abbreviated guide and who want to learn a thing or two about using vimscript safely.
Fair warning: Vimscript is a maddening abyss. When you gaze into it, it gazes also into you. Proceed with caution.
Vim is highly configurable. Users can change many of the default settings, including the case sensitivity, the regular expression rules, the substitution rules, and more. In order for your vimscript to work for all users, follow these guidelines:
\m,
\v, \M, or \V (prefer
tersity)
., *, and {.
magic setting you must prefix it
with one of the magic control atoms. This future-proofs your
regular expression against other devs modifying it and forgetting
to add the control atom.
:s[ubstitute] in scripts.
:substitute moves the cursor.
:substitute outputs an error message when the match
does not exist.
g flag depends upon the
gdefault setting. If you do use
:substitute you must save gdefault, set
it to 0 or 1, perform the substitution,
and then restore it.
maktaba#buffer#Replace.
=~# and
=~?, never =~).
!~ == != > >= < and
<=
== and
>= are fine for numbers, but ==# and
>=# must be used for strings.
=~ and friends is dependant upon the
ignorecase setting.
ignorecase setting. Be prepared to justify
your reasoning.
\c or \C.
=~#, etc.).
ignorecase
setting.
ignorecase setting. Be prepared to justify
your reasoning.
normal! instead of normal.
! the command will use the user's
key mappings and you have literally no idea what your macro will
do.
noremap family of commands.
map command respects the users existing
mappings and could do anything.
catch, match the error code rather than the
error text.
:help error-messages.
In general, guard all commands and functions against user settings.
maktaba#error codes found in
maktaba.
:help error-messages.
maktaba#error#Message.
0 == 'foo' evaluates to true.
is# operator.
Otherwise, prefer maktaba#value#IsEqual or check
type() explicitly.
maktaba#ensure, or check
maktaba#value or type() and throw your own
errors.
:unlet for variables that may change types,
particularly those assigned inside loops.
maktaba#function instead to create and
manipulate handles to functions.
self parameter which access
the dict state.
All other language features are fair game.
maktaba.
plugin-names-like-this
autoload/ subdirectory of
your plugin.
plugin/ or instant/ directory
should begin with the boilerplate
instant/flags.vim.
call s:plugin.Flag('FLAGNAME', DEFAULT_VALUE).
:Glaive
command (see glaive).
plugin/ or the
ftplugin/ subdirectories.
plugin/commands.vim
or ftplugin/ files.
plugin/autocmds.vim,
inside an augroup.
plugin/mappings.vim and
will be disabled unless explicitly enabled by users.
plugin/settings.vim or
instant/settings.vim.
after/ subdirectory.
after/ should be reserved for the user.
after/.
Many plugins provide either user functionality (commands, autocommands, etc) or an API (of autoloaded functions) but not both. This separation is encouraged, as it allows other plugins to pull in a library without also pulling in commands, setting changes, and other plugin functionality that affects the end user.
:Glaive command.
Follow google-wide style conventions. Mimic google python style when in doubt.
Provide help files generated by vimdoc. Write documentation in .vim files in conformance with the vimdoc standards and include fields like "description" and "author" in the addon-info.json file (see the VAM documentation).
" before the comment text.
plugin-names-like-this,
FunctionNamesLikeThis,
CommandNamesLikeThis,
augroup_names_like_this,
variable_names_like_this.
Prefix all variables with their scope.
variable_names_like_this
g:
autoload directories.
s:
a:
l:
l: disambiguates between function-local and
vim-predefined variables. For example, count
refers to
v:count, not l:count.
v:
b:
Prefer single quoted strings. Specifically, in order of precedence:
'\s*' is not the same as "\s*"
'example ('')' represents the
string
example (')
\n,
\t, etc.) use double quotes.
'\n' in a regex does not represent a
newline, but rather "\n". You only need to use double quotes
when you want to embed the represented character itself (e.g. a
newline) in the string.
tabstop
over
ts).
setlocal and &l: instead of
set and &.
Vim plugins should provide any or all of the following: Commands, Autocommands, Functions, Statusline Flags, and Mappings.
plugin/commands.vim.[!]CommandNamesLikeThis
command without a bang.
<bang>,
<register>, etc.) before argument parameters
(<f-args>, etc.).
instant/commands.vim file in plugins using
maktaba, or explicitly installed via an autoload function in
non-maktaba plugins.
<bang> to functions with
'<bang>' == '!'.
plugin/autocmds.vim.plugin/autocmds.vim file.
Glaive myplugin !plugin[autocmds].
augroup block.
autocmd!.
augroup, the
augroup name should be the same as your plugin
name, with underscores in place of any hyphens.
augroup names should start with your
plugin name followed by an underscore.
augroup, clear it with
autocmd!
s:[!].[abort].FunctionNamesLikeThis
s:
abort.
try..endtry block
somewhere on the stack.
abort keyword forces the function to act
consistently.
function! with a bang.
autoload directory.
... for optional arguments, not for lists of
arguments.
... for a list of arguments.
plugin/mappings.vim.
<Plug> mappings can be defined in
plugin/plugs.vim (unlike mappings.vim, plugs.vim is
opt-out).
plugin/mappings.vim, using
maktaba#plugin#MapPrefix to get a prefix.
plugin/mappings.vim
file will be disabled by default (by the standard
maktaba#plugin#Enter() boilerplate).
Glaive myplugin plugin[mappings].
<unique>.
<Plug> and
your plugin's name in plugin/plugs.vim (separate from
standard key mappings).
<Plug> is a sequence which can not be typed.
noremap <Plug>namespace#MappingName
some_key_sequence
and then users can do
noremap <leader>x
<Plug>namespace#MappingName
to take advantage of your pseudo-mapping.
plugin/mappings.vim or they will be disabled by
default.
<Plug>
followed by your plugin name, a pound sign, and a unique mapping
name (CamelCased like a function).
noremap family of commands. Never use
the map family.
map depends upon the user's existing mappings, and
could do anything.
noremap for commands that both make a motion
and take a range.
noremap makes mappings in normal, visual, and
operator-pending modes.
nnoremap
onoremap or vnoremap explicitly.
<SID> in place of s: when
accessing script locals in mappings.
s: will often fail as the mapping attempts to
type a literal s and colon.
maktaba.
Declaring dependencies in addon-info.json allows conformant plugin managers (like VAM) to ensure dependencies are installed. See the VAM documentation for details.
Calling maktaba#library#Require from dependent code at
runtime ensures that dependencies have been installed and that they
don't include unsafe non-library files.
<plugin-name>#status#Status() or its
finer-grained variants to provide statusline flags.
Following is a convention for exposing statusline flags to the user. A plugin should never modify the user's statusline except for when that is the only purpose of the plugin (powerline, etc.).
Info,
Alert,
Warning, and
Error functions under the
<plugin-name>#status namespace.
Info should provide information about the
state of the buffer.
Alert should provide a quiet reminder
that the buffer is non-standard.
Warning should provide a warning about
the current state of the buffer.
Error should bring to attention a loud
issue with the buffer.
[Google]. For example:
[$] if
the file contains trailing whitespace
[write] if vim
is in writing mode.
<plugin-name>#status#Status function.
Error,
Warning, Alert, or Info.
These are commands which can only be used by a limited number of plugins, and should not in general be used by yours.
:match :2match or :3match
matchadd() to create a matchlevel unique to your
plugin.
echoerr.
echoerr does not print the red error message that you
might think it does.
echoerr prints an error message as well as context
about the code where echoerr was called.
echoerr is best suited for debugging.
echohl in tandem with echomsg if
you want the red error bar.
echomsg instead of echo.
echomsg messages can be reviewed with the
:messages command.
echo messages disappear permanently on redraw, which
can be very annoying to users who failed to read the message in
time.
Lay out plugin/ files in the following sections, if
applicable, separated by two blank lines:
commands.vim file,
autocommands in autocmds.vim file, etc.)
Lay out autoload/ files in the following sections, if
applicable, separated by two blank lines:
maktaba#library#Require calls
This is recommended convention and is not enforced.
Use the following shortcuts:
catch over catch /.*/
return over return 0 when the return value
has no semantic purpose.
This section plumbs some of the darker corners of vimscript, explaining the language pathologies that you wish you didn't have to know.
When compatible is set, many vim features are not
available. The vim feature which most commonly affects vimscript
authors is line continuations.
If you want your plugin to work in vim with vi compatibility on, you
will need to save the compatibility options at the beginning of each
plugin file, clear them, and restore them at the end of each plugin
file. See :help use-cpo-save for details.
Plugins that depend on maktaba generally don't need to worry about compatible mode since maktaba currently just disables it, printing a warning.
Revision 1.1
Nate Soares