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