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>
<CATEGORYtitle="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 <ahref="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><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>
<SUBSECTIONtitle="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>
<STYLEPOINTtitle="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>
<STYLEPOINTtitle="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>
<STYLEPOINTtitle="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>
<CATEGORYtitle="Conventions">
<STYLEPOINTtitle="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
<ahref="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>
<STYLEPOINTtitle="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.).