Auto pair plugin for neovim
This is still very much a work in progress... APIs may break at various times.
|
-- type {
{|}
|
-- type <!--
<!--|-->
{|}
-- type <CR>
{
|
}
{|}
-- type <BS>
|
{}|
-- type <BS>
|
<!--|-->
-- type <BS>
|
<!---->|
-- type <BS>
|
|
-- type {
{|}
-- type }
{}|
|
-- type <!--
<!--|-->
-- type -
<!---->|
pears.nvim is lightning fast and doesn't slow down input at all!
Detects language based off of the treesitter language at the cursor. This will fallback to ft
if there is no treesitter parser.
nvim-treesitter
is required, but for basic injected language support it is not required.You can install this with your favorite package manager (packer.nvim shown).
use "steelsojka/pears.nvim"
require "pears".setup()
The setup function takes a configuration function as an argument that will get called with a configuration API.
require "pears".setup(function(conf)
conf.pair("{", "}")
conf.expand_on_enter(false)
end)
The configuration interface is described as:
type CallableList<T> = ((value: T) => boolean | nil) | {
include?: T[];
exclude?: T[];
} | T[]
interface PearsConfig {
// Registers a pair to expand
pair(opener: string, closer_or_config: string | PearsPairConfig | nil): void;
// Enables an empty pair to be removed on backspace when the cursor is in the empty pair
remove_pair_on_inner_backspace(enable: boolean): void;
// Enables an empty pair to be removed on backspace when the cursor at the end of the empty pair
remove_pair_on_outer_backspace(enable: boolean): void;
// Overrides the on enter handler. Use to integrate other plugins to the <CR> key binding.
// Any string returned will be fed to `feedkeys`.
on_enter(handler: (pear_handler: () => void) => string | nil): void;
// Whether to bind <CR> to expand pairs
expand_on_enter(enable: boolean): void;
// A list of filetypes to never attach it to, basically not including this plugin at all.
disabled_filetypes(filetypes: string[]): void;
}
interface PearsPairConfig {
// Close characters
close: string;
// Whether the pair should expand or not. Use to add custom behavior to a pair
should_expand?: (args: RuleArg) => boolean;
// Whether the pair should perform <CR> behavior. Use to add custom behavior to a pair
should_return?: (args: RuleArg) => boolean;
// Whether when entering a closing pair char the cursor should move past the closing char or insert a new char
should_move_right?: (args: RuleArg) => boolean;
// A function to handle <CR> when the cursor is placed inside an empty pair
// Default behavior is <CR><C-c>O
handle_return?: (bufnr: number) => void;
// Includes and excludes for this specific pair by filetype.
// This will be ignored if `setup_buf_pairs` is called with a pairs param.
filetypes?: CallableList<string>;
}
interface RuleArg {
char: string | nil;
context: Context | nil;
leaf: PearsPairConfig;
lang: string;
cursor: [number, number];
bufnr: number;
input: Input;
}
You can setup filetype specific configuration a couple different ways.
You can configure a pair to only work on a set of filetypes.
require "pears".setup(function(conf)
conf.pair("{", {filetypes = {"c", "javascript"}})
end)
This will only expand {
on c
and javascript
files.
Look at the interface for filetypes
to see all possible ways to determine the filetype to include/exclude.
You can specify which pairs to include/exclude by calling setup_buf_pairs()
with a CallableList<string>
.
This is useful when using filetype files. All these are valid.
lua require "pears".setup_buf_pairs {"{", "<"}
lua require "pears".setup_buf_pairs {include = {"{", "<"}}
lua require "pears".setup_buf_pairs {exclude = {"<!--"}}
lua require "pears".setup_buf_pairs(function(opener)
return opener ~= "{"
end)
You can use pears to produce matching html tags or any matching content. Here is a sample configuration for matching html tags.
<div|
-- type > or any non valid character
<div>|</div>
For an example, take a look at the tag_matching
preset.
You can also enable this using the preset.
require "pears".setup(function(conf)
conf.preset "tag_matching"
end)
You can bind the expansion to a certain key if you want to expand a wildcard before the terminating condition.
inoremap <silent> <C-l> lua require "pears".expand()
<div class="test|"
-- press <C-l>
<div class="test">|</div>
pears uses several hooks to define how a specific pear should behave. These hooks can be set using rules, which in the end are just functions. A rule api is provided, and used internally, to make this enjoyable to write. Here is an example.
local R = require "pears.rule"
require "pears".setup(function(conf)
conf.pair("'", {
close = "'",
-- Don't expand a quote if it comes after an alpha character
should_expand = R.not_(R.start_of_context "[a-zA-Z]")
})
end)
We could also add a rule to only expand this within a treesitter "string" node.
local R = require "pears.rule"
require "pears".setup(function(conf)
conf.pair("'", {
close = "'",
should_expand = R.all_of(
-- Don't expand a quote if it comes after an alpha character
R.not_(R.start_of_context "[a-zA-Z]")
-- Only expand when in a treesitter "string" node
R.child_of_node "string"
)
})
end)
To work with completion framesworks you can use the on_enter
option to add custom behavior on enter. Shown with compe
.
require "pears".setup(function(conf)
conf.on_enter(function(pears_handle)
if vim.fn.pumvisible() == 1 and vim.fn.complete_info().selected ~= -1 then
return vim.fn["compe#confirm"]("<CR>")
else
pears_handle()
end
end)
end)