feat: support multi byte character

fix #126
This commit is contained in:
windwp 2021-09-08 10:56:09 +07:00
parent b9bb171325
commit f0822ddc38
3 changed files with 92 additions and 20 deletions

View File

@ -215,8 +215,8 @@ M.on_attach = function(bufnr)
{ expr = true, noremap = true }
)
local key_end = rule.end_pair:sub(1, 1)
if #key_end == 1 and key_end ~= rule.key_map and rule.move_cond ~= nil then
local key_end = rule.key_end or rule.end_pair:sub(1, 1)
if #key_end >= 1 and key_end ~= rule.key_map and rule.move_cond ~= nil then
mapping = string.format(
[[v:lua.MPairs.autopairs_map(%d, '%s')]],
bufnr,
@ -318,10 +318,10 @@ M.autopairs_bs = function(bufnr)
})
then
local input = ''
for _ = 1, #rule.start_pair, 1 do
for _ = 1, vim.fn.strdisplaywidth(rule.start_pair), 1 do
input = input .. utils.key.bs
end
for _ = 1, #rule.end_pair, 1 do
for _ = 1, vim.fn.strdisplaywidth(rule.end_pair), 1 do
input = input .. utils.key.right .. utils.key.bs
end
return utils.esc('<c-g>U' .. input)
@ -344,7 +344,8 @@ M.autopairs_map = function(bufnr, char)
if rule.is_regex and rule.key_map and rule.key_map ~= '' then
new_text = line:sub(1, col) .. line:sub(col + 1, #line)
add_char = 0
elseif rule.key_map and #rule.key_map > 1 then
elseif rule.key_map and rule.key_map:match("<.*>") then
-- if it is a special key liek <c-a>
if utils.esc(rule.key_map) ~= char then
new_text = ''
else
@ -353,7 +354,7 @@ M.autopairs_map = function(bufnr, char)
end
else
new_text = line:sub(1, col) .. char .. line:sub(col + 1, #line)
add_char = 1
add_char = rule.key_map and #rule.key_map or 1
end
-- log.debug("new_text:[" .. new_text .. "]")
@ -383,7 +384,8 @@ M.autopairs_map = function(bufnr, char)
and rule:can_move(cond_opt)
then
local end_pair = rule:get_end_pair(cond_opt)
return utils.esc(utils.repeat_key(utils.key.join_right, #end_pair))
local end_pair_length = rule:get_end_pair_length(end_pair)
return utils.esc(utils.repeat_key(utils.key.join_right, end_pair_length))
end
if
@ -397,7 +399,10 @@ M.autopairs_map = function(bufnr, char)
move_text = ''
char = ''
end
return utils.esc(char .. end_pair .. move_text)
if end_pair:match("<.*>") then
end_pair = utils.esc(end_pair)
end
return char .. end_pair .. utils.esc(move_text)
end
end
end
@ -564,7 +569,7 @@ M.autopairs_afterquote = function(line, key_char)
end
end
end
return utils.esc(key_char)
return key_char
end
M.autopairs_closequote_expr = function()
@ -578,3 +583,4 @@ end
M.esc = utils.esc
_G.MPairs = M
return M

View File

@ -1,5 +1,5 @@
local log = require('nvim-autopairs._log')
local Rule = {}
local log = require('nvim-autopairs._log')
local Cond = require('nvim-autopairs.conds')
@ -33,11 +33,21 @@ function Rule.new(...)
is_endwise = false,
-- use regex to compare
is_regex = false,
is_multibyte = false,
-- some end_pair have key map like <left>.. then the length of string is
-- not correct
end_pair_length = nil,
},opt)
return setmetatable(opt, {__index = Rule})
local function verify(rule)
-- check multibyte
if #rule.start_pair ~= vim.fn.strdisplaywidth(rule.start_pair) then
rule:use_multibyte()
end
return rule
end
local r = setmetatable(opt, {__index = Rule})
return verify(r)
end
function Rule:use_regex(value,key_map)
@ -51,6 +61,14 @@ function Rule:use_key(key_map)
return self
end
function Rule:use_multibyte()
self.is_multibyte = true
self.end_pair_length = vim.fn.strdisplaywidth(self.end_pair)
self.key_map = string.match(self.start_pair, "[^\128-\191][\128-\191]*$")
self.key_end = string.match(self.end_pair, "[%z\1-\127\194-\244][\128-\191]*")
return self
end
function Rule:get_end_pair(opts)
if self.end_pair_func then
return self.end_pair_func(opts)

View File

@ -29,14 +29,16 @@ npairs.add_rules({
})
vim.api.nvim_set_keymap('i' , '<CR>','v:lua.npairs.check_break_line_char()', {expr = true , noremap = true})
function helpers.feed(text, feed_opts)
function helpers.feed(text, feed_opts, is_replace)
feed_opts = feed_opts or 'n'
local to_feed = vim.api.nvim_replace_termcodes(text, true, false, true)
vim.api.nvim_feedkeys(to_feed, feed_opts, true)
if not is_replace then
text = vim.api.nvim_replace_termcodes(text, true, false, true)
end
vim.api.nvim_feedkeys(text, feed_opts, true)
end
function helpers.insert(text)
helpers.feed('i' .. text, 'x')
function helpers.insert(text, is_replace)
helpers.feed('i' .. text, 'x',is_replace)
end
local data = {
@ -397,7 +399,7 @@ local data = {
:set_end_pair_length(2)
})
end,
name="mapping regex with custom end_pair_length",
name = "mapping regex with custom end_pair_length",
filetype="typescript",
key=">",
before = [[(o)=| ]],
@ -415,12 +417,58 @@ local data = {
end, true),
})
end,
name="mapping same pair with different key",
name = "mapping same pair with different key",
filetype="typescript",
key="(",
before = [[(test|) ]],
after = [[(test(|)) ]]
},
{
setup_func = function()
npairs.clear_rules()
npairs.add_rule(Rule("",""))
end,
name = "multibyte character from custom keyboard",
not_replace_term_code = true,
key = "",
before = [[a | ]],
after = [[a „|” ]],
end_cursor = 6,
},
{
setup_func = function()
npairs.clear_rules()
npairs.add_rule(Rule("",""):with_move(cond.done()))
end,
name = "multibyte character move_right",
not_replace_term_code = true,
key = "",
before = [[a „|”xx ]],
after = [[a „”|xx ]],
end_cursor = 9,
},
{
setup_func = function()
npairs.clear_rules()
npairs.add_rule(Rule("", ""):with_move(cond.done()))
end,
name = "multibyte character delete",
key = "<bs>",
before = [[a „|” ]],
after = [[a | ]],
},
{
setup_func = function()
npairs.clear_rules()
npairs.add_rule(Rule("a„", "”b"):with_move(cond.done()))
end,
not_replace_term_code = true,
name = "multibyte character and multiple ",
key = "",
before = [[a| ]],
after = [[a„|”b ]],
end_cursor = 5,
}
}
@ -452,14 +500,14 @@ 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})
helpers.insert(value.key)
helpers.insert(value.key,value.not_replace_term_code )
vim.wait(10)
helpers.feed("<esc>")
local result = vim.fn.getline(line)
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] + 1, "\n\n pos error: " .. value.name .. "\n")
eq(p_after, value.end_cursor or (pos[3] + 1), "\n\n pos error: " .. value.name .. "\n")
else
local line2 = vim.fn.getline(line + 2)