diff --git a/lua/cmp/utils/keymap.lua b/lua/cmp/utils/keymap.lua index 681b0ee..2a07717 100644 --- a/lua/cmp/utils/keymap.lua +++ b/lua/cmp/utils/keymap.lua @@ -142,17 +142,14 @@ keymap.evacuate = function(mode, lhs) -- Keep existing mapping as mapping. We escape fisrt recursive key sequence. See `:help recursive_mapping`) local rhs = map.rhs if map.noremap == 0 then - local fallback_lhs = ('(cmp-utils-keymap-listen-lhs:%s)'):format(map.lhs) - vim.api.nvim_buf_set_keymap(0, mode, fallback_lhs, map.lhs, { - expr = false, - noremap = true, - silent = true, - nowait = true, - }) - rhs = string.gsub(rhs, '^' .. vim.pesc(map.lhs), fallback_lhs) + if map.expr == 1 then + rhs = string.format('v:lua.cmp.utils.keymap.evacuate.expr("%s", "%s", "%s")', mode, str.escape(keymap.escape(lhs), { '"' }), str.escape(keymap.escape(rhs), { '"' })) + else + rhs = keymap.recursive(mode, lhs, rhs) + end end - local fallback = ('(cmp-utils-keymap-listen-rhs:%s)'):format(map.lhs) + local fallback = ('(cmp-utils-keymap-evacuate-rhs:%s)'):format(map.lhs) vim.api.nvim_buf_set_keymap(0, mode, fallback, rhs, { expr = map.expr ~= 0, noremap = map.noremap ~= 0, @@ -162,6 +159,28 @@ keymap.evacuate = function(mode, lhs) }) return fallback end +misc.set(_G, { 'cmp', 'utils', 'keymap', 'evacuate', 'expr' }, function(mode, lhs, rhs) + return keymap.t(keymap.recursive(mode, lhs, vim.api.nvim_eval(rhs))) +end) + +---Solve recursive mapping +---@param mode string +---@param lhs string +---@param rhs string +---@return string +keymap.recursive = function(mode, lhs, rhs) + local fallback_lhs = ('(cmp-utils-keymap-listen-lhs:%s)'):format(lhs) + local new_rhs = string.gsub(rhs, '^' .. vim.pesc(lhs), fallback_lhs) + if new_rhs ~= rhs then + vim.api.nvim_buf_set_keymap(0, mode, fallback_lhs, lhs, { + expr = false, + noremap = true, + silent = true, + nowait = true, + }) + end + return new_rhs +end ---Get specific key mapping ---@param mode string diff --git a/lua/cmp/utils/keymap_spec.lua b/lua/cmp/utils/keymap_spec.lua index 99398f9..06f74fa 100644 --- a/lua/cmp/utils/keymap_spec.lua +++ b/lua/cmp/utils/keymap_spec.lua @@ -43,5 +43,28 @@ describe('keymap', function() vim.api.nvim_feedkeys('i' .. keymap.t(fallback), 'x', true) assert.are.same({ '()' }, vim.api.nvim_buf_get_lines(0, 0, -1, true)) 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('i', '') + vim.api.nvim_feedkeys('i' .. keymap.t(fallback), 'x', 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('i', '') + vim.api.nvim_feedkeys('i' .. keymap.t(fallback), 'x', true) + assert.are.same({ '\taiueo' }, vim.api.nvim_buf_get_lines(0, 0, -1, true)) + end) + end) end) end)