@@ -19,7 +19,8 @@ local default = {
1919 disable_filetype = { 'TelescopePrompt', 'spectre_panel' },
2020 disable_in_macro = false,
2121 disable_in_visualblock = false,
22− ignored_next_char = [=[[%w%%%'%[%"%.]]=],
22+ disable_in_replace_mode = true,
23+ ignored_next_char = [=[[%w%%%'%[%"%.%`%$]]=],
2324 break_undo = true,
2425 check_ts = false,
2526 enable_moveright = true,
@@ -53,18 +54,21 @@ M.setup = function(opt)
5354 end
5455
5556 M.force_attach()
56−
57− api.nvim_exec(
58− [[
59− augroup autopairs_buf
60− autocmd!
61− autocmd BufEnter,BufWinEnter * lua require("nvim-autopairs").on_attach()
62− autocmd BufDelete * lua require("nvim-autopairs").set_buf_rule(nil,tonumber(vim.fn.expand("<abuf>")))
63− autocmd FileType * lua require("nvim-autopairs").force_attach()
64− augroup end
65− ]],
66− false
67− )
57+ local group = api.nvim_create_augroup('autopairs_buf', { clear = true })
58+ api.nvim_create_autocmd({ 'BufEnter', 'BufWinEnter' }, {
59+ group = group, pattern = '*',
60+ callback = function() M.on_attach() end
61+ })
62+ api.nvim_create_autocmd('BufDelete', {
63+ group = group, pattern = '*',
64+ callback = function(data)
65+ M.set_buf_rule(nil, tonumber(data.buf) or 0)
66+ end,
67+ })
68+ api.nvim_create_autocmd('FileType', {
69+ group = group, pattern = '*',
70+ callback = function() M.force_attach() end
71+ })
6872end
6973
7074M.add_rule = function(rule)
@@ -99,7 +103,7 @@ M.remove_rule = function(pair)
99103 if r.start_pair ~= pair then
100104 table.insert(state_tbl, r)
101105 elseif r.key_map and r.key_map ~= '' then
102− vim.api.nvim_buf_del_keymap(0, 'i', r.key_map)
106+ api.nvim_buf_del_keymap(0, 'i', r.key_map)
103107 end
104108 end
105109 M.set_buf_rule(state_tbl, 0)
@@ -133,6 +137,15 @@ M.force_attach = function(bufnr)
133137 M.on_attach(bufnr)
134138end
135139
140+local del_keymaps = function()
141+ local status, autopairs_keymaps = pcall(api.nvim_buf_get_var, 0, 'autopairs_keymaps')
142+ if status and autopairs_keymaps and #autopairs_keymaps > 0 then
143+ for _, key in pairs(autopairs_keymaps) do
144+ pcall(api.nvim_buf_del_keymap, 0, 'i', key)
145+ end
146+ end
147+end
148+
136149local function is_disable()
137150 if M.state.disabled then
138151 return true
@@ -153,14 +166,16 @@ local function is_disable()
153166 return true
154167 end
155168
169+ if M.config.disable_in_replace_mode and vim.api.nvim_get_mode().mode == "R" then
170+ return true
171+ end
172+
156173 if M.config.disable_in_visualblock and utils.is_block_wise_mode() then
157174 return true
158175 end
159176
160177 if utils.check_filetype(M.config.disable_filetype, vim.bo.filetype) then
161− -- should have a way to remove the mapping when vim.bo.filetype = ''
162− -- now we only remove a rule
163− -- the event FileType happen after BufEnter
178+ del_keymaps()
164179 M.set_buf_rule({}, 0)
165180 return true
166181 end
@@ -169,14 +184,14 @@ end
169184
170185---@return table <number, Rule>
171186M.get_buf_rules = function(bufnr)
172− return M.state.rules[bufnr or vim.api.nvim_get_current_buf()] or {}
187+ return M.state.rules[bufnr or api.nvim_get_current_buf()] or {}
173188end
174189
175−---@param rules table list or rule
190+---@param rules nil|table list or rule
176191---@param bufnr number buffer number
177192M.set_buf_rule = function(rules, bufnr)
178193 if bufnr == 0 or bufnr == nil then
179− bufnr = vim.api.nvim_get_current_buf()
194+ bufnr = api.nvim_get_current_buf()
180195 end
181196 M.state.rules[bufnr] = rules
182197end
@@ -226,78 +241,50 @@ M.on_attach = function(bufnr)
226241 if utils.is_attached(bufnr) then
227242 return
228243 end
244+ del_keymaps()
229245 local enable_insert_auto = false
246+ local autopairs_keymaps = {}
247+ local expr_map = function(key)
248+ api.nvim_buf_set_keymap(bufnr, 'i', key, '', {
249+ expr = true,
250+ noremap = true,
251+ desc = "autopairs map key",
252+ callback = function() return M.autopairs_map(bufnr, key) end,
253+ })
254+ table.insert(autopairs_keymaps, key)
255+ end
230256 for _, rule in pairs(rules) do
231257 if rule.key_map ~= nil then
232258 if rule.is_regex == false then
233259 if rule.key_map == '' then
234260 rule.key_map = rule.start_pair:sub(#rule.start_pair)
235261 end
236− local mapping = string.format(
237− "v:lua.MPairs.autopairs_map(%d,%q)",
238− bufnr,
239− rule.key_map:gsub("<", "<lt>")
240− )
241− api.nvim_buf_set_keymap(
242− bufnr,
243− 'i',
244− rule.key_map,
245− mapping,
246− { expr = true, noremap = true }
247− )
248−
262+ expr_map(rule.key_map)
249263 local key_end = rule.key_end or rule.end_pair:sub(1, 1)
250264 if #key_end >= 1 and key_end ~= rule.key_map and rule.move_cond ~= nil then
251− mapping = string.format(
252− "v:lua.MPairs.autopairs_map(%d,%q)",
253− bufnr,
254− key_end
255− )
256− vim.api.nvim_buf_set_keymap(
257− bufnr,
258− 'i',
259− key_end,
260− mapping,
261− { expr = true, noremap = true }
262− )
265+ expr_map(key_end)
263266 end
264267 else
265268 if rule.key_map ~= '' then
266− local mapping = string.format(
267− "v:lua.MPairs.autopairs_map(%d,%q)",
268− bufnr,
269− rule.key_map:gsub("<", "<lt>")
270− )
271− api.nvim_buf_set_keymap(
272− bufnr,
273− 'i',
274− rule.key_map,
275− mapping,
276− { expr = true, noremap = true }
277− )
269+ expr_map(rule.key_map)
278270 elseif rule.is_endwise == false then
279271 enable_insert_auto = true
280272 end
281273 end
282274 end
283275 end
276+ api.nvim_buf_set_var(bufnr, 'autopairs_keymaps', autopairs_keymaps)
284277
285278 if enable_insert_auto then
286279 -- capture all key use it to trigger regex pairs
287280 -- it can make an issue with paste from register
288− api.nvim_exec(
289− string.format(
290− [[
291− augroup autopairs_insert_%d
292− autocmd!
293− autocmd InsertCharPre <buffer=%d> call luaeval("require('nvim-autopairs').autopairs_insert(%d, _A)", v:char)
294− augroup end ]],
295− bufnr,
296− bufnr,
297− bufnr
298− ),
299− false
300− )
281+ api.nvim_create_autocmd('InsertCharPre', {
282+ group = api.nvim_create_augroup(string.format("autopairs_insert_%d", bufnr), { clear = true }),
283+ buffer = bufnr,
284+ callback = function()
285+ M.autopairs_insert(bufnr, vim.v.char)
286+ end
287+ })
301288 end
302289
303290 if M.config.fast_wrap and M.config.fast_wrap.map then
@@ -315,7 +302,7 @@ M.on_attach = function(bufnr)
315302 bufnr,
316303 'i',
317304 '<bs>',
318− string.format('v:lua.MPairs.autopairs_bs(%d)', bufnr),
305+ 'v:lua.MPairs.autopairs_bs()',
319306 { expr = true, noremap = true }
320307 )
321308 end
@@ -346,7 +333,7 @@ local autopairs_delete = function(bufnr, key)
346333 if is_disable() then
347334 return utils.esc(key)
348335 end
349− bufnr = bufnr or 0
336+ bufnr = bufnr or api.nvim_get_current_buf()
350337 local line = utils.text_get_current_line(bufnr)
351338 local _, col = utils.get_cursor()
352339 local rules = M.get_buf_rules(bufnr)
@@ -372,10 +359,10 @@ local autopairs_delete = function(bufnr, key)
372359 })
373360 then
374361 local input = ''
375− for _ = 1, vim.api.nvim_strwidth(rule.start_pair), 1 do
362+ for _ = 1, api.nvim_strwidth(rule.start_pair), 1 do
376363 input = input .. utils.key.bs
377364 end
378− for _ = 1, vim.api.nvim_strwidth(rule.end_pair), 1 do
365+ for _ = 1, api.nvim_strwidth(rule.end_pair), 1 do
379366 input = input .. utils.key.del
380367 end
381368 return utils.esc('<c-g>U' .. input)
@@ -613,7 +600,7 @@ M.autopairs_afterquote = function(line, key_char)
613600 is_prev_slash = char == '\\'
614601 end
615602 if count == 2 and index >= (#line - 2) then
616− local rules = M.get_buf_rules(vim.api.nvim_get_current_buf())
603+ local rules = M.get_buf_rules(api.nvim_get_current_buf())
617604 for _, rule in pairs(rules) do
618605 if rule.start_pair == prev_char and char_end ~= rule.end_pair then
619606 local new_text = line:sub(0, index)
@@ -651,7 +638,7 @@ M.map_cr = function()
651638 return M.autopairs_cr()
652639 end
653640 end
654− vim.api.nvim_set_keymap(
641+ api.nvim_set_keymap(
655642 'i',
656643 '<CR>',
657644 'v:lua.MPairs.completion_confirm()',