on master help sign in
11 files changed+177−115
since splitsnapshots
unifiedsplit
.gitignore+1 README.md+17−3 lua/nvim-autopairs.lua+63−76 lua/nvim-autopairs/completion/cmp.lua+2−1 lua/nvim-autopairs/completion/handlers.lua+1−1 lua/nvim-autopairs/conds.lua+52−10 lua/nvim-autopairs/fastwrap.lua+4−12 lua/nvim-autopairs/rule.lua+1−5 lua/nvim-autopairs/rules/basic.lua+10−5 lua/nvim-autopairs/utils.lua+1−1 tests/nvim-autopairs_spec.lua+25−1
.gitignorenew file+1
@@ -0,0 +1 @@
1+doc/tags
README.md+17−3
@@ -2,7 +2,7 @@
22
33A super powerful autopair plugin for Neovim that supports multiple characters.
44
5−Requires neovim 0.5+
5+Requires neovim 0.7
66
77## Installation
88
@@ -33,7 +33,8 @@ use {
3333local disable_filetype = { "TelescopePrompt" }
3434local disable_in_macro = false -- disable when recording or executing a macro
3535local disable_in_visualblock = false -- disable when insert after visual block mode
36−local ignored_next_char = [=[[%w%%%'%[%"%.]]=]
36+local disable_in_replace_mode = true
37+local ignored_next_char = [=[[%w%%%'%[%"%.%`%$]]=]
3738local enable_moveright = true
3839local enable_afterquote = true -- add bracket pairs after quote
3940local enable_check_bracket_line = true --- check bracket in same line
@@ -339,9 +340,17 @@ Before Input After
339340 require('nvim-autopairs').enable()
340341 require('nvim-autopairs').remove_rule('(') -- remove rule (
341342 require('nvim-autopairs').clear_rules() -- clear all rules
342− require('nvim-autopairs').get_rule('"') -- get rule " then modify it
343+ -- get rule " then modify it. It can return a list of rule or just a rule
344+ require('nvim-autopairs').get_rule('"')
345+```
343346
347+* Sample
348+```lua
349+-- remove add single quote on filetype scheme or lisp
350+require("nvim-autopairs").get_rule("'")[1].not_filetypes = { "scheme", "lisp" }
351+require("nvim-autopairs").get_rule("'")[1]:with_pair(cond.not_after_text("["}))
344352```
353+
345354### FastWrap
346355
347356``` text
@@ -382,3 +391,8 @@ npairs.setup({
382391
383392### Custom rules
384393[rules](https://github.com/windwp/nvim-autopairs/wiki/Custom-rules)
394+
395+## Sponsors
396+
397+Thanks to everyone who sponsors my projects and makes continued development maintenance possible!
398+<!-- patreon --><a href="https://github.com/t4t5"><img src="https://github.com/t4t5.png" width="60px" alt="" /></a><!-- patreon-->
lua/nvim-autopairs.lua+63−76
@@ -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()',
lua/nvim-autopairs/completion/cmp.lua+2−1
@@ -38,7 +38,8 @@ M.filetypes = {
3838 handler = handlers.lisp
3939 }
4040 },
41− tex = false
41+ tex = false,
42+ haskell = false
4243}
4344
4445M.on_confirm_done = function(opts)
lua/nvim-autopairs/completion/handlers.lua+1−1
@@ -12,7 +12,7 @@ M["*"] = function(char, item, bufnr, commit_character)
1212 local char_before, char_after = utils.text_cusor_line(line, col, 1, 1, false)
1313
1414 if char == '' or char_before == char or char_after == char
15− or (item.data and item.data.funcParensDisabled)
15+ or (item.data and type(item.data) == 'table' and item.data.funcParensDisabled)
1616 or (item.textEdit and item.textEdit.newText and item.textEdit.newText:match "[%(%[%$]")
1717 or (item.insertText and item.insertText:match "[%(%[%$]")
1818 or char == commit_character
lua/nvim-autopairs/conds.lua+52−10
@@ -1,5 +1,16 @@
11local utils = require('nvim-autopairs.utils')
22local log = require('nvim-autopairs._log')
3+---@class CondOpts
4+---@field ts_node table
5+---@field text string
6+---@field rule table
7+---@field bufnr number
8+---@field col number
9+---@field char string
10+---@field line string
11+---@field prev_char string
12+---@field next_char string
13+---@field is_endwise string
314
415local cond = {}
516
@@ -31,6 +42,7 @@ cond.before_regex = function(regex, length)
3142 if not regex then
3243 return cond.none()
3344 end
45+ ---@param opts CondOpts
3446 return function(opts)
3547 log.debug('before_regex')
3648 if length < 0 then
@@ -46,6 +58,7 @@ end
4658
4759cond.before_text = function(text)
4860 local length = #text
61+ ---@param opts CondOpts
4962 return function(opts)
5063 log.debug('before_text')
5164 local str = utils.text_sub_char(opts.line, opts.col - 1, -length)
@@ -58,6 +71,7 @@ end
5871
5972cond.after_text = function(text)
6073 local length = #text
74+ ---@param opts CondOpts
6175 return function(opts)
6276 log.debug('after_text')
6377 local str = utils.text_sub_char(opts.line, opts.col, length)
@@ -73,6 +87,7 @@ cond.after_regex = function(regex, length)
7387 if not regex then
7488 return cond.none()
7589 end
90+ ---@param opts CondOpts
7691 return function(opts)
7792 log.debug('after_regex')
7893 if length < 0 then
@@ -99,6 +114,7 @@ end
99114
100115cond.not_after_text = function(text)
101116 local length = #text
117+ ---@param opts CondOpts
102118 return function(opts)
103119 log.debug('not_after_text')
104120 local str = utils.text_sub_char(opts.line, opts.col, length)
@@ -113,6 +129,7 @@ cond.not_before_regex = function(regex, length)
113129 if not regex then
114130 return cond.none()
115131 end
132+ ---@param opts CondOpts
116133 return function(opts)
117134 log.debug('not_before_regex')
118135 if length < 0 then
@@ -130,6 +147,7 @@ cond.not_after_regex = function(regex, length)
130147 if not regex then
131148 return cond.none()
132149 end
150+ ---@param opts CondOpts
133151 return function(opts)
134152 log.debug('not_after_regex')
135153 if length < 0 then
@@ -170,7 +188,7 @@ local function is_brackets_balanced_around_position(line, open_char, close_char,
170188 elseif balance > 0 and c == close_char then
171189 balance = balance - 1
172190 if col <= i and balance == 0 then
173− break
191+ break
174192 end
175193 end
176194 end
@@ -178,15 +196,19 @@ local function is_brackets_balanced_around_position(line, open_char, close_char,
178196end
179197
180198cond.is_bracket_line = function()
199+ ---@param opts CondOpts
181200 return function(opts)
182201 log.debug('is_bracket_line')
183− if utils.is_bracket(opts.char) and opts.next_char == opts.rule.end_pair then
202+ if utils.is_bracket(opts.char) and
203+ (opts.next_char == opts.rule.end_pair
204+ or opts.next_char == opts.rule.start_pair)
205+ then
184206 -- (( many char |)) => add
185207 -- ( many char |)) => not add
186208 local count_prev_char, count_next_char = count_bracket_char(
187209 opts.line,
188− opts.char,
189− opts.next_char
210+ opts.rule.start_pair,
211+ opts.rule.end_pair
190212 )
191213 if count_prev_char ~= count_next_char then
192214 return false
@@ -196,10 +218,10 @@ cond.is_bracket_line = function()
196218end
197219
198220cond.is_bracket_line_move = function()
221+ ---@param opts CondOpts
199222 return function(opts)
200223 log.debug('is_bracket_line_move')
201− if
202− utils.is_close_bracket(opts.char)
224+ if utils.is_close_bracket(opts.char)
203225 and opts.char == opts.rule.end_pair
204226 then
205227 -- (( many char |)) => move
@@ -216,6 +238,7 @@ cond.is_bracket_line_move = function()
216238end
217239
218240cond.not_inside_quote = function()
241+ ---@param opts CondOpts
219242 return function(opts)
220243 log.debug('not_inside_quote')
221244 if utils.is_in_quotes(opts.text, opts.col - 1) then
@@ -225,6 +248,7 @@ cond.not_inside_quote = function()
225248end
226249
227250cond.is_inside_quote = function()
251+ ---@param opts CondOpts
228252 return function(opts)
229253 log.debug('is_inside_quote')
230254 if utils.is_in_quotes(opts.text, opts.col - 1) then
@@ -234,10 +258,10 @@ cond.is_inside_quote = function()
234258end
235259
236260cond.not_add_quote_inside_quote = function()
261+ ---@param opts CondOpts
237262 return function(opts)
238263 log.debug('not_add_quote_inside_quote')
239− if
240− utils.is_quote(opts.char)
264+ if utils.is_quote(opts.char)
241265 and utils.is_in_quotes(opts.text, opts.col - 1)
242266 then
243267 return false
@@ -246,6 +270,7 @@ cond.not_add_quote_inside_quote = function()
246270end
247271
248272cond.move_right = function()
273+ ---@param opts CondOpts
249274 return function(opts)
250275 log.debug('move_right')
251276 if opts.next_char == opts.char then
@@ -270,6 +295,7 @@ cond.move_right = function()
270295end
271296
272297cond.is_end_line = function()
298+ ---@param opts CondOpts
273299 return function(opts)
274300 log.debug('is_end_line')
275301 local end_text = opts.line:sub(opts.col + 1)
@@ -282,10 +308,10 @@ end
282308
283309--- Check the next char is quote and cursor is inside quote
284310cond.is_bracket_in_quote = function()
311+ ---@param opts CondOpts
285312 return function(opts)
286313 log.debug("is_bracket_in_quote")
287− if
288− utils.is_bracket(opts.char)
314+ if utils.is_bracket(opts.char)
289315 and utils.is_quote(opts.next_char)
290316 and utils.is_in_quotes(opts.line, opts.col - 1, opts.next_char)
291317 then
@@ -305,6 +331,22 @@ cond.not_filetypes = function(filetypes)
305331 end
306332end
307333
334+--- Check the character before the cursor is not equal
335+---@param char string character to compare
336+---@param index number the position of character before current curosr
337+cond.not_before_char = function(char, index)
338+ index = index or 1
339+ ---@param opts CondOpts
340+ return function(opts)
341+ log.debug('not_before_char')
342+ local match_char = #opts.line > index
343+ and opts.line:sub(#opts.line - index, #opts.line - index) or ''
344+ if match_char == char and match_char ~= "" then
345+ return false
346+ end
347+ end
348+end
349+
308350---@deprecated
309351cond.not_after_regex_check = cond.not_after_regex
310352---@deprecated
lua/nvim-autopairs/fastwrap.lua+4−12
@@ -56,7 +56,6 @@ M.show = function(line)
5656 local index = 1
5757 local str_length = #line
5858 local offset = -1
59− local is_end_key = true
6059 for i = col + 2, #line, 1 do
6160 local char = line:sub(i, i)
6261 local char2 = line:sub(i - 1, i)
@@ -74,11 +73,6 @@ M.show = function(line)
7473 offset = 0
7574 end
7675
77− if i == str_length then
78− is_end_key = false
79− key = config.end_key
80− offset = 0
81− end
8276 table.insert(
8377 list_pos,
8478 { col = i + offset, key = key, char = char, pos = i }
@@ -86,12 +80,10 @@ M.show = function(line)
8680 end
8781 end
8882
89− if is_end_key then
90− table.insert(
91− list_pos,
92− { col = str_length + 1, key = config.end_key, pos = str_length + 1 }
93− )
94− end
83+ table.insert(
84+ list_pos,
85+ { col = str_length + 1, key = config.end_key, pos = str_length + 1 }
86+ )
9587
9688 M.highlight_wrap(list_pos, row, col, #line)
9789 vim.defer_fn(function()
lua/nvim-autopairs/rule.lua+1−5
@@ -169,11 +169,7 @@ end
169169---@return Rule
170170function Rule:with_pair(cond, pos)
171171 if self.pair_cond == nil then self.pair_cond = {} end
172− if pos then
173− table.insert(self.pair_cond, pos, cond)
174− else
175− table.insert(self.pair_cond, cond)
176− end
172+ self.pair_cond[pos or (#self.pair_cond+1)] = cond
177173 return self
178174end
179175
lua/nvim-autopairs/rules/basic.lua+10−5
@@ -36,25 +36,30 @@ local function setup(opt)
3636 Rule("```.*$", "```", { 'markdown', 'vimwiki', 'rmarkdown', 'rmd', 'pandoc' })
3737 :only_cr()
3838 :use_regex(true),
39− Rule('"""', '"""', { 'python', 'elixir', 'julia', 'kotlin' }),
40− Rule("'''", "'''", { 'python' }),
39+ Rule('"""', '"""', { 'python', 'elixir', 'julia', 'kotlin' })
40+ :with_pair(cond.not_before_char('"', 3)),
41+ Rule("'''", "'''", { 'python' })
42+ :with_pair(cond.not_before_char('"', 3)),
4143 basic("'", "'", '-rust')
4244 :with_pair(cond.not_before_regex("%w")),
4345 basic("'", "'", 'rust')
4446 :with_pair(cond.not_before_regex("[%w<&]"))
4547 :with_pair(cond.not_after_text(">")),
4648 basic("`", "`"),
47− basic('"', '"','-vim'),
48− basic('"', '"','vim')
49+ basic('"', '"', '-vim'),
50+ basic('"', '"', 'vim')
4951 :with_pair(cond.not_before_regex("^%s*$", -1)),
5052 bracket("(", ")"),
5153 bracket("[", "]"),
5254 bracket("{", "}"),
5355 Rule(">[%w%s]*$", "^%s*</",
54− { 'html', 'typescript', 'typescriptreact', 'javascript' , 'javascriptreact', 'svelte', 'vue', 'xml', 'rescript'})
56+ { 'html', 'typescript', 'typescriptreact', 'javascript', 'javascriptreact', 'svelte', 'vue', 'xml',
57+ 'rescript' })
5558 :only_cr()
5659 :use_regex(true)
5760 }
5861 return rules
5962end
63+
6064return { setup = setup }
65+
lua/nvim-autopairs/utils.lua+1−1
@@ -74,7 +74,7 @@ M.is_in_quotes = function (line, pos, quote_type)
7474end
7575
7676M.is_attached = function(bufnr)
77− local _, check = pcall(api.nvim_buf_get_var, bufnr, "nvim-autopairs")
77+ local _, check = pcall(api.nvim_buf_get_var, bufnr or 0, "nvim-autopairs")
7878 return check == 1
7979end
8080
tests/nvim-autopairs_spec.lua+25−1
@@ -1,4 +1,3 @@
1−local helpers = {}
21local npairs = require('nvim-autopairs')
32local Rule = require('nvim-autopairs.rule')
43local cond = require('nvim-autopairs.conds')
@@ -50,6 +49,13 @@ local data = {
5049 before = [[""| ]],
5150 after = [["""|""" ]]
5251 },
52+ {
53+ name = "don't repeat python quote" ,
54+ filetype = "python",
55+ key = [["]],
56+ before = [[a"""|""" ]],
57+ after = [[a""""|"" ]]
58+ },
5359
5460 {
5561 name = "add markdown quote" ,
@@ -682,6 +688,24 @@ local data = {
682688 [[}]],
683689 },
684690 },
691+ {
692+ name='open bracker on back tick',
693+ key = [[(]],
694+ before = [[ |`abcd`]],
695+ after = [[ (`abcd`) ]]
696+ },
697+ {
698+ name='should not add bracket on line have bracket ',
699+ key = [[(]],
700+ before = [[ |(abcd))]],
701+ after = [[ ((abcd)) ]]
702+ },
703+ {
704+ name='not add bracket on line have bracket ',
705+ key = [[(]],
706+ before = [[ |(abcd) ( visual)]],
707+ after = [[ ()(abcd) ( visual)]]
708+ }
685709}
686710
687711local run_data = _G.Test_filter(data)