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