mirror of
https://github.com/tiennm99/styleguide.git
synced 2026-10-13 00:15:04 +00:00
vim: switch to markdown
This commit is contained in:
1 parent
e277feb66e
commit
b3cc1ed6cc
5 files changed
+1175
-2438
No files matched your search
@@ -93,7 +93,7 @@ primarily optimizing for Google's internal needs.
|
||||
[ts]: https://google.github.io/styleguide/tsguide.html
|
||||
[angular]: https://google.github.io/styleguide/angularjs-google-style.html
|
||||
[cl]: https://google.github.io/styleguide/lispguide.html
|
||||
[vim]: https://google.github.io/styleguide/vimscriptguide.html
|
||||
[vim]: vimscriptguide.md
|
||||
[emacs]: https://raw.githubusercontent.com/google/styleguide/gh-pages/google-c-style.el
|
||||
[xml]: https://google.github.io/styleguide/xmlstyle.html
|
||||
[dart]: https://www.dartlang.org/guides/language/effective-dart
|
||||
|
||||
-1775
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,843 @@
|
||||
# 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](http://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](http://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](http://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.
|
||||
|
||||
@@ -1,662 +0,0 @@
|
||||
<HTML xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcq="http://purl.org/dc/qualifiers/1.0/" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:fn="http://www.w3.org/2005/xpath-functions">
|
||||
<HEAD>
|
||||
<TITLE>Google Vimscript Style Guide</TITLE>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<LINK HREF="/styleguide/favicon.ico" type="image/x-icon" rel="shortcut icon">
|
||||
<LINK HREF="styleguide.css" type="text/css" rel="stylesheet">
|
||||
<SCRIPT language="javascript" type="text/javascript">
|
||||
|
||||
function GetElementsByName(name) {
|
||||
// Workaround a bug on old versions of opera.
|
||||
if (document.getElementsByName) {
|
||||
return document.getElementsByName(name);
|
||||
} else {
|
||||
return [document.getElementById(name)];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} namePrefix The prefix of the body name.
|
||||
* @param {function(boolean): boolean} getVisibility Computes the new
|
||||
* visibility state, given the current one.
|
||||
*/
|
||||
function ChangeVisibility(namePrefix, getVisibility) {
|
||||
var bodyName = namePrefix + '__body';
|
||||
var buttonName = namePrefix + '__button';
|
||||
var bodyElements = GetElementsByName(bodyName);
|
||||
var linkElement = GetElementsByName('link-' + buttonName)[0];
|
||||
if (bodyElements.length != 1) {
|
||||
throw Error('ShowHideByName() got the wrong number of bodyElements: ' +
|
||||
bodyElements.length);
|
||||
} else {
|
||||
var bodyElement = bodyElements[0];
|
||||
var buttonElement = GetElementsByName(buttonName)[0];
|
||||
var isVisible = bodyElement.style.display != "none";
|
||||
if (getVisibility(isVisible)) {
|
||||
bodyElement.style.display = "inline";
|
||||
linkElement.style.display = "block";
|
||||
buttonElement.innerHTML = '▽';
|
||||
} else {
|
||||
bodyElement.style.display = "none";
|
||||
linkElement.style.display = "none";
|
||||
buttonElement.innerHTML = '▶';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ShowHideByName(namePrefix) {
|
||||
ChangeVisibility(namePrefix, function(old) { return !old; });
|
||||
}
|
||||
|
||||
function ShowByName(namePrefix) {
|
||||
ChangeVisibility(namePrefix, function() { return true; });
|
||||
}
|
||||
|
||||
function ShowHideAll() {
|
||||
var allButton = GetElementsByName("show_hide_all_button")[0];
|
||||
if (allButton.innerHTML == '▽') {
|
||||
allButton.innerHTML = '▶';
|
||||
SetHiddenState(document.getElementsByTagName("body")[0].childNodes, "none", '▶');
|
||||
} else {
|
||||
allButton.innerHTML = '▽';
|
||||
SetHiddenState(document.getElementsByTagName("body")[0].childNodes, "inline", '▽');
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively sets state of all children
|
||||
// of a particular node.
|
||||
function SetHiddenState(root, newState, newButton) {
|
||||
for (var i = 0; i != root.length; i++) {
|
||||
SetHiddenState(root[i].childNodes, newState, newButton);
|
||||
if (root[i].className == 'showhide_button') {
|
||||
root[i].innerHTML = newButton;
|
||||
}
|
||||
if (root[i].className == 'stylepoint_body' ||
|
||||
root[i].className == 'link_button') {
|
||||
root[i].style.display = newState;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function EndsWith(str, suffix) {
|
||||
var l = str.length - suffix.length;
|
||||
return l >= 0 && str.indexOf(suffix, l) == l;
|
||||
}
|
||||
|
||||
function RefreshVisibilityFromHashParam() {
|
||||
var hashRegexp = new RegExp('#([^&#]*)$');
|
||||
var hashMatch = hashRegexp.exec(window.location.href);
|
||||
var anchor = hashMatch && GetElementsByName(hashMatch[1])[0];
|
||||
var node = anchor;
|
||||
var suffix = '__body';
|
||||
while (node) {
|
||||
var id = node.id;
|
||||
var matched = id && EndsWith(id, suffix);
|
||||
if (matched) {
|
||||
var len = id.length - suffix.length;
|
||||
ShowByName(id.substring(0, len));
|
||||
if (anchor.scrollIntoView) {
|
||||
anchor.scrollIntoView();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
node = node.parentNode;
|
||||
}
|
||||
}
|
||||
|
||||
window.onhashchange = RefreshVisibilityFromHashParam;
|
||||
|
||||
window.onload = function() {
|
||||
// if the URL contains "?showall=y", expand the details of all children
|
||||
var showHideAllRegex = new RegExp("[\\?&](showall)=([^&#]*)");
|
||||
var showHideAllValue = showHideAllRegex.exec(window.location.href);
|
||||
if (showHideAllValue != null) {
|
||||
if (showHideAllValue[2] == "y") {
|
||||
SetHiddenState(document.getElementsByTagName("body")[0].childNodes,
|
||||
"inline", '▽');
|
||||
} else {
|
||||
SetHiddenState(document.getElementsByTagName("body")[0].childNodes,
|
||||
"none", '▶');
|
||||
}
|
||||
}
|
||||
var showOneRegex = new RegExp("[\\?&](showone)=([^&#]*)");
|
||||
var showOneValue = showOneRegex.exec(window.location.href);
|
||||
if (showOneValue) {
|
||||
ShowHideByName(showOneValue[2]);
|
||||
}
|
||||
|
||||
|
||||
RefreshVisibilityFromHashParam();
|
||||
}
|
||||
</SCRIPT>
|
||||
</HEAD>
|
||||
<BODY>
|
||||
<H1>Google Vimscript Style Guide</H1>
|
||||
<p class="revision">
|
||||
|
||||
Revision 1.1
|
||||
</p>
|
||||
|
||||
|
||||
<address>
|
||||
Nate Soares<br>
|
||||
Artemis Sparks<br>
|
||||
David Barnett<br>
|
||||
</address>
|
||||
|
||||
<DIV style="margin-left: 50%; font-size: 75%;">
|
||||
<P>
|
||||
Each style point has a summary for which additional information is available
|
||||
by toggling the accompanying arrow button that looks this way:
|
||||
<SPAN class="showhide_button" style="margin-left: 0; float: none">▶</SPAN>.
|
||||
You may toggle all summaries with the big arrow button:
|
||||
</P>
|
||||
<DIV style=" font-size: larger; margin-left: +2em;">
|
||||
<SPAN class="showhide_button" style="font-size: 180%; float: none" onclick="javascript:ShowHideAll()" name="show_hide_all_button" id="show_hide_all_button">▶</SPAN>
|
||||
Toggle all summaries
|
||||
</DIV>
|
||||
</DIV>
|
||||
<DIV class="toc">
|
||||
<DIV class="toc_title">Table of Contents</DIV>
|
||||
<TABLE>
|
||||
<TR valign="top" class="">
|
||||
<TD><DIV class="toc_category"><A href="#Portability">Portability</A></DIV></TD>
|
||||
<TD><DIV class="toc_stylepoint">
|
||||
<SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Strings">Strings</A></SPAN> <SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Matching_Strings">Matching Strings</A></SPAN> <SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Regular_Expressions">Regular Expressions</A></SPAN> <SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Dangerous_commands">Dangerous commands</A></SPAN> <SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Fragile_commands">Fragile commands</A></SPAN> <SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Catching_Exceptions">Catching Exceptions</A></SPAN> </DIV></TD>
|
||||
</TR>
|
||||
<TR valign="top" class="">
|
||||
<TD><DIV class="toc_category"><A href="#General_Guidelines">General Guidelines</A></DIV></TD>
|
||||
<TD><DIV class="toc_stylepoint">
|
||||
<SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Messaging">Messaging</A></SPAN> <SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Type_checking">Type checking</A></SPAN> <SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Python">Python</A></SPAN> <SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Other_Languages">Other Languages</A></SPAN> <SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Boilerplate">Boilerplate</A></SPAN> <SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Plugin_layout">Plugin layout</A></SPAN> <SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Functions">Functions</A></SPAN> <SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Commands">Commands</A></SPAN> <SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Autocommands">Autocommands</A></SPAN> <SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Mappings">Mappings</A></SPAN> <SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Settings">Settings</A></SPAN> </DIV></TD>
|
||||
</TR>
|
||||
<TR valign="top" class="">
|
||||
<TD><DIV class="toc_category"><A href="#Style">Style</A></DIV></TD>
|
||||
<TD><DIV class="toc_stylepoint">
|
||||
<SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Whitespace">Whitespace</A></SPAN> <SPAN style="padding-right: 1em; white-space:nowrap;" class=""><A href="#Naming">Naming</A></SPAN> </DIV></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</DIV>
|
||||
<DIV class="">
|
||||
<H2 name="Background" id="Background">Background</H2>
|
||||
<p>
|
||||
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
|
||||
<a href="vimscriptfull.xml">heavy guide</a>.
|
||||
</p>
|
||||
</DIV>
|
||||
|
||||
|
||||
<DIV class="">
|
||||
<H2 name="Portability" id="Portability">Portability</H2>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<DIV class="">
|
||||
<H3><A name="Strings" id="Strings">Strings</A></H3>
|
||||
<SPAN class="link_button" id="link-Strings__button" name="link-Strings__button"><A href="?showone=Strings#Strings">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Strings')" name="Strings__button" id="Strings__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">Prefer single quoted strings</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Strings__body" id="Strings__body" style="display: none">
|
||||
<p>
|
||||
Double quoted strings are semantically different in vimscript, and
|
||||
you probably don't want them (they break regexes).
|
||||
</p>
|
||||
<p>
|
||||
Use double quoted strings when you need an escape sequence (such as
|
||||
<code>"\n"</code>) or if you know it doesn't matter and you need to
|
||||
embed single quotes.
|
||||
</p>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
<DIV class="">
|
||||
<H3><A name="Matching_Strings" id="Matching_Strings">Matching Strings</A></H3>
|
||||
<SPAN class="link_button" id="link-Matching_Strings__button" name="link-Matching_Strings__button"><A href="?showone=Matching_Strings#Matching_Strings">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Matching_Strings')" name="Matching_Strings__button" id="Matching_Strings__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">
|
||||
Use the <code>=~#</code> or <code>=~?</code> operator families over the
|
||||
<code>=~</code> family.
|
||||
</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Matching_Strings__body" id="Matching_Strings__body" style="display: none">
|
||||
<p>
|
||||
The matching behavior depends upon the user's ignorecase and smartcase
|
||||
settings and on whether you compare them with the <code>=~</code>,
|
||||
<code>=~#</code>, or <code>=~?</code> family of operators. Use the
|
||||
<code>=~#</code> and <code>=~?</code> operator families explicitly
|
||||
when comparing strings unless you explicitly need to honor the user's
|
||||
case sensitivity settings.
|
||||
</p>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
<DIV class="">
|
||||
<H3><A name="Regular_Expressions" id="Regular_Expressions">Regular Expressions</A></H3>
|
||||
<SPAN class="link_button" id="link-Regular_Expressions__button" name="link-Regular_Expressions__button"><A href="?showone=Regular_Expressions#Regular_Expressions">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Regular_Expressions')" name="Regular_Expressions__button" id="Regular_Expressions__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">Prefix all regexes with <code>\m\C</code>.</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Regular_Expressions__body" id="Regular_Expressions__body" style="display: none">
|
||||
<p>
|
||||
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 <code>\m\C</code>.
|
||||
</p>
|
||||
<p>
|
||||
You are welcome to use other magic levels (<code>\v</code>) and case
|
||||
sensitivities (<code>\c</code>) so long as they are intentional and
|
||||
explicit.
|
||||
</p>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
<DIV class="">
|
||||
<H3><A name="Dangerous_commands" id="Dangerous_commands">Dangerous commands</A></H3>
|
||||
<SPAN class="link_button" id="link-Dangerous_commands__button" name="link-Dangerous_commands__button"><A href="?showone=Dangerous_commands#Dangerous_commands">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Dangerous_commands')" name="Dangerous_commands__button" id="Dangerous_commands__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">Avoid commands with unintended side effects.</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Dangerous_commands__body" id="Dangerous_commands__body" style="display: none">
|
||||
<p>
|
||||
Avoid using <code>:s[ubstitute]</code> as it moves the cursor and
|
||||
prints error messages. Prefer functions (such as
|
||||
<code>search()</code>) better suited to scripts.
|
||||
</p>
|
||||
<p>
|
||||
For many vim commands, functions exist that do the same thing with
|
||||
fewer side effects. See <code>:help functions()</code> for a list of
|
||||
built-in functions.
|
||||
</p>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
<DIV class="">
|
||||
<H3><A name="Fragile_commands" id="Fragile_commands">Fragile commands</A></H3>
|
||||
<SPAN class="link_button" id="link-Fragile_commands__button" name="link-Fragile_commands__button"><A href="?showone=Fragile_commands#Fragile_commands">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Fragile_commands')" name="Fragile_commands__button" id="Fragile_commands__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">Avoid commands that rely on user settings.</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Fragile_commands__body" id="Fragile_commands__body" style="display: none">
|
||||
<p>
|
||||
Always use <code>normal!</code> instead of <code>normal</code>. The
|
||||
latter depends upon the user's key mappings and could do anything.
|
||||
</p>
|
||||
<p>
|
||||
Avoid <code>:s[ubstitute]</code>, as its behavior depends upon a
|
||||
number of local settings.
|
||||
</p>
|
||||
<p>
|
||||
The same applies to other commands not listed here.
|
||||
</p>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
<DIV class="">
|
||||
<H3><A name="Catching_Exceptions" id="Catching_Exceptions">Catching Exceptions</A></H3>
|
||||
<SPAN class="link_button" id="link-Catching_Exceptions__button" name="link-Catching_Exceptions__button"><A href="?showone=Catching_Exceptions#Catching_Exceptions">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Catching_Exceptions')" name="Catching_Exceptions__button" id="Catching_Exceptions__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">Match error codes, not error text.</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Catching_Exceptions__body" id="Catching_Exceptions__body" style="display: none">
|
||||
<p>Error text may be locale dependent.</p>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
</DIV>
|
||||
|
||||
<DIV class="">
|
||||
<H2 name="General_Guidelines" id="General_Guidelines">General Guidelines</H2>
|
||||
|
||||
|
||||
<DIV class="">
|
||||
<H3><A name="Messaging" id="Messaging">Messaging</A></H3>
|
||||
<SPAN class="link_button" id="link-Messaging__button" name="link-Messaging__button"><A href="?showone=Messaging#Messaging">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Messaging')" name="Messaging__button" id="Messaging__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">Message the user infrequently.</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Messaging__body" id="Messaging__body" style="display: none">
|
||||
<p>
|
||||
Loud scripts are annoying. Message the user only when:
|
||||
<ul>
|
||||
<li>A long-running process has kicked off.</li>
|
||||
<li>An error has occurred.</li>
|
||||
</ul>
|
||||
</p>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
<DIV class="">
|
||||
<H3><A name="Type_checking" id="Type_checking">Type checking</A></H3>
|
||||
<SPAN class="link_button" id="link-Type_checking__button" name="link-Type_checking__button"><A href="?showone=Type_checking#Type_checking">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Type_checking')" name="Type_checking__button" id="Type_checking__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">Use strict and explicit checks where possible.</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Type_checking__body" id="Type_checking__body" style="display: none">
|
||||
<p>
|
||||
Vimscript has unsafe, unintuitive behavior when dealing with some
|
||||
types. For instance, <code>0 == 'foo'</code> evaluates to true.
|
||||
</p>
|
||||
<p>
|
||||
Use strict comparison operators where possible. When comparing against
|
||||
a string literal, use the <code>is#</code> operator. Otherwise, prefer
|
||||
<code>maktaba#value#IsEqual</code> or check <code>type()</code>
|
||||
explicitly.
|
||||
</p>
|
||||
<p>
|
||||
Check variable types explicitly before using them. Use functions from
|
||||
<code>maktaba#ensure</code>, or check <code>maktaba#value</code> or
|
||||
<code>type()</code> and throw your own errors.
|
||||
</p>
|
||||
<p>
|
||||
Use <code>:unlet</code> for variables that may change types,
|
||||
particularly those assigned inside loops.
|
||||
</p>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
<DIV class="">
|
||||
<H3><A name="Python" id="Python">Python</A></H3>
|
||||
<SPAN class="link_button" id="link-Python__button" name="link-Python__button"><A href="?showone=Python#Python">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Python')" name="Python__button" id="Python__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">Use sparingly.</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Python__body" id="Python__body" style="display: none">
|
||||
<p>
|
||||
Use python only when it provides critical functionality, for example
|
||||
when writing threaded code.
|
||||
</p>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
<DIV class="">
|
||||
<H3><A name="Other_Languages" id="Other_Languages">Other Languages</A></H3>
|
||||
<SPAN class="link_button" id="link-Other_Languages__button" name="link-Other_Languages__button"><A href="?showone=Other_Languages#Other_Languages">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Other_Languages')" name="Other_Languages__button" id="Other_Languages__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">Use vimscript instead.</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Other_Languages__body" id="Other_Languages__body" style="display: none">
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
<DIV class="">
|
||||
<H3><A name="Boilerplate" id="Boilerplate">Boilerplate</A></H3>
|
||||
<SPAN class="link_button" id="link-Boilerplate__button" name="link-Boilerplate__button"><A href="?showone=Boilerplate#Boilerplate">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Boilerplate')" name="Boilerplate__button" id="Boilerplate__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">
|
||||
Use <a href="https://github.com/google/maktaba">maktaba</a>.
|
||||
</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Boilerplate__body" id="Boilerplate__body" style="display: none">
|
||||
<p>
|
||||
maktaba removes boilerplate, including:
|
||||
<ul>
|
||||
<li>Plugin creation</li>
|
||||
<li>Error handling</li>
|
||||
<li>Dependency checking</li>
|
||||
</ul>
|
||||
</p>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
<DIV class="">
|
||||
<H3><A name="Plugin_layout" id="Plugin_layout">Plugin layout</A></H3>
|
||||
<SPAN class="link_button" id="link-Plugin_layout__button" name="link-Plugin_layout__button"><A href="?showone=Plugin_layout#Plugin_layout">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Plugin_layout')" name="Plugin_layout__button" id="Plugin_layout__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">Organize functionality into modular plugins</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Plugin_layout__body" id="Plugin_layout__body" style="display: none">
|
||||
<p>
|
||||
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
|
||||
<a href="https://github.com/MarcWeber/vim-addon-manager/blob/master/doc/vim-addon-manager-additional-documentation.txt">VAM documentation</a> for details).
|
||||
</p>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
<DIV class="">
|
||||
<H3><A name="Functions" id="Functions">Functions</A></H3>
|
||||
<SPAN class="link_button" id="link-Functions__button" name="link-Functions__button"><A href="?showone=Functions#Functions">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Functions')" name="Functions__button" id="Functions__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">
|
||||
In the autoload/ directory, defined with <code>[!]</code> and
|
||||
<code>[abort]</code>.
|
||||
</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Functions__body" id="Functions__body" style="display: none">
|
||||
<p>
|
||||
Autoloading allows functions to be loaded on demand, which makes
|
||||
startuptime faster and enforces function namespacing.
|
||||
</p>
|
||||
<p>
|
||||
Script-local functions are welcome, but should also live in autoload/
|
||||
and be called by autoloaded functions.
|
||||
</p>
|
||||
<p>
|
||||
Non-library plugins should expose commands instead of functions.
|
||||
Command logic should be extracted into functions and autoloaded.
|
||||
</p>
|
||||
<p>
|
||||
<code>[!]</code> allows developers to reload their functions
|
||||
without complaint.
|
||||
</p>
|
||||
<p>
|
||||
<code>[abort]</code> forces the function to halt when it encounters
|
||||
an error.
|
||||
</p>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
<DIV class="">
|
||||
<H3><A name="Commands" id="Commands">Commands</A></H3>
|
||||
<SPAN class="link_button" id="link-Commands__button" name="link-Commands__button"><A href="?showone=Commands#Commands">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Commands')" name="Commands__button" id="Commands__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">
|
||||
In the plugin/commands.vim or under the ftplugin/ directory, defined
|
||||
without <code>[!]</code>.
|
||||
</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Commands__body" id="Commands__body" style="display: none">
|
||||
<p>
|
||||
General commands go in <code>plugin/commands.vim</code>.
|
||||
Filetype-specific commands go in <code>ftplugin/</code>.
|
||||
</p>
|
||||
<p>
|
||||
Excluding <code>[!]</code> prevents your plugin from silently
|
||||
clobbering existing commands. Command conflicts should be resolved by
|
||||
the user.
|
||||
</p>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
<DIV class="">
|
||||
<H3><A name="Autocommands" id="Autocommands">Autocommands</A></H3>
|
||||
<SPAN class="link_button" id="link-Autocommands__button" name="link-Autocommands__button"><A href="?showone=Autocommands#Autocommands">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Autocommands')" name="Autocommands__button" id="Autocommands__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">
|
||||
Place them in plugin/autocmds.vim, within augroups.
|
||||
</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Autocommands__body" id="Autocommands__body" style="display: none">
|
||||
<p>
|
||||
Place all autocommands in augroups.
|
||||
</p>
|
||||
<p>
|
||||
The augroup name should be unique. It should either be, or be prefixed
|
||||
with, the plugin name.
|
||||
</p>
|
||||
<p>
|
||||
Clear the augroup with <code>autocmd!</code> before defining new
|
||||
autocommands in the augroup. This makes your plugin re-entrable.
|
||||
</p>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
<DIV class="">
|
||||
<H3><A name="Mappings" id="Mappings">Mappings</A></H3>
|
||||
<SPAN class="link_button" id="link-Mappings__button" name="link-Mappings__button"><A href="?showone=Mappings#Mappings">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Mappings')" name="Mappings__button" id="Mappings__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">
|
||||
Place them in <code>plugin/mappings.vim</code>, using
|
||||
<code>maktaba#plugin#MapPrefix</code> to get a prefix.
|
||||
</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Mappings__body" id="Mappings__body" style="display: none">
|
||||
<p>
|
||||
All key mappings should be defined in
|
||||
<code>plugin/mappings.vim</code>.
|
||||
</p>
|
||||
<p>
|
||||
Partial mappings (see :help using-<Plug>.) should be defined in
|
||||
<code>plugin/plugs.vim</code>.
|
||||
</p>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
<DIV class="">
|
||||
<H3><A name="Settings" id="Settings">Settings</A></H3>
|
||||
<SPAN class="link_button" id="link-Settings__button" name="link-Settings__button"><A href="?showone=Settings#Settings">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Settings')" name="Settings__button" id="Settings__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">Change settings locally</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Settings__body" id="Settings__body" style="display: none">
|
||||
<p>
|
||||
Use <code>:setlocal</code> and <code>&l:</code> instead of
|
||||
<code>:set</code> and <code>&</code> unless you have explicit
|
||||
reason to do otherwise.
|
||||
</p>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
</DIV>
|
||||
|
||||
<DIV class="">
|
||||
<H2 name="Style" id="Style">Style</H2>
|
||||
<p>
|
||||
Follow google style conventions. When in doubt, treat vimscript style
|
||||
like python style.
|
||||
</p>
|
||||
|
||||
<DIV class="">
|
||||
<H3><A name="Whitespace" id="Whitespace">Whitespace</A></H3>
|
||||
<SPAN class="link_button" id="link-Whitespace__button" name="link-Whitespace__button"><A href="?showone=Whitespace#Whitespace">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Whitespace')" name="Whitespace__button" id="Whitespace__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">
|
||||
Similar to python.
|
||||
|
||||
<br>
|
||||
<br>
|
||||
</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Whitespace__body" id="Whitespace__body" style="display: none">
|
||||
<ul>
|
||||
<li>Use two spaces for indents</li>
|
||||
<li>Do not use tabs</li>
|
||||
<li>Use spaces around operators
|
||||
<p>This does not apply to arguments to commands.</p>
|
||||
<DIV class=""><PRE>let s:variable = "concatenated " . "strings"
|
||||
command -range=% MyCommand</PRE></DIV>
|
||||
</li>
|
||||
<li>Do not introduce trailing whitespace
|
||||
<p>You need not go out of your way to remove it.</p>
|
||||
<p>
|
||||
Trailing whitespace is allowed in mappings which prep commands
|
||||
for user input, such as
|
||||
"<code>noremap <leader>gf :grep -f </code>".
|
||||
</p>
|
||||
</li>
|
||||
<li>Restrict lines to 80 columns wide</li>
|
||||
<li>Indent continued lines by four spaces</li>
|
||||
<li>Do not align arguments of commands
|
||||
<DIV class=""><PRE class="badcode">command -bang MyCommand call myplugin#foo()
|
||||
command MyCommand2 call myplugin#bar()</PRE></DIV>
|
||||
<DIV class=""><PRE>command -bang MyCommand call myplugin#foo()
|
||||
command MyCommand2 call myplugin#bar()</PRE></DIV>
|
||||
</li>
|
||||
</ul>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
|
||||
<DIV class="">
|
||||
<H3><A name="Naming" id="Naming">Naming</A></H3>
|
||||
<SPAN class="link_button" id="link-Naming__button" name="link-Naming__button"><A href="?showone=Naming#Naming">
|
||||
link
|
||||
</A></SPAN><SPAN class="showhide_button" onclick="javascript:ShowHideByName('Naming')" name="Naming__button" id="Naming__button">▶</SPAN>
|
||||
<DIV style="display:inline;" class="">
|
||||
<p>
|
||||
In general, use
|
||||
<code>plugin-names-like-this</code>,
|
||||
<code>FunctionNamesLikeThis</code>,
|
||||
<code>CommandNamesLikeThis</code>,
|
||||
<code>augroup_names_like_this</code>,
|
||||
<code>variable_names_like_this</code>.
|
||||
</p>
|
||||
<p>Always prefix variables with their scope.</p>
|
||||
</DIV>
|
||||
<DIV class=""><DIV class="stylepoint_body" name="Naming__body" id="Naming__body" style="display: none">
|
||||
<P class="">
|
||||
<SPAN class="stylepoint_subsection">plugin-names-like-this</SPAN>
|
||||
<p>Keep them short and sweet.</p>
|
||||
|
||||
</P>
|
||||
<P class="">
|
||||
<SPAN class="stylepoint_subsection">FunctionNamesLikeThis</SPAN>
|
||||
<p>Prefix script-local functions with <code>s:</code></p>
|
||||
<p>Autoloaded functions may not have a scope prefix.</p>
|
||||
<p>
|
||||
Do not create global functions. Use autoloaded functions
|
||||
instead.
|
||||
</p>
|
||||
</P>
|
||||
<P class="">
|
||||
<SPAN class="stylepoint_subsection">CommandNamesLikeThis</SPAN>
|
||||
<p>Prefer succinct command names over common command prefixes.</p>
|
||||
</P>
|
||||
<P class="">
|
||||
<SPAN class="stylepoint_subsection">variable_names_like_this</SPAN>
|
||||
<p>Augroup names count as variables for naming purposes.</p>
|
||||
</P>
|
||||
<P class="">
|
||||
<SPAN class="stylepoint_subsection">Prefix all variables with their scope.</SPAN>
|
||||
<ul>
|
||||
<li>Global variables with <code>g:</code>
|
||||
</li>
|
||||
<li>Script-local variables with <code>s:</code>
|
||||
</li>
|
||||
<li>Function arguments with <code>a:</code>
|
||||
</li>
|
||||
<li>Function-local variables with <code>l:</code>
|
||||
</li>
|
||||
<li>Vim-predefined variables with <code>v:</code>
|
||||
</li>
|
||||
<li>Buffer-local variables with <code>b:</code>
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
<code>g:</code>, <code>s:</code>, and <code>a:</code> must always
|
||||
be used.
|
||||
</p>
|
||||
<p>
|
||||
<code>b:</code> changes the variable semantics; use it when you
|
||||
want buffer-local semantics.
|
||||
</p>
|
||||
<p>
|
||||
<code>l:</code> and <code>v:</code> 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.
|
||||
</p>
|
||||
</P>
|
||||
</DIV></DIV>
|
||||
</DIV>
|
||||
</DIV>
|
||||
|
||||
<p align="right">
|
||||
Revision 1.1
|
||||
</p>
|
||||
|
||||
|
||||
<address>
|
||||
Nate Soares<br>
|
||||
Artemis Sparks<br>
|
||||
David Barnett<br>
|
||||
</address>
|
||||
</BODY>
|
||||
</HTML>
|
||||
@@ -0,0 +1,331 @@
|
||||
# Google Vimscript Style Guide
|
||||
|
||||
* Nate Soares
|
||||
* Artemis Sparks
|
||||
* David Barnett
|
||||
|
||||
<!-- mdformat on -->
|
||||
|
||||
## Background
|
||||
|
||||
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](./vimscriptfull.md).
|
||||
|
||||
## Portability
|
||||
|
||||
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.
|
||||
|
||||
### Strings
|
||||
|
||||
|
||||
Prefer single quoted strings
|
||||
|
||||
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 `"\n"`) or
|
||||
if you know it doesn't matter and you need to embed single quotes.
|
||||
|
||||
|
||||
### Matching Strings
|
||||
|
||||
|
||||
Use the `=~#` or `=~?` operator families over the `=~` family.
|
||||
|
||||
The matching behavior depends upon the user's ignorecase and smartcase settings
|
||||
and on whether you compare them with the `=~`, `=~#`, 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.
|
||||
|
||||
|
||||
### Regular Expressions
|
||||
|
||||
|
||||
Prefix all regexes with `\m\C`.
|
||||
|
||||
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 `\m\C`.
|
||||
|
||||
You are welcome to use other magic levels (`\v`) and case sensitivities (`\c`)
|
||||
so long as they are intentional and explicit.
|
||||
|
||||
|
||||
### Dangerous commands
|
||||
|
||||
|
||||
Avoid commands with unintended side effects.
|
||||
|
||||
Avoid using `:s[ubstitute]` as it moves the cursor and prints error messages.
|
||||
Prefer functions (such as `search()`) better suited to scripts.
|
||||
|
||||
For many vim commands, functions exist that do the same thing with fewer side
|
||||
effects. See `:help functions()` for a list of built-in functions.
|
||||
|
||||
|
||||
### Fragile commands
|
||||
|
||||
|
||||
Avoid commands that rely on user settings.
|
||||
|
||||
Always use `normal!` instead of `normal`. The latter depends upon the user's key
|
||||
mappings and could do anything.
|
||||
|
||||
Avoid `:s[ubstitute]`, as its behavior depends upon a number of local settings.
|
||||
|
||||
The same applies to other commands not listed here.
|
||||
|
||||
|
||||
### Catching Exceptions
|
||||
|
||||
|
||||
Match error codes, not error text.
|
||||
|
||||
Error text may be locale dependant.
|
||||
|
||||
|
||||
## General Guidelines
|
||||
|
||||
### Messaging
|
||||
|
||||
|
||||
Message the user infrequently.
|
||||
|
||||
Loud scripts are annoying. Message the user only when:
|
||||
|
||||
* A long-running process has kicked off.
|
||||
* An error has occurred.
|
||||
|
||||
|
||||
|
||||
### 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.
|
||||
|
||||
|
||||
### Python
|
||||
|
||||
|
||||
Use sparingly.
|
||||
|
||||
Use python only when it provides critical functionality, for example when
|
||||
writing threaded code.
|
||||
|
||||
|
||||
### Other Languages
|
||||
|
||||
|
||||
Use vimscript instead.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
### Boilerplate
|
||||
|
||||
|
||||
Use [maktaba](https://github.com/google/maktaba).
|
||||
|
||||
maktaba removes boilerplate, including:
|
||||
|
||||
* Plugin creation
|
||||
* Error handling
|
||||
* Dependency checking
|
||||
|
||||
|
||||
|
||||
### Plugin layout
|
||||
|
||||
|
||||
Organize functionality into modular plugins
|
||||
|
||||
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](http://goo.gl/CUXJZC) for
|
||||
details).
|
||||
|
||||
|
||||
### Functions
|
||||
|
||||
|
||||
In the autoload/ directory, defined with `[!]` 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.
|
||||
|
||||
|
||||
### Commands
|
||||
|
||||
|
||||
In the plugin/commands.vim or under the ftplugin/ directory, defined without `[!]`.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
### Autocommands
|
||||
|
||||
|
||||
Place them in `plugin/autocmds.vim`, within augroups.
|
||||
|
||||
Place all autocommands in augroups.
|
||||
|
||||
The augroup name should be unique. It should either be the plugin name 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.
|
||||
|
||||
|
||||
### Mappings
|
||||
|
||||
|
||||
Place them in `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`.
|
||||
|
||||
|
||||
### Settings
|
||||
|
||||
|
||||
Change settings locally
|
||||
|
||||
Use `:setlocal` and `&l:` instead of `:set` and `&` unless you have explicit
|
||||
reason to do otherwise.
|
||||
|
||||
|
||||
## Style
|
||||
|
||||
Follow google style conventions. When in doubt, treat vimscript style like
|
||||
python style.
|
||||
|
||||
### Whitespace
|
||||
|
||||
|
||||
Similar to python.
|
||||
|
||||
* Use two spaces for indents
|
||||
* Do not use tabs
|
||||
* Use spaces around operators
|
||||
|
||||
This does not apply to arguments to commands.
|
||||
|
||||
```
|
||||
let s:variable = 'concatenated ' . 'strings'
|
||||
command -range=% MyCommand
|
||||
```
|
||||
|
||||
* Do not introduce trailing whitespace
|
||||
|
||||
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`.
|
||||
|
||||
* Restrict lines to 80 columns wide
|
||||
|
||||
* Indent continued lines by four spaces
|
||||
|
||||
```
|
||||
let l:something = SomeReallyLongFunctionName(
|
||||
\ 'arg1', 0, ['XXXXX'], {'somekey': 9999999999})
|
||||
```
|
||||
|
||||
* Do not align arguments of commands
|
||||
|
||||
```
|
||||
command -bang MyCommand call myplugin#foo()
|
||||
command MyCommand2 call myplugin#bar()
|
||||
```
|
||||
|
||||
```
|
||||
command -bang MyCommand call myplugin#foo()
|
||||
command MyCommand2 call myplugin#bar()
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Naming
|
||||
|
||||
|
||||
In general, use `plugin-names-like-this`, `FunctionNamesLikeThis`,
|
||||
`CommandNamesLikeThis`, `augroup_names_like_this`, `variable_names_like_this`.
|
||||
Always prefix variables with their scope.
|
||||
|
||||
#### plugin-names-like-this
|
||||
|
||||
Keep them short and sweet.
|
||||
|
||||
#### FunctionNamesLikeThis
|
||||
|
||||
Prefix script-local functions with `s:`
|
||||
|
||||
Autoloaded functions may not have a scope prefix.
|
||||
|
||||
Do not create global functions. Use autoloaded functions instead.
|
||||
|
||||
#### CommandNamesLikeThis
|
||||
|
||||
Prefer succinct command names over common command prefixes.
|
||||
|
||||
#### variable_names_like_this
|
||||
|
||||
Augroup names count as variables for naming purposes.
|
||||
|
||||
#### Prefix all variables with their scope.
|
||||
|
||||
* Global variables with `g:`
|
||||
* Script-local variables with `s:`
|
||||
* Function arguments with `a:`
|
||||
* Function-local variables with `l:`
|
||||
* Vim-predefined variables with `v:`
|
||||
* Buffer-local or window-local variables with `b:` or `w:`
|
||||
|
||||
`g:`, `s:`, and `a:` must always be used.
|
||||
|
||||
`b:` and `w:` change the variable semantics; use them when you want buffer- or
|
||||
window-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.
|
||||
|
||||
Reference in new issue
Block a user