langmap_spec.lua (8717B)
1 local t = require('test.testutil') 2 local n = require('test.functional.testnvim')() 3 4 local eq, neq, call = t.eq, t.neq, n.call 5 local eval, feed, clear = n.eval, n.feed, n.clear 6 local command, insert, expect = n.command, n.insert, n.expect 7 local feed_command = n.feed_command 8 local curwin = n.api.nvim_get_current_win 9 10 describe("'langmap'", function() 11 before_each(function() 12 clear() 13 insert('iii www') 14 command('set langmap=iw,wi') 15 feed('gg0') 16 end) 17 18 it('converts keys in normal mode', function() 19 feed('ix') 20 expect('iii ww') 21 feed('whello<esc>') 22 expect('iii helloww') 23 end) 24 it('gives characters that are mapped by :nmap.', function() 25 command('map i 0x') 26 feed('w') 27 expect('ii www') 28 end) 29 describe("'langnoremap' option.", function() 30 before_each(function() 31 command('nmapclear') 32 end) 33 it("'langnoremap' is by default ON", function() 34 eq(1, eval('&langnoremap')) 35 end) 36 it("Results of maps are not converted when 'langnoremap' ON.", function() 37 command('nmap x i') 38 feed('xdl<esc>') 39 expect('dliii www') 40 end) 41 it('applies when deciding whether to map recursively', function() 42 command('nmap l i') 43 command('nmap w j') 44 feed('ll') 45 expect('liii www') 46 end) 47 it("does not stop applying 'langmap' on first character of a mapping", function() 48 command('1t1') 49 command('1t1') 50 command('goto 1') 51 command('nmap w j') 52 feed('iiahello') 53 expect([[ 54 iii www 55 iii www 56 ihelloii www]]) 57 end) 58 it("Results of maps are converted when 'langnoremap' OFF.", function() 59 command('set nolangnoremap') 60 command('nmap x i') 61 feed('xdl<esc>') 62 expect('iii ww') 63 end) 64 end) 65 -- e.g. CTRL-W_j , mj , 'j and "jp 66 it('conversions are applied to keys in middle of command', function() 67 -- Works in middle of window command 68 feed('<C-w>s') 69 local origwin = curwin() 70 feed('<C-w>i') 71 neq(origwin, curwin()) 72 -- Works when setting a mark 73 feed('yy3p3gg0mwgg0mi') 74 eq({ 0, 3, 1, 0 }, call('getpos', "'i")) 75 eq({ 0, 1, 1, 0 }, call('getpos', "'w")) 76 feed('3dd') 77 -- Works when moving to a mark 78 feed("'i") 79 eq({ 0, 1, 1, 0 }, call('getpos', '.')) 80 -- Works when selecting a register 81 feed('qillqqwhhq') 82 eq('hh', eval('@i')) 83 eq('ll', eval('@w')) 84 feed('a<C-r>i<esc>') 85 expect('illii www') 86 feed('"ip') 87 expect('illllii www') 88 -- Works with i_CTRL-O 89 feed('0a<C-O>ihi<esc>') 90 expect('illllii hiwww') 91 end) 92 93 describe('exceptions', function() 94 -- All "command characters" that 'langmap' does not apply to. 95 -- These tests consist of those places where some subset of ASCII 96 -- characters define certain commands, yet 'langmap' is not applied to 97 -- them. 98 -- n.b. I think these shouldn't be exceptions. 99 it(':s///c confirmation', function() 100 command('set langmap=yn,ny') 101 feed('qa') 102 feed_command('s/i/w/gc') 103 feed('yynq') 104 expect('wwi www') 105 feed('u@a') 106 expect('wwi www') 107 eq(':s/i/w/gc\ryyn', eval('@a')) 108 end) 109 it('insert-mode CTRL-G', function() 110 command('set langmap=jk,kj') 111 command('d') 112 insert([[ 113 hello 114 hello 115 hello]]) 116 expect([[ 117 hello 118 hello 119 hello]]) 120 feed('qa') 121 feed('gg3|ahello<C-G>jx<esc>') 122 feed('q') 123 expect([[ 124 helhellolo 125 helxlo 126 hello]]) 127 eq('gg3|ahellojx', eval('@a')) 128 end) 129 it('command-line CTRL-\\', function() 130 command('set langmap=en,ne') 131 feed(':<C-\\>e\'hello\'\r<C-B>put ="<C-E>"<CR>') 132 expect([[ 133 iii www 134 hello]]) 135 end) 136 it('command-line CTRL-R', function() 137 n.source([[ 138 let i_value = 0 139 let j_value = 0 140 call setreg('i', 'i_value') 141 call setreg('j', 'j_value') 142 set langmap=ij,ji 143 ]]) 144 feed(':let <C-R>i=1<CR>') 145 eq(1, eval('i_value')) 146 eq(0, eval('j_value')) 147 end) 148 -- it('-- More -- prompt', function() 149 -- -- The 'b' 'j' 'd' 'f' commands at the -- More -- prompt 150 -- end) 151 it('ask yes/no after backwards range', function() 152 command('set langmap=yn,ny') 153 feed('dd') 154 insert([[ 155 hello 156 there 157 these 158 are 159 some 160 lines 161 ]]) 162 feed_command('4,2d') 163 feed('n') 164 expect([[ 165 hello 166 there 167 these 168 are 169 some 170 lines 171 ]]) 172 end) 173 it('prompt for number', function() 174 command('set langmap=12,21') 175 n.source([[ 176 let gotten_one = 0 177 function Map() 178 let answer = inputlist(['a', '1.', '2.', '3.']) 179 if answer == 1 180 let g:gotten_one = 1 181 endif 182 endfunction 183 nnoremap x :call Map()<CR> 184 ]]) 185 feed('x1<CR>') 186 eq(1, eval('gotten_one')) 187 command('let g:gotten_one = 0') 188 feed_command('call Map()') 189 feed('1<CR>') 190 eq(1, eval('gotten_one')) 191 end) 192 end) 193 it('conversions are not applied during setreg()', function() 194 call('setreg', 'i', 'ww') 195 eq('ww', eval('@i')) 196 end) 197 it('conversions not applied in insert mode', function() 198 feed('aiiiwww') 199 expect('iiiiwwwii www') 200 end) 201 it('conversions not applied in search mode', function() 202 feed('/iii<cr>x') 203 expect('ii www') 204 end) 205 it('conversions not applied in cmdline mode', function() 206 feed(':call append(1, "iii")<cr>') 207 expect([[ 208 iii www 209 iii]]) 210 end) 211 212 local function testrecording(command_string, expect_string, setup_function, expect_macro) 213 if setup_function then 214 setup_function() 215 end 216 feed('qa' .. command_string .. 'q') 217 expect(expect_string) 218 eq(expect_macro or n.fn.nvim_replace_termcodes(command_string, true, true, true), eval('@a')) 219 if setup_function then 220 setup_function() 221 end 222 -- n.b. may need nvim_replace_termcodes() here. 223 feed('@a') 224 expect(expect_string) 225 end 226 227 local function local_setup() 228 -- Can't use `insert` as it uses `i` and we've swapped the meaning of that 229 -- with the `langmap` setting. 230 command('%d') 231 command("put ='hello'") 232 command('1d') 233 end 234 235 it('does not affect recording special keys', function() 236 testrecording('A<BS><esc>', 'hell', local_setup) 237 testrecording('>><lt><lt>', 'hello', local_setup) 238 command('nnoremap \\ x') 239 testrecording('\\', 'ello', local_setup) 240 testrecording('A<C-V><BS><esc>', 'hello<BS>', local_setup) 241 end) 242 pending('Translates modified keys correctly', function() 243 command('nnoremap <M-i> x') 244 command('nnoremap <M-w> l') 245 testrecording('<M-w>', 'ello', local_setup) 246 testrecording('<M-i>x', 'hllo', local_setup) 247 end) 248 pending('handles multi-byte characters', function() 249 command('set langmap=ïx') 250 testrecording('ï', 'ello', local_setup) 251 -- The test below checks that what's recorded is correct. 252 -- It doesn't check the behaviour, as in order to cause some behaviour we 253 -- need to map the multi-byte character, and there is a known bug 254 -- preventing this from working (see the test below). 255 command('set langmap=xï') 256 testrecording('x', 'hello', local_setup) 257 end) 258 pending('handles multibyte mappings', function() 259 -- See this vim issue for the problem, may as well add a test. 260 -- https://github.com/vim/vim/issues/297 261 command('set langmap=ïx') 262 command('nnoremap x diw') 263 testrecording('ï', '', local_setup) 264 command('set nolangnoremap') 265 command('set langmap=xï') 266 command('nnoremap ï ix<esc>') 267 testrecording('x', 'xhello', local_setup) 268 end) 269 it('does not crash when mapping char < 256 to char >= 256', function() 270 -- Note: this warning should be removed when the pending tests above are fixed. 271 local wmsg = table.concat({ 272 "'langmap': Mapping from e to ε will not work properly", 273 "'langmap': Mapping from ü to μ will not work properly", 274 }, '\n') 275 -- ä ë ï ö ü ÿ < 256, β γ ε μ >= 256 276 command('set langmap=iw,wi,äë,ëä,ïx,xï,βγ,γβ,eε,εe,üμ,μü,ÿy,yÿ') 277 eq(wmsg, n.exec_capture('messages')) 278 command('messages clear | set langmap=iwäëïxβγeεüμÿy;wiëäxïγβεeμüyÿ') 279 eq(wmsg, n.exec_capture('messages')) 280 end) 281 -- This test is to ensure the behaviour doesn't change from what's already 282 -- around. I (hardenedapple) personally think this behaviour should be 283 -- changed. 284 it('treats control modified keys as characters', function() 285 command('nnoremap <C-w> iw<esc>') 286 command('nnoremap <C-i> ii<esc>') 287 testrecording('<C-w>', 'whello', local_setup, eval([["\<*C-w>"]])) 288 testrecording('<C-i>', 'ihello', local_setup, eval([["\<*C-i>"]])) 289 end) 290 end)