Skip to content

Commit 95dd9ee

Browse files
committed
fix(surround): ignore buffer-local s mapping when mapping to <Nop>
Details: - Currently presence of buffer-local `s` mapping is detected as a reason to not create global `s`-><Nop> mapping. This is not the intended behavior (a side effect of `vim.fn.maparg()` first checking buffer-local mapping with falling back on a global one). This is also visible in the case of 'mini.starter' plus 'mini.surround' loading behind `MiniDeps.later()` (like in MiniMax): there is no global `s`-><Nop> created as Starter buffer has buffer-local mapping to `s`.
1 parent d1a9158 commit 95dd9ee

File tree

2 files changed

+38
-17
lines changed

2 files changed

+38
-17
lines changed

lua/mini/surround.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2265,7 +2265,8 @@ H.map = function(mode, lhs, rhs, opts)
22652265
if lhs == '' then return end
22662266
opts = vim.tbl_deep_extend('force', { silent = true }, opts or {})
22672267
vim.keymap.set(mode, lhs, rhs, opts)
2268-
if vim.fn.maparg('s', mode) == '' and lhs:find('^s.') ~= nil then vim.keymap.set(mode, 's', '<Nop>') end
2268+
local no_global_s_mapping = vim.fn.maparg('s', mode, false, true).buffer ~= 0
2269+
if no_global_s_mapping and lhs:find('^s.') ~= nil then vim.keymap.set(mode, 's', '<Nop>') end
22692270
end
22702271

22712272
H.get_line_cols = function(line_num) return vim.fn.getline(line_num):len() end

tests/test_surround.lua

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -168,47 +168,46 @@ end
168168
T['setup()']['properly handles `config.mappings`'] = function()
169169
local has_surround_map = function(lhs, mode) return child.fn.maparg(lhs, mode):find('[Ss]urround') ~= nil end
170170

171+
local make_clean_state = function()
172+
unload_module()
173+
for _, map in ipairs(child.api.nvim_get_keymap('n')) do
174+
child.api.nvim_del_keymap('n', map.lhs)
175+
end
176+
for _, map in ipairs(child.api.nvim_get_keymap('x')) do
177+
child.api.nvim_del_keymap('x', map.lhs)
178+
end
179+
end
180+
171181
-- Regular mappings
172182
eq(has_surround_map('sa', 'n'), true)
173183

174184
-- Should map "s" to <Nop>, but only if needed
175185
eq(child.fn.maparg('s', 'n'), '<Nop>')
176186
eq(child.fn.maparg('s', 'x'), '<Nop>')
177187

178-
unload_module()
179-
child.api.nvim_del_keymap('n', 'sa')
180-
181188
-- Supplying empty string should mean "don't create keymap"
189+
make_clean_state()
182190
load_module({ mappings = { add = '' } })
183191
eq(has_surround_map('sa', 'n'), false)
184192

185193
-- Extended mappings
186194
eq(has_surround_map('sdl', 'n'), true)
187195
eq(has_surround_map('sdn', 'n'), true)
188196

189-
unload_module()
190-
child.api.nvim_del_keymap('n', 'sd')
191-
child.api.nvim_del_keymap('n', 'sdl')
192-
child.api.nvim_del_keymap('n', 'sdn')
193-
child.api.nvim_del_keymap('n', 'srl')
194-
child.api.nvim_del_keymap('n', 'srn')
195-
197+
make_clean_state()
196198
load_module({ mappings = { delete = '', suffix_last = '' } })
197199
eq(has_surround_map('sdl', 'n'), false)
198200
eq(has_surround_map('sdn', 'n'), false)
199201
eq(has_surround_map('srl', 'n'), false)
200202
eq(has_surround_map('srn', 'n'), true)
201203

202204
-- Should precisely set 's' keymap
203-
unload_module()
204-
child.api.nvim_del_keymap('n', 'sa')
205-
child.api.nvim_del_keymap('n', 's')
206-
child.api.nvim_del_keymap('x', 's')
207-
208-
load_module({ mappings = { add = 'cs' } })
205+
make_clean_state()
206+
load_module({ mappings = { add = 'cs', delete = 'sd' } })
209207
eq(child.fn.maparg('s', 'n'), '<Nop>')
210208
eq(child.fn.maparg('s', 'x'), '')
211209

210+
-- - Should ignore presence of buffer-local mappings
212211
local vim_surround_mappings = {
213212
add = 'ys',
214213
delete = 'ds',
@@ -220,16 +219,37 @@ T['setup()']['properly handles `config.mappings`'] = function()
220219
suffix_next = '',
221220
}
222221
-- - Should also not override already present user mapping for `s`
222+
make_clean_state()
223223
child.cmd('nmap s <Cmd>echo 1<CR>')
224224
load_module({ mappings = vim_surround_mappings })
225225
eq(child.fn.maparg('s', 'n'), '<Cmd>echo 1<CR>')
226226
eq(child.fn.maparg('s', 'x'), '')
227227

228228
-- - Should allow creating a plain `s` as a mapping
229229
vim_surround_mappings.add = 's'
230+
make_clean_state()
230231
load_module({ mappings = vim_surround_mappings })
231232
eq(has_surround_map('s', 'n'), true)
232233
eq(has_surround_map('s', 'x'), true)
234+
235+
-- - Should ignore buffer-local `s` mappings and still create global `<Nop>`
236+
make_clean_state()
237+
child.cmd('nmap <buffer> s <Cmd>echo 1<CR>')
238+
child.cmd('xmap <buffer> s <Cmd>echo 2<CR>')
239+
load_module()
240+
eq(child.fn.maparg('s', 'n'), '<Cmd>echo 1<CR>')
241+
eq(child.fn.maparg('s', 'x'), '<Cmd>echo 2<CR>')
242+
243+
local get_global_mapping = function(mode, lhs)
244+
for _, map in ipairs(child.api.nvim_get_keymap(mode)) do
245+
if map.lhs == lhs then return map end
246+
end
247+
return {}
248+
end
249+
-- - NOTE: `nvim_get_keymap()` return `rhs=''` if it is mapped to `<Nop>`
250+
-- For absent mapping it would have been `nil`
251+
eq(get_global_mapping('x', 's').rhs, '')
252+
eq(get_global_mapping('x', 's').rhs, '')
233253
end
234254

235255
T['update_n_lines()'] = new_set({

0 commit comments

Comments
 (0)