diff options
| -rw-r--r-- | src/nvim/macros.h | 2 | ||||
| -rw-r--r-- | test/functional/normal/langmap_spec.lua | 280 | 
2 files changed, 281 insertions, 1 deletions
| diff --git a/src/nvim/macros.h b/src/nvim/macros.h index a98c1e05a0..0406574990 100644 --- a/src/nvim/macros.h +++ b/src/nvim/macros.h @@ -75,7 +75,7 @@    do { \      if (*p_langmap \          && (condition) \ -        && (p_lrm || KeyTyped) \ +        && (p_lrm || (vgetc_busy ? typebuf_maplen() == 0 : KeyTyped)) \          && !KeyStuffed \          && (c) >= 0) \      { \ diff --git a/test/functional/normal/langmap_spec.lua b/test/functional/normal/langmap_spec.lua new file mode 100644 index 0000000000..e4349a22e7 --- /dev/null +++ b/test/functional/normal/langmap_spec.lua @@ -0,0 +1,280 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq, neq, call = helpers.eq, helpers.neq, helpers.call +local eval, feed, clear = helpers.eval, helpers.feed, helpers.clear +local command, insert, expect = helpers.command, helpers.insert, helpers.expect +local feed_command = helpers.feed_command +local curwin = helpers.curwin + +describe("'langmap'", function() +  before_each(function() +    clear() +    insert('iii www') +    command('set langmap=iw,wi') +    feed('gg0') +  end) + +  it("converts keys in normal mode", function() +    feed('ix') +    expect('iii ww') +    feed('whello<esc>') +    expect('iii helloww') +  end) +  it("gives characters that are mapped by :nmap.", function() +    command('map i 0x') +    feed('w') +    expect('ii www') +  end) +  describe("'langnoremap' option.", function() +    before_each(function() +      command('nmapclear') +    end) +    it("'langnoremap' is by default ON", function() +      eq(eval('&langnoremap'), 1) +    end) +    it("Results of maps are not converted when 'langnoremap' ON.", +    function() +      command('nmap x i') +      feed('xdl<esc>') +      expect('dliii www') +    end) +    it("applies when deciding whether to map recursively", function() +      command('nmap l i') +      command('nmap w j') +      feed('ll') +      expect('liii www') +    end) +    it("does not stop applying 'langmap' on first character of a mapping", +    function() +      command('1t1') +      command('1t1') +      command('goto 1') +      command('nmap w j') +      feed('iiahello') +      expect([[ +      iii www +      iii www +      ihelloii www]]) +    end) +    it("Results of maps are converted when 'langnoremap' OFF.", +    function() +      command('set nolangnoremap') +      command('nmap x i') +      feed('xdl<esc>') +      expect('iii ww') +    end) +  end) +  -- e.g. CTRL-W_j  ,  mj , 'j and "jp +  it('conversions are applied to keys in middle of command', +  function() +    -- Works in middle of window command +    feed('<C-w>s') +    local origwin = curwin() +    feed('<C-w>i') +    neq(curwin(), origwin) +    -- Works when setting a mark +    feed('yy3p3gg0mwgg0mi') +    eq(call('getpos', "'i"), {0, 3, 1, 0}) +    eq(call('getpos', "'w"), {0, 1, 1, 0}) +    feed('3dd') +    -- Works when moving to a mark +    feed("'i") +    eq(call('getpos', '.'), {0, 1, 1, 0}) +    -- Works when selecting a register +    feed('qillqqwhhq') +    eq(eval('@i'), 'hh') +    eq(eval('@w'), 'll') +    feed('a<C-r>i<esc>') +    expect('illii www') +    feed('"ip') +    expect('illllii www') +    -- Works with i_CTRL-O +    feed('0a<C-O>ihi<esc>') +    expect('illllii hiwww') +  end) + +  describe('exceptions', function() +    -- All "command characters" that 'langmap' does not apply to. +    -- These tests consist of those places where some subset of ASCII +    -- characters define certain commands, yet 'langmap' is not applied to +    -- them. +    -- n.b. I think these shouldn't be exceptions. +    it(':s///c confirmation', function() +      command('set langmap=yn,ny') +      feed('qa') +      feed_command('s/i/w/gc') +      feed('yynq') +      expect('wwi www') +      feed('u@a') +      expect('wwi www') +      eq(eval('@a'), ':s/i/w/gc\ryyn') +    end) +    it('insert-mode CTRL-G', function() +      command('set langmap=jk,kj') +      command('d') +      insert([[ +      hello +      hello +      hello]]) +      expect([[ +      hello +      hello +      hello]]) +      feed('qa') +      feed('gg3|ahello<C-G>jx<esc>') +      feed('q') +      expect([[ +      helhellolo +      helxlo +      hello]]) +      eq(eval('@a'), 'gg3|ahellojx') +    end) +    it('command-line CTRL-\\', function() +      command('set langmap=en,ne') +      feed(':<C-\\>e\'hello\'\r<C-B>put ="<C-E>"<CR>') +      expect([[ +      iii www +      hello]]) +    end) +    it('command-line CTRL-R', function() +      helpers.source([[ +        let i_value = 0 +        let j_value = 0 +        call setreg('i', 'i_value') +        call setreg('j', 'j_value') +        set langmap=ij,ji +      ]]) +      feed(':let <C-R>i=1<CR>') +      eq(eval('i_value'), 1) +      eq(eval('j_value'), 0) +    end) +    -- it('-- More -- prompt', function() +    --   -- The 'b' 'j' 'd' 'f' commands at the -- More -- prompt +    -- end) +    it('ask yes/no after backwards range', function() +      command('set langmap=yn,ny') +      feed('dd') +      insert([[ +      hello +      there +      these +      are +      some +      lines +      ]]) +      feed_command('4,2d') +      feed('n') +      expect([[ +      hello +      there +      these +      are +      some +      lines +      ]]) +    end) +    it('prompt for number', function() +      command('set langmap=12,21') +      helpers.source([[ +        let gotten_one = 0 +        function Map() +          let answer = inputlist(['a', '1.', '2.', '3.']) +          if answer == 1 +            let g:gotten_one = 1 +          endif +        endfunction +        nnoremap x :call Map()<CR> +      ]]) +      feed('x1<CR>') +      eq(eval('gotten_one'), 1) +      command('let g:gotten_one = 0') +      feed_command('call Map()') +      feed('1<CR>') +      eq(eval('gotten_one'), 1) +    end) +  end) +  it('conversions are not applied during setreg()', +  function() +    call('setreg', 'i', 'ww') +    eq(eval('@i'), 'ww') +  end) +  it('conversions not applied in insert mode', function() +    feed('aiiiwww') +    expect('iiiiwwwii www') +  end) +  it('conversions not applied in search mode', function() +    feed('/iii<cr>x') +    expect('ii www') +  end) +  it('conversions not applied in cmdline mode', function() +    feed(':call append(1, "iii")<cr>') +    expect([[ +    iii www +    iii]]) +  end) + +  local function testrecording(command_string, expect_string, setup_function) +    if setup_function then setup_function() end +    feed('qa' .. command_string .. 'q') +    expect(expect_string) +    eq(helpers.funcs.nvim_replace_termcodes(command_string, true, true, true), +      eval('@a')) +    if setup_function then setup_function() end +    -- n.b. may need nvim_replace_termcodes() here. +    feed('@a') +    expect(expect_string) +  end + +  local function local_setup() +    -- Can't use `insert` as it uses `i` and we've swapped the meaning of that +    -- with the `langmap` setting. +    command('%d') +    command("put ='hello'") +    command('1d') +  end + +  it('does not affect recording special keys', function() +    testrecording('A<BS><esc>', 'hell', local_setup) +    testrecording('>><lt><lt>', 'hello', local_setup) +    command('nnoremap \\ x') +    testrecording('\\', 'ello', local_setup) +    testrecording('A<C-V><BS><esc>', 'hello<BS>', local_setup) +  end) +  pending('Translates modified keys correctly', function() +    command('nnoremap <M-i> x') +    command('nnoremap <M-w> l') +    testrecording('<M-w>', 'ello', local_setup) +    testrecording('<M-i>x', 'hllo', local_setup) +  end) +  pending('handles multi-byte characters', function() +    command('set langmap=ïx') +    testrecording('ï', 'ello', local_setup) +    -- The test below checks that what's recorded is correct. +    -- It doesn't check the behaviour, as in order to cause some behaviour we +    -- need to map the multi-byte character, and there is a known bug +    -- preventing this from working (see the test below). +    command('set langmap=xï') +    testrecording('x', 'hello', local_setup) +  end) +  pending('handles multibyte mappings', function() +    -- See this vim issue for the problem, may as well add a test. +    -- https://github.com/vim/vim/issues/297 +    command('set langmap=ïx') +    command('nnoremap x diw') +    testrecording('ï', '', local_setup) +    command('set nolangnoremap') +    command('set langmap=xï') +    command('nnoremap ï ix<esc>') +    testrecording('x', 'xhello', local_setup) +  end) +  -- This test is to ensure the behaviour doesn't change from what's already +  -- around. I (hardenedapple) personally think this behaviour should be +  -- changed. +  it('treats control modified keys as characters', function() +    command('nnoremap <C-w> iw<esc>') +    command('nnoremap <C-i> ii<esc>') +    testrecording('<C-w>', 'whello', local_setup) +    testrecording('<C-i>', 'ihello', local_setup) +  end) + +end) | 
