From 4882d60145a157f586722c0ca21f8d72e89e8aae Mon Sep 17 00:00:00 2001
From: "dbarnett@google.com"
+
+ Revision 1.1
+
+ This 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:
+
+ In general, guard all commands and functions against user settings.
+
+ All other language features are fair game.
+
+ 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.
+
+ 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).
+
+
+ Prefix all variables with their scope.
+
+ Prefer single quoted strings. Specifically, in order of precedence:
+
+ Vim plugins should provide any or all of the following:
+ Commands, Autocommands,
+ Functions, Statusline Flags, and
+ Mappings.
+
+ Declaring dependencies in addon-info.json allows conformant plugin
+ managers (like VAM) to ensure dependencies are installed. See the
+ VAM documentation for details.
+
+ Calling
+ 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.).
+
+ These are commands which can only be used by a limited number of
+ plugins, and should not in general be used by yours.
+
+ Lay out
+ Lay out
+ This is recommended convention and is not enforced.
+
+ Use the following shortcuts:
+
+ This section plumbs some of the darker corners of vimscript, explaining
+ the language pathologies that you wish you didn't have to know.
+
+
+ When
+ 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
+ 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
+
+
+ Revision 1.1
+
+ This is a casual version of the vimscript style guide, because
+ vimscript is a casual language. When submitting vim plugin code, you
+ must adhere to these rules. For clarifications, justifications, and
+ explanations about the finer points of vimscript, please refer to the
+ heavy guide.
+
+ It's hard to get vimscript right. Many commands depend upon the user's
+ settings. By following these guidelines, you can hope to make your
+ scripts portable.
+
+ Double quoted strings are semantically different in vimscript, and
+ you probably don't want them (they break regexes).
+
+ Use double quoted strings when you need an escape sequence (such as
+
+ The matching behavior depends upon the user's ignorecase and smartcase
+ settings and on whether you compare them with the
+ In addition to the case sensitivity settings, regex behavior depends
+ upon the user's nomagic setting. To make regexes act like nomagic and
+ noignorecase are set, prepend all regexes with
+ You are welcome to use other magic levels (
+ Avoid using
+ For many vim commands, functions exist that do the same thing with
+ fewer side effects. See
+ Always use
+ Avoid
+ The same applies to other commands not listed here.
+ Error text may be locale dependant.
+ Loud scripts are annoying. Message the user only when:
+
+ Joshua Hoak
+ David Barnett
+
+
+
+
+ \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
.
+
+
+
+
+
+
+
+
+
+ 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.
+
+
+
+
+
+ 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/
.
+
+
+
+ :Glaive
command.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "
before the comment text.
+
+
+
+
+
+
+ plugin-names-like-this
,
+ FunctionNamesLikeThis
,
+ CommandNamesLikeThis
,
+ augroup_names_like_this
,
+ variable_names_like_this
.
+
+
+
+ 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:
+
+
+
+
+
+
+
+ '\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 &
.
+
+
+ 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
.
+ 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.
+
+
+
+ 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
.
+
+
+ :match :2match
or :3match
+
+
+ addmatch()
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.
+ plugin/
files in the following sections, if
+ applicable, separated by two blank lines:
+
+
+ commands.vim
file,
+ autocommands in autocmds.vim
file, etc.)
+ autoload/
files in the following sections, if
+ applicable, separated by two blank lines:
+
+
+ maktaba#library#Require
calls
+
+
+
+ catch
over catch /.*/
+ return
over return 0
when the return value
+ has no semantic purpose.
+ compatible
is set, many vim features are not
+ available. The vim feature which most commonly affects vimscript
+ authors is line continuations.
+ :help use-cpo-save
for details.
+
+ Joshua Hoak
+ David Barnett
+
+
+ Joshua Hoak
+ David Barnett
+
+
+ "\n"
) or if you know it doesn't matter and you need to
+ embed single quotes.
+ =~#
or =~?
operator families over the
+ =~
family.
+ =~
,
+ =~#
, or =~?
family of operators. Use the
+ =~#
and =~?
operator families explicitly
+ when comparing strings unless you explicitly need to honor the user's
+ case sensitivity settings.
+ \m\C
.\m\C
.
+ \v
) and case
+ sensitivities (\c
) so long as they are intentional and
+ explicit.
+ :s[ubstitute]
as it moves the cursor and
+ prints error messages. Prefer functions (such as
+ search()
) better suited to scripts.
+ :help functions()
for a list of
+ built-in functions.
+ normal!
instead of normal
. The
+ latter depends upon the user's key mappings and could do anything.
+ :s[ubstitute]
, as its behavior depends upon a
+ number of local settings.
+
+
+
+ Vimscript has unsafe, unintuitive behavior when dealing with some
+ types. For instance, 0 == 'foo'
evaluates to true.
+
+ Use strict comparison operators where possible. When comparing against
+ a string literal, use the is#
operator. Otherwise, prefer
+ maktaba#value#IsEqual
or check type()
+ explicitly.
+
+ Check variable types explicitly before using them. Use functions from
+ maktaba#ensure
, or check maktaba#value
or
+ type()
and throw your own errors.
+
+ Use :unlet
for variables that may change types,
+ particularly those assigned inside loops.
+
+ Use python only when it provides critical functionality, for example + when writing threaded code. +
+ ++ Avoid using other scripting languages such as ruby and lua. We can + not guarantee that the end user's vim has been compiled with support + for non-vimscript languages. +
+ ++ maktaba removes boilerplate, including: +
+ Group your functionality as a plugin, unified in one directory (or + code repository) which shares your plugin's name (with a "vim-" prefix + or ".vim" suffix if desired). It should be split into plugin/, + autoload/, etc. subdirectories as necessary, and it should declare + metadata in the addon-info.json format (see the + VAM documentation for details). +
+ +[!]
and
+ [abort]
.
+ + Autoloading allows functions to be loaded on demand, which makes + startuptime faster and enforces function namespacing. +
++ Script-local functions are welcome, but should also live in autoload/ + and be called by autoloaded functions. +
++ Non-library plugins should expose commands instead of functions. + Command logic should be extracted into functions and autoloaded. +
+
+ [!]
allows developers to reload their functions
+ without complaint.
+
+ [abort]
forces the function to halt when it encounters
+ an error.
+
[!]
.
+
+ General commands go in plugin/commands.vim
.
+ Filetype-specific commands go in ftplugin/
.
+
+ Excluding [!]
prevents your plugin from silently
+ clobbering existing commands. Command conflicts should be resolved by
+ the user.
+
+ Place all autocommands in augroups. +
++ The augroup name should be unique. It should either be, or be prefixed + with, the plugin name. +
+
+ Clear the augroup with autocmd!
before defining new
+ autocommands in the augroup. This makes your plugin re-entrable.
+
plugin/mappings.vim
, using
+ maktaba#plugin#MapPrefix
to get a prefix.
+
+ All key mappings should be defined in
+ plugin/mappings.vim
.
+
+ Partial mappings (see :help using-<Plug>.) should be defined in
+ plugin/plugs.vim
.
+
+ Use :setlocal
and &l:
instead of
+ :set
and &
unless you have explicit
+ reason to do otherwise.
+
+ Follow google style conventions. When in doubt, treat vimscript style + like python style. +
+ +This does not apply to arguments to commands.
+You need not go out of your way to remove it.
+
+ Trailing whitespace is allowed in mappings which prep commands
+ for user input, such as
+ "noremap <leader>gf :grep -f
".
+
+ In general, use
+ plugin-names-like-this
,
+ FunctionNamesLikeThis
,
+ CommandNamesLikeThis
,
+ augroup_names_like_this
,
+ variable_names_like_this
.
+
Always prefix variables with their scope.
+Keep them short and sweet.
+ +Prefix script-local functions with s:
Autoloaded functions may not have a scope prefix.
++ Do not create global functions. Use autoloaded functions + instead. +
+Prefer succinct command names over common command prefixes.
+Augroup names count as variables for naming purposes.
+g:
s:
a:
l:
v:
b:
+ g:
, s:
, and a:
must always
+ be used.
+
+ b:
changes the variable semantics; use it when you
+ want buffer-local semantics.
+
+ l:
and v:
should be used for consistency,
+ future proofing, and to avoid subtle bugs. They are not strictly
+ required. Add them in new code but don’t go out of your way to add
+ them elsewhere.
+
+ Revision 1.1 +
+ + + + Nate Soares