finish add pair

This commit is contained in:
windwp 2021-04-17 19:50:45 +07:00 committed by windwp
parent 8e9187d001
commit 1e808ecdf0
9 changed files with 325 additions and 79 deletions

View File

@ -17,7 +17,7 @@ M.setup = function(opt)
autocmd!
autocmd BufEnter * :lua require("nvim-autopairs").on_attach()
augroup end
]],false)
]],false)
end
@ -28,9 +28,9 @@ M.on_attach = function(bufnr)
state.rules = M.config.rules
api.nvim_exec(string.format([[
augroup autopairs_insert_%d
autocmd!
autocmd InsertCharPre <buffer=%d> call luaeval("require('nvim-autopairs').autopairs_insert(%d, _A)", v:char)
augroup autopairs_insert_%d
autocmd!
autocmd InsertCharPre <buffer=%d> call luaeval("require('nvim-autopairs').autopairs_insert(%d, _A)", v:char)
augroup end ]],
bufnr, bufnr, bufnr), false)
@ -43,7 +43,7 @@ end
local skip_next = false
M.autopairs_insert = function(bufnr, char)
if skip_next then skip_next = false 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)
@ -51,23 +51,43 @@ M.autopairs_insert = function(bufnr, char)
local _, col = utils.get_cursor()
log.debug(vim.inspect(col))
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
local new_text = line:sub(0, col) .. char .. line:sub(col)
log.debug("new_text:[" .. new_text .. "]")
log.debug("start_pair" .. rule.start_pair)
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)
log.debug('prev_char' .. prev_char)
log.debug('next_char' .. next_char)
if
prev_char == rule.start_pair
then
vim.schedule(function()
utils.insert_char(rule.end_pair)
utils.feed("<left>")
end)
return
if rule.start_pair == '(' then
log.debug("start_pair" .. rule.start_pair)
log.debug('prev_char' .. prev_char)
log.debug('next_char' .. next_char)
end
if prev_char == rule.start_pair then
local cond_opt = {
text = new_text,
rule = rule,
bufnr = bufnr,
col = col,
char = char,
line = line,
prev_char = prev_char,
next_char = next_char,
}
if rule:can_move(cond_opt) then
vim.schedule(function()
utils.feed(utils.key.del, 1)
end)
return
end
if rule:can_pair(cond_opt) then
log.debug('match')
vim.schedule(function()
utils.insert_char(rule.end_pair)
utils.feed(utils.key.left, #rule.end_pair)
end)
return
end
end
end
end

View File

@ -0,0 +1,37 @@
local utils = require('nvim-autopairs.utils')
local log = require('nvim-autopairs._log')
local cond={}
cond.not_regex_check = function(regex, length)
length = length or 1
return function(opts)
local str = utils.text_sub_char(opts.line, opts.col, - length)
log.debug(vim.inspect(str))
if str:match(regex) then
return false
end
return true
end
end
cond.move_right = function ()
return function(opts)
log.debug("move right test")
log.debug(opts)
if utils.is_quote(opts.char)
and opts.next_char == opts.char
then
local length = string.len(opts.line) -- situtaion |" => "|
log.debug("is quote" .. length) -- move right when have quote on end line or in quote
if opts.col + 1 == string.len(opts.line) then
return true
end
-- ("|") => (""|)
-- "" |" " => "" "| "
if utils.is_in_quote(opts.text, opts.col - 1, opts.char) then
return true
end
end
return false
end
end
return cond

View File

@ -1,37 +1,66 @@
local log = require('nvim-autopairs._log')
local Rule = {}
function Rule.new(...)
local params = {...}
local opt = {}
if params.start_pair then
opt = params
if type(params[1]) == 'table' then
opt = params[1]
else
opt.start_pair = params[1]
opt.end_pair = params[2]
opt.filetype = params[3]
if type(params[3])=="string" then
opt.filetypes = {params[3]}
else
opt.filetypes = params[3]
end
end
opt = vim.tbl_extend('force', {
start_pair = nil,
end_pair = nil,
filetype = "*",
filetypes = nil,
-- allow move when press close_pairs
can_move = function ()
return true
move_cond = function ()
return false
end,
-- allow delete when press bs
can_delete = function()
return true
del_cond = function()
return false
end,
can_pair = function(_)
pair_cond = function(_)
-- local prev_char, line, ts_node = unpack(opts)
return true
end,
},opt)
return setmetatable(opt, {__index = Rule})
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
end
end
return true
elseif type(conds) == 'function' then
return conds(opt)
end
return false
end
function Rule:can_pair(opt)
return can_do(self.pair_cond, opt)
end
function Rule:can_move(opt)
return can_do(self.move_cond, opt)
end
function Rule:can_del(opt)
return can_do(self.del_cond, opt)
end
return Rule.new

View File

@ -1,17 +1,30 @@
local Rule = require('nvim-autopairs.rule')
local check_func = require('nvim-autopairs.check_func')
local cond = require('nvim-autopairs.conds')
local basic = {
Rule("```", "```", 'markdown'),
Rule("'", "'"),
Rule('"""', '"""', 'python'),
Rule({
start_pair = "'",
end_pair = "'",
pair_cond = {
cond.not_regex_check('%w')
}
}),
Rule("`", "`"),
Rule('"', '"'),
-- Rule({
-- start_pair = '"',
-- end_pair = '"',
-- move_cond = {
-- cond.move_right()
-- }
-- }),
Rule("(", ")"),
Rule("[", "]"),
Rule("{", "}"),
Rule('"""', '"""', 'python'),
}

View File

@ -2,6 +2,38 @@ local M={}
local api = vim.api
local log = require('nvim-autopairs._log')
M.key = {
left = "<left>",
del = "<del>",
bs = "<bs>",
right = "<right>"
}
M.is_quote = function (char)
return char == "'" or char == '"' or char == '`'
end
M.is_in_quote = function(line, pos, quote)
local cIndex = 0
local result = false
while cIndex < string.len(line) and cIndex < pos do
cIndex = cIndex + 1
local char = line:sub(cIndex, cIndex)
if
result == true and
char == quote and
line:sub(cIndex -1, cIndex -1) ~= "\\"
then
result = false
elseif result == false and char == quote then
result = true
end
end
return result
end
M.is_attached = function(bufnr)
local _, check = pcall(api.nvim_buf_get_var, bufnr, "nvim-autopairs")
@ -45,24 +77,49 @@ M.text_get_current_line = function(bufnr)
return M.text_get_line(bufnr, row -1)
end
-- function M.text_prev_next(line, col, prev_count, next_char)
-- prev_count = prev_count or 1
-- next_char = next_char or prev_count
-- if line then
-- local prev = string.sub(line, math.max(col - prev_count + 1, 0), col)
-- local next = string.sub(line, col + 1, math.min(col + next_char, #line + 1))
-- return prev, next
-- end
-- end
M.text_sub_char = function(line, start, num)
if num > 0 then num = num - 1
elseif num < 0 then num = num + 1 end
log.debug(vim.inspect(num))
return string.sub(line,
math.min(start, start + num),
math.max(start, start + num)
)
local finish = start
if num < 0 then
start = start + num + 1
else
finish = start + num -1
end
return string.sub(line, start, finish)
end
-- P(M.text_sub_char("aa'' aaa", 3, -1))
M.insert_char = function(text)
api.nvim_put({text}, "c", false, true)
end
M.feed = function(text)
api.nvim_feedkeys (api.nvim_replace_termcodes(
text, true, false, true),
"n", true)
M.feed = function(text, num)
-- num = num or 1
-- local result = ''
-- for _ = 1, num, 1 do
-- result = result .. text
-- end
-- log.debug("result" .. result)
-- api.nvim_feedkeys (api.nvim_replace_termcodes(
-- result, true, false, true),
-- "n", true)
for i = 1, num, 1 do
api.nvim_feedkeys (api.nvim_replace_termcodes(
text, true, false, true),
"n", true)
end
end
M.esc = function(cmd)

View File

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

View File

@ -1,20 +1,8 @@
local helpers = {}
local npairs = require('nvim-autopairs')
_G.npairs = npairs;
local utils = require('nvim-autopairs.utils')
local api = vim.api
utils.insert_char = function(text)
api.nvim_put({text}, "c", true, true)
end
utils.feed = function(text)
api.nvim_feedkeys (api.nvim_replace_termcodes(
text, true, false, true),
"x", true)
end
local log = require('nvim-autopairs._log')
local eq = assert.are.same
_G.npairs = npairs;
local eq=_G.eq
vim.api.nvim_set_keymap('i' , '<CR>','v:lua.npairs.check_break_line_char()', {expr = true , noremap = true})
function helpers.feed(text, feed_opts)
@ -32,8 +20,8 @@ local data = {
name = "add normal bracket" ,
key = [[{]],
before = [[| ]],
after = [[{|} ]]
before = [[x| ]],
after = [[x{|} ]]
},
{
@ -45,8 +33,8 @@ local data = {
{
name = "add normal bracket" ,
key = [[(]],
before = [[aaaa| ]],
after = [[aaaa(|) ]]
before = [[aaaa|x ]],
after = [[aaaa(|)x ]]
},
{
name = "add normal quote" ,
@ -55,19 +43,33 @@ local data = {
after = [[aa"|" aa]]
},
{
only = true,
name = "add normal quote" ,
name = "add python quote" ,
filetype = "python",
key = [["]],
before = [[""|]],
after = [["""|"""]]
before = [[""| ]],
after = [["""|""" ]]
},
{
name = "add markdown quote" ,
filetype = "markdown",
key = [[`]],
before = [[``| ]],
after = [[```|``` ]]
},
{
name = "don't add single quote with previous alphabet char" ,
key = [[']],
before = [[aa| aa ]],
after = [[aa'| aa ]]
},
{
name = "don't add single quote with alphabet char" ,
key = [[']],
before = [[a|x ]],
after = [[a'|x ]]
},
-- {
-- name = "don't add single quote with previous alphabet char" ,
-- key = [[']],
-- before = [[aa| aa]],
-- after = [[aa'| aa]]
-- },
-- {
-- name = "don't add single quote on end line",
-- key = [[<right>']],
@ -98,12 +100,12 @@ local data = {
-- before = [[aa |aa]],
-- after = [[aa (|aa]]
-- },
-- {
-- name = "move right end line " ,
-- key = [["]],
-- before = [[aaaa|"]],
-- after = [[aaaa"|]]
-- },
{
name = "move right end line " ,
key = [["]],
before = [[aaaa|"]],
after = [[aaaa"|]]
},
-- {
-- name = "move right when inside quote" ,
-- key = [["]],
@ -195,7 +197,7 @@ local function Test(test_data)
local pos = vim.fn.getpos('.')
if value.key ~= '<cr>' then
eq(after, result , "\n\n text error: " .. value.name .. "\n")
eq(p_after , pos[3], "\n\n pos error: " .. value.name .. "\n")
eq(p_after, pos[3] + 1, "\n\n pos error: " .. value.name .. "\n")
else
local line2 = vim.fn.getline(line + 2)
eq(line + 1, pos[2], '\n\n breakline error:' .. value.name .. "\n")

26
tests/test_utils.lua Normal file
View File

@ -0,0 +1,26 @@
local utils = require('nvim-autopairs.utils')
local log = require('nvim-autopairs._log')
local api = vim.api
utils.insert_char = function(text)
api.nvim_put({text}, "c", true, true)
end
utils.feed = function(text,num)
if num > 0 then
num = num + 1
else
num = 1
end
local result = ''
for _ = 1, num, 1 do
result = result .. text
end
log.debug("result" .. result)
api.nvim_feedkeys (api.nvim_replace_termcodes(
result, true, false, true),
"x", true)
end
_G.eq = assert.are.same

62
tests/utils_spec.lua Normal file
View File

@ -0,0 +1,62 @@
local utils = require('nvim-autopairs.utils')
local eq = assert.are.same
local data = {
{
text = "add normal bracket",
start = 2,
num = 2,
result = 'dd'
},
{
text = "iood",
start = 1,
num = 2,
result = 'io'
},
{
text = "add normal bracket",
start = 0,
num = -2,
result = ''
},
{
text = "add normal bracket",
start = 3,
num = -2,
result = 'dd'
},
{
text = [["""]],
start = 3,
num = -3,
result = '"""'
},
{
text = [["""]],
start = 3,
num = 3,
result = '"'
},
{
text = [["""]],
start = 2,
num = 2,
result = '""'
},
}
describe('utils test substring ', function()
for _, value in pairs(data) do
it('test sub: ' .. value.text, function()
local result = utils.text_sub_char(value.text, value.start, value.num)
eq(value.result, result, 'start ' .. value.start .. ' num' .. value.num)
end)
end
end)