From 008de7eb8a023b5496a0e6968c6c453ec8f308e4 Mon Sep 17 00:00:00 2001 From: hrsh7th Date: Sat, 15 Jan 2022 19:18:04 +0900 Subject: [PATCH] Avoid expr mapping message (#738) * Avoid display message by register mapping * Escape to json * Improve tests * fmt * lint * Fix evacuate condition * Default silent * fallback mapping should be silent by default * Support legacy nvim --- lua/cmp/utils/keymap.lua | 86 ++++++++++++++++++++++------------- lua/cmp/utils/keymap_spec.lua | 24 ++++------ 2 files changed, 64 insertions(+), 46 deletions(-) diff --git a/lua/cmp/utils/keymap.lua b/lua/cmp/utils/keymap.lua index ab25ae4..79e3efe 100644 --- a/lua/cmp/utils/keymap.lua +++ b/lua/cmp/utils/keymap.lua @@ -1,3 +1,4 @@ +local cache = require('cmp.utils.cache') local misc = require('cmp.utils.misc') local api = require('cmp.utils.api') @@ -101,15 +102,16 @@ 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) keymap.set_map(bufnr, mode, lhs, function() if mode == 'c' and vim.fn.getcmdtype() == '=' then - return keymap.feed_map(existing) + return vim.api.nvim_feedkeys(keymap.t(fallback), 'it', true) end callback( lhs, misc.once(function() - keymap.feed_map(existing) + return vim.api.nvim_feedkeys(keymap.t(fallback), 'it', true) end) ) end, { @@ -119,6 +121,56 @@ keymap.listen = function(mode, lhs, callback) }) end +---Evacuate existing keymapping. +---@param bufnr number +---@param mode string +---@param existing table +---@return string +keymap.evacuate = setmetatable({ + cache = cache.new(), +}, { + __call = function(self, bufnr, mode, existing) + local fallback = self.cache:ensure({ bufnr, mode, existing.lhs }, function() + return string.format('(cmp.u.k.evacuate:%s)', misc.id('cmp.utils.keymap.evacuate')) + end) + + local callback = not existing.expr and existing.callback + keymap.set_map(bufnr, mode, fallback, function() + local lhs = keymap.t(existing.lhs) + local rhs + if existing.callback then + rhs = existing.callback() + elseif existing.expr then + rhs = vim.api.nvim_eval(keymap.t(existing.rhs)) + else + rhs = keymap.t(existing.rhs) + end + + if not existing.noremap then + if string.find(rhs, lhs, 1, true) == 1 then + rhs = string.gsub(rhs, '^' .. vim.pesc(lhs), string.format(keymap.t([[=v:lua.vim.json.decode(%s)]]), vim.fn.string(vim.json.encode(lhs)))) + end + end + return rhs + end, callback and { + expr = false, + callback = callback, + noremap = existing.noremap, + script = existing.script, + silent = true, + nowait = existing.nowait, + } or { + expr = true, + noremap = existing.noremap, + script = existing.script, + silent = true, + nowait = existing.nowait, + }) + + return fallback + end, +}) + ---Get map ---@param mode string ---@param lhs string @@ -165,40 +217,12 @@ keymap.get_map = function(mode, lhs) callback = nil, noremap = true, script = false, - silent = false, + silent = true, nowait = false, buffer = false, } end ----Feed mapping object. ----@param map table -keymap.feed_map = function(map) - local lhs = keymap.t(map.lhs) - local rhs - if map.callback and not map.expr then - return map.callback() - elseif map.callback and map.expr then - rhs = map.callback() - elseif map.expr then - rhs = vim.api.nvim_eval(keymap.t(map.rhs)) - else - rhs = keymap.t(map.rhs) - end - - if map.noremap then - vim.api.nvim_feedkeys(rhs, 'itn', true) - else - if string.find(rhs, lhs, 1, true) == 1 then - rhs = string.gsub(rhs, '^' .. vim.pesc(lhs), '') - vim.api.nvim_feedkeys(rhs, 'itm', true) - vim.api.nvim_feedkeys(lhs, 'itn', true) - else - vim.api.nvim_feedkeys(rhs, 'itm', true) - end - end -end - ---Set keymapping keymap.set_map = setmetatable({ callbacks = {}, diff --git a/lua/cmp/utils/keymap_spec.lua b/lua/cmp/utils/keymap_spec.lua index 71210e4..bd6a56f 100644 --- a/lua/cmp/utils/keymap_spec.lua +++ b/lua/cmp/utils/keymap_spec.lua @@ -1,4 +1,3 @@ -local feedkeys = require('cmp.utils.feedkeys') local spec = require('cmp.utils.spec') local keymap = require('cmp.utils.keymap') @@ -32,7 +31,7 @@ describe('keymap', function() assert.are.equal(keymap.to_keymap('|'), '') end) - describe('feedmap', function() + describe('evacuate', function() before_each(spec.before) it('expr & register', function() @@ -40,9 +39,8 @@ describe('keymap', function() expr = true, noremap = false, }) - feedkeys.call('i', 'nx', function() - keymap.feed_map(keymap.get_map('i', '(')) - end) + local fallback = keymap.evacuate(0, 'i', keymap.get_map('i', '(')) + vim.api.nvim_feedkeys('i' .. keymap.t(fallback), 'x', true) assert.are.same({ '(' }, vim.api.nvim_buf_get_lines(0, 0, -1, true)) end) @@ -55,9 +53,8 @@ describe('keymap', function() expr = false, noremap = false, }) - feedkeys.call('i', 'nx', function() - keymap.feed_map(keymap.get_map('i', '(')) - end) + local fallback = keymap.evacuate(0, 'i', keymap.get_map('i', '(')) + vim.api.nvim_feedkeys('i' .. keymap.t(fallback), 'x', true) assert.are.same({ '()' }, vim.api.nvim_buf_get_lines(0, 0, -1, true)) end) @@ -69,10 +66,8 @@ describe('keymap', function() expr = true, noremap = false, }) - feedkeys.call('i', 'n', function() - keymap.feed_map(keymap.get_map('i', '')) - end) - feedkeys.call('', 'x') + local fallback = keymap.evacuate(0, 'i', keymap.get_map('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() @@ -80,9 +75,8 @@ describe('keymap', function() expr = true, noremap = false, }) - feedkeys.call('i', 'nx', function() - keymap.feed_map(keymap.get_map('i', '')) - end) + local fallback = keymap.evacuate(0, 'i', keymap.get_map('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)