map_functions_spec.lua (8160B)
1 local t = require('test.testutil') 2 local n = require('test.functional.testnvim')() 3 4 local clear = n.clear 5 local eq = t.eq 6 local eval = n.eval 7 local exec = n.exec 8 local exec_lua = n.exec_lua 9 local expect = n.expect 10 local feed = n.feed 11 local fn = n.fn 12 local api = n.api 13 local source = n.source 14 local command = n.command 15 local exec_capture = n.exec_capture 16 local pcall_err = t.pcall_err 17 18 describe('maparg()', function() 19 before_each(clear) 20 21 local foo_bar_map_table = { 22 lhs = 'foo', 23 lhsraw = 'foo', 24 script = 0, 25 silent = 0, 26 rhs = 'bar', 27 expr = 0, 28 replace_keycodes = 0, 29 sid = 0, 30 scriptversion = 1, 31 buffer = 0, 32 nowait = 0, 33 mode = 'n', 34 mode_bits = 0x01, 35 abbr = 0, 36 noremap = 1, 37 lnum = 0, 38 } 39 40 it('returns a dict', function() 41 command('nnoremap foo bar') 42 eq('bar', fn.maparg('foo')) 43 eq(foo_bar_map_table, fn.maparg('foo', 'n', false, true)) 44 end) 45 46 it('returns 1 for silent when <silent> is used', function() 47 command('nnoremap <silent> foo bar') 48 eq(1, fn.maparg('foo', 'n', false, true)['silent']) 49 50 command('nnoremap baz bat') 51 eq(0, fn.maparg('baz', 'n', false, true)['silent']) 52 end) 53 54 it('returns an empty string when no map is present', function() 55 eq('', fn.maparg('not a mapping')) 56 end) 57 58 it('returns an empty dict when no map is present and dict is requested', function() 59 eq({}, fn.maparg('not a mapping', 'n', false, true)) 60 end) 61 62 it('returns the same value for noremap and <script>', function() 63 command('inoremap <script> hello world') 64 command('inoremap this that') 65 eq( 66 fn.maparg('hello', 'i', false, true)['noremap'], 67 fn.maparg('this', 'i', false, true)['noremap'] 68 ) 69 end) 70 71 it('returns a boolean for buffer', function() 72 -- Open enough windows to know we aren't on buffer number 1 73 command('new') 74 command('new') 75 command('new') 76 command('cnoremap <buffer> this that') 77 eq(1, fn.maparg('this', 'c', false, true)['buffer']) 78 79 -- Global will return 0 always 80 command('nnoremap other another') 81 eq(0, fn.maparg('other', 'n', false, true)['buffer']) 82 end) 83 84 it('returns script numbers', function() 85 source([[ 86 function! s:maparg_test_function() abort 87 return 'testing' 88 endfunction 89 90 nnoremap fizz :call <SID>maparg_test_function()<CR> 91 ]]) 92 eq(1, fn.maparg('fizz', 'n', false, true)['sid']) 93 eq('testing', api.nvim_call_function('<SNR>1_maparg_test_function', {})) 94 end) 95 96 it('works with <F12> and others', function() 97 source([[ 98 let g:maparg_test_var = 0 99 100 nnoremap <F12> :let g:maparg_test_var = 1<CR> 101 ]]) 102 eq(0, eval('g:maparg_test_var')) 103 source([[ 104 call feedkeys("\<F12>") 105 ]]) 106 eq(1, eval('g:maparg_test_var')) 107 108 eq(':let g:maparg_test_var = 1<CR>', fn.maparg('<F12>', 'n', false, true)['rhs']) 109 end) 110 111 it('works with <expr>', function() 112 source([[ 113 let counter = 0 114 inoremap <expr> <C-L> ListItem() 115 inoremap <expr> <C-R> ListReset() 116 117 func ListItem() 118 let g:counter += 1 119 return g:counter . '. ' 120 endfunc 121 122 func ListReset() 123 let g:counter = 0 124 return '' 125 endfunc 126 127 call feedkeys("i\<C-L>") 128 ]]) 129 eq(1, eval('g:counter')) 130 131 local map_dict = fn.maparg('<C-L>', 'i', false, true) 132 eq(1, map_dict['expr']) 133 eq('i', map_dict['mode']) 134 end) 135 136 it('works with combining characters', function() 137 -- Using addacutes to make combining character better visible 138 local function ac(s) 139 local acute = '\204\129' -- U+0301 COMBINING ACUTE ACCENT 140 local ret = s:gsub('`', acute) 141 return ret 142 end 143 command(ac([[ 144 nnoremap a b` 145 nnoremap c` d 146 nnoremap e` f` 147 ]])) 148 eq(ac('b`'), fn.maparg(ac('a'))) 149 eq(ac(''), fn.maparg(ac('c'))) 150 eq(ac('d'), fn.maparg(ac('c`'))) 151 eq(ac('f`'), fn.maparg(ac('e`'))) 152 153 local function acmap(lhs, rhs) 154 return { 155 lhs = ac(lhs), 156 lhsraw = ac(lhs), 157 rhs = ac(rhs), 158 159 buffer = 0, 160 expr = 0, 161 replace_keycodes = 0, 162 mode = 'n', 163 mode_bits = 0x01, 164 abbr = 0, 165 noremap = 1, 166 nowait = 0, 167 script = 0, 168 sid = 0, 169 scriptversion = 1, 170 silent = 0, 171 lnum = 0, 172 } 173 end 174 175 eq({}, fn.maparg(ac('c'), 'n', 0, 1)) 176 eq(acmap('a', 'b`'), fn.maparg(ac('a'), 'n', 0, 1)) 177 eq(acmap('c`', 'd'), fn.maparg(ac('c`'), 'n', 0, 1)) 178 eq(acmap('e`', 'f`'), fn.maparg(ac('e`'), 'n', 0, 1)) 179 end) 180 end) 181 182 describe('mapset()', function() 183 before_each(clear) 184 185 it('can restore mapping with backslash in lhs', function() 186 api.nvim_set_keymap('n', '\\ab', 'a', {}) 187 eq('\nn \\ab a', exec_capture('nmap \\ab')) 188 local mapargs = fn.maparg('\\ab', 'n', false, true) 189 api.nvim_set_keymap('n', '\\ab', 'b', {}) 190 eq('\nn \\ab b', exec_capture('nmap \\ab')) 191 fn.mapset('n', false, mapargs) 192 eq('\nn \\ab a', exec_capture('nmap \\ab')) 193 end) 194 195 it('can restore mapping description from the dict returned by maparg()', function() 196 api.nvim_set_keymap('n', 'lhs', 'rhs', { desc = 'map description' }) 197 eq('\nn lhs rhs\n map description', exec_capture('nmap lhs')) 198 local mapargs = fn.maparg('lhs', 'n', false, true) 199 api.nvim_set_keymap('n', 'lhs', 'rhs', { desc = 'MAP DESCRIPTION' }) 200 eq('\nn lhs rhs\n MAP DESCRIPTION', exec_capture('nmap lhs')) 201 fn.mapset('n', false, mapargs) 202 eq('\nn lhs rhs\n map description', exec_capture('nmap lhs')) 203 end) 204 205 it('can restore "replace_keycodes" from the dict returned by maparg()', function() 206 api.nvim_set_keymap('i', 'foo', [['<l' .. 't>']], { expr = true, replace_keycodes = true }) 207 feed('Afoo') 208 expect('<') 209 local mapargs = fn.maparg('foo', 'i', false, true) 210 api.nvim_set_keymap('i', 'foo', [['<l' .. 't>']], { expr = true }) 211 feed('foo') 212 expect('<<lt>') 213 fn.mapset('i', false, mapargs) 214 feed('foo') 215 expect('<<lt><') 216 end) 217 218 it('replaces an abbreviation of the same lhs #20320', function() 219 command('inoreabbr foo bar') 220 eq('\ni foo * bar', exec_capture('iabbr foo')) 221 feed('ifoo ') 222 expect('bar ') 223 local mapargs = fn.maparg('foo', 'i', true, true) 224 command('inoreabbr foo BAR') 225 eq('\ni foo * BAR', exec_capture('iabbr foo')) 226 feed('foo ') 227 expect('bar BAR ') 228 fn.mapset('i', true, mapargs) 229 eq('\ni foo * bar', exec_capture('iabbr foo')) 230 feed('foo<Esc>') 231 expect('bar BAR bar') 232 end) 233 234 it('can restore Lua callback from the dict returned by maparg()', function() 235 eq( 236 0, 237 exec_lua([[ 238 GlobalCount = 0 239 vim.api.nvim_set_keymap('n', 'asdf', '', { 240 callback = function() GlobalCount = GlobalCount + 1 end, 241 }) 242 return GlobalCount 243 ]]) 244 ) 245 feed('asdf') 246 eq(1, exec_lua([[return GlobalCount]])) 247 248 exec_lua([[ 249 _G.saved_asdf_map = vim.fn.maparg('asdf', 'n', false, true) 250 vim.api.nvim_set_keymap('n', 'asdf', '', { 251 callback = function() GlobalCount = GlobalCount + 10 end, 252 }) 253 ]]) 254 feed('asdf') 255 eq(11, exec_lua([[return GlobalCount]])) 256 257 exec_lua([[vim.fn.mapset('n', false, _G.saved_asdf_map)]]) 258 feed('asdf') 259 eq(12, exec_lua([[return GlobalCount]])) 260 261 exec([[ 262 let g:saved_asdf_map = maparg('asdf', 'n', v:false, v:true) 263 lua << 264 vim.api.nvim_set_keymap('n', 'asdf', '', { 265 callback = function() GlobalCount = GlobalCount + 10 end, 266 }) 267 ]]) 268 feed('asdf') 269 eq(22, exec_lua([[return GlobalCount]])) 270 271 command([[call mapset('n', v:false, g:saved_asdf_map)]]) 272 feed('asdf') 273 eq(23, exec_lua([[return GlobalCount]])) 274 end) 275 276 it('does not leak memory if lhs is missing', function() 277 eq( 278 'Vim:E460: Entries missing in mapset() dict argument', 279 pcall_err(exec_lua, [[vim.fn.mapset('n', false, {rhs = 'foo'})]]) 280 ) 281 eq( 282 'Vim:E460: Entries missing in mapset() dict argument', 283 pcall_err(exec_lua, [[vim.fn.mapset('n', false, {callback = function() end})]]) 284 ) 285 end) 286 end)