mirror of
https://github.com/google/styleguide.git
synced 2024-03-22 13:11:43 +08:00
413 lines
14 KiB
XML
413 lines
14 KiB
XML
|
<?xml version = '1.0'?>
|
|||
|
<?xml-stylesheet type="text/xsl" href="styleguide.xsl"?>
|
|||
|
<GUIDE title="Google Vimscript Style 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 a casual version of the vimscript style guide, because
|
|||
|
vimscript is a casual language. When submitting vim plugin code, you
|
|||
|
must adhere to these rules. For clarifications, justifications, and
|
|||
|
explanations about the finer points of vimscript, please refer to the
|
|||
|
<a href="vimscriptfull.xml">heavy guide</a>.
|
|||
|
</p>
|
|||
|
</CATEGORY>
|
|||
|
</OVERVIEW>
|
|||
|
|
|||
|
<CATEGORY title="Portability">
|
|||
|
<p>
|
|||
|
It's hard to get vimscript right. Many commands depend upon the user's
|
|||
|
settings. By following these guidelines, you can hope to make your
|
|||
|
scripts portable.
|
|||
|
</p>
|
|||
|
<STYLEPOINT title="Strings">
|
|||
|
<SUMMARY>Prefer single quoted strings</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<p>
|
|||
|
Double quoted strings are semantically different in vimscript, and
|
|||
|
you probably don't want them (they break regexes).
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
Use double quoted strings when you need an escape sequence (such as
|
|||
|
<code>"\n"</code>) or if you know it doesn't matter and you need to
|
|||
|
embed single quotes.
|
|||
|
</p>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
<STYLEPOINT title="Matching Strings">
|
|||
|
<SUMMARY>
|
|||
|
Use the <code>=~#</code> or <code>=~?</code> operator families over the
|
|||
|
<code>=~</code> family.
|
|||
|
</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<p>
|
|||
|
The matching behavior depends upon the user's ignorecase and smartcase
|
|||
|
settings and on whether you compare them with the <code>=~</code>,
|
|||
|
<code>=~#</code>, or <code>=~?</code> family of operators. Use the
|
|||
|
<code>=~#</code> and <code>=~?</code> operator families explicitly
|
|||
|
when comparing strings unless you explicitly need to honor the user's
|
|||
|
case sensitivity settings.
|
|||
|
</p>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
<STYLEPOINT title="Regular Expressions">
|
|||
|
<SUMMARY>Prefix all regexes with <code>\m\C</code>.</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<p>
|
|||
|
In addition to the case sensitivity settings, regex behavior depends
|
|||
|
upon the user's nomagic setting. To make regexes act like nomagic and
|
|||
|
noignorecase are set, prepend all regexes with <code>\m\C</code>.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
You are welcome to use other magic levels (<code>\v</code>) and case
|
|||
|
sensitivities (<code>\c</code>) so long as they are intentional and
|
|||
|
explicit.
|
|||
|
</p>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
<STYLEPOINT title="Dangerous commands">
|
|||
|
<SUMMARY>Avoid commands with unintended side effects.</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<p>
|
|||
|
Avoid using <code>:s[ubstitute]</code> as it moves the cursor and
|
|||
|
prints error messages. Prefer functions (such as
|
|||
|
<code>search()</code>) better suited to scripts.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
For many vim commands, functions exist that do the same thing with
|
|||
|
fewer side effects. See <code>:help functions()</code> for a list of
|
|||
|
built-in functions.
|
|||
|
</p>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
<STYLEPOINT title="Fragile commands">
|
|||
|
<SUMMARY>Avoid commands that rely on user settings.</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<p>
|
|||
|
Always use <code>normal!</code> instead of <code>normal</code>. The
|
|||
|
latter depends upon the user's key mappings and could do anything.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
Avoid <code>:s[ubstitute]</code>, as its behavior depends upon a
|
|||
|
number of local settings.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
The same applies to other commands not listed here.
|
|||
|
</p>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
<STYLEPOINT title="Catching Exceptions">
|
|||
|
<SUMMARY>Match error codes, not error text.</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<p>Error text may be locale dependant.</p>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
</CATEGORY>
|
|||
|
|
|||
|
<CATEGORY title="General Guidelines">
|
|||
|
|
|||
|
|
|||
|
<STYLEPOINT title="Messaging">
|
|||
|
<SUMMARY>Message the user infrequently.</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<p>
|
|||
|
Loud scripts are annoying. Message the user only when:
|
|||
|
<ul>
|
|||
|
<li>A long-running process has kicked off.</li>
|
|||
|
<li>An error has occurred.</li>
|
|||
|
</ul>
|
|||
|
</p>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
<STYLEPOINT title="Type checking">
|
|||
|
<SUMMARY>Use strict and explicit checks where possible.</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<p>
|
|||
|
Vimscript has unsafe, unintuitive behavior when dealing with some
|
|||
|
types. For instance, <code>0 == 'foo'</code> evaluates to true.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
Use strict comparison operators where possible. When comparing against
|
|||
|
a string literal, use the <code>is#</code> operator. Otherwise, prefer
|
|||
|
<code>maktaba#value#IsEqual</code> or check <code>type()</code>
|
|||
|
explicitly.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
Check variable types explicitly before using them. Use functions from
|
|||
|
<code>maktaba#ensure</code>, or check <code>maktaba#value</code> or
|
|||
|
<code>type()</code> and throw your own errors.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
Use <code>:unlet</code> for variables that may change types,
|
|||
|
particularly those assigned inside loops.
|
|||
|
</p>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
<STYLEPOINT title="Python">
|
|||
|
<SUMMARY>Use sparingly.</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<p>
|
|||
|
Use python only when it provides critical functionality, for example
|
|||
|
when writing threaded code.
|
|||
|
</p>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
<STYLEPOINT title="Other Languages">
|
|||
|
<SUMMARY>Use vimscript instead.</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<p>
|
|||
|
Avoid using other scripting languages such as ruby and lua. We can
|
|||
|
not guarantee that the end user's vim has been compiled with support
|
|||
|
for non-vimscript languages.
|
|||
|
</p>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
<STYLEPOINT title="Boilerplate">
|
|||
|
<SUMMARY>
|
|||
|
Use <a href="https://github.com/google/maktaba">maktaba</a>.
|
|||
|
</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<p>
|
|||
|
maktaba removes boilerplate, including:
|
|||
|
<ul>
|
|||
|
<li>Plugin creation</li>
|
|||
|
<li>Error handling</li>
|
|||
|
<li>Dependency checking</li>
|
|||
|
</ul>
|
|||
|
</p>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
<STYLEPOINT title="Plugin layout">
|
|||
|
<SUMMARY>Organize functionality into modular plugins</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<p>
|
|||
|
Group your functionality as a plugin, unified in one directory (or
|
|||
|
code repository) which shares your plugin's name (with a "vim-" prefix
|
|||
|
or ".vim" suffix if desired). It should be split into plugin/,
|
|||
|
autoload/, etc. subdirectories as necessary, and it should declare
|
|||
|
metadata in the addon-info.json format (see the
|
|||
|
<a href="https://github.com/MarcWeber/vim-addon-manager/blob/master/doc/vim-addon-manager-additional-documentation.txt">VAM documentation</a> for details).
|
|||
|
</p>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
<STYLEPOINT title="Functions">
|
|||
|
<SUMMARY>
|
|||
|
In the autoload/ directory, defined with <code>[!]</code> and
|
|||
|
<code>[abort]</code>.
|
|||
|
</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<p>
|
|||
|
Autoloading allows functions to be loaded on demand, which makes
|
|||
|
startuptime faster and enforces function namespacing.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
Script-local functions are welcome, but should also live in autoload/
|
|||
|
and be called by autoloaded functions.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
Non-library plugins should expose commands instead of functions.
|
|||
|
Command logic should be extracted into functions and autoloaded.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
<code>[!]</code> allows developers to reload their functions
|
|||
|
without complaint.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
<code>[abort]</code> forces the function to halt when it encounters
|
|||
|
an error.
|
|||
|
</p>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
<STYLEPOINT title="Commands">
|
|||
|
<SUMMARY>
|
|||
|
In the plugin/commands.vim or under the ftplugin/ directory, defined
|
|||
|
without <code>[!]</code>.
|
|||
|
</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<p>
|
|||
|
General commands go in <code>plugin/commands.vim</code>.
|
|||
|
Filetype-specific commands go in <code>ftplugin/</code>.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
Excluding <code>[!]</code> prevents your plugin from silently
|
|||
|
clobbering existing commands. Command conflicts should be resolved by
|
|||
|
the user.
|
|||
|
</p>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
<STYLEPOINT title="Autocommands">
|
|||
|
<SUMMARY>
|
|||
|
Place them in plugin/autocmds.vim, within augroups.
|
|||
|
</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<p>
|
|||
|
Place all autocommands in augroups.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
The augroup name should be unique. It should either be, or be prefixed
|
|||
|
with, the plugin name.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
Clear the augroup with <code>autocmd!</code> before defining new
|
|||
|
autocommands in the augroup. This makes your plugin re-entrable.
|
|||
|
</p>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
<STYLEPOINT title="Mappings">
|
|||
|
<SUMMARY>
|
|||
|
Place them in <code>plugin/mappings.vim</code>, using
|
|||
|
<code>maktaba#plugin#MapPrefix</code> to get a prefix.
|
|||
|
</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<p>
|
|||
|
All key mappings should be defined in
|
|||
|
<code>plugin/mappings.vim</code>.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
Partial mappings (see :help using-<Plug>.) should be defined in
|
|||
|
<code>plugin/plugs.vim</code>.
|
|||
|
</p>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
<STYLEPOINT title="Settings">
|
|||
|
<SUMMARY>Change settings locally</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<p>
|
|||
|
Use <code>:setlocal</code> and <code>&l:</code> instead of
|
|||
|
<code>:set</code> and <code>&</code> unless you have explicit
|
|||
|
reason to do otherwise.
|
|||
|
</p>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
</CATEGORY>
|
|||
|
|
|||
|
<CATEGORY title="Style">
|
|||
|
<p>
|
|||
|
Follow google style conventions. When in doubt, treat vimscript style
|
|||
|
like python style.
|
|||
|
</p>
|
|||
|
|
|||
|
<STYLEPOINT title="Whitespace">
|
|||
|
<SUMMARY>
|
|||
|
Similar to python.
|
|||
|
|
|||
|
<br/>
|
|||
|
<br/>
|
|||
|
</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<ul>
|
|||
|
<li>Use two spaces for indents</li>
|
|||
|
<li>Do not use tabs</li>
|
|||
|
<li>Use spaces around operators
|
|||
|
<p>This does not apply to arguments to commands.</p>
|
|||
|
<CODE_SNIPPET>
|
|||
|
let s:variable = "concatenated " . "strings"
|
|||
|
command -range=% MyCommand
|
|||
|
</CODE_SNIPPET>
|
|||
|
</li>
|
|||
|
<li>Do not introduce trailing whitespace
|
|||
|
<p>You need not go out of your way to remove it.</p>
|
|||
|
<p>
|
|||
|
Trailing whitespace is allowed in mappings which prep commands
|
|||
|
for user input, such as
|
|||
|
"<code>noremap <leader>gf :grep -f </code>".
|
|||
|
</p>
|
|||
|
</li>
|
|||
|
<li>Restrict lines to 80 columns wide</li>
|
|||
|
<li>Indent continued lines by four spaces</li>
|
|||
|
<li>Do not align arguments of commands
|
|||
|
<BAD_CODE_SNIPPET>
|
|||
|
command -bang MyCommand call myplugin#foo()
|
|||
|
command MyCommand2 call myplugin#bar()
|
|||
|
</BAD_CODE_SNIPPET>
|
|||
|
<CODE_SNIPPET>
|
|||
|
command -bang MyCommand call myplugin#foo()
|
|||
|
command MyCommand2 call myplugin#bar()
|
|||
|
</CODE_SNIPPET>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
|
|||
|
<STYLEPOINT title="Naming">
|
|||
|
<SUMMARY>
|
|||
|
<p>
|
|||
|
In general, use
|
|||
|
<code>plugin-names-like-this</code>,
|
|||
|
<code>FunctionNamesLikeThis</code>,
|
|||
|
<code>CommandNamesLikeThis</code>,
|
|||
|
<code>augroup_names_like_this</code>,
|
|||
|
<code>variable_names_like_this</code>.
|
|||
|
</p>
|
|||
|
<p>Always prefix variables with their scope.</p>
|
|||
|
</SUMMARY>
|
|||
|
<BODY>
|
|||
|
<SUBSECTION title="plugin-names-like-this">
|
|||
|
<p>Keep them short and sweet.</p>
|
|||
|
|
|||
|
</SUBSECTION>
|
|||
|
<SUBSECTION title="FunctionNamesLikeThis">
|
|||
|
<p>Prefix script-local functions with <code>s:</code></p>
|
|||
|
<p>Autoloaded functions may not have a scope prefix.</p>
|
|||
|
<p>
|
|||
|
Do not create global functions. Use autoloaded functions
|
|||
|
instead.
|
|||
|
</p>
|
|||
|
</SUBSECTION>
|
|||
|
<SUBSECTION title="CommandNamesLikeThis">
|
|||
|
<p>Prefer succinct command names over common command prefixes.</p>
|
|||
|
</SUBSECTION>
|
|||
|
<SUBSECTION title="variable_names_like_this">
|
|||
|
<p>Augroup names count as variables for naming purposes.</p>
|
|||
|
</SUBSECTION>
|
|||
|
<SUBSECTION title="Prefix all variables with their scope.">
|
|||
|
<ul>
|
|||
|
<li>Global variables with <code>g:</code></li>
|
|||
|
<li>Script-local variables with <code>s:</code></li>
|
|||
|
<li>Function arguments with <code>a:</code></li>
|
|||
|
<li>Function-local variables with <code>l:</code></li>
|
|||
|
<li>Vim-predefined variables with <code>v:</code></li>
|
|||
|
<li>Buffer-local variables with <code>b:</code></li>
|
|||
|
</ul>
|
|||
|
<p>
|
|||
|
<code>g:</code>, <code>s:</code>, and <code>a:</code> must always
|
|||
|
be used.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
<code>b:</code> changes the variable semantics; use it when you
|
|||
|
want buffer-local semantics.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
<code>l:</code> and <code>v:</code> should be used for consistency,
|
|||
|
future proofing, and to avoid subtle bugs. They are not strictly
|
|||
|
required. Add them in new code but don’t go out of your way to add
|
|||
|
them elsewhere.
|
|||
|
</p>
|
|||
|
</SUBSECTION>
|
|||
|
</BODY>
|
|||
|
</STYLEPOINT>
|
|||
|
</CATEGORY>
|
|||
|
|
|||
|
<p align="right">
|
|||
|
Revision 1.1
|
|||
|
</p>
|
|||
|
|
|||
|
|
|||
|
<address>
|
|||
|
Nate Soares<br/>
|
|||
|
Joshua Hoak<br/>
|
|||
|
David Barnett<br/>
|
|||
|
</address>
|
|||
|
</GUIDE>
|