| # 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). | |
| <!-- mdformat off --> | |
| * TOC | |
| {:toc} | |
| <!-- mdformat on --> | |
| ## 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 function-list` 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](https://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. | |
| <div class='goodcode'></div> | |
| ``` | |
| 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 | |
| <div class='goodcode'></div> | |
| ``` | |
| let l:something = SomeReallyLongFunctionName( | |
| \ 'arg1', 0, ['XXXXX'], {'somekey': 9999999999}) | |
| ``` | |
| * Do not align arguments of commands | |
| <div class='badcode'></div> | |
| ``` | |
| command -bang MyCommand call myplugin#foo() | |
| command MyCommand2 call myplugin#bar() | |
| ``` | |
| <div class='goodcode'></div> | |
| ``` | |
| 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. |