diff --git a/lua/cmp/utils/keymap.lua b/lua/cmp/utils/keymap.lua index b59ce6e..c65e5ce 100644 --- a/lua/cmp/utils/keymap.lua +++ b/lua/cmp/utils/keymap.lua @@ -102,7 +102,7 @@ keymap.listen = function(mode, lhs, callback) end local bufnr = existing.buffer and vim.api.nvim_get_current_buf() or -1 - local fallback = keymap.evacuate(bufnr, mode, existing) + local fallback = keymap.fallback(bufnr, mode, existing) keymap.set_map(bufnr, mode, lhs, function() if mode == 'c' and vim.fn.getcmdtype() == '=' then vim.api.nvim_feedkeys(fallback.keys, 'it' .. (fallback.noremap and 'n' or 'm'), true) @@ -121,19 +121,19 @@ keymap.listen = function(mode, lhs, callback) }) end ----Evacuate existing mapping. +---Fallback existing mapping. --- NOTE: ---- In insert-mode, we should all mapping evacuate to the `` because `=` will display gabage message. +--- In insert-mode, we should all mapping fallback to the `` because `=` will display gabage message. --- In cmdline-mode, we shouldn't re-map as `` because `cmap (map-to-tab)` will broke native behavior. --- We should resolve recursive mapping because existing mapping will feed by `feedkeys` that doesn't solve recursive mapping. --- We use `=` to solve recursive mapping. ---@param map table -keymap.evacuate = setmetatable({ +keymap.fallback = setmetatable({ cache = cache.new(), }, { __call = function(self, bufnr, mode, map) local fallback = self.cache:ensure({ bufnr, mode, map.lhs }, function() - return string.format('(cmp.u.k.evacuate:%s)', misc.id('cmp.utils.keymap.evacuate')) + return string.format('(cmp.u.k.fallback:%s)', misc.id('cmp.utils.keymap.fallback')) end) if map.expr then diff --git a/lua/cmp/utils/keymap_spec.lua b/lua/cmp/utils/keymap_spec.lua index 561b851..3b3dce3 100644 --- a/lua/cmp/utils/keymap_spec.lua +++ b/lua/cmp/utils/keymap_spec.lua @@ -1,4 +1,6 @@ local spec = require('cmp.utils.spec') +local api = require('cmp.utils.api') +local feedkeys = require('cmp.utils.feedkeys') local keymap = require('cmp.utils.keymap') @@ -32,56 +34,65 @@ describe('keymap', function() assert.are.equal(keymap.to_keymap('|'), '') end) - describe('evacuate', function() + describe('fallback', function() before_each(spec.before) - it('expr & register', function() - vim.api.nvim_buf_set_keymap(0, 'i', '(', [['="("']], { + local keys = function(keys, mode) + local state = {} + feedkeys.call(keys, mode, function() + if api.is_cmdline_mode() then + state.buffer = { api.get_current_line() } + else + state.buffer = vim.api.nvim_buf_get_lines(0, 0, -1, false) + end + state.cursor = api.get_cursor() + state.wildmenumode = vim.fn.wildmenumode() == 1 + end) + feedkeys.call('', 'x') + return state + end + + it('recursive', function() + vim.api.nvim_buf_set_keymap(0, 'i', '(', '()', { + expr = false, + noremap = false, + silent = true, + }) + local fallback = keymap.fallback(0, 'i', keymap.get_map('i', '(')) + local state = keys('i' .. fallback.keys, fallback.noremap and 'n' or 'm') + assert.are.same({ '()' }, state.buffer) + assert.are.same({ 1, 1 }, state.cursor) + end) + + it('recursive expr', function() + vim.api.nvim_buf_set_keymap(0, 'i', '(', '"()"', { expr = true, noremap = false, + silent = true, }) - local fallback = keymap.evacuate(0, 'i', keymap.get_map('i', '(')) - vim.api.nvim_feedkeys('i' .. fallback.keys, 'x' .. (fallback.noremap and 'n' or 'm'), true) - assert.are.same({ '(' }, vim.api.nvim_buf_get_lines(0, 0, -1, true)) + local fallback = keymap.fallback(0, 'i', keymap.get_map('i', '(')) + local state = keys('i' .. fallback.keys, fallback.noremap and 'n' or 'm') + assert.are.same({ '()' }, state.buffer) + assert.are.same({ 1, 1 }, state.cursor) end) - it('recursive & (tpope/vim-endwise)', function() - vim.api.nvim_buf_set_keymap(0, 'i', '(paren-close)', [[)]], { - expr = false, - noremap = true, - }) - vim.api.nvim_buf_set_keymap(0, 'i', '(', [[((paren-close)]], { - expr = false, + it('recursive callback', function() + vim.api.nvim_buf_set_keymap(0, 'i', '(', '', { + expr = true, noremap = false, + silent = true, + callback = function() + return keymap.t('()') + end }) - local fallback = keymap.evacuate(0, 'i', keymap.get_map('i', '(')) - vim.api.nvim_feedkeys('i' .. fallback.keys, 'x' .. (fallback.noremap and 'n' or 'm'), true) - assert.are.same({ '()' }, vim.api.nvim_buf_get_lines(0, 0, -1, true)) + local fallback = keymap.fallback(0, 'i', keymap.get_map('i', '(')) + local state = keys('i' .. fallback.keys, fallback.noremap and 'n' or 'm') + assert.are.same({ '()' }, state.buffer) + assert.are.same({ 1, 1 }, state.cursor) end) - describe('expr & recursive', function() - before_each(spec.before) - - it('true', function() - vim.api.nvim_buf_set_keymap(0, 'i', '', [[v:true ? '="foobar"' : 'aiueo']], { - expr = true, - noremap = false, - }) - local fallback = keymap.evacuate(0, 'i', keymap.get_map('i', '')) - vim.api.nvim_feedkeys('i' .. fallback.keys, 'x' .. (fallback.noremap and 'n' or 'm'), true) - assert.are.same({ 'foobar' }, vim.api.nvim_buf_get_lines(0, 0, -1, true)) - end) - it('false', function() - vim.api.nvim_buf_set_keymap(0, 'i', '', [[v:false ? '="foobar"' : 'aiueo']], { - expr = true, - noremap = false, - }) - local fallback = keymap.evacuate(0, 'i', keymap.get_map('i', '')) - vim.api.nvim_feedkeys('i' .. fallback.keys, 'x' .. (fallback.noremap and 'n' or 'm'), true) - assert.are.same({ '\taiueo' }, vim.api.nvim_buf_get_lines(0, 0, -1, true)) - end) - end) end) + describe('realworld', function() before_each(spec.before) it('#226', function()