This commit is contained in:
windwp 2021-04-18 08:20:56 +07:00 committed by windwp
parent d55ab8ae10
commit fd20894296
10 changed files with 219 additions and 103 deletions

View File

@ -1,6 +1,7 @@
## nvim-autopairs
A minimalist autopairs for Neovim written by Lua.
It can support multipple character
Requires neovim 0.5+
@ -13,17 +14,8 @@ require('nvim-autopairs').setup()
## Default values
``` lua
local pairs_map = {
["'"] = "'",
['"'] = '"',
['('] = ')',
['['] = ']',
['{'] = '}',
['`'] = '`',
}
local disable_filetype = { "TelescopePrompt" }
local break_line_filetype = nil -- mean all file type
local html_break_line_filetype = {'html' , 'vue' , 'typescriptreact' , 'svelte' , 'javascriptreact'}
local ignored_next_char = "%w"
```
@ -37,8 +29,49 @@ require('nvim-autopairs').setup({
```
### Rule
- Pairs map only accept 1 character
- You can use regex on filetype
It can support multipple character
``` lua
local Rule = require('nvim-autopairs.rule')
local npairs = require('nvim-autopairs')
npairs.add_rule({
Rule("$$","$$","tex")
})
-- you can use some builtin condition
local cond = require('nvim-autopairs.cond')
print(vim.inspect(cond))
npairs.add_rules({
Rule("$", "$",{"tex", "latex"})
-- don't add a pair if the next character is %
:with_pair(cond.not_after_regex_check("%%"))
-- don't add a pair if the previous character is xxx
:with_pair(cond.not_before_regex_check("xxx", 3))
-- don't move right when repeat character
:with_move(cond.none())
-- don't delete if the next character is xx
:with_del(cond.not_after_regex_check("xx"))
-- disable add newline when press <cr>
:with_cr(cond.none())
},
)
npairs.add_rules({
Rule("$$","$$","tex")
:with_pair(function(otps)
print(vim.inspect(otps))
if opts.line=="aa $$" then
-- don't add pair on that line
return false
end
end)
}
)
--- check ./lua/nvim-autopairs/rules/basic.lua
```
### Break line on html or inside pairs
@ -81,7 +114,7 @@ MUtils.completion_confirm=function()
return npairs.esc("<c-n><c-y>")
end
else
return npairs.check_break_line_char()
return npairs.autopairs_cr()
end
end
@ -89,6 +122,7 @@ end
remap('i' , '<CR>','v:lua.MUtils.completion_confirm()', {expr = true , noremap = true})
```
#### using nvim-compe
``` lua
local remap = vim.api.nvim_set_keymap
local npairs = require('nvim-autopairs')
@ -108,7 +142,7 @@ MUtils.completion_confirm=function()
return npairs.esc("<c-n>")
end
else
return npairs.check_break_line_char()
return npairs.autopairs_cr()
end
end
@ -166,16 +200,4 @@ Before Input After
## FAQ
- Is this support autopair of 2 character?
> No, Any PR is welcome :)
- Do you have any plan to add more feature (flymode ,end-wise) ?
>No, It is a minimalist autopairs.
>I don't want to make everything complicated.
>
>If you want a flymode or something else you can use [jiangmiao autopairs](https://github.com/jiangmiao/auto-pairs)
>
>If you want more feature please try to use [lexima](https://github.com/cohama/lexima.vim)
https://github.com/tpope/vim-endwise

View File

@ -23,7 +23,27 @@ M.setup = function(opt)
]],false)
end
M.add_rule = function (rule)
table.insert(M.config.rules, rule)
end
M.disable=function()
state.disabled = true
end
M.enable = function()
state.disabled = false
end
M.add_rules = function (rules)
for _, rule in pairs(rules) do
table.insert(M.config.rules, rule)
end
end
M.on_attach = function(bufnr)
if state.disabled then return end
bufnr = bufnr or api.nvim_get_current_buf()
if not utils.check_disable_ft(M.config.disable_filetype, vim.bo.filetype) then return end
local rules = {};
@ -55,6 +75,7 @@ M.on_attach = function(bufnr)
end
M.autopairs_bs = function(bufnr)
if state.disabled then return end
local line = utils.text_get_current_line(bufnr)
local _, col = utils.get_cursor()
local filetype = vim.bo.filetype
@ -92,55 +113,56 @@ end
local skip_next = false
M.autopairs_insert = function(bufnr, char)
if state.disabled then return end
if skip_next then skip_next = false return end
local line = utils.text_get_current_line(bufnr)
-- log.debug("-----------------")
-- log.debug("line:" .. line)
-- log.debug("char:" .. char)
local _, col = utils.get_cursor()
local filetype = vim.bo.filetype
local new_text = line:sub(1, col) .. char .. line:sub(col + 1,#line)
-- log.debug("new_text:[" .. new_text .. "]")
for _, rule in pairs(state.rules) do
if rule.start_pair and utils.check_filetype(rule.filetypes, filetype) then
if rule.start_pair then
local prev_char = utils.text_sub_char(new_text, col + 1,-#rule.start_pair)
local next_char = utils.text_sub_char(new_text, col + 2,#rule.start_pair)
if prev_char == rule.start_pair then
-- log.debug("start_pair" .. rule.start_pair)
-- log.debug('prev_char' .. prev_char)
-- log.debug('next_char' .. next_char)
local cond_opt = {
text = new_text,
rule = rule,
bufnr = bufnr,
col = col,
char = char,
line = line,
prev_char = prev_char,
next_char = next_char,
}
local next_char = utils.text_sub_char(new_text, col + 2,#rule.end_pair)
local cond_opt = {
text = new_text,
rule = rule,
bufnr = bufnr,
col = col,
char = char,
line = line,
prev_char = prev_char,
next_char = next_char,
}
-- log.debug("start_pair" .. rule.start_pair)
-- log.debug('prev_char' .. prev_char)
-- log.debug('next_char' .. next_char)
if
next_char == rule.end_pair
and rule:can_move(cond_opt)
then
utils.reset_vchar()
vim.schedule(function()
utils.feed(utils.key.right, -1)
end)
return false
end
if rule:can_move(cond_opt) then
utils.reset_vchar()
vim.schedule(function()
utils.feed(utils.key.right, -1)
end)
return false
end
if rule:can_pair(cond_opt) then
vim.schedule(function()
utils.insert_char(rule.end_pair)
utils.feed(utils.key.left, #rule.end_pair)
end)
return
end
if
prev_char == rule.start_pair
and rule:can_pair(cond_opt)
then
vim.schedule(function()
utils.insert_char(rule.end_pair)
utils.feed(utils.key.left, #rule.end_pair)
end)
return
end
end
end
end
M.autopairs_cr = function(bufnr)
if state.disabled then return end
bufnr = bufnr or api.nvim_get_current_buf()
local line = utils.text_get_current_line(bufnr)
local _, col = utils.get_cursor()
@ -148,10 +170,16 @@ M.autopairs_cr = function(bufnr)
for _, rule in pairs(state.rules) do
if rule.start_pair and utils.check_filetype(rule.filetypes, filetype) then
local prev_char = utils.text_sub_char(line, col,-#rule.start_pair)
local next_char = utils.text_sub_char(line, col+1,#rule.start_pair)
local next_char = utils.text_sub_char(line, col+1,#rule.end_pair)
if
rule.start_pair == prev_char
and rule.end_pair == next_char
and rule:can_cr({
bufnr = bufnr,
prev_char = prev_char,
next_char = next_char,
line = line
})
then
return utils.esc("<cr><c-o>O")
end

View File

@ -1,14 +0,0 @@
local M={}
M.check_previous_word = function (regex)
return function(opt)
return opt.pre_word:match(regex) ~= nil
end
end
return

View File

@ -2,53 +2,94 @@ local utils = require('nvim-autopairs.utils')
local log = require('nvim-autopairs._log')
local cond={}
-- cond
-- @return false when it is not correct
-- true when it is correct
-- nil when it is not determine
cond.none = function()
return function() return false end
end
cond.done = function()
return function() return true end
end
cond.not_before_regex_check = function(regex, length)
length = length or 1
return function(opts)
log.debug('not_before_regex_check')
local str = utils.text_sub_char(opts.line, opts.col, - length)
if str:match(regex) then
return false
end
return true
end
end
cond.not_after_regex_check = function(regex, length)
length = length or 1
return function(opts)
log.debug('not_after_regex_check')
local str = utils.text_sub_char(opts.line, opts.col + 1, length)
if str:match(regex) then
return false
end
return true
end
end
cond.not_add_quote_inside_quote=function()
cond.check_is_bracket_line=function ()
return function(opts)
log.debug('check_is_bracket_line')
if
utils.is_bracket(opts.char)
and opts.next_char == opts.rule.end_pair
then
-- (( many char |)) => add
-- ( many char |)) => not add
local count_prev_char = 0
local count_next_char = 0
for i = 1, #opts.line, 1 do
local c = opts.line:sub(i, i)
if c == opts.char then
count_prev_char = count_prev_char + 1
elseif c == opts.rule.end_pair then
count_next_char = count_next_char + 1
end
end
if count_prev_char ~= count_next_char then
return false
end
end
end
end
cond.not_add_quote_inside_quote = function()
return function(opts)
log.debug('not_add_quote_inside_quote')
if
utils.is_quote(opts.char)
and utils.is_in_quote(opts.text, opts.col, opts.char)
then
return false
end
return true
end
end
cond.move_right = function ()
return function(opts)
log.debug("move_right")
if utils.is_close_bracket(opts.char) then
return true
end
-- move right when have quote on end line or in quote
-- situtaion |" => "|
if
utils.is_quote(opts.char)
and opts.next_char == opts.char
then
if opts.col + 1 == string.len(opts.line) then
log.debug("move right correct")
return true
end
-- ("|") => (""|)

View File

@ -23,9 +23,9 @@ function Rule.new(...)
-- allow move when press close_pairs
move_cond = nil,
-- allow delete when press bs
del_cond = {function() return true end},
cr_cond = {function() return true end},
pair_cond = {function() return true end},
del_cond = {},
cr_cond = {},
pair_cond = {},
},opt)
return setmetatable(opt, {__index = Rule})
end
@ -42,18 +42,31 @@ function Rule:with_del(cond)
return self
end
function Rule:with_pair(cond)
if self.pair_cond == nil then self.pair_cond = {}end
table.insert(self.pair_cond, cond)
function Rule:with_cr(cond)
if self.cr_cond == nil then self.cr_cond = {}end
table.insert(self.cr_cond, cond)
return self
end
function Rule:with_pair(cond)
if self.pair_cond == nil then self.pair_cond = {}end
table.insert(self.pair_cond, cond)
if self=="dafs" the
return self
end
function Rule:end_wise()
return self
end
local function can_do(conds, opt)
if type(conds) == 'table' then
for _, cond in pairs(conds) do
if not cond(opt) then
return false
local result = cond(opt)
if result ~= nil then
return result
end
end
return true
@ -81,4 +94,4 @@ function Rule:can_cr(opt)
return can_do(self.cr_cond, opt)
end
return {new = Rule.new}
return Rule.new

View File

@ -1,9 +1,6 @@
local Rule = require('nvim-autopairs.rule').new
local log = require('nvim-autopairs._log')
local Rule = require('nvim-autopairs.rule')
local cond = require('nvim-autopairs.conds')
local function setup(opt)
local basic = function(...)
return Rule(...)
@ -12,15 +9,19 @@ local function setup(opt)
:with_pair(cond.not_add_quote_inside_quote())
end
local rules = {
Rule("<!--", "-->", 'html'):with_cr(cond.none()),
Rule("```", "```", 'markdown'),
Rule('"""', '"""', 'python'),
basic("'", "'")
:with_pair(cond.not_before_regex_check("%w")) ,
basic("`", "`"),
basic('"', '"'),
basic("(", ")"),
basic("[", "]"),
basic("{", "}"),
basic("(", ")")
:with_pair(cond.check_is_bracket_line()),
basic("[", "]")
:with_pair(cond.check_is_bracket_line()),
basic("{", "}")
:with_pair(cond.check_is_bracket_line()),
Rule(">", "<",
{ 'html', 'typescript', 'typescriptreact', 'svelte', 'vue'})
:with_move(cond.none())

View File

@ -17,6 +17,15 @@ M.is_quote = function (char)
return char == "'" or char == '"' or char == '`'
end
M.is_bracket = function (char)
return char == "(" or char == '[' or char == '{'
end
M.is_close_bracket = function (char)
return char == ")" or char == ']' or char == '}'
end
M.is_in_quote = function(line, pos, quote)
local cIndex = 0
local result = false

View File

@ -18,7 +18,7 @@ set nosmartindent
set indentexpr=
lua << EOF
_G.__is_log = true
-- _G.__is_log = true
require("plenary/busted")
vim.cmd[[luafile ./tests/test_utils.lua]]
require("nvim-autopairs").setup()

View File

@ -107,7 +107,12 @@ local data = {
before = [[aa |.aa]],
after = [[aa (|.aa]]
},
{
name = "don't add bracket have open bracket in same line" ,
key = [[(]],
before = [[( many char |))]],
after = [[( many char (|))]]
},
{
name = "move right end line " ,
key = [["]],
@ -121,6 +126,18 @@ local data = {
after = [[("abcd"|)]]
},
{
name = "move right square bracket" ,
key = [[)]],
before = [[("abcd|) ]],
after = [[("abcd)| ]]
},
{
name = "move right bracket" ,
key = [[}]],
before = [[("abcd|}} ]],
after = [[("abcd}|} ]]
},
{
name = "move right when inside grave with special slash" ,
key = [[`]],
@ -133,6 +150,7 @@ local data = {
before = [[("abcd\"|")]],
after = [[("abcd\""|)]]
},
{
name = "move right when inside single quote with special slash",
filetype="javascript",
@ -199,7 +217,6 @@ if #run_data == 0 then run_data = data end
local function Test(test_data)
for _, value in pairs(test_data) do
it("test "..value.name, function()
log.debug("Start" .. value.name)
local before = string.gsub(value.before , '%|' , "")
local after = string.gsub(value.after , '%|' , "")
local p_before = string.find(value.before , '%|')
@ -213,7 +230,6 @@ local function Test(test_data)
npairs.on_attach(vim.api.nvim_get_current_buf())
vim.fn.setline(line , before)
vim.fn.setpos('.' ,{0, line, p_before , 0})
log.debug("insert " .. value.key)
helpers.insert(value.key)
vim.wait(10)
helpers.feed("<esc>")

View File

@ -17,7 +17,7 @@ utils.feed = function(text,num)
for _ = 1, num, 1 do
result = result .. text
end
log.debug("result" .. result)
-- log.debug("result" .. result)
api.nvim_feedkeys (api.nvim_replace_termcodes(
result, true, false, true),
"x", true)