A fork of the auto-pairs plugin for vim with more sensible auto-completion rules. This fork is currently only intended to be used by myself. If you want to know how to use the plugin, please read the original readme.
Since auto-pairing can be extremely subjective, if you are unsatisfied with your own auto-pairing configurations, I would suggest you read the survey below or here. Pick one of the plugins, make a fork and customize it to your liking. The issues listed below should be enough to get you started.
Of course, if you want to use
auto-pairs, the comments in my
auto-pairs.vim
might be helpful (search for Krasjet
).
With vim-plug
Plug 'Krasjet/auto.pairs'
Basic principles: auto-completion and jump should be as lazy as possible, because correcting one completion mistake would take more keystrokes than closing the pair manually.
- Only insert the closing pair if the next character is a space or a non-quote closing pair.
input: | s (press '(')
output: (|) s
input: |s (press '(')
output: (|s
input: (|) (press '(')
output: ((|))
input: (|) (press '[')
output: ([|])
input: '|' (press '[')
output: '[|'
All the quote characters can be set as a global variable g:AutoPairsQuoteClosingChar
or buffer variable b:AutoPairsQuoteClosingChar
.
let g:AutoPairsQuoteClosingChar = ['"', "'",'`']
let b:AutoPairsQuoteClosingChar = ['"', "'",'`']
If the next character of the cursor is any of these, auto-completion will be inhibited.
There is also variables g:AutoPairsNextCharWhitelist
and
b:AutoPairsNextCharWhitelist
to whitelist certain characters (or strings)
such that trigger the auto-completion when appeared as the next character.
let g:AutoPairsNextCharWhitelist = []
let b:AutoPairsNextCharWhitelist = ['.', ',']
If the next character(s) of the cursor is any of these, auto-completion will be
triggered. I usually would add .
and ,
to the whitelist for LaTeX and
markdown files.
In summary, auto-completion will only be triggered if
- the next character is a space
- or the next character is not from the closing pair of a quote
- or the next character is in the whitelist
- Do not search for the closing pair if spaces are in between
input: " | " (press '"')
output: " "| "
input: " |" (press '"')
output: " "|
- Only jump across the closing pair if pairs are balanced
input: (((|)) (press ')')
output: (((|)))
input: (((|))) (press ')')
output: ((()|))
- Do not complete the closing pair until pairs are balanced
input: ((|))) (press '(')
output: (((|)))
input: (((|))) (press '(')
output: ((((|))))
input: "str| (press '"')
output: "str"|
The balance check for single quote ('
) can be turned on or off using the variable
g:AutoPairsSingleQuoteBalanceCheck
and b:AutoPairsSingleQuoteBalanceCheck
let g:AutoPairsSingleQuoteBalanceCheck = 1
let b:AutoPairsSingleQuoteBalanceCheck = 0
It is turned on by default, but you might want to use ftplugin
or autocmd
to turn it off for text files (LaTeX, markdown, etc.). Consider
input: There's a '| (press "'")
// single quote balance check on
output: There's a ''|'
// single quote balance check off
output: There's a ''|
However, for code files,
input: ['a', |] (press "'")
// single quote balance check on
output: ['a', '|']
// single quote balance check off
output: ['a', '|]
The balance check for a opening pair can be turned off using
g:AutoPairsOpenBalanceBlacklist
and b:AutoPairsOpenBalanceBlacklist
let g:AutoPairsOpenBalanceBlacklist = []
let b:AutoPairsOpenBalanceBlacklist = ['{']
This is a temporary workaround for if-else
clause in C-like languages.
input: } else | (press '{')
// with open balance check off
output: } else {|}
// with open balance check on
output: } else {|
Nothing is in the blacklist by default, but you can use ftplugin
or autocmd
to turn off the open balance check for {
.
- The default value of
g:AutoPairsMultilineClose
has been changed to 0. If you want to enable it, set
let g:AutoPairsMultilineClose = 1
but be cautious that this fork might break it (and the fly mode, which is also disabled by default), but I haven't tested them, and I don't need them anyways.
More to be added when I encounter more problems.
The one I'm most familiar with, despite some minor annoyances. This is why
the fork is based on this plugin. However, this plugin has too many mappings
that I don't need, such as <M-e>
, <M-n>
, and the fly mode.
// settings
let g:AutoPairsMultilineClose = 0
// before character
input: |s (press '(')
output: (|)s
// inside quote
input: '|' (press '[')
output: '[|]'
// seach for closing pair
input: " | " (press '"')
output: " "|
// closing pair balance
input: (((|)) (press ')')
output: ((()|)
// open pair balance
input: ((|))) (press '(')
output: (((|))))
// open pair balance
input: "str| (press '"')
output: "str"|"
I would say I'm pretty impressed with the smart pairing of this plugin. You can
even set completion rules based on syntax groups. There are still some minor
issues, though. One issue is that I never got the g:pear_tree_smart_backspace
working. Also, if g:pear_tree_repeatable_expand
is enabled, the closing braces
will disappear after a line break, which can be quite annoying.
// settings
let g:pear_tree_smart_openers = 1
let g:pear_tree_smart_closers = 1
let g:pear_tree_smart_backspace = 1
let g:pear_tree_repeatable_expand = 0
// backspace (might be a bug in smart backspace)
input: (|) (press '<bs>')
output: |)
// open pair balance
input: ((|))) (press '(')
output: (((|))))
One of the biggest drawback is that this plugin has to be installed on top of coc.nvim, which can make your vimrc less portable, but if you are already using coc.nvim for auto-completions, it can be an option. However, do notice that there are several minor issues (but in the case of auto-completion, minor annoyances can be exaggerated).
// inside quote
input: '|' (press '[')
output: '[|]'
// closing pair balance
input: (((|)) (press ')')
output: ((()|)
// open pair balance
input: ((|))) (press '(')
output: (((|))))
// multiple character opening (very wierd)
input: `|` (press '`')
output: ``| (press '`')
```| (press '`')
```|``` (press '`')
```|`````` (press '`')
// <cr> mapping
input:
"""|""" (press '<cr>')
output:
"""
|"""
It is possible to set up some snippets for auto pairing, e.g.
snippet ( "()" iA
($1)$0
endsnippet
Since you can use regex and scripting in UltiSnips, it can be very powerful. However, there is no mechanism for deleting pairs, which can be very critical.
This plugin is extremely customizable. The number of options can be very overwhelming (with regular expressions). The smart pairing rules are also fairly good.
However, there is one critical issue. I don't think it support multi-byte opening/closing pair very well. For example,
// setting
let delimitMate_expand_cr = 1
let delimitMate_balance_matchpairs = 1
let delimitMate_nesting_quotes = ['"','`']
let delimitMate_quotes = "\" ' ` * **"
// multi-byte
input: | (press '**')
output: ***|*
// multi-byte
input: | (press '*', wait)
output: *|* (press '*', wait)
**|
It will add a imap
for **
, which will cause some delay when you type *
.
In addition, there are some other problems,
// inside quote
input: '|' (press '[')
output: '[|]'
// closing pair balance
input: (((|)) (press ')')
output: ((()|)
// <cr> mapping
input:
"""|""" (press '<cr>')
output:
"""
|"""
The completion and deletion are based on "rules", which can be very customizable, but the default rules are not very smart, so it can take some time to properly set it up.
// before character
input: |s (press '(')
output: (|)s
// inside quote
input: '|' (press '[')
output: '[|]'
// open pair balance
input: ((|))) (press '(')
output: (((|))))
// open pair balance
input: "str| (press '"')
output: "str"|"
// <cr> mapping
input:
"""|""" (press '<cr>')
output:
"""
|"""
Copyright (C) 2011-2013 Miao Jiang
Copyright (C) 2020 Krasjet
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.