From b3cc1ed6cc0b69eed8c8ff7d8506aa4b8c1827e5 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 24 Sep 2026 15:46:50 -0400 Subject: [PATCH] vim: switch to markdown --- README.md | 2 +- vimscriptfull.html | 1775 ------------------------------------------- vimscriptfull.md | 843 ++++++++++++++++++++ vimscriptguide.html | 662 ---------------- vimscriptguide.md | 331 ++++++++ 5 files changed, 1175 insertions(+), 2438 deletions(-) delete mode 100644 vimscriptfull.html create mode 100644 vimscriptfull.md delete mode 100644 vimscriptguide.html create mode 100644 vimscriptguide.md diff --git a/README.md b/README.md index 97f7653..7f850aa 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/vimscriptfull.html b/vimscriptfull.html deleted file mode 100644 index 511fb09..0000000 --- a/vimscriptfull.html +++ /dev/null @@ -1,1775 +0,0 @@ - - -Google Vimscript Guide - - - - - - -

Google Vimscript Guide

-

- - Revision 1.1 -

- - -
- Nate Soares
- Artemis Sparks
- David Barnett
-
- -
-

- Each style point has a summary for which additional information is available - by toggling the accompanying arrow button that looks this way: - ▶. - You may toggle all summaries with the big arrow button: -

-
-▶ - Toggle all summaries -
-
-
-
Table of Contents
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-

Background

-

- This is the in-depth vimscript guide. If you're just a casual user - looking to write a plugin, the - abbreviated style guide is for you. -

-

- This rather rotund guide dives into justifications and clarifications. - It provides an idealized set of rules that are rather too draconian to - push on casual scripters. -

- -

- It's for users who want to know why certain decisions were made in the - abbreviated guide and who want to learn a thing or two about using - vimscript safely. -

-

- Fair warning: Vimscript is a maddening abyss. When you gaze into it, it - gazes also into you. Proceed with caution. -

-
- - -
-

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: -

- -

- In general, guard all commands and functions against user settings. -

- -
-
-

Language Guide

- -

- All other language features are fair game. -

-
-
-

Structure

- - -
-

Libraries vs. Functionality

- - link - ▶ -
- Separate library-providing plugins from command-providing plugins. -
-
-
- -
-

Configuration

- - link - ▶ -
- Don't clobber user settings. Provide as much configurability as - possible: that's what Vim's all about. -
-
-
-
-
-

Style Guide

-

- Follow google-wide style conventions. Mimic google python style when - in doubt. -

- - - -
-

Documentation

- - link - ▶ -
- Use vimdoc. -
-
-
- -
-

Whitespace

- - link - ▶ -
- Follow google-wide conventions. -
-
-
- -
-

Variables

- - link - ▶ -
-

- plugin-names-like-this, - FunctionNamesLikeThis, - CommandNamesLikeThis, - augroup_names_like_this, - variable_names_like_this. -

-

- Prefix all variables with their scope. -

-
-
-
- -
-

Strings

- - link - ▶ -
- Prefer single quotes. -
-
-
- -
-

Settings

- - link - ▶ -
- Prefer long names. Set settings locally. -
-
-
-
-
-

Usage Guide

-

- Vim plugins should provide any or all of the following: - Commands, Autocommands, - Functions, Statusline Flags, and - Mappings. -

- -
-

Commands

- - link - ▶ -
-
    -
  • Define in plugin/commands.vim.
  • -
  • CommandNamesLikeThis.
  • -
  • Prefer semantic names to a unified prefix.
  • -
  • Do not use [!] -
  • -
  • Extract logic into functions.
  • -
-
-
-
- -
-

Autocommands

- - link - ▶ -
-
    -
  • Define in plugin/autocmds.vim.
  • -
  • Use augroups.
  • -
  • augroup_names_like_this.
  • -
  • Clear the augroup first.
  • -
  • Extract logic into functions.
  • -
-
-
-
- -
-

Functions

- - link - ▶ -
-
    -
  • FunctionNamesLikeThis.
  • -
  • Autoload all functions.
  • -
  • Prefix script-local functions with s: -
  • -
  • Use [!].
  • -
  • Use [abort].
  • -
-
-
-
- -
-

Mappings

- - link - ▶ -
-
    -
  • - 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). -
  • -
-
-
-
-
-
-

Conventions

-
-

Dependency Checking

- - link - ▶ -
- Declare dependencies in addon-info.json and use maktaba. -
-
-
- -
-

Statusline Flags

- - link - ▶ -
- Use <plugin-name>#status#Status() or its - finer-grained variants to provide statusline flags. -
-
-
-
-
-

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. -

- -
-
-

Layout

-

- Lay out plugin/ files in the following sections, if - applicable, separated by two blank lines: -

- -

- Lay out autoload/ files in the following sections, if - applicable, separated by two blank lines: -

- -

- This is recommended convention and is not enforced. -

- -
-
- - -

- Use the following shortcuts: -

- - -
-
-

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

- - link - ▶ -
- If you don't support vi-compatibility mode, fail gracefully. -
-
-
-
- -

- Revision 1.1 -

- - -
- Nate Soares
- Artemis Sparks
- David Barnett
-
- - diff --git a/vimscriptfull.md b/vimscriptfull.md new file mode 100644 index 0000000..9178388 --- /dev/null +++ b/vimscriptfull.md @@ -0,0 +1,843 @@ +# Google Vimscript Guide + +* Nate Soares +* Artemis Sparks +* David Barnett + + + +## 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(':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. + + + +* 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 + \ 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 (``, ``, etc.) + before argument parameters (``, 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 `` to functions with `'' == '!'`. + + * 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`. +* `` 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 ``. + + * This will inform the user when they have a mapping conflict instead of + silently clobbering their existing mappings. + +* You may provide pseudo-mappings using `` and your plugin's name in + `plugin/plugs.vim` (separate from standard key mappings). + + * `` is a sequence which can not be typed. + * You can do something like `noremap namespace#MappingName + some_key_sequence` and then users can do `noremap x + 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 `` 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 `` 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 `#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 + `#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 `#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. + diff --git a/vimscriptguide.html b/vimscriptguide.html deleted file mode 100644 index 3fc0457..0000000 --- a/vimscriptguide.html +++ /dev/null @@ -1,662 +0,0 @@ - - -Google Vimscript Style Guide - - - - - - -

Google Vimscript Style Guide

-

- - Revision 1.1 -

- - -
- Nate Soares
- Artemis Sparks
- David Barnett
-
- -
-

- Each style point has a summary for which additional information is available - by toggling the accompanying arrow button that looks this way: - ▶. - You may toggle all summaries with the big arrow button: -

-
-▶ - Toggle all summaries -
-
- -
-

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. -

-
- - -
-

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

- - link - ▶ -
Prefer single quoted strings
-
-
-
-

Matching Strings

- - link - ▶ -
- Use the =~# or =~? operator families over the - =~ family. -
-
-
-
-

Regular Expressions

- - link - ▶ -
Prefix all regexes with \m\C.
-
-
-
-

Dangerous commands

- - link - ▶ -
Avoid commands with unintended side effects.
-
-
-
-

Fragile commands

- - link - ▶ -
Avoid commands that rely on user settings.
-
-
-
-

Catching Exceptions

- - link - ▶ -
Match error codes, not error text.
-
-
-
- -
-

General Guidelines

- - -
-

Messaging

- - link - ▶ -
Message the user infrequently.
-
-
-
-

Type checking

- - link - ▶ -
Use strict and explicit checks where possible.
-
-
-
-

Python

- - link - ▶ -
Use sparingly.
-
-
-
-

Other Languages

- - link - ▶ -
Use vimscript instead.
-
-
-
-

Boilerplate

- - link - ▶ -
- Use maktaba. -
-
-
-
-

Plugin layout

- - link - ▶ -
Organize functionality into modular plugins
-
-
-
-

Functions

- - link - ▶ -
- In the autoload/ directory, defined with [!] and - [abort]. -
-
-
-
-

Commands

- - link - ▶ -
- In the plugin/commands.vim or under the ftplugin/ directory, defined - without [!]. -
-
-
-
-

Autocommands

- - link - ▶ -
- Place them in plugin/autocmds.vim, within augroups. -
-
-
-
-

Mappings

- - link - ▶ -
- Place them in plugin/mappings.vim, using - maktaba#plugin#MapPrefix to get a prefix. -
-
-
-
-

Settings

- - link - ▶ -
Change settings locally
-
-
-
- -
-

Style

-

- Follow google style conventions. When in doubt, treat vimscript style - like python style. -

- -
-

Whitespace

- - link - ▶ -
- Similar to python. - -
-
-
-
-
- -
-

Naming

- - link - ▶ -
-

- In general, use - plugin-names-like-this, - FunctionNamesLikeThis, - CommandNamesLikeThis, - augroup_names_like_this, - variable_names_like_this. -

-

Always prefix variables with their scope.

-
-
-
-
- -

- Revision 1.1 -

- - -
- Nate Soares
- Artemis Sparks
- David Barnett
-
- - diff --git a/vimscriptguide.md b/vimscriptguide.md new file mode 100644 index 0000000..be32431 --- /dev/null +++ b/vimscriptguide.md @@ -0,0 +1,331 @@ +# Google Vimscript Style Guide + +* Nate Soares +* Artemis Sparks +* David Barnett + + + +## 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-`.) 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 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. +