mirror of
https://github.com/tiennm99/styleguide.git
synced 2026-10-12 12:14:18 +00:00
836 lines
28 KiB
Markdown
836 lines
28 KiB
Markdown
# Google Vimscript Guide
|
|
|
|
* Nate Soares
|
|
* Artemis Sparks
|
|
* David Barnett
|
|
|
|
<!-- mdformat on -->
|
|
|
|
## Background
|
|
|
|
This is the in-depth vimscript guide. If you're just a casual user looking to
|
|
write a plugin, the
|
|
[abbreviated style guide](./vimscriptguide.md)
|
|
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.
|
|
|
|
## Portability
|
|
|
|
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:
|
|
|
|
* Always prefix regular expressions with one of `\m`, `\v`, `\M`, or `\V`
|
|
(prefer tersity)
|
|
|
|
* Users can change the global "magic level" of regular expressions. This
|
|
changes how atoms are parsed in regular expressions, including `.`, `*`,
|
|
and `{`.
|
|
* Even if your regular expression does not contain characters which are
|
|
affected by the `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.
|
|
* This is recommended, but not required, when using regexes in a context
|
|
where the "magic level" is not used (e.g., calls to `substitute()`)
|
|
since it makes the pattern self-contained and future-proofs against the
|
|
same pattern being used in other contexts.
|
|
* If you have no opinion about what type of regular expression to use,
|
|
prefer the one which makes your regular expression most concise.
|
|
|
|
* Avoid using `:s[ubstitute]` in scripts.
|
|
|
|
* `:substitute` moves the cursor.
|
|
* `:substitute` outputs an error message when the match does not exist.
|
|
* The meaning of the `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.
|
|
* Script authors who want a safe way to replace text in the buffer are
|
|
encouraged to use `maktaba#buffer#Replace`.
|
|
|
|
* Always use case-explicit operators for strings (`=~#` and `=~?`, never
|
|
`=~`).
|
|
|
|
* This also applies to `!~ == != > >= < <= is` and `isnot`.
|
|
* This only applies for strings. `==` and `>=` are fine for numbers, but
|
|
`==#` and `>=#` must be used for comparing values that may be strings.
|
|
* The behavior of `=~` and friends is dependant upon the `ignorecase`
|
|
setting.
|
|
* You may break this rule when you explicitly want to obey the user's
|
|
`ignorecase` setting. Be prepared to justify your reasoning.
|
|
|
|
* When using regular expressions as arguments to functions, prepend them with
|
|
`\c` or `\C`.
|
|
|
|
* This forces case to be either explicitly matched or ignored.
|
|
* This is recommended, but not required, when comparing regexes with
|
|
operators that specify case sensitivity (`=~#`, etc.).
|
|
* This rule applies when your regexes are matching syntax, external APIs,
|
|
external messages, and most other cases.
|
|
* It does not apply when matching text in the buffer. When matching text
|
|
in the buffer you should honor the `ignorecase` setting.
|
|
* You may also ignore this rule any time that you explicitly want to honor
|
|
the `ignorecase` setting. Be prepared to justify your reasoning.
|
|
|
|
* Always use `normal!` instead of `normal`.
|
|
|
|
* If you forgo the `!` the command will use the user's key mappings and
|
|
you have literally no idea what your macro will do.
|
|
|
|
* Always use the `noremap` family of commands.
|
|
|
|
* Your plugins generally shouldn't introduce mappings, but if they do, the
|
|
`map` command respects the users existing mappings and could do
|
|
anything.
|
|
|
|
* When using `catch`, match the error code rather than the error text.
|
|
|
|
* The error text may be locale-dependant.
|
|
* See `:help error-messages`.
|
|
|
|
In general, guard all commands and functions against user settings.
|
|
|
|
## Language Guide
|
|
|
|
* Line continuations: **Yes**
|
|
|
|
* Plugins that support vi compatibility mode must save and restore
|
|
compatibility options as described in the **Errata section** so line
|
|
continuations work properly.
|
|
|
|
* Exceptions: **Yes, with caution**
|
|
|
|
* Always use an error code in thrown exception messages.
|
|
* Prefer the `maktaba#error` codes found in `maktaba`.
|
|
* Fall back to the vim error codes. See `:help error-messages`.
|
|
* Generate custom error messages using `maktaba#error#Message`.
|
|
* Public user commands and functions should catch and echo known errors
|
|
(via echomsg or `maktaba#error#Shout`) before they reach the user.
|
|
|
|
```
|
|
try
|
|
call somelibrary#FuncThatCanFail()
|
|
catch /ERROR(NotFound):/
|
|
call maktaba#error#Shout('Failed to do thing: %s', v:exception)
|
|
endtry
|
|
```
|
|
|
|
* Library functions are encouraged to throw errors to callers instead of
|
|
shouting them so the caller can manage error conditions. Always document
|
|
thrown errors in vimdoc doc comments with the `@throws` directive.
|
|
|
|
* Global Variables: **As configuration only**
|
|
|
|
* See the plugin guide.
|
|
|
|
* Messaging: **As little as possible.**
|
|
|
|
* Loud scripts are annoying.
|
|
* Message the user when an error has occured.
|
|
* Message the user when an operation which takes a long time has begun
|
|
work.
|
|
* Avoid messaging otherwise.
|
|
|
|
* Type checking: **Use strict and explicit checks where possible.**
|
|
|
|
* 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.
|
|
|
|
* FuncRefs: **No in most cases.**
|
|
|
|
* FuncRefs have inconsistently enforced naming restrictions. (Functions
|
|
can have names that FuncRefs can not.)
|
|
* FuncRefs have inconsistent ability to be reassigned (in Vim 7.2 and
|
|
before you must unlet a FuncRef before assigning it).
|
|
* In most instances where a FuncRef is needed a string works just as well:
|
|
just pass the string that you would use to make the FuncRef.
|
|
* Consider using `maktaba#function` instead to create and manipulate
|
|
handles to functions.
|
|
|
|
* Python: **Sparingly**
|
|
|
|
* Hurts code reuse since python code embedded in python plugins is awkward
|
|
to share between plugins.
|
|
* Using python introduces python language version dependencies, which are
|
|
likely to get stale.
|
|
* Exception: It's reasonable to use python for plugin functionality that
|
|
needs to do work in the background, as vimscript can not do this.
|
|
|
|
* Ruby: **No**
|
|
|
|
* We can not assume ruby interoperability.
|
|
* You shouldn't depend upon the version of the ruby language that the user
|
|
has installed.
|
|
|
|
* Lua: **No**
|
|
|
|
* For the same reasons an Ruby.
|
|
|
|
* Dict Functions: **Encouraged**
|
|
|
|
* Vimscript can attach functions to dictionaries. Such functions have
|
|
access to the `self` parameter which access the dict state.
|
|
* Use these where you would use a class in python.
|
|
* Do not over-use this feature; it is not necessary for helper functions
|
|
or API functions, only for encapsulated objects.
|
|
|
|
All other language features are fair game.
|
|
|
|
## Structure
|
|
|
|
* Provided functionality should be packed into modular plugins.
|
|
|
|
* Every function in your plugin should be specific to your plugin.
|
|
* General utility functions should be abstracted into library plugins.
|
|
* Manage dependencies with `maktaba`.
|
|
|
|
* `plugin-names-like-this`
|
|
|
|
* Plugin names should be descriptive and
|
|
concise.
|
|
|
|
* Each plugin must consist of one directory (or code repository), sharing a
|
|
name with the plugin (with a "vim-" prefix or ".vim" suffix if desired).
|
|
|
|
* Plugin metadata should be declared in the addon-info.json format (see the
|
|
[VAM documentation](https://goo.gl/CUXJZC) for details).
|
|
|
|
* Functions should go in the `autoload/` subdirectory of your plugin.
|
|
|
|
* This allows them to be late-loaded, which speeds up startup time.
|
|
* This helps vim enforce namespacing conventions.
|
|
|
|
* Each file in the `plugin/` or `instant/` directory should begin with the
|
|
boilerplate
|
|
|
|
```
|
|
let [s:plugin, s:enter] = maktaba#plugin#Enter(expand('<sfile>:p'))
|
|
if !s:enter
|
|
finish
|
|
endif
|
|
```
|
|
|
|
(This prevents re-entry and allows users to selectively disable
|
|
functionality.)
|
|
|
|
* User configuration should be via plugin flags defined in
|
|
`instant/flags.vim`.
|
|
|
|
* Define flags with `call s:plugin.Flag('FLAGNAME', DEFAULT_VALUE)`.
|
|
* Users can configure these flags using the `:Glaive` command (see
|
|
[glaive](https://github.com/google/glaive)).
|
|
|
|
* Commands, autocommands, mappings, and settings changes should occur either
|
|
in the `plugin/` or the `ftplugin/` subdirectories.
|
|
|
|
* All commands should be defined in `plugin/commands.vim` or `ftplugin/`
|
|
files.
|
|
* Autocommands should be defined in `plugin/autocmds.vim`, inside an
|
|
augroup.
|
|
* Mappings should be defined in `plugin/mappings.vim` and will be disabled
|
|
unless explicitly enabled by users.
|
|
* If the plugin configures any standard vim settings, those should be
|
|
configured in `plugin/settings.vim` or `instant/settings.vim`.
|
|
|
|
* Avoid using the `after/` subdirectory.
|
|
|
|
* `after/` should be reserved for the user.
|
|
* It is difficult for the user to add their own overrides when plugins use
|
|
`after/`.
|
|
|
|
### Libraries vs. Functionality
|
|
|
|
|
|
Separate library-providing plugins from command-providing plugins.
|
|
|
|
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.
|
|
|
|
|
|
### Configuration
|
|
|
|
|
|
Don't clobber user settings. Provide as much configurability as possible: that's
|
|
what Vim's all about.
|
|
|
|
* Use maktaba flags for plugin configuration. Users can configure them using
|
|
the `:Glaive` command.
|
|
|
|
<!-- TODO(dbarnett): Add links and/or more detail for flags. -->
|
|
|
|
* Check if configuration variables exist before setting them.
|
|
|
|
```
|
|
if !exists('g:myplugin_option')
|
|
let g:myplugin_option = 1
|
|
endif
|
|
```
|
|
|
|
|
|
|
|
## Style Guide
|
|
|
|
Follow google-wide style conventions. Mimic google python style when in doubt.
|
|
|
|
### Documentation
|
|
|
|
|
|
Use [vimdoc](https://github.com/google/vimdoc).
|
|
|
|
Provide help files generated by [vimdoc](https://github.com/google/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](https://goo.gl/CUXJZC)).
|
|
|
|
|
|
### Whitespace
|
|
|
|
|
|
Follow google-wide conventions.
|
|
|
|
* Use two spaces for indents.
|
|
* Do not use tabs.
|
|
* Use spaces around operators except for arguments to commands.
|
|
|
|
* Using spaces around operators for commands is often invalid syntax. This
|
|
is inconsistently enforced by vimscript. To be safe, always omit
|
|
whitespace around arguments to commands.
|
|
|
|
```
|
|
let s:variable = "concatenated " . "strings"
|
|
command -range=% MyCommand
|
|
```
|
|
|
|
```
|
|
let s:variable="concatenated "."strings"
|
|
command -range = % MyCommand
|
|
```
|
|
|
|
* Do not introduce trailing whitespace.
|
|
|
|
* You need not go out of your way to remove it.
|
|
|
|
* Restrict lines to 80 columns wide.
|
|
|
|
* Indent continued lines by four spaces.
|
|
|
|
```
|
|
let l:something = SomeReallyLongFunctionName(
|
|
\ 'arg1', 0, ['XXXXX'], {'somekey': 9999999999})
|
|
```
|
|
|
|
* Do not waste whitespace aligning common segments of similar commands. It is
|
|
both difficult and expensive to maintain.
|
|
|
|
```
|
|
command -bang MyCommand call myplugin#foo()
|
|
command MyCommand2 call myplugin#bar()
|
|
```
|
|
|
|
```
|
|
command -bang MyCommand call myplugin#foo()
|
|
command MyCommand2 call myplugin#bar()
|
|
```
|
|
|
|
#### Line Continuations
|
|
|
|
* Prefer line continuations on semantic boundaries.
|
|
|
|
```
|
|
command SomeLongCommand
|
|
\ call some#function()
|
|
```
|
|
|
|
```
|
|
command SomeLongCommand call
|
|
\ some#function()
|
|
```
|
|
|
|
Use your best judgement.
|
|
|
|
* Place one space after the backslash denoting a line continuation.
|
|
|
|
* When continuing a multi-line command a pipe can be substituted for this
|
|
space as necessary, as follows:
|
|
|
|
```
|
|
autocommand BufEnter <buffer>
|
|
\ if !empty(s:var)
|
|
\| call some#function()
|
|
\|else
|
|
\| call some#function(s:var)
|
|
\|endif
|
|
```
|
|
|
|
* Do not continue multi-line commands when you can avoid it. Prefer function
|
|
calls.
|
|
|
|
#### Comments
|
|
|
|
* Place a space after the `"` before the comment text.
|
|
|
|
```
|
|
" I am a line comment.
|
|
call call(s:my_function)
|
|
```
|
|
|
|
* Do not use inline comments.
|
|
|
|
* Some commands treat them as comments and others as unclosed quotes.
|
|
There are many edge cases. It's difficult to get right and difficult to
|
|
maintain.
|
|
* Where you would use an inline comment, put a line comment on the line
|
|
above.
|
|
* When leaving blank lines in comments, include the quote in the blank
|
|
line.
|
|
|
|
```
|
|
" I am one continuous
|
|
"
|
|
" comment block
|
|
```
|
|
|
|
|
|
|
|
### Variables
|
|
|
|
|
|
`plugin-names-like-this`, `FunctionNamesLikeThis`, `CommandNamesLikeThis`,
|
|
`augroup_names_like_this`, `variable_names_like_this`. Prefix all variables with
|
|
their scope.
|
|
|
|
* `variable_names_like_this`
|
|
|
|
* FuncRef variables count as functions and should be named like functions.
|
|
* This (pathological) convention is enforced by vim itself.
|
|
|
|
* Prefix global variables with `g:`
|
|
|
|
* Vimscript allows you to create global variables without prefixing them.
|
|
* It is very bad practice to introduce non-prefixed global variables into
|
|
scope.
|
|
* Global variables should only be used for plugin configuration.
|
|
* This does not apply to functions defined in `autoload` directories.
|
|
|
|
* Prefix script-local variables with `s:`
|
|
|
|
* This prevents namespace collisions between plugins.
|
|
* This also applies to script-local functions.
|
|
|
|
* Prefix function arguments with `a:`
|
|
|
|
* This is enforced by vim itself.
|
|
|
|
* Prefix function-local variables with `l:`
|
|
|
|
* This is not enforced by vimscript but is good practice.
|
|
* It helps you remember that all other variables must be prefixed with
|
|
scope.
|
|
* `l:` disambiguates between function-local and vim-predefined variables.
|
|
For example, `count` refers to `v:count`, not `l:count`.
|
|
* It future proofs your scripts against the introduction of new
|
|
vim-predefined variables.
|
|
|
|
* Prefix pre-defined vim variables with `v:`
|
|
|
|
* This is not enforced by vimscript but is good practice.
|
|
* It provides context as to where the (undeclared) variable is coming
|
|
from.
|
|
* It reminds you that the variable can not be assigned to.
|
|
|
|
* Prefix buffer-local or window-local variables with `b:` or `w:`
|
|
|
|
* This is useful for plugins that keep per-buffer or per-window state.
|
|
|
|
|
|
|
|
### Strings
|
|
|
|
|
|
Prefer single quotes.
|
|
|
|
Prefer single quoted strings. Specifically, in order of precedence:
|
|
|
|
* Always use single quotes for regular expressions.
|
|
|
|
* `'\s*'` is not the same as `"\s*"`
|
|
* Single quotes will prevent the need for excessive backslashes.
|
|
* Double single quotes escape to one single quote in single quoted
|
|
strings: `'example ('')'` represents the string `example (')`
|
|
|
|
* If your string requires escape characters (`\n`, `\t`, etc.) use double
|
|
quotes.
|
|
|
|
* Escapes can not be expressed in single quoted strings.
|
|
* Remember that `'\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.
|
|
|
|
* If your string contains no escapes nor single quotes, use single quoted
|
|
strings.
|
|
|
|
* Most strings in vimscript are regexes, so this provides maximum
|
|
consistency.
|
|
|
|
* If your non-regex string contains single quotes but no double quotes, use
|
|
double quotes.
|
|
|
|
* Don't bother escaping strings if you don't have to.
|
|
* This is similar to the python string rules.
|
|
|
|
* If your string contains both single and double quotes, use whichever quoting
|
|
style requires less escaping.
|
|
|
|
* Break ties in favor of single quotes.
|
|
|
|
|
|
|
|
### Settings
|
|
|
|
|
|
Prefer long names. Set settings locally.
|
|
|
|
* Prefer long names of built in settings (i.e. `tabstop` over `ts`).
|
|
* Set local settings unless you explicitly want to set global settings.
|
|
|
|
* Use `setlocal` and `&l:` instead of `set` and `&`.
|
|
|
|
|
|
|
|
## Usage Guide
|
|
|
|
Vim plugins should provide any or all of the following: **Commands**,
|
|
**Autocommands**, **Functions**, **Statusline Flags**, and **Mappings**.
|
|
|
|
### Commands
|
|
|
|
|
|
* Define in `plugin/commands.vim`.
|
|
* CommandNamesLikeThis.
|
|
* Prefer semantic names to a unified prefix.
|
|
* Do not use `[!]`
|
|
* Extract logic into functions.
|
|
|
|
* `CommandNamesLikeThis`
|
|
|
|
* Commands should be defined in one block with no whitespace between them.
|
|
|
|
* Name commands semantically at the expense of a common prefix.
|
|
|
|
```
|
|
command WhitespaceFixTrailing
|
|
command WhitespaceFixIndentation
|
|
```
|
|
|
|
```
|
|
command FixTrailingWhitespace
|
|
command FixIndentation
|
|
```
|
|
|
|
* Use `command` without a bang.
|
|
|
|
* This notifies users to command name conflicts immediately at startup.
|
|
* Command name collisions are an error and should not fail silently.
|
|
* Plugins are guarded against re-entry, so a single vim session should
|
|
never attempt to re-define defined commands.
|
|
|
|
* Do not put logic in commands.
|
|
|
|
* Delegate to functions instead.
|
|
* Pass non-argument command parameters (`<bang>`, `<register>`, etc.)
|
|
before argument parameters (`<f-args>`, etc.).
|
|
* Otherwise variable-length argument functions are difficult to implement.
|
|
|
|
* Do not autoload commands.
|
|
|
|
* Autoloaded commands will not be available until after a function in the
|
|
same file is called.
|
|
* Commands intended to be used in the .vimrc should be defined in a
|
|
`instant/commands.vim` file in plugins using maktaba, or explicitly
|
|
installed via an autoload function in non-maktaba plugins.
|
|
|
|
#### Conventions {#commands-conventions}
|
|
|
|
* Pass `<bang>` to functions with `'<bang>' == '!'`.
|
|
|
|
* The function should receive a boolean parameter, not a string.
|
|
|
|
|
|
|
|
### Autocommands
|
|
|
|
|
|
* Define in `plugin/autocmds.vim`.
|
|
* Use augroups.
|
|
* `augroup_names_like_this`.
|
|
* Clear the augroup first.
|
|
* Extract logic into functions.
|
|
|
|
* All autocommands should be defined in the `plugin/autocmds.vim` file.
|
|
|
|
* This allows users to disable your autocommands with `Glaive myplugin
|
|
!plugin[autocmds]`.
|
|
|
|
* Declare all autocommands in an `augroup` block.
|
|
|
|
* This allows your autocommands to be cleared with `autocmd!`.
|
|
|
|
* If your plugin only has one `augroup`, the `augroup` name should be the
|
|
same as your plugin name, with underscores in place of any hyphens.
|
|
|
|
* Otherwise `augroup` names should start with your plugin name followed by
|
|
an underscore.
|
|
|
|
* Do not put logic in autocommands.
|
|
|
|
* Delegate to functions instead.
|
|
|
|
* When creating a new `augroup`, clear it with `autocmd!`
|
|
|
|
* This allows your plugins to be re-enterable.
|
|
|
|
|
|
|
|
### Functions
|
|
|
|
|
|
* FunctionNamesLikeThis.
|
|
* Autoload all functions.
|
|
* Prefix script-local functions with `s:`
|
|
* Use `[!]`.
|
|
* Use `[abort]`.
|
|
|
|
* `FunctionNamesLikeThis`
|
|
|
|
* Prefix all script-local functions with `s:`
|
|
|
|
* Do not provide global functions. Use autoloaded functions instead.
|
|
|
|
* Place two blank lines between top-level functions.
|
|
|
|
* Declare all functions with `abort`.
|
|
|
|
* If you do not do this, the function's behavior depends upon whether it
|
|
is called within a `try..endtry` block somewhere on the stack.
|
|
* The `abort` keyword forces the function to act consistently.
|
|
* Without it, the function may (or may not) attempt to continue execution
|
|
after an error occurs.
|
|
|
|
* Use `function!` with a bang.
|
|
|
|
* This allows developers to re-source their scripts and have the functions
|
|
reloaded without complaint.
|
|
* Function names should never collide because functions should always be
|
|
either script-local or defined in an `autoload` directory.
|
|
* Failing to use a bang in any function in an autoload file will lead to
|
|
cryptic errors if vim tries to re-source the file (e.g., if you refer to
|
|
an nonexistent autoload function).
|
|
|
|
* Use `...` for optional arguments, not for lists of arguments.
|
|
|
|
* Vimscript functions take at most 20 arguments.
|
|
* Lists have no such length restriction.
|
|
* Your function is likely to break when given too many arguments if you
|
|
use `...` for a list of arguments.
|
|
|
|
* Throw exceptions rather than printing errors.
|
|
|
|
* Printed errors can not be caught.
|
|
* Top-level functions expecting errors may catch them and print error
|
|
messages, but even those should throw their own errors when they choke.
|
|
|
|
|
|
|
|
### Mappings
|
|
|
|
|
|
* Provide opt-in key mappings in `plugin/mappings.vim`.
|
|
* `<Plug>` mappings can be defined in `plugin/plugs.vim` (unlike mappings.vim,
|
|
plugs.vim is opt-out).
|
|
|
|
* Define key mappings in `plugin/mappings.vim`, using
|
|
`maktaba#plugin#MapPrefix` to get a prefix.
|
|
|
|
* Mappings defined in the special `plugin/mappings.vim` file will be
|
|
disabled by default (by the standard `maktaba#plugin#Enter()`
|
|
boilerplate).
|
|
* Users can enable key mappings with `Glaive myplugin plugin[mappings]`.
|
|
|
|
* Make all mappings with `<unique>`.
|
|
|
|
* This will inform the user when they have a mapping conflict instead of
|
|
silently clobbering their existing mappings.
|
|
|
|
* You may provide pseudo-mappings using `<Plug>` and your plugin's name in
|
|
`plugin/plugs.vim` (separate from standard key mappings).
|
|
|
|
* `<Plug>` is a sequence which can not be typed.
|
|
* You can do something like `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.
|
|
* Pseudo-mappings should **not** be in `plugin/mappings.vim` or they will
|
|
be disabled by default.
|
|
* Such pseudo-mappings should be named `<Plug>` followed by your plugin
|
|
name, a pound sign, and a unique mapping name (CamelCased like a
|
|
function).
|
|
|
|
* Always use the `noremap` family of commands. Never use the `map` family.
|
|
|
|
* `map` depends upon the user's existing mappings, and could do anything.
|
|
|
|
* Only use `noremap` for commands that both make a motion and take a range.
|
|
|
|
* `noremap` makes mappings in normal, visual, and operator-pending modes.
|
|
* If you don't want all these use `nnoremap` `onoremap` or `vnoremap`
|
|
explicitly.
|
|
|
|
* Always use `<SID>` in place of `s:` when accessing script locals in
|
|
mappings.
|
|
|
|
* Using `s:` will often fail as the mapping attempts to type a literal s
|
|
and colon.
|
|
|
|
|
|
|
|
## Conventions
|
|
|
|
### Dependency Checking
|
|
|
|
|
|
Declare dependencies in addon-info.json and use `maktaba`.
|
|
|
|
Declaring dependencies in addon-info.json allows conformant plugin managers
|
|
(like VAM) to ensure dependencies are installed. See the
|
|
[VAM documentation](https://goo.gl/CUXJZC) 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.
|
|
|
|
|
|
### Statusline Flags
|
|
|
|
|
|
Use `<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.).
|
|
|
|
* Provide the `Info`, `Alert`, `Warning`, and `Error` functions under the
|
|
`<plugin-name>#status` namespace.
|
|
* `Info`should provide information about the state of the buffer.
|
|
* Example: The current git branch.
|
|
* `Alert` should provide a quiet reminder that the buffer is non-standard.
|
|
* Example: The readonly setting is on.
|
|
* `Warning`should provide a warning about the current state of the buffer.
|
|
* Example: The file has been edited elsewhere.
|
|
* `Error` should bring to attention a loud issue with the buffer.
|
|
* Example: The file does not pass the syntax checker.
|
|
* By following these conventions, users can easily build up their own
|
|
statusline customizing the verbosity and colors to their tastes.
|
|
* All functions should take no arguments and should return either empty
|
|
strings or strings enclosed by square brackets, e.g. `[Google]`. For
|
|
example:
|
|
* A trailing whitespace plugin might return `[$]` if the file contains
|
|
trailing whitespace
|
|
* A prose writing plugin might return `[write]` if vim is in writing mode.
|
|
* Consider providing the `<plugin-name>#status#Status` function.
|
|
* It should return the first non-empty of `Error`, `Warning`, `Alert`, or
|
|
`Info`.
|
|
* This is useful for users who want only the most relevant flag and do not
|
|
have a colored statusline.
|
|
|
|
|
|
|
|
## Forbidden Commands
|
|
|
|
These are commands which can only be used by a limited number of plugins, and
|
|
should not in general be used by yours.
|
|
|
|
* Do not use `:match :2match` or `:3match`
|
|
* These are reserved for the user and for vim itself.
|
|
* Use `matchadd()` to create a matchlevel unique to your plugin.
|
|
* Do not use `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.
|
|
* Use `echohl` in tandem with `echomsg` if you want the red error bar.
|
|
* Use `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.
|
|
|
|
## Layout
|
|
|
|
Lay out `plugin/` files in the following sections, if applicable, separated by
|
|
two blank lines:
|
|
|
|
* Declaration of script constants
|
|
* Declaration of configuration variables
|
|
* Other declarations (commands in `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
|
|
* Script-local variables
|
|
* Script-local functions
|
|
* Private autoloaded functions
|
|
* Public autoloaded functions
|
|
|
|
This is recommended convention and is not enforced.
|
|
|
|
## Recommended Shortcuts
|
|
|
|
Use the following shortcuts:
|
|
|
|
* `catch` over `catch /.*/`
|
|
* `return` over `return 0` when the return value has no semantic purpose.
|
|
|
|
## Errata
|
|
|
|
This section plumbs some of the darker corners of vimscript, explaining the
|
|
language pathologies that you wish you didn't have to know.
|
|
|
|
### Compatibility Mode
|
|
|
|
|
|
If you don't support vi-compatibility mode, fail gracefully.
|
|
|
|
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.
|
|
|